/** * Scriptcase input plugin */ $.widget('scriptcase.scInput', { /** * Default options */ options: { // General datatype : 'text', maxLength : 0, alignment : '', alignRight : false, enterTab : false, enterSubmit : false, selectOnFocus : true, lettersCase : '', // Mask mask : '', maskChars : '(){}[].,;:-+/ ', maskList : '', maskOrientation : 'right', maskZeroValue : '', allowedChars : '', decimalSep : '.', thousandsSep : ',', precision : 2, dateFormat : 'mdy', dateSep : '/', timeFormat : 'his', timeSep : ':', currencySymbol : '', currencyPosition: 'left', allowNegative : true, onlyNegative : false, negativePos : 'prefix', manualDecimals : false, thousandsFormat : 1, // Auto tab autoTab : false, // Watermark watermark : '', watermarkClass : '', // Internal $clone : null, completedZero : false, invalidCount : 0, inputFocusValue : '', isNegative : false, isNumeric : false, isZero : false, hasDecimalSep : false, pressedMinus : false, originalMask : '', forceMask : false, forceDecimalPos : false, longestMask : 0 }, /** * List of predefined masks */ masks: { 'cep' : '99.999-999', 'cpf' : '999.999.999-99', 'cnpj': '99.999.999/9999-99', 'ssn' : '999-99-9999', 'cc' : '9999 9999 9999 9999' }, // masks /** * List of special keys */ specialKeys: { 8 : 'backspace', 9 : 'tab', 13 : 'enter', 16 : 'shift', 17 : 'control', 18 : 'alt', 27 : 'esc', 33 : 'page up', 34 : 'page down', 35 : 'end', 36 : 'home', 37 : 'left', 38 : 'up', 39 : 'right', 40 : 'down', 45 : 'insert', 46 : 'delete', 93 : 'menu', 116: 'f5', 123: 'f12', 224: 'command' }, // specialKeys //------------------------------------------------------------------------------------------------------------------ // constructor method /** * Plugin instance creator */ _create: function() { this._loadOptions(); this._initializeSettings(); this._bindEvents(); this._createWatermark(); }, //------------------------------------------------------------------------------------------------------------------ // public method /** * Format the current value on the input */ formatValue: function() { this._getNewValue(); this._getRange(); this._maskValue(); this._setNewValue(); this._autoTab(); }, // formatValue //------------------------------------------------------------------------------------------------------------------ // event handling method /** * Bind the input element events */ _bindEvents: function() { this._on(this.element, { 'focus': '_onFocus', 'keypress': '_onKeyPress', 'input': '_onInput', 'blur': '_onBlur' }); }, // _bindEvents /** * Handle the focus event */ _onFocus: function() { this.options.hasChanged = false; this.options.isZero = this._hasOnlyZeros($(this.element).val()); if (this.options.selectOnFocus) { $(this.element).select(); } }, // _onFocus /** * Handle the keypress event */ _onKeyPress: function(e) { this._getNewValue(); this._getRange(); this._getPressedKey(e); this._checkForNegative(); if (this._isSpecialEnterTab()) { var prevDef = this._goToNextElement(); if (prevDef) { e.preventDefault(); } return true; } if (this._isNotText(this.element[0])) { return true; } if (this.options.isSpecial) { if (this._isEnterSubmit('enter')) { if (typeof nm_submit_form == 'function') { // para filtro da consulta nm_submit_form(); } else { document.F1.submit(); } } else if (this._isEnterTab('enter')) { var prevDef = this._goToNextElement(); if (prevDef) { e.preventDefault(); } } else if (13 == this.options.pressedKey && 'textarea' != this.element[0].type) { e.preventDefault(); } return true; } this._checkDecimalsPress(); }, // _onKeyPress /** * Handle the input event */ _onInput: function() { if (!this._isNotText(this.element[0])) { this._getNewValue(); this._getRange(); this._maskValue(); this._setNewValue(); } this._autoTab(); }, // _onInput /** * Handle the blur event */ _onBlur: function() { if (typeof _scCalculatorControl !== 'undefined') { if (_scCalculatorControl[$(this.element).attr('id')]) { return; } } if (this.options.isNumeric) { var testValue; testValue = this._removeCurrencySymbol($(this.element).val()); testValue = this._removeNegativeSymbol(testValue); if ('' == testValue) { $(this.element).val(''); } else if (this.options.isZero) { $(this.element).val(this._removeNegativeSymbol($(this.element).val())); } } if ('decimal' == this.options.datatype || 'currency' == this.options.datatype) { this._completeDecimal(); } if (typeof _scBrowser != undefined && ('msie' == _scBrowser || 'safari' == _scBrowser) && this.options.hasChanged) { $(this.element).trigger('change'); } }, // _onBlur //------------------------------------------------------------------------------------------------------------------ // range methods /** * Get the cursor position on the input */ _getRange: function() { this.options.range = {start: 0, end: 0}; if (!$.browser.msie) { this.options.range.start = this.element[0].selectionStart; this.options.range.end = this.element[0].selectionEnd; } else { if ('textarea' == this.element[0].type) { var inputRange = $(this.element).getSelection(); this.options.range.start = inputRange.start; this.options.range.end = inputRange.end; } else { var inputRange = document.selection.createRange(); this.options.range.start = 0 - inputRange.duplicate().moveStart('character', -100000); this.options.range.end = oPos.start + inputRange.text.length; } } this.options.charsFromRight = this.options.newValue.length - this.options.range.end; }, // _getRange /** * Set the cursor position on the input */ _setRange: function(startPos, endPos) { if ('undefined' == typeof endPos) { endPos = startPos; } if (this.element[0].setSelectionRange) { this.element[0].setSelectionRange(startPos, endPos); } else { var inputRange = this.element[0].createTextRange(); inputRange.collapse(); inputRange.moveStart('character', startPos); inputRange.moveEnd('character', endPos - startPos); inputRange.select(); } }, // _setRange //------------------------------------------------------------------------------------------------------------------ // processing methods /** * Get the new value after user input */ _getNewValue: function() { this.options.newValue = $(this.element).val(); }, // _getNewValue /** * Check if the value has changed. If yes, set the new value on the input */ _setNewValue: function() { if (this.options.newValue != this.options.maskedValue) { $(this.element).val(this.options.maskedValue); var negativePosFix = 0; if ('suffix' == this.options.negativePos) { if (this.options.isNegative) { negativePosFix = 1; } else if (this.options.pressedMinus) { negativePosFix = -1; } } this._setRange(this.options.maskedValue.length - this.options.charsFromRight - negativePosFix); this.options.hasChanged = true; } }, // _setNewValue /** * Get the pressed key and char */ _getPressedKey: function(e) { this.options.pressedKey = e.charCode || e.keyCode || e.which; this.options.pressedChar = String.fromCharCode(this.options.pressedKey); this.options.isSpecial = (null != this.specialKeys[this.options.pressedKey]) || e.ctrlKey || e.metaKey || e.altKey; if (this.options.isSpecial && ((46 == e.charCode && 0 == e.keyCode && 46 == e.which) || (46 == e.charCode && 46 == e.keyCode && 46 == e.which))) { this.options.isSpecial = false; } /*console.log(e.charCode + " - " + e.keyCode + " - " + e.which);*/ }, // _getPressedKey /** * Check if the negative sign was pressed on a numeric input */ _checkForNegative: function() { if (!this.options.isNumeric || !this.options.allowNegative) { return; } var hasMinus = false, newValue = this.options.newValue; while (-1 != (minusPos = newValue.indexOf('-'))) { newValue = newValue.substr(0, minusPos) + newValue.substr(minusPos + 1); hasMinus = !hasMinus; } if (this.options.onlyNegative) { this.options.isNegative = true; } else if (!hasMinus && '-' == this.options.pressedChar) { this.options.pressedMinus = true; this.options.isNegative = true; } else if (hasMinus && '-' == this.options.pressedChar) { this.options.pressedMinus = true; this.options.isNegative = false; } else if (!hasMinus && '+' == this.options.pressedChar) { this.options.isNegative = false; } else if (hasMinus && '+' == this.options.pressedChar) { this.options.isNegative = false; } else { this.options.isNegative = hasMinus; } }, // _checkForNegative //------------------------------------------------------------------------------------------------------------------ // configuration methods /** * Load any values set on the 'alt' attribute into the plugin options */ _loadOptions: function() { var userOptions = {}; if ($(this.element).attr('alt')) { eval('userOptions = ' + $(this.element).attr('alt') + ';'); } this.options = $.extend(this.options, userOptions); }, /** * Initialize the instance settings according to its type */ _initializeSettings: function() { if ('currency' == this.options.datatype && '' == this.options.currencySymbol) { this.options.datatype = 'decimal'; } if (('currency' == this.options.datatype || 'decimal' == this.options.datatype) && 0 == this.options.precision) { this.options.datatype = 'integer'; } if ('currency' != this.options.datatype && 'decimal' != this.options.datatype) { this.options.manualDecimals = false; } switch (this.options.datatype) { case 'integer': if ('left' != this.options.alignment && 'center' != this.options.alignment && 'justify' != this.options.alignment) { this.options.alignRight = true; } this.options.isNumeric = true; this.options.maskList = this._createIntegerMask(this.options.maxLength, this.options.thousandsFormat, this.options.thousandsSep); this.options.maskOrientation = 'left'; this.options.maskChars = this.options.thousandsSep; this.options.originalMask = this.options.maskList; this.options.precision = 0; break; case 'decimal': if ('left' != this.options.alignment && 'center' != this.options.alignment && 'justify' != this.options.alignment) { this.options.alignRight = true; } this.options.isNumeric = true; this.options.maskList = this._createDecimalMask(this.options.maxLength, this.options.thousandsFormat, this.options.decimalSep, this.options.thousandsSep, this.options.precision); this.options.maskZeroValue = this._createDecimalZeroValueMask(this.options.decimalSep, this.options.precision); this.options.maskOrientation = 'left'; this.options.maskChars = this.options.decimalSep + this.options.thousandsSep; this.options.originalMask = this.options.maskList; break; case 'currency': if ('left' != this.options.alignment && 'center' != this.options.alignment && 'justify' != this.options.alignment) { this.options.alignRight = true; } this.options.isNumeric = true; this.options.maskList = this._createDecimalMask(this.options.maxLength, this.options.thousandsFormat, this.options.decimalSep, this.options.thousandsSep, this.options.precision); this.options.maskZeroValue = this._createDecimalZeroValueMask(this.options.decimalSep, this.options.precision); this.options.maskOrientation = 'left'; this.options.maskChars = this.options.decimalSep + this.options.thousandsSep + this.options.currencySymbol + ' '; this.options.originalMask = this.options.maskList; break; case 'datetime': this.options.allowNegative = false; this.options.maskList = this._createDateTimeMask(this.options.dateFormat, this.options.dateSep, this.options.timeSep); this.options.maskChars = this.options.dateSep + this.options.timeSep + ' '; this.options.originalMask = this.options.maskList; break; case 'date': this.options.allowNegative = false; this.options.maskList = this._createDateMask(this.options.dateFormat, this.options.dateSep); this.options.maskChars = this.options.dateSep; this.options.originalMask = this.options.maskList; break; case 'time': this.options.allowNegative = false; this.options.maskList = this._createTimeMask(this.options.timeFormat, this.options.timeSep); this.options.maskChars = this.options.timeSep; this.options.originalMask = this.options.maskList; break; case 'mask': this.options.allowNegative = false; this.options.maskList = this.options.maskList; this.options.longestMask = this._getLongestMaskSize(this.options.maskList, this.options.maskChars); this.options.originalMask = this.options.maskList; break; case 'text': this.options.allowedChars = this.options.allowedChars.toLowerCase(); if(this.options.allowedChars != '') { this.options.allowedChars += "\r\n"; } this.options.maskChars = ''; break; default: this.options.allowNegative = false; this.options.maskList = this.masks[this.options.datatype] ? this.masks[this.options.datatype] : ''; this.options.originalMask = this.options.maskList; break; } if ('' != this.options.maskList) { this.options.maskListArray = this.options.maskList.split(';'); } else { this.options.maskListArray = new Array(); } this.options.originalLength = this.options.maxLength; this.options.maxLength = this._getMaxLength(); this.options.maskCharsArray = this.options.maskChars.split(''); $(this.element).attr('maxlength', this.options.maxLength); }, //------------------------------------------------------------------------------------------------------------------ // masking methods /** * Mask a value according to its configuration */ _maskValue: function() { var cleanValue = this._getCleanValue(); if (this.options.isNumeric && 0 < this.options.precision && this.options.manualDecimals) { this.options.hasDecimalSep = -1 < this.options.newValue.indexOf(this.options.decimalSep) || this.options.pressedChar == this.options.decimalSep; } if ('' == cleanValue) { this.options.maskedValue = ''; this._addNegativeSymbol(); return; } this.options.maskedValue = 'text' == this.options.datatype ? this._filterUnallowedChars(cleanValue) : this._applyMask(cleanValue); this._addNegativeSymbol(); this._addCurrencySymbol(); }, // _maskValue /** * Remove unallowed characters from the value */ _filterUnallowedChars: function(cleanValue) { if ('' == this.options.allowedChars) { return this._matchCase(cleanValue); } var filtered = ''; for (var i = 0; i < cleanValue.length; i++) { if (-1 < this.options.allowedChars.indexOf(cleanValue.charAt(i).toLowerCase())) { filtered += cleanValue.charAt(i); } } return this._matchCase(filtered); }, // _filterUnallowedChars /** * Apply the current mask to a clean value */ _applyMask: function(cleanValue) { var cleanArray, maskedValue, maskArray; if ('left' == this.options.maskOrientation && (!this.options.isNumeric || !this.options.isZero || this.options.precision == 0)) { cleanValue = this._checkMaxLength(cleanValue); } cleanArray = cleanValue.split(''); maskedValue = ''; if (this.options.isNumeric && this.options.isZero && this.options.precision > 0) { // allow deletion of decimals whose value is zero maskArray = this.options.maskZeroValue.split(''); } else { maskArray = this._getMaskArray(cleanValue.length); } if ('left' == this.options.maskOrientation && (!this.options.isNumeric || !this.options.isZero || this.options.precision == 0)) { maskArray.reverse(); cleanArray.reverse(); } this.options.invalidCount = 0; for (var i = 0; i < maskArray.length; i++) { if (-1 < $.inArray(maskArray[i], this.options.maskCharsArray)) { maskedValue += maskArray[i]; } else { getChar = true; while (getChar) { thisChar = cleanArray.shift(); if (this._testChar(thisChar, maskArray[i])) { getChar = false; } else { this.options.invalidCount++; thisChar = ''; } if (0 == cleanArray.length) { getChar = false; } } maskedValue += thisChar; } if (0 == cleanArray.length) { break; } } if ('left' == this.options.maskOrientation && (!this.options.isNumeric || !this.options.isZero || this.options.precision == 0)) { maskedValue = this._strReverse(maskedValue); } if (this.options.isNumeric && this.options.isZero && this.options.precision && this.options.pressedChar == this.options.decimalSep) { maskedValue += this.options.decimalSep; } return this._matchCase(maskedValue); }, // _applyMask /** * Get the mask array to be used to format the input value */ _getMaskArray: function(valueLength) { this.options.mask = ''; if (1 == this.options.maskListArray.length) { this.options.mask = this.options.maskListArray[0]; } else if (1 < this.options.maskListArray.length) { for (var i = 0; i < this.options.maskListArray.length; i++) { cleanMask = this._removeMaskChars(this.options.mask , this.options.maskCharsArray); cleanMaskI = this._removeMaskChars(this.options.maskListArray[i], this.options.maskCharsArray); if ('' == this.options.mask) { this.options.mask = this.options.maskListArray[i]; } else if (cleanMask.length < cleanMaskI.length && cleanMask.length < valueLength) { this.options.mask = this.options.maskListArray[i]; } } } // removes decimal part of the mask when using manual decimals if the input // length is less than than the integer length part configured for this field if (this.options.isNumeric && 0 < this.options.precision && this.options.manualDecimals && !this.options.hasDecimalSep) { var maskParts = this.options.mask.split(this.options.decimalSep); var cleanIntegerPart = this._removeMaskChars(maskParts[0], this.options.maskCharsArray); if (valueLength <= cleanIntegerPart.length) { this.options.mask = maskParts[0]; } } return this.options.mask.split(''); }, // _getMaskArray /** * Adds the currency symbol of a value */ _addCurrencySymbol: function() { if ('' == this.options.maskedValue) { return; } else if ('currency' != this.options.datatype) { return; } this.options.maskedValue = ('left' == this.options.currencyPosition) ? this.options.currencySymbol + ' ' + this.options.maskedValue : this.options.maskedValue + ' ' + this.options.currencySymbol; }, // _addCurrencySymbol /** * Removes the currency symbol of a value */ _removeCurrencySymbol: function(numValue) { if ('currency' != this.options.datatype) { return numValue; } if ('left' == this.options.currencyPosition) { if (numValue.substr(0, this.options.currencySymbol.length + 1) == this.options.currencySymbol + ' ') { return numValue.substr(this.options.currencySymbol.length + 1); } else if (numValue.substr(0, this.options.currencySymbol.length) == this.options.currencySymbol) { return numValue.substr(this.options.currencySymbol.length); } } else if ('right' == this.options.currencyPosition) { var curStr = numValue.substr(numValue.length - this.options.currencySymbol.length - 2), curPos = curStr.indexOf('-'); if (-1 < curPos) { numValue = numValue.substr(0, numValue.length - this.options.currencySymbol.length - 2) + '-' + curStr.substr(0, curPos) + curStr.substr(curPos + 1); } if (numValue.substr(numValue.length - this.options.currencySymbol.length - 1) == this.options.currencySymbol + ' ') { return numValue.substr(0, numValue.length - this.options.currencySymbol.length - 2); } else if (numValue.substr(numValue.length - this.options.currencySymbol.length) == this.options.currencySymbol) { return numValue.substr(0, numValue.length - this.options.currencySymbol.length - 1); } } var valArray = numValue.split(''), curSymbol = this.options.currencySymbol + ' ', arrSymbol = curSymbol.split(''); newValue = ''; for (var i = 0; i < valArray.length; i++) { if (-1 == $.inArray(numValue.charAt(i), arrSymbol)) { newValue += numValue.charAt(i); } } return newValue; }, // _removeCurrencySymbol /** * Adds the negative symbol to a value */ _addNegativeSymbol: function() { if (!this.options.isNumeric || !this.options.allowNegative) { return; } var maxLength = this.options.maxLength; // allow typing of decimal separator for manual decimals // when precision is 1 less than number size if (this.options.isNumeric && this.options.precision > 0) { maxLength++; if ('' != this.options.currencySymbol) { maxLength += this.options.currencySymbol.length + 1; } } if (this.options.isNegative) { $(this.element).attr('maxlength', maxLength + 1); if ('prefix' == this.options.negativePos) { this.options.maskedValue = '-' + this.options.maskedValue; } else { this.options.maskedValue = this.options.maskedValue + '-'; } } else { $(this.element).attr('maxlength', maxLength); } }, // _addNegativeSymbol /** * Removes the negative symbol of a value */ _removeNegativeSymbol: function(numValue) { if (!this.options.isNumeric) { return; } var hasMinus = false; while (-1 != (minusPos = numValue.indexOf('-'))) { numValue = numValue.substr(0, minusPos) + numValue.substr(minusPos + 1); hasMinus = !hasMinus; } if (!this.options.allowNegative) { this.options.isNegative = false; } else if (this.options.onlyNegative) { this.options.isNegative = true; } else { this.options.isNegative = hasMinus; } return numValue; }, // _removeNegativeSymbol /** * Complete a decimal value with trailing zeros */ _completeDecimal: function() { if (1 > this.options.precision) { return; } var newValue = $(this.element).val(); newValue = this._removeCurrencySymbol(newValue); if ('' != newValue) { if (-1 == newValue.indexOf(this.options.decimalSep)) { newValue += this.options.decimalSep + this._strRepeat('0', this.options.precision) } else { var valueParts = newValue.split(this.options.decimalSep); if (valueParts[1].length < this.options.precision) { valueParts[1] += this._strRepeat('0', this.options.precision - valueParts[1].length); newValue = valueParts.join(this.options.decimalSep); } } } this.options.maskedValue = newValue; this._addCurrencySymbol(); $(this.element).val(this.options.maskedValue); }, // _completeDecimal /** * Check if the input value exceeds the lenght of the mask when formatting to the left. If it does, remove last * character */ _checkMaxLength: function(cleanValue) { if (this.options.isNumeric && cleanValue.length > this.options.originalLength) { cleanValue = cleanValue.substr(0, cleanValue.length - 1); } return cleanValue; }, // _checkMaxLength /** * Test if a character 'thisChar' is valid */ _testChar: function(thisChar, charType) { var regExpression; if ('9' == charType) { regExpression = new RegExp('[0-9]'); return regExpression.test(thisChar); } else if ('a' == charType) { regExpression = new RegExp('[a-zA-Z]'); return regExpression.test(thisChar); } else if ('*' == charType) { regExpression = new RegExp('[0-9a-zA-Z]'); if (regExpression.test(thisChar)) { return true; } // http://kourge.net/projects/regexp-unicode-block /*regExpression = /[\u0600-\u06FF\u0750-\u077F]/; if (regExpression.test(thisChar)) { return true; }*/ return false; } return thisChar == charType; }, // _testChar /** * Transform the text according to the character case configuration */ _matchCase: function(oldValue) { if ('' == oldValue || '' == this.options.lettersCase) { return oldValue; } var newValue = ''; if ('first' == this.options.lettersCase) { var pos = 0; while (pos < oldValue.length && ' ' == oldValue.charAt(pos)) { newValue += oldValue.charAt(pos++); } if (pos < oldValue.length) { newValue += oldValue.charAt(pos).toUpperCase() + oldValue.substr(pos + 1); } } else if ('upper' == this.options.lettersCase || 'lower' == this.options.lettersCase) { for (var i = 0; i < oldValue.length; i++) { newValue += ('upper' == this.options.lettersCase) ? oldValue.charAt(i).toUpperCase() : oldValue.charAt(i).toLowerCase(); } } else if ('words' == this.options.lettersCase) { var words = oldValue.split(' '); for (var i = 0; i < words.length; i++) { if (0 < words[i].length) { words[i] = words[i].charAt(0).toUpperCase() + words[i].substr(1); } } newValue = words.join(' '); } return newValue; }, // _matchCase /** * Check if the value has a decimal separator when using manual decimals */ _checkDecimalsPress: function() { if (!this.options.manualDecimals) { return; } var decimalPos = this.options.newValue.indexOf(this.options.decimalSep), isDecimalKey = this.options.pressedChar == this.options.decimalSep, isNumberKey = 48 <= this.options.pressedKey && 57 >= this.options.pressedKey, maksParts = this.options.originalMask.split(this.options.decimalSep); if (isNumberKey && -1 == decimalPos && !this.options.manualDecimals) { this.options.maskList = maksParts[0]; } else if (isDecimalKey && ((-1 == decimalPos) || (decimalPos >= this.options.range.start && decimalPos <= this.options.range.end))) { var decimalSize = this.options.newValue.length - this.options.range.end; this.options.forceMask = true; this.options.forceDecimalPos = true; if (0 == decimalSize) { this.options.maskList = maksParts[0] + this.options.decimalSep; } else if (decimalSize < this.options.precision) { this.options.maskList = maksParts[0] + this.options.decimalSep + maksParts[1].substr(0, decimalSize); } else { this.options.maskList = this.options.originalMask; } } else if (isNumberKey && this.options.range.start == this.options.range.end && this.options.range.end > decimalPos) { var decimalSize = this.options.newValue.length - decimalPos; this.options.forceMask = true; if (this.options.precision == decimalSize) { this.options.maskList = this.options.originalMask; } else { this.options.maskList = maksParts[0] + this.options.decimalSep + maksParts[1].substr(0, decimalSize); } } else if (isNumberKey && this.options.range.start == this.options.range.end && this.options.range.end <= decimalPos) { var decimalSize = this.options.newValue.length - decimalPos; this.options.forceMask = true; if (this.options.precision == decimalSize - 1) { this.options.maskList = this.options.originalMask; } else { this.options.maskList = maksParts[0] + this.options.decimalSep + maksParts[1].substr(0, decimalSize - 1); } } else if (!isNumberKey && -1 < decimalPos) { var decimalSize = this.options.newValue.length - decimalPos; this.options.forceMask = true; if (this.options.precision == decimalSize) { this.options.maskList = this.options.originalMask; } else { this.options.maskList = maksParts[0] + this.options.decimalSep + maksParts[1].substr(0, decimalSize); } } this.options.maskListArray = this.options.maskList.split(';'); this.options.maxLength = this.options.maskList.length; }, // _checkDecimalsPress /** * Get the longest size of the mask list */ _getLongestMaskSize: function(maskList, charList) { var charArray = charList.split(''), maskArray = maskList.split(';'), maxLength = 0; for (var i = 0; i < maskArray.length; i++) { maxLength = Math.max(maxLength, this._removeMaskChars(maskArray[i], charArray).length); } return maxLength; }, // _getLongestMaskSize //------------------------------------------------------------------------------------------------------------------ // cleaning methods /** * Get the value without any mask characters */ _getCleanValue: function() { var cleanValue = this._removeMaskChars(this.options.newValue, this.options.maskCharsArray); if ('currency' == this.options.datatype) { cleanValue = this._removeCurrencySymbol(cleanValue); } if (this.options.isNumeric) { cleanValue = this._removeNegativeSymbol(cleanValue); } if (this.options.isNumeric) { if (0 == parseInt(cleanValue)) { this.options.isZero = true; if (this.options.precision > 0) { // allow deletion of decimals whose value is zero return cleanValue; } } else { this.options.isZero = false; } } if ('integer' == this.options.datatype) { cleanValue = this._removeZeros(cleanValue, 0); } else if ('decimal' == this.options.datatype || 'currency' == this.options.datatype) { cleanValue = this._removeZeros(cleanValue, this.options.precision); } return cleanValue; }, // _getCleanValue /** * Remove all mask characters leaving only the clean value */ _removeMaskChars: function(originalValue, maskCharsArray) { var unmaskedValue = ''; for (var i = 0; i < originalValue.length; i++) { if (-1 == $.inArray(originalValue.charAt(i), maskCharsArray)) { unmaskedValue += originalValue.charAt(i); } } return unmaskedValue; }, // _removeMaskChars /** * Remove the extra zeros on the left for numerical values */ _removeZeros: function(numValue, numPrecision) { if ('' == numValue) { return numValue; } while ('0' == numValue.substr(0, 1) && numPrecision + 1 < numValue.length) { numValue = numValue.substr(1); } this.options.completedZero = false; if (!this.options.manualDecimals && 0 < numPrecision && numPrecision + 1 > numValue.length) { numValue = this._strRepeat('0', numPrecision + 1 - numValue.length) + numValue; this.options.completedZero = true; } return numValue; }, // _removeZeros //------------------------------------------------------------------------------------------------------------------ // mask creation methods /** * Create an integer mask based on the input length 'numLength' and the thousands separator 'thousandSep' according * to a given format * * numFormat = 1: 9,999,999,999 * numFormat = 2: 9999999,999 * numFormat = 3: 9,99,99,99,999 */ _createIntegerMask: function(numLength, numFormat, thousandSep) { var numMask = new Array(); if (1 == numFormat) { var iRepeat = Math.floor(numLength / 3), iComplete = numLength % 3; if (0 != iComplete) { numMask.push(this._strRepeat('9', iComplete)); } for (var i = 0; i < iRepeat; i++) { numMask.push('999'); } } else if (2 == numFormat) { if (4 > numLength) { numMask.push(this._strRepeat('9', numLength)); } else { numMask.push(this._strRepeat('9', numLength - 3)); numMask.push(this._strRepeat('9', 3)); } } else if (3 == numFormat) { if (4 > numLength) { numMask.push(this._strRepeat('9', numLength)); } else { var iRepeat = Math.floor((numLength - 3) / 2), iComplete = (numLength - 3) % 2; if (0 != iComplete) { numMask.push(this._strRepeat('9', iComplete)); } for (var i = 0; i < iRepeat; i++) { numMask.push('99'); } numMask.push(this._strRepeat('9', 3)); } } return numMask.join(thousandSep); }, // _createIntegerMask /** * Create a decimal mask based on the input length 'numLength', the decimal separator 'decimalSep', the thousands * separator 'thousandSep' and the precision 'numPrecision' */ _createDecimalMask: function(numLength, numFormat, decimalSep, thousandSep, numPrecision) { var decimals = ''; if (0 < numPrecision) { numLength -= numPrecision; decimals = decimalSep + this._strRepeat('9', numPrecision) } return this._createIntegerMask(numLength, numFormat, thousandSep) + decimals; }, // _createDecimalMask /** * Create a mask for zero values. */ _createDecimalZeroValueMask: function(decimalSep, numPrecision) { var decimals = ''; if (0 < numPrecision) { decimals = decimalSep + this._strRepeat('9', numPrecision) } return '9' + decimals; }, // _createDecimalZeroValueMask /** * Create a date mask based on the input format 'dateFormat' and the date separator 'dateSep' */ _createDateMask: function(dateFormat, dateSep) { var dateMask = new Array(); dateFormat = dateFormat.replace(/dd/i, 'd') .replace(/mm/i, 'm') .replace(/yyyy/i, 'y') .replace(/aaaa/i, 'y'); for (var i = 0; i < dateFormat.length; i++) { switch (dateFormat.charAt(i)) { case 'd': case 'm': dateMask.push('99'); break; case 'y': dateMask.push('9999'); break; } } return dateMask.join(dateSep); }, // _createDateMask /** * Create a time mask based on the input format 'timeFormat' and the time separator 'timeSep' */ _createTimeMask: function(timeFormat, timeSep) { var timeMask = new Array(); timeFormat = timeFormat.replace(/hh/i, 'h') .replace(/ii/i, 'i') .replace(/sss/i, 'm') .replace(/ss/i, 's'); for (var i = 0; i < timeFormat.length; i++) { switch (timeFormat.charAt(i)) { case 'h': case 'i': case 's': timeMask.push('99'); break; case 'm': timeMask.push('999'); break; } } return timeMask.join(timeSep); }, // _createTimeMask /** * Create a date & time mask based on the input format 'dateTimeFormat', the date separator 'dateSep' and time * separator 'timeSep' */ _createDateTimeMask: function(dateTimeFormat, dateSep, timeSep) { var formatParts = dateTimeFormat.split(';'); return this._createDateMask(formatParts[0], dateSep) + ' ' + this._createTimeMask(formatParts[1], timeSep); }, // _createDateTimeMask //------------------------------------------------------------------------------------------------------------------ // auto tabbing methods /** * Auto tab to the next form element */ _autoTab: function() { if (!this.options.autoTab) { return; } else if (this.options.isSpecial || 16 == this.options.pressedKey) { return; } else if ('decimal' == this.options.datatype || 'currency' == this.options.datatype) { var sepPos = this.options.maskedValue.indexOf(this.options.decimalSep); if (-1 == sepPos) { return; } else if (this.options.maskedValue.substr(sepPos + 1).length < this.options.precision) { return; } } if ('mask' == this.options.datatype && this.options.longestMask <= this._removeMaskChars(this.options.maskedValue, this.options.maskChars.split('')).length) { this._goToNextElement(); } else if ('mask' != this.options.datatype && !this.options.isNegative && this.options.maskedValue.length >= this.options.maxLength) { this._goToNextElement(); } else if ('mask' != this.options.datatype && this.options.isNegative && (this.options.maskedValue.length - 1) >= this.options.maxLength) { this._goToNextElement(); } }, // _autoTab /** * Get the next form element if it exists */ _getNextElement: function() { var elementList = this.element[0].form.elements, inputIndex = $.inArray(this.element[0], elementList) + 1, testInput; for (var i = inputIndex; i < elementList.length; i++) { testInput = $(elementList[i]); if (this._isValidInput(testInput)) { return testInput; } } var formList = document.forms, formIndex = $.inArray(this.element[0].form, formList) + 1; for (var j = formIndex; j < formList.length; j++) { elementList = formList[j].elements; for (i = 0; i < elementList.length; i++) { testInput = $(elementList[i]); if (this._isValidInput(testInput)) { return testInput; } } } return null; }, // _getNextElement /** * Move the focus to the next form element */ _goToNextElement: function() { if ('textarea' == this.element[0].type) { return false; } nextElement = this._getNextElement(); if (nextElement) { nextElement.focus(); return this._isNotText(this.element[0]); } return false; }, // _goToNextElement /** * Test if an input is a valid one to focus to */ _isValidInput: function(testInput) { var inputElement = testInput.get(0); if (0 >= inputElement.offsetHeight || 0 >= inputElement.offsetWidth || inputElement.disabled) { return false; } if ('file' == inputElement.type) { return false; } return true; }, // _isValidInput //------------------------------------------------------------------------------------------------------------------ // watermark methods /** * Set the watermark for the input */ _createWatermark: function() { if ('' == this.options.watermark) { return; } $(this.element).attr('placeholder', this.options.watermark); }, // _createWatermark //------------------------------------------------------------------------------------------------------------------ // auxiliary methods /** * Get the maximum length of an input element */ _getMaxLength: function() { var maxLength = 0; if ('' != this.options.maskList) { for (var i = 0; i < this.options.maskListArray.length; i++) { maxLength = Math.max(maxLength, this.options.maskListArray[i].length); } } if (0 == maxLength) { if (0 < this.options.maxLength) { if (this.options.isNumeric && 0 < this.options.precision) { return this.options.maxLength + 1; } else { return this.options.maxLength; } } var thisElement = $(this.element); if (thisElement.attr('maxlength') && 0 < thisElement.attr('maxlength')) { return thisElement.attr('maxlength'); } if (thisElement.attr('size') && 0 < thisElement.attr('size')) { return thisElement.attr('size'); } } if ('currency' == this.options.datatype) { maxLength += this.options.currencySymbol.length + 1; } if (this.options.isNumeric && 0 < this.options.precision) { return maxLength + 1; } else { return maxLength; } }, // _getMaxLength /** * Check if the string only has '0' as numbers */ _hasOnlyZeros: function(testValue) { if (!this.options.isNumeric) { return false; } var regExpression = new RegExp('[1-9]'), i; for (i =0; i < testValue.length; i++) { if (regExpression.test(testValue[i])) { return false; } } return true; }, // _hasOnlyZeros /** * Check if the 'enter' tab option is enabled and which key was pressed */ _isEnterTab: function(pressedKey) { if (!this.options.enterTab) { return false; } if ('enter' == pressedKey) { return 13 == this.options.pressedKey; } else { return 9 == this.options.pressedKey; } }, // _isEnterTab /** * Check if the 'enter' submit option is enabled and which key was pressed */ _isEnterSubmit: function(pressedKey) { if (!this.options.enterSubmit) { return false; } if ('enter' == pressedKey) { return 13 == this.options.pressedKey; } else { return 9 == this.options.pressedKey; } }, // _isEnterSubmit /** * Check if the input is not text */ _isNotText: function(thisElement) { return ('select' == thisElement.type || 'select-one' == thisElement.type || 'select-multiple' == thisElement.type || 'checkbox' == thisElement.type || 'radio' == thisElement.type); }, // _isNotText _isSpecialEnterTab: function() { return this._isEnterTab('enter') && this._isNotText(this.element[0]); }, // _isSpecialEnterTab /** * Repeat a string 's' for 'n' times */ _strRepeat: function(s, n) { return new Array(n + 1).join(s); }, // _strRepeat /** * Reverse a string 's' */ _strReverse: function(s) { return s.split('').reverse().join(''); } // _strReverse });