username-1.0.x-dev/js/username.mask.js

js/username.mask.js
/********************************************************************
* Limit the characters that may be entered in a text field
* Common options: alphanumeric, alphabetic or numeric
* Kevin Sheedy, 2012
* http://github.com/KevinSheedy/jquery.alphanum
*********************************************************************/
(function( $ ){

  // API ///////////////////////////////////////////////////////////////////
  $.fn.alphanum = function(settings) {

    var combinedSettings = getCombinedSettingsAlphaNum(settings);

    var $collection = this;

    setupEventHandlers($collection, trimAlphaNum, combinedSettings);

    return this;
  };

  $.fn.alpha = function(settings) {

    var defaultAlphaSettings = getCombinedSettingsAlphaNum('alpha');
    var combinedSettings = getCombinedSettingsAlphaNum(settings, defaultAlphaSettings);

    var $collection = this;

    setupEventHandlers($collection, trimAlphaNum, combinedSettings);

    return this;
  };

  $.fn.numeric = function(settings) {

    var combinedSettings = getCombinedSettingsNum(settings);
    var $collection = this;

    setupEventHandlers($collection, trimNum, combinedSettings);

    $collection.blur(function(){
      numericField_Blur(this, combinedSettings);
    });

    return this;
  };

  // End of API /////////////////////////////////////////////////////////////


  // Start Settings ////////////////////////////////////////////////////////

  var DEFAULT_SETTINGS_ALPHANUM = {
    allow              : '',    // Allow extra characters
    disallow           : '',    // Disallow extra characters
    allowSpace         : true,  // Allow the space character
    allowNewline       : true,  // Allow the newline character \n ascii 10
    allowNumeric       : true,  // Allow digits 0-9
    allowUpper         : true,  // Allow upper case characters
    allowLower         : true,  // Allow lower case characters
    allowCaseless      : true,  // Allow characters that don't have both upper & lower variants - eg Arabic or Chinese
    allowLatin         : true,  // a-z A-Z
    allowOtherCharSets : true,  // eg é, Á, Arabic, Chinese etc
    forceUpper         : false, // Convert lower case characters to upper case
    forceLower         : false, // Convert upper case characters to lower case
    maxLength          : NaN    // eg Max Length
  };

  var DEFAULT_SETTINGS_NUM = {
    allowPlus           : false, // Allow the + sign
    allowMinus          : true,  // Allow the - sign
    allowThouSep        : true,  // Allow the thousands separator, default is the comma eg 12,000
    allowDecSep         : true,  // Allow the decimal separator, default is the fullstop eg 3.141
    allowLeadingSpaces  : false,
    maxDigits           : NaN,   // The max number of digits
    maxDecimalPlaces    : NaN,   // The max number of decimal places
    maxPreDecimalPlaces : NaN,   // The max number digits before the decimal point
    max                 : NaN,   // The max numeric value allowed
    min                 : NaN    // The min numeric value allowed
  };

  // Some pre-defined groups of settings for convenience
  var CONVENIENCE_SETTINGS_ALPHANUM = {
    'alpha' : {
      allowNumeric  : false
    },
    'upper' : {
      allowNumeric  : false,
      allowUpper    : true,
      allowLower    : false,
      allowCaseless : true
    },
    'lower' : {
      allowNumeric  : false,
      allowUpper    : false,
      allowLower    : true,
      allowCaseless : true
    }
  };

  // Some pre-defined groups of settings for convenience
  var CONVENIENCE_SETTINGS_NUMERIC = {
    'integer' : {
      allowPlus    : false,
      allowMinus   : true,
      allowThouSep : false,
      allowDecSep  : false
    },
    'positiveInteger' : {
      allowPlus    : false,
      allowMinus   : false,
      allowThouSep : false,
      allowDecSep  : false
    }
  };


  var BLACKLIST   = getBlacklistAscii() + getBlacklistNonAscii();
  var THOU_SEP    = ',';
  var DEC_SEP     = '.';
  var DIGITS      = getDigitsMap();
  var LATIN_CHARS = getLatinCharsSet();

  // Return the blacklisted special chars that are encodable using 7-bit ascii
  function getBlacklistAscii(){
    var blacklist = '!@#$%^&*()+=[]\\\';,/{}|":<>?~`.-_';
    blacklist += ' '; // 'Space' is on the blacklist but can be enabled using the 'allowSpace' config entry
    return blacklist;
  }

  // Return the blacklisted special chars that are NOT encodable using 7-bit ascii
  // We want this .js file to be encoded using 7-bit ascii so it can reach the widest possible audience
  // Higher order chars must be escaped eg "\xAC"
  // Not too worried about comments containing higher order characters for now (let's wait and see if it becomes a problem)
  function getBlacklistNonAscii(){
    var blacklist =
        '\xAC'     // ¬
      + '\u20AC'   // €
      + '\xA3'     // £
      + '\xA6'     // ¦
      ;
    return blacklist;
  }

  // End Settings ////////////////////////////////////////////////////////


  // Implementation details go here ////////////////////////////////////////////////////////

  function setupEventHandlers($textboxes, trimFunction, settings) {

    $textboxes.each(function(){

      var $textbox = $(this);

      $textbox
        // Unbind existing alphanum event handlers
        .off('.alphanum')

        .on('keyup.alphanum change.alphanum paste.alphanum', function(e){

          var pastedText = '';

          if(e.originalEvent && e.originalEvent.clipboardData && e.originalEvent.clipboardData.getData)
            pastedText = e.originalEvent.clipboardData.getData('text/plain');

          // setTimeout is necessary for handling the 'paste' event
          setTimeout(function(){
            trimTextbox($textbox, trimFunction, settings, pastedText);
          }, 0);
        })

        .on('keypress.alphanum', function(e){

        // Determine which key is pressed.
        // If it's a control key, then allow the event's default action to occur eg backspace, tab
          var charCode = !e.charCode ? e.which : e.charCode;
          if(isControlKey(charCode)
          || e.ctrlKey
          || e.metaKey ) // cmd on MacOS
            return;

          var newChar         = String.fromCharCode(charCode);

          // Determine if some text was selected / highlighted when the key was pressed
          var selectionObject = $textbox.selection();
          var start = selectionObject.start;
          var end   = selectionObject.end;

          var textBeforeKeypress  = $textbox.val();

          // The new char may be inserted:
          //  1) At the start
          //  2) In the middle
          //  3) At the end
          //  4) User highlights some text and then presses a key which would replace the highlighted text
          //
          // Here we build the string that would result after the keypress.
          // If the resulting string is invalid, we cancel the event.
          // Unfortunately, it isn't enough to just check if the new char is valid because some chars
          // are position sensitive eg the decimal point '.'' or the minus sign '-'' are only valid in certain positions.
          var potentialTextAfterKeypress = textBeforeKeypress.substring(0, start) + newChar + textBeforeKeypress.substring(end);
          var validatedText              = trimFunction(potentialTextAfterKeypress, settings);

          // If the keypress would cause the textbox to contain invalid characters, then cancel the keypress event
          if(validatedText != potentialTextAfterKeypress)
            e.preventDefault();
        });
    });

  }

  // Ensure the text is a valid number when focus leaves the textbox
  // This catches the case where a user enters '-' or '.' without entering any digits
  function numericField_Blur(inputBox, settings) {
    var fieldValueNumeric = parseFloat($(inputBox).val());
    var $inputBox = $(inputBox);

    if(isNaN(fieldValueNumeric)) {
      $inputBox.val('');
      return;
    }

    if(isNumeric(settings.min) && fieldValueNumeric < settings.min)
      $inputBox.val('');

    if(isNumeric(settings.max) && fieldValueNumeric > settings.max)
      $inputBox.val('');
  }

  function isNumeric(value) {
    return !isNaN(value);
  }

  function isControlKey(charCode) {

    if(charCode >= 32)
      return false;
    if(charCode == 10)
      return false;
    if(charCode == 13)
      return false;

    return true;
  }

  // One way to prevent a character being entered is to cancel the keypress event.
  // However, this gets messy when you have to deal with things like copy paste which isn't a keypress.
  // Which event gets fired first, keypress or keyup? What about IE6 etc etc?
  // Instead, it's easier to allow the 'bad' character to be entered and then to delete it immediately after.

  function trimTextbox($textBox, trimFunction, settings, pastedText){

    var inputString = $textBox.val();

    if(inputString == '' && pastedText.length > 0)
      inputString = pastedText;

    var outputString = trimFunction(inputString, settings);

    if(inputString == outputString)
      return;

    var caretPos = $textBox.alphanum_caret();

    $textBox.val(outputString);

    //Reset the caret position
    if(inputString.length ==(outputString.length + 1))
      $textBox.alphanum_caret(caretPos - 1);
    else
      $textBox.alphanum_caret(caretPos);
  }

  function getCombinedSettingsAlphaNum(settings, defaultSettings){
    if(typeof defaultSettings == 'undefined')
      defaultSettings = DEFAULT_SETTINGS_ALPHANUM;
    var userSettings, combinedSettings = {};
    if(typeof settings === 'string')
      userSettings = CONVENIENCE_SETTINGS_ALPHANUM[settings];
    else if(typeof settings == 'undefined')
      userSettings = {};
    else
      userSettings = settings;

    $.extend(combinedSettings, defaultSettings, userSettings);

    if(typeof combinedSettings.blacklist == 'undefined')
      combinedSettings.blacklistSet = getBlacklistSet(combinedSettings.allow, combinedSettings.disallow);

    return combinedSettings;
  }

  function getCombinedSettingsNum(settings){
    var userSettings, combinedSettings = {};
    if(typeof settings === 'string')
      userSettings = CONVENIENCE_SETTINGS_NUMERIC[settings];
    else if(typeof settings == 'undefined')
      userSettings = {};
    else
      userSettings = settings;

    $.extend(combinedSettings, DEFAULT_SETTINGS_NUM, userSettings);

    return combinedSettings;
  }


  // This is the heart of the algorithm
  function alphanum_allowChar(validatedStringFragment, Char, settings){

    if(settings.maxLength && validatedStringFragment.length >= settings.maxLength)
      return false;

    if(settings.allow.indexOf(Char) >=0 )
      return true;

    if(settings.allowSpace && (Char == ' '))
      return true;

    if(!settings.allowNewline && (Char == '\n' || Char == '\r'))
      return false;

    if(settings.blacklistSet.contains(Char))
      return false;

    if(!settings.allowNumeric && DIGITS[Char])
      return false;

    if(!settings.allowUpper && isUpper(Char))
      return false;

    if(!settings.allowLower && isLower(Char))
      return false;

    if(!settings.allowCaseless && isCaseless(Char))
      return false;

    if(!settings.allowLatin && LATIN_CHARS.contains(Char))
      return false;

    if(!settings.allowOtherCharSets){
      if(DIGITS[Char] || LATIN_CHARS.contains(Char))
        return true;
      else
        return false;
    }

    return true;
  }

  function numeric_allowChar(validatedStringFragment, Char, settings){

    if(DIGITS[Char]) {

      if(isMaxDigitsReached(validatedStringFragment, settings))
        return false;

      if(isMaxPreDecimalsReached(validatedStringFragment, settings))
        return false;

      if(isMaxDecimalsReached(validatedStringFragment, settings))
        return false;

      if(isGreaterThanMax(validatedStringFragment + Char, settings))
        return false;

      if(isLessThanMin(validatedStringFragment + Char, settings))
        return false;

      return true;
    }

    if(settings.allowPlus && Char == '+' && validatedStringFragment == '')
      return true;

    if(settings.allowMinus && Char == '-' && validatedStringFragment == '')
      return true;

    if(Char == THOU_SEP && settings.allowThouSep && allowThouSep(validatedStringFragment))
      return true;

    if(Char == DEC_SEP) {
      // Only one decimal separator allowed
      if(validatedStringFragment.indexOf(DEC_SEP) >= 0)
        return false;
      // Don't allow decimal separator when maxDecimalPlaces is set to 0
      if(settings.allowDecSep && settings.maxDecimalPlaces === 0)
        return false;
      if(settings.allowDecSep)
        return true;
    }

    return false;
  }

  function countDigits(string) {

    // Error handling, nulls etc
    string = string + '';

    // Count the digits
    return string.replace(/[^0-9]/g,'').length;
  }

  function isMaxDigitsReached(string, settings) {

    var maxDigits = settings.maxDigits;

    if(maxDigits === '' || isNaN(maxDigits))
      return false; // In this case, there is no maximum

    var numDigits = countDigits(string);

    if(numDigits >= maxDigits)
      return true;

    return false;
  }

  function isMaxDecimalsReached(string, settings) {

    var maxDecimalPlaces = settings.maxDecimalPlaces;

    if(maxDecimalPlaces === '' || isNaN(maxDecimalPlaces))
      return false; // In this case, there is no maximum

    var indexOfDecimalPoint = string.indexOf(DEC_SEP);

    if(indexOfDecimalPoint == -1)
      return false;

    var decimalSubstring = string.substring(indexOfDecimalPoint);
    var numDecimals = countDigits(decimalSubstring);

    if(numDecimals >= maxDecimalPlaces)
      return true;

    return false;
  }

  function isMaxPreDecimalsReached(string, settings) {

    var maxPreDecimalPlaces = settings.maxPreDecimalPlaces;

    if(maxPreDecimalPlaces === '' || isNaN(maxPreDecimalPlaces))
      return false; // In this case, there is no maximum

    var indexOfDecimalPoint = string.indexOf(DEC_SEP);

    if(indexOfDecimalPoint >= 0)
      return false;

    var numPreDecimalDigits = countDigits(string);

    if(numPreDecimalDigits >= maxPreDecimalPlaces)
      return true;

    return false;
  }

  function isGreaterThanMax(numericString, settings) {

    if(!settings.max || settings.max < 0)
      return false;

    var outputNumber = parseFloat(numericString);
    if(outputNumber > settings.max)
      return true;

    return false;
  }

  function isLessThanMin(numericString, settings) {

    if(!settings.min || settings.min > 0)
      return false;

    var outputNumber = parseFloat(numericString);
    if(outputNumber < settings.min)
      return true;

    return false;
  }

  /********************************
   * Trims a string according to the settings provided
   ********************************/
  function trimAlphaNum(inputString, settings){

    if(typeof inputString != 'string')
      return inputString;

    var inChars = inputString.split('');
    var outChars = [];
    var i = 0;
    var Char;

    for(i=0; i<inChars.length; i++){
      Char = inChars[i];
      var validatedStringFragment = outChars.join('');
      if(alphanum_allowChar(validatedStringFragment, Char, settings))
        outChars.push(Char);
    }

    var outputString = outChars.join('');

    if(settings.forceLower)
      outputString = outputString.toLowerCase();
    else if(settings.forceUpper)
      outputString = outputString.toUpperCase();

    return outputString;
  }

  function trimNum(inputString, settings){
    if(typeof inputString != 'string')
      return inputString;

    var inChars = inputString.split('');
    var outChars = [];
    var i = 0;
    var Char;

    for(i=0; i<inChars.length; i++){
      Char = inChars[i];
      var validatedStringFragment = outChars.join('');
      if(numeric_allowChar(validatedStringFragment, Char, settings))
        outChars.push(Char);
    }

    return outChars.join('');
  }

  function isUpper(Char){
    var upper = Char.toUpperCase();
    var lower = Char.toLowerCase();

    if( (Char == upper) && (upper != lower))
      return true;
    else
      return false;
  }

  function isLower(Char){
    var upper = Char.toUpperCase();
    var lower = Char.toLowerCase();

    if( (Char == lower) && (upper != lower))
      return true;
    else
      return false;
  }

  function isCaseless(Char){
    if(Char.toUpperCase() == Char.toLowerCase())
      return true;
    else
      return false;
  }

  function getBlacklistSet(allow, disallow){

    var setOfBadChars  = new Set(BLACKLIST + disallow);
    var setOfGoodChars = new Set(allow);

    var blacklistSet   = setOfBadChars.subtract(setOfGoodChars);

    return blacklistSet;
  }

  function getDigitsMap(){
    var array = '0123456789'.split('');
    var map = {};
    var i = 0;
    var digit;

    for(i=0; i<array.length; i++){
      digit = array[i];
      map[digit] = true;
    }

    return map;
  }

  function getLatinCharsSet(){
    var lower = 'abcdefghijklmnopqrstuvwxyz';
    var upper = lower.toUpperCase();
    var azAZ = new Set(lower + upper);

    return azAZ;
  }

  function allowThouSep(currentString) {

    // Can't start with a THOU_SEP
    if(currentString.length == 0)
      return false;

    // Can't have a THOU_SEP anywhere after a DEC_SEP
    var posOfDecSep = currentString.indexOf(DEC_SEP);
    if(posOfDecSep >= 0)
      return false;

    var posOfFirstThouSep       = currentString.indexOf(THOU_SEP);

    // Check if this is the first occurrence of a THOU_SEP
    if(posOfFirstThouSep < 0)
      return true;

    var posOfLastThouSep        = currentString.lastIndexOf(THOU_SEP);
    var charsSinceLastThouSep   = currentString.length - posOfLastThouSep - 1;

    // Check if there has been 3 digits since the last THOU_SEP
    if(charsSinceLastThouSep < 3)
      return false;

    var digitsSinceFirstThouSep = countDigits(currentString.substring(posOfFirstThouSep));

    // Check if there has been a multiple of 3 digits since the first THOU_SEP
    if((digitsSinceFirstThouSep % 3) > 0)
      return false;

    return true;
  }

  ////////////////////////////////////////////////////////////////////////////////////
  // Implementation of a Set
  ////////////////////////////////////////////////////////////////////////////////////
  function Set(elems){
    if(typeof elems == 'string')
      this.map = stringToMap(elems);
    else
      this.map = {};
  }

  Set.prototype.add = function(set){

    var newSet = this.clone();

    for(var key in set.map)
      newSet.map[key] = true;

    return newSet;
  };

  Set.prototype.subtract = function(set){

    var newSet = this.clone();

    for(var key in set.map)
      delete newSet.map[key];

    return newSet;
  };

  Set.prototype.contains = function(key){
    if(this.map[key])
      return true;
    else
      return false;
  };

  Set.prototype.clone = function(){
    var newSet = new Set();

    for(var key in this.map)
      newSet.map[key] = true;

    return newSet;
  };
  ////////////////////////////////////////////////////////////////////////////////////

  function stringToMap(string){
    var map = {};
    var array = string.split('');
    var i=0;
    var Char;

    for(i=0; i<array.length; i++){
      Char = array[i];
      map[Char] = true;
    }

    return map;
  }

  // Backdoor for testing
  $.fn.alphanum.backdoorAlphaNum = function(inputString, settings){
    var combinedSettings = getCombinedSettingsAlphaNum(settings);

    return trimAlphaNum(inputString, combinedSettings);
  };

  $.fn.alphanum.backdoorNumeric = function(inputString, settings){
    var combinedSettings = getCombinedSettingsNum(settings);

    return trimNum(inputString, combinedSettings);
  };

  $.fn.alphanum.setNumericSeparators = function(settings) {

    if(settings.thousandsSeparator.length != 1)
      return;

    if(settings.decimalSeparator.length != 1)
      return;

    THOU_SEP = settings.thousandsSeparator;
    DEC_SEP = settings.decimalSeparator;
  };

})( jQuery );

