1/** 2 * autoNumeric.js 3 * @author: Bob Knothe 4 * @author: Sokolov Yura 5 * @version: 1.9.45 - 2015-06-13 GMT 5:00 PM / 19:00 6 * 7 * Created by Robert J. Knothe on 2010-10-25. Please report any bugs to https://github.com/BobKnothe/autoNumeric 8 * Contributor by Sokolov Yura on 2010-11-07 9 * 10 * Copyright (c) 2011 Robert J. Knothe http://www.decorplanit.com/plugin/ 11 * 12 * The MIT License (http://www.opensource.org/licenses/mit-license.php) 13 * 14 * Permission is hereby granted, free of charge, to any person 15 * obtaining a copy of this software and associated documentation 16 * files (the "Software"), to deal in the Software without 17 * restriction, including without limitation the rights to use, 18 * copy, modify, merge, publish, distribute, sublicense, and/or sell 19 * copies of the Software, and to permit persons to whom the 20 * Software is furnished to do so, subject to the following 21 * conditions: 22 * 23 * The above copyright notice and this permission notice shall be 24 * included in all copies or substantial portions of the Software. 25 * 26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 27 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 28 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 29 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 30 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 31 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 32 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 33 * OTHER DEALINGS IN THE SOFTWARE. 34 */ 35(function(factory) { 36 if (typeof define === "function" && define.amd) { 37 /** AMD. Register as an anonymous module. */ 38 define(["jquery"], factory); 39 } else if (typeof module === "object" && module.exports) { 40 /** Node/CommonJS */ 41 module.exports = factory(require("jquery")); 42 } else { 43 /** Browser globals */ 44 factory(window.jQuery); 45 } 46}(function($) { 47 "use strict"; 48 /*jslint browser: true*/ 49 /*global jQuery: false*/ 50 /*Cross browser routine for getting selected range/cursor position 51 */ 52 53 /** 54 * Cross browser routine for getting selected range/cursor position 55 */ 56 57 function getElementSelection(that) { 58 var position = {}; 59 if (that.selectionStart === undefined) { 60 that.focus(); 61 var select = document.selection.createRange(); 62 position.length = select.text.length; 63 select.moveStart('character', -that.value.length); 64 position.end = select.text.length; 65 position.start = position.end - position.length; 66 } else { 67 position.start = that.selectionStart; 68 position.end = that.selectionEnd; 69 position.length = position.end - position.start; 70 } 71 return position; 72 } 73 74 /** 75 * Cross browser routine for setting selected range/cursor position 76 */ 77 78 function setElementSelection(that, start, end) { 79 if (that.selectionStart === undefined) { 80 that.focus(); 81 var r = that.createTextRange(); 82 r.collapse(true); 83 r.moveEnd('character', end); 84 r.moveStart('character', start); 85 r.select(); 86 } else { 87 that.selectionStart = start; 88 that.selectionEnd = end; 89 } 90 } 91 92 /** 93 * run callbacks in parameters if any 94 * any parameter could be a callback: 95 * - a function, which invoked with jQuery element, parameters and this parameter name and returns parameter value 96 * - a name of function, attached to $(selector).autoNumeric.functionName(){} - which was called previously 97 */ 98 99 function runCallbacks($this, settings) { 100 /** 101 * loops through the settings object (option array) to find the following 102 * k = option name example k=aNum 103 * val = option value example val=0123456789 104 */ 105 $.each(settings, function(k, val) { 106 if (typeof val === 'function') { 107 settings[k] = val($this, settings, k); 108 } else if (typeof $this.autoNumeric[val] === 'function') { 109 /** 110 * calls the attached function from the html5 data example: data-a-sign="functionName" 111 */ 112 settings[k] = $this.autoNumeric[val]($this, settings, k); 113 } 114 }); 115 } 116 117 /** 118 * Converts the vMin, vMax & mDec string to numeric value 119 */ 120 121 function convertKeyToNumber(settings, key) {
122 if (typeof(settings[key]) === 'string') { 123 settings[key] *= 1; 124 } 125 } 126 127 /** 128 * Preparing user defined options for further usage 129 * merge them with defaults appropriately 130 */ 131 132 function autoCode($this, settings) { 133 runCallbacks($this, settings); 134 settings.tagList = ['b', 'caption', 'cite', 'code', 'dd', 'del', 'div', 'dfn', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'ins', 'kdb', 'label', 'li', 'output', 'p', 'q', 's', 'sample', 'span', 'strong', 'td', 'th', 'u', 'var']; 135 var vmax = settings.vMax.toString().split('.'), 136 vmin = (!settings.vMin && settings.vMin !== 0) ? [] : settings.vMin.toString().split('.'); 137 convertKeyToNumber(settings, 'vMax'); 138 convertKeyToNumber(settings, 'vMin'); 139 convertKeyToNumber(settings, 'mDec'); /** set mDec if not defined by user */ 140 settings.mDec = (settings.mRound === 'CHF') ? '2' : settings.mDec; 141 settings.allowLeading = true; 142 settings.aNeg = settings.vMin < 0 ? '-' : ''; 143 vmax[0] = vmax[0].replace('-', ''); 144 vmin[0] = vmin[0].replace('-', ''); 145 settings.mInt = Math.max(vmax[0].length, vmin[0].length, 1); 146 if (settings.mDec === null) { 147 var vmaxLength = 0, 148 vminLength = 0; 149 if (vmax[1]) { 150 vmaxLength = vmax[1].length; 151 } 152 if (vmin[1]) { 153 vminLength = vmin[1].length; 154 } 155 settings.mDec = Math.max(vmaxLength, vminLength); 156 } /** set alternative decimal separator key */ 157 if (settings.altDec === null && settings.mDec > 0) { 158 if (settings.aDec === '.' && settings.aSep !== ',') { 159 settings.altDec = ','; 160 } else if (settings.aDec === ',' && settings.aSep !== '.') { 161 settings.altDec = '.'; 162 } 163 } 164 /** cache regexps for autoStrip */ 165 var aNegReg = settings.aNeg ? '([-\\' + settings.aNeg + ']?)' : '(-?)'; 166 settings.aNegRegAutoStrip = aNegReg; 167 settings.skipFirstAutoStrip = new RegExp(aNegReg + '[^-' + (settings.aNeg ? '\\' + settings.aNeg : '') + '\\' + settings.aDec + '\\d]' + '.*?(\\d|\\' + settings.aDec + '\\d)'); 168 settings.skipLastAutoStrip = new RegExp('(\\d\\' + settings.aDec + '?)[^\\' + settings.aDec + '\\d]\\D*$'); 169 var allowed = '-' + settings.aNum + '\\' + settings.aDec; 170 settings.allowedAutoStrip = new RegExp('[^' + allowed + ']', 'gi'); 171 settings.numRegAutoStrip = new RegExp(aNegReg + '(?:\\' + settings.aDec + '?(\\d+\\' + settings.aDec + '\\d+)|(\\d*(?:\\' + settings.aDec + '\\d*)?))'); 172 return settings; 173 } 174 175 /** 176 * strips all unwanted characters and leave only a number alert 177 */ 178 179 function autoStrip(s, settings, strip_zero) { 180 if (settings.aSign) { /** remove currency sign */ 181 while (s.indexOf(settings.aSign) > -1) { 182 s = s.replace(settings.aSign, ''); 183 } 184 } 185 s = s.replace(settings.skipFirstAutoStrip, '$1$2'); /** first replace anything before digits */ 186 s = s.replace(settings.skipLastAutoStrip, '$1'); /** then replace anything after digits */ 187 s = s.replace(settings.allowedAutoStrip, ''); /** then remove any uninterested characters */ 188 if (settings.altDec) { 189 s = s.replace(settings.altDec, settings.aDec); 190 } /** get only number string */ 191 var m = s.match(settings.numRegAutoStrip); 192 s = m ? [m[1], m[2], m[3]].join('') : ''; 193 if ((settings.lZero === 'allow' || settings.lZero === 'keep') && strip_zero !== 'strip') { 194 var parts = [], 195 nSign = ''; 196 parts = s.split(settings.aDec); 197 if (parts[0].indexOf('-') !== -1) { 198 nSign = '-'; 199 parts[0] = parts[0].replace('-', ''); 200 } 201 if (parts[0].length > settings.mInt && parts[0].charAt(0) === '0') { /** strip leading zero if need */ 202 parts[0] = parts[0].slice(1); 203 } 204 s = nSign + parts.join(settings.aDec); 205 } 206 if ((strip_zero && settings.lZero === 'deny') || (strip_zero && settings.lZero === 'allow' && settings.allowLeading === false)) { 207 var strip_reg = '^' + settings.aNegRegAutoStrip + '0*(\\d' + (strip_zero === 'leading' ? ')' : '|$)');
208 strip_reg = new RegExp(strip_reg); 209 s = s.replace(strip_reg, '$1$2'); 210 } 211 return s; 212 } 213 214 /** 215 * places or removes brackets on negative values 216 * works only when with pSign: 'p' 217 */ 218 219 function negativeBracket(s, settings) { 220 if (settings.pSign === 'p') { 221 var brackets = settings.nBracket.split(','); 222 if (!settings.hasFocus && !settings.removeBrackets) { 223 s = s.replace(settings.aNeg, ''); 224 s = brackets[0] + s + brackets[1]; 225 } else if ((settings.hasFocus && s.charAt(0) === brackets[0]) || (settings.removeBrackets && s.charAt(0) === brackets[0])) { 226 s = s.replace(brackets[0], settings.aNeg); 227 s = s.replace(brackets[1], ''); 228 } 229 } 230 return s; 231 } 232 233 /** 234 * function to handle numbers less than 0 that are stored in Exponential notation ex: .0000001 stored as 1e-7 235 */ 236 237 function checkValue(value, settings) { 238 if (value) { 239 var checkSmall = +value; 240 if (checkSmall < 0.000001 && checkSmall > -1) { 241 value = +value; 242 if (value < 0.000001 && value > 0) { 243 value = (value + 10).toString(); 244 value = value.substring(1); 245 } 246 if (value < 0 && value > -1) { 247 value = (value - 10).toString(); 248 value = '-' + value.substring(2); 249 } 250 value = value.toString(); 251 } else { 252 var parts = value.split('.'); 253 if (parts[1] !== undefined) { 254 if (+parts[1] === 0) { 255 value = parts[0]; 256 } else { 257 parts[1] = parts[1].replace(/0*$/, ''); 258 value = parts.join('.'); 259 } 260 } 261 } 262 } 263 return (settings.lZero === 'keep') ? value : value.replace(/^0*(\d)/, '$1'); 264 } 265 266 /** 267 * prepare number string to be converted to real number 268 */ 269 270 function fixNumber(s, aDec, aNeg) { 271 if (aDec && aDec !== '.') { 272 s = s.replace(aDec, '.'); 273 } 274 if (aNeg && aNeg !== '-') { 275 s = s.replace(aNeg, '-'); 276 } 277 if (!s.match(/\d/)) { 278 s += '0'; 279 } 280 return s; 281 } 282 283 /** 284 * prepare real number to be converted to our format 285 */ 286 287 function presentNumber(s, aDec, aNeg) { 288 if (aNeg && aNeg !== '-') { 289 s = s.replace('-', aNeg); 290 } 291 if (aDec && aDec !== '.') { 292 s = s.replace('.', aDec); 293 } 294 return s; 295 } 296 297 /** 298 * private function to check for empty value 299 */ 300 301 function checkEmpty(iv, settings, signOnEmpty) { 302 if (iv === '' || iv === settings.aNeg) { 303 if (settings.wEmpty === 'zero') { 304 return iv + '0'; 305 } 306 if (settings.wEmpty === 'sign' || signOnEmpty) { 307 return iv + settings.aSign; 308 } 309 return iv; 310 } 311 return null; 312 } 313 314 /** 315 * private function that formats our number 316 */ 317 318 function autoGroup(iv, settings) { 319 iv = autoStrip(iv, settings); 320 var testNeg = iv.replace(',', '.'), 321 empty = checkEmpty(iv, settings, true); 322 if (empty !== null) { 323 return empty; 324 } 325 var digitalGroup = ''; 326 if (settings.dGroup === 2) { 327 digitalGroup = /(\d)((\d)(\d{2}?)+)$/; 328 } else if (settings.dGroup === 4) { 329 digitalGroup = /(\d)((\d{4}?)+)$/; 330 } else { 331 digitalGroup = /(\d)((\d{3}?)+)$/; 332 } /** splits the string at the decimal string */ 333 var ivSplit = iv.split(settings.aDec); 334 if (settings.altDec && ivSplit.length === 1) { 335 ivSplit = iv.split(settings.altDec); 336 } /** assigns the whole number to the a variable (s) */ 337 var s = ivSplit[0]; 338 if (settings.aSep) { 339 while (digitalGroup.test(s)) { /** re-inserts the thousand separator via a regular expression */ 340 s = s.replace(digitalGroup, '$1' + settings.aSep + '$2'); 341 } 342 } 343 if (settings.mDec !== 0 && ivSplit.length > 1) { 344 if (ivSplit[1].length > settings.mDec) { 345 ivSplit[1] = ivSplit[1].substring(0, settings.mDec); 346 } /** joins the whole number with the decimal value */ 347 iv = s + settings.aDec + ivSplit[1]; 348 } else { /** if whole numbers only */ 349 iv = s; 350 } 351 if (settings.aSign) { 352 var has_aNeg = iv.indexOf(settings.aNeg) !== -1; 353 iv = iv.replace(settings.aNeg, ''); 354 iv = settings.pSign === 'p' ? settings.aSign + iv : iv + settings.aSign; 355 if (has_aNeg) { 356 iv = settings.aNeg + iv; 357 } 358 } 359 if (testNeg < 0 && settings.nBracket !== null) { /** removes the negative sign and places brackets */ 360 iv = negativeBracket(iv, settings); 361 } 362 return iv; 363 } 364 365 /** 366 * round number after setting by pasting or $().autoNumericSet()
367 * private function for round the number 368 * please note this handled as text - JavaScript math function can return inaccurate values 369 * also this offers multiple rounding methods that are not easily accomplished in JavaScript 370 */ 371 372 function autoRound(iv, settings) { /** value to string */ 373 iv = (iv === '') ? '0' : iv.toString(); 374 convertKeyToNumber(settings, 'mDec'); /** set mDec to number needed when mDec set by 'update method */ 375 if (settings.mRound === 'CHF') { 376 iv = (Math.round(iv * 20) / 20).toString(); 377 } 378 var ivRounded = '', 379 i = 0, 380 nSign = '', 381 rDec = (typeof(settings.aPad) === 'boolean' || settings.aPad === null) ? (settings.aPad ? settings.mDec : 0) : +settings.aPad; 382 var truncateZeros = function(ivRounded) { /** truncate not needed zeros */ 383 var regex = (rDec === 0) ? (/(\.(?:\d*[1-9])?)0*$/) : rDec === 1 ? (/(\.\d(?:\d*[1-9])?)0*$/) : new RegExp('(\\.\\d{' + rDec + '}(?:\\d*[1-9])?)0*$'); 384 ivRounded = ivRounded.replace(regex, '$1'); /** If there are no decimal places, we don't need a decimal point at the end */ 385 if (rDec === 0) { 386 ivRounded = ivRounded.replace(/\.$/, ''); 387 } 388 return ivRounded; 389 }; 390 if (iv.charAt(0) === '-') { /** Checks if the iv (input Value)is a negative value */ 391 nSign = '-'; 392 iv = iv.replace('-', ''); /** removes the negative sign will be added back later if required */ 393 } 394 if (!iv.match(/^\d/)) { /** append a zero if first character is not a digit (then it is likely to be a dot)*/ 395 iv = '0' + iv; 396 } 397 if (nSign === '-' && +iv === 0) { /** determines if the value is zero - if zero no negative sign */ 398 nSign = ''; 399 } 400 if ((+iv > 0 && settings.lZero !== 'keep') || (iv.length > 0 && settings.lZero === 'allow')) { /** trims leading zero's if needed */ 401 iv = iv.replace(/^0*(\d)/, '$1'); 402 } 403 var dPos = iv.lastIndexOf('.'), 404 /** virtual decimal position */ 405 vdPos = (dPos === -1) ? iv.length - 1 : dPos, 406 /** checks decimal places to determine if rounding is required */ 407 cDec = (iv.length - 1) - vdPos; /** check if no rounding is required */ 408 if (cDec <= settings.mDec) { 409 ivRounded = iv; /** check if we need to pad with zeros */ 410 if (cDec < rDec) { 411 if (dPos === -1) { 412 ivRounded += settings.aDec; 413 } 414 var zeros = '000000'; 415 while (cDec < rDec) { 416 zeros = zeros.substring(0, rDec - cDec); 417 ivRounded += zeros; 418 cDec += zeros.length; 419 } 420 } else if (cDec > rDec) { 421 ivRounded = truncateZeros(ivRounded); 422 } else if (cDec === 0 && rDec === 0) { 423 ivRounded = ivRounded.replace(/\.$/, ''); 424 } 425 if (settings.mRound !== 'CHF') { 426 return (+ivRounded === 0) ? ivRounded : nSign + ivRounded; 427 } 428 if (settings.mRound === 'CHF') { 429 dPos = ivRounded.lastIndexOf('.'); 430 iv = ivRounded; 431 } 432 433 } /** rounded length of the string after rounding */ 434 var rLength = dPos + settings.mDec, 435 tRound = +iv.charAt(rLength + 1), 436 ivArray = iv.substring(0, rLength + 1).split(''), 437 odd = (iv.charAt(rLength) === '.') ? (iv.charAt(rLength - 1) % 2)
437: (iv.charAt(rLength) % 2), 438 onePass = true; 439 if (odd !== 1) { 440 odd = (odd === 0 && (iv.substring(rLength + 2, iv.length) > 0)) ? 1 : 0; 441 } 442 /*jslint white: true*/ 443 if ((tRound > 4 && settings.mRound === 'S') || /** Round half up symmetric */ 444 (tRound > 4 && settings.mRound === 'A' && nSign === '') || /** Round half up asymmetric positive values */ 445 (tRound > 5 && settings.mRound === 'A' && nSign === '-') || /** Round half up asymmetric negative values */ 446 (tRound > 5 && settings.mRound === 's') || /** Round half down symmetric */ 447 (tRound > 5 && settings.mRound === 'a' && nSign === '') || /** Round half down asymmetric positive values */ 448 (tRound > 4 && settings.mRound === 'a' && nSign === '-') || /** Round half down asymmetric negative values */ 449 (tRound > 5 && settings.mRound === 'B') || /** Round half even "Banker's Rounding" */ 450 (tRound === 5 && settings.mRound === 'B' && odd === 1) || /** Round half even "Banker's Rounding" */ 451 (tRound > 0 && settings.mRound === 'C' && nSign === '') || /** Round to ceiling toward positive infinite */ 452 (tRound > 0 && settings.mRound === 'F' && nSign === '-') || /** Round to floor toward negative infinite */ 453 (tRound > 0 && settings.mRound === 'U') || /** round up away from zero */ 454 (settings.mRound === 'CHF')) { /** Round Swiss FRanc */ 455 /*jslint white: false*/ 456 for (i = (ivArray.length - 1); i >= 0; i -= 1) { /** Round up the last digit if required, and continue until no more 9's are found */ 457 if (ivArray[i] !== '.') { 458 if (settings.mRound === 'CHF' && ivArray[i] <= 2 && onePass) { 459 ivArray[i] = 0; 460 onePass = false; 461 break; 462 } 463 if (settings.mRound === 'CHF' && ivArray[i] <= 7 && onePass) { 464 ivArray[i] = 5; 465 onePass = false; 466 break; 467 } 468 if (settings.mRound === 'CHF' && onePass) { 469 ivArray[i] = 10; 470 onePass = false; 471 } else { 472 ivArray[i] = +ivArray[i] + 1; 473 } 474 if (ivArray[i] < 10) { 475 break; 476 } 477 if (i > 0) { 478 ivArray[i] = '0'; 479 } 480 } 481 } 482 } 483 ivArray = ivArray.slice(0, rLength + 1); /** Reconstruct the string, converting any 10's to 0's */ 484 ivRounded = truncateZeros(ivArray.join('')); /** return rounded value */ 485 return (+ivRounded === 0) ? ivRounded : nSign + ivRounded; 486 } 487 488 /** 489 * truncate decimal part of a number 490 */ 491 492 function truncateDecimal(s, settings, paste) { 493 var aDec = settings.aDec, 494 mDec = settings.mDec; 495 s = (paste === 'paste') ? autoRound(s, settings) : s; 496 if (aDec && mDec) { 497 var parts = s.split(aDec); 498 /** truncate decimal part to satisfying length 499 * cause we would round it anyway */ 500 if (parts[1] && parts[1].length > mDec) { 501 if (mDec > 0) { 502 parts[1] = parts[1].substring(0, mDec); 503 s = parts.join(aDec); 504 } else { 505 s = parts[0]; 506 } 507 } 508 } 509 return s; 510 } 511 512 /** 513 * checking that number satisfy format conditions 514 * and lays between settings.vMin and settings.vMax 515 * and the string length does not exceed the digits in settings.vMin and settings.vMax 516 */ 517 518 function autoCheck(s, settings) { 519 s = autoStrip(s, settings); 520 s = truncateDecimal(s, settings); 521 s = fixNumber(s, settings.aDec, settings.aNeg); 522 var value = +s; 523 return value >= settings.vMin && value <= settings.vMax; 524 } 525 526 /** 527 * Holder object for field properties 528 */ 529 530 function AutoNumericHolder(that, settings) { 531 this.settings = settings; 532 this.that = that; 533 this.$that = $(that); 534 this.formatted = false;
535 this.settingsClone = autoCode(this.$that, this.settings); 536 this.value = that.value; 537 } 538 AutoNumericHolder.prototype = { 539 init: function(e) { 540 this.value = this.that.value; 541 this.settingsClone = autoCode(this.$that, this.settings); 542 this.ctrlKey = e.ctrlKey; 543 this.cmdKey = e.metaKey; 544 this.shiftKey = e.shiftKey; 545 this.selection = getElementSelection(this.that); /** keypress event overwrites meaningful value of e.keyCode */ 546 if (e.type === 'keydown' || e.type === 'keyup') { 547 this.kdCode = e.keyCode; 548 } 549 this.which = e.which; 550 this.processed = false; 551 this.formatted = false; 552 }, 553 setSelection: function(start, end, setReal) { 554 start = Math.max(start, 0); 555 end = Math.min(end, this.that.value.length); 556 this.selection = { 557 start: start, 558 end: end, 559 length: end - start 560 }; 561 if (setReal === undefined || setReal) { 562 setElementSelection(this.that, start, end); 563 } 564 }, 565 setPosition: function(pos, setReal) { 566 this.setSelection(pos, pos, setReal); 567 }, 568 getBeforeAfter: function() { 569 var value = this.value, 570 left = value.substring(0, this.selection.start), 571 right = value.substring(this.selection.end, value.length); 572 return [left, right]; 573 }, 574 getBeforeAfterStriped: function() { 575 var parts = this.getBeforeAfter(); 576 parts[0] = autoStrip(parts[0], this.settingsClone); 577 parts[1] = autoStrip(parts[1], this.settingsClone); 578 return parts; 579 }, 580 581 582 /** 583 * strip parts from excess characters and leading zeroes 584 */ 585 normalizeParts: function(left, right) { 586 var settingsClone = this.settingsClone; 587 right = autoStrip(right, settingsClone); /** if right is not empty and first character is not aDec, */ 588 /** we could strip all zeros, otherwise only leading */ 589 var strip = right.match(/^\d/) ? true : 'leading'; 590 left = autoStrip(left, settingsClone, strip); /** prevents multiple leading zeros from being entered */ 591 if ((left === '' || left === settingsClone.aNeg) && settingsClone.lZero === 'deny') { 592 if (right > '') { 593 right = right.replace(/^0*(\d)/, '$1'); 594 } 595 } 596 var new_value = left + right; /** insert zero if has leading dot */ 597 if (settingsClone.aDec) { 598 var m = new_value.match(new RegExp('^' + settingsClone.aNegRegAutoStrip + '\\' + settingsClone.aDec)); 599 if (m) { 600 left = left.replace(m[1], m[1] + '0'); 601 new_value = left + right; 602 } 603 } /** insert zero if number is empty and io.wEmpty == 'zero' */ 604 if (settingsClone.wEmpty === 'zero' && (new_value === settingsClone.aNeg || new_value === '')) { 605 left += '0'; 606 } 607 return [left, right]; 608 }, 609 610 /** 611 * set part of number to value keeping position of cursor 612 */ 613 setValueParts: function(left, right, paste) { 614 var settingsClone = this.settingsClone, 615 parts = this.normalizeParts(left, right), 616 new_value = parts.join(''), 617 position = parts[0].length; 618 if (autoCheck(new_value, settingsClone)) { 619 new_value = truncateDecimal(new_value, settingsClone, paste); 620 if (position > new_value.length) { 621 position = new_value.length; 622 } 623 this.value = new_value; 624 this.setPosition(position, false); 625 return true; 626 } 627 return false; 628 }, 629 630 /** 631 * helper function for expandSelectionOnSign 632 * returns sign position of a formatted value 633 */ 634 signPosition: function() { 635 var settingsClone = this.settingsClone, 636 aSign = settingsClone.aSign, 637 that = this.that; 638 if (aSign) { 639 var aSignLen = aSign.length; 640 if (settingsClone.pSign === 'p') { 641 var hasNeg = settingsClone.aNeg && that.value && that.value.charAt(0) === settingsClone.aNeg; 642 return hasNeg ? [1, aSignLen + 1] : [0, aSignLen]; 643 } 644 var valueLen = that.value.length; 645 return [valueLen - aSignLen, valueLen]; 646 } 647 return [1000, -1]; 648 }, 649 650 /** 651 * expands selection to cover whole sign 652 * prevents partial deletion/copying/overwriting of a sign 653 */ 654 expandSelectionOnSign: function(setReal) { 655 var sign_position = this.signPosition(), 656 selection = this.selection; 657 if (selection.start < sign_position[1] && selection.end > sign_position[0]) { /** if selection catches something except sign and catches only space from sign */ 658 if ((selection.start < sign_position[0] || selection.end > sign_position[1]) && this.value.substring(Math.max(selection.start, sign_position[0]), Math.min(selection.end, sign_position[1])).match(/^\s*$/)) { /** then select without empty space */ 659 if (selection.start < sign_position[0]) { 660 this.setSelection(selection.start, sign_position[0], setReal); 661 } else { 662 this.setSelection(sign_position[1], selection.end, setReal); 663 } 664 } else { /** else select with whole sign */ 665 this.setSelection(Math.min(selection.start, sign_position[0]), Math.max(selection.end, sign_position[1]), setReal); 666 } 667 } 668 }, 669 670 /**
671 * try to strip pasted value to digits 672 */ 673 checkPaste: function() { 674 if (this.valuePartsBeforePaste !== undefined) { 675 var parts = this.getBeforeAfter(), 676 677 oldParts = this.valuePartsBeforePaste; 678 delete this.valuePartsBeforePaste; /** try to strip pasted value first */ 679 parts[0] = parts[0].substr(0, oldParts[0].length) + autoStrip(parts[0].substr(oldParts[0].length), this.settingsClone); 680 if (!this.setValueParts(parts[0], parts[1], 'paste')) { 681 this.value = oldParts.join(''); 682 this.setPosition(oldParts[0].length, false); 683 } 684 } 685 }, 686 687 /** 688 * process pasting, cursor moving and skipping of not interesting keys 689 * if returns true, further processing is not performed 690 */ 691 skipAllways: function(e) { 692 var kdCode = this.kdCode, 693 which = this.which, 694 ctrlKey = this.ctrlKey, 695 cmdKey = this.cmdKey, 696 shiftKey = this.shiftKey; /** catch the ctrl up on ctrl-v */ 697 if (((ctrlKey || cmdKey) && e.type === 'keyup' && this.valuePartsBeforePaste !== undefined) || (shiftKey && kdCode === 45)) { 698 this.checkPaste(); 699 return false; 700 } 701 /** codes are taken from http://www.cambiaresearch.com/c4/702b8cd1-e5b0-42e6-83ac-25f0306e3e25/Javascript-Char-Codes-Key-Codes.aspx 702 * skip Fx keys, windows keys, other special keys 703 * Thanks Ney Estrabelli for the FF for Mac meta key support "keycode 224" 704 */ 705 if ((kdCode >= 112 && kdCode <= 123) || (kdCode >= 91 && kdCode <= 93) || (kdCode >= 9 && kdCode <= 31) || (kdCode < 8 && (which === 0 || which === kdCode)) || kdCode === 144 || kdCode === 145 || kdCode === 45 || kdCode === 224) { 706 return true; 707 } 708 if ((ctrlKey || cmdKey) && kdCode === 65) { /** if select all (a=65)*/ 709 return true; 710 } 711 if ((ctrlKey || cmdKey) && (kdCode === 67 || kdCode === 86 || kdCode === 88)) { /** if copy (c=67) paste (v=86) or cut (x=88) */ 712 if (e.type === 'keydown') { 713 this.expandSelectionOnSign(); 714 } 715 if (kdCode === 86 || kdCode === 45) { /** try to prevent wrong paste */ 716 if (e.type === 'keydown' || e.type === 'keypress') { 717 if (this.valuePartsBeforePaste === undefined) { 718 this.valuePartsBeforePaste = this.getBeforeAfter(); 719 } 720 } else { 721 this.checkPaste(); 722 } 723 } 724 return e.type === 'keydown' || e.type === 'keypress' || kdCode === 67; 725 } 726 if (ctrlKey || cmdKey) { 727 return true; 728 } 729 if (kdCode === 37 || kdCode === 39) { /** jump over thousand separator */ 730 var aSep = this.settingsClone.aSep, 731 start = this.selection.start, 732 value = this.that.value; 733 if (e.type === 'keydown' && aSep && !this.shiftKey) { 734 if (kdCode === 37 && value.charAt(start - 2) === aSep) { 735 this.setPosition(start - 1); 736 } else if (kdCode === 39 && value.charAt(start + 1) === aSep) { 737 this.setPosition(start + 1); 738 } 739 } 740 return true; 741 } 742 if (kdCode >= 34 && kdCode <= 40) { 743 return true; 744 } 745 return false; 746 }, 747 748 /** 749 * process deletion of characters 750 * returns true if processing performed 751 */ 752 processAllways: function() { 753 var parts; /** process backspace or delete */ 754 if (this.kdCode === 8 || this.kdCode === 46) { 755 if (!this.selection.length) { 756 parts = this.getBeforeAfterStriped(); 757 if (this.kdCode === 8) { 758 parts[0] = parts[0].substring(0, parts[0].length - 1); 759 } else { 760 parts[1] = parts[1].substring(1, parts[1].length); 761 } 762 this.setValueParts(parts[0], parts[1]); 763 } else { 764 this.expandSelectionOnSign(false); 765 parts = this.getBeforeAfterStriped(); 766 this.setValueParts(parts[0], parts[1]); 767 } 768 return true; 769 } 770 return false;
771 }, 772 773 /** 774 * process insertion of characters 775 * returns true if processing performed 776 */ 777 processKeypress: function() { 778 var settingsClone = this.settingsClone, 779 cCode = String.fromCharCode(this.which), 780 parts = this.getBeforeAfterStriped(), 781 left = parts[0], 782 right = parts[1]; /** start rules when the decimal character key is pressed */ 783 /** always use numeric pad dot to insert decimal separator */ 784 if (cCode === settingsClone.aDec || (settingsClone.altDec && cCode === settingsClone.altDec) || ((cCode === '.' || cCode === ',') && this.kdCode === 110)) { /** do not allow decimal character if no decimal part allowed */ 785 if (!settingsClone.mDec || !settingsClone.aDec) { 786 return true; 787 } /** do not allow decimal character before aNeg character */ 788 if (settingsClone.aNeg && right.indexOf(settingsClone.aNeg) > -1) { 789 return true; 790 } /** do not allow decimal character if other decimal character present */ 791 if (left.indexOf(settingsClone.aDec) > -1) { 792 return true; 793 } 794 if (right.indexOf(settingsClone.aDec) > 0) { 795 return true; 796 } 797 if (right.indexOf(settingsClone.aDec) === 0) { 798 right = right.substr(1); 799 } 800 this.setValueParts(left + settingsClone.aDec, right); 801 return true; 802 } 803 /** 804 * start rule on negative sign & prevent minus if not allowed 805 */ 806 if (cCode === '-' || cCode === '+') { 807 if (!settingsClone.aNeg) { 808 return true; 809 } /** caret is always after minus */ 810 if (left === '' && right.indexOf(settingsClone.aNeg) > -1) { 811 left = settingsClone.aNeg; 812 right = right.substring(1, right.length); 813 } /** change sign of number, remove part if should */ 814 if (left.charAt(0) === settingsClone.aNeg) { 815 left = left.substring(1, left.length); 816 } else { 817 left = (cCode === '-') ? settingsClone.aNeg + left : left; 818 } 819 this.setValueParts(left, right); 820 return true; 821 } /** digits */ 822 if (cCode >= '0' && cCode <= '9') { /** if try to insert digit before minus */ 823 if (settingsClone.aNeg && left === '' && right.indexOf(settingsClone.aNeg) > -1) { 824 left = settingsClone.aNeg; 825 right = right.substring(1, right.length); 826 } 827 if (settingsClone.vMax <= 0 && settingsClone.vMin < settingsClone.vMax && this.value.indexOf(settingsClone.aNeg) === -1 && cCode !== '0') { 828 left = settingsClone.aNeg + left; 829 } 830 this.setValueParts(left + cCode, right); 831 return true; 832 } /** prevent any other character */ 833 return true; 834 }, 835 836 /** 837 * formatting of just processed value with keeping of cursor position 838 */ 839 formatQuick: function() { 840 var settingsClone = this.settingsClone, 841 parts = this.getBeforeAfterStriped(), 842 leftLength = this.value;
843 if ((settingsClone.aSep === '' || (settingsClone.aSep !== '' && leftLength.indexOf(settingsClone.aSep) === -1)) && (settingsClone.aSign === '' || (settingsClone.aSign !== '' && leftLength.indexOf(settingsClone.aSign) === -1))) { 844 var subParts = [], 845 nSign = ''; 846 subParts = leftLength.split(settingsClone.aDec); 847 if (subParts[0].indexOf('-') > -1) { 848 nSign = '-'; 849 subParts[0] = subParts[0].replace('-', ''); 850 parts[0] = parts[0].replace('-', ''); 851 } 852 if (subParts[0].length > settingsClone.mInt && parts[0].charAt(0) === '0') { /** strip leading zero if need */ 853 parts[0] = parts[0].slice(1); 854 } 855 parts[0] = nSign + parts[0]; 856 } 857 var value = autoGroup(this.value, this.settingsClone), 858 position = value.length; 859 if (value) { 860 /** prepare regexp which searches for cursor position from unformatted left part */ 861 var left_ar = parts[0].split(''), 862 i = 0; 863 for (i; i < left_ar.length; i += 1) { /** thanks Peter Kovari */ 864 if (!left_ar[i].match('\\d')) { 865 left_ar[i] = '\\' + left_ar[i]; 866 } 867 } 868 var leftReg = new RegExp('^.*?' + left_ar.join('.*?')); 869 /** search cursor position in formatted value */ 870 var newLeft = value.match(leftReg); 871 if (newLeft) { 872 position = newLeft[0].length; 873 /** if we are just before sign which is in prefix position */ 874 if (((position === 0 && value.charAt(0) !== settingsClone.aNeg) || (position === 1 && value.charAt(0) === settingsClone.aNeg)) && settingsClone.aSign && settingsClone.pSign === 'p') { 875 /** place caret after prefix sign */ 876 position = this.settingsClone.aSign.length + (value.charAt(0) === '-' ? 1 : 0); 877 } 878 } else if (settingsClone.aSign && settingsClone.pSign === 's') { 879 /** if we could not find a place for cursor and have a sign as a suffix */ 880 /** place carret before suffix currency sign */ 881 position -= settingsClone.aSign.length; 882 } 883 } 884 this.that.value = value; 885 this.setPosition(position); 886 this.formatted = true; 887 } 888 }; 889 890 /** 891 * thanks to Anthony & Evan C 892 */ 893 894 function autoGet(obj) { 895 if (typeof obj === 'string') { 896 obj = obj.replace(/\[/g, "\\[").replace(/\]/g, "\\]"); 897 obj = '#' + obj.replace(/(:|\.)/g, '\\$1'); 898 /** obj = '#' + obj.replace(/([;&,\.\+\*\~':"\!\^#$%@\[\]\(\)=>\|])/g, '\\$1'); */ 899 /** possible modification to replace the above 2 lines */ 900 } 901 return $(obj); 902 } 903 904 /** 905 * function to attach data to the element 906 * and imitate the holder 907 */ 908 909 function getHolder($that, settings, update) { 910 var data = $that.data('autoNumeric'); 911 if (!data) { 912 data = {}; 913 $that.data('autoNumeric', data); 914 } 915 var holder = data.holder; 916 if ((holder === undefined && settings) || update) { 917 holder = new AutoNumericHolder($that.get(0), settings); 918 data.holder = holder; 919 } 920 return holder; 921 } 922 923 var methods = { 924 925 /** 926 * Method to initiate autoNumeric and attached the settings (default and options passed as a parameter 927 * $(someSelector).autoNumeric('init'); // initiate autoNumeric with defaults 928 * $(someSelector).autoNumeric('init', {option}); // initiate autoNumeric with options 929 * $(someSelector).autoNumeric(); // initiate autoNumeric with defaults 930 * $(someSelector).autoNumeric({option}); // initiate autoNumeric with options 931 * options passes as a parameter example '{aSep: '.', aDec: ',', aSign: '⬠'} 932 */ 933 init: function(options) { 934 return this.each(function() { 935 var $this = $(this), 936 settings = $this.data('autoNumeric'), 937 /** attempt to grab 'autoNumeric' settings, if they don't exist returns "undefined". */ 938 tagData = $this.data(), 939 /** attempt to grab HTML5 data, if they don't exist we'll get "undefined".*/ 940 $input = $this.is('input[type=text], input[type=hidden], input[type=tel], input
940:not([type])'); 941 if (typeof settings !== 'object') { /** If we couldn't grab settings, create them from defaults and passed options. */ 942 settings = $.extend({}, $.fn.autoNumeric.defaults, tagData, options, { 943 aNum: '0123456789', 944 hasFocus: false, 945 removeBrackets: false, 946 runOnce: false, 947 tagList: ['b', 'caption', 'cite', 'code', 'dd', 'del', 'div', 'dfn', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'ins', 'kdb', 'label', 'li', 'output', 'p', 'q', 's', 'sample', 'span', 'strong', 'td', 'th', 'u', 'var'] 948 }); /** Merge defaults, tagData and options */ 949 if (settings.aDec === settings.aSep) { 950 $.error("autoNumeric will not function properly when the decimal character aDec: '" + settings.aDec + "' and thousand separator aSep: '" + settings.aSep + "' are the same character"); 951 } 952 $this.data('autoNumeric', settings); /** Save our new settings */ 953 } else { 954 return this; 955 } 956 var holder = getHolder($this, settings); 957 if (!$input && $this.prop('tagName').toLowerCase() === 'input') { /** checks for non-supported input types */ 958 $.error('The input type "' + $this.prop('type') + '" is not supported by autoNumeric()'); 959 960 } 961 if ($.inArray($this.prop('tagName').toLowerCase(), settings.tagList) === -1 && $this.prop('tagName').toLowerCase() !== 'input') { 962 $.error("The <" + $this.prop('tagName').toLowerCase() + "> is not supported by autoNumeric()"); 963 964 } 965 if (settings.runOnce === false && settings.aForm) { /** routine to format default value on page load */ 966 if ($input) { 967 var setValue = true; 968 if ($this[0].value === '' && settings.wEmpty === 'empty') { 969 $this[0].value = ''; 970 setValue = false; 971 } 972 if ($this[0].value === '' && settings.wEmpty === 'sign') { 973 $this[0].value = settings.aSign; 974 setValue = false; 975 } 976 /** checks for page reload from back button 977 * also checks for ASP.net form post back 978 * the following HTML data attribute is REQUIRED (data-an-default="same value as the value attribute") 979 * example: <asp:TextBox runat="server" id="someID" value="1234.56" data-an-default="1234.56"> 980 */ 981 if (setValue && $this.val() !== '' && ((settings.anDefault === null && $this[0].value === $this.prop('defaultValue')) || (settings.anDefault !== null && settings.anDefault.toString() === $this.val()))) { 982 $this.autoNumeric('set', $this.val()); 983 } 984 } 985 if ($.inArray($this.prop('tagName').toLowerCase(), settings.tagList) !== -1 && $this.text() !== '') { 986 $this.autoNumeric('set', $this.text()); 987 } 988 } 989 settings.runOnce = true; 990 if ($this.is('input[type=text], input[type=hidden], input[type=tel], input:not([type])')) { /**added hidden type */ 991 $this.on('keydown.autoNumeric', function(e) { 992 holder = getHolder($this); 993 if (holder.settings.aDec === holder.settings.aSep) { 994 $.error("autoNumeric will not function properly when the decimal character aDec: '" + holder.settings.aDec + "' and thousand separator aSep: '" + holder.settings.aSep + "' are the same character"); 995 } 996 if (holder.that.readOnly) { 997 holder.processed = true; 998 return true; 999 } 1000 /** The below streamed code / comment allows the "enter" keydown to throw a change() event */ 1001 /** if (e.keyCode === 13 && holder.inVal !== $this.val()){ 1002 $this.change(); 1003 holder.inVal = $this.val(); 1004 }*/ 1005 holder.init(e); 1006 if (holder.skipAllways(e)) { 1007 holder.processed = true; 1008 return true; 1009 } 1010 if (holder.processAllways()) { 1011 holder.processed = true; 1012 holder.formatQuick(); 1013 e.preventDefault(); 1014 return false;
1015 } 1016 holder.formatted = false; 1017 return true; 1018 }); 1019 $this.on('keypress.autoNumeric', function(e) { 1020 holder = getHolder($this); 1021 var processed = holder.processed; 1022 holder.init(e); 1023 if (holder.skipAllways(e)) { 1024 return true; 1025 } 1026 if (processed) { 1027 e.preventDefault(); 1028 return false; 1029 } 1030 if (holder.processAllways() || holder.processKeypress()) { 1031 holder.formatQuick(); 1032 e.preventDefault(); 1033 return false; 1034 } 1035 holder.formatted = false; 1036 }); 1037 $this.on('keyup.autoNumeric', function(e) { 1038 holder = getHolder($this); 1039 holder.init(e); 1040 var skip = holder.skipAllways(e), 1041 tabIn = holder.kdCode; 1042 holder.kdCode = 0; 1043 delete holder.valuePartsBeforePaste; 1044 if ($this[0].value === holder.settings.aSign) { /** added to properly place the caret when only the currency is present */ 1045 if (holder.settings.pSign === 's') { 1046 setElementSelection(this, 0, 0); 1047 } else { 1048 setElementSelection(this, holder.settings.aSign.length, holder.settings.aSign.length); 1049 } 1050 } else if (tabIn === 9 && holder.settings.nBracket !== null && $this[0].value !== holder.settings.aSign) { 1051 setElementSelection(this, 0, $this.val().length); 1052 } 1053 if (skip) { 1054 return true; 1055 } 1056 if (this.value === '') { 1057 return true; 1058 } 1059 if (!holder.formatted) { 1060 holder.formatQuick(); 1061 } 1062 }); 1063 $this.on('focusin.autoNumeric', function(e) { 1064 holder = getHolder($this); 1065 var $settings = holder.settingsClone; 1066 $settings.hasFocus = true; 1067 if ($settings.nBracket !== null) { 1068 var checkVal = $this.val(); 1069 $this.val(negativeBracket(checkVal, $settings)); 1070 } 1071 holder.inVal = $this.val(); 1072 var onEmpty = checkEmpty(holder.inVal, $settings, true); 1073 if (onEmpty !== null && onEmpty !== '') { 1074 $this.val(onEmpty); 1075 } 1076 }); 1077 $this.on('focusout.autoNumeric', function(e) { 1078 holder = getHolder($this); 1079 var $settings = holder.settingsClone, 1080 value = $this.val(), 1081 origValue = value; 1082 $settings.hasFocus = false; 1083 var strip_zero = ''; /** added to control leading zero */ 1084 if ($settings.lZero === 'allow') { /** added to control leading zero */ 1085 $settings.allowLeading = false; 1086 strip_zero = 'leading'; 1087 } 1088 if (value !== '') { 1089 value = autoStrip(value, $settings, strip_zero); 1090 if (checkEmpty(value, $settings) === null && autoCheck(value, $settings, $this[0])) { 1091 value = fixNumber(value, $settings.aDec, $settings.aNeg); 1092 value = autoRound(value, $settings); 1093 value = presentNumber(value, $settings.aDec, $settings.aNeg); 1094 } else { 1095 value = ''; 1096 } 1097 } 1098 var groupedValue = checkEmpty(value, $settings, false); 1099 if (groupedValue === null) { 1100 groupedValue = autoGroup(value, $settings); 1101 } 1102 if (groupedValue !== holder.inVal || groupedValue !== origValue) { 1103 $this.val(groupedValue); 1104 $this.change(); 1105 delete holder.inVal; 1106 } 1107 }); 1108 } 1109 }); 1110 }, 1111 1112 /** 1113 * method to remove settings and stop autoNumeric() - does not remove the formatting 1114 * $(someSelector).autoNumeric('destroy'); // destroy autoNumeric 1115 * no parameters accepted 1116 */ 1117 destroy: function() { 1118 return $(this).each(function() { 1119 var $this = $(this); 1120 $this.removeData('autoNumeric'); 1121 $this.off('autoNumeric'); 1122 }); 1123 }, 1124 1125 /** 1126 * method to update settings - can be call as many times 1127 * $(someSelector).autoNumeric('update', {options}); // updates the settings 1128 * options passes as a parameter example '{aSep: '.', aDec: ',', aSign: '⬠'} 1129 */ 1130 update: function(options) { 1131 return $(this).each(function() { 1132 var $this = autoGet($(this)), 1133 settings = $this.data('autoNumeric'); 1134 if (typeof settings !== 'object') { 1135 $.error("You must initialize autoNumeric('init', {options}) prior to calling the 'update' method"); 1136 } 1137 var strip = $this.autoNumeric('get'); 1138 settings = $.extend(settings, options); 1139 getHolder($this, settings, true); 1140 if (settings.aDec === settings.aSep) { 1141 $.error("autoNumeric will not function properly when the decimal character aDec: '" + settings.aDec + "' and thousand separator aSep: '" + settings.aSep + "' are the same character"); 1142 } 1143 $this.data('autoNumeric', settings); 1144 if ($this.val() !== '' || $this.text() !== '') { 1145 return $this.autoNumeric('set', strip); 1146 } 1147 return; 1148 }); 1149 }, 1150 1151 /** 1152 * method to format value sent as a parameter "" 1153 * $(someSelector).autoNumeric('set', 'value'}); // formats the value being passed 1154 * value passed as a string - can be a integer '1234' or double '1234.56789' 1155 * must contain only numbers and one decimal (period) character 1156 */ 1157 set: function(valueIn) { 1158 if (valueIn === null || isNaN(valueIn)) { 1159 return; 1160 } 1161 return $(this).each(function() { 1162 var $this = autoGet($(this)), 1163 settings = $this.data('autoNumeric'), 1164 value = valueIn.toString(), 1165 testValue = valueIn.toString(), 1166 $input = $this.is('input[type=text], input[type=hidden], input[type=tel], input
1166:not([type])'); 1167 if (typeof settings !== 'object') { 1168 $.error("You must initialize autoNumeric('init', {options}) prior to calling the 'set' method"); 1169 } 1170 /** allows locale decimal separator to be a comma */ 1171 if ((testValue === $this.attr('value') || testValue === $this.text()) && settings.runOnce === false) { 1172 value = value.replace(',', '.'); 1173 } 1174 if (!$.isNumeric(+value)) { 1175 $.error("The value (" + value + ") being 'set' is not numeric and has caused a error to be thrown"); 1176 } 1177 value = checkValue(value, settings); 1178 settings.setEvent = true; 1179 value.toString(); 1180 if (value !== '') { 1181 value = autoRound(value, settings); 1182 } 1183 value = presentNumber(value, settings.aDec, settings.aNeg); 1184 if (!autoCheck(value, settings)) { 1185 value = autoRound('', settings); 1186 } 1187 value = autoGroup(value, settings); 1188 if ($input) { 1189 return $this.val(value); 1190 } 1191 if ($.inArray($this.prop('tagName').toLowerCase(), settings.tagList) !== -1) { 1192 return $this.text(value); 1193 } 1194 return false; 1195 }); 1196 }, 1197 1198 /** 1199 * method to get the unformatted that accepts up to one parameter 1200 * $(someSelector).autoNumeric('get'); no parameters accepted 1201 * values returned as ISO numeric string "1234.56" where the decimal character is a period 1202 * only the first element in the selector is returned 1203 */ 1204 get: function() { 1205 var $this = autoGet($(this)), 1206 settings = $this.data('autoNumeric'); 1207 if (typeof settings !== 'object') { 1208 $.error("You must initialize autoNumeric('init', {options}) prior to calling the 'get' method"); 1209 } 1210 var getValue = ''; 1211 /** determine the element type then use .eq(0) selector to grab the value of the first element in selector */ 1212 if ($this.is('input[type=text], input[type=hidden], input[type=tel], input:not([type])')) { /**added hidden type */ 1213 getValue = $this.eq(0).val(); 1214 } else if ($.inArray($this.prop('tagName').toLowerCase(), settings.tagList) !== -1) { 1215 getValue = $this.eq(0).text(); 1216 } else { 1217 $.error("The <" + $this.prop('tagName').toLowerCase() + "> is not supported by autoNumeric()"); 1218 } 1219 if ((getValue === '' && settings.wEmpty === 'empty') || (getValue === settings.aSign && (settings.wEmpty === 'sign' || settings.wEmpty === 'empty'))) { 1220 return ''; 1221 } 1222 if (getValue !== '' && settings.nBracket !== null) { 1223 settings.removeBrackets = true; 1224 getValue = negativeBracket(getValue, settings); 1225 settings.removeBrackets = false; 1226 } 1227 if (settings.runOnce || settings.aForm === false) { 1228 getValue = autoStrip(getValue, settings); 1229 } 1230 getValue = fixNumber(getValue, settings.aDec, settings.aNeg); 1231 if (+getValue === 0 && settings.lZero !== 'keep') { 1232 getValue = '0'; 1233 } 1234 if (settings.lZero === 'keep') { 1235 return getValue; 1236 } 1237 getValue = checkValue(getValue, settings); 1238 return getValue; /** returned Numeric String */ 1239 }, 1240 1241 /** 1242 * The 'getString' method used jQuerys .serialize() method that creates a text string in standard URL-encoded notation 1243 * it then loops through the string and un-formats the inputs with autoNumeric 1244 * $(someSelector).autoNumeric('getString'); no parameter accepted 1245 * values returned as ISO numeric string "1234.56" where the decimal character is a period 1246 */ 1247 getString: function() { 1248 var isAutoNumeric = false, 1249 $this = autoGet($(this)), 1250 formFields = $this.serialize(), 1251 formParts = formFields.split('&'), 1252 formIndex = $('form').index($this), 1253 allFormElements = $('form:eq(' + formIndex + ')'), 1254 aiIndex = [], 1255 /* all input index */ 1256 scIndex = [], 1257 /* successful control index */ 1258 rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, 1259 /* from jQuery serialize method */ 1260 rsubmittable = /^(?:input|select|textarea|keygen)/i, 1261 /* from jQuery serialize method */ 1262 rcheckableType = /^(?:checkbox|radio)$/i, 1263 rnonAutoNumericTypes = /^(?:button|checkbox|color|date|datetime|datetime-local|email|file|image|month|number|password|radio|range|reset|search|submit|time|url|week)/i, 1264 count = 0; 1265 /*jslint unparam: true*/ 1266 /* index of successful elements */ 1267 $.each(allFormElements[0], function(i, field) { 1268 if (field.name !== '' && rsubmittable.test(field.localName) && !rsubmitterTypes.test(field.type) && !field.disabled && (field.checked || !rcheckableType.test(field.type))) { 1269 scIndex.push(count); 1270 count = count + 1; 1271 } else { 1272 scIndex.push(-1); 1273 } 1274 }); 1275 /* index of all inputs tags except checkbox */ 1276 count = 0; 1277 $.each(allFormElements[0], function(i, field) { 1278 if (field.localName === 'input' && (field.type === '' || field.type === 'text' || field.type === 'hidden' || field.type === 'tel')) { 1279 aiIndex.push(count); 1280 count = count + 1; 1281 } else { 1282 aiIndex.push(-1); 1283 if (field.localName === 'input' && rnonAutoNumericTypes.test(field.type)) { 1284 count = count + 1; 1285 } 1286 } 1287 }); 1288 $.each(formParts, function(i, miniParts) { 1289 miniParts = formParts[i].split('='); 1290 var scElement = $.inArray(i, scIndex); 1291 if (scElement > -1 && aiIndex[scElement] > -1) { 1292 var testInput = $('form:eq(' + formIndex + ') input:eq(' + aiIndex[scElement] + ')'), 1293 settings = testInput.data('autoNumeric'); 1294 if (typeof settings === 'object') { 1295 if (miniParts[1] !== null) { 1296 miniParts[1] = $('form:eq(' + formIndex + ') input:eq(' + aiIndex[scElement] + ')').autoNumeric('get').toString(); 1297 formParts[i] = miniParts.join('='); 1298 isAutoNumeric = true; 1299 } 1300 } 1301 } 1302 }); 1303 /*jslint unparam: false*/ 1304 if (!isAutoNumeric) { 1305 $.error("You must initialize autoNumeric('init', {options}) prior to calling the 'getString' method"); 1306 } 1307 return formParts.join('&'); 1308 }, 1309 1310 /** 1311 * The 'getString' method used jQuerys .serializeArray() method that creates array or objects that can be encoded as a JSON string 1312 * it then loops through the string and un-formats the inputs with autoNumeric 1313 * $(someSelector).autoNumeric('getArray'); no parameter accepted 1314 * values returned as ISO numeric string "1234.56" where the decimal character is a period 1315 */ 1316 getArray: function() { 1317 var isAutoNumeric = false, 1318 $this = autoGet($(this)), 1319 formFields = $this.serializeArray(), 1320 formIndex = $('form').index($this), 1321 allFormElements = $('form:eq(' + formIndex + ')'), 1322 aiIndex = [], 1323 /* all input index */ 1324 scIndex = [], 1325 /* successful control index */ 1326 rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, 1327 /* from jQuery serialize method */ 1328 rsubmittable = /^(?:input|select|textarea|keygen)/i, 1329 /* from jQuery serialize method */ 1330 rcheckableType = /^(?:checkbox|radio)$/i, 1331 rnonAutoNumericTypes = /^(?:button|checkbox|color|date|datetime|datetime-local|email|file|image|month|number|password|radio|range|reset|search|submit|time|url|week)/i, 1332 count = 0; 1333 /*jslint unparam: true*/ 1334 /* index of successful elements */ 1335 $.each(allFormElements[0], function(i, field) { 1336 if (field.name !== '' && rsubmittable.test(field.localName) && !rsubmitterTypes.test(field.type) && !field.disabled && (field.checked || !rcheckableType.test(field.type))) { 1337 scIndex.push(count); 1338 count = count + 1; 1339 } else { 1340 scIndex.push(-1); 1341 } 1342 }); 1343 /* index of all inputs tags */ 1344 count = 0; 1345 $.each(allFormElements[0], function(i, field) { 1346 if (field.localName === 'input' && (field.type === '' || field.type === 'text' || field.type === 'hidden' || field.type === 'tel')) { 1347 aiIndex.push(count); 1348 count = count + 1; 1349 } else { 1350 aiIndex.push(-1); 1351 if (field.localName === 'input' && rnonAutoNumericTypes.test(field.type)) { 1352 count = count + 1; 1353 } 1354 } 1355 }); 1356 $.each(formFields, function(i, field) { 1357 var scElement = $.inArray(i, scIndex); 1358 if (scElement > -1 && aiIndex[scElement] > -1) { 1359 var testInput = $('form:eq(' + formIndex + ') input:eq(' + aiIndex[scElement] + ')'), 1360 settings = testInput.data('autoNumeric'); 1361 if (typeof settings === 'object') { 1362 field.value = $('form:eq(' + formIndex + ') input:eq(' + aiIndex[scElement] + ')').autoNumeric('get').toString(); 1363 isAutoNumeric = true; 1364 } 1365 } 1366 }); 1367 /*jslint unparam: false*/ 1368 if (!isAutoNumeric) { 1369 $.error("None of the successful form inputs are initialized by autoNumeric."); 1370 } 1371 return formFields; 1372 }, 1373 1374 /** 1375 * The 'getSteetings returns the object with autoNumeric settings for those who need to look under the hood 1376 * $(someSelector).autoNumeric('getSettings'); // no parameters accepted 1377 * $(someSelector).autoNumeric('getSettings').aDec; // return the aDec setting as a string - ant valid setting can be used 1378 */ 1379 getSettings: function() { 1380 var $this = autoGet($(this)); 1381 return $this.eq(0).data('autoNumeric'); 1382 } 1383 }; 1384 1385 /** 1386 * autoNumeric function 1387 */ 1388 $.fn.autoNumeric = function(method) { 1389 if (methods[method]) { 1390 return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); 1391 } 1392 if (typeof method === 'object' || !method) { 1393 return methods.init.apply(this, arguments); 1394 } 1395 $.error('Method "' + method + '" is not supported by autoNumeric()'); 1396 }; 1397 1398 /** 1399 * Defaults are public - these can be overridden by the following: 1400 * HTML5 data attributes 1401 * Options passed by the 'init' or 'update' methods 1402 * Use jQuery's $.extend method - great way to pass ASP.NET current culture settings 1403 */ 1404 $.fn.autoNumeric.defaults = { 1405 /** allowed thousand separator characters 1406 * comma = ',' 1407 * period "full stop" = '.' 1408 * apostrophe is escaped = '\'' 1409 * space = ' ' 1410 * none = '' 1411 * NOTE: do not use numeric characters 1412 */ 1413 aSep: ',', 1414 /** digital grouping for the thousand separator used in Format 1415 * dGroup: '2', results in 99,99,99,999 common in India for values less than 1 billion and greater than -1 billion 1416 * dGroup: '3', results in 999,999,999 default 1417 * dGroup: '4', results in 9999,9999,9999 used in some Asian countries 1418 */ 1419 dGroup: '3', 1420 /** allowed decimal separator characters 1421 * period "full stop" = '.' 1422 * comma = ',' 1423 */ 1424 aDec: '.', 1425 /** allow to declare alternative decimal separator which is automatically replaced by aDec
1426 * developed for countries the use a comma ',' as the decimal character 1427 * and have keyboards\numeric pads that have a period 'full stop' as the decimal characters (Spain is an example) 1428 */ 1429 altDec: null, 1430 /** allowed currency symbol 1431 * Must be in quotes aSign: '$', a space is allowed aSign: '$ ' 1432 */ 1433 aSign: '', 1434 /** placement of currency sign 1435 * for prefix pSign: 'p', 1436 * for suffix pSign: 's', 1437 */ 1438 pSign: 'p', 1439 /** maximum possible value 1440 * value must be enclosed in quotes and use the period for the decimal point 1441 * value must be larger than vMin 1442 */ 1443 vMax: '9999999999999.99', 1444 /** minimum possible value 1445 * value must be enclosed in quotes and use the period for the decimal point 1446 * value must be smaller than vMax 1447 */ 1448 vMin: '-9999999999999.99', 1449 /** max number of decimal places = used to override decimal places set by the vMin & vMax values 1450 * value must be enclosed in quotes example mDec: '3', 1451 * This can also set the value via a call back function mDec: 'css:# 1452 */ 1453 mDec: null, 1454 /** method used for rounding 1455 * mRound: 'S', Round-Half-Up Symmetric (default) 1456 * mRound: 'A', Round-Half-Up Asymmetric 1457 * mRound: 's', Round-Half-Down Symmetric (lower case s) 1458 * mRound: 'a', Round-Half-Down Asymmetric (lower case a) 1459 * mRound: 'B', Round-Half-Even "Bankers Rounding" 1460 * mRound: 'U', Round Up "Round-Away-From-Zero" 1461 * mRound: 'D', Round Down "Round-Toward-Zero" - same as truncate 1462 * mRound: 'C', Round to Ceiling "Toward Positive Infinity" 1463 * mRound: 'F', Round to Floor "Toward Negative Infinity" 1464 */ 1465 mRound: 'S', 1466 /** controls decimal padding 1467 * aPad: true - always Pad decimals with zeros 1468 * aPad: false - does not pad with zeros. 1469 * aPad: `some number` - pad decimals with zero to number different from mDec 1470 * thanks to Jonas Johansson for the suggestion 1471 */ 1472 aPad: true, 1473 /** places brackets on negative value -$ 999.99 to (999.99) 1474 * visible only when the field does NOT have focus the left and right symbols should be enclosed in quotes and seperated by a comma 1475 * nBracket: null, nBracket: '(,)', nBracket: '[,]', nBracket: '<,>' or nBracket: '{,}' 1476 */ 1477 nBracket: null, 1478 /** Displayed on empty string 1479 * wEmpty: 'empty', - input can be blank 1480 * wEmpty: 'zero', - displays zero 1481 * wEmpty: 'sign', - displays the currency sign 1482 */ 1483 wEmpty: 'empty', 1484 /** controls leading zero behavior 1485 * lZero: 'allow', - allows leading zeros to be entered. Zeros will be truncated when entering additional digits. On focusout zeros will be deleted. 1486 * lZero: 'deny', - allows only one leading zero on values less than one 1487 * lZero: 'keep', - allows leading zeros to be entered. on fousout zeros will be retained. 1488 */ 1489 lZero: 'allow', 1490 /** determine if the select all keyboard command will select 1491 * the complete input text or only the input numeric value 1492 * if the currency symbol is between the numeric value and the negative sign only the numeric value will sellected 1493 */ 1494 sNumber: true, 1495 /** determine if the default value will be formatted on page ready. 1496 * true = automatically formats the default value on page ready 1497 * false = will not format the default value 1498 */ 1499 aForm: true, 1500 /** helper option for ASP.NET postback 1501 * should be the value of the unformatted default value 1502 * examples: 1503 * no default value='' {anDefault: ''} 1504 * value=1234.56 {anDefault: '1234.56'} 1505 */ 1506 anDefault: null 1507 }; 1508}));
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.