1/** 2* autoNumeric.js 3* @author: Bob Knothe 4* @author: Sokolov Yura aka funny_falcon 5* @version: 1.9.8 - 2013-05-20 GMT 3:00 PM 6* 7* Created by Robert J. Knothe on 2010-10-25. Please report any bugs to https://github.com/BobKnothe/autoNumeric 8* Created by Sokolov Yura on 2010-11-07 9* 10* Copyright (c) 2011 Robert J. Knothe http://www.decorplanit.com/plugin/ 11* Copyright (c) 2011 Sokolov Yura 12* 13* The MIT License (http://www.opensource.org/licenses/mit-license.php) 14* 15* Permission is hereby granted, free of charge, to any person 16* obtaining a copy of this software and associated documentation 17* files (the "Software"), to deal in the Software without 18* restriction, including without limitation the rights to use, 19* copy, modify, merge, publish, distribute, sublicense, and/or sell 20* copies of the Software, and to permit persons to whom the 21* Software is furnished to do so, subject to the following 22* conditions: 23* 24* The above copyright notice and this permission notice shall be 25* included in all copies or substantial portions of the Software. 26* 27* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 28* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 29* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 30* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 31* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 32* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 33* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 34* OTHER DEALINGS IN THE SOFTWARE. 35*/ 36(function($) { 37 "use strict"; 38 /**jslint browser: true*/ 39 /**global jQuery*/ 40 /** 41 * Cross browser routine for getting selected range/cursor position 42 */ 43 function getElementSelection(that) { 44 var position = {}; 45 if (that.selectionStart === undefined) { 46 that.focus(); 47 var select = document.selection.createRange(); 48 position.length = select.text.length; 49 select.moveStart('character', -that.value.length); 50 position.end = select.text.length; 51 position.start = position.end - position.length; 52 } else { 53 position.start = that.selectionStart; 54 position.end = that.selectionEnd; 55 position.length = position.end - position.start; 56 } 57 return position; 58 } 59 /** 60 * Cross browser routine for setting selected range/cursor position 61 */ 62 function setElementSelection(that, start, end) { 63 if (that.selectionStart === undefined) { 64 that.focus(); 65 var r = that.createTextRange(); 66 r.collapse(true); 67 r.moveEnd('character', end); 68 r.moveStart('character', start); 69 r.select(); 70 } else { 71 that.selectionStart = start; 72 that.selectionEnd = end; 73 } 74 } 75 /** 76 * run callbacks in parameters if any 77 * any parameter could be a callback: 78 * - a function, which invoked with jQuery element, parameters and this parameter name and returns parameter value 79 * - a name of function, attached to $(selector).autoNumeric.functionName(){} - which was called previously 80 */ 81 function runCallbacks($this, settings) { 82 /** 83 * loops through the settings object (option array) to find the following 84 * k = option name example k=aNum 85 * val = option value example val=0123456789 86 */ 87 $.each(settings, function(k, val) { 88 if (typeof val === 'function') { 89 settings[k] = val($this, settings, k); 90 } else if (typeof $this.autoNumeric[val] === 'function') { 91 /** 92 * calls the attached function from the html5 data example: data-a-sign="functionName" 93 */ 94 settings[k] = $this.autoNumeric[val]($this, settings, k); 95 } 96 }); 97 } 98 99 function convertKeyToNumber(settings, key) { 100 if (typeof (settings[key]) === 'string') { 101 settings[key] *= 1; 102 } 103 } 104 /** 105 * Preparing user defined options for further usage 106 * merge them with defaults appropriatly 107 */ 108 function autoCode($this, settings) { 109 runCallbacks($this, settings); 110 settings.oEvent = null; 111 settings.tagList = ['DD', 'DT', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'LABEL', 'P', 'SPAN', 'TD', 'TH']; 112 var vmax = settings.vMax.toString().split('.'), 113 vmin = (!settings.vMin && settings.vMin !== 0) ? [] : settings.vMin.toString().split('.'); 114 convertKeyToNumber(settings, 'vMax'); 115 convertKeyToNumber(settings, 'vMin'); 116 convertKeyToNumber(settings, 'mDec'); /** set mDec if not defained by user */ 117 settings.allowLeading = true; 118 settings.aNeg = settings.vMin < 0 ? '-' : ''; 119 vmax[0] = vmax[0].replace('-', ''); 120 vmin[0] = vmin[0].replace('-', ''); 121 settings.mInt = Math.max(vmax[0].length, vmin[0].length, 1); 122 if (settings.mDec === null) { 123 var vmaxLength = 0, 124 vminLength = 0; 125 if (vmax[1]) { 126 vmaxLength = vmax[1].length; 127 } 128 if (vmin[1]) { 129 vminLength = vmin[1].length; 130 } 131 settings.mDec = Math.max(vmaxLength, vminLength); 132 } /** set alternative decimal separator key */ 133 if (settings.altDec === null && settings.mDec > 0) { 134 if (settings.aDec === '.' && settings.aSep !== ',') { 135 settings.altDec = ','; 136 } else if (settings.aDec === ',' && settings.aSep !== '.') { 137 settings.altDec = '.'; 138 } 139 } 140 /** cache regexps for autoStrip */ 141 var aNegReg = settings.aNeg ? '([-\\' + settings.aNeg + ']?)' : '(-?)'; 142 settings.aNegRegAutoStrip = aNegReg; 143 settings.skipFirstAutoStrip = new RegExp(aNegReg + '[^-' + (settings.aNeg ? '\\' + settings.aNeg : '') + '\\' + settings.aDec + '\\d]' + '.*?(\\d|\\' + settings.aDec + '\\d)'); 144 settings.skipLastAutoStrip = new RegExp('(\\d\\' + settings.aDec + '?)[^\\' + settings.aDec + '\\d]\\D*$'); 145 var allowed = '-' + settings.aNum + '\\' + settings.aDec; 146 settings.allowedAutoStrip = new RegExp('[^' + allowed + ']', 'gi'); 147 settings.numRegAutoStrip = new RegExp(aNegReg + '(?:\\' + settings.aDec + '?(\\d+\\' + settings.aDec + '\\d+)|(\\d*(?:\\' + settings.aDec + '\\d*)?))'); 148 return settings; 149 } 150 /** 151 * strip all unwanted characters and leave only a number alert 152 */ 153 function autoStrip(s, settings, strip_zero) { 154 if (settings.aSign) { /** remove currency sign */ 155 while (s.indexOf(settings.aSign) > -1) { 156 s = s.replace(settings.aSign, ''); 157 } 158 } 159 s = s.replace(settings.skipFirstAutoStrip, '$1$2'); /** first replace anything before digits */ 160 s = s.replace(settings.skipLastAutoStrip, '$1'); /** then replace anything after digits */ 161 s = s.replace(settings.allowedAutoStrip, ''); /** then remove any uninterested characters */ 162 if (settings.altDec) { 163 s = s.replace(settings.altDec, settings.aDec); 164 } /** get only number string */ 165 var m = s.match(settings.numRegAutoStrip); 166 s = m ? [m[1], m[2], m[3]].join('') : ''; 167 if ((settings.lZero === 'allow' || settings.lZero === 'keep') && str
167ip_zero !== 'strip') { 168 var parts = [], 169 nSign = ''; 170 parts = s.split(settings.aDec); 171 if (parts[0].indexOf('-') !== -1) { 172 nSign = '-'; 173 parts[0] = parts[0].replace('-', ''); 174 } 175 if (parts[0].length > settings.mInt && parts[0].charAt(0) === '0') { /** strip leading zero if need */ 176 parts[0] = parts[0].slice(1); 177 } 178 s = nSign + parts.join(settings.aDec); 179 } 180 if ((strip_zero && settings.lZero === 'deny') || (strip_zero && settings.lZero === 'allow' && settings.allowLeading === false)) { 181 var strip_reg = '^' + settings.aNegRegAutoStrip + '0*(\\d' + (strip_zero === 'leading' ? ')' : '|$)'); 182 strip_reg = new RegExp(strip_reg); 183 s = s.replace(strip_reg, '$1$2'); 184 } 185 return s; 186 } 187 /** 188 * places or removes brackets on negative values 189 */ 190 function negativeBracket(s, nBracket, oEvent) { /** oEvent = settings.oEvent */ 191 nBracket = nBracket.split(','); 192 if (oEvent === 'set' || oEvent === 'focusout') { 193 s = s.replace('-', ''); 194 s = nBracket[0] + s + nBracket[1]; 195 } else if ((oEvent === 'get' || oEvent === 'focusin' || oEvent === 'pageLoad') && s.charAt(0) === nBracket[0]) { 196 s = s.replace(nBracket[0], '-'); 197 s = s.replace(nBracket[1], ''); 198 } 199 return s; 200 } 201 /** 202 * truncate decimal part of a number 203 */ 204 function truncateDecimal(s, aDec, mDec) { 205 if (aDec && mDec) { 206 var parts = s.split(aDec); 207 /** truncate decimal part to satisfying length 208 * cause we would round it anyway */ 209 if (parts[1] && parts[1].length > mDec) { 210 if (mDec > 0) { 211 parts[1] = parts[1].substring(0, mDec); 212 s = parts.join(aDec); 213 } else { 214 s = parts[0]; 215 } 216 } 217 } 218 return s; 219 } 220 /** 221 * prepare number string to be converted to real number 222 */ 223 function fixNumber(s, aDec, aNeg) { 224 if (aDec && aDec !== '.') { 225 s = s.replace(aDec, '.'); 226 } 227 if (aNeg && aNeg !== '-') { 228 s = s.replace(aNeg, '-'); 229 } 230 if (!s.match(/\d/)) { 231 s += '0'; 232 } 233 return s; 234 } 235 /** 236 * function to handle numbers less than 0 that are stored in Exponential notaion ex: .0000001 stored as 1e-7 237 */ 238 function checkValue(value) { 239 var decimal = value.indexOf('.'); 240 if (decimal !== -1) { 241 if (decimal === 1 && value.charAt(0) === '0') { 242 value = +value; 243 if (value < 0.000001 && value > 0) { 244 value = (value + 1).toString(); 245 value = value.substring(1); 246 } 247 if (value < 0 && value > -1) { 248 value = (value - 1).toString(); 249 value = '-' + value.substring(2); 250 } 251 value = value.toString(); 252 } else { 253 var parts = value.split('.'); 254 if (parts[1] !== undefined) { 255 if (+parts[1] === 0) { 256 value = parts[0]; 257 } else { 258 parts[1] = parts[1].replace(/0*$/, ''); 259 value = parts.join('.'); 260 } 261 } 262 } 263 } 264 return value.replace(/^0*(\d)/, '$1'); 265 } 266 /** 267 * prepare real number to be converted to our format 268 */ 269 function presentNumber(s, aDec, aNeg) { 270 if (aNeg && aNeg !== '-') { 271 s = s.replace('-', aNeg); 272 } 273 if (aDec && aDec !== '.') { 274 s = s.replace('.', aDec); 275 } 276 return s; 277 } 278 /** 279 * checking that number satisfy format conditions 280 * and lays between settings.vMin and settings.vMax 281 * and the string length does not exceed the digits in settings.vMin and settings.vMax 282 */ 283 function autoCheck(s, settings) { 284 s = autoStrip(s, settings); 285 s = truncateDecimal(s, settings.aDec, settings.mDec); 286 s = fixNumber(s, settings.aDec, settings.aNeg); 287 var value = +s; 288 if (settings.oEvent === 'set' && (value < settings.vMin || value > settings.vMax)) { 289 $.error("The value (" + value + ") from the 'set' method falls outside of the vMin / vMax range"); 290 } 291 return value >= settings.vMin && value <= settings.vMax; 292 } 293 /** 294 * private function to check for empty value 295 */ 296 function checkEmpty(iv, settings, signOnEmpty) { 297 if (iv === '' || iv === settings.aNeg) { 298 if (settings.wEmpty === 'zero') { 299 return iv + '0'; 300 } 301 if (settings.wEmpty === 'sign' || signOnEmpty) { 302 return iv + settings.aSign; 303 } 304 return iv; 305 } 306 return null; 307 } 308 /** 309 * private function that formats our number 310 */ 311 function autoGroup(iv, settings) { 312 iv = autoStrip(iv, settings); 313 var testNeg = iv, 314 empty = checkEmpty(iv, settings, true); 315 if (empty !== null) { 316 return empty; 317 } 318 var digitalGroup = ''; 319 if (settings.dGroup === 2) { 320 digitalGroup = /(\d)((\d)(\d{2}?)+)$/; 321 } else if (settings.dGroup === 4) { 322 digitalGroup = /(\d)((\d{4}?)+)$/; 323 } else { 324 digitalGroup = /(\d)((\d{3}?)+)$/; 325 } /** splits the string at the decimal string */ 326 var ivSplit = iv.split(settings.aDec); 327 if (settings.altDec && ivSplit.length === 1) { 328 ivSplit = iv.split(settings.altDec); 329 } /** assigns the whole number to the a varibale (s) */ 330 var s = ivSplit[0]; 331 if (settings.aSep) { 332 while (digitalGroup.test(s)) { /** re-inserts the thousand sepparator via a regualer expression */ 333 s = s.replace(digitalGroup, '$1' + settings.aSep + '$2'); 334 } 335 } 336 if (settings.mDec !== 0 && ivSplit.length > 1) { 337 if (ivSplit[1].length > settings.mDec) { 338 ivSplit[1] = ivSplit[1].substring(0, settings.mDec); 339 } /** joins the whole number with the deciaml value */ 340 iv = s + settings.aDec + ivSplit[1]; 341 } else { /** if whole numers only */ 342 iv = s; 343 } 344 if (settings.aSign) { 345 var has_aNeg = iv.indexOf(settings.aNeg) !== -1; 346 iv = iv.replace(settings.aNeg, ''); 347 iv = settings.pSign === 'p' ? settings.aSign + iv : iv + settings.aSign; 348 if (has_aNeg) { 349 iv = settings.aNeg + iv; 350 } 351 } 352 if (settings.oEvent === 'set' && testNeg < 0 && settings.nBracket !== null) { /** removes the negative sign and places brackets */ 353 iv = negativeBracket(iv, settings.nBracket, settings.oEvent); 354 } 355 return iv; 356 } 357 /** 358 * round number after setting by pasting or $().autoNumericSet()
359 * private function for round the number 360 * please note this handled as text - Javascript math function can return inaccurate values 361 * also this offers multiple rounding metods that are not easily accomplished in javascript 362 */ 363 function autoRound(iv, settings) { /** value to string */ 364 iv = (iv === '') ? '0' : iv.toString(); 365 convertKeyToNumber(settings, 'mDec'); /** set mDec to number needed when mDec set by 'update method */ 366 var ivRounded = '', 367 i = 0, 368 nSign = '', 369 rDec = (typeof (settings.aPad) === 'boolean' || settings.aPad === null) ? (settings.aPad ? settings.mDec : 0) : +settings.aPad; 370 var truncateZeros = function(ivRounded) { /** truncate not needed zeros */ 371 var regex = rDec === 0 ? (/(\.[1-9]*)0*$/) : rDec === 1 ? (/(\.\d[1-9]*)0*$/) : new RegExp('(\\.\\d{' + rDec + '}[1-9]*)0*$'); 372 ivRounded = ivRounded.replace(regex, '$1'); /** If there are no decimal places, we don't need a decimal point at the end */ 373 if (rDec === 0) { 374 ivRounded = ivRounded.replace(/\.$/, ''); 375 } 376 return ivRounded; 377 }; 378 if (iv.charAt(0) === '-') { /** Checks if the iv (input Value)is a negative value */ 379 nSign = '-'; /** removes the negative sign will be added back later if required */ 380 iv = iv.replace('-', ''); 381 } /** prepend a zero if first character is not a digit (then it is likely to be a dot)*/ 382 if (!iv.match(/^\d/)) { 383 iv = '0' + iv; 384 } /** determines if the value is zero - if zero no negative sign */ 385 if (nSign === '-' && +iv === 0) { 386 nSign = ''; 387 } 388 if ((+iv > 0 && settings.lZero !== 'keep') || (iv.length > 0 && settings.lZero === 'allow')) { /** trims leading zero's if needed */ 389 iv = iv.replace(/^0*(\d)/, '$1'); 390 } 391 var dPos = iv.lastIndexOf('.'); /** virtual decimal position */ 392 var vdPos = dPos === -1 ? iv.length - 1 : dPos; /** checks decimal places to determine if rounding is required */ 393 var cDec = (iv.length - 1) - vdPos; /** check if no rounding is required */ 394 if (cDec <= settings.mDec) { 395 ivRounded = iv; /** check if we need to pad with zeros */ 396 if (cDec < rDec) { 397 if (dPos === -1) { 398 ivRounded += '.'; 399 } 400 while (cDec < rDec) { 401 var zeros = '000000'.substring(0, rDec - cDec); 402 ivRounded += zeros; 403 cDec += zeros.length; 404 } 405 } else if (cDec > rDec) { 406 ivRounded = truncateZeros(ivRounded); 407 } else if (cDec === 0 && rDec === 0) { 408 ivRounded = ivRounded.replace(/\.$/, ''); 409 } 410 return nSign + ivRounded; 411 } /** rounded length of the string after rounding */ 412 var rLength = dPos + settings.mDec; /** test round */ 413 var tRound = +iv.charAt(rLength + 1); 414 var ivArray = iv.substring(0, rLength + 1).split(''); 415 var odd = (iv.charAt(rLength) === '.') ? (iv.charAt(rLength - 1) % 2)
415: (iv.charAt(rLength) % 2); 416 if ((tRound > 4 && settings.mRound === 'S') || (tRound > 4 && settings.mRound === 'A' && nSign === '') || (tRound > 5 && settings.mRound === 'A' && nSign === '-') || (tRound > 5 && settings.mRound === 's') || (tRound > 5 && settings.mRound === 'a' && nSign === '') || (tRound > 4 && settings.mRound === 'a' && nSign === '-') || (tRound > 5 && settings.mRound === 'B') || (tRound === 5 && settings.mRound === 'B' && odd === 1) || (tRound > 0 && settings.mRound === 'C' && nSign === '') || (tRound > 0 && settings.mRound === 'F' && nSign === '-') || (tRound > 0 && settings.mRound === 'U')) { 417 /** Round up the last digit if required, and continue until no more 9's are found */ 418 for (i = (ivArray.length - 1); i >= 0; i -= 1) { 419 if (ivArray[i] !== '.') { 420 ivArray[i] = +ivArray[i] + 1; 421 if (ivArray[i] < 10) { 422 break; 423 } else if (i > 0) { 424 ivArray[i] = '0'; 425 } 426 } 427 } 428 } /** Reconstruct the string, converting any 10's to 0's */ 429 ivArray = ivArray.slice(0, rLength + 1); 430 ivRounded = truncateZeros(ivArray.join('')); /** return rounded value */ 431 return nSign + ivRounded; 432 } 433 /** 434 * Holder object for field properties 435 */ 436 function AutoNumericHolder(that, settings) { 437 this.settings = settings; 438 this.that = that; 439 this.$that = $(that); 440 this.formatted = false; 441 this.settingsClone = autoCode(this.$that, this.settings); 442 this.value = that.value; 443 } 444 AutoNumericHolder.prototype = { 445 init: function(e) { 446 this.value = this.that.value; 447 this.settingsClone = autoCode(this.$that, this.settings); 448 this.ctrlKey = e.ctrlKey; 449 this.cmdKey = e.metaKey; 450 this.shiftKey = e.shiftKey; 451 this.selection = getElementSelection(this.that); /** keypress event overwrites meaningfull value of e.keyCode */ 452 if (e.type === 'keydown' || e.type === 'keyup') { 453 this.kdCode = e.keyCode; 454 } 455 this.which = e.which; 456 this.processed = false; 457 this.formatted = false; 458 }, 459 setSelection: function(start, end, setReal) { 460 start = Math.max(start, 0); 461 end = Math.min(end, this.that.value.length); 462 this.selection = { 463 start: start, 464 end: end, 465 length: end - start 466 }; 467 if (setReal === undefined || setReal) { 468 setElementSelection(this.that, start, end); 469 } 470 }, 471 setPosition: function(pos, setReal) { 472 this.setSelection(pos, pos, setReal); 473 }, 474 getBeforeAfter: function() { 475 var value = this.value; 476 var left = value.substring(0, this.selection.start); 477 var right = value.substring(this.selection.end, value.length); 478 return [left, right]; 479 }, 480 getBeforeAfterStriped: function() { 481 var parts = this.getBeforeAfter(); 482 parts[0] = autoStrip(parts[0], this.settingsClone); 483 parts[1] = autoStrip(parts[1], this.settingsClone); 484 return parts; 485 }, 486 /** 487 * strip parts from excess characters and leading zeroes 488 */ 489 normalizeParts: function(left, right) { 490 var settingsClone = this.settingsClone; 491 right = autoStrip(right, settingsClone); /** if right is not empty and first character is not aDec, */ 492 /** we could strip all zeros, otherwise only leading */ 493 var strip = right.match(/^\d/) ? true : 'leading'; 494 left = autoStrip(left, settingsClone, strip); /** prevents multiple leading zeros from being entered */ 495 if ((left === '' || left === settingsClone.aNeg) && settingsClone.lZero === 'deny') { 496 if (right > '') { 497 right = right.replace(/^0*(\d)/, '$1'); 498 } 499 } 500 var new_value = left + right; /** insert zero if has leading dot */ 501 if (settingsClone.aDec) { 502 var m = new_value.match(new RegExp('^' + settingsClone.aNegRegAutoStrip + '\\' + settingsClone.aDec)); 503 if (m) { 504 left = left.replace(m[1], m[1] + '0'); 505 new_value = left + right; 506 } 507 } /** insert zero if number is empty and io.wEmpty == 'zero' */ 508 if (settingsClone.wEmpty === 'zero' && (new_value === settingsClone.aNeg || new_value === '')) { 509 left += '0'; 510 } 511 return [left, right]; 512 }, 513 /** 514 * set part of number to value keeping position of cursor 515 */ 516 setValueParts: function(left, right) { 517 var settingsClone = this.settingsClone; 518 var parts = this.normalizeParts(left, right); 519 var new_value = parts.join(''); 520 var position = parts[0].length; 521 if (autoCheck(new_value, settingsClone)) { 522 new_value = truncateDecimal(new_value, settingsClone.aDec, settingsClone.mDec); 523 if (position > new_value.length) { 524 position = new_value.length; 525 } 526 this.value = new_value; 527 this.setPosition(position, false); 528 return true; 529 } 530 return false;
531 }, 532 /** 533 * helper function for expandSelectionOnSign 534 * returns sign position of a formatted value 535 */ 536 signPosition: function() { 537 var settingsClone = this.settingsClone, 538 aSign = settingsClone.aSign, 539 that = this.that; 540 if (aSign) { 541 var aSignLen = aSign.length; 542 if (settingsClone.pSign === 'p') { 543 var hasNeg = settingsClone.aNeg && that.value && that.value.charAt(0) === settingsClone.aNeg; 544 return hasNeg ? [1, aSignLen + 1] : [0, aSignLen]; 545 } 546 var valueLen = that.value.length; 547 return [valueLen - aSignLen, valueLen]; 548 } 549 return [1000, -1]; 550 }, 551 /** 552 * expands selection to cover whole sign 553 * prevents partial deletion/copying/overwritting of a sign 554 */ 555 expandSelectionOnSign: function(setReal) { 556 var sign_position = this.signPosition(); 557 var selection = this.selection; 558 if (selection.start < sign_position[1] && selection.end > sign_position[0]) { /** if selection catches something except sign and catches only space from sign */ 559 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 */ 560 if (selection.start < sign_position[0]) { 561 this.setSelection(selection.start, sign_position[0], setReal); 562 } else { 563 this.setSelection(sign_position[1], selection.end, setReal); 564 } 565 } else { /** else select with whole sign */ 566 this.setSelection(Math.min(selection.start, sign_position[0]), Math.max(selection.end, sign_position[1]), setReal); 567 } 568 } 569 }, 570 /** 571 * try to strip pasted value to digits 572 */ 573 checkPaste: function() { 574 if (this.valuePartsBeforePaste !== undefined) { 575 var parts = this.getBeforeAfter(); 576 var oldParts = this.valuePartsBeforePaste; 577 delete this.valuePartsBeforePaste; /** try to strip pasted value first */ 578 parts[0] = parts[0].substr(0, oldParts[0].length) + autoStrip(parts[0].substr(oldParts[0].length), this.settingsClone); 579 if (!this.setValueParts(parts[0], parts[1])) { 580 this.value = oldParts.join(''); 581 this.setPosition(oldParts[0].length, false); 582 } 583 } 584 }, 585 /** 586 * process pasting, cursor moving and skipping of not interesting keys 587 * if returns true, futher processing is not performed 588 */ 589 skipAllways: function(e) { 590 var kdCode = this.kdCode, which = this.which, ctrlKey = this.ctrlKey, cmdKey = this.cmdKey, shiftKey = this.shiftKey; /** catch the ctrl up on ctrl-v */ 591 if (((ctrlKey || cmdKey) && e.type === 'keyup' && this.valuePartsBeforePaste !== undefined) || (shiftKey && kdCode === 45)) { 592 this.checkPaste(); 593 return false; 594 } 595 /** codes are taken from http://www.cambiaresearch.com/c4/702b8cd1-e5b0-42e6-83ac-25f0306e3e25/Javascript-Char-Codes-Key-Codes.aspx 596 * skip Fx keys, windows keys, other special keys 597 */ 598 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) { 599 return true; 600 } 601 if ((ctrlKey || cmdKey) && kdCode === 65) { /** if select all (a=65)*/ 602 return true; 603 } 604 if ((ctrlKey || cmdKey) && (kdCode === 67 || kdCode === 86 || kdCode === 88)) { /** if copy (c=67) paste (v=86) or cut (x=88) */ 605 if (e.type === 'keydown') { 606 this.expandSelectionOnSign(); 607 } 608 if (kdCode === 86 || kdCode === 45) { /** try to prevent wrong paste */ 609 if (e.type === 'keydown' || e.type === 'keypress') { 610 if (this.valuePartsBeforePaste === undefined) { 611 this.valuePartsBeforePaste = this.getBeforeAfter(); 612 } 613 } else { 614 this.checkPaste(); 615 } 616 } 617 return e.type === 'keydown' || e.type === 'keypress' || kdCode === 67; 618 } 619 if (ctrlKey || cmdKey) { 620 return true; 621 } 622 if (kdCode === 37 || kdCode === 39) { /** jump over thousand separator */ 623 var aSep = this.settingsClone.aSep, 624 start = this.selection.start, 625 value = this.that.value; 626 if (e.type === 'keydown' && aSep && !this.shiftKey) { 627 if (kdCode === 37 && value.charAt(start - 2) === aSep) { 628 this.setPosition(start - 1); 629 } else if (kdCode === 39 && value.charAt(start + 1) === aSep) { 630 this.setPosition(start + 1); 631 } 632 } 633 return true; 634 } 635 if (kdCode >= 34 && kdCode <= 40) { 636 return true; 637 } 638 return false;
639 }, 640 /** 641 * process deletion of characters 642 * returns true if processing performed 643 */ 644 processAllways: function() { 645 var parts; /** process backspace or delete */ 646 if (this.kdCode === 8 || this.kdCode === 46) { 647 if (!this.selection.length) { 648 parts = this.getBeforeAfterStriped(); 649 if (this.kdCode === 8) { 650 parts[0] = parts[0].substring(0, parts[0].length - 1); 651 } else { 652 parts[1] = parts[1].substring(1, parts[1].length); 653 } 654 this.setValueParts(parts[0], parts[1]); 655 } else { 656 this.expandSelectionOnSign(false); 657 parts = this.getBeforeAfterStriped(); 658 this.setValueParts(parts[0], parts[1]); 659 } 660 return true; 661 } 662 return false; 663 }, 664 /** 665 * process insertion of characters 666 * returns true if processing performed 667 */ 668 processKeypress: function() { 669 var settingsClone = this.settingsClone; 670 var cCode = String.fromCharCode(this.which); 671 var parts = this.getBeforeAfterStriped(); 672 var left = parts[0], right = parts[1]; /** start rules when the decimal charactor key is pressed */ 673 /** always use numeric pad dot to insert decimal separator */ 674 if (cCode === settingsClone.aDec || (settingsClone.altDec && cCode === settingsClone.altDec) || ((cCode === '.' || cCode === ',') && this.kdCode === 110)) { /** do not allow decimal character if no decimal part allowed */ 675 if (!settingsClone.mDec || !settingsClone.aDec) { 676 return true; 677 } /** do not allow decimal character before aNeg character */ 678 if (settingsClone.aNeg && right.indexOf(settingsClone.aNeg) > -1) { 679 return true; 680 } /** do not allow decimal character if other decimal character present */ 681 if (left.indexOf(settingsClone.aDec) > -1) { 682 return true; 683 } 684 if (right.indexOf(settingsClone.aDec) > 0) { 685 return true; 686 } 687 if (right.indexOf(settingsClone.aDec) === 0) { 688 right = right.substr(1); 689 } 690 this.setValueParts(left + settingsClone.aDec, right); 691 return true; 692 } /** start rule on negative sign */ 693 694 if (cCode === '-' || cCode === '+') { /** prevent minus if not allowed */ 695 if (!settingsClone.aNeg) { 696 return true; 697 } /** carret is always after minus */ 698 if (left === '' && right.indexOf(settingsClone.aNeg) > -1) { 699 left = settingsClone.aNeg; 700 right = right.substring(1, right.length); 701 } /** change sign of number, remove part if should */ 702 if (left.charAt(0) === settingsClone.aNeg) { 703 left = left.substring(1, left.length); 704 } else { 705 left = (cCode === '-') ? settingsClone.aNeg + left : left; 706 } 707 this.setValueParts(left, right); 708 return true; 709 } /** digits */ 710 if (cCode >= '0' && cCode <= '9') { /** if try to insert digit before minus */ 711 if (settingsClone.aNeg && left === '' && right.indexOf(settingsClone.aNeg) > -1) { 712 left = settingsClone.aNeg; 713 right = right.substring(1, right.length); 714 } 715 if (settingsClone.vMax <= 0 && settingsClone.vMin < settingsClone.vMax && this.value.indexOf(settingsClone.aNeg) === -1 && cCode !== '0') { 716 left = settingsClone.aNeg + left; 717 } 718 this.setValueParts(left + cCode, right); 719 return true; 720 } /** prevent any other character */ 721 return true; 722 }, 723 /** 724 * formatting of just processed value with keeping of cursor position 725 */ 726 formatQuick: function() { 727 var settingsClone = this.settingsClone; 728 var parts = this.getBeforeAfterStriped(); 729 var leftLength = this.value;
730 if ((settingsClone.aSep === '' || (settingsClone.aSep !== '' && leftLength.indexOf(settingsClone.aSep) === -1)) && (settingsClone.aSign === '' || (settingsClone.aSign !== '' && leftLength.indexOf(settingsClone.aSign) === -1))) { 731 var subParts = [], 732 nSign = ''; 733 subParts = leftLength.split(settingsClone.aDec); 734 if (subParts[0].indexOf('-') > -1) { 735 nSign = '-'; 736 subParts[0] = subParts[0].replace('-', ''); 737 parts[0] = parts[0].replace('-', ''); 738 } 739 if (subParts[0].length > settingsClone.mInt && parts[0].charAt(0) === '0') { /** strip leading zero if need */ 740 parts[0] = parts[0].slice(1); 741 } 742 parts[0] = nSign + parts[0]; 743 } 744 var value = autoGroup(this.value, this.settingsClone); 745 var position = value.length; 746 if (value) { 747 /** prepare regexp which searches for cursor position from unformatted left part */ 748 var left_ar = parts[0].split(''); 749 var i = 0; 750 for (i; i < left_ar.length; i += 1) { /** thanks Peter Kovari */ 751 if (!left_ar[i].match('\\d')) { 752 left_ar[i] = '\\' + left_ar[i]; 753 } 754 } 755 var leftReg = new RegExp('^.*?' + left_ar.join('.*?')); 756 /** search cursor position in formatted value */ 757 var newLeft = value.match(leftReg); 758 if (newLeft) { 759 position = newLeft[0].length; 760 /** if we are just before sign which is in prefix position */ 761 if (((position === 0 && value.charAt(0) !== settingsClone.aNeg) || (position === 1 && value.charAt(0) === settingsClone.aNeg)) && settingsClone.aSign && settingsClone.pSign === 'p') { 762 /** place carret after prefix sign */ 763 position = this.settingsClone.aSign.length + (value.charAt(0) === '-' ? 1 : 0); 764 } 765 } else if (settingsClone.aSign && settingsClone.pSign === 's') { 766 /** if we could not find a place for cursor and have a sign as a suffix */ 767 /** place carret before suffix currency sign */ 768 position -= settingsClone.aSign.length; 769 } 770 } 771 this.that.value = value; 772 this.setPosition(position); 773 this.formatted = true; 774 } 775 }; 776 /** thanks to Anthony & Evan C */ 777 function autoGet(obj) { 778 if (typeof obj === 'string') { 779 obj = obj.replace(/\[/g, "\\[").replace(/\]/g, "\\]"); 780 obj = '#' + obj.replace(/(:|\.)/g, '\\$1'); 781 /** obj = '#' + obj.replace(/([;&,\.\+\*\~':"\!\^#$%@\[\]\(\)=>\|])/g, '\\$1'); */ 782 /** possible modification to replace the above 2 lines */ 783 } 784 return $(obj); 785 } 786 787 function getHolder($that, settings, update) { 788 var data = $that.data('autoNumeric'); 789 if (!data) { 790 data = {}; 791 $that.data('autoNumeric', data); 792 } 793 var holder = data.holder; 794 if ((holder === undefined && settings) || update) { 795 holder = new AutoNumericHolder($that.get(0), settings); 796 data.holder = holder; 797 } 798 return holder; 799 } 800 var methods = { 801 init: function(options) { 802 return this.each(function() { 803 var $this = $(this); 804 var settings = $this.data('autoNumeric'); /** attempt to grab 'autoNumeric' settings, if they don't exist returns "undefined". */ 805 var tagData = $this.data(); /** attempt to grab HTML5 data, if they don't exist we'll get "undefined".*/ 806 if (typeof settings !== 'object') { /** If we could't grab settings, create them from defaults and passed options. */ 807 var defaults = { 808 /** allowed numeric values 809 * please do not modify 810 */ 811 aNum: '0123456789', 812 /** allowed thousand separator characters 813 * comma = ',' 814 * period "full stop" = '.' 815 * apostrophe is escaped = '\'' 816 * space = ' ' 817 * none = '' 818 * NOTE: do not use numeric characters 819 */ 820 aSep: ',', 821 /** digital grouping for the thousand separator used in Format 822 * dGroup: '2', results in 99,99,99,999 common in India for values less than 1 billion and greater than -1 billion 823 * dGroup: '3', results in 999,999,999 default 824 * dGroup: '4', results in 9999,9999,9999 used in some Asian countries 825 */ 826 dGroup: '3', 827 /** allowed decimal separator characters 828 * period "full stop" = '.' 829 * comma = ',' 830 */ 831 aDec: '.', 832 /** allow to declare alternative decimal separator which is automatically replaced by aDec
833 * developed for countries the use a comma ',' as the decimal character 834 * and have keyboards\numeric pads that have a period 'full stop' as the decimal characters (Spain is an example) 835 */ 836 altDec: null, 837 /** allowed currency symbol 838 * Must be in quotes aSign: '$', a space is allowed aSign: '$ ' 839 */ 840 aSign: '', 841 /** placement of currency sign 842 * for prefix pSign: 'p', 843 * for suffix pSign: 's', 844 */ 845 pSign: 'p', 846 /** maximum possible value 847 * value must be enclosed in quotes and use the period for the decimal point 848 * value must be larger than vMin 849 */ 850 vMax: '999999999.99', 851 /** minimum possible value 852 * value must be enclosed in quotes and use the period for the decimal point 853 * value must be smaller than vMax 854 */ 855 vMin: '0.00', 856 /** max number of decimal places = used to overide deciaml places set by the vMin & vMax values 857 * value must be enclosed in quotes example mDec: '3', 858 * This can also set the value via a call back function mDec: 'css:# 859 */ 860 mDec: null, 861 /** method used for rounding 862 * mRound: 'S', Round-Half-Up Symmetric (default) 863 * mRound: 'A', Round-Half-Up Asymmetric 864 * mRound: 's', Round-Half-Down Symmetric (lower case s) 865 * mRound: 'a', Round-Half-Down Asymmetric (lower case a) 866 * mRound: 'B', Round-Half-Even "Bankers Rounding" 867 * mRound: 'U', Round Up "Round-Away-From-Zero" 868 * mRound: 'D', Round Down "Round-Toward-Zero" - same as trancate 869 * mRound: 'C', Round to Ceiling "Toward Positive Infinity" 870 * mRound: 'F', Round to Floor "Toward Negative Infinity" 871 */ 872 mRound: 'S', 873 /** controls decimal padding 874 * aPad: true - always Pad decimals with zeros 875 * aPad: false - does not pad with zeros. 876 * aPad: `some number` - pad decimals with zero to number different from mDec 877 * thanks to Jonas Johansson for the suggestion 878 */ 879 aPad: true, 880 /** places brackets on negative value -$ 999.99 to (999.99) 881 * visible only when the field does NOT have focus the left and right symbols should be enclosed in quotes and seperated by a comma 882 * nBracket: null, nBracket: '(,)', nBracket: '[,]', nBracket: '<,>' or nBracket: '{,}' 883 */ 884 nBracket: null, 885 /** Displayed on empty string 886 * wEmpty: 'empty', - input can be blank 887 * wEmpty: 'zero', - displays zero 888 * wEmpty: 'sign', - displays the currency sign 889 */ 890 wEmpty: 'empty', 891 /** controls leading zero behavior 892 * lZero: 'allow', - allows leading zeros to be entered. Zeros will be truncated when entering additional digits. On focusout zeros will be deleted. 893 * lZero: 'deny', - allows only one leading zero on values less than one 894 * lZero: 'keep', - allows leading zeros to be entered. on fousout zeros will be retained. 895 */ 896 lZero: 'allow', 897 /** determine if the default value will be formatted on page ready. 898 * true = atomatically formats the default value on page ready 899 * false = will not format the default value 900 */ 901 aForm: true, 902 /** future use */ 903 onSomeEvent: function() {} 904 }; 905 settings = $.extend({}, defaults, tagData, options); /** Merge defaults, tagData and options */ 906 if (settings.aDec === settings.aSep) { 907 $.error("autoNumeric will not function properly when the decimal character aDec: '" + settings.aDec + "' and thousand seperater aSep: '" + settings.aSep + "' are the same character"); 908 return this; 909 } 910 if ($.inArray($this.prop('tagName'), settings.tagList) !== -1) { 911 $.error("The <" + $this.prop('tagName') + "> is not supported by autoNumeric()"); 912 return this; 913 } 914 $this.data('autoNumeric', settings); /** Save our new settings */ 915 } else { 916 return this; 917 } 918 settings.lastSetValue = ''; 919 var holder = getHolder($this, settings); 920 if (settings.runOnce === undefined && settings.aForm) {/** routine to format default value on page load */ 921 if ($this.is('input[type=text], input[type=hidden], input:not([type])')) { 922 var setValue = true; 923 if ($this[0].value === '' && settings.wEmpty === 'empty') { 924 $this[0].value = ''; 925 setValue = false;
926 } 927 if ($this[0].value === '' && settings.wEmpty === 'sign') { 928 $this[0].value = settings.aSign; 929 setValue = false; 930 } 931 if (setValue) { 932 $this.autoNumeric('set', $this.val()); 933 } 934 } 935 if ($.inArray($this.prop('tagName'), settings.tagList) !== -1) { 936 $this.autoNumeric('set', $this.text()); 937 } 938 } 939 settings.runOnce = true; 940 if ($this.is('input[type=text], input[type=hidden], input:not([type])')) { /**added hidden type */ 941 $this.on('keydown.autoNumeric', function(e) { 942 holder = getHolder($this); 943 if (holder.settings.aDec === holder.settings.aSep) { 944 $.error("autoNumeric will not function properly when the decimal character aDec: '" + holder.settings.aDec + "' and thousand seperater aSep: '" + holder.settings.aSep + "' are the same character"); 945 return this; 946 } 947 if (holder.that.readOnly) { 948 holder.processed = true; 949 return true; 950 } 951 /** The below streamed code / comment allows the "enter" keydown to throw a change() event */ 952 /** if (e.keyCode === 13 && holder.inVal !== $this.val()){ 953 $this.change(); 954 holder.inVal = $this.val(); 955 }*/ 956 holder.init(e); 957 holder.settings.oEvent = 'keydown'; 958 if (holder.skipAllways(e)) { 959 holder.processed = true; 960 return true; 961 } 962 if (holder.processAllways()) { 963 holder.processed = true; 964 holder.formatQuick(); 965 e.preventDefault(); 966 return false; 967 } 968 holder.formatted = false; 969 return true; 970 }); 971 $this.on('keypress.autoNumeric', function(e) { 972 var holder = getHolder($this), processed = holder.processed; 973 holder.init(e); 974 holder.settings.oEvent = 'keypress'; 975 if (holder.skipAllways(e)) { 976 return true; 977 } 978 if (processed) { 979 e.preventDefault(); 980 return false; 981 } 982 if (holder.processAllways() || holder.processKeypress()) { 983 holder.formatQuick(); 984 e.preventDefault(); 985 return false; 986 } 987 holder.formatted = false; 988 989 }); 990 $this.on('keyup.autoNumeric', function(e) { 991 var holder = getHolder($this); 992 holder.init(e); 993 holder.settings.oEvent = 'keyup'; 994 var skip = holder.skipAllways(e); 995 holder.kdCode = 0; 996 delete holder.valuePartsBeforePaste; 997 if (skip) { 998 return true; 999 } 1000 if (this.value === '') { 1001 return true; 1002 } 1003 if (!holder.formatted) { 1004 holder.formatQuick(); 1005 } 1006 }); 1007 $this.on('focusin.autoNumeric', function() { 1008 var holder = getHolder($this); 1009 holder.settingsClone.oEvent = 'focusin'; 1010 if (holder.settingsClone.nBracket !== null) { 1011 var checkVal = $this.val(); 1012 $this.val(negativeBracket(checkVal, holder.settingsClone.nBracket, holder.settingsClone.oEvent)); 1013 } 1014 holder.inVal = $this.val(); 1015 var onempty = checkEmpty(holder.inVal, holder.settingsClone, true); 1016 if (onempty !== null) { 1017 $this.val(onempty); 1018 } 1019 }); 1020 $this.on('focusout.autoNumeric', function() { 1021 var holder = getHolder($this), 1022 settingsClone = holder.settingsClone, 1023 value = $this.val(), 1024 origValue = value; 1025 holder.settingsClone.oEvent = 'focusout'; 1026 var strip_zero = ''; /** added to control leading zero */ 1027 if (settingsClone.lZero === 'allow') { /** added to control leading zero */ 1028 settingsClone.allowLeading = false;
1029 strip_zero = 'leading'; 1030 } 1031 if (value !== '') { 1032 value = autoStrip(value, settingsClone, strip_zero); 1033 if (checkEmpty(value, settingsClone) === null && autoCheck(value, settingsClone, $this[0])) { 1034 value = fixNumber(value, settingsClone.aDec, settingsClone.aNeg); 1035 value = autoRound(value, settingsClone); 1036 value = presentNumber(value, settingsClone.aDec, settingsClone.aNeg); 1037 } else { 1038 value = ''; 1039 } 1040 } 1041 var groupedValue = checkEmpty(value, settingsClone, false); 1042 if (groupedValue === null) { 1043 groupedValue = autoGroup(value, settingsClone); 1044 } 1045 if (groupedValue !== origValue) { 1046 $this.val(groupedValue); 1047 } 1048 if (groupedValue !== holder.inVal) { 1049 $this.change(); 1050 delete holder.inVal; 1051 } 1052 if (settingsClone.nBracket !== null && $this.autoNumeric('get') < 0) { 1053 holder.settingsClone.oEvent = 'focusout'; 1054 $this.val(negativeBracket($this.val(), settingsClone.nBracket, settingsClone.oEvent)); 1055 } 1056 }); 1057 } 1058 }); 1059 }, 1060 /** method to remove settings and stop autoNumeric() */ 1061 destroy: function() { 1062 return $(this).each(function() { 1063 var $this = $(this); 1064 $this.off('.autoNumeric'); 1065 $this.removeData('autoNumeric'); 1066 }); 1067 }, 1068 /** method to update settings - can call as many times */ 1069 update: function(options) { 1070 return $(this).each(function() { 1071 var $this = autoGet($(this)), 1072 settings = $this.data('autoNumeric'); 1073 if (typeof settings !== 'object') { 1074 $.error("You must initialize autoNumeric('init', {options}) prior to calling the 'update' method"); 1075 return this; 1076 } 1077 var strip = $this.autoNumeric('get'); 1078 settings = $.extend(settings, options); 1079 getHolder($this, settings, true); 1080 if (settings.aDec === settings.aSep) { 1081 $.error("autoNumeric will not function properly when the decimal character aDec: '" + settings.aDec + "' and thousand seperater aSep: '" + settings.aSep + "' are the same character"); 1082 return this; 1083 } 1084 $this.data('autoNumeric', settings); 1085 if ($this.val() !== '' || $this.text() !== '') { 1086 return $this.autoNumeric('set', strip); 1087 } 1088 return; 1089 }); 1090 }, 1091 /** returns a formated strings for "input:text" fields Uses jQuery's .val() method*/ 1092 set: function(valueIn) { 1093 return $(this).each(function() { 1094 var $this = autoGet($(this)), settings = $this.data('autoNumeric'), value = valueIn.toString(); 1095 if (typeof settings !== 'object') { 1096 $.error("You must initialize autoNumeric('init', {options}) prior to calling the 'set' method"); 1097 return this; 1098 } 1099 /** returns a empty string if the value being 'set' contains non-numeric characters and or more than decimal point (full stop) and will not be formatted */ 1100 if (!$.isNumeric(+value)) { 1101 return ''; 1102 } 1103 value = checkValue(value); 1104 settings.oEvent = 'set'; 1105 settings.lastSetValue = value; /** saves the unrounded value from the set method - $('selector').data('autoNumeric').lastSetValue; - helpful when you need to change the rounding accuracy*/ 1106 value.toString(); 1107 if (value !== '') { 1108 value = autoRound(value, settings); 1109 } 1110 value = presentNumber(value, settings.aDec, settings.aNeg); 1111 if (!autoCheck(value, settings)) { 1112 value = autoRound('', settings); 1113 } 1114 value = autoGroup(value, settings); 1115 if ($this.is('input[type=text], input[type=hidden], input:not([type])')) { /**added hidden type */ 1116 return $this.val(value); 1117 } 1118 if ($.inArray($this.prop('tagName'), settings.tagList) !== -1) { 1119 return $this.text(value); 1120 } 1121 $.error("The <" + $this.prop('tagName') + "> is not supported by autoNumeric()"); 1122 return false;
1123 }); 1124 }, 1125 /** method to get the unformated value from a specific input field, returns a numeric value */ 1126 get: function() { 1127 var $this = autoGet($(this)), 1128 settings = $this.data('autoNumeric'); 1129 if (typeof settings !== 'object') { 1130 $.error("You must initialize autoNumeric('init', {options}) prior to calling the 'get' method"); 1131 return this; 1132 } 1133 settings.oEvent = 'get'; 1134 var getValue = ''; 1135 /** determine the element type then use .eq(0) selector to grab the value of the first element in selector */ 1136 if ($this.is('input[type=text], input[type=hidden], input:not([type])')) { /**added hidden type */ 1137 getValue = $this.eq(0).val(); 1138 } else if ($.inArray($this.prop('tagName'), settings.tagList) !== -1) { 1139 getValue = $this.eq(0).text(); 1140 } else { 1141 $.error("The <" + $this.prop('tagName') + "> is not supported by autoNumeric()"); 1142 return false; 1143 } 1144 if ((getValue === '' && settings.wEmpty === 'empty') || (getValue === settings.aSign && settings.wEmpty === 'sign')) { 1145 return ''; 1146 } 1147 if (settings.nBracket !== null && getValue !== '') { 1148 getValue = negativeBracket(getValue, settings.nBracket, settings.oEvent); 1149 } 1150 if (settings.runOnce || settings.aForm === false) { 1151 getValue = autoStrip(getValue, settings); 1152 } 1153 getValue = fixNumber(getValue, settings.aDec, settings.aNeg); 1154 if (+getValue === 0 && settings.lZero !== 'keep') { 1155 getValue = '0'; 1156 } 1157 if (settings.lZero === 'keep') { 1158 return getValue; 1159 } 1160 getValue = checkValue(getValue); 1161 return getValue; /** returned Numeric String */ 1162 }, 1163 /** method to get the unformated value from multiple fields */ 1164 getString: function() { 1165 var isAutoNumeric = false, 1166 $this = autoGet($(this)), 1167 str = $this.serialize(), 1168 parts = str.split('&'), 1169 i = 0; 1170 for (i; i < parts.length; i += 1) { 1171 var miniParts = parts[i].split('='); 1172 var settings = $('*[name="' + decodeURIComponent(miniParts[0]) + '"]').data('autoNumeric'); 1173 if (typeof settings === 'object') { 1174 if (miniParts[1] !== null && $('*[name="' + decodeURIComponent(miniParts[0]) + '"]').data('autoNumeric') !== undefined) { 1175 miniParts[1] = $('input[name="' + decodeURIComponent(miniParts[0]) + '"]').autoNumeric('get'); 1176 parts[i] = miniParts.join('='); 1177 isAutoNumeric = true; 1178 } 1179 } 1180 } 1181 if (isAutoNumeric === true) { 1182 return parts.join('&'); 1183 } 1184 $.error("You must initialize autoNumeric('init', {options}) prior to calling the 'getString' method"); 1185 return this; 1186 }, 1187 /** method to get the unformated value from multiple fields */ 1188 getArray: function() { 1189 var isAutoNumeric = false, 1190 $this = autoGet($(this)), 1191 formFields = $this.serializeArray(); 1192 $.each(formFields, function(i, field) { 1193 var settings = $('*[name="' + decodeURIComponent(field.name) + '"]').data('autoNumeric'); 1194 if (typeof settings === 'object') { 1195 if (field.value !== '' && $('*[name="' + decodeURIComponent(field.name) + '"]').data('autoNumeric') !== undefined) { 1196 field.value = $('input[name="' + decodeURIComponent(field.name) + '"]').autoNumeric('get').toString(); 1197 } 1198 isAutoNumeric = true; 1199 } 1200 }); 1201 if (isAutoNumeric === true) { 1202 return formFields; 1203 } 1204 $.error("You must initialize autoNumeric('init', {options}) prior to calling the 'getArray' method"); 1205 return this; 1206 }, 1207 /** returns the settings object for those who need to look under the hood */ 1208 getSettings: function() { 1209 var $this = autoGet($(this)); 1210 return $this.eq(0).data('autoNumeric'); 1211 } 1212 }; 1213 $.fn.autoNumeric = function(method) { 1214 if (methods[method]) { 1215 return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); 1216 } 1217 if (typeof method === 'object' || !method) { 1218 return methods.init.apply(this, arguments); 1219 } 1220 $.error('Method "' + method + '" is not supported by autoNumeric()'); 1221 }; 1222}(jQuery));
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.