/*eslint-disable */
//Include the 3rd party lib: jquery.caret.js


// Set caret position easily in jQuery
// Written by and Copyright of Luke Morton, 2011
// Licensed under MIT
(function ($) {
  // Behind the scenes method deals with browser
  // idiosyncrasies and such
  function caretTo(el, index) {
    if (el.createTextRange) {
      var range = el.createTextRange();
      range.move("character", index);
      range.select();
    } else if (el.selectionStart != null) {
      el.focus();
      el.setSelectionRange(index, index);
    }
  };

  // Another behind the scenes that collects the
  // current caret position for an element

  // TODO: Get working with Opera
  function caretPos(el) {
    if ("selection" in document) {
      var range = el.createTextRange();
      try {
        range.setEndPoint("EndToStart", document.selection.createRange());
      } catch (e) {
        // Catch IE failure here, return 0 like
        // other browsers
        return 0;
      }
      return range.text.length;
    } else if (el.selectionStart != null) {
      return el.selectionStart;
    }
  };

  // The following methods are queued under fx for more
  // flexibility when combining with $.fn.delay() and
  // jQuery effects.

  // Set caret to a particular index
  $.fn.alphanum_caret = function (index, offset) {
    if (typeof(index) === "undefined") {
      return caretPos(this.get(0));
    }

    return this.queue(function (next) {
      if (isNaN(index)) {
        var i = $(this).val().indexOf(index);

        if (offset === true) {
          i += index.length;
        } else if (typeof(offset) !== "undefined") {
          i += offset;
        }

        caretTo(this, i);
      } else {
        caretTo(this, index);
      }

      next();
    });
  };
}(jQuery));

