1/** 2 * Scriptcase input plugin 3 */ 4$.widget('scriptcase.scInput', { 5 6 /** 7 * Default options 8 */ 9 options: { 10 // General 11 datatype : 'text', 12 maxLength : 0, 13 alignment : '', 14 alignRight : false, 15 enterTab : false, 16 enterSubmit : false, 17 selectOnFocus : true, 18 lettersCase : '', 19 // Mask 20 mask : '', 21 maskChars : '(){}[].,;:-+/ ', 22 maskList : '', 23 maskOrientation : 'right', 24 maskZeroValue : '', 25 allowedChars : '', 26 decimalSep : '.', 27 thousandsSep : ',', 28 precision : 2, 29 dateFormat : 'mdy', 30 dateSep : '/', 31 timeFormat : 'his', 32 timeSep : ':', 33 currencySymbol : '', 34 currencyPosition: 'left', 35 allowNegative : true, 36 onlyNegative : false, 37 negativePos : 'prefix', 38 manualDecimals : false, 39 thousandsFormat : 1, 40 // Auto tab 41 autoTab : false, 42 // Watermark 43 watermark : '', 44 watermarkClass : '', 45 // Internal 46 $clone : null, 47 completedZero : false, 48 invalidCount : 0, 49 inputFocusValue : '', 50 isNegative : false, 51 isNumeric : false, 52 isZero : false, 53 hasDecimalSep : false, 54 pressedMinus : false, 55 originalMask : '', 56 forceMask : false, 57 forceDecimalPos : false, 58 longestMask : 0 59 }, 60 61 /** 62 * List of predefined masks 63 */ 64 masks: { 65 'cep' : '99.999-999', 66 'cpf' : '999.999.999-99', 67 'cnpj': '**.***.***/****-**', 68 'ssn' : '999-99-9999', 69 'cc' : '9999 9999 9999 9999' 70 }, // masks 71 72 /** 73 * List of special keys 74 */ 75 specialKeys: { 76 8 : 'backspace', 77 9 : 'tab', 78 13 : 'enter', 79 16 : 'shift', 80 17 : 'control', 81 18 : 'alt', 82 27 : 'esc', 83 33 : 'page up', 84 34 : 'page down', 85 35 : 'end', 86 36 : 'home', 87 37 : 'left', 88 38 : 'up', 89 39 : 'right', 90 40 : 'down', 91 45 : 'insert', 92 46 : 'delete', 93 93 : 'menu', 94 116: 'f5', 95 123: 'f12', 96 224: 'command' 97 }, // specialKeys 98 99 //------------------------------------------------------------------------------------------------------------------ 100 // constructor method 101 102 /** 103 * Plugin instance creator 104 */ 105 _create: function() { 106 this._loadOptions(); 107 this._initializeSettings(); 108 this._bindEvents(); 109 this._createWatermark(); 110 }, 111 112 //------------------------------------------------------------------------------------------------------------------ 113 // public method 114 115 /** 116 * Format the current value on the input 117 */ 118 formatValue: function() { 119 this._getNewValue(); 120 this._getRange(); 121 this._maskValue(); 122 this._setNewValue(); 123 this._autoTab(); 124 }, // formatValue 125 126 //------------------------------------------------------------------------------------------------------------------ 127 // event handling method 128 129 /** 130 * Bind the input element events 131 */ 132 _bindEvents: function() { 133 this._on(this.element, { 134 'focus': '_onFocus', 135 'keypress': '_onKeyPress', 136 'input': '_onInput', 137 'blur': '_onBlur' 138 }); 139 }, // _bindEvents 140 141 /** 142 * Handle the focus event 143 */ 144 _onFocus: function() { 145 this.options.hasChanged = false; 146 147 this.options.isZero = this._hasOnlyZeros($(this.element).val()); 148 149 if (this.options.selectOnFocus) { 150 $(this.element).select(); 151 } 152 }, // _onFocus 153 154 /** 155 * Handle the keypress event 156 */ 157 _onKeyPress: function(e) { 158 this._getNewValue(); 159 this._getRange(); 160 this._getPressedKey(e); 161 this._checkForNegative(); 162 163 if (this._isSpecialEnterTab()) { 164 var prevDef = this._goToNextElement(); 165 166 if (prevDef) { 167 e.preventDefault(); 168 } 169 170 return true; 171 } 172 173 if (this._isNotText(this.element[0])) { 174 return true; 175 } 176 177 if (this.options.isSpecial) { 178 if (this._isEnterSubmit('enter')) { 179 if (typeof nm_submit_form == 'function') { // para filtro da consulta 180 nm_submit_form(); 181 } 182 else { 183 document.F1.submit(); 184 } 185 } 186 else if (this._isEnterTab('enter')) { 187 var prevDef = this._goToNextElement(); 188 189 if (prevDef) { 190 e.preventDefault(); 191 } 192 } 193 else if (13 == this.options.pressedKey && 'textarea' != this.element[0].type) { 194 e.preventDefault(); 195 } 196 197 return true; 198 } 199 200 this._checkDecimalsPress(); 201 }, // _onKeyPress 202 203 /** 204 * Handle the input event 205 */ 206 _onInput: function() { 207 if (!this._isNotText(this.element[0])) { 208 this._getNewValue(); 209 this._getRange(); 210 this._maskValue(); 211 this._setNewValue(); 212 } 213 this._autoTab(); 214 }, // _onInput 215 216 /** 217 * Handle the blur event 218 */ 219 _onBlur: function() { 220 if (typeof _scCalculatorControl !== 'undefined') { 221 if (_scCalculatorControl[$(this.element).attr('id')]) { 222 return; 223 } 224 } 225 226 if (this.options.isNumeric) { 227 var testValue; 228 229 testValue = this._removeCurrencySymbol($(this.element).val()); 230 testValue = this._removeNegativeSymbol(testValue); 231 232 if ('' == testValue) { 233 $(this.element).val(''); 234 } 235 else if (this.options.isZero) { 236 $(this.element).val(this._removeNegativeSymbol($(this.element).val())); 237 } 238 } 239 240 if ('decimal' == this.options.datatype || 'currency' == this.options.datatype) { 241 this._completeDecimal(); 242 } 243 244 if (typeof _scBrowser != undefined && ('msie' == _scBrowser || 'safari' == _scBrowser) && this.options.hasChanged) { 245 $(this.element).trigger('change'); 246 } 247 }, // _onBlur 248 249 //------------------------------------------------------------------------------------------------------------------ 250 // range methods 251 252 /** 253 * Get the cursor position on the input 254 */ 255 _getRange: function() { 256 this.options.range = {start: 0, end: 0}; 257 258 if (!$.browser.msie) { 259 this.options.range.start = this.element[0].selectionStart; 260 this.options.range.end = this.element[0].selectionEnd; 261 } 262 else { 263 if ('textarea' == this.element[0].type) { 264 var inputRange = $(this.element).getSelection(); 265 266 this.options.range.start = inputRange.start; 267 this.options.range.end = inputRange.end; 268 } 269 else { 270 var inputRange = document.selection.createRange(); 271 272 this.options.range.start = 0 - inputRange.duplicate().moveStart('character', -100000); 273 this.options.range.end = oPos.start + inputRange.text.length; 274 } 275 } 276 277 this.options.charsFromRight = this.options.newValue.length - this.options.range.end; 278 }, // _getRange 279 280 /** 281 * Set the cursor position on the input 282 */ 283 _setRange: function(startPos, endPos) { 284 if ('undefined' == typeof endPos) { 285 endPos = startPos; 286 } 287 288 if (this.element[0].setSelectionRange) { 289 this.element[0].setSelectionRange(startPos, endPos); 290 } 291 else { 292 var inputRange = this.element[0].createTextRange(); 293 294 inputRange.collapse(); 295 inputRange.moveStart('character', startPos); 296 inputRange.moveEnd('character', endPos - startPos); 297 inputRange.select(); 298 } 299 }, // _setRange 300 301 //------------------------------------------------------------------------------------------------------------------ 302 // processing methods 303 304 /** 305 * Get the new value after user input 306 */ 307 _getNewValue: function() { 308 this.options.newValue = $(this.element).val(); 309 }, // _getNewValue 310 311 /** 312 * Check if the value has changed. If yes, set the new value on the input 313 */ 314 _setNewValue: function() { 315 if (this.options.newValue != this.options.maskedValue) { 316 $(this.element).val(this.options.maskedValue); 317 318 var negativePosFix = 0; 319 320 if ('suffix' == this.options.negativePos) { 321 if (this.options.isNegative) { 322 negativePosFix = 1; 323 } 324 else if (this.options.pressedMinus) { 325 negativePosFix = -1; 326 } 327 } 328 329 this._setRange(this.options.maskedValue.length - this.options.charsFromRight - negativePosFix); 330 331 this.options.hasChanged = true; 332 } 333 }, // _setNewValue 334 335 /** 336 * Get the pressed key and char 337 */ 338 _getPressedKey: function(e) { 339 this.options.pressedKey = e.charCode || e.keyCode || e.which;
340 this.options.pressedChar = String.fromCharCode(this.options.pressedKey); 341 this.options.isSpecial = (null != this.specialKeys[this.options.pressedKey]) || e.ctrlKey || e.metaKey || e.altKey; 342 343 if (this.options.isSpecial && ((46 == e.charCode && 0 == e.keyCode && 46 == e.which) || (46 == e.charCode && 46 == e.keyCode && 46 == e.which))) { 344 this.options.isSpecial = false; 345 } 346 /*console.log(e.charCode + " - " + e.keyCode + " - " + e.which);*/ 347 }, // _getPressedKey 348 349 /** 350 * Check if the negative sign was pressed on a numeric input 351 */ 352 _checkForNegative: function() { 353 if (!this.options.isNumeric || !this.options.allowNegative) { 354 return; 355 } 356 357 var hasMinus = false, newValue = this.options.newValue; 358 359 while (-1 != (minusPos = newValue.indexOf('-'))) { 360 newValue = newValue.substr(0, minusPos) + newValue.substr(minusPos + 1); 361 hasMinus = !hasMinus; 362 } 363 364 if (this.options.onlyNegative) { 365 this.options.isNegative = true; 366 } 367 else if (!hasMinus && '-' == this.options.pressedChar) { 368 this.options.pressedMinus = true; 369 this.options.isNegative = true; 370 } 371 else if (hasMinus && '-' == this.options.pressedChar) { 372 this.options.pressedMinus = true; 373 this.options.isNegative = false; 374 } 375 else if (!hasMinus && '+' == this.options.pressedChar) { 376 this.options.isNegative = false; 377 } 378 else if (hasMinus && '+' == this.options.pressedChar) { 379 this.options.isNegative = false; 380 } 381 else { 382 this.options.isNegative = hasMinus; 383 } 384 }, // _checkForNegative 385 386 //------------------------------------------------------------------------------------------------------------------ 387 // configuration methods 388 389 /** 390 * Load any values set on the 'alt' attribute into the plugin options 391 */ 392 _loadOptions: function() { 393 var userOptions = {}; 394 395 if ($(this.element).attr('alt')) { 396 eval('userOptions = ' + $(this.element).attr('alt') + ';'); 397 } 398 399 this.options = $.extend(this.options, userOptions); 400 }, 401 402 /** 403 * Initialize the instance settings according to its type 404 */ 405 _initializeSettings: function() { 406 if ('currency' == this.options.datatype && '' == this.options.currencySymbol) { 407 this.options.datatype = 'decimal'; 408 } 409 410 if (('currency' == this.options.datatype || 'decimal' == this.options.datatype) && 0 == this.options.precision) { 411 this.options.datatype = 'integer'; 412 } 413 414 if ('currency' != this.options.datatype && 'decimal' != this.options.datatype) { 415 this.options.manualDecimals = false; 416 } 417 418 switch (this.options.datatype) { 419 case 'integer': 420 if ('left' != this.options.alignment && 'center' != this.options.alignment && 'justify' != this.options.alignment) { 421 this.options.alignRight = true; 422 } 423 this.options.isNumeric = true; 424 this.options.maskList = this._createIntegerMask(this.options.maxLength, this.options.thousandsFormat, this.options.thousandsSep); 425 this.options.maskOrientation = 'left'; 426 this.options.maskChars = this.options.thousandsSep; 427 this.options.originalMask = this.options.maskList; 428 this.options.precision = 0; 429 break; 430 431 case 'decimal': 432 if ('left' != this.options.alignment && 'center' != this.options.alignment && 'justify' != this.options.alignment) { 433 this.options.alignRight = true; 434 } 435 this.options.isNumeric = true; 436 this.options.maskList = this._createDecimalMask(this.options.maxLength, this.options.thousandsFormat, this.options.decimalSep, this.options.thousandsSep, this.options.precision); 437 this.options.maskZeroValue = this._createDecimalZeroValueMask(this.options.decimalSep, this.options.precision); 438 this.options.maskOrientation = 'left'; 439 this.options.maskChars = this.options.decimalSep + this.options.thousandsSep; 440 this.options.originalMask = this.options.maskList; 441 break; 442 443 case 'currency': 444 if ('left' != this.options.alignment && 'center' != this.options.alignment && 'justify' != this.options.alignment) { 445 this.options.alignRight = true; 446 } 447 this.options.isNumeric = true; 448 this.options.maskList = this._createDecimalMask(this.options.maxLength, this.options.thousandsFormat, this.options.decimalSep, this.options.thousandsSep, this.options.precision); 449 this.options.maskZeroValue = this._createDecimalZeroValueMask(this.options.decimalSep, this.options.precision); 450 this.options.maskOrientation = 'left'; 451 this.options.maskChars = this.options.decimalSep + this.options.thousandsSep + this.options.currencySymbol + ' '; 452 this.options.originalMask = this.options.maskList; 453 break; 454 455 case 'datetime': 456 this.options.allowNegative = false; 457 this.options.maskList = this._createDateTimeMask(this.options.dateFormat, this.options.dateSep, this.options.timeSep); 458 this.options.maskChars = this.options.dateSep + this.options.timeSep + ' '; 459 this.options.originalMask = this.options.maskList; 460 break; 461 462 case 'date': 463 this.options.allowNegative = false; 464 this.options.maskList = this._createDateMask(this.options.dateFormat, this.options.dateSep); 465 this.options.maskChars = this.options.dateSep; 466 this.options.originalMask = this.options.maskList; 467 break; 468 469 case 'time': 470 this.options.allowNegative = false; 471 this.options.maskList = this._createTimeMask(this.options.timeFormat, this.options.timeSep); 472 this.options.maskChars = this.options.timeSep; 473 this.options.originalMask = this.options.maskList; 474 break; 475 476 case 'mask': 477 this.options.allowNegative = false; 478 this.options.maskList = this.options.maskList; 479 this.options.longestMask = this._getLongestMaskSize(this.options.maskList, this.options.maskChars); 480 this.options.originalMask = this.options.maskList; 481 break; 482 483 case 'text': 484 this.options.allowedChars = this.options.allowedChars.toLowerCase(); 485 if(this.options.allowedChars != '') 486 { 487 this.options.allowedChars += "\r\n"; 488 } 489 this.options.maskChars = ''; 490 break; 491 492 default: 493 this.options.allowNegative = false; 494 this.options.maskList = this.masks[this.options.datatype] ? this.masks[this.options.datatype] : ''; 495 this.options.originalMask = this.options.maskList; 496 break; 497 } 498 499 if ('' != this.options.maskList) { 500 this.options.maskListArray = this.options.maskList.split(';'); 501 } 502 else { 503 this.options.maskListArray = new Array(); 504 } 505 506 this.options.originalLength = this.options.maxLength; 507 this.options.maxLength = this._getMaxLength(); 508 this.options.maskCharsArray = this.options.maskChars.split(''); 509 510 $(this.element).attr('maxlength', this.options.maxLength); 511 }, 512 513 //------------------------------------------------------------------------------------------------------------------ 514 // masking methods 515 516 /** 517 * Mask a value according to its configuration 518 */ 519 _maskValue: function() { 520 var cleanValue = this._getCleanValue(); 521 522 if (this.options.isNumeric && 0 < this.options.precision && this.options.manualDecimals) { 523 this.options.hasDecimalSep = -1 < this.options.newValue.indexOf(this.options.decimalSep) || this.options.pressedChar == this.options.decimalSep; 524 } 525 526 if ('' == cleanValue) { 527 this.options.maskedValue = ''; 528 this._addNegativeSymbol(); 529 return; 530 } 531 532 this.options.maskedValue = 'text' == this.options.datatype 533 ? this._filterUnallowedChars(cleanValue) 534 : this._applyMask(cleanValue); 535 536 this._addNegativeSymbol(); 537 this._addCurrencySymbol(); 538 }, // _maskValue 539 540 /** 541 * Remove unallowed characters from the value 542 */ 543 _filterUnallowedChars: function(cleanValue) { 544 if ('' == this.options.allowedChars) { 545 return this._matchCase(cleanValue); 546 } 547 548 var filtered = ''; 549 550 for (var i = 0; i < cleanValue.length; i++) { 551 if (-1 < this.options.allowedChars.indexOf(cleanValue.charAt(i).toLowerCase())) { 552 filtered += cleanValue.charAt(i); 553 } 554 } 555 556 return this._matchCase(filtered); 557 }, // _filterUnallowedChars 558 559 /** 560 * Apply the current mask to a clean value 561 */ 562 _applyMask: function(cleanValue) { 563 var cleanArray, maskedValue, maskArray; 564 565 if ('left' == this.options.maskOrientation && (!this.options.isNumeric || !this.options.isZero || this.options.precision == 0)) { 566 cleanValue = this._checkMaxLength(cleanValue); 567 } 568 569 cleanArray = cleanValue.split(''); 570 maskedValue = ''; 571 if (this.options.isNumeric && this.options.isZero && this.options.precision > 0) { // allow deletion of decimals whose value is zero 572 maskArray = this.options.maskZeroValue.split(''); 573 } 574 else { 575 maskArray = this._getMaskArray(cleanValue.length); 576 } 577 578 if ('left' == this.options.maskOrientation && (!this.options.isNumeric || !this.options.isZero || this.options.precision == 0)) { 579 maskArray.reverse(); 580 cleanArray.reverse(); 581 } 582 583 this.options.invalidCount = 0; 584 585 for (var i = 0; i < maskArray.length; i++) { 586 if (-1 < $.inArray(maskArray[i], this.options.maskCharsArray)) { 587 maskedValue += maskArray[i]; 588 } 589 else { 590 getChar = true; 591 592 while (getChar) { 593 thisChar = cleanArray.shift(); 594 595 if (this._testChar(thisChar, maskArray[i])) { 596 getChar = false; 597 } 598 else { 599 this.options.invalidCount++; 600 thisChar = ''; 601 } 602 603 if (0 == cleanArray.length) { 604 getChar = false; 605 } 606 } 607 608 maskedValue += thisChar; 609 } 610 611 if (0 == cleanArray.length) { 612 break; 613 } 614 } 615 616 if ('left' == this.options.maskOrientation && (!this.options.isNumeric || !this.options.isZero || this.options.precision == 0)) { 617 maskedValue = this._strReverse(maskedValue); 618 } 619 620 if (this.options.isNumeric && this.options.isZero && this.options.precision && this.options.pressedChar == this.options.decimalSep) { 621 maskedValue += this.options.decimalSep; 622 } 623 624 return this._matchCase(maskedValue); 625 }, // _applyMask 626 627 /** 628 * Get the mask array to be used to format the input value 629 */ 630 _getMaskArray: function(valueLength) { 631 this.options.mask = ''; 632 633 if (1 == this.options.maskListArray.length) { 634 this.options.mask = this.options.maskListArray[0]; 635 } 636 else if (1 < this.options.maskListArray.length) { 637 for (var i = 0; i < this.options.maskListArray.length; i++) { 638 cleanMask = this._removeMaskChars(this.options.mask , this.options.maskCharsArray);
639 cleanMaskI = this._removeMaskChars(this.options.maskListArray[i], this.options.maskCharsArray); 640 641 if ('' == this.options.mask) { 642 this.options.mask = this.options.maskListArray[i]; 643 } 644 else if (cleanMask.length < cleanMaskI.length && cleanMask.length < valueLength) { 645 this.options.mask = this.options.maskListArray[i]; 646 } 647 } 648 } 649 650 // removes decimal part of the mask when using manual decimals if the input 651 // length is less than than the integer length part configured for this field 652 if (this.options.isNumeric && 0 < this.options.precision && this.options.manualDecimals && !this.options.hasDecimalSep) { 653 var maskParts = this.options.mask.split(this.options.decimalSep); 654 var cleanIntegerPart = this._removeMaskChars(maskParts[0], this.options.maskCharsArray); 655 656 if (valueLength <= cleanIntegerPart.length) { 657 this.options.mask = maskParts[0]; 658 } 659 } 660 661 return this.options.mask.split(''); 662 }, // _getMaskArray 663 664 /** 665 * Adds the currency symbol of a value 666 */ 667 _addCurrencySymbol: function() { 668 if ('' == this.options.maskedValue) { 669 return; 670 } 671 else if ('currency' != this.options.datatype) { 672 return; 673 } 674 675 this.options.maskedValue = ('left' == this.options.currencyPosition) 676 ? this.options.currencySymbol + ' ' + this.options.maskedValue 677 : this.options.maskedValue + ' ' + this.options.currencySymbol; 678 }, // _addCurrencySymbol 679 680 /** 681 * Removes the currency symbol of a value 682 */ 683 _removeCurrencySymbol: function(numValue) { 684 if ('currency' != this.options.datatype) { 685 return numValue; 686 } 687 688 if ('left' == this.options.currencyPosition) { 689 if (numValue.substr(0, this.options.currencySymbol.length + 1) == this.options.currencySymbol + ' ') { 690 return numValue.substr(this.options.currencySymbol.length + 1); 691 } 692 else if (numValue.substr(0, this.options.currencySymbol.length) == this.options.currencySymbol) { 693 return numValue.substr(this.options.currencySymbol.length); 694 } 695 } 696 else if ('right' == this.options.currencyPosition) { 697 var curStr = numValue.substr(numValue.length - this.options.currencySymbol.length - 2), 698 curPos = curStr.indexOf('-'); 699 if (-1 < curPos) { 700 numValue = numValue.substr(0, numValue.length - this.options.currencySymbol.length - 2) + '-' 701 + curStr.substr(0, curPos) + curStr.substr(curPos + 1); 702 } 703 704 if (numValue.substr(numValue.length - this.options.currencySymbol.length - 1) == this.options.currencySymbol + ' ') { 705 return numValue.substr(0, numValue.length - this.options.currencySymbol.length - 2); 706 } 707 else if (numValue.substr(numValue.length - this.options.currencySymbol.length) == this.options.currencySymbol) { 708 return numValue.substr(0, numValue.length - this.options.currencySymbol.length - 1); 709 } 710 } 711 712 var valArray = numValue.split(''), 713 curSymbol = this.options.currencySymbol + ' ', 714 arrSymbol = curSymbol.split(''); 715 newValue = ''; 716 717 for (var i = 0; i < valArray.length; i++) { 718 if (-1 == $.inArray(numValue.charAt(i), arrSymbol)) { 719 newValue += numValue.charAt(i); 720 } 721 } 722 723 return newValue; 724 }, // _removeCurrencySymbol 725 726 /** 727 * Adds the negative symbol to a value 728 */ 729 _addNegativeSymbol: function() { 730 if (!this.options.isNumeric || !this.options.allowNegative) { 731 return; 732 } 733 734 var maxLength = this.options.maxLength; 735 736 // allow typing of decimal separator for manual decimals 737 // when precision is 1 less than number size 738 if (this.options.isNumeric && this.options.precision > 0) { 739 maxLength++; 740 741 if ('' != this.options.currencySymbol) { 742 maxLength += this.options.currencySymbol.length + 1; 743 } 744 } 745 746 if (this.options.isNegative) { 747 $(this.element).attr('maxlength', maxLength + 1); 748 if ('prefix' == this.options.negativePos) { 749 this.options.maskedValue = '-' + this.options.maskedValue; 750 } 751 else { 752 this.options.maskedValue = this.options.maskedValue + '-'; 753 } 754 } 755 else { 756 $(this.element).attr('maxlength', maxLength); 757 } 758 }, // _addNegativeSymbol 759 760 /** 761 * Removes the negative symbol of a value 762 */ 763 _removeNegativeSymbol: function(numValue) { 764 if (!this.options.isNumeric) { 765 return; 766 } 767 768 var hasMinus = false; 769 770 while (-1 != (minusPos = numValue.indexOf('-'))) { 771 numValue = numValue.substr(0, minusPos) + numValue.substr(minusPos + 1); 772 hasMinus = !hasMinus; 773 } 774 775 if (!this.options.allowNegative) { 776 this.options.isNegative = false; 777 } 778 else if (this.options.onlyNegative) { 779 this.options.isNegative = true; 780 } 781 else { 782 this.options.isNegative = hasMinus; 783 } 784 785 return numValue; 786 }, // _removeNegativeSymbol 787 788 /** 789 * Complete a decimal value with trailing zeros 790 */
791 _completeDecimal: function() { 792 if (1 > this.options.precision) { 793 return; 794 } 795 796 var newValue = $(this.element).val(); 797 798 newValue = this._removeCurrencySymbol(newValue); 799 800 if ('' != newValue) { 801 if (-1 == newValue.indexOf(this.options.decimalSep)) { 802 newValue += this.options.decimalSep + this._strRepeat('0', this.options.precision) 803 } 804 else { 805 var valueParts = newValue.split(this.options.decimalSep); 806 807 if (valueParts[1].length < this.options.precision) { 808 valueParts[1] += this._strRepeat('0', this.options.precision - valueParts[1].length); 809 newValue = valueParts.join(this.options.decimalSep); 810 } 811 } 812 } 813 814 this.options.maskedValue = newValue; 815 816 this._addCurrencySymbol(); 817 818 $(this.element).val(this.options.maskedValue); 819 }, // _completeDecimal 820 821 /** 822 * Check if the input value exceeds the lenght of the mask when formatting to the left. If it does, remove last 823 * character 824 */ 825 _checkMaxLength: function(cleanValue) { 826 if (this.options.isNumeric && cleanValue.length > this.options.originalLength) { 827 cleanValue = cleanValue.substr(0, cleanValue.length - 1); 828 } 829 830 return cleanValue; 831 }, // _checkMaxLength 832 833 /** 834 * Test if a character 'thisChar' is valid 835 */ 836 _testChar: function(thisChar, charType) { 837 var regExpression; 838 839 if ('9' == charType) { 840 regExpression = new RegExp('[0-9]'); 841 return regExpression.test(thisChar); 842 } 843 else if ('a' == charType) { 844 regExpression = new RegExp('[a-zA-Z]'); 845 return regExpression.test(thisChar); 846 } 847 else if ('*' == charType) { 848 regExpression = new RegExp('[0-9a-zA-Z]'); 849 if (regExpression.test(thisChar)) { 850 return true; 851 } 852 853 // http://kourge.net/projects/regexp-unicode-block 854 /*regExpression = /[\u0600-\u06FF\u0750-\u077F]/; 855 if (regExpression.test(thisChar)) { 856 return true; 857 }*/ 858 859 return false; 860 } 861 862 return thisChar == charType; 863 }, // _testChar 864 865 /** 866 * Transform the text according to the character case configuration 867 */ 868 _matchCase: function(oldValue) { 869 if ('' == oldValue || '' == this.options.lettersCase) { 870 return oldValue; 871 } 872 873 var newValue = ''; 874 875 if ('first' == this.options.lettersCase) { 876 var pos = 0; 877 878 while (pos < oldValue.length && ' ' == oldValue.charAt(pos)) { 879 newValue += oldValue.charAt(pos++); 880 } 881 if (pos < oldValue.length) { 882 newValue += oldValue.charAt(pos).toUpperCase() + oldValue.substr(pos + 1); 883 } 884 } 885 else if ('upper' == this.options.lettersCase || 'lower' == this.options.lettersCase) { 886 for (var i = 0; i < oldValue.length; i++) { 887 newValue += ('upper' == this.options.lettersCase) 888 ? oldValue.charAt(i).toUpperCase() 889 : oldValue.charAt(i).toLowerCase(); 890 } 891 } 892 else if ('words' == this.options.lettersCase) { 893 var words = oldValue.split(' '); 894 895 for (var i = 0; i < words.length; i++) { 896 if (0 < words[i].length) { 897 words[i] = words[i].charAt(0).toUpperCase() + words[i].substr(1); 898 } 899 } 900 newValue = words.join(' '); 901 } 902 903 return newValue; 904 }, // _matchCase 905 906 /** 907 * Check if the value has a decimal separator when using manual decimals 908 */ 909 _checkDecimalsPress: function() { 910 if (!this.options.manualDecimals) { 911 return; 912 } 913 914 var decimalPos = this.options.newValue.indexOf(this.options.decimalSep), 915 isDecimalKey = this.options.pressedChar == this.options.decimalSep, 916 isNumberKey = 48 <= this.options.pressedKey && 57 >= this.options.pressedKey, 917 maksParts = this.options.originalMask.split(this.options.decimalSep); 918 919 if (isNumberKey && -1 == decimalPos && !this.options.manualDecimals) { 920 this.options.maskList = maksParts[0]; 921 } 922 else if (isDecimalKey && ((-1 == decimalPos) || (decimalPos >= this.options.range.start && decimalPos <= this.options.range.end))) { 923 var decimalSize = this.options.newValue.length - this.options.range.end; 924 925 this.options.forceMask = true; 926 this.options.forceDecimalPos = true; 927 928 if (0 == decimalSize) { 929 this.options.maskList = maksParts[0] + this.options.decimalSep; 930 } 931 else if (decimalSize < this.options.precision) { 932 this.options.maskList = maksParts[0] + this.options.decimalSep + maksParts[1].substr(0, decimalSize); 933 } 934 else { 935 this.options.maskList = this.options.originalMask; 936 } 937 } 938 else if (isNumberKey && this.options.range.start == this.options.range.end && this.options.range.end > decimalPos) { 939 var decimalSize = this.options.newValue.length - decimalPos; 940 941 this.options.forceMask = true; 942 943 if (this.options.precision == decimalSize) { 944 this.options.maskList = this.options.originalMask; 945 } 946 else { 947 this.options.maskList = maksParts[0] + this.options.decimalSep + maksParts[1].substr(0, decimalSize); 948 } 949 } 950 else if (isNumberKey && this.options.range.start == this.options.range.end && this.options.range.end <= decimalPos) { 951 var decimalSize = this.options.newValue.length - decimalPos; 952 953 this.options.forceMask = true; 954 955 if (this.options.precision == decimalSize - 1) { 956 this.options.maskList = this.options.originalMask; 957 } 958 else { 959 this.options.maskList = maksParts[0] + this.options.decimalSep + maksParts[1].substr(0, decimalSize - 1); 960 } 961 } 962 else if (!isNumberKey && -1 < decimalPos) { 963 var decimalSize = this.options.newValue.length - decimalPos; 964 965 this.options.forceMask = true; 966 967 if (this.options.precision == decimalSize) { 968 this.options.maskList = this.options.originalMask; 969 } 970 else { 971 this.options.maskList = maksParts[0] + this.options.decimalSep + maksParts[1].substr(0, decimalSize); 972 } 973 } 974 975 this.options.maskListArray = this.options.maskList.split(';'); 976 this.options.maxLength = this.options.maskList.length; 977 }, // _checkDecimalsPress 978 979 /** 980 * Get the longest size of the mask list 981 */ 982 _getLongestMaskSize: function(maskList, charList) { 983 var charArray = charList.split(''), 984 maskArray = maskList.split(';'), 985 maxLength = 0; 986 987 for (var i = 0; i < maskArray.length; i++) { 988 maxLength = Math.max(maxLength, this._removeMaskChars(maskArray[i], charArray).length); 989 } 990 991 return maxLength; 992 }, // _getLongestMaskSize 993 994 //------------------------------------------------------------------------------------------------------------------ 995 // cleaning methods 996 997 /** 998 * Get the value without any mask characters 999 */ 1000 _getCleanValue: function() { 1001 var cleanValue = this._removeMaskChars(this.options.newValue, this.options.maskCharsArray);
1002 1003 if ('currency' == this.options.datatype) { 1004 cleanValue = this._removeCurrencySymbol(cleanValue); 1005 } 1006 if (this.options.isNumeric) { 1007 cleanValue = this._removeNegativeSymbol(cleanValue); 1008 } 1009 1010 if (this.options.isNumeric) { 1011 if (0 == parseInt(cleanValue)) { 1012 this.options.isZero = true; 1013 1014 if (this.options.precision > 0) { // allow deletion of decimals whose value is zero 1015 return cleanValue; 1016 } 1017 } 1018 else { 1019 this.options.isZero = false; 1020 } 1021 } 1022 1023 if ('integer' == this.options.datatype) { 1024 cleanValue = this._removeZeros(cleanValue, 0); 1025 } 1026 else if ('decimal' == this.options.datatype || 'currency' == this.options.datatype) { 1027 cleanValue = this._removeZeros(cleanValue, this.options.precision); 1028 } 1029 1030 return cleanValue; 1031 }, // _getCleanValue 1032 1033 /** 1034 * Remove all mask characters leaving only the clean value 1035 */ 1036 _removeMaskChars: function(originalValue, maskCharsArray) { 1037 var unmaskedValue = ''; 1038 1039 for (var i = 0; i < originalValue.length; i++) { 1040 if (-1 == $.inArray(originalValue.charAt(i), maskCharsArray)) { 1041 unmaskedValue += originalValue.charAt(i); 1042 } 1043 } 1044 1045 return unmaskedValue; 1046 }, // _removeMaskChars 1047 1048 /** 1049 * Remove the extra zeros on the left for numerical values 1050 */ 1051 _removeZeros: function(numValue, numPrecision) { 1052 if ('' == numValue) { 1053 return numValue; 1054 } 1055 1056 while ('0' == numValue.substr(0, 1) && numPrecision + 1 < numValue.length) { 1057 numValue = numValue.substr(1); 1058 } 1059 1060 this.options.completedZero = false; 1061 if (!this.options.manualDecimals && 0 < numPrecision && numPrecision + 1 > numValue.length) { 1062 numValue = this._strRepeat('0', numPrecision + 1 - numValue.length) + numValue; 1063 this.options.completedZero = true; 1064 } 1065 1066 return numValue; 1067 }, // _removeZeros 1068 1069 //------------------------------------------------------------------------------------------------------------------ 1070 // mask creation methods 1071 1072 /** 1073 * Create an integer mask based on the input length 'numLength' and the thousands separator 'thousandSep' according 1074 * to a given format 1075 * 1076 * numFormat = 1: 9,999,999,999 1077 * numFormat = 2: 9999999,999 1078 * numFormat = 3: 9,99,99,99,999 1079 */ 1080 _createIntegerMask: function(numLength, numFormat, thousandSep) { 1081 var numMask = new Array(); 1082 1083 if (1 == numFormat) { 1084 var iRepeat = Math.floor(numLength / 3), 1085 iComplete = numLength % 3; 1086 1087 if (0 != iComplete) { 1088 numMask.push(this._strRepeat('9', iComplete)); 1089 } 1090 for (var i = 0; i < iRepeat; i++) { 1091 numMask.push('999'); 1092 } 1093 } 1094 else if (2 == numFormat) { 1095 if (4 > numLength) { 1096 numMask.push(this._strRepeat('9', numLength)); 1097 } 1098 else { 1099 numMask.push(this._strRepeat('9', numLength - 3)); 1100 numMask.push(this._strRepeat('9', 3)); 1101 } 1102 } 1103 else if (3 == numFormat) { 1104 if (4 > numLength) { 1105 numMask.push(this._strRepeat('9', numLength)); 1106 } 1107 else { 1108 var iRepeat = Math.floor((numLength - 3) / 2), 1109 iComplete = (numLength - 3) % 2; 1110 1111 if (0 != iComplete) { 1112 numMask.push(this._strRepeat('9', iComplete)); 1113 } 1114 for (var i = 0; i < iRepeat; i++) { 1115 numMask.push('99'); 1116 } 1117 numMask.push(this._strRepeat('9', 3)); 1118 } 1119 } 1120 1121 return numMask.join(thousandSep); 1122 }, // _createIntegerMask 1123 1124 /** 1125 * Create a decimal mask based on the input length 'numLength', the decimal separator 'decimalSep', the thousands 1126 * separator 'thousandSep' and the precision 'numPrecision' 1127 */ 1128 _createDecimalMask: function(numLength, numFormat, decimalSep, thousandSep, numPrecision) { 1129 var decimals = ''; 1130 1131 if (0 < numPrecision) { 1132 numLength -= numPrecision; 1133 decimals = decimalSep + this._strRepeat('9', numPrecision) 1134 } 1135 1136 return this._createIntegerMask(numLength, numFormat, thousandSep) + decimals; 1137 }, // _createDecimalMask 1138 1139 /** 1140 * Create a mask for zero values. 1141 */ 1142 _createDecimalZeroValueMask: function(decimalSep, numPrecision) { 1143 var decimals = ''; 1144 1145 if (0 < numPrecision) { 1146 decimals = decimalSep + this._strRepeat('9', numPrecision) 1147 } 1148 1149 return '9' + decimals; 1150 }, // _createDecimalZeroValueMask 1151 1152 /** 1153 * Create a date mask based on the input format 'dateFormat' and the date separator 'dateSep' 1154 */ 1155 _createDateMask: function(dateFormat, dateSep) { 1156 var dateMask = new Array(); 1157 1158 dateFormat = dateFormat.replace(/dd/i, 'd') 1159 .replace(/mm/i, 'm') 1160 .replace(/yyyy/i, 'y') 1161 .replace(/aaaa/i, 'y'); 1162 1163 for (var i = 0; i < dateFormat.length; i++) { 1164 switch (dateFormat.charAt(i)) { 1165 case 'd': 1166 case 'm': 1167 dateMask.push('99'); 1168 break; 1169 1170 case 'y': 1171 dateMask.push('9999'); 1172 break; 1173 } 1174 } 1175 1176 return dateMask.join(dateSep); 1177 }, // _createDateMask 1178 1179 /** 1180 * Create a time mask based on the input format 'timeFormat' and the time separator 'timeSep' 1181 */ 1182 _createTimeMask: function(timeFormat, timeSep) { 1183 var timeMask = new Array(); 1184 1185 timeFormat = timeFormat.replace(/hh/i, 'h') 1186 .replace(/ii/i, 'i') 1187 .replace(/sss/i, 'm') 1188 .replace(/ss/i, 's'); 1189 1190 for (var i = 0; i < timeFormat.length; i++) { 1191 switch (timeFormat.charAt(i)) { 1192 case 'h': 1193 case 'i': 1194 case 's': 1195 timeMask.push('99'); 1196 break; 1197 case 'm': 1198 timeMask.push('999'); 1199 break; 1200 } 1201 } 1202 1203 return timeMask.join(timeSep); 1204 }, // _createTimeMask 1205 1206 /** 1207 * Create a date & time mask based on the input format 'dateTimeFormat', the date separator 'dateSep' and time 1208 * separator 'timeSep' 1209 */ 1210 _createDateTimeMask: function(dateTimeFormat, dateSep, timeSep) { 1211 var formatParts = dateTimeFormat.split(';'); 1212 1213 return this._createDateMask(formatParts[0], dateSep) + 1214 ' ' + 1215 this._createTimeMask(formatParts[1], timeSep); 1216 }, // _createDateTimeMask 1217 1218 //------------------------------------------------------------------------------------------------------------------ 1219 // auto tabbing methods 1220 1221 /** 1222 * Auto tab to the next form element 1223 */ 1224 _autoTab: function() { 1225 if (!this.options.autoTab) { 1226 return; 1227 } 1228 else if (this.options.isSpecial || 16 == this.options.pressedKey) { 1229 return; 1230 } 1231 else if ('decimal' == this.options.datatype || 'currency' == this.options.datatype) { 1232 var sepPos = this.options.maskedValue.indexOf(this.options.decimalSep); 1233 1234 if (-1 == sepPos) { 1235 return; 1236 } 1237 else if (this.options.maskedValue.substr(sepPos + 1).length < this.options.precision) { 1238 return; 1239 } 1240 } 1241 1242 if ('mask' == this.options.datatype && this.options.longestMask <= this._removeMaskChars(this.options.maskedValue, this.options.maskChars.split('')).length) { 1243 this._goToNextElement(); 1244 } 1245 else if ('mask' != this.options.datatype && !this.options.isNegative && this.options.maskedValue.length >= this.options.maxLength) { 1246 this._goToNextElement(); 1247 } 1248 else if ('mask' != this.options.datatype && this.options.isNegative && (this.options.maskedValue.length - 1) >= this.options.maxLength) { 1249 this._goToNextElement(); 1250 } 1251 }, // _autoTab 1252 1253 /** 1254 * Get the next form element if it exists 1255 */ 1256 _getNextElement: function() { 1257 var elementList = this.element[0].form.elements, 1258 inputIndex = $.inArray(this.element[0], elementList) + 1, 1259 testInput; 1260 1261 for (var i = inputIndex; i < elementList.length; i++) { 1262 testInput = $(elementList[i]); 1263 1264 if (this._isValidInput(testInput)) { 1265 return testInput; 1266 } 1267 } 1268 1269 var formList = document.forms, 1270 formIndex = $.inArray(this.element[0].form, formList) + 1; 1271 1272 for (var j = formIndex; j < formList.length; j++) { 1273 elementList = formList[j].elements; 1274 1275 for (i = 0; i < elementList.length; i++) { 1276 testInput = $(elementList[i]); 1277 1278 if (this._isValidInput(testInput)) { 1279 return testInput; 1280 } 1281 } 1282 } 1283 1284 return null; 1285 }, // _getNextElement 1286 1287 /** 1288 * Move the focus to the next form element 1289 */ 1290 _goToNextElement: function() { 1291 if ('textarea' == this.element[0].type) { 1292 return false; 1293 } 1294 1295 nextElement = this._getNextElement(); 1296 1297 if (nextElement) { 1298 nextElement.focus(); 1299 1300 return this._isNotText(this.element[0]); 1301 } 1302 1303 return false; 1304 }, // _goToNextElement 1305 1306 /** 1307 * Test if an input is a valid one to focus to 1308 */ 1309 _isValidInput: function(testInput) { 1310 var inputElement = testInput.get(0); 1311 1312 if (0 >= inputElement.offsetHeight || 0 >= inputElement.offsetWidth || inputElement.disabled) { 1313 return false; 1314 } 1315 1316 if ('file' == inputElement.type) { 1317 return false; 1318 } 1319 1320 return true; 1321 }, // _isValidInput 1322 1323 //------------------------------------------------------------------------------------------------------------------ 1324 // watermark methods 1325 1326 /** 1327 * Set the watermark for the input 1328 */ 1329 _createWatermark: function() { 1330 if ('' == this.options.watermark) { 1331 return; 1332 } 1333 1334 $(this.element).attr('placeholder', this.options.watermark); 1335 }, // _createWatermark 1336 1337 //------------------------------------------------------------------------------------------------------------------ 1338 // auxiliary methods 1339 1340 /** 1341 * Get the maximum length of an input element 1342 */ 1343 _getMaxLength: function() { 1344 var maxLength = 0; 1345 1346 if ('' != this.options.maskList) { 1347 for (var i = 0; i < this.options.maskListArray.length; i++) { 1348 maxLength = Math.max(maxLength, this.options.maskListArray[i].length); 1349 } 1350 } 1351 1352 if (0 == maxLength) { 1353 if (0 < this.options.maxLength) { 1354 if (this.options.isNumeric && 0 < this.options.precision) { 1355 return this.options.maxLength + 1; 1356 } else { 1357 return this.options.maxLength; 1358 } 1359 } 1360 1361 var thisElement = $(this.element); 1362 1363 if (thisElement.attr('maxlength') && 0 < thisElement.attr('maxlength')) { 1364 return thisElement.attr('maxlength'); 1365 } 1366 if (thisElement.attr('size') && 0 < thisElement.attr('size')) { 1367 return thisElement.attr('size'); 1368 } 1369 } 1370 1371 if ('currency' == this.options.datatype) { 1372 maxLength += this.options.currencySymbol.length + 1; 1373 } 1374 1375 if (this.options.isNumeric && 0 < this.options.precision) { 1376 return maxLength + 1; 1377 } else { 1378 return maxLength; 1379 } 1380 }, // _getMaxLength 1381 1382 /** 1383 * Check if the string only has '0' as numbers 1384 */ 1385 _hasOnlyZeros: function(testValue) { 1386 if (!this.options.isNumeric) { 1387 return false; 1388 } 1389 1390 var regExpression = new RegExp('[1-9]'), i; 1391 1392 for (i =0; i < testValue.length; i++) { 1393 if (regExpression.test(testValue[i])) { 1394 return false; 1395 } 1396 } 1397 1398 return true; 1399 }, // _hasOnlyZeros 1400 1401 /** 1402 * Check if the 'enter' tab option is enabled and which key was pressed 1403 */ 1404 _isEnterTab: function(pressedKey) { 1405 if (!this.options.enterTab) { 1406 return false; 1407 } 1408 1409 if ('enter' == pressedKey) { 1410 return 13 == this.options.pressedKey; 1411 } 1412 else { 1413 return 9 == this.options.pressedKey; 1414 } 1415 }, // _isEnterTab 1416 1417 /** 1418 * Check if the 'enter' submit option is enabled and which key was pressed 1419 */ 1420 _isEnterSubmit: function(pressedKey) { 1421 if (!this.options.enterSubmit) { 1422 return false; 1423 } 1424 1425 if ('enter' == pressedKey) { 1426 return 13 == this.options.pressedKey; 1427 } 1428 else { 1429 return 9 == this.options.pressedKey; 1430 } 1431 }, // _isEnterSubmit 1432 1433 /** 1434 * Check if the input is not text 1435 */ 1436 _isNotText: function(thisElement) { 1437 return ('select' == thisElement.type || 'select-one' == thisElement.type || 'select-multiple' == thisElement.type || 'checkbox' == thisElement.type || 'radio' == thisElement.type); 1438 }, // _isNotText 1439 1440 _isSpecialEnterTab: function() { 1441 return this._isEnterTab('enter') && this._isNotText(this.element[0]); 1442 }, // _isSpecialEnterTab 1443 1444 /** 1445 * Repeat a string 's' for 'n' times 1446 */ 1447 _strRepeat: function(s, n) { 1448 return new Array(n + 1).join(s);
1449 }, // _strRepeat 1450 1451 /** 1452 * Reverse a string 's' 1453 */ 1454 _strReverse: function(s) { 1455 return s.split('').reverse().join(''); 1456 } // _strReverse 1457 1458});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.