2017-02-22 14 views
1

У меня возникла проблема, когда я делал маску ввода с помощью ui-mask в angularJs.I'm chechking, если написанная строка верна, тогда textarea должна стать зеленым. Но в моем случае , textarea изначально зеленый, тогда, когда вы вводите какое-то слово, оно становится красным до тех пор, пока вы не наберете правильное слово. Я выложу свой код, и если вы можете помочь мне решить эту проблему, я не знаю, как сделать больше, я пробовал много чего, но ничего не работало. Ребята, ребята, за такой огромный скрипт. Heres мой index.htmlДействительная маска ввода с angularjs (ui-mask)

<!DOCTYPE html> 
<html ng-app="myApp" lang="en"> 
    <head> 
    <meta charset="utf-8"> 
    <title>I am Tom</title> 
     <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.1/angular.js"></script> 
    <script type="text/javascript" src="js/angularjs/mask.js"></script> 
    <script type="text/javascript" src="js/angularjs/module.js"></script> 
    <link rel="stylesheet" type="text/css" href="style.css"> 
    </head> 

    <body ng-controller="myController"> 

    <div class="divito"> 

     <h3 clas="h3">Please Input following text: I am Tom</h3> 

     <textarea class="textarea" style="resize: none" cols="30" row="2" ui-mask="i am tom" ng-model="greeting" data-ng-trim="fasle" ng-trim="false"> 
     </textarea> 

    </div> 

    </body> 

</html> 

style.css

body{ 
    background-color: #fbfbfb; 
} 
.textarea{ 
    width:600px; 
    height:60px; 
    text-align: center; 
    font-size: 43px; 
    border-radius: 10px; 
} 
.divito { 
    margin: 200px 30% 0 33%; 
    position: relative; 
} 

textarea.ng-invalid { 
    border:2px solid #EA4335; 
} 
textarea.ng-valid { 
    background-color:lightgreen; 
} 

А вот мой script.js

var app = angular.module('myApp',[]); 

app.controller('myController', ['$scope', function ($scope) { 
     $scope.greeting = '123456789'; 
    }]).directive('uiMask', [ 
    function() { 
    var maskDefinitions = { 
     // 'I': /[I-i]/, 
     // '2': /[a]/, 
     // '3': /[m]/, 
     // '4': /[T]/, 
     // '5': /[o]/ 
     'a': /[a]/, 'A': /[A]/, 
     'b': /[b]/, 'B': /[B]/, 
     'c': /[c]/, 'C': /[C]/, 
     'd': /[d]/, 'D': /[D]/, 
     'e': /[e]/, 'E': /[E]/, 
     'f': /[f]/, 'F': /[F]/, 
     'g': /[g]/, 'G': /[G]/, 
     'h': /[h]/, 'H': /[H]/, 
     'i': /[i]/, 'I': /[I]/, 
     'j': /[j]/, 'J': /[J]/, 
     'k': /[h]/, 'K': /[K]/, 
     'l': /[l]/, 'L': /[L]/, 
     'm': /[m]/, 'M': /[M]/, 
     'n': /[n]/, 'N': /[N]/, 
     'o': /[o]/, 'O': /[O]/, 
     'p': /[p]/, 'P': /[P]/, 
     'q': /[q]/, 'Q': /[Q]/, 
     'r': /[r]/, 'R': /[R]/, 
     's': /[s]/, 'S': /[S]/, 
     't': /[t]/, 'T': /[T]/, 
     'u': /[u]/, 'U': /[U]/, 
     'v': /[v]/, 'V': /[V]/, 
     'w': /[w]/, 'W': /[W]/, 
     'x': /[x]/, 'X': /[X]/, 
     'y': /[y]/, 'Y': /[Y]/, 
     'z': /[z]/, 'Z': /[Z]/ 
    }; 
    return { 
     priority: 100, 
     require: 'ngModel', 
     restrict: 'A', 
     link: function (scope, iElement, iAttrs, controller) { 
      //console.log('init'); 
     var maskProcessed = false, eventsBound = false, 
      maskCaretMap, maskPatterns, maskPlaceholder, maskComponents, 
      validValue, 
      // Minimum required length of the value to be considered valid 
      minRequiredLength, 
      value, valueMasked, isValid, 
      // Vars for initializing/uninitializing 
      originalPlaceholder = iAttrs.placeholder, 
      originalMaxlength = iAttrs.maxlength, 
      // Vars used exclusively in eventHandler() 
      oldValue, oldValueUnmasked, oldCaretPosition, oldSelectionLength; 

     function initialize(maskAttr) { 
      if (!angular.isDefined(maskAttr)){ 
      return uninitialize(); 
      } 
      processRawMask(maskAttr); 
      if (!maskProcessed){ 
      return uninitialize(); 
      } 
      initializeElement(); 
      bindEventListeners(); 
     } 

     function formatter(fromModelValue) { 
      if (!maskProcessed){ 
      return fromModelValue; 
      } 
      value = unmaskValue(fromModelValue || ''); 
      // isValid = validateValue(value); 
      // controller.$setValidity('mask', isValid); 

      if (isValid) validValue = value; 
      //console.log('formatter valid:'+validValue); 
      return isValid && value.length ? maskValue(value) : undefined; 
     } 

     function parser(fromViewValue) { 
      if (!maskProcessed){ 
      return fromViewValue; 
      } 
      value  = unmaskValue(fromViewValue || ''); 
      isValid = validateValue(value); 
      viewValue = value.length ? maskValue(value) : ''; 
      // We have to set viewValue manually as the reformatting of the input 
      // value performed by eventHandler() doesn't happen until after 
      // this parser is called, which causes what the user sees in the input 
      // to be out-of-sync with what the controller's $viewValue is set to. 
      controller.$viewValue = viewValue; 
      controller.$setValidity('mask', isValid); 
      if (value === '' && controller.$error.required !== undefined){ 
      controller.$setValidity('required', false); 
      } 
      if (isValid) validValue = value; 
      //console.log('parser valid:'+validValue); 
      return isValid ? value : undefined; 
     } 

     iAttrs.$observe('uiMask', initialize); 
     controller.$formatters.push(formatter); 
     controller.$parsers.push(parser); 

     function uninitialize() { 
      maskProcessed = false; 
      unbindEventListeners(); 

      if (angular.isDefined(originalPlaceholder)){ 
      iElement.attr('placeholder', originalPlaceholder); 
      }else{ 
      iElement.removeAttr('placeholder'); 
      } 

      if (angular.isDefined(originalMaxlength)){ 
      iElement.attr('maxlength', originalMaxlength); 
      }else{ 
      iElement.removeAttr('maxlength'); 
      } 

      iElement.val(controller.$modelValue); 
      controller.$viewValue = controller.$modelValue; 
      return false; 
     } 

     function initializeElement() { 
      value  = oldValueUnmasked = unmaskValue(controller.$modelValue || ''); 
      valueMasked = oldValue   = maskValue(value); 
      isValid  = validateValue(value); 
      viewValue = isValid && value.length ? valueMasked : ''; 
      if (iAttrs.maxlength){ // Double maxlength to allow pasting new val at end of mask 
      iElement.attr('maxlength', maskCaretMap[maskCaretMap.length-1]*2); 
      } 
      iElement.attr('placeholder', maskPlaceholder); 
      iElement.val(viewValue); 
      controller.$viewValue = viewValue; 
      // Not using $setViewValue so we don't clobber the model value and dirty the form 
      // without any kind of user interaction. 
     } 

     function bindEventListeners() { 
      if (eventsBound){ 
      return true; 
      } 
      iElement.bind('blur',    blurHandler); 
      iElement.bind('mousedown mouseup', mouseDownUpHandler); 
      iElement.bind('input keyup click', eventHandler); 
      eventsBound = true; 
     } 

     // function unbindEventListeners() { 
     // if (!eventsBound){ 
     //  return true; 
     // } 
     // iElement.unbind('blur',  blurHandler); 
     // iElement.unbind('mousedown', mouseDownUpHandler); 
     // iElement.unbind('mouseup', mouseDownUpHandler); 
     // iElement.unbind('input',  eventHandler); 
     // iElement.unbind('keyup',  eventHandler); 
     // iElement.unbind('click',  eventHandler); 
     // eventsBound = false; 
     // } 

     function validateValue(value) { 
      // Zero-length value validity is ngRequired's determination 
      return value.length ? value.length >= minRequiredLength : true; 
     } 

     function unmaskValue(value) { 
      var valueUnmasked = '', 
       maskPatternsCopy = maskPatterns.slice(); 
      // Preprocess by stripping mask components from value 
      value = value.toString(); 
      angular.forEach(maskComponents, function(component, i) { 
      value = value.replace(component, ''); 
      }); 
      angular.forEach(value.split(''), function(chr, i) { 
      if (maskPatternsCopy.length && maskPatternsCopy[0].test(chr)) { 
       valueUnmasked += chr; 
       maskPatternsCopy.shift(); 
      } 
      }); 
      return valueUnmasked; 
     } 

     function maskValue(unmaskedValue) { 
      var valueMasked  = '', 
       maskCaretMapCopy = maskCaretMap.slice(); 
      angular.forEach(maskPlaceholder.split(''), function(chr, i) { 
      if (unmaskedValue.length && i === maskCaretMapCopy[0]) { 
       valueMasked += unmaskedValue.charAt(0) || '_'; 
       unmaskedValue = unmaskedValue.substr(1); 
       maskCaretMapCopy.shift(); } 
      else{ 
       valueMasked += chr; 
      } 
      }); 
      return valueMasked; 
     } 

     function processRawMask(mask) { 
      var characterCount = 0; 
      maskCaretMap  = []; 
      maskPatterns  = []; 
      maskPlaceholder = ''; 

      // No complex mask support for now... 
      // if (mask instanceof Array) { 
      // angular.forEach(mask, function(item, i) { 
      //  if (item instanceof RegExp) { 
      //  maskCaretMap.push(characterCount++); 
      //  maskPlaceholder += '_'; 
      //  maskPatterns.push(item); 
      //  } 
      //  else if (typeof item == 'string') { 
      //  angular.forEach(item.split(''), function(chr, i) { 
      //   maskPlaceholder += chr; 
      //   characterCount++; 
      //  }); 
      //  } 
      // }); 
      // } 
      // Otherwise it's a simple mask 
      // else 

      if (typeof mask === 'string') { 
      minRequiredLength = 0; 
      var isOptional = false; 

      angular.forEach(mask.split(''), function(chr, i) { 
       if (maskDefinitions[chr]) { 
       maskCaretMap.push(characterCount); 
       maskPlaceholder += '_'; 
       maskPatterns.push(maskDefinitions[chr]); 

       characterCount++; 
       if (!isOptional) { 
        minRequiredLength++; 
       } 
       } 
       else if (chr === "?") { 
       isOptional = true; 
       } 
       else{ 
       maskPlaceholder += chr; 
       characterCount++; 
       } 
      }); 
      } 
      // Caret position immediately following last position is valid. 
      maskCaretMap.push(maskCaretMap.slice().pop() + 1); 
      // Generate array of mask components that will be stripped from a masked value 
      // before processing to prevent mask components from being added to the unmasked value. 
      // E.g., a mask pattern of '+7 9999' won't have the 7 bleed into the unmasked value. 
                   // If a maskable char is followed by a mask char and has a mask 
                   // char behind it, we'll split it into it's own component so if 
                   // a user is aggressively deleting in the input and a char ahead 
                   // of the maskable char gets deleted, we'll still be able to strip 
                   // it in the unmaskValue() preprocessing. 
      maskComponents = maskPlaceholder.replace(/[_]+/g,'_').replace(/([^_]+)([a-zA-Z0-9])([^_])/g, '$1$2_$3').split('_'); 
      maskProcessed = maskCaretMap.length > 1 ? true : false; 
     } 

     function blurHandler(e) { 
      oldCaretPosition = 0; 
      oldSelectionLength = 0; 
      if (!isValid || value.length === 0) { 
      valueMasked = ''; 
      iElement.val(''); 
      scope.$apply(function() { 
       controller.$setViewValue(''); 
      }); 
      } 
     } 

     function mouseDownUpHandler(e) { 
      if (e.type === 'mousedown'){ 
      iElement.bind('mouseout', mouseoutHandler); 
      }else{ 
      iElement.unbind('mouseout', mouseoutHandler); 
      } 
     } 

     iElement.bind('mousedown mouseup', mouseDownUpHandler); 

     function mouseoutHandler(e) { 
      oldSelectionLength = getSelectionLength(this); 
      iElement.unbind('mouseout', mouseoutHandler); 
     } 

     function eventHandler(e) { 
      e = e || {}; 
      // Allows more efficient minification 
      var eventWhich = e.which, 
       eventType = e.type; 
      // Prevent shift and ctrl from mucking with old values 
      if (eventWhich === 16 || eventWhich === 91){ return true;} 

      var val    = iElement.val(), 
       valOld   = oldValue, 
       valMasked, 
       valUnmasked  = unmaskValue(val), 
       valUnmaskedOld = oldValueUnmasked, 
       valAltered  = false, 

       caretPos  = getCaretPosition(this) || 0, 
       caretPosOld  = oldCaretPosition || 0, 
       caretPosDelta = caretPos - caretPosOld, 
       caretPosMin  = maskCaretMap[0], 
       caretPosMax  = maskCaretMap[valUnmasked.length] || maskCaretMap.slice().shift(), 

       selectionLen = getSelectionLength(this), 
       selectionLenOld = oldSelectionLength || 0, 
       isSelected  = selectionLen > 0, 
       wasSelected  = selectionLenOld > 0, 

                   // Case: Typing a character to overwrite a selection 
       isAddition  = (val.length > valOld.length) || (selectionLenOld && val.length > valOld.length - selectionLenOld), 
                   // Case: Delete and backspace behave identically on a selection 
       isDeletion  = (val.length < valOld.length) || (selectionLenOld && val.length === valOld.length - selectionLenOld), 
       isSelection  = (eventWhich >= 37 && eventWhich <= 40) && e.shiftKey, // Arrow key codes 

       isKeyLeftArrow = eventWhich === 37, 
                // Necessary due to "input" event not providing a key code 
       isKeyBackspace = eventWhich === 8 || (eventType !== 'keyup' && isDeletion && (caretPosDelta === -1)), 
       isKeyDelete  = eventWhich === 46 || (eventType !== 'keyup' && isDeletion && (caretPosDelta === 0) && !wasSelected), 

       // Handles cases where caret is moved and placed in front of invalid maskCaretMap position. Logic below 
       // ensures that, on click or leftward caret placement, caret is moved leftward until directly right of 
       // non-mask character. Also applied to click since users are (arguably) more likely to backspace 
       // a character when clicking within a filled input. 
       caretBumpBack = (isKeyLeftArrow || isKeyBackspace || eventType === 'click') && caretPos > caretPosMin; 

      oldSelectionLength = selectionLen; 

      // These events don't require any action 
      if (isSelection || (isSelected && (eventType === 'click' || eventType === 'keyup'))){ 
      return true; 
      } 

      // Value Handling 
      // ============== 

      // User attempted to delete but raw value was unaffected--correct this grievous offense 

      if ((eventType === 'input') && isDeletion && !wasSelected && valUnmasked === valUnmaskedOld) { 
      while (isKeyBackspace && caretPos > caretPosMin && !isValidCaretPosition(caretPos)){ 
       caretPos--; 
      } 
      while (isKeyDelete && caretPos < caretPosMax && maskCaretMap.indexOf(caretPos) === -1){ 
       caretPos++; 
      } 
      var charIndex = maskCaretMap.indexOf(caretPos); 
      // Strip out non-mask character that user would have deleted if mask hadn't been in the way. 
      valUnmasked = valUnmasked.substring(0, charIndex) + valUnmasked.substring(charIndex + 1); 
      valAltered = true; 
      } 

      // Update values 
      console.log(e); 
      console.log(String.fromCharCode(e.keyCode)); 
      //console.log(String.fromCodePoint(e.keyCode)); 
      //console.log("---> update values start"); 
      //console.log("valUnmasked:" + valUnmasked); 
      //console.log("valMasked:" + valMasked); 
      valMasked  = maskValue(valUnmasked); 
      oldValue   = valMasked; 
      oldValueUnmasked = valUnmasked; 
      iElement.val(valMasked); 



      // Make sure caret is within min and max position limits 
      caretPos = caretPos > caretPosMax ? caretPosMax : caretPos < caretPosMin ? caretPosMin : caretPos; 

      // Scoot the caret back or forth until it's in a non-mask position and within min/max position limits 
      while (!isValidCaretPosition(caretPos) && caretPos > caretPosMin && caretPos < caretPosMax){ 
      caretPos += caretBumpBack ? -1 : 1; 
      } 

      if ((caretBumpBack && caretPos < caretPosMax) || (isAddition && !isValidCaretPosition(caretPosOld))){ 
      caretPos++; 
      } 
      oldCaretPosition = caretPos; 
      setCaretPosition(this, caretPos); 
     } 

     function isValidCaretPosition(pos) { return maskCaretMap.indexOf(pos) > -1; } 

     function getCaretPosition(input) { 
      if (input.selectionStart !== undefined){ 
      return input.selectionStart; 
      }else if (document.selection) { 
      // Curse you IE 
      input.focus(); 
      var selection = document.selection.createRange(); 
      selection.moveStart('character', -input.value.length); 
      return selection.text.length; 
      } 
     } 

     function setCaretPosition(input, pos) { 
      if (input.offsetWidth === 0 || input.offsetHeight === 0){ 
      return true; // Input's hidden 
      } 
      if (input.setSelectionRange) { 
      input.focus(); 
      input.setSelectionRange(pos,pos); } 
      else if (input.createTextRange) { 
      // Curse you IE 
      var range = input.createTextRange(); 
      range.collapse(true); 
      range.moveEnd('character', pos); 
      range.moveStart('character', pos); 
      range.select(); 
      } 
     } 

     function getSelectionLength(input) { 
      if (input.selectionStart !== undefined){ 
      return (input.selectionEnd - input.selectionStart); 
      } 
      if (document.selection){ 
      return (document.selection.createRange().text.length); 
      } 
     } 


     } 
    }; 
    } 
]); 
+0

, пожалуйста, уменьшите свой пример, см. Также http://stackoverflow.com/help/mcve – hering

+0

как я могу уменьшить? просто удалите ненужные строки? – brithwulf

+0

разделите его на «Минимальный, полный и проверенный пример» – hering

ответ

0

я нашел решение, я просто нужно добавить это в CSS.

textarea.ng-dirty.ng-invalid { 
    border:2px solid #EA4335; 
} 
textarea.ng-dirty.ng-valid { 
    background-color:lightgreen; 
} 

и теперь он отлично работает.