/**********************************************************
* Selection Library
* Used to determine what text is highlighted in the textbox before a key is pressed.
* http://donejs.com/docs.html#!jQuery.fn.selection
* https://github.com/jupiterjs/jquerymx/blob/master/dom/selection/selection.js
***********************************************************/
(function(e){var t=function(e){return e.replace(/([a-z])([a-z]+)/gi,function(e,t,n){return t+n.toLowerCase()}).replace(/_/g,"")},n=function(e){return e.replace(/^([a-z]+)_TO_([a-z]+)/i,function(e,t,n){return n+"_TO_"+t})},r=function(e){return e?e.ownerDocument.defaultView||e.ownerDocument.parentWindow:window},i=function(t,n){var r=e.Range.current(t).clone(),i=e.Range(t).select(t);if(!r.overlaps(i)){return null}if(r.compare("START_TO_START",i)<1){startPos=0;r.move("START_TO_START",i)}else{fromElementToCurrent=i.clone();fromElementToCurrent.move("END_TO_START",r);startPos=fromElementToCurrent.toString().length}if(r.compare("END_TO_END",i)>=0){endPos=i.toString().length}else{endPos=startPos+r.toString().length}return{start:startPos,end:endPos}},s=function(t){var n=r(t);if(t.selectionStart!==undefined){if(document.activeElement&&document.activeElement!=t&&t.selectionStart==t.selectionEnd&&t.selectionStart==0){return{start:t.value.length,end:t.value.length}}return{start:t.selectionStart,end:t.selectionEnd}}else if(n.getSelection){return i(t,n)}else{try{if(t.nodeName.toLowerCase()=="input"){var s=r(t).document.selection.createRange(),o=t.createTextRange();o.setEndPoint("EndToStart",s);var u=o.text.length;return{start:u,end:u+s.text.length}}else{var a=i(t,n);if(!a){return a}var f=e.Range.current().clone(),l=f.clone().collapse().range,c=f.clone().collapse(false).range;l.moveStart("character",-1);c.moveStart("character",-1);if(a.startPos!=0&&l.text==""){a.startPos+=2}if(a.endPos!=0&&c.text==""){a.endPos+=2}return a}}catch(h){return{start:t.value.length,end:t.value.length}}}},o=function(e,t,n){var i=r(e);if(e.setSelectionRange){if(n===undefined){e.focus();e.setSelectionRange(t,t)}else{e.select();e.selectionStart=t;e.selectionEnd=n}}else if(e.createTextRange){var s=e.createTextRange();s.moveStart("character",t);n=n||t;s.moveEnd("character",n-e.value.length);s.select()}else if(i.getSelection){var o=i.document,u=i.getSelection(),f=o.createRange(),l=[t,n!==undefined?n:t];a([e],l);f.setStart(l[0].el,l[0].count);f.setEnd(l[1].el,l[1].count);u.removeAllRanges();u.addRange(f)}else if(i.document.body.createTextRange){var f=document.body.createTextRange();f.moveToElementText(e);f.collapse();f.moveStart("character",t);f.moveEnd("character",n!==undefined?n:t);f.select()}},u=function(e,t,n,r){if(typeof n[0]==="number"&&n[0]<t){n[0]={el:r,count:n[0]-e}}if(typeof n[1]==="number"&&n[1]<=t){n[1]={el:r,count:n[1]-e};}},a=function(e,t,n){var r,i;n=n||0;for(var s=0;e[s];s++){r=e[s];if(r.nodeType===3||r.nodeType===4){i=n;n+=r.nodeValue.length;u(i,n,t,r)}else if(r.nodeType!==8){n=a(r.childNodes,t,n)}}return n};jQuery.fn.selection=function(e,t){if(e!==undefined){return this.each(function(){o(this,e,t)})}else{return s(this[0])}};e.fn.selection.getCharElement=a})(jQuery);
/*eslint-enable */

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc