{"version":3,"sources":["webpack:///webpack/universalModuleDefinition","webpack:///autoNumeric.min.js","webpack:///webpack/bootstrap 28aa359b7d6224364eb0","webpack:///./src/autoNumeric.js","webpack:///external {\"root\":\"jQuery\",\"commonjs\":\"jquery\",\"commonjs2\":\"jquery\",\"amd\":\"jquery\"}"],"names":["root","factory","exports","module","require","define","amd","this","__WEBPACK_EXTERNAL_MODULE_1__","modules","__webpack_require__","moduleId","installedModules","id","loaded","call","m","c","p","__WEBPACK_AMD_DEFINE_FACTORY__","__WEBPACK_AMD_DEFINE_ARRAY__","__WEBPACK_AMD_DEFINE_RESULT__","_classCallCheck","instance","Constructor","TypeError","Object","defineProperty","value","_createClass","defineProperties","target","props","i","length","descriptor","enumerable","configurable","writable","key","protoProps","staticProps","prototype","_slicedToArray","sliceIterator","arr","_arr","_n","_d","_e","undefined","_s","_i","Symbol","iterator","next","done","push","err","Array","isArray","_typeof","obj","constructor","autoFormat","autoUnFormat","getDefaultConfig","getLanguages","validate","areSettingsValid","allowedTagList","defaultSettings","digitGroupSeparator","noSeparatorOnFocus","digitalGroupSpacing","decimalCharacter","decimalCharacterAlternative","currencySymbol","currencySymbolPlacement","negativePositiveSignPlacement","showPositiveSign","suffixText","overrideMinMaxLimits","maximumValue","minimumValue","decimalPlacesOverride","decimalPlacesShownOnFocus","scaleDivisor","scaleDecimalPlaces","scaleSymbol","saveValueToSessionStorage","onInvalidPaste","roundingMethod","allowDecimalPadding","negativeBracketsTypeOnBlur","emptyInputBehavior","leadingZero","formatOnPageLoad","selectNumberOnly","defaultValueOverride","unformatOnSubmit","outputFormat","showWarnings","failOnUnknownOption","keyCode","Backspace","Tab","Enter","Shift","Ctrl","Alt","PauseBreak","CapsLock","Esc","Space","PageUp","PageDown","End","Home","LeftArrow","UpArrow","RightArrow","DownArrow","Insert","Delete","num0","num1","num2","num3","num4","num5","num6","num7","num8","num9","a","b","d","e","f","g","h","j","k","l","n","o","q","r","s","t","u","v","w","x","y","z","Windows","RightClick","numpad0","numpad1","numpad2","numpad3","numpad4","numpad5","numpad6","numpad7","numpad8","numpad9","MultiplyNumpad","PlusNumpad","MinusNumpad","DotNumpad","SlashNumpad","F1","F2","F3","F4","F5","F6","F7","F8","F9","F10","F11","F12","NumLock","ScrollLock","MyComputer","MyCalculator","Semicolon","Equal","Comma","Hyphen","Dot","Slash","Backquote","LeftBracket","Backslash","RightBracket","Quote","Command","AndroidDefault","keyName","Unidentified","AltGr","Fn","FnLock","Hyper","Meta","Super","SymbolLock","Clear","Copy","CrSel","Cut","EraseEof","ExSel","Paste","Redo","Undo","Accept","Again","Attn","Cancel","ContextMenu","Execute","Find","Finish","Help","Pause","Play","Props","Select","ZoomIn","ZoomOut","BrightnessDown","BrightnessUp","Eject","LogOff","Power","PowerOff","PrintScreen","Hibernate","Standby","WakeUp","Compose","Dead","Print","Minus","Plus","NumpadDot","NumpadDotAlt","NumpadMultiply","NumpadPlus","NumpadMinus","NumpadSlash","NumpadDotObsoleteBrowsers","NumpadMultiplyObsoleteBrowsers","NumpadPlusObsoleteBrowsers","NumpadMinusObsoleteBrowsers","NumpadSlashObsoleteBrowsers","defaultMinimumValue","defaultMaximumValue","defaultRoundingMethod","defaultLeadingZero","defaultSelectNumberOnly","languageOption","French","NorthAmerican","British","Swiss","Japanese","Spanish","Chinese","apply","$","isNull","isUndefined","isUndefinedOrNullOrEmpty","isString","str","String","isBoolean","isTrueOrFalseString","lowercaseValue","toLowerCase","isObject","reference","isEmptyObj","prop","hasOwnProperty","isNumber","isNaN","parseFloat","isFinite","isInt","parseInt","preparePastedText","text","holder","stripAllNonNumberCharacters","settingsClone","replace","contains","needle","indexOf","isInArray","array","toString","Error","decimalPlaces","_str$split","split","_str$split2","decimalPart","keyCodeNumber","event","which","character","fromCharCode","result","checkIfInRange","parsedMinValue","parsedMaxValue","parsedValue","parseStr","testMinMax","isNegative","numericString","checkEverywhere","arguments","isNegativeStrict","charAt","isZeroOrHasNoValue","test","setRawNegativeSign","replaceCharAt","string","index","newCharacter","substr","clampToRangeLimits","settings","Math","max","min","countNumberCharactersOnTheCaretLeftSide","formattedNumberString","caretPosition","numberDotOrNegativeSign","RegExp","numberDotAndNegativeSignCount","findCaretPositionInFormattedNumber","rawNumberString","caretPositionInRawValue","formattedNumberStringSize","rawNumberStringSize","formattedNumberStringIndex","rawNumberStringIndex","countCharInText","charCounter","convertCharacterCountToIndexPosition","characterCount","getElementSelection","that","position","selectionStart","focus","select","document","selection","createRange","moveStart","end","start","selectionEnd","setElementSelection","range","createTextRange","collapse","moveEnd","throwError","message","warning","showWarning","console","warn","runCallbacksFoundInTheSettingsObject","$this","each","val","autoNumeric","maximumVMinAndVMaxDecimalLength","leftOrAll","skipFirstAutoStrip","trailingNegative","skipLastAutoStrip","allowedAutoStrip","match","numRegAutoStrip","join","nSign","_s$split","_s$split2","integerPart","modifiedIntegerPart","negativeSignCharacter","mIntPos","slice","mIntNeg","hasFocus","stripReg","toggleNegativeBracket","_settings$negativeBra","_settings$negativeBra2","firstBracket","lastBracket","convertToNumericString","lastIndexOf","temp","arabicToLatinNumbers","toLocale","locale","Number","modifyNegativeSignAndDecimalCharacterForRawValue","modifyNegativeSignAndDecimalCharacterForFormattedValue","checkEmpty","inputValue","signOnEmpty","addGroupSeparators","strip","empty","isValueNegative","isZero","digitalGroup","_inputValue$split","_inputValue$split2","_inputValue$split3","_inputValue$split4","substring","positiveSignCharacter","rawValue","truncateZeros","roundedInputValue","temporaryDecimalPlacesOverride","regex","roundValue","round","ceil","floor","ivRounded","dPos","inputValueHasADot","vdPos","cDec","zeros","rLength","tRound","odd","ivArray","truncateDecimal","isPaste","_s$split3","_s$split4","modifiedDecimalPart","nL","search","xc","yc","xNeg","checkIfInRangeWithOverrideOption","minParse","maxParse","valParse","getCurrentElement","element","getAutoNumericHolder","update","data","AutoNumericHolder","get","keepAnOriginalSettingsCopy","oDec","oPad","oBracket","oSep","oSign","oSuffix","readCookie","name","nameEQ","ca","cookie","storageTest","mod","sessionStorage","setItem","removeItem","cleanLeadingTrailingZeros","trimPaddedZerosFromDecimalPlaces","_numericString$split","_numericString$split2","trimmedDecimalPart","saveValueToPersistentStorage","action","storedName","decodeURIComponent","date","expires","Date","setTime","getTime","toUTCString","getItem","_getStringOrArray","getArrayBehavior","formIndex","allFormElements","aiIndex","scIndex","rSubmitterTypes","rSubmittable","rCheckableType","rNonAutoNumericTypes","count","field","localName","type","disabled","checked","formFields","serializeArray","scElement","testInput","_ret2","serialize","formParts","_formParts$i$split","_formParts$i$split2","inputName","modifiedInputValue","onFocusInAndMouseEnter","is","roundedValue","valueOnFocus","lastVal","onEmpty","onKeydown","_updateAutoNumericHolderEventKeycode","initialValueOnKeydown","readOnly","processed","eventKeyCode","triggerEvent","_updateAutoNumericHolderProperties","_skipAlways","_processCharacterDeletion","_formatValue","throwInput","preventDefault","formatted","onKeypress","eventCharacter","isCharacterInsertionAllowed","_processCharacterInsertion","onInput","androidSelectionStart","charCodeAt","androidCharEntered","decimalCharacterPosition","hasDecimalCharacter","onKeyup","skip","valuePartsBeforePaste","isOnAndroid","onFocusOutAndMouseLeave","origValue","_checkIfInRangeWithOv3","_checkIfInRangeWithOv4","minTest","maxTest","trigger","groupedValue","change","onPaste","rawPastedText","clipboardData","getData","initialFormattedValue","selectionSize","isAllInputTextSelected","isPasteNegative","untranslatedPastedText","pastedText","caretPositionOnInitialTextAfterPasting","initialUnformattedNumber","isInitialValueNegative","isPasteNegativeAndInitialValueIsPositive","leftPartContainedADot","leftPart","rightPart","leftFormattedPart","rightFormattedPart","lastGoodKnownResult","pastedTextIndex","modifiedLeftPart","lastGoodKnownResultIndex","lastGoodKnownResultSize","leftFormattedPart2","rightFormattedPart2","indexWherePastedTextHasBeenInserted","indexSelectionEndInRawValue","selectedText","valueHasBeenSet","valueHasBeenClamped","error","clampedValue","caretPositionInFormattedNumber","onBlur","onSubmit","closest","on","$settings","getInputIfSupportedTagAndType","$input","currentElementTag","formatDefaultValueOnPageLoad","setValue","currentValue","unLocalizedCurrentValue","toNumericValue","attr","Infinity","toStrip","tagList","correctNegativePositiveSignPlacementOption","calculateVMinAndVMaxIntegerSizes","_settings$maximumValu","_settings$maximumValu2","maximumValueIntegerPart","_ref3","_ref4","minimumValueIntegerPart","correctDecimalPlacesOverrideOption","setsAlternativeDecimalSeparatorCharacter","cachesUsualRegularExpressions","allNumbersReg","noAllNumbersReg","aNegReg","aNegRegAutoStrip","negativeSignRegPart","allowed","transformOptionsValuesToDefaultTypes","convertOldOptionsToNewOnes","options","oldOptionsConverter","aSep","nSep","dGroup","aDec","altDec","aSign","pSign","pNeg","aSuffix","oLimits","vMax","vMin","mDec","eDec","scaleDecimal","aStor","mRound","aPad","nBracket","wEmpty","lZero","aForm","sNumber","anDefault","unSetOnSubmit","outputType","debug","runOnce","caretFix","option","getInitialSettings","extend","tagData","NaN","arabicNumbers","returnANumber","parseDecimalCharacter","parseThousandSeparator","resultAsNumber","eventName","detail","window","CustomEvent","bubbles","cancelable","createEvent","initCustomEvent","dispatchEvent","$that","setReal","pos","_setSelection","left","right","_getLeftAndRightPartA","_getLeftAndRightPartAroundTheSelection","_getLeftAndRightPartA2","stripZeros","newValue","parts","_normalizeParts","_checkIfInRangeWithOv","_checkIfInRangeWithOv2","testValue","_setCaretPosition","currencySymbolLen","hasNeg","valueLen","signPosition","_getSignPosition","oldParts","_getLeftAndRightPartA3","_getLeftAndRightPartA4","_setValueParts","ctrlKey","metaKey","shiftKey","_checkPaste","negLen","suffixTextLen","_expandSelectionOnSign","_ref","_ref2","_getUnformattedLeftAn3","_getUnformattedLeftAndRightPartAroundTheSelection","_getUnformattedLeftAn4","_getUnformattedLeftAn","_getUnformattedLeftAn2","_processCharacterDele","_processCharacterDeletionIfTrailingNegativeSign","_processCharacterDele2","eventOrChar","_getUnformattedLeftAn5","_getUnformattedLeftAn6","eventNumber","_this","leftLength","_getUnformattedLeftAn7","_getUnformattedLeftAn8","_leftLength$split","_leftLength$split2","subParts","leftAr","shift","signParts","escapeChr","escapedParts","miniParts","leftReg","newLeft","input","methods","init","addEventListener","destroy","removeData","off","wipe","set","_checkIfInRangeWithOv5","_checkIfInRangeWithOv6","attemptedValue","hasBeenRounded","tempDecimal","onOff","unSet","reSet","eq","getLocalized","getNumber","getFormatted","getString","getArray","getSettings","fn","method","_len","args","_key","defaults","lang","valueString","_checkIfInRangeWithOv7","_checkIfInRangeWithOv8","autoStrip","autoUnformat","userOptions","shouldExtendDefaultOptions","testPositiveInteger","testNumericalCharacters","testFloatOrIntegerAndPossibleNegativeSign","testPositiveFloatOrInteger","vMinAndVMaxMaximumDecimalPlaces","autoValidate","isValid","params","evt","Event","default","format","unFormat"],"mappings":"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","file":"autoNumeric.min.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory(require(\"jquery\"));\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([\"jquery\"], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"autonumeric\"] = factory(require(\"jquery\"));\n\telse\n\t\troot[\"autonumeric\"] = factory(root[\"jQuery\"]);\n})(this, function(__WEBPACK_EXTERNAL_MODULE_1__) {\nreturn \n\n\n// WEBPACK FOOTER //\n// webpack/universalModuleDefinition","(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory(require(\"jquery\"));\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([\"jquery\"], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"autonumeric\"] = factory(require(\"jquery\"));\n\telse\n\t\troot[\"autonumeric\"] = factory(root[\"jQuery\"]);\n})(this, function(__WEBPACK_EXTERNAL_MODULE_1__) {\nreturn /******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n/******/\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId])\n/******/ \t\t\treturn installedModules[moduleId].exports;\n/******/\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\texports: {},\n/******/ \t\t\tid: moduleId,\n/******/ \t\t\tloaded: false\n/******/ \t\t};\n/******/\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n/******/\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.loaded = true;\n/******/\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/\n/******/\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n/******/\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n/******/\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n/******/\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(0);\n/******/ })\n/************************************************************************/\n/******/ ([\n/* 0 */\n/***/ function(module, exports, __webpack_require__) {\n\n\tvar __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*** IMPORTS FROM imports-loader ***/\n\tvar jQuery = __webpack_require__(1);\n\tvar $ = __webpack_require__(1);\n\t(function() {\n\t\n\t'use strict';\n\t\n\tObject.defineProperty(exports, \"__esModule\", {\n\t value: true\n\t});\n\t\n\tvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\t\n\tvar _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"]) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); } }; }();\n\t\n\tvar _typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; };\n\t\n\tfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\t\n\t/**\n\t * autoNumeric.js\n\t *\n\t * @version 2.0.12\n\t * @date 2017-04-07 UTC 07:00\n\t *\n\t * @author Bob Knothe\n\t * @contributors Alexandre Bonneau, Sokolov Yura and other Github users,\n\t * cf. AUTHORS.md.\n\t * @copyright 2009 Robert J. Knothe http://www.decorplanit.com/plugin/\n\t * @since 2009-08-09\n\t *\n\t * @summary autoNumeric is a library that provides live as-you-type\n\t * formatting for international numbers and currencies.\n\t *\n\t * Note : Some functions are borrowed from big.js\n\t * @link https://github.com/MikeMcl/big.js/\n\t *\n\t * Please report any bugs to https://github.com/autoNumeric/autoNumeric\n\t *\n\t * @license Released under the MIT License\n\t * @link http://www.opensource.org/licenses/mit-license.php\n\t *\n\t * Permission is hereby granted, free of charge, to any person\n\t * obtaining a copy of this software and associated documentation\n\t * files (the \"Software\"), to deal in the Software without\n\t * restriction, including without limitation the rights to use,\n\t * copy, modify, merge, publish, distribute, sub license, and/or sell\n\t * copies of the Software, and to permit persons to whom the\n\t * Software is furnished to do so, subject to the following\n\t * conditions:\n\t *\n\t * The above copyright notice and this permission notice shall be\n\t * included in all copies or substantial portions of the Software.\n\t *\n\t * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n\t * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n\t * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n\t * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n\t * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n\t * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n\t * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n\t * OTHER DEALINGS IN THE SOFTWARE.\n\t */\n\t\n\t/* global module, require, define */\n\t\n\t// Functions names for ES6 exports\n\tvar autoFormat = void 0;\n\tvar autoUnFormat = void 0;\n\tvar getDefaultConfig = void 0;\n\tvar getLanguages = void 0;\n\tvar validate = void 0;\n\tvar areSettingsValid = void 0;\n\t\n\t// AutoNumeric default settings\n\t/**\n\t * List of allowed tag on which autoNumeric can be used.\n\t */\n\tvar allowedTagList = ['b', 'caption', 'cite', 'code', 'const', 'dd', 'del', 'div', 'dfn', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'ins', 'kdb', 'label', 'li', 'option', 'output', 'p', 'q', 's', 'sample', 'span', 'strong', 'td', 'th', 'u'];\n\t\n\t/**\n\t * Defaults options are public - these can be overridden by the following method:\n\t * - HTML5 data attributes (ie. ``)\n\t * - Options passed by the 'init' or 'update' methods (ie. `aNInput.autoNumeric('update', { currencySymbol: ' €' });`)\n\t * - Use jQuery's `$.extend` method for global changes - also a great way to pass ASP.NET current culture settings\n\t */\n\tvar defaultSettings = {\n\t /* Allowed thousand grouping separator characters :\n\t * ',' // Comma\n\t * '.' // Dot\n\t * ' ' // Normal space\n\t * '\\u2009' // Thin-space\n\t * '\\u202f' // Narrow no-break space\n\t * '\\u00a0' // No-break space\n\t * '' // No separator\n\t * \"'\" // Apostrophe\n\t * '٬' // Arabic thousands separator\n\t * '˙' // Dot above\n\t * Deprecated older option name : aSep\n\t */\n\t digitGroupSeparator: ',',\n\t\n\t /* Remove the thousand separator on focus, currency symbol and suffix on focus\n\t * example if the input value \"$ 1,999.88 suffix\"\n\t * on \"focusin\" it becomes \"1999.88\" and back to \"$ 1,999.88 suffix\" on focus out.\n\t * Deprecated older option name : nSep\n\t */\n\t noSeparatorOnFocus: false,\n\t\n\t /* Digital grouping for the thousand separator used in Format\n\t * digitalGroupSpacing: \"2\", results in 99,99,99,999 India's lakhs\n\t * digitalGroupSpacing: \"2s\", results in 99,999,99,99,999 India's lakhs scaled\n\t * digitalGroupSpacing: \"3\", results in 999,999,999 default\n\t * digitalGroupSpacing: \"4\", results in 9999,9999,9999 used in some Asian countries\n\t * Deprecated older option name : dGroup\n\t */\n\t digitalGroupSpacing: '3',\n\t\n\t /* Allowed decimal separator characters :\n\t * ',' : Comma\n\t * '.' : Dot\n\t * '·' : Middle-dot\n\t * '٫' : Arabic decimal separator\n\t * '⎖' : Decimal separator key symbol\n\t * Deprecated older option name : aDec\n\t */\n\t decimalCharacter: '.',\n\t\n\t /* Allow to declare an alternative decimal separator which is automatically replaced by `decimalCharacter` when typed.\n\t * This is used by countries that use a comma \",\" as the decimal character and have keyboards\\numeric pads that have\n\t * a period 'full stop' as the decimal characters (France or Spain for instance).\n\t * Deprecated older option name : altDec\n\t */\n\t decimalCharacterAlternative: null,\n\t\n\t /* currencySymbol = allowed currency symbol\n\t * Must be in quotes currencySymbol: \"$\"\n\t * space to the right of the currency symbol currencySymbol: '$ '\n\t * space to the left of the currency symbol currencySymbol: ' $'\n\t * Deprecated older option name : aSign\n\t */\n\t currencySymbol: '',\n\t\n\t /* currencySymbolPlacement = placement of currency sign as a p=prefix or s=suffix\n\t * for prefix currencySymbolPlacement: \"p\" (default)\n\t * for suffix currencySymbolPlacement: \"s\"\n\t * Deprecated older option name : pSign\n\t */\n\t //TODO Rename the options to more explicit names ('p' => 'prefix', etc.)\n\t currencySymbolPlacement: 'p',\n\t\n\t /* Placement of negative/positive sign relative to the currencySymbol option l=left, r=right, p=prefix & s=suffix\n\t * -1,234.56 => default no options required\n\t * -$1,234.56 => {currencySymbol: \"$\"} or {currencySymbol: \"$\", negativePositiveSignPlacement: \"l\"}\n\t * $-1,234.56 => {currencySymbol: \"$\", negativePositiveSignPlacement: \"r\"} // Default if negativePositiveSignPlacement is 'null' and currencySymbol is not empty\n\t * -1,234.56$ => {currencySymbol: \"$\", currencySymbolPlacement: \"s\", negativePositiveSignPlacement: \"p\"} // Default if negativePositiveSignPlacement is 'null' and currencySymbol is not empty\n\t * 1,234.56- => {negativePositiveSignPlacement: \"s\"}\n\t * $1,234.56- => {currencySymbol: \"$\", negativePositiveSignPlacement: \"s\"}\n\t * 1,234.56-$ => {currencySymbol: \"$\", currencySymbolPlacement: \"s\"}\n\t * 1,234.56$- => {currencySymbol: \"$\", currencySymbolPlacement: \"s\", negativePositiveSignPlacement: \"r\"}\n\t * Deprecated older option name : pNeg\n\t */\n\t //TODO Rename the options to more explicit names ('p' => 'prefix', etc.)\n\t negativePositiveSignPlacement: null,\n\t\n\t /* Allow the positive sign symbol `+` to be displayed for positive numbers.\n\t * By default, this positive sign is not shown.\n\t * The sign placement is controlled by the 'negativePositiveSignPlacement' option, mimicking the negative sign placement rules.\n\t */\n\t showPositiveSign: false,\n\t\n\t /* Additional suffix\n\t * Must be in quotes suffixText: 'gross', a space is allowed suffixText: ' dollars'\n\t * Numeric characters and negative sign not allowed'\n\t * Deprecated older option name : aSuffix\n\t */\n\t suffixText: '',\n\t\n\t /* Override min max limits\n\t * overrideMinMaxLimits: \"ceiling\" adheres to maximumValue and ignores minimumValue settings\n\t * overrideMinMaxLimits: \"floor\" adheres to minimumValue and ignores maximumValue settings\n\t * overrideMinMaxLimits: \"ignore\" ignores both minimumValue & maximumValue\n\t * Deprecated older option name : oLimits\n\t */\n\t overrideMinMaxLimits: null,\n\t\n\t /* Maximum possible value\n\t * value must be enclosed in quotes and use the period for the decimal point\n\t * value must be larger than minimumValue\n\t * Deprecated older option name : vMax\n\t */\n\t maximumValue: '9999999999999.99', // 9.999.999.999.999,99 ~= 10000 billions\n\t\n\t /* Minimum possible value\n\t * value must be enclosed in quotes and use the period for the decimal point\n\t * value must be smaller than maximumValue\n\t * Deprecated older option name : vMin\n\t */\n\t minimumValue: '-9999999999999.99', // -9.999.999.999.999,99 ~= 10000 billions\n\t\n\t /* Maximum number of decimal places = used to override decimal places set by the minimumValue & maximumValue values\n\t * Deprecated older option name : mDec\n\t */\n\t decimalPlacesOverride: null,\n\t\n\t /* Expanded decimal places visible when input has focus - example:\n\t * {decimalPlacesShownOnFocus: \"5\"} and the default 2 decimal places with focus \"1,000.12345\" without focus \"1,000.12\" the results depends on the rounding method used\n\t * the \"get\" method returns the extended decimal places\n\t * Deprecated older option name : eDec\n\t */\n\t decimalPlacesShownOnFocus: null,\n\t\n\t /* The next three options (scaleDivisor, scaleDecimalPlaces & scaleSymbol) handle scaling of the input when the input does not have focus\n\t * Please note that the non-scaled value is held in data and it is advised that you use the \"saveValueToSessionStorage\" option to ensure retaining the value\n\t * [\"divisor\", \"decimal places\", \"symbol\"]\n\t * Example: with the following options set {scaleDivisor: '1000', scaleDecimalPlaces: '1', scaleSymbol: ' K'}\n\t * Example: focusin value \"1,111.11\" focusout value \"1.1 K\"\n\t */\n\t\n\t /* The `scaleDivisor` decides the on focus value and places the result in the input on focusout\n\t * Example {scaleDivisor: '1000'} or \n\t * The divisor value - does not need to be whole number but please understand that Javascript has limited accuracy in math\n\t * The \"get\" method returns the full value, including the 'hidden' decimals.\n\t */\n\t scaleDivisor: null,\n\t\n\t /*\n\t * The `scaleDecimalPlaces` option is the number of decimal place when not in focus - for this to work, `scaledDivisor` must not be `null`.\n\t * This is optional ; if omitted the decimal places will be the same when the input has the focus.\n\t * Deprecated older option name : scaleDecimal\n\t */\n\t scaleDecimalPlaces: null,\n\t\n\t /*\n\t * The `scaleSymbol` option is a symbol placed as a suffix when not in focus.\n\t * This is optional too.\n\t */\n\t scaleSymbol: null,\n\t\n\t /* Set to true to allow the decimalPlacesShownOnFocus value to be saved with sessionStorage\n\t * if ie 6 or 7 the value will be saved as a session cookie\n\t * Deprecated older option name : aStor\n\t */\n\t saveValueToSessionStorage: false,\n\t\n\t /*\n\t * Manage how autoNumeric react when the user tries to paste an invalid number.\n\t * - 'error' : (This is the default behavior) The input value is not changed and an error is output in the console.\n\t * - 'ignore' : idem than 'error', but fail silently without outputting any error/warning in the console.\n\t * - 'clamp' : if the pasted value is either too small or too big regarding the minimumValue and maximumValue range, then the result is clamped to those limits.\n\t * - 'truncate' : autoNumeric will insert as many pasted numbers it can at the initial caret/selection, until everything is pasted, or the range limit is hit.\n\t * The non-pasted numbers are dropped and therefore not used at all.\n\t * - 'replace' : autoNumeric will first insert as many pasted numbers it can at the initial caret/selection, then if the range limit is hit, it will try\n\t * to replace one by one the remaining initial numbers (on the right side of the caret) with the rest of the pasted numbers.\n\t *\n\t * Note 1 : A paste content starting with a negative sign '-' will be accepted anywhere in the input, and will set the resulting value as a negative number\n\t * Note 2 : A paste content starting with a number will be accepted, even if the rest is gibberish (ie. '123foobar456').\n\t * Only the first number will be used (here '123').\n\t * Note 3 : The paste event works with the `decimalPlacesShownOnFocus` option too.\n\t */\n\t //TODO Shouldn't we use `truncate` as the default value?\n\t onInvalidPaste: 'error',\n\t\n\t /* method used for rounding\n\t * roundingMethod: \"S\", Round-Half-Up Symmetric (default)\n\t * roundingMethod: \"A\", Round-Half-Up Asymmetric\n\t * roundingMethod: \"s\", Round-Half-Down Symmetric (lower case s)\n\t * roundingMethod: \"a\", Round-Half-Down Asymmetric (lower case a)\n\t * roundingMethod: \"B\", Round-Half-Even \"Bankers Rounding\"\n\t * roundingMethod: \"U\", Round Up \"Round-Away-From-Zero\"\n\t * roundingMethod: \"D\", Round Down \"Round-Toward-Zero\" - same as truncate\n\t * roundingMethod: \"C\", Round to Ceiling \"Toward Positive Infinity\"\n\t * roundingMethod: \"F\", Round to Floor \"Toward Negative Infinity\"\n\t * roundingMethod: \"N05\" Rounds to the nearest .05 => same as \"CHF\" used in 1.9X and still valid\n\t * roundingMethod: \"U05\" Rounds up to next .05\n\t * roundingMethod: \"D05\" Rounds down to next .05\n\t * Deprecated older option name : mRound\n\t */\n\t //TODO Rename the options to more explicit names ('S' => 'RoundHalfUpSymmetric', etc.)\n\t //TODO Add an `an.roundingMethod` object that enum those options clearly\n\t roundingMethod: 'S',\n\t\n\t /* Allow padding the decimal places with zeros\n\t * allowDecimalPadding: true - always Pad decimals with zeros\n\t * allowDecimalPadding: false - does not pad with zeros.\n\t * Note: setting allowDecimalPadding to 'false' will override the 'decimalPlacesOverride' setting.\n\t *\n\t * thanks to Jonas Johansson for the suggestion\n\t * Deprecated older option name : aPad\n\t */\n\t allowDecimalPadding: true,\n\t\n\t /* Adds brackets on negative values (ie. transforms '-$ 999.99' to '(999.99)')\n\t * Those brackets are visible only when the field does NOT have the focus.\n\t * The left and right symbols should be enclosed in quotes and separated by a comma\n\t * This option can be of the following values :\n\t * null, // This is the default value, which deactivate this feature\n\t * '(,)',\n\t * '[,]',\n\t * '<,>' or\n\t * '{,}'\n\t * Deprecated older option name : nBracket\n\t */\n\t //TODO Rename the options to more explicit names ('(,)' => 'parentheses', etc.)\n\t negativeBracketsTypeOnBlur: null,\n\t\n\t /* Displayed on empty string \"\"\n\t * emptyInputBehavior: \"focus\" - (default) currency sign displayed and the input receives focus\n\t * emptyInputBehavior: \"press\" - currency sign displays on any key being pressed\n\t * emptyInputBehavior: \"always\" - always displays the currency sign only\n\t * emptyInputBehavior: \"zero\" - if the input has no value on focus out displays a zero \"rounded\" with or without a currency sign\n\t * Deprecated older option name : wEmpty\n\t */\n\t emptyInputBehavior: 'focus',\n\t\n\t /* Controls leading zero behavior\n\t * leadingZero: \"allow\", - allows leading zeros to be entered. Zeros will be truncated when entering additional digits. On focusout zeros will be deleted.\n\t * leadingZero: \"deny\", - allows only one leading zero on values less than one\n\t * leadingZero: \"keep\", - allows leading zeros to be entered. on focusout zeros will be retained.\n\t * Deprecated older option name : lZero\n\t */\n\t leadingZero: 'deny',\n\t\n\t /* Determine if the default value will be formatted on initialization.\n\t * true = automatically formats the default value on initialization\n\t * false = will not format the default value on initialization\n\t * Deprecated older option name : aForm\n\t */\n\t formatOnPageLoad: true,\n\t\n\t /* Determine if the select all keyboard command will select the complete input text, or only the input numeric value\n\t * Note : If the currency symbol is between the numeric value and the negative sign, only the numeric value will selected\n\t * Deprecated older option name : sNumber\n\t */\n\t selectNumberOnly: false,\n\t\n\t /* Helper option for ASP.NET postback\n\t * should be the value of the unformatted default value\n\t * examples:\n\t * no default value=\"\" {defaultValueOverride: \"\"}\n\t * value=1234.56 {defaultValueOverride: '1234.56'}\n\t * Deprecated older option name : anDefault\n\t */\n\t defaultValueOverride: null,\n\t\n\t /* Removes formatting on submit event\n\t * this output format: positive nnnn.nn, negative -nnnn.nn\n\t * review the 'unSet' method for other formats\n\t * Deprecated older option name : unSetOnSubmit\n\t */\n\t unformatOnSubmit: false,\n\t\n\t /* Allows the output to be in the locale format via the \"get\", \"getString\" & \"getArray\" methods\n\t * null or 'string' => 'nnnn.nn' or '-nnnn.nn' as text type. This is the default behavior.\n\t * 'number' => nnnn.nn or -nnnn.nn as a Number (Warning: this works only for integers inferior to Number.MAX_SAFE_INTEGER)\n\t * ',' or '-,' => 'nnnn,nn' or '-nnnn,nn'\n\t * '.-' => 'nnnn.nn' or 'nnnn.nn-'\n\t * ',-' => 'nnnn,nn' or 'nnnn,nn-'\n\t * Deprecated older option name : outputType\n\t */\n\t outputFormat: null,\n\t\n\t /* Defines if warnings should be shown\n\t * Error handling function\n\t * true => all warning are shown\n\t * false => no warnings are shown, only the thrown errors\n\t * Deprecated older option name : debug\n\t */\n\t showWarnings: true,\n\t\n\t /*\n\t * This option is the 'strict mode' (aka 'debug' mode), which allows autoNumeric to strictly analyse the options passed, and fails if an unknown options is used in the settings object.\n\t * You should set that to 'TRUE' if you want to make sure you are only using 'pure' autoNumeric settings objects in your code.\n\t * If you see uncaught errors in the console and your code starts to fail, this means somehow those options gets corrupted by another program.\n\t */\n\t failOnUnknownOption: false\n\t};\n\t\n\t/**\n\t * Wrapper variable that hold named keyboard keys with their respective keyCode as seen in DOM events.\n\t * //TODO Replace every call to this object with a call to `keyName`\n\t * @deprecated\n\t */\n\tvar keyCode = {\n\t Backspace: 8,\n\t Tab: 9,\n\t Enter: 13,\n\t Shift: 16,\n\t Ctrl: 17,\n\t Alt: 18,\n\t PauseBreak: 19,\n\t CapsLock: 20,\n\t Esc: 27,\n\t Space: 32,\n\t PageUp: 33,\n\t PageDown: 34,\n\t End: 35,\n\t Home: 36,\n\t LeftArrow: 37,\n\t UpArrow: 38,\n\t RightArrow: 39,\n\t DownArrow: 40,\n\t Insert: 45,\n\t Delete: 46,\n\t num0: 48,\n\t num1: 49,\n\t num2: 50,\n\t num3: 51,\n\t num4: 52,\n\t num5: 53,\n\t num6: 54,\n\t num7: 55,\n\t num8: 56,\n\t num9: 57,\n\t a: 65,\n\t b: 66,\n\t c: 67,\n\t d: 68,\n\t e: 69,\n\t f: 70,\n\t g: 71,\n\t h: 72,\n\t i: 73,\n\t j: 74,\n\t k: 75,\n\t l: 76,\n\t m: 77,\n\t n: 78,\n\t o: 79,\n\t p: 80,\n\t q: 81,\n\t r: 82,\n\t s: 83,\n\t t: 84,\n\t u: 85,\n\t v: 86,\n\t w: 87,\n\t x: 88,\n\t y: 89,\n\t z: 90,\n\t Windows: 91,\n\t RightClick: 93,\n\t numpad0: 96,\n\t numpad1: 97,\n\t numpad2: 98,\n\t numpad3: 99,\n\t numpad4: 100,\n\t numpad5: 101,\n\t numpad6: 102,\n\t numpad7: 103,\n\t numpad8: 104,\n\t numpad9: 105,\n\t MultiplyNumpad: 106,\n\t PlusNumpad: 107,\n\t MinusNumpad: 109,\n\t DotNumpad: 110,\n\t SlashNumpad: 111,\n\t F1: 112,\n\t F2: 113,\n\t F3: 114,\n\t F4: 115,\n\t F5: 116,\n\t F6: 117,\n\t F7: 118,\n\t F8: 119,\n\t F9: 120,\n\t F10: 121,\n\t F11: 122,\n\t F12: 123,\n\t NumLock: 144,\n\t ScrollLock: 145,\n\t MyComputer: 182,\n\t MyCalculator: 183,\n\t Semicolon: 186,\n\t Equal: 187,\n\t Comma: 188,\n\t Hyphen: 189,\n\t Dot: 190,\n\t Slash: 191,\n\t Backquote: 192,\n\t LeftBracket: 219,\n\t Backslash: 220,\n\t RightBracket: 221,\n\t Quote: 222,\n\t Command: 224,\n\t AndroidDefault: 229 };\n\t\n\t/**\n\t * Wrapper variable that hold named keyboard keys with their respective key name (as set in KeyboardEvent.key).\n\t * Those names are listed here :\n\t * @link https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values\n\t */\n\tvar keyName = {\n\t // Special values\n\t Unidentified: 'Unidentified',\n\t\n\t // Modifier keys\n\t Alt: 'Alt',\n\t AltGr: 'AltGraph',\n\t CapsLock: 'CapsLock', // Under Chrome, e.key is empty for CapsLock\n\t Ctrl: 'Control',\n\t Fn: 'Fn',\n\t FnLock: 'FnLock',\n\t Hyper: 'Hyper', // 'OS' under Firefox\n\t Meta: 'Meta', // The Windows, Command or ⌘ key // 'OS' under Firefox and IE9\n\t Windows: 'Meta', // This is a non-official key name\n\t Command: 'Meta', // This is a non-official key name\n\t NumLock: 'NumLock',\n\t ScrollLock: 'ScrollLock',\n\t Shift: 'Shift',\n\t Super: 'Super', // 'OS' under Firefox\n\t Symbol: 'Symbol',\n\t SymbolLock: 'SymbolLock',\n\t\n\t // Whitespace keys\n\t Enter: 'Enter',\n\t Tab: 'Tab',\n\t Space: ' ', // 'Spacebar' for Firefox <37, and IE9\n\t\n\t // Navigation keys\n\t DownArrow: 'ArrowDown', // 'Down' for Firefox <=36, and IE9\n\t LeftArrow: 'ArrowLeft', // 'Left' for Firefox <=36, and IE9\n\t RightArrow: 'ArrowRight', // 'Right' for Firefox <=36, and IE9\n\t UpArrow: 'ArrowUp', // 'Up' for Firefox <=36, and IE9\n\t End: 'End',\n\t Home: 'Home',\n\t PageDown: 'PageDown',\n\t PageUp: 'PageUp',\n\t\n\t // Editing keys\n\t Backspace: 'Backspace',\n\t Clear: 'Clear',\n\t Copy: 'Copy',\n\t CrSel: 'CrSel', // 'Crsel' for Firefox <=36, and IE9\n\t Cut: 'Cut',\n\t Delete: 'Delete', // 'Del' for Firefox <=36, and IE9\n\t EraseEof: 'EraseEof',\n\t ExSel: 'ExSel', // 'Exsel' for Firefox <=36, and IE9\n\t Insert: 'Insert',\n\t Paste: 'Paste',\n\t Redo: 'Redo',\n\t Undo: 'Undo',\n\t\n\t // UI keys\n\t Accept: 'Accept',\n\t Again: 'Again',\n\t Attn: 'Attn', // 'Unidentified' for Firefox, Chrome, and IE9 ('KanaMode' when using the Japanese keyboard layout)\n\t Cancel: 'Cancel',\n\t ContextMenu: 'ContextMenu', // 'Apps' for Firefox <=36, and IE9\n\t Esc: 'Escape', // 'Esc' for Firefox <=36, and IE9\n\t Execute: 'Execute',\n\t Find: 'Find',\n\t Finish: 'Finish', // 'Unidentified' for Firefox, Chrome, and IE9 ('Katakana' when using the Japanese keyboard layout)\n\t Help: 'Help',\n\t Pause: 'Pause',\n\t Play: 'Play',\n\t Props: 'Props',\n\t Select: 'Select',\n\t ZoomIn: 'ZoomIn',\n\t ZoomOut: 'ZoomOut',\n\t\n\t // Device keys\n\t BrightnessDown: 'BrightnessDown',\n\t BrightnessUp: 'BrightnessUp',\n\t Eject: 'Eject',\n\t LogOff: 'LogOff',\n\t Power: 'Power',\n\t PowerOff: 'PowerOff',\n\t PrintScreen: 'PrintScreen',\n\t Hibernate: 'Hibernate', // 'Unidentified' for Firefox <=37\n\t Standby: 'Standby', // 'Unidentified' for Firefox <=36, and IE9\n\t WakeUp: 'WakeUp',\n\t\n\t // IME and composition keys\n\t Compose: 'Compose',\n\t Dead: 'Dead',\n\t\n\t // Function keys\n\t F1: 'F1',\n\t F2: 'F2',\n\t F3: 'F3',\n\t F4: 'F4',\n\t F5: 'F5',\n\t F6: 'F6',\n\t F7: 'F7',\n\t F8: 'F8',\n\t F9: 'F9',\n\t F10: 'F10',\n\t F11: 'F11',\n\t F12: 'F12',\n\t\n\t // Document keys\n\t Print: 'Print',\n\t\n\t // 'Normal' keys\n\t num0: '0',\n\t num1: '1',\n\t num2: '2',\n\t num3: '3',\n\t num4: '4',\n\t num5: '5',\n\t num6: '6',\n\t num7: '7',\n\t num8: '8',\n\t num9: '9',\n\t numpad0: '0',\n\t numpad1: '1',\n\t numpad2: '2',\n\t numpad3: '3',\n\t numpad4: '4',\n\t numpad5: '5',\n\t numpad6: '6',\n\t numpad7: '7',\n\t numpad8: '8',\n\t numpad9: '9',\n\t a: 'a',\n\t b: 'b',\n\t c: 'c',\n\t d: 'd',\n\t e: 'e',\n\t f: 'f',\n\t g: 'g',\n\t h: 'h',\n\t i: 'i',\n\t j: 'j',\n\t k: 'k',\n\t l: 'l',\n\t m: 'm',\n\t n: 'n',\n\t o: 'o',\n\t p: 'p',\n\t q: 'q',\n\t r: 'r',\n\t s: 's',\n\t t: 't',\n\t u: 'u',\n\t v: 'v',\n\t w: 'w',\n\t x: 'x',\n\t y: 'y',\n\t z: 'z',\n\t MultiplyNumpad: '*',\n\t PlusNumpad: '+',\n\t MinusNumpad: '-',\n\t DotNumpad: '.',\n\t SlashNumpad: '/',\n\t Semicolon: ';',\n\t Equal: '=',\n\t Comma: ',',\n\t Hyphen: '-',\n\t Minus: '-',\n\t Plus: '+',\n\t Dot: '.',\n\t Slash: '/',\n\t Backquote: '`',\n\t LeftBracket: '[',\n\t RightBracket: ']',\n\t Backslash: '\\\\',\n\t Quote: \"'\",\n\t NumpadDot: '.',\n\t NumpadDotAlt: ',', // Modern browsers automatically adapt the character sent by this key to the decimal character of the current language\n\t NumpadMultiply: '*',\n\t NumpadPlus: '+',\n\t NumpadMinus: '-',\n\t NumpadSlash: '/',\n\t NumpadDotObsoleteBrowsers: 'Decimal',\n\t NumpadMultiplyObsoleteBrowsers: 'Multiply',\n\t NumpadPlusObsoleteBrowsers: 'Add',\n\t NumpadMinusObsoleteBrowsers: 'Subtract',\n\t NumpadSlashObsoleteBrowsers: 'Divide'\n\t};\n\t\n\tvar defaultMinimumValue = '-999999999999.99';\n\tvar defaultMaximumValue = '999999999999.99';\n\tvar defaultRoundingMethod = 'U';\n\tvar defaultLeadingZero = 'deny';\n\tvar defaultSelectNumberOnly = true;\n\t\n\t/**\n\t * Predefined options for the most common languages\n\t */\n\tvar languageOption = {\n\t French: { // Français\n\t digitGroupSeparator: '.', // or '\\u202f'\n\t decimalCharacter: ',',\n\t decimalCharacterAlternative: '.',\n\t currencySymbol: '\\u202F\\u20AC',\n\t currencySymbolPlacement: 's',\n\t selectNumberOnly: defaultSelectNumberOnly,\n\t roundingMethod: defaultRoundingMethod,\n\t leadingZero: defaultLeadingZero,\n\t minimumValue: defaultMinimumValue,\n\t maximumValue: defaultMaximumValue\n\t },\n\t NorthAmerican: {\n\t digitGroupSeparator: ',',\n\t decimalCharacter: '.',\n\t currencySymbol: '$',\n\t currencySymbolPlacement: 'p',\n\t selectNumberOnly: defaultSelectNumberOnly,\n\t roundingMethod: defaultRoundingMethod,\n\t leadingZero: defaultLeadingZero,\n\t minimumValue: defaultMinimumValue,\n\t maximumValue: defaultMaximumValue\n\t },\n\t British: {\n\t digitGroupSeparator: ',',\n\t decimalCharacter: '.',\n\t currencySymbol: '£',\n\t currencySymbolPlacement: 'p',\n\t selectNumberOnly: defaultSelectNumberOnly,\n\t roundingMethod: defaultRoundingMethod,\n\t leadingZero: defaultLeadingZero,\n\t minimumValue: defaultMinimumValue,\n\t maximumValue: defaultMaximumValue\n\t },\n\t Swiss: { // Suisse\n\t digitGroupSeparator: '\\'',\n\t decimalCharacter: '.',\n\t currencySymbol: '\\u202FCHF',\n\t currencySymbolPlacement: 's',\n\t selectNumberOnly: defaultSelectNumberOnly,\n\t roundingMethod: defaultRoundingMethod,\n\t leadingZero: defaultLeadingZero,\n\t minimumValue: defaultMinimumValue,\n\t maximumValue: defaultMaximumValue\n\t },\n\t Japanese: { // 日本語\n\t digitGroupSeparator: ',',\n\t decimalCharacter: '.',\n\t currencySymbol: '¥',\n\t currencySymbolPlacement: 'p',\n\t selectNumberOnly: defaultSelectNumberOnly,\n\t roundingMethod: defaultRoundingMethod,\n\t leadingZero: defaultLeadingZero,\n\t minimumValue: defaultMinimumValue,\n\t maximumValue: defaultMaximumValue\n\t }\n\t};\n\tlanguageOption.Spanish = languageOption.French; // Español (idem French)\n\tlanguageOption.Chinese = languageOption.Japanese; // 中国語 (Chinese)\n\t\n\t/**\n\t * UMD structure\n\t */\n\t(function (factory) {\n\t //TODO This surely can be improved by letting webpack take care of generating this UMD part\n\t if (true) {\n\t // AMD. Register as an anonymous module.\n\t !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(1)], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n\t } else if ((typeof module === 'undefined' ? 'undefined' : _typeof(module)) === 'object' && module.exports) {\n\t // Node/CommonJS\n\t module.exports = factory(require('jquery'));\n\t } else {\n\t // Browser globals\n\t factory(window.jQuery);\n\t }\n\t})(function ($) {\n\t // Helper functions\n\t\n\t /**\n\t * Return TRUE if the `value` is null\n\t *\n\t * @static\n\t * @param {*} value The value to test\n\t * @returns {boolean} Return TRUE if the `value` is null, FALSE otherwise\n\t */\n\t function isNull(value) {\n\t return value === null;\n\t }\n\t\n\t /**\n\t * Return TRUE if the `value` is undefined\n\t *\n\t * @static\n\t * @param {*} value The value to test\n\t * @returns {boolean} Return TRUE if the `value` is undefined, FALSE otherwise\n\t */\n\t function isUndefined(value) {\n\t return value === void 0;\n\t }\n\t\n\t /**\n\t * Return TRUE if the `value` is undefined, null or empty\n\t *\n\t * @param {*} value\n\t * @returns {boolean}\n\t */\n\t function isUndefinedOrNullOrEmpty(value) {\n\t return value === null || value === void 0 || '' === value;\n\t }\n\t\n\t /**\n\t * Return TRUE if the given parameter is a String\n\t *\n\t * @param {*} str\n\t * @returns {boolean}\n\t */\n\t function isString(str) {\n\t return typeof str === 'string' || str instanceof String;\n\t }\n\t\n\t /**\n\t * Return TRUE if the parameter is a boolean\n\t *\n\t * @static\n\t * @param {*} value\n\t * @returns {boolean}\n\t */\n\t function isBoolean(value) {\n\t return typeof value === 'boolean';\n\t }\n\t\n\t /**\n\t * Return TRUE if the parameter is a string 'true' or 'false'\n\t *\n\t * This function accepts any cases for those strings.\n\t * @param {string} value\n\t * @returns {boolean}\n\t */\n\t function isTrueOrFalseString(value) {\n\t var lowercaseValue = String(value).toLowerCase();\n\t return lowercaseValue === 'true' || lowercaseValue === 'false';\n\t }\n\t\n\t /**\n\t * Return TRUE if the parameter is an object\n\t *\n\t * @param {*} reference\n\t * @returns {boolean}\n\t */\n\t function isObject(reference) {\n\t return (typeof reference === 'undefined' ? 'undefined' : _typeof(reference)) === 'object' && reference !== null && !Array.isArray(reference);\n\t }\n\t\n\t /**\n\t * Return TRUE if the given object is empty\n\t * cf. http://stackoverflow.com/questions/679915/how-do-i-test-for-an-empty-javascript-object and http://jsperf.com/empty-object-test\n\t *\n\t * @param {object} obj\n\t * @returns {boolean}\n\t */\n\t function isEmptyObj(obj) {\n\t for (var prop in obj) {\n\t if (obj.hasOwnProperty(prop)) {\n\t return false;\n\t }\n\t }\n\t return true;\n\t }\n\t\n\t /**\n\t * Return TRUE if the parameter is a number (or a number written as a string).\n\t *\n\t * @param {*} n\n\t * @returns {boolean}\n\t */\n\t function isNumber(n) {\n\t return !isArray(n) && !isNaN(parseFloat(n)) && isFinite(n);\n\t }\n\t\n\t /**\n\t * Return TRUE if the parameter is an integer (and not a float).\n\t *\n\t * @param {*} n\n\t * @returns {boolean}\n\t */\n\t function isInt(n) {\n\t return typeof n === 'number' && parseFloat(n) === parseInt(n, 10) && !isNaN(n);\n\t }\n\t\n\t /**\n\t * Return the pasted text that will be used.\n\t *\n\t * @param {string} text\n\t * @param {AutoNumericHolder} holder\n\t * @returns {string|void|XML|*}\n\t */\n\t function preparePastedText(text, holder) {\n\t return stripAllNonNumberCharacters(text, holder.settingsClone, true).replace(holder.settingsClone.decimalCharacter, '.');\n\t }\n\t\n\t /**\n\t * Return TRUE is the string `str` contains the string `needle`\n\t * Note: this function does not coerce the parameters types\n\t *\n\t * @param {string} str\n\t * @param {string} needle\n\t * @returns {boolean}\n\t */\n\t function contains(str, needle) {\n\t if (!isString(str) || !isString(needle) || str === '' || needle === '') {\n\t return false;\n\t }\n\t\n\t return str.indexOf(needle) !== -1;\n\t }\n\t\n\t /**\n\t * Return TRUE if the `needle` is in the array\n\t *\n\t * @param {*} needle\n\t * @param {Array} array\n\t * @returns {boolean}\n\t */\n\t function isInArray(needle, array) {\n\t if (!isArray(array) || array === [] || isUndefined(needle)) {\n\t return false;\n\t }\n\t\n\t return array.indexOf(needle) !== -1;\n\t }\n\t\n\t /**\n\t * Return TRUE if the parameter is an Array\n\t *\n\t * @param {*} arr\n\t * @throws Error\n\t * @returns {*|boolean}\n\t */\n\t function isArray(arr) {\n\t if (Object.prototype.toString.call([]) === '[object Array]') {\n\t // Make sure an array has a class attribute of [object Array]\n\t // Test passed, now check if is an Array\n\t return Array.isArray(arr) || (typeof arr === 'undefined' ? 'undefined' : _typeof(arr)) === 'object' && Object.prototype.toString.call(arr) === '[object Array]';\n\t } else {\n\t throw new Error('toString message changed for Object Array'); // Verify that the string returned by `toString` does not change in the future (cf. http://stackoverflow.com/a/8365215)\n\t }\n\t }\n\t\n\t /**\n\t * Return TRUE if the parameter is a string that represents a float number, and that number has a decimal part\n\t *\n\t * @param {string} str\n\t * @returns {boolean}\n\t */\n\t // function hasDecimals(str) {\n\t // const [, decimalPart] = str.split('.');\n\t // return !isUndefined(decimalPart);\n\t // }\n\t\n\t /**\n\t * Return the number of decimal places if the parameter is a string that represents a float number, and that number has a decimal part.\n\t *\n\t * @param {string} str\n\t * @returns {int}\n\t */\n\t function decimalPlaces(str) {\n\t var _str$split = str.split('.'),\n\t _str$split2 = _slicedToArray(_str$split, 2),\n\t decimalPart = _str$split2[1];\n\t\n\t if (!isUndefined(decimalPart)) {\n\t return decimalPart.length;\n\t }\n\t\n\t return 0;\n\t }\n\t\n\t /**\n\t * Return the code for the key used to generate the given event.\n\t *\n\t * @param {Event} event\n\t * @returns {string|Number}\n\t */\n\t function keyCodeNumber(event) {\n\t // `event.keyCode` and `event.which` are deprecated, `KeyboardEvent.key` (https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key) must be used now\n\t return typeof event.which === 'undefined' ? event.keyCode : event.which;\n\t }\n\t\n\t /**\n\t * Return the character from the event key code.\n\t * @example character(50) => '2'\n\t *\n\t * @param {Event} event\n\t * @returns {string}\n\t */\n\t function character(event) {\n\t if (typeof event.key === 'undefined' || event.key === 'Unidentified') {\n\t return String.fromCharCode(keyCodeNumber(event));\n\t } else {\n\t // Special case for obsolete browsers like IE that return the old names\n\t var result = void 0;\n\t switch (event.key) {\n\t case 'Decimal':\n\t result = keyName.NumpadDot;\n\t break;\n\t case 'Multiply':\n\t result = keyName.NumpadMultiply;\n\t break;\n\t case 'Add':\n\t result = keyName.NumpadPlus;\n\t break;\n\t case 'Subtract':\n\t result = keyName.NumpadMinus;\n\t break;\n\t case 'Divide':\n\t result = keyName.NumpadSlash;\n\t break;\n\t case 'Del':\n\t // Special workaround for the obsolete browser IE11 which output a 'Delete' key when using the numpad 'dot' one! This fixes issue #401 //FIXME à terminer\n\t result = keyName.Dot; // as of version 2.0.8 the character() function is only called on keypress event. The 'Del' does not throw the keypress event.\n\t break;\n\t default:\n\t result = event.key;\n\t }\n\t\n\t return result;\n\t }\n\t }\n\t\n\t /**\n\t * Return TRUE if the given value (a number as a string) is within the range set in the settings `minimumValue` and `maximumValue`, FALSE otherwise.\n\t *\n\t * @param {string} value\n\t * @param {object} parsedMinValue Parsed via the `parseStr()` function\n\t * @param {object} parsedMaxValue Parsed via the `parseStr()` function\n\t * @returns {boolean}\n\t */\n\t function checkIfInRange(value, parsedMinValue, parsedMaxValue) {\n\t var parsedValue = parseStr(value);\n\t return testMinMax(parsedMinValue, parsedValue) > -1 && testMinMax(parsedMaxValue, parsedValue) < 1;\n\t }\n\t\n\t /**\n\t * Return TRUE if the given string contains a negative sign :\n\t * - everywhere in the string (by default), or\n\t * - on the first character only if the `checkEverywhere` parameter is set to `false`.\n\t *\n\t * @param {string} numericString A number represented by a string\n\t * @param {boolean} checkEverywhere If TRUE, then the negative sign is search everywhere in the numeric string (this is needed for instance if the string is '1234.56-')\n\t * @returns {boolean}\n\t */\n\t function isNegative(numericString) {\n\t var checkEverywhere = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n\t\n\t //TODO Use the `negativeSignCharacter` from the settings here\n\t if (checkEverywhere) {\n\t return contains(numericString, '-');\n\t }\n\t\n\t return isNegativeStrict(numericString);\n\t }\n\t\n\t /**\n\t * Return TRUE if the given string contains a negative sign on the first character (on the far left).\n\t *\n\t * @example isNegativeStrict('1234.56') => false\n\t * @example isNegativeStrict('1234.56-') => false\n\t * @example isNegativeStrict('-1234.56') => true\n\t * @example isNegativeStrict('-1,234.56 €') => true\n\t *\n\t * @param {string} numericString\n\t * @returns {boolean}\n\t */\n\t function isNegativeStrict(numericString) {\n\t //TODO Using the `negativeSignCharacter` from the settings here\n\t return numericString.charAt(0) === '-';\n\t }\n\t\n\t /**\n\t * Return TRUE if the formatted or unformatted numeric string represent the value 0 (ie. '0,00 €'), or is empty (' €').\n\t * This works since we test if there are any numbers from 1 to 9 in the string. If there is none, then the number is zero (or the string is empty).\n\t *\n\t * @param {string} numericString\n\t * @returns {boolean}\n\t */\n\t function isZeroOrHasNoValue(numericString) {\n\t return !/[1-9]/g.test(numericString);\n\t }\n\t\n\t /**\n\t * Return the negative version of the value (represented as a string) given as a parameter.\n\t *\n\t * @param {string} value\n\t * @returns {*}\n\t */\n\t function setRawNegativeSign(value) {\n\t if (!isNegativeStrict(value)) {\n\t return '-' + value;\n\t }\n\t\n\t return value;\n\t }\n\t\n\t /**\n\t * Replace the character at the position `index` in the string `string` by the character(s) `newCharacter`.\n\t *\n\t * @param {string} string\n\t * @param {int} index\n\t * @param {string} newCharacter\n\t * @returns {string}\n\t */\n\t function replaceCharAt(string, index, newCharacter) {\n\t return '' + string.substr(0, index) + newCharacter + string.substr(index + newCharacter.length);\n\t }\n\t\n\t /**\n\t * Return the value clamped to the nearest minimum/maximum value, as defined in the settings.\n\t *\n\t * @param {string|number} value\n\t * @param {object} settings\n\t * @returns {number}\n\t */\n\t function clampToRangeLimits(value, settings) {\n\t //XXX This function always assume `settings.minimumValue` is lower than `settings.maximumValue`\n\t return Math.max(settings.minimumValue, Math.min(settings.maximumValue, value));\n\t }\n\t\n\t /**\n\t * Return the number of number or dot characters on the left side of the caret, in a formatted number.\n\t *\n\t * @param {string} formattedNumberString\n\t * @param {int} caretPosition This must be a positive integer\n\t * @param {string} decimalCharacter\n\t * @returns {number}\n\t */\n\t function countNumberCharactersOnTheCaretLeftSide(formattedNumberString, caretPosition, decimalCharacter) {\n\t // Here we count the dot and report it as a number character too, since it will 'stay' in the Javascript number when unformatted\n\t var numberDotOrNegativeSign = new RegExp('[0-9' + decimalCharacter + '-]'); // No need to escape the decimal character here, since it's in `[]`\n\t\n\t var numberDotAndNegativeSignCount = 0;\n\t for (var i = 0; i < caretPosition; i++) {\n\t // Test if the character is a number, a dot or an hyphen. If it is, count it, otherwise ignore it\n\t if (numberDotOrNegativeSign.test(formattedNumberString[i])) {\n\t numberDotAndNegativeSignCount++;\n\t }\n\t }\n\t\n\t return numberDotAndNegativeSignCount;\n\t }\n\t\n\t /**\n\t * Walk the `formattedNumberString` from left to right, one char by one, counting the `formattedNumberStringIndex`.\n\t * If the char is in the `rawNumberString` (starting at index 0), then `rawNumberStringIndex++`, and continue until\n\t * there is no more characters in `rawNumberString`) or that `rawNumberStringIndex === caretPositionInRawValue`.\n\t * When you stop, the `formattedNumberStringIndex` is the position where the caret should be set.\n\t *\n\t * @example\n\t * 1234567|89.01 : position 7 (rawNumberString)\n\t * 123.456.7|89,01 : position 9 (formattedNumberString)\n\t *\n\t * @param {string} rawNumberString\n\t * @param {int} caretPositionInRawValue\n\t * @param {string} formattedNumberString\n\t * @param {string} decimalCharacter\n\t * @returns {*}\n\t */\n\t function findCaretPositionInFormattedNumber(rawNumberString, caretPositionInRawValue, formattedNumberString, decimalCharacter) {\n\t var formattedNumberStringSize = formattedNumberString.length;\n\t var rawNumberStringSize = rawNumberString.length;\n\t\n\t var formattedNumberStringIndex = void 0;\n\t var rawNumberStringIndex = 0;\n\t for (formattedNumberStringIndex = 0; formattedNumberStringIndex < formattedNumberStringSize && rawNumberStringIndex < rawNumberStringSize && rawNumberStringIndex < caretPositionInRawValue; formattedNumberStringIndex++) {\n\t if (rawNumberString[rawNumberStringIndex] === formattedNumberString[formattedNumberStringIndex] || rawNumberString[rawNumberStringIndex] === '.' && formattedNumberString[formattedNumberStringIndex] === decimalCharacter) {\n\t rawNumberStringIndex++;\n\t }\n\t }\n\t\n\t return formattedNumberStringIndex;\n\t }\n\t\n\t /**\n\t * Count the number of occurrence of the given character, in the given text.\n\t *\n\t * @param {string} character\n\t * @param {string} text\n\t * @returns {number}\n\t */\n\t function countCharInText(character, text) {\n\t var charCounter = 0;\n\t for (var i = 0; i < text.length; i++) {\n\t if (text[i] === character) {\n\t charCounter++;\n\t }\n\t }\n\t\n\t return charCounter;\n\t }\n\t\n\t /**\n\t * Return the index that can be used to set the caret position.\n\t * This takes into account that the position is starting at '0', not 1.\n\t *\n\t * @param {int} characterCount\n\t * @returns {number}\n\t */\n\t function convertCharacterCountToIndexPosition(characterCount) {\n\t return Math.max(characterCount, characterCount - 1);\n\t }\n\t\n\t /**\n\t * Cross browser routine for getting selected range/cursor position\n\t *\n\t * @param {HTMLElement|EventTarget} that\n\t * @returns {{}}\n\t */\n\t function getElementSelection(that) {\n\t var position = {};\n\t if (isUndefined(that.selectionStart)) {\n\t that.focus();\n\t var select = document.selection.createRange();\n\t position.length = select.text.length;\n\t select.moveStart('character', -that.value.length);\n\t position.end = select.text.length;\n\t position.start = position.end - position.length;\n\t } else {\n\t position.start = that.selectionStart;\n\t position.end = that.selectionEnd;\n\t position.length = position.end - position.start;\n\t }\n\t\n\t return position;\n\t }\n\t\n\t /**\n\t * Cross browser routine for setting selected range/cursor position\n\t *\n\t * @param {HTMLElement|EventTarget} that\n\t * @param {int} start\n\t * @param {int|null} end\n\t */\n\t function setElementSelection(that, start) {\n\t var end = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;\n\t\n\t if (isUndefinedOrNullOrEmpty(end)) {\n\t end = start;\n\t }\n\t\n\t if (isUndefined(that.selectionStart)) {\n\t that.focus();\n\t var range = that.createTextRange();\n\t range.collapse(true);\n\t range.moveEnd('character', end);\n\t range.moveStart('character', start);\n\t range.select();\n\t } else {\n\t that.selectionStart = start;\n\t that.selectionEnd = end;\n\t }\n\t }\n\t\n\t /**\n\t * Function that throw error messages\n\t *\n\t * @param {string} message\n\t */\n\t function throwError(message) {\n\t throw new Error(message);\n\t }\n\t\n\t /**\n\t * Function that display a warning messages, according to the debug level.\n\t *\n\t * @param {string} message\n\t * @param {boolean} showWarning If FALSE, then the warning message is not displayed\n\t */\n\t function warning(message) {\n\t var showWarning = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n\t\n\t if (showWarning) {\n\t /* eslint no-console: 0 */\n\t console.warn('Warning: ' + message);\n\t }\n\t }\n\t\n\t // autoNumeric-specific functions\n\t\n\t /**\n\t * Run any callbacks found in the settings object.\n\t * Any parameter could be a callback:\n\t * - a function, which invoked with jQuery element, parameters and this parameter name and returns parameter value\n\t * - a name of function, attached to $(selector).autoNumeric.functionName(){} - which was called previously\n\t * @param {object} $this jQuery-selected DOM element\n\t * @param {object} settings\n\t */\n\t function runCallbacksFoundInTheSettingsObject($this, settings) {\n\t // Loops through the settings object (option array) to find the following\n\t $.each(settings, function (k, val) {\n\t if (typeof val === 'function') {\n\t settings[k] = val($this, settings, k);\n\t } else if (typeof $this.autoNumeric[val] === 'function') {\n\t // Calls the attached function from the html5 data example: data-a-sign=\"functionName\"\n\t settings[k] = $this.autoNumeric[val]($this, settings, k);\n\t }\n\t });\n\t }\n\t\n\t /**\n\t * Determine the maximum decimal length from the minimumValue and maximumValue settings\n\t *\n\t * @param {string} minimumValue\n\t * @param {string} maximumValue\n\t * @returns {number}\n\t */\n\t function maximumVMinAndVMaxDecimalLength(minimumValue, maximumValue) {\n\t return Math.max(decimalPlaces(minimumValue), decimalPlaces(maximumValue));\n\t }\n\t\n\t /**\n\t * Strip all unwanted non-number characters.\n\t * This keeps the numbers, the negative sign as well as the custom decimal character.\n\t *\n\t * @param {string} s\n\t * @param {object} settings\n\t * @param {boolean} leftOrAll\n\t * @returns {string|*}\n\t */\n\t function stripAllNonNumberCharacters(s, settings, leftOrAll) {\n\t //TODO This function is called 10 times (sic!) on each key input, couldn't we lower that number? cf. issue #325\n\t //TODO Refactor this with `convertToNumericString()` if possible?\n\t if (settings.currencySymbol !== '') {\n\t // Remove currency sign\n\t s = s.replace(settings.currencySymbol, '');\n\t }\n\t if (settings.suffixText) {\n\t // Remove suffix\n\t while (contains(s, settings.suffixText)) {\n\t s = s.replace(settings.suffixText, '');\n\t }\n\t }\n\t\n\t // First replace anything before digits\n\t s = s.replace(settings.skipFirstAutoStrip, '$1$2');\n\t\n\t if ((settings.negativePositiveSignPlacement === 's' || settings.currencySymbolPlacement === 's' && settings.negativePositiveSignPlacement !== 'p') && isNegative(s) && s !== '') {\n\t settings.trailingNegative = true;\n\t }\n\t\n\t // Then replace anything after digits\n\t s = s.replace(settings.skipLastAutoStrip, '$1');\n\t\n\t // Then remove any uninteresting characters\n\t s = s.replace(settings.allowedAutoStrip, '');\n\t if (settings.decimalCharacterAlternative) {\n\t s = s.replace(settings.decimalCharacterAlternative, settings.decimalCharacter);\n\t }\n\t\n\t // Get only number string\n\t var m = s.match(settings.numRegAutoStrip);\n\t s = m ? [m[1], m[2], m[3]].join('') : '';\n\t\n\t if (settings.leadingZero === 'allow' || settings.leadingZero === 'keep') {\n\t var nSign = '';\n\t\n\t var _s$split = s.split(settings.decimalCharacter),\n\t _s$split2 = _slicedToArray(_s$split, 2),\n\t integerPart = _s$split2[0],\n\t decimalPart = _s$split2[1];\n\t\n\t var modifiedIntegerPart = integerPart;\n\t if (contains(modifiedIntegerPart, settings.negativeSignCharacter)) {\n\t nSign = settings.negativeSignCharacter;\n\t modifiedIntegerPart = modifiedIntegerPart.replace(settings.negativeSignCharacter, '');\n\t }\n\t\n\t // Strip leading zero on positive value if need\n\t if (nSign === '' && modifiedIntegerPart.length > settings.mIntPos && modifiedIntegerPart.charAt(0) === '0') {\n\t modifiedIntegerPart = modifiedIntegerPart.slice(1);\n\t }\n\t\n\t // Strip leading zero on negative value if need\n\t if (nSign !== '' && modifiedIntegerPart.length > settings.mIntNeg && modifiedIntegerPart.charAt(0) === '0') {\n\t modifiedIntegerPart = modifiedIntegerPart.slice(1);\n\t }\n\t\n\t s = '' + nSign + modifiedIntegerPart + (isUndefined(decimalPart) ? '' : settings.decimalCharacter + decimalPart);\n\t }\n\t\n\t if (leftOrAll && settings.leadingZero === 'deny' || !settings.hasFocus && settings.leadingZero === 'allow') {\n\t s = s.replace(settings.stripReg, '$1$2');\n\t }\n\t\n\t return s;\n\t }\n\t\n\t /**\n\t * Sets or removes brackets on negative values, depending on the focus state.\n\t * The focus state is 'stored' in the settings object under the `settings.hasFocus` attribute.\n\t * //TODO Use another object to keep track of internal data that are not settings\n\t *\n\t * @param {string} s\n\t * @param {object} settings\n\t * @returns {*}\n\t */\n\t function toggleNegativeBracket(s, settings) {\n\t if (settings.currencySymbolPlacement === 'p' && settings.negativePositiveSignPlacement === 'l' || settings.currencySymbolPlacement === 's' && settings.negativePositiveSignPlacement === 'p') {\n\t //TODO Split the first and last bracket only once during the settings initialization\n\t var _settings$negativeBra = settings.negativeBracketsTypeOnBlur.split(','),\n\t _settings$negativeBra2 = _slicedToArray(_settings$negativeBra, 2),\n\t firstBracket = _settings$negativeBra2[0],\n\t lastBracket = _settings$negativeBra2[1];\n\t\n\t if (!settings.hasFocus) {\n\t // Add brackets\n\t s = s.replace(settings.negativeSignCharacter, '');\n\t s = firstBracket + s + lastBracket;\n\t } else if (settings.hasFocus && s.charAt(0) === firstBracket) {\n\t // Remove brackets\n\t //TODO Quid if the negative sign is not on the left, shouldn't we replace the '-' sign at the right place?\n\t s = s.replace(firstBracket, settings.negativeSignCharacter);\n\t s = s.replace(lastBracket, '');\n\t }\n\t }\n\t\n\t return s;\n\t }\n\t\n\t /**\n\t * Return a number as a numeric string that can be typecast to a Number that Javascript will understand.\n\t *\n\t * This function return the given string by stripping the currency sign (currencySymbol), the grouping separators (digitalGroupSpacing) and by replacing the decimal character (decimalCharacter) by a dot.\n\t * Lastly, it also put the negative sign back to its normal position if needed.\n\t *\n\t * @param {string} s\n\t * @param {object} settings\n\t * @returns {string|void|XML|*}\n\t */\n\t function convertToNumericString(s, settings) {\n\t // Remove the currency symbol\n\t s = s.replace(settings.currencySymbol, '');\n\t\n\t // Remove the grouping separators (thousands separators usually)\n\t s = s.replace(settings.digitGroupSeparator, '');\n\t\n\t // Replace the decimal character by a dot\n\t if (settings.decimalCharacter !== '.') {\n\t s = s.replace(settings.decimalCharacter, '.');\n\t }\n\t\n\t // Move the trailing negative sign to the right position, if any\n\t if (isNegative(s) && s.lastIndexOf('-') === s.length - 1) {\n\t s = s.replace('-', '');\n\t s = '-' + s;\n\t }\n\t\n\t // Convert any arabic numbers to latin ones\n\t var temp = arabicToLatinNumbers(s, true, false, false);\n\t if (!isNaN(temp)) {\n\t s = temp.toString();\n\t }\n\t\n\t return s;\n\t }\n\t\n\t /**\n\t * Converts the ISO numeric string to the locale decimal and minus sign placement.\n\t * See the \"outputFormat\" option definition for more details.\n\t *\n\t * @param {string|null} value\n\t * @param {string} locale\n\t * @returns {*}\n\t */\n\t function toLocale(value, locale) {\n\t if (isNull(locale) || locale === 'string') {\n\t return value;\n\t }\n\t\n\t var result = void 0;\n\t switch (locale) {\n\t case 'number':\n\t result = Number(value);\n\t break;\n\t case '.-':\n\t result = isNegative(value) ? value.replace('-', '') + '-' : value;\n\t break;\n\t case ',':\n\t case '-,':\n\t result = value.replace('.', ',');\n\t break;\n\t case ',-':\n\t result = value.replace('.', ',');\n\t result = isNegative(result) ? result.replace('-', '') + '-' : result;\n\t break;\n\t // The default case\n\t case '.':\n\t case '-.':\n\t result = value;\n\t break;\n\t default:\n\t throwError('The given outputFormat [' + locale + '] option is not recognized.');\n\t }\n\t\n\t return result;\n\t }\n\t\n\t /**\n\t * Modify the negative sign and the decimal character of the given string value to an hyphen (-) and a dot (.) in order to make that value 'typecastable' to a real number.\n\t *\n\t * @param {string} s\n\t * @param {object} settings\n\t * @returns {string}\n\t */\n\t function modifyNegativeSignAndDecimalCharacterForRawValue(s, settings) {\n\t if (settings.decimalCharacter !== '.') {\n\t s = s.replace(settings.decimalCharacter, '.');\n\t }\n\t if (settings.negativeSignCharacter !== '-' && settings.negativeSignCharacter !== '') {\n\t s = s.replace(settings.negativeSignCharacter, '-');\n\t }\n\t if (!s.match(/\\d/)) {\n\t // The default value returned by `get` is not formatted with decimals\n\t s += '0';\n\t }\n\t\n\t return s;\n\t }\n\t\n\t /**\n\t * Modify the negative sign and the decimal character to use those defined in the settings.\n\t *\n\t * @param {string} s\n\t * @param {object} settings\n\t * @returns {string}\n\t */\n\t function modifyNegativeSignAndDecimalCharacterForFormattedValue(s, settings) {\n\t if (settings.negativeSignCharacter !== '-' && settings.negativeSignCharacter !== '') {\n\t s = s.replace('-', settings.negativeSignCharacter);\n\t }\n\t if (settings.decimalCharacter !== '.') {\n\t s = s.replace('.', settings.decimalCharacter);\n\t }\n\t\n\t return s;\n\t }\n\t\n\t /**\n\t * Private function to check for empty value\n\t * //TODO Modify this function so that it return either TRUE or FALSE if the value is empty. Then create another function to return the input value if it's not empty.\n\t *\n\t * @param {string} inputValue\n\t * @param {object} settings\n\t * @param {boolean} signOnEmpty\n\t * @returns {*}\n\t */\n\t function checkEmpty(inputValue, settings, signOnEmpty) {\n\t if (inputValue === '' || inputValue === settings.negativeSignCharacter) {\n\t if (settings.emptyInputBehavior === 'always' || signOnEmpty) {\n\t return settings.negativePositiveSignPlacement === 'l' ? inputValue + settings.currencySymbol + settings.suffixText : settings.currencySymbol + inputValue + settings.suffixText;\n\t }\n\t\n\t return inputValue;\n\t }\n\t\n\t return null;\n\t }\n\t\n\t /**\n\t * Modify the input value by adding the group separators, as defined in the settings.\n\t *\n\t * @param {string} inputValue\n\t * @param {object} settings\n\t * @returns {*}\n\t */\n\t function addGroupSeparators(inputValue, settings) {\n\t if (settings.strip) {\n\t inputValue = stripAllNonNumberCharacters(inputValue, settings, false);\n\t }\n\t\n\t //TODO This function `addGroupSeparators()` add group separators. Adding the negative sign as well is out of its scope. Move that to another function.\n\t if (settings.trailingNegative && !isNegative(inputValue)) {\n\t inputValue = '-' + inputValue;\n\t }\n\t\n\t var empty = checkEmpty(inputValue, settings, true);\n\t var isValueNegative = isNegative(inputValue);\n\t var isZero = isZeroOrHasNoValue(inputValue);\n\t if (isValueNegative) {\n\t inputValue = inputValue.replace('-', '');\n\t }\n\t\n\t if (!isNull(empty)) {\n\t return empty;\n\t }\n\t\n\t settings.digitalGroupSpacing = settings.digitalGroupSpacing.toString();\n\t var digitalGroup = void 0;\n\t switch (settings.digitalGroupSpacing) {\n\t case '2':\n\t digitalGroup = /(\\d)((\\d)(\\d{2}?)+)$/;\n\t break;\n\t case '2s':\n\t digitalGroup = /(\\d)((?:\\d{2}){0,2}\\d{3}(?:(?:\\d{2}){2}\\d{3})*?)$/;\n\t break;\n\t case '4':\n\t digitalGroup = /(\\d)((\\d{4}?)+)$/;\n\t break;\n\t default:\n\t digitalGroup = /(\\d)((\\d{3}?)+)$/;\n\t }\n\t\n\t // Splits the string at the decimal string\n\t\n\t var _inputValue$split = inputValue.split(settings.decimalCharacter),\n\t _inputValue$split2 = _slicedToArray(_inputValue$split, 2),\n\t integerPart = _inputValue$split2[0],\n\t decimalPart = _inputValue$split2[1];\n\t\n\t if (settings.decimalCharacterAlternative && isUndefined(decimalPart)) {\n\t var _inputValue$split3 = inputValue.split(settings.decimalCharacterAlternative);\n\t\n\t var _inputValue$split4 = _slicedToArray(_inputValue$split3, 2);\n\t\n\t integerPart = _inputValue$split4[0];\n\t decimalPart = _inputValue$split4[1];\n\t }\n\t\n\t if (settings.digitGroupSeparator !== '') {\n\t // Re-inserts the thousand separator via a regular expression\n\t while (digitalGroup.test(integerPart)) {\n\t integerPart = integerPart.replace(digitalGroup, '$1' + settings.digitGroupSeparator + '$2');\n\t }\n\t }\n\t\n\t if (settings.decimalPlacesOverride !== 0 && !isUndefined(decimalPart)) {\n\t if (decimalPart.length > settings.decimalPlacesOverride) {\n\t decimalPart = decimalPart.substring(0, settings.decimalPlacesOverride);\n\t }\n\t\n\t // Joins the whole number with the decimal value\n\t inputValue = integerPart + settings.decimalCharacter + decimalPart;\n\t } else {\n\t // Otherwise if it's an integer\n\t inputValue = integerPart;\n\t }\n\t\n\t settings.trailingNegative = false;\n\t\n\t if (settings.currencySymbolPlacement === 'p') {\n\t if (isValueNegative) {\n\t switch (settings.negativePositiveSignPlacement) {\n\t case 'l':\n\t inputValue = '' + settings.negativeSignCharacter + settings.currencySymbol + inputValue;\n\t break;\n\t case 'r':\n\t inputValue = '' + settings.currencySymbol + settings.negativeSignCharacter + inputValue;\n\t break;\n\t case 's':\n\t inputValue = '' + settings.currencySymbol + inputValue + settings.negativeSignCharacter;\n\t settings.trailingNegative = true;\n\t break;\n\t default:\n\t //\n\t }\n\t } else if (settings.showPositiveSign && !isZero) {\n\t switch (settings.negativePositiveSignPlacement) {\n\t case 'l':\n\t inputValue = '' + settings.positiveSignCharacter + settings.currencySymbol + inputValue;\n\t break;\n\t case 'r':\n\t inputValue = '' + settings.currencySymbol + settings.positiveSignCharacter + inputValue;\n\t break;\n\t case 's':\n\t inputValue = '' + settings.currencySymbol + inputValue + settings.positiveSignCharacter;\n\t break;\n\t default:\n\t //\n\t }\n\t } else {\n\t inputValue = settings.currencySymbol + inputValue;\n\t }\n\t }\n\t\n\t if (settings.currencySymbolPlacement === 's') {\n\t if (isValueNegative) {\n\t switch (settings.negativePositiveSignPlacement) {\n\t case 'r':\n\t inputValue = '' + inputValue + settings.currencySymbol + settings.negativeSignCharacter;\n\t settings.trailingNegative = true;\n\t break;\n\t case 'l':\n\t inputValue = '' + inputValue + settings.negativeSignCharacter + settings.currencySymbol;\n\t settings.trailingNegative = true;\n\t break;\n\t case 'p':\n\t inputValue = '' + settings.negativeSignCharacter + inputValue + settings.currencySymbol;\n\t break;\n\t default:\n\t //\n\t }\n\t } else if (settings.showPositiveSign && !isZero) {\n\t switch (settings.negativePositiveSignPlacement) {\n\t case 'r':\n\t inputValue = '' + inputValue + settings.currencySymbol + settings.positiveSignCharacter;\n\t break;\n\t case 'l':\n\t inputValue = '' + inputValue + settings.positiveSignCharacter + settings.currencySymbol;\n\t break;\n\t case 'p':\n\t inputValue = '' + settings.positiveSignCharacter + inputValue + settings.currencySymbol;\n\t break;\n\t default:\n\t //\n\t }\n\t } else {\n\t inputValue = inputValue + settings.currencySymbol;\n\t }\n\t }\n\t\n\t // Removes the negative sign and places brackets\n\t if (settings.negativeBracketsTypeOnBlur !== null && (settings.rawValue < 0 || isNegativeStrict(inputValue))) {\n\t inputValue = toggleNegativeBracket(inputValue, settings);\n\t }\n\t\n\t return inputValue + settings.suffixText;\n\t }\n\t\n\t /**\n\t * Truncate not needed zeros\n\t *\n\t * @param {string} roundedInputValue\n\t * @param {int} temporaryDecimalPlacesOverride\n\t * @returns {void|XML|string|*}\n\t */\n\t function truncateZeros(roundedInputValue, temporaryDecimalPlacesOverride) {\n\t var regex = void 0;\n\t switch (temporaryDecimalPlacesOverride) {\n\t case 0:\n\t // Prevents padding - removes trailing zeros until the first significant digit is encountered\n\t regex = /(\\.(?:\\d*[1-9])?)0*$/;\n\t break;\n\t case 1:\n\t // Allows padding when decimalPlacesOverride equals one - leaves one zero trailing the decimal character\n\t regex = /(\\.\\d(?:\\d*[1-9])?)0*$/;\n\t break;\n\t default:\n\t // Removes access zeros to the decimalPlacesOverride length when allowDecimalPadding is set to true\n\t regex = new RegExp('(\\\\.\\\\d{' + temporaryDecimalPlacesOverride + '}(?:\\\\d*[1-9])?)0*');\n\t }\n\t\n\t // If there are no decimal places, we don't need a decimal point at the end\n\t roundedInputValue = roundedInputValue.replace(regex, '$1');\n\t if (temporaryDecimalPlacesOverride === 0) {\n\t roundedInputValue = roundedInputValue.replace(/\\.$/, '');\n\t }\n\t\n\t return roundedInputValue;\n\t }\n\t\n\t /**\n\t * Round the input value using the rounding method defined in the settings.\n\t * This function accepts multiple rounding methods. See the documentation for more details about those.\n\t *\n\t * Note : This is handled as text since JavaScript math function can return inaccurate values.\n\t *\n\t * @param {string} inputValue\n\t * @param {object} settings\n\t * @returns {*}\n\t */\n\t function roundValue(inputValue, settings) {\n\t inputValue = inputValue === '' ? '0' : inputValue.toString();\n\t if (settings.roundingMethod === 'N05' || settings.roundingMethod === 'CHF' || settings.roundingMethod === 'U05' || settings.roundingMethod === 'D05') {\n\t switch (settings.roundingMethod) {\n\t case 'N05':\n\t inputValue = (Math.round(inputValue * 20) / 20).toString();\n\t break;\n\t case 'U05':\n\t inputValue = (Math.ceil(inputValue * 20) / 20).toString();\n\t break;\n\t default:\n\t inputValue = (Math.floor(inputValue * 20) / 20).toString();\n\t }\n\t\n\t var result = void 0;\n\t if (!contains(inputValue, '.')) {\n\t result = inputValue + '.00';\n\t } else if (inputValue.length - inputValue.indexOf('.') < 3) {\n\t result = inputValue + '0';\n\t } else {\n\t result = inputValue;\n\t }\n\t return result;\n\t }\n\t\n\t var ivRounded = '';\n\t var i = 0;\n\t var nSign = '';\n\t var temporaryDecimalPlacesOverride = void 0;\n\t\n\t // sets the truncate zero method\n\t if (settings.allowDecimalPadding) {\n\t temporaryDecimalPlacesOverride = settings.decimalPlacesOverride;\n\t } else {\n\t temporaryDecimalPlacesOverride = 0;\n\t }\n\t\n\t // Checks if the inputValue (input Value) is a negative value\n\t if (isNegativeStrict(inputValue)) {\n\t nSign = '-';\n\t\n\t // Removes the negative sign that will be added back later if required\n\t inputValue = inputValue.replace('-', '');\n\t }\n\t\n\t // Append a zero if the first character is not a digit (then it is likely to be a dot)\n\t if (!inputValue.match(/^\\d/)) {\n\t inputValue = '0' + inputValue;\n\t }\n\t\n\t // Determines if the value is equal to zero. If it is, remove the negative sign\n\t if (Number(inputValue) === 0) {\n\t nSign = '';\n\t }\n\t\n\t // Trims leading zero's as needed\n\t if (Number(inputValue) > 0 && settings.leadingZero !== 'keep' || inputValue.length > 0 && settings.leadingZero === 'allow') {\n\t inputValue = inputValue.replace(/^0*(\\d)/, '$1');\n\t }\n\t\n\t var dPos = inputValue.lastIndexOf('.');\n\t var inputValueHasADot = dPos === -1;\n\t\n\t // Virtual decimal position\n\t var vdPos = inputValueHasADot ? inputValue.length - 1 : dPos;\n\t\n\t // Checks decimal places to determine if rounding is required :\n\t // Check if no rounding is required\n\t var cDec = inputValue.length - 1 - vdPos;\n\t\n\t if (cDec <= settings.decimalPlacesOverride) {\n\t // Check if we need to pad with zeros\n\t ivRounded = inputValue;\n\t if (cDec < temporaryDecimalPlacesOverride) {\n\t if (inputValueHasADot) {\n\t ivRounded += settings.decimalCharacter;\n\t }\n\t\n\t var zeros = '000000';\n\t while (cDec < temporaryDecimalPlacesOverride) {\n\t zeros = zeros.substring(0, temporaryDecimalPlacesOverride - cDec);\n\t ivRounded += zeros;\n\t cDec += zeros.length;\n\t }\n\t } else if (cDec > temporaryDecimalPlacesOverride) {\n\t ivRounded = truncateZeros(ivRounded, temporaryDecimalPlacesOverride);\n\t } else if (cDec === 0 && temporaryDecimalPlacesOverride === 0) {\n\t ivRounded = ivRounded.replace(/\\.$/, '');\n\t }\n\t\n\t return Number(ivRounded) === 0 ? ivRounded : nSign + ivRounded;\n\t }\n\t\n\t // Rounded length of the string after rounding\n\t var rLength = void 0;\n\t if (inputValueHasADot) {\n\t rLength = settings.decimalPlacesOverride - 1;\n\t } else {\n\t rLength = settings.decimalPlacesOverride + dPos;\n\t }\n\t\n\t var tRound = Number(inputValue.charAt(rLength + 1));\n\t var odd = inputValue.charAt(rLength) === '.' ? inputValue.charAt(rLength - 1) % 2 : inputValue.charAt(rLength) % 2;\n\t var ivArray = inputValue.substring(0, rLength + 1).split('');\n\t\n\t if (tRound > 4 && settings.roundingMethod === 'S' || // Round half up symmetric\n\t tRound > 4 && settings.roundingMethod === 'A' && nSign === '' || // Round half up asymmetric positive values\n\t tRound > 5 && settings.roundingMethod === 'A' && nSign === '-' || // Round half up asymmetric negative values\n\t tRound > 5 && settings.roundingMethod === 's' || // Round half down symmetric\n\t tRound > 5 && settings.roundingMethod === 'a' && nSign === '' || // Round half down asymmetric positive values\n\t tRound > 4 && settings.roundingMethod === 'a' && nSign === '-' || // Round half down asymmetric negative values\n\t tRound > 5 && settings.roundingMethod === 'B' || // Round half even \"Banker's Rounding\"\n\t tRound === 5 && settings.roundingMethod === 'B' && odd === 1 || // Round half even \"Banker's Rounding\"\n\t tRound > 0 && settings.roundingMethod === 'C' && nSign === '' || // Round to ceiling toward positive infinite\n\t tRound > 0 && settings.roundingMethod === 'F' && nSign === '-' || // Round to floor toward negative infinite\n\t tRound > 0 && settings.roundingMethod === 'U') {\n\t // Round up away from zero\n\t // Round up the last digit if required, and continue until no more 9's are found\n\t for (i = ivArray.length - 1; i >= 0; i -= 1) {\n\t if (ivArray[i] !== '.') {\n\t ivArray[i] = +ivArray[i] + 1;\n\t if (ivArray[i] < 10) {\n\t break;\n\t }\n\t\n\t if (i > 0) {\n\t ivArray[i] = '0';\n\t }\n\t }\n\t }\n\t }\n\t\n\t // Reconstruct the string, converting any 10's to 0's\n\t ivArray = ivArray.slice(0, rLength + 1);\n\t\n\t // Return the rounded value\n\t ivRounded = truncateZeros(ivArray.join(''), temporaryDecimalPlacesOverride);\n\t\n\t return Number(ivRounded) === 0 ? ivRounded : nSign + ivRounded;\n\t }\n\t\n\t /**\n\t * Truncates the decimal part of a number.\n\t *\n\t * @param {string} s\n\t * @param {object} settings\n\t * @param {boolean} isPaste\n\t * @returns {*}\n\t */\n\t function truncateDecimal(s, settings, isPaste) {\n\t s = isPaste ? roundValue(s, settings) : s;\n\t\n\t if (settings.decimalCharacter && settings.decimalPlacesOverride) {\n\t var _s$split3 = s.split(settings.decimalCharacter),\n\t _s$split4 = _slicedToArray(_s$split3, 2),\n\t integerPart = _s$split4[0],\n\t decimalPart = _s$split4[1];\n\t\n\t // truncate decimal part to satisfying length since we would round it anyway\n\t\n\t\n\t if (decimalPart && decimalPart.length > settings.decimalPlacesOverride) {\n\t if (settings.decimalPlacesOverride > 0) {\n\t var modifiedDecimalPart = decimalPart.substring(0, settings.decimalPlacesOverride);\n\t s = '' + integerPart + settings.decimalCharacter + modifiedDecimalPart;\n\t } else {\n\t s = integerPart;\n\t }\n\t }\n\t }\n\t\n\t return s;\n\t }\n\t\n\t /**\n\t * Function to parse minimumValue, maximumValue & the input value to prepare for testing to determine if the value falls within the min / max range.\n\t * Return an object example: minimumValue: \"999999999999999.99\" returns the following \"{s: -1, e: 12, c: Array[15]}\".\n\t *\n\t * This function is adapted from Big.js https://github.com/MikeMcl/big.js/. Many thanks to Mike.\n\t *\n\t * @param {number|string} n A numeric value.\n\t * @returns {{}}\n\t */\n\t function parseStr(n) {\n\t var x = {}; // A Big number instance.\n\t var e = void 0;\n\t var i = void 0;\n\t var nL = void 0;\n\t var j = void 0;\n\t\n\t // Minus zero?\n\t if (n === 0 && 1 / n < 0) {\n\t n = '-0';\n\t }\n\t\n\t // Determine sign. 1 positive, -1 negative\n\t n = n.toString();\n\t if (isNegativeStrict(n)) {\n\t n = n.slice(1);\n\t x.s = -1;\n\t } else {\n\t x.s = 1;\n\t }\n\t\n\t // Decimal point?\n\t e = n.indexOf('.');\n\t if (e > -1) {\n\t n = n.replace('.', '');\n\t }\n\t\n\t // length of string if no decimal character\n\t if (e < 0) {\n\t // Integer\n\t e = n.length;\n\t }\n\t\n\t // Determine leading zeros\n\t i = n.search(/[1-9]/i) === -1 ? n.length : n.search(/[1-9]/i);\n\t nL = n.length;\n\t if (i === nL) {\n\t // Zero\n\t x.e = 0;\n\t x.c = [0];\n\t } else {\n\t // Determine trailing zeros\n\t for (j = nL - 1; n.charAt(j) === '0'; j -= 1) {\n\t nL -= 1;\n\t }\n\t nL -= 1;\n\t\n\t // Decimal location\n\t x.e = e - i - 1;\n\t x.c = [];\n\t\n\t // Convert string to array of digits without leading/trailing zeros\n\t for (e = 0; i <= nL; i += 1) {\n\t x.c[e] = +n.charAt(i);\n\t e += 1;\n\t }\n\t }\n\t\n\t return x;\n\t }\n\t\n\t /**\n\t * Function to test if the input value falls with the Min / Max settings.\n\t * This uses the parsed strings for the above parseStr function.\n\t *\n\t * This function is adapted from Big.js https://github.com/MikeMcl/big.js/. Many thanks to Mike.\n\t *\n\t * @param {object} y Big number instance\n\t * @param {object} x Big number instance\n\t * @returns {*}\n\t */\n\t function testMinMax(y, x) {\n\t var xc = x.c;\n\t var yc = y.c;\n\t var i = x.s;\n\t var j = y.s;\n\t var k = x.e;\n\t var l = y.e;\n\t\n\t // Either zero?\n\t if (!xc[0] || !yc[0]) {\n\t var _result = void 0;\n\t if (!xc[0]) {\n\t _result = !yc[0] ? 0 : -j;\n\t } else {\n\t _result = i;\n\t }\n\t return _result;\n\t }\n\t\n\t // Signs differ?\n\t if (i !== j) {\n\t return i;\n\t }\n\t var xNeg = i < 0;\n\t\n\t // Compare exponents\n\t if (k !== l) {\n\t return k > l ^ xNeg ? 1 : -1;\n\t }\n\t i = -1;\n\t k = xc.length;\n\t l = yc.length;\n\t j = k < l ? k : l;\n\t\n\t // Compare digit by digit\n\t for (i += 1; i < j; i += 1) {\n\t if (xc[i] !== yc[i]) {\n\t return xc[i] > yc[i] ^ xNeg ? 1 : -1;\n\t }\n\t }\n\t\n\t // Compare lengths\n\t var result = void 0;\n\t if (k === l) {\n\t result = 0;\n\t } else {\n\t result = k > l ^ xNeg ? 1 : -1;\n\t }\n\t\n\t return result;\n\t }\n\t\n\t /**\n\t * Check that the number satisfy the format conditions\n\t * and lays between settings.minimumValue and settings.maximumValue\n\t * and the string length does not exceed the digits in settings.minimumValue and settings.maximumValue\n\t *\n\t * @param {string} s\n\t * @param {object} settings\n\t * @returns {*}\n\t */\n\t function checkIfInRangeWithOverrideOption(s, settings) {\n\t s = s.toString();\n\t s = s.replace(',', '.');\n\t var minParse = parseStr(settings.minimumValue);\n\t var maxParse = parseStr(settings.maximumValue);\n\t var valParse = parseStr(s);\n\t\n\t var result = void 0;\n\t switch (settings.overrideMinMaxLimits) {\n\t case 'floor':\n\t result = [testMinMax(minParse, valParse) > -1, true];\n\t break;\n\t case 'ceiling':\n\t result = [true, testMinMax(maxParse, valParse) < 1];\n\t break;\n\t case 'ignore':\n\t result = [true, true];\n\t break;\n\t default:\n\t result = [testMinMax(minParse, valParse) > -1, testMinMax(maxParse, valParse) < 1];\n\t }\n\t\n\t return result;\n\t }\n\t\n\t /**\n\t * Thanks to Anthony & Evan C\n\t *\n\t * @param {Element|string} element\n\t * @returns {*|jQuery|HTMLElement}\n\t */\n\t function getCurrentElement(element) {\n\t /*\n\t * If the parameter is a string (and therefore is a CSS selector), then we need to modify this string in order\n\t * for jQuery to be able to parse the selector correctly.\n\t * cf. http://learn.jquery.com/using-jquery-core/faq/how-do-i-select-an-element-by-an-id-that-has-characters-used-in-css-notation/\n\t */\n\t if (isString(element)) {\n\t //TODO This block is apparently never entered. We should remove it after making sure that's 100% the case\n\t element = '#' + element.replace(/(:|\\.|\\[|]|,|=)/g, '\\\\$1');\n\t }\n\t\n\t return $(element);\n\t }\n\t\n\t /**\n\t * Function that attach the autoNumeric field properties to the DOM element via an AutoNumericHolder object.\n\t *\n\t * @param {object} $this jQuery-selected DOM element\n\t * @param {object} settings\n\t * @param {boolean} update\n\t * @returns {*}\n\t */\n\t function getAutoNumericHolder($this, settings) {\n\t var update = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;\n\t\n\t var data = $this.data('autoNumeric');\n\t if (!data) {\n\t data = {};\n\t $this.data('autoNumeric', data);\n\t }\n\t\n\t var holder = data.holder;\n\t if (update || isUndefined(holder) && settings) {\n\t holder = new AutoNumericHolder($this.get(0), settings);\n\t data.holder = holder;\n\t }\n\t\n\t return holder;\n\t }\n\t\n\t /**\n\t * Original settings saved for use when decimalPlacesShownOnFocus & noSeparatorOnFocus options are being used.\n\t * Those original settings are used exclusively in the `focusin` and `focusout` event handlers.\n\t *\n\t * @param {object} settings\n\t */\n\t function keepAnOriginalSettingsCopy(settings) {\n\t //TODO Rename the old option names to the new ones\n\t settings.oDec = settings.decimalPlacesOverride;\n\t settings.oPad = settings.allowDecimalPadding;\n\t settings.oBracket = settings.negativeBracketsTypeOnBlur;\n\t settings.oSep = settings.digitGroupSeparator;\n\t settings.oSign = settings.currencySymbol;\n\t settings.oSuffix = settings.suffixText;\n\t }\n\t\n\t /**\n\t * Original settings saved for use when `decimalPlacesShownOnFocus` & `noSeparatorOnFocus` options are being used.\n\t * This is taken from Quirksmode.\n\t *\n\t * @param {string} name\n\t * @returns {*}\n\t */\n\t function readCookie(name) {\n\t var nameEQ = name + '=';\n\t var ca = document.cookie.split(';');\n\t var c = '';\n\t for (var i = 0; i < ca.length; i += 1) {\n\t c = ca[i];\n\t while (c.charAt(0) === ' ') {\n\t c = c.substring(1, c.length);\n\t }\n\t if (c.indexOf(nameEQ) === 0) {\n\t return c.substring(nameEQ.length, c.length);\n\t }\n\t }\n\t\n\t return null;\n\t }\n\t\n\t /**\n\t * Test if sessionStorage is supported.\n\t * This is taken from Modernizr.\n\t *\n\t * @returns {boolean}\n\t */\n\t function storageTest() {\n\t var mod = 'modernizr';\n\t try {\n\t sessionStorage.setItem(mod, mod);\n\t sessionStorage.removeItem(mod);\n\t return true;\n\t } catch (e) {\n\t return false;\n\t }\n\t }\n\t\n\t /**\n\t * properly formats the string to a numeric when leadingZero does not 'keep'.\n\t *\n\t * @param {string} value\n\t * @param {object} settings\n\t * @returns {string}\n\t */\n\t function cleanLeadingTrailingZeros(value, settings) {\n\t // Return the empty string is the value is already empty. This prevent converting that value to '0'.\n\t if (value === '') {\n\t return '';\n\t }\n\t\n\t // Return '0' if the value is zero\n\t if (Number(value) === 0 && settings.leadingZero !== 'keep') {\n\t return '0';\n\t }\n\t\n\t if (settings.leadingZero !== 'keep') {\n\t // Trim leading zero's - leaves one zero to the left of the decimal point\n\t value = value.replace(/^(-)?0+(?=\\d)/g, '$1');\n\t\n\t //TODO remove this from that function and use `trimPaddedZerosFromDecimalPlaces()` instead. Also create a new `trailingZero` option.\n\t if (contains(value, '.')) {\n\t // Trims trailing zeros after the decimal point\n\t value = value.replace(/(\\.[0-9]*?)0+$/, '$1');\n\t }\n\t }\n\t // Strips trailing decimal point\n\t value = value.replace(/\\.$/, '');\n\t\n\t return value;\n\t }\n\t\n\t /**\n\t * Remove the trailing zeros in the decimal part of a number.\n\t *\n\t * @param {string} numericString\n\t * @returns {*}\n\t */\n\t function trimPaddedZerosFromDecimalPlaces(numericString) {\n\t var _numericString$split = numericString.split('.'),\n\t _numericString$split2 = _slicedToArray(_numericString$split, 2),\n\t integerPart = _numericString$split2[0],\n\t decimalPart = _numericString$split2[1];\n\t\n\t if (isUndefinedOrNullOrEmpty(decimalPart)) {\n\t return integerPart;\n\t }\n\t\n\t var trimmedDecimalPart = decimalPart.replace(/0+$/g, '');\n\t\n\t var result = void 0;\n\t if (trimmedDecimalPart === '') {\n\t result = integerPart;\n\t } else {\n\t result = integerPart + '.' + trimmedDecimalPart;\n\t }\n\t\n\t return result;\n\t }\n\t\n\t /**\n\t * Creates or removes sessionStorage or cookie depending on what the browser is supporting.\n\t *\n\t * @param {Element|EventTarget} element\n\t * @param {object} settings\n\t * @param {string} action\n\t * @returns {*}\n\t */\n\t function saveValueToPersistentStorage(element, settings, action) {\n\t if (settings.saveValueToSessionStorage) {\n\t var storedName = element.name !== '' && !isUndefined(element.name) ? 'AUTO_' + decodeURIComponent(element.name) : 'AUTO_' + element.id;\n\t var date = void 0;\n\t var expires = void 0;\n\t\n\t // Sets cookie for browser that do not support sessionStorage IE 6 & IE 7\n\t if (storageTest() === false) {\n\t switch (action) {\n\t case 'set':\n\t document.cookie = storedName + '=' + settings.rawValue + '; expires= ; path=/';\n\t break;\n\t case 'wipe':\n\t date = new Date();\n\t date.setTime(date.getTime() + -1 * 24 * 60 * 60 * 1000);\n\t expires = '; expires=' + date.toUTCString(); // Note : `toGMTString()` has been deprecated (cf. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toGMTString)\n\t document.cookie = storedName + '=\\'\\' ;' + expires + '; path=/';\n\t break;\n\t case 'get':\n\t return readCookie(storedName);\n\t }\n\t } else {\n\t switch (action) {\n\t case 'set':\n\t sessionStorage.setItem(storedName, settings.rawValue);\n\t break;\n\t case 'wipe':\n\t sessionStorage.removeItem(storedName);\n\t break;\n\t case 'get':\n\t return sessionStorage.getItem(storedName);\n\t }\n\t }\n\t }\n\t }\n\t\n\t /**\n\t * Holder object for field properties\n\t */\n\t\n\t var AutoNumericHolder = function () {\n\t /**\n\t * Class constructor\n\t *\n\t * @param {HTMLElement} that - A reference to the current DOM element\n\t * @param {object} settings\n\t */\n\t function AutoNumericHolder(that, settings) {\n\t _classCallCheck(this, AutoNumericHolder);\n\t\n\t this.settings = settings;\n\t this.that = that;\n\t this.$that = $(that);\n\t this.formatted = false;\n\t this.settingsClone = settings;\n\t this.value = that.value;\n\t }\n\t\n\t /**\n\t * Update the value and the selection values inside the AutoNumericHolder object.\n\t * This keeps tracks of the input value, as well as the current selection.\n\t * This also resets the 'processed' and 'formatted' state.\n\t *\n\t * Note : Those two can change between the keydown, keypress and keyup events, that's why\n\t * this function is called on each event handler.\n\t *\n\t * @private\n\t */\n\t\n\t\n\t _createClass(AutoNumericHolder, [{\n\t key: '_updateAutoNumericHolderProperties',\n\t value: function _updateAutoNumericHolderProperties() {\n\t this.value = this.that.value;\n\t this.selection = getElementSelection(this.that);\n\t this.processed = false;\n\t this.formatted = false;\n\t }\n\t\n\t /**\n\t * Update the keycode of the key that triggered the given event.\n\t * Note : e.which is sometimes different than e.keyCode during the keypress event, when entering a printable character key (ie. 't'). `e.which` equals 0 for non-printable characters.\n\t *\n\t * //TODO Switch to the non-deprecated e.key attribute, instead of inconsistant e.which and e.keyCode.\n\t * e.key describe the key name used to trigger the event.\n\t * e.keyCode being deprecated : https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode\n\t * How e.key works : https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key\n\t * The key list is described here\n\t * @link https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values\n\t *\n\t * @param {Event} e\n\t * @private\n\t */\n\t\n\t }, {\n\t key: '_updateAutoNumericHolderEventKeycode',\n\t value: function _updateAutoNumericHolderEventKeycode(e) {\n\t // Note: the keypress event overwrites meaningful value of e.keyCode, hence we do not update that value on 'keypress'\n\t this.eventKeyCode = keyCodeNumber(e);\n\t }\n\t\n\t /**\n\t * Set the text selection inside the input with the given start and end position.\n\t *\n\t * @param {int} start\n\t * @param {int} end\n\t * @param {undefined|boolean} setReal\n\t * @private\n\t */\n\t\n\t }, {\n\t key: '_setSelection',\n\t value: function _setSelection(start, end, setReal) {\n\t //TODO Modify setReal to be more explicit (and a boolean)\n\t start = Math.max(start, 0);\n\t end = Math.min(end, this.that.value.length); //TODO Replace `this.that.value.length` with `this.value.length`\n\t this.selection = {\n\t start: start,\n\t end: end,\n\t length: end - start\n\t };\n\t\n\t if (isUndefined(setReal) || setReal) {\n\t setElementSelection(this.that, start, end);\n\t }\n\t }\n\t\n\t /**\n\t * Set the caret position inside the input at the given position.\n\t *\n\t * @param {int} pos\n\t * @param {undefined|boolean} setReal\n\t * @private\n\t */\n\t\n\t }, {\n\t key: '_setCaretPosition',\n\t value: function _setCaretPosition(pos, setReal) {\n\t //TODO Modify setReal to be more explicit (and a boolean)\n\t this._setSelection(pos, pos, setReal);\n\t }\n\t\n\t /**\n\t * Return an array containing the string parts located on the left and right side of the caret or selection.\n\t * Those parts are left 'untouched', ie. formatted by autoNumeric.\n\t *\n\t * @returns {[string, string]} The parts on the left and right of the caret or selection\n\t * @private\n\t */\n\t\n\t }, {\n\t key: '_getLeftAndRightPartAroundTheSelection',\n\t value: function _getLeftAndRightPartAroundTheSelection() {\n\t var value = this.value;\n\t var left = value.substring(0, this.selection.start);\n\t var right = value.substring(this.selection.end, value.length);\n\t\n\t return [left, right];\n\t }\n\t\n\t /**\n\t * Return an array containing the string parts located on the left and right side of the caret or selection.\n\t * Those parts are unformatted (stripped) of any non-numbers characters.\n\t *\n\t * @returns {[string, string]} The parts on the left and right of the caret or selection, unformatted.\n\t * @private\n\t */\n\t\n\t }, {\n\t key: '_getUnformattedLeftAndRightPartAroundTheSelection',\n\t value: function _getUnformattedLeftAndRightPartAroundTheSelection() {\n\t var settingsClone = this.settingsClone;\n\t\n\t var _getLeftAndRightPartA = this._getLeftAndRightPartAroundTheSelection(),\n\t _getLeftAndRightPartA2 = _slicedToArray(_getLeftAndRightPartA, 2),\n\t left = _getLeftAndRightPartA2[0],\n\t right = _getLeftAndRightPartA2[1];\n\t\n\t if (left === '' && right === '') {\n\t settingsClone.trailingNegative = false;\n\t }\n\t // if changing the sign and left is equal to the number zero - prevents stripping the leading zeros\n\t var stripZeros = true;\n\t if (this.eventKeyCode === keyCode.Hyphen && Number(left) === 0) {\n\t stripZeros = false;\n\t }\n\t left = stripAllNonNumberCharacters(left, this.settingsClone, stripZeros);\n\t right = stripAllNonNumberCharacters(right, this.settingsClone, false);\n\t\n\t if (settingsClone.trailingNegative && !isNegative(left)) {\n\t left = '-' + left;\n\t right = right === '-' ? '' : right;\n\t settingsClone.trailingNegative = false;\n\t }\n\t\n\t return [left, right];\n\t }\n\t\n\t /**\n\t * Strip parts from excess characters and leading zeros.\n\t *\n\t * @param {string} left\n\t * @param {string} right\n\t * @returns {[*,*]}\n\t * @private\n\t */\n\t\n\t }, {\n\t key: '_normalizeParts',\n\t value: function _normalizeParts(left, right) {\n\t var settingsClone = this.settingsClone;\n\t\n\t // if changing the sign and left is equal to the number zero - prevents stripping the leading zeros\n\t var stripZeros = true;\n\t if (this.eventKeyCode === keyCode.Hyphen && Number(left) === 0) {\n\t stripZeros = false;\n\t }\n\t left = stripAllNonNumberCharacters(left, settingsClone, stripZeros);\n\t\n\t // If right is not empty and first character is not decimalCharacter\n\t right = stripAllNonNumberCharacters(right, settingsClone, false);\n\t\n\t // Prevents multiple leading zeros from being entered\n\t if (settingsClone.leadingZero === 'deny' && (this.eventKeyCode === keyCode.num0 || this.eventKeyCode === keyCode.numpad0) && Number(left) === 0 && !contains(left, settingsClone.decimalCharacter) && right !== '') {\n\t left = left.substring(0, left.length - 1);\n\t }\n\t\n\t if (settingsClone.trailingNegative && !isNegative(left)) {\n\t left = '-' + left;\n\t settingsClone.trailingNegative = false;\n\t }\n\t\n\t // Insert zero if has leading dot\n\t this.newValue = left + right;\n\t if (settingsClone.decimalCharacter) {\n\t var m = this.newValue.match(new RegExp('^' + settingsClone.aNegRegAutoStrip + '\\\\' + settingsClone.decimalCharacter));\n\t if (m) {\n\t left = left.replace(m[1], m[1] + '0');\n\t this.newValue = left + right;\n\t }\n\t }\n\t\n\t return [left, right];\n\t }\n\t\n\t /**\n\t * Set part of number to value while keeping the cursor position. //TODO What about the cursor selection?\n\t *\n\t * @param {string} left\n\t * @param {string} right\n\t * @param {boolean} isPaste\n\t * @returns {boolean}\n\t * @private\n\t */\n\t\n\t }, {\n\t key: '_setValueParts',\n\t value: function _setValueParts(left, right) {\n\t var isPaste = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;\n\t\n\t var settingsClone = this.settingsClone;\n\t var parts = this._normalizeParts(left, right);\n\t\n\t var _checkIfInRangeWithOv = checkIfInRangeWithOverrideOption(this.newValue, settingsClone),\n\t _checkIfInRangeWithOv2 = _slicedToArray(_checkIfInRangeWithOv, 2),\n\t minTest = _checkIfInRangeWithOv2[0],\n\t maxTest = _checkIfInRangeWithOv2[1];\n\t\n\t var position = parts[0].length;\n\t this.newValue = parts.join('');\n\t\n\t if (minTest && maxTest) {\n\t this.newValue = truncateDecimal(this.newValue, settingsClone, isPaste);\n\t //TODO Check if we need to replace the hard-coded ',' with settings.decimalCharacter\n\t var testValue = contains(this.newValue, ',') ? this.newValue.replace(',', '.') : this.newValue;\n\t if (testValue === '' || testValue === settingsClone.negativeSignCharacter) {\n\t settingsClone.rawValue = settingsClone.emptyInputBehavior === 'zero' ? '0' : '';\n\t } else {\n\t settingsClone.rawValue = cleanLeadingTrailingZeros(testValue, settingsClone);\n\t }\n\t\n\t if (position > this.newValue.length) {\n\t position = this.newValue.length;\n\t }\n\t\n\t // Make sure when the user enter a '0' on the far left with a leading zero option set to 'deny', that the caret does not moves since the input is dropped (fix issue #283)\n\t if (position === 1 && parts[0] === '0' && settingsClone.leadingZero === 'deny') {\n\t // If the user enter `0`, then the caret is put on the right side of it (Fix issue #299)\n\t if (parts[1] === '' || parts[0] === '0' && parts[1] !== '') {\n\t position = 1;\n\t } else {\n\t position = 0;\n\t }\n\t }\n\t\n\t this.value = this.newValue;\n\t this._setCaretPosition(position, false);\n\t\n\t return true;\n\t }\n\t\n\t if (!minTest) {\n\t this.$that.trigger('autoNumeric:minExceeded');\n\t } else if (!maxTest) {\n\t this.$that.trigger('autoNumeric:maxExceeded');\n\t }\n\t\n\t return false;\n\t }\n\t\n\t /**\n\t * Helper function for `_expandSelectionOnSign()`.\n\t *\n\t * @returns {*} Sign position of a formatted value\n\t * @private\n\t */\n\t\n\t }, {\n\t key: '_getSignPosition',\n\t value: function _getSignPosition() {\n\t var settingsClone = this.settingsClone;\n\t var currencySymbol = settingsClone.currencySymbol;\n\t var that = this.that;\n\t\n\t if (currencySymbol) {\n\t var currencySymbolLen = currencySymbol.length;\n\t if (settingsClone.currencySymbolPlacement === 'p') {\n\t var hasNeg = settingsClone.negativeSignCharacter && that.value && that.value.charAt(0) === settingsClone.negativeSignCharacter;\n\t return hasNeg ? [1, currencySymbolLen + 1] : [0, currencySymbolLen];\n\t }\n\t var valueLen = that.value.length;\n\t return [valueLen - currencySymbolLen, valueLen];\n\t }\n\t\n\t return [1000, -1];\n\t }\n\t\n\t /**\n\t * Expands selection to cover whole sign\n\t * Prevents partial deletion/copying/overwriting of a sign\n\t *\n\t * @param {undefined|boolean} setReal\n\t * @private\n\t */\n\t\n\t }, {\n\t key: '_expandSelectionOnSign',\n\t value: function _expandSelectionOnSign(setReal) {\n\t //TODO Modify setReal to be more explicit (and a boolean only)\n\t //TODO Use array destructuring here to set signPosition to more explicit variables\n\t var signPosition = this._getSignPosition();\n\t var selection = this.selection;\n\t\n\t // If selection catches something except sign and catches only space from sign\n\t if (selection.start < signPosition[1] && selection.end > signPosition[0]) {\n\t // Then select without empty space\n\t if ((selection.start < signPosition[0] || selection.end > signPosition[1]) && this.value.substring(Math.max(selection.start, signPosition[0]), Math.min(selection.end, signPosition[1])).match(/^\\s*$/)) {\n\t if (selection.start < signPosition[0]) {\n\t this._setSelection(selection.start, signPosition[0], setReal);\n\t } else {\n\t this._setSelection(signPosition[1], selection.end, setReal);\n\t }\n\t } else {\n\t // Else select with whole sign\n\t this._setSelection(Math.min(selection.start, signPosition[0]), Math.max(selection.end, signPosition[1]), setReal);\n\t }\n\t }\n\t }\n\t\n\t /**\n\t * Try to strip pasted value to digits\n\t */\n\t\n\t }, {\n\t key: '_checkPaste',\n\t value: function _checkPaste() {\n\t if (!isUndefined(this.valuePartsBeforePaste)) {\n\t var oldParts = this.valuePartsBeforePaste;\n\t\n\t var _getLeftAndRightPartA3 = this._getLeftAndRightPartAroundTheSelection(),\n\t _getLeftAndRightPartA4 = _slicedToArray(_getLeftAndRightPartA3, 2),\n\t left = _getLeftAndRightPartA4[0],\n\t right = _getLeftAndRightPartA4[1];\n\t\n\t // Try to strip the pasted value first\n\t\n\t\n\t delete this.valuePartsBeforePaste;\n\t\n\t var modifiedLeftPart = left.substr(0, oldParts[0].length) + stripAllNonNumberCharacters(left.substr(oldParts[0].length), this.settingsClone, true);\n\t if (!this._setValueParts(modifiedLeftPart, right, true)) {\n\t this.value = oldParts.join('');\n\t this._setCaretPosition(oldParts[0].length, false);\n\t }\n\t }\n\t }\n\t\n\t /**\n\t * Process pasting, cursor moving and skipping of not interesting keys.\n\t * If this function returns TRUE, then further processing is not performed.\n\t *\n\t * @param {Event} e\n\t * @returns {boolean}\n\t * @private\n\t */\n\t\n\t }, {\n\t key: '_skipAlways',\n\t value: function _skipAlways(e) {\n\t // Catch the ctrl up on ctrl-v\n\t if ((e.ctrlKey || e.metaKey) && e.type === 'keyup' && !isUndefined(this.valuePartsBeforePaste) || e.shiftKey && this.eventKeyCode === keyCode.Insert) {\n\t //TODO Move this test inside the `onKeyup` handler\n\t this._checkPaste();\n\t return false;\n\t }\n\t\n\t // Skip all function keys (F1-F12), Windows keys, tab and other special keys\n\t if (this.eventKeyCode >= keyCode.F1 && this.eventKeyCode <= keyCode.F12 || this.eventKeyCode >= keyCode.Windows && this.eventKeyCode <= keyCode.RightClick || this.eventKeyCode >= keyCode.Tab && this.eventKeyCode < keyCode.Space ||\n\t // `e.which` is sometimes different than `this.eventKeyCode` during the keypress event when entering a printable character key (ie. 't'). Also, `e.which` equals 0 for non-printable characters.\n\t this.eventKeyCode < keyCode.Backspace && (e.which === 0 || e.which === this.eventKeyCode) || this.eventKeyCode === keyCode.NumLock || this.eventKeyCode === keyCode.ScrollLock || this.eventKeyCode === keyCode.Insert || this.eventKeyCode === keyCode.Command) {\n\t return true;\n\t }\n\t\n\t // If a \"Select all\" keyboard shortcut is detected (ctrl + a)\n\t if ((e.ctrlKey || e.metaKey) && this.eventKeyCode === keyCode.a) {\n\t if (this.settings.selectNumberOnly) {\n\t // `preventDefault()` is used here to prevent the browser to first select all the input text (including the currency sign), otherwise we would see that whole selection first in a flash, then the selection with only the number part without the currency sign.\n\t e.preventDefault();\n\t var valueLen = this.that.value.length;\n\t var currencySymbolLen = this.settings.currencySymbol.length;\n\t var negLen = !isNegative(this.that.value) ? 0 : 1;\n\t var suffixTextLen = this.settings.suffixText.length;\n\t var currencySymbolPlacement = this.settings.currencySymbolPlacement;\n\t var negativePositiveSignPlacement = this.settings.negativePositiveSignPlacement;\n\t\n\t var start = void 0;\n\t if (currencySymbolPlacement === 's') {\n\t start = 0;\n\t } else {\n\t start = negativePositiveSignPlacement === 'l' && negLen === 1 && currencySymbolLen > 0 ? currencySymbolLen + 1 : currencySymbolLen;\n\t }\n\t\n\t var end = void 0;\n\t if (currencySymbolPlacement === 'p') {\n\t end = valueLen - suffixTextLen;\n\t } else {\n\t switch (negativePositiveSignPlacement) {\n\t case 'l':\n\t end = valueLen - (suffixTextLen + currencySymbolLen);\n\t break;\n\t case 'r':\n\t end = currencySymbolLen > 0 ? valueLen - (currencySymbolLen + negLen + suffixTextLen) : valueLen - (currencySymbolLen + suffixTextLen);\n\t break;\n\t default:\n\t end = valueLen - (currencySymbolLen + suffixTextLen);\n\t }\n\t }\n\t\n\t setElementSelection(this.that, start, end);\n\t }\n\t\n\t return true;\n\t }\n\t\n\t // If a \"Copy\", \"Paste\" or \"Cut\" keyboard shortcut is detected (respectively 'ctrl + c', 'ctrl + v' or 'ctrl + x')\n\t if ((e.ctrlKey || e.metaKey) && (this.eventKeyCode === keyCode.c || this.eventKeyCode === keyCode.v || this.eventKeyCode === keyCode.x)) {\n\t if (e.type === 'keydown') {\n\t this._expandSelectionOnSign();\n\t }\n\t\n\t // Try to prevent wrong paste\n\t if (this.eventKeyCode === keyCode.v || this.eventKeyCode === keyCode.Insert) {\n\t if (e.type === 'keydown' || e.type === 'keypress') {\n\t if (isUndefined(this.valuePartsBeforePaste)) {\n\t this.valuePartsBeforePaste = this._getLeftAndRightPartAroundTheSelection();\n\t }\n\t } else {\n\t this._checkPaste();\n\t }\n\t }\n\t\n\t return e.type === 'keydown' || e.type === 'keypress' || this.eventKeyCode === keyCode.c;\n\t }\n\t\n\t if (e.ctrlKey || e.metaKey) {\n\t return true;\n\t }\n\t\n\t // Jump over thousand separator\n\t //TODO Move this test inside the `onKeydown` handler\n\t if (this.eventKeyCode === keyCode.LeftArrow || this.eventKeyCode === keyCode.RightArrow) {\n\t if (e.type === 'keydown' && !e.shiftKey) {\n\t if (this.eventKeyCode === keyCode.LeftArrow && (this.that.value.charAt(this.selection.start - 2) === this.settingsClone.digitGroupSeparator || this.that.value.charAt(this.selection.start - 2) === this.settingsClone.decimalCharacter)) {\n\t this._setCaretPosition(this.selection.start - 1);\n\t } else if (this.eventKeyCode === keyCode.RightArrow && (this.that.value.charAt(this.selection.start + 1) === this.settingsClone.digitGroupSeparator || this.that.value.charAt(this.selection.start + 1) === this.settingsClone.decimalCharacter)) {\n\t this._setCaretPosition(this.selection.start + 1);\n\t }\n\t }\n\t return true;\n\t }\n\t\n\t return this.eventKeyCode >= keyCode.PageDown && this.eventKeyCode <= keyCode.DownArrow;\n\t }\n\t\n\t /**\n\t * Process deletion of characters when the minus sign is to the right of the numeric characters.\n\t *\n\t * @param {string} left The part on the left of the caret or selection\n\t * @param {string} right The part on the right of the caret or selection\n\t * @returns {[string, string]}\n\t * @private\n\t */\n\t\n\t }, {\n\t key: '_processCharacterDeletionIfTrailingNegativeSign',\n\t value: function _processCharacterDeletionIfTrailingNegativeSign(_ref) {\n\t var _ref2 = _slicedToArray(_ref, 2),\n\t left = _ref2[0],\n\t right = _ref2[1];\n\t\n\t var settingsClone = this.settingsClone;\n\t if (settingsClone.currencySymbolPlacement === 'p' && settingsClone.negativePositiveSignPlacement === 's') {\n\t if (this.eventKeyCode === keyCode.Backspace) {\n\t settingsClone.caretFix = this.selection.start >= this.value.indexOf(settingsClone.suffixText) && settingsClone.suffixText !== '';\n\t if (this.value.charAt(this.selection.start - 1) === '-') {\n\t left = left.substring(1);\n\t } else if (this.selection.start <= this.value.length - settingsClone.suffixText.length) {\n\t left = left.substring(0, left.length - 1);\n\t }\n\t } else {\n\t settingsClone.caretFix = this.selection.start >= this.value.indexOf(settingsClone.suffixText) && settingsClone.suffixText !== '';\n\t if (this.selection.start >= this.value.indexOf(settingsClone.currencySymbol) + settingsClone.currencySymbol.length) {\n\t right = right.substring(1, right.length);\n\t }\n\t if (isNegative(left) && this.value.charAt(this.selection.start) === '-') {\n\t left = left.substring(1);\n\t }\n\t }\n\t }\n\t\n\t //TODO Merge the two following 'if' blocks into one `if (settingsClone.currencySymbolPlacement === 's') {` and a switch on settingsClone.negativePositiveSignPlacement\n\t if (settingsClone.currencySymbolPlacement === 's' && settingsClone.negativePositiveSignPlacement === 'l') {\n\t settingsClone.caretFix = this.selection.start >= this.value.indexOf(settingsClone.negativeSignCharacter) + settingsClone.negativeSignCharacter.length;\n\t if (this.eventKeyCode === keyCode.Backspace) {\n\t if (this.selection.start === this.value.indexOf(settingsClone.negativeSignCharacter) + settingsClone.negativeSignCharacter.length && contains(this.value, settingsClone.negativeSignCharacter)) {\n\t left = left.substring(1);\n\t } else if (left !== '-' && (this.selection.start <= this.value.indexOf(settingsClone.negativeSignCharacter) || !contains(this.value, settingsClone.negativeSignCharacter))) {\n\t left = left.substring(0, left.length - 1);\n\t }\n\t } else {\n\t if (left[0] === '-') {\n\t right = right.substring(1);\n\t }\n\t if (this.selection.start === this.value.indexOf(settingsClone.negativeSignCharacter) && contains(this.value, settingsClone.negativeSignCharacter)) {\n\t left = left.substring(1);\n\t }\n\t }\n\t }\n\t\n\t if (settingsClone.currencySymbolPlacement === 's' && settingsClone.negativePositiveSignPlacement === 'r') {\n\t settingsClone.caretFix = this.selection.start >= this.value.indexOf(settingsClone.negativeSignCharacter) + settingsClone.negativeSignCharacter.length;\n\t if (this.eventKeyCode === keyCode.Backspace) {\n\t if (this.selection.start === this.value.indexOf(settingsClone.negativeSignCharacter) + settingsClone.negativeSignCharacter.length) {\n\t left = left.substring(1);\n\t } else if (left !== '-' && this.selection.start <= this.value.indexOf(settingsClone.negativeSignCharacter) - settingsClone.currencySymbol.length) {\n\t left = left.substring(0, left.length - 1);\n\t } else if (left !== '' && !contains(this.value, settingsClone.negativeSignCharacter)) {\n\t left = left.substring(0, left.length - 1);\n\t }\n\t } else {\n\t settingsClone.caretFix = this.selection.start >= this.value.indexOf(settingsClone.currencySymbol) && settingsClone.currencySymbol !== '';\n\t if (this.selection.start === this.value.indexOf(settingsClone.negativeSignCharacter)) {\n\t left = left.substring(1);\n\t }\n\t right = right.substring(1);\n\t }\n\t }\n\t\n\t return [left, right];\n\t }\n\t\n\t /**\n\t * Process the deletion of characters.\n\t */\n\t\n\t }, {\n\t key: '_processCharacterDeletion',\n\t value: function _processCharacterDeletion() {\n\t var settingsClone = this.settingsClone;\n\t\n\t var left = void 0;\n\t var right = void 0;\n\t\n\t if (!this.selection.length) {\n\t var _getUnformattedLeftAn = this._getUnformattedLeftAndRightPartAroundTheSelection();\n\t\n\t var _getUnformattedLeftAn2 = _slicedToArray(_getUnformattedLeftAn, 2);\n\t\n\t left = _getUnformattedLeftAn2[0];\n\t right = _getUnformattedLeftAn2[1];\n\t\n\t if (left === '' && right === '') {\n\t settingsClone.throwInput = false;\n\t }\n\t\n\t if ((settingsClone.currencySymbolPlacement === 'p' && settingsClone.negativePositiveSignPlacement === 's' || settingsClone.currencySymbolPlacement === 's' && (settingsClone.negativePositiveSignPlacement === 'l' || settingsClone.negativePositiveSignPlacement === 'r')) && isNegative(this.value)) {\n\t var _processCharacterDele = this._processCharacterDeletionIfTrailingNegativeSign([left, right]); //TODO Change `this.value` to `this.that.value`?\n\t\n\t\n\t var _processCharacterDele2 = _slicedToArray(_processCharacterDele, 2);\n\t\n\t left = _processCharacterDele2[0];\n\t right = _processCharacterDele2[1];\n\t } else {\n\t if (this.eventKeyCode === keyCode.Backspace) {\n\t left = left.substring(0, left.length - 1);\n\t } else {\n\t right = right.substring(1, right.length);\n\t }\n\t }\n\t } else {\n\t this._expandSelectionOnSign(false);\n\t\n\t var _getUnformattedLeftAn3 = this._getUnformattedLeftAndRightPartAroundTheSelection();\n\t\n\t var _getUnformattedLeftAn4 = _slicedToArray(_getUnformattedLeftAn3, 2);\n\t\n\t left = _getUnformattedLeftAn4[0];\n\t right = _getUnformattedLeftAn4[1];\n\t }\n\t\n\t this._setValueParts(left, right);\n\t }\n\t\n\t /**\n\t * This function decides if the key pressed should be dropped or accepted, and modify the value 'on-the-fly' accordingly.\n\t * Returns TRUE if the keycode is allowed.\n\t * This functions also modify the value on-the-fly. //FIXME This should use another function in order to separate the test and the modification\n\t *\n\t * @param {Event|string} eventOrChar The event object, or the character entered (from an android device)\n\t * @returns {boolean}\n\t */\n\t\n\t }, {\n\t key: '_processCharacterInsertion',\n\t value: function _processCharacterInsertion(eventOrChar) {\n\t var settingsClone = this.settingsClone;\n\t\n\t var _getUnformattedLeftAn5 = this._getUnformattedLeftAndRightPartAroundTheSelection(),\n\t _getUnformattedLeftAn6 = _slicedToArray(_getUnformattedLeftAn5, 2),\n\t left = _getUnformattedLeftAn6[0],\n\t right = _getUnformattedLeftAn6[1];\n\t\n\t var eventCharacter = void 0;\n\t if (isString(eventOrChar)) {\n\t // Android browsers\n\t eventCharacter = eventOrChar;\n\t } else {\n\t // Normal browsers\n\t settingsClone.throwInput = true;\n\t\n\t // Retrieve the real character that has been entered (ie. 'a' instead of the key code)\n\t eventCharacter = character(eventOrChar);\n\t }\n\t\n\t // Start rules when the decimal character key is pressed always use numeric pad dot to insert decimal separator\n\t // Do not allow decimal character if no decimal part allowed\n\t if (eventCharacter === settingsClone.decimalCharacter || settingsClone.decimalCharacterAlternative && eventCharacter === settingsClone.decimalCharacterAlternative || (eventCharacter === '.' || eventCharacter === ',') && this.eventKeyCode === keyCode.DotNumpad) {\n\t if (!settingsClone.decimalPlacesOverride || !settingsClone.decimalCharacter) {\n\t return true;\n\t }\n\t\n\t // Do not allow decimal character before negativeSignCharacter character\n\t if (settingsClone.negativeSignCharacter && contains(right, settingsClone.negativeSignCharacter)) {\n\t return true;\n\t }\n\t\n\t // Do not allow decimal character if other decimal character present\n\t if (contains(left, settingsClone.decimalCharacter)) {\n\t return true;\n\t }\n\t\n\t if (right.indexOf(settingsClone.decimalCharacter) > 0) {\n\t return true;\n\t }\n\t\n\t if (right.indexOf(settingsClone.decimalCharacter) === 0) {\n\t right = right.substr(1);\n\t }\n\t\n\t this._setValueParts(left + settingsClone.decimalCharacter, right);\n\t\n\t return true;\n\t }\n\t\n\t // Prevent minus if not allowed\n\t if ((eventCharacter === '-' || eventCharacter === '+') && settingsClone.negativeSignCharacter === '-') {\n\t if (!settingsClone) {\n\t return true;\n\t }\n\t\n\t // Caret is always after minus\n\t if (settingsClone.currencySymbolPlacement === 'p' && settingsClone.negativePositiveSignPlacement === 's' || settingsClone.currencySymbolPlacement === 's' && settingsClone.negativePositiveSignPlacement !== 'p') {\n\t if (left === '' && contains(right, settingsClone.negativeSignCharacter)) {\n\t left = settingsClone.negativeSignCharacter;\n\t right = right.substring(1, right.length);\n\t }\n\t\n\t // Change number sign, remove part if should\n\t if (isNegativeStrict(left) || contains(left, settingsClone.negativeSignCharacter)) {\n\t left = left.substring(1, left.length);\n\t } else {\n\t left = eventCharacter === '-' ? settingsClone.negativeSignCharacter + left : left;\n\t }\n\t } else {\n\t if (left === '' && contains(right, settingsClone.negativeSignCharacter)) {\n\t left = settingsClone.negativeSignCharacter;\n\t right = right.substring(1, right.length);\n\t }\n\t\n\t // Change number sign, remove part if should\n\t if (left.charAt(0) === settingsClone.negativeSignCharacter) {\n\t left = left.substring(1, left.length);\n\t } else {\n\t left = eventCharacter === '-' ? settingsClone.negativeSignCharacter + left : left;\n\t }\n\t }\n\t\n\t this._setValueParts(left, right);\n\t\n\t return true;\n\t }\n\t\n\t // If the user tries to insert digit before minus sign\n\t var eventNumber = Number(eventCharacter);\n\t if (eventNumber >= 0 && eventNumber <= 9) {\n\t if (settingsClone.negativeSignCharacter && left === '' && contains(right, settingsClone.negativeSignCharacter)) {\n\t left = settingsClone.negativeSignCharacter;\n\t right = right.substring(1, right.length);\n\t }\n\t\n\t if (settingsClone.maximumValue <= 0 && settingsClone.minimumValue < settingsClone.maximumValue && !contains(this.value, settingsClone.negativeSignCharacter) && eventCharacter !== '0') {\n\t left = settingsClone.negativeSignCharacter + left;\n\t }\n\t\n\t this._setValueParts(left + eventCharacter, right);\n\t\n\t return true;\n\t }\n\t\n\t // Prevent any other character\n\t settingsClone.throwInput = false;\n\t\n\t return false;\n\t }\n\t\n\t /**\n\t * Formatting of just processed value while keeping the cursor position\n\t *\n\t * @param {Event} e\n\t * @private\n\t */\n\t\n\t }, {\n\t key: '_formatValue',\n\t value: function _formatValue(e) {\n\t var _this = this;\n\t\n\t var settingsClone = this.settingsClone;\n\t var leftLength = this.value;\n\t\n\t var _getUnformattedLeftAn7 = this._getUnformattedLeftAndRightPartAroundTheSelection(),\n\t _getUnformattedLeftAn8 = _slicedToArray(_getUnformattedLeftAn7, 1),\n\t left = _getUnformattedLeftAn8[0];\n\t\n\t // No grouping separator and no currency sign\n\t\n\t\n\t if ((settingsClone.digitGroupSeparator === '' || settingsClone.digitGroupSeparator !== '' && !contains(leftLength, settingsClone.digitGroupSeparator)) && (settingsClone.currencySymbol === '' || settingsClone.currencySymbol !== '' && !contains(leftLength, settingsClone.currencySymbol))) {\n\t var _leftLength$split = leftLength.split(settingsClone.decimalCharacter),\n\t _leftLength$split2 = _slicedToArray(_leftLength$split, 1),\n\t subParts = _leftLength$split2[0];\n\t\n\t var nSign = '';\n\t if (isNegative(subParts)) {\n\t nSign = '-';\n\t subParts = subParts.replace('-', '');\n\t left = left.replace('-', '');\n\t }\n\t\n\t // Strip leading zero on positive value if needed\n\t if (nSign === '' && subParts.length > settingsClone.mIntPos && left.charAt(0) === '0') {\n\t left = left.slice(1);\n\t }\n\t\n\t // Strip leading zero on negative value if needed\n\t if (nSign === '-' && subParts.length > settingsClone.mIntNeg && left.charAt(0) === '0') {\n\t left = left.slice(1);\n\t }\n\t\n\t left = nSign + left;\n\t }\n\t\n\t var value = addGroupSeparators(this.value, this.settingsClone);\n\t var position = value.length;\n\t if (value) {\n\t // Prepare regexp which searches for cursor position from unformatted left part\n\t var leftAr = left.split('');\n\t\n\t // Fixes caret position with trailing minus sign\n\t if ((settingsClone.negativePositiveSignPlacement === 's' || settingsClone.currencySymbolPlacement === 's' && settingsClone.negativePositiveSignPlacement !== 'p') && leftAr[0] === '-' && settingsClone.negativeSignCharacter !== '') {\n\t leftAr.shift();\n\t\n\t if ((this.eventKeyCode === keyCode.Backspace || this.eventKeyCode === keyCode.Delete) && settingsClone.caretFix) {\n\t if (settingsClone.currencySymbolPlacement === 's' && settingsClone.negativePositiveSignPlacement === 'l') {\n\t leftAr.push('-');\n\t settingsClone.caretFix = e.type === 'keydown';\n\t }\n\t\n\t if (settingsClone.currencySymbolPlacement === 'p' && settingsClone.negativePositiveSignPlacement === 's') {\n\t leftAr.push('-');\n\t settingsClone.caretFix = e.type === 'keydown';\n\t }\n\t\n\t if (settingsClone.currencySymbolPlacement === 's' && settingsClone.negativePositiveSignPlacement === 'r') {\n\t (function () {\n\t var signParts = settingsClone.currencySymbol.split('');\n\t var escapeChr = ['\\\\', '^', '$', '.', '|', '?', '*', '+', '(', ')', '['];\n\t var escapedParts = [];\n\t $.each(signParts, function (i, miniParts) {\n\t miniParts = signParts[i];\n\t if (isInArray(miniParts, escapeChr)) {\n\t escapedParts.push('\\\\' + miniParts);\n\t } else {\n\t escapedParts.push(miniParts);\n\t }\n\t });\n\t\n\t if (_this.eventKeyCode === keyCode.Backspace) {\n\t escapedParts.push('-');\n\t }\n\t\n\t // Pushing the escaped sign\n\t leftAr.push(escapedParts.join(''));\n\t settingsClone.caretFix = e.type === 'keydown';\n\t })();\n\t }\n\t }\n\t }\n\t\n\t for (var i = 0; i < leftAr.length; i++) {\n\t if (!leftAr[i].match('\\\\d')) {\n\t leftAr[i] = '\\\\' + leftAr[i];\n\t }\n\t }\n\t\n\t var leftReg = new RegExp('^.*?' + leftAr.join('.*?'));\n\t\n\t // Search cursor position in formatted value\n\t var newLeft = value.match(leftReg);\n\t if (newLeft) {\n\t position = newLeft[0].length;\n\t\n\t // If the positive sign is shown, calculate the caret position accordingly\n\t if (settingsClone.showPositiveSign) {\n\t if (position === 0 && newLeft.input.charAt(0) === settingsClone.positiveSignCharacter) {\n\t position = newLeft.input.indexOf(settingsClone.currencySymbol) === 1 ? settingsClone.currencySymbol.length + 1 : 1;\n\t }\n\t\n\t if (position === 0 && newLeft.input.charAt(settingsClone.currencySymbol.length) === settingsClone.positiveSignCharacter) {\n\t position = settingsClone.currencySymbol.length + 1;\n\t }\n\t }\n\t\n\t // If we are just before the sign which is in prefix position\n\t if ((position === 0 && value.charAt(0) !== settingsClone.negativeSignCharacter || position === 1 && value.charAt(0) === settingsClone.negativeSignCharacter) && settingsClone.currencySymbol && settingsClone.currencySymbolPlacement === 'p') {\n\t // Place caret after prefix sign\n\t //TODO Should the test be 'isNegative' instead of 'isNegativeStrict' in order to search for '-' everywhere in the string?\n\t position = this.settingsClone.currencySymbol.length + (isNegativeStrict(value) ? 1 : 0);\n\t }\n\t } else {\n\t if (settingsClone.currencySymbol && settingsClone.currencySymbolPlacement === 's') {\n\t // If we could not find a place for cursor and have a sign as a suffix\n\t // Place caret before suffix currency sign\n\t position -= settingsClone.currencySymbol.length;\n\t }\n\t\n\t if (settingsClone.suffixText) {\n\t // If we could not find a place for cursor and have a suffix\n\t // Place caret before suffix\n\t position -= settingsClone.suffixText.length;\n\t }\n\t }\n\t }\n\t\n\t // Only update the value if it has changed. This prevents modifying the selection, if any.\n\t if (value !== this.that.value || value === this.that.value && (this.eventKeyCode === keyCode.num0 || this.eventKeyCode === keyCode.numpad0)) {\n\t this.that.value = value;\n\t this._setCaretPosition(position);\n\t }\n\t\n\t if (settingsClone.androidSelectionStart !== null) {\n\t // If an Android browser is detected, fix the caret position\n\t // Unfortunately this does not fix all android browsers, only Android Chrome currently.\n\t // This is due to the fact those provide different order of events and/or keycodes thrown (this is a real mess :|).\n\t this._setCaretPosition(settingsClone.androidSelectionStart);\n\t }\n\t\n\t this.formatted = true; //TODO Rename `this.formatted` to `this._formatExecuted`, since it's possible this function does not need to format anything (in the case where the keycode is dropped for instance)\n\t }\n\t }]);\n\t\n\t return AutoNumericHolder;\n\t }();\n\t\n\t /**\n\t * This function factorise the `getString()` and `getArray()` functions since they share quite a lot of code.\n\t *\n\t * The \"getString\" method uses jQuery's .serialize() method that creates a text string in standard URL-encoded notation.\n\t * The \"getArray\" method on the other hand uses jQuery's .serializeArray() method that creates array or objects that can be encoded as a JSON string.\n\t *\n\t * It then loops through the string and un-formats the inputs with autoNumeric.\n\t * By defaults values returned as ISO numeric string \"1234.56\" or \"-1234.56\" where the decimal character is a period\n\t * Locale formats are supported \"1234.56-\" or \"1234,56\" or \"-1234,56 or \"1234,56-\", or even plain numbers => please see option \"outputFormat\" for more details\n\t *\n\t * @param {boolean} getArrayBehavior - If set to TRUE, then this function behave like `getArray()`, otherwise if set to FALSE, it behave like `getString()`\n\t * @param {HTMLElement} that - A reference to the current DOM element\n\t * @returns {*}\n\t * @private\n\t */\n\t\n\t\n\t function _getStringOrArray() {\n\t var getArrayBehavior = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;\n\t var that = arguments[1];\n\t\n\t var $this = getCurrentElement(that);\n\t var formIndex = $('form').index($this);\n\t var allFormElements = $('form:eq(' + formIndex + ')')[0];\n\t var aiIndex = [];\n\t\n\t // all input index\n\t var scIndex = [];\n\t\n\t // successful control index\n\t var rSubmitterTypes = /^(?:submit|button|image|reset|file)$/i;\n\t\n\t // from jQuery serialize method\n\t var rSubmittable = /^(?:input|select|textarea|keygen)/i;\n\t\n\t // from jQuery serialize method\n\t var rCheckableType = /^(?:checkbox|radio)$/i;\n\t var rNonAutoNumericTypes = /^(?:button|checkbox|color|date|datetime|datetime-local|email|file|image|month|number|password|radio|range|reset|search|submit|time|url|week)/i;\n\t\n\t var count = 0;\n\t\n\t // index of successful elements\n\t $.each(allFormElements, function (i, field) {\n\t if (field.name !== '' && rSubmittable.test(field.localName) && !rSubmitterTypes.test(field.type) && !field.disabled && (field.checked || !rCheckableType.test(field.type))) {\n\t scIndex.push(count);\n\t count++;\n\t } else {\n\t scIndex.push(-1);\n\t }\n\t });\n\t\n\t // index of all inputs tags except checkbox\n\t count = 0;\n\t $.each(allFormElements, function (i, field) {\n\t if (field.localName === 'input' && (field.type === '' || field.type === 'text' || field.type === 'hidden' || field.type === 'tel')) {\n\t aiIndex.push(count);\n\t count++;\n\t } else {\n\t aiIndex.push(-1);\n\t if (field.localName === 'input' && rNonAutoNumericTypes.test(field.type)) {\n\t count++;\n\t }\n\t }\n\t });\n\t\n\t if (getArrayBehavior) {\n\t var formFields = $this.serializeArray();\n\t\n\t $.each(formFields, function (i, field) {\n\t var scElement = scIndex.indexOf(i);\n\t\n\t if (scElement > -1 && aiIndex[scElement] > -1) {\n\t var testInput = $('form:eq(' + formIndex + ') input:eq(' + aiIndex[scElement] + ')');\n\t var settings = testInput.data('autoNumeric');\n\t\n\t if ((typeof settings === 'undefined' ? 'undefined' : _typeof(settings)) === 'object') {\n\t field.value = testInput.autoNumeric('getLocalized').toString();\n\t }\n\t }\n\t });\n\t\n\t return formFields;\n\t } else {\n\t var _ret2 = function () {\n\t // getString() behavior\n\t var formFields = $this.serialize();\n\t var formParts = formFields.split('&');\n\t\n\t $.each(formParts, function (i) {\n\t var _formParts$i$split = formParts[i].split('='),\n\t _formParts$i$split2 = _slicedToArray(_formParts$i$split, 2),\n\t inputName = _formParts$i$split2[0],\n\t inputValue = _formParts$i$split2[1];\n\t\n\t var scElement = scIndex.indexOf(i);\n\t\n\t // If the current element is a valid element\n\t if (scElement > -1 && aiIndex[scElement] > -1) {\n\t var testInput = $('form:eq(' + formIndex + ') input:eq(' + aiIndex[scElement] + ')');\n\t var settings = testInput.data('autoNumeric');\n\t\n\t if ((typeof settings === 'undefined' ? 'undefined' : _typeof(settings)) === 'object') {\n\t if (inputValue !== null) {\n\t var modifiedInputValue = testInput.autoNumeric('getLocalized').toString();\n\t formParts[i] = inputName + '=' + modifiedInputValue;\n\t }\n\t }\n\t }\n\t });\n\t\n\t return {\n\t v: formParts.join('&')\n\t };\n\t }();\n\t\n\t if ((typeof _ret2 === 'undefined' ? 'undefined' : _typeof(_ret2)) === \"object\") return _ret2.v;\n\t }\n\t }\n\t\n\t /**\n\t * Handler for 'focusin' events\n\t *\n\t * @param {object} $this jQuery-selected DOM element\n\t * @param {AutoNumericHolder} holder\n\t * @param {Event} e\n\t */\n\t function onFocusInAndMouseEnter($this, holder, e) {\n\t var settings = holder.settingsClone;\n\t\n\t if (e.type === 'focusin' || e.type === 'mouseenter' && !$this.is(':focus') && settings.emptyInputBehavior === 'focus') {\n\t settings.hasFocus = true;\n\t\n\t if (settings.negativeBracketsTypeOnBlur !== null && settings.negativeSignCharacter !== '') {\n\t $this.val(toggleNegativeBracket(e.target.value, settings));\n\t }\n\t\n\t // clean the value to compare to rawValue\n\t var result = stripAllNonNumberCharacters(e.target.value, settings, true);\n\t result = convertToNumericString(result, settings);\n\t result = cleanLeadingTrailingZeros(result, settings);\n\t if (settings.trailingNegative) {\n\t result = '-' + result;\n\t }\n\t\n\t var roundedValue = void 0;\n\t if (settings.decimalPlacesShownOnFocus) {\n\t settings.decimalPlacesOverride = settings.decimalPlacesShownOnFocus;\n\t roundedValue = roundValue(settings.rawValue, settings);\n\t $this.val(addGroupSeparators(roundedValue, settings));\n\t } else if (settings.scaleDivisor) {\n\t settings.decimalPlacesOverride = Number(settings.oDec);\n\t roundedValue = roundValue(settings.rawValue, settings);\n\t $this.val(addGroupSeparators(roundedValue, settings));\n\t } else if (settings.noSeparatorOnFocus) {\n\t settings.digitGroupSeparator = '';\n\t settings.currencySymbol = '';\n\t settings.suffixText = '';\n\t roundedValue = roundValue(settings.rawValue, settings);\n\t $this.val(addGroupSeparators(roundedValue, settings));\n\t } else if (result !== settings.rawValue) {\n\t // updates the rawValue\n\t $this.autoNumeric('set', result);\n\t }\n\t\n\t // In order to send a 'native' change event when blurring the input, we need to first store the initial input value on focus.\n\t holder.valueOnFocus = e.target.value;\n\t holder.lastVal = holder.valueOnFocus;\n\t var onEmpty = checkEmpty(holder.valueOnFocus, settings, true);\n\t if (onEmpty !== null && onEmpty !== '' && settings.emptyInputBehavior === 'focus') {\n\t $this.val(onEmpty);\n\t if (onEmpty === settings.currencySymbol && settings.currencySymbolPlacement === 's') {\n\t setElementSelection(e.target, 0, 0);\n\t }\n\t }\n\t }\n\t }\n\t\n\t /**\n\t * Handler for 'keydown' events.\n\t * The user just started pushing any key, hence one event is sent.\n\t *\n\t * Note :\n\t * By default a 'normal' input output those events in the right order when inputting a character key (ie. 'a') :\n\t * - keydown\n\t * - keypress\n\t * - input\n\t * - keyup\n\t *\n\t * ...when inputting a modifier key (ie. 'ctrl') :\n\t * - keydown\n\t * - keyup\n\t *\n\t * If 'delete' or 'backspace' is entered, the following events are sent :\n\t * - keydown\n\t * - input\n\t * - keyup\n\t *\n\t * If 'enter' is entered and the value has not changed, the following events are sent :\n\t * - keydown\n\t * - keypress\n\t * - keyup\n\t *\n\t * If 'enter' is entered and the value has been changed, the following events are sent :\n\t * - keydown\n\t * - keypress\n\t * - change\n\t * - keyup\n\t *\n\t * When a paste is done, the following events are sent :\n\t * - input (if paste is done with the mouse)\n\t *\n\t * - keydown (if paste is done with ctrl+v)\n\t * - keydown\n\t * - input\n\t * - keyup\n\t * - keyup\n\t *\n\t * @param {AutoNumericHolder} holder\n\t * @param {Event} e\n\t */\n\t function onKeydown(holder, e) {\n\t //TODO Create a function that retrieve the element value (either by using `e.target.value` when the element is an , or by using `element.textContent` when the element as its `contenteditable` set to true)\n\t holder._updateAutoNumericHolderEventKeycode(e);\n\t holder.initialValueOnKeydown = e.target.value; // This is needed in `onKeyup()` to check if the value as changed during the key press\n\t\n\t if (holder.that.readOnly) {\n\t holder.processed = true;\n\t\n\t return;\n\t }\n\t\n\t // The \"enter\" key throws a `change` event if the value has changed since the `focus` event\n\t if (holder.eventKeyCode === keyCode.Enter && holder.valueOnFocus !== e.target.value) {\n\t triggerEvent('change', e.target);\n\t holder.valueOnFocus = e.target.value;\n\t }\n\t\n\t holder._updateAutoNumericHolderProperties(e);\n\t\n\t if (holder._skipAlways(e)) {\n\t holder.processed = true;\n\t\n\t return;\n\t }\n\t\n\t // Check if the key is a delete/backspace key\n\t if (holder.eventKeyCode === keyCode.Backspace || holder.eventKeyCode === keyCode.Delete) {\n\t holder._processCharacterDeletion(); // Because backspace and delete only triggers keydown and keyup events, not keypress\n\t holder.processed = true;\n\t holder._formatValue(e);\n\t\n\t // If and only if the resulting value has changed after that backspace/delete, then we have to send an 'input' event like browsers normally do.\n\t if (e.target.value !== holder.lastVal && holder.settingsClone.throwInput) {\n\t // Throw an input event when a character deletion is detected\n\t triggerEvent('input', e.target);\n\t e.preventDefault(); // ...and immediately prevent the browser to delete a second character\n\t }\n\t\n\t holder.lastVal = e.target.value;\n\t holder.settingsClone.throwInput = true;\n\t\n\t return;\n\t }\n\t\n\t holder.formatted = false; //TODO Is this line needed?\n\t }\n\t\n\t /**\n\t * Handler for 'keypress' events.\n\t * The user is still pressing the key, which will output a character (ie. '2') continuously until it releases the key.\n\t * Note: 'keypress' events are not sent for delete keys like Backspace/Delete.\n\t *\n\t * @param {AutoNumericHolder} holder\n\t * @param {Event} e\n\t */\n\t function onKeypress(holder, e) {\n\t // Retrieve the real character that has been entered (ie. 'a' instead of the key code)\n\t var eventCharacter = character(e);\n\t\n\t // Firefox generate a 'keypress' event (e.keyCode === 0) for the keys that do not print a character (ie. 'Insert', 'Delete', 'Fn' keys, 'PageUp', 'PageDown' etc.). 'Shift' on the other hand does not generate a keypress event.\n\t if (eventCharacter === keyName.Insert) {\n\t return;\n\t }\n\t\n\t var processed = holder.processed;\n\t holder._updateAutoNumericHolderProperties(e);\n\t\n\t if (holder._skipAlways(e)) {\n\t return;\n\t }\n\t\n\t if (processed) {\n\t e.preventDefault();\n\t\n\t return;\n\t }\n\t\n\t var isCharacterInsertionAllowed = holder._processCharacterInsertion(e);\n\t if (isCharacterInsertionAllowed) {\n\t holder._formatValue(e);\n\t if (e.target.value !== holder.lastVal && holder.settingsClone.throwInput) {\n\t // Throws input event on adding a character\n\t triggerEvent('input', e.target);\n\t e.preventDefault(); // ...and immediately prevent the browser to add a second character\n\t } else {\n\t if ((eventCharacter === holder.settings.decimalCharacter || eventCharacter === holder.settings.decimalCharacterAlternative) && getElementSelection(e.target).start === getElementSelection(e.target).end && getElementSelection(e.target).start === e.target.value.indexOf(holder.settings.decimalCharacter)) {\n\t var position = getElementSelection(e.target).start + 1;\n\t setElementSelection(e.target, position, position);\n\t }\n\t e.preventDefault();\n\t }\n\t\n\t holder.lastVal = e.target.value;\n\t holder.settingsClone.throwInput = true;\n\t\n\t return;\n\t }\n\t\n\t e.preventDefault();\n\t\n\t holder.formatted = false;\n\t }\n\t\n\t /**\n\t * Handler for 'input' events.\n\t * added to support android devices with mobile chrome browsers and others\n\t * Has the potential to replace the keypress event.\n\t *\n\t * @param {AutoNumericHolder} holder\n\t * @param {Event} e\n\t */\n\t function onInput(holder, e) {\n\t var value = e.target.value;\n\t\n\t // Fix the caret position on keyup in the `_formatValue()` function\n\t holder.settings.androidSelectionStart = null;\n\t\n\t if (holder.eventKeyCode === keyCode.AndroidDefault) {\n\t // The keyCode is equal to the default Android Chrome one (which is always equal to `keyCode.AndroidDefault`)\n\t if (value.length > holder.lastVal.length || value.length >= holder.lastVal.length - holder.selection.length) {\n\t // Determine the keycode of the character that was entered, and overwrite the faulty `eventKeyCode` info with it\n\t holder.eventKeyCode = value.charCodeAt(holder.selection.start);\n\t\n\t // Capture the actual character entered\n\t var androidCharEntered = value.charAt(holder.selection.start);\n\t\n\t // Check if the given character should be inserted, and if so, do insert it into the current element value\n\t var isCharacterInsertionAllowed = holder._processCharacterInsertion(androidCharEntered);\n\t\n\t if (isCharacterInsertionAllowed) {\n\t // Allowed character entered (number, decimal or plus/minus sign)\n\t holder._formatValue(e);\n\t\n\t // Capture the new caret position. This is required because on keyup, `_updateAutoNumericHolderEventKeycode()` captures the old caret position\n\t //TODO Check if this is an Android bug or an autoNumeric one\n\t holder.settings.androidSelectionStart = holder.selection.start;\n\t\n\t var decimalCharacterPosition = e.target.value.indexOf(holder.settings.decimalCharacter);\n\t var hasDecimalCharacter = decimalCharacterPosition === -1;\n\t\n\t // Move the caret to the right if the `androidCharEntered` is the decimal character or if it's on the left of the caret position\n\t if (androidCharEntered === holder.settings.decimalCharacter || !hasDecimalCharacter && decimalCharacterPosition < holder.settings.androidSelectionStart) {\n\t holder.settings.androidSelectionStart = holder.selection.start + 1;\n\t }\n\t\n\t if (e.target.value.length > value.length) {\n\t // Position the caret right now before the 'keyup' event in order to prevent the caret from jumping around\n\t setElementSelection(e.target, holder.settings.androidSelectionStart, holder.settings.androidSelectionStart);\n\t }\n\t\n\t holder.lastVal = e.target.value;\n\t\n\t return;\n\t } else {\n\t // The entered character is not allowed ; overwrite the new invalid value with the previous valid one, and set back the caret/selection\n\t e.target.value = holder.lastVal;\n\t setElementSelection(e.target, holder.selection.start, holder.selection.end);\n\t holder.settings.androidSelectionStart = holder.selection.start;\n\t }\n\t\n\t e.preventDefault(); //FIXME How does that affects the normal trigger of the input event?\n\t\n\t holder.formatted = false;\n\t } else {\n\t // Character deleted\n\t //TODO What about the `Delete` key?\n\t holder.eventKeyCode = keyCode.Backspace;\n\t }\n\t }\n\t }\n\t\n\t /**\n\t * Handler for 'keyup' events.\n\t * The user just released any key, hence one event is sent.\n\t *\n\t * @param {AutoNumericHolder} holder\n\t * @param {object} settings\n\t * @param {Event} e\n\t */\n\t function onKeyup(holder, settings, e) {\n\t holder._updateAutoNumericHolderProperties(e);\n\t\n\t var skip = holder._skipAlways(e);\n\t delete holder.valuePartsBeforePaste;\n\t var isOnAndroid = holder.settingsClone.androidSelectionStart !== null;\n\t if (skip && !isOnAndroid || e.target.value === '') {\n\t return;\n\t }\n\t\n\t // Added to properly place the caret when only the currency sign is present\n\t if (e.target.value === holder.settingsClone.currencySymbol) {\n\t if (holder.settingsClone.currencySymbolPlacement === 's') {\n\t setElementSelection(e.target, 0, 0);\n\t } else {\n\t setElementSelection(e.target, holder.settingsClone.currencySymbol.length, holder.settingsClone.currencySymbol.length);\n\t }\n\t } else if (holder.eventKeyCode === keyCode.Tab) {\n\t setElementSelection(e.target, 0, e.target.value.length);\n\t }\n\t\n\t if (e.target.value === holder.settingsClone.suffixText || holder.settingsClone.rawValue === '' && holder.settingsClone.currencySymbol !== '' && holder.settingsClone.suffixText !== '') {\n\t setElementSelection(e.target, 0, 0);\n\t }\n\t\n\t // Saves the extended decimal to preserve the data when navigating away from the page\n\t if (holder.settingsClone.decimalPlacesShownOnFocus !== null && holder.settingsClone.saveValueToSessionStorage) {\n\t saveValueToPersistentStorage(e.target, settings, 'set');\n\t }\n\t\n\t if (!holder.formatted) {\n\t holder._formatValue(e);\n\t }\n\t\n\t // If the input value has changed during the key press event chain, an event is sent to alert that a formatting has been done (cf. Issue #187)\n\t if (e.target.value !== holder.initialValueOnKeydown) {\n\t triggerEvent('autoNumeric:formatted', e.target);\n\t }\n\t }\n\t\n\t /**\n\t * Handler for 'focusout' events\n\t *\n\t * @param {object} $this jQuery-selected DOM element\n\t * @param {AutoNumericHolder} holder\n\t * @param {Event} e\n\t */\n\t function onFocusOutAndMouseLeave($this, holder, e) {\n\t if (!$this.is(':focus')) {\n\t var value = e.target.value;\n\t var origValue = value;\n\t var settings = holder.settingsClone;\n\t settings.hasFocus = false;\n\t\n\t if (settings.saveValueToSessionStorage) {\n\t saveValueToPersistentStorage(e.target, settings, 'set');\n\t }\n\t\n\t if (settings.noSeparatorOnFocus === true) {\n\t settings.digitGroupSeparator = settings.oSep;\n\t settings.currencySymbol = settings.oSign;\n\t settings.suffixText = settings.oSuffix;\n\t }\n\t\n\t if (settings.decimalPlacesShownOnFocus !== null) {\n\t settings.decimalPlacesOverride = settings.oDec;\n\t settings.allowDecimalPadding = settings.oPad;\n\t settings.negativeBracketsTypeOnBlur = settings.oBracket;\n\t }\n\t\n\t value = stripAllNonNumberCharacters(value, settings, true);\n\t\n\t if (value !== '') {\n\t if (settings.trailingNegative && !isNegative(value)) {\n\t value = '-' + value;\n\t settings.trailingNegative = false;\n\t }\n\t\n\t var _checkIfInRangeWithOv3 = checkIfInRangeWithOverrideOption(value, settings),\n\t _checkIfInRangeWithOv4 = _slicedToArray(_checkIfInRangeWithOv3, 2),\n\t minTest = _checkIfInRangeWithOv4[0],\n\t maxTest = _checkIfInRangeWithOv4[1];\n\t\n\t if (checkEmpty(value, settings, false) === null && minTest && maxTest) {\n\t value = modifyNegativeSignAndDecimalCharacterForRawValue(value, settings);\n\t settings.rawValue = cleanLeadingTrailingZeros(value, settings);\n\t\n\t if (settings.scaleDivisor) {\n\t value = value / settings.scaleDivisor;\n\t value = value.toString();\n\t }\n\t\n\t settings.decimalPlacesOverride = settings.scaleDivisor && settings.scaleDecimalPlaces ? Number(settings.scaleDecimalPlaces) : settings.decimalPlacesOverride;\n\t value = roundValue(value, settings);\n\t value = modifyNegativeSignAndDecimalCharacterForFormattedValue(value, settings);\n\t } else {\n\t if (!minTest) {\n\t $this.trigger('autoNumeric:minExceeded');\n\t }\n\t if (!maxTest) {\n\t $this.trigger('autoNumeric:maxExceeded');\n\t }\n\t\n\t value = settings.rawValue;\n\t }\n\t } else {\n\t if (settings.emptyInputBehavior === 'zero') {\n\t settings.rawValue = '0';\n\t value = roundValue('0', settings);\n\t } else {\n\t settings.rawValue = '';\n\t }\n\t }\n\t\n\t var groupedValue = checkEmpty(value, settings, false);\n\t if (groupedValue === null) {\n\t groupedValue = addGroupSeparators(value, settings);\n\t }\n\t\n\t if (groupedValue !== origValue) {\n\t groupedValue = settings.scaleSymbol ? groupedValue + settings.scaleSymbol : groupedValue;\n\t $this.val(groupedValue);\n\t }\n\t\n\t if (groupedValue !== holder.valueOnFocus) {\n\t $this.change();\n\t delete holder.valueOnFocus;\n\t }\n\t }\n\t }\n\t\n\t /**\n\t * Handler for 'paste' events\n\t *\n\t * @param {object} $this jQuery-selected DOM element\n\t * @param {AutoNumericHolder} holder\n\t * @param {Event} e\n\t */\n\t function onPaste($this, holder, e) {\n\t //TODO Using ctrl+z after a paste should cancel it -> How would that affect other frameworks/component built with that feature in mind though?\n\t //FIXME When pasting '000' on a thousand group selection, the whole selection gets deleted, and only one '0' is pasted (cf. issue #302)\n\t // The event is prevented by default, since otherwise the user would be able to paste invalid characters into the input\n\t e.preventDefault();\n\t\n\t var rawPastedText = e.clipboardData.getData('text/plain');\n\t\n\t // 0. Special case if the user has selected all the input text before pasting\n\t var initialFormattedValue = e.target.value;\n\t var selectionStart = e.target.selectionStart || 0;\n\t var selectionEnd = e.target.selectionEnd || 0;\n\t var selectionSize = selectionEnd - selectionStart;\n\t var isAllInputTextSelected = false;\n\t\n\t if (selectionSize === initialFormattedValue.length) {\n\t isAllInputTextSelected = true;\n\t }\n\t\n\t // 1. Check if the paste has a negative sign (only if it's the first character), and store that information for later use\n\t var isPasteNegative = isNegativeStrict(rawPastedText);\n\t if (isPasteNegative) {\n\t // 1a. Remove the negative sign from the pasted text\n\t rawPastedText = rawPastedText.slice(1, rawPastedText.length);\n\t }\n\t\n\t // 2. Strip all thousand separators, brackets and currency sign, and convert the decimal character to a dot\n\t var untranslatedPastedText = preparePastedText(rawPastedText, holder);\n\t\n\t var pastedText = void 0;\n\t if (untranslatedPastedText === '.') {\n\t // Special case : If the user tries to paste a single decimal character (that has been translated to '.' already)\n\t pastedText = '.';\n\t } else {\n\t // Normal case\n\t // Allow pasting arabic numbers\n\t pastedText = arabicToLatinNumbers(untranslatedPastedText, false, false, false);\n\t }\n\t\n\t // 3. Test if the paste is valid (only has numbers and eventually a decimal character). If it's not valid, stop here.\n\t if (pastedText !== '.' && (!isNumber(pastedText) || pastedText === '')) {\n\t if (holder.settings.onInvalidPaste === 'error') {\n\t //TODO Should we send a warning instead of throwing an error?\n\t throwError('The pasted value \\'' + rawPastedText + '\\' is not a valid paste content.');\n\t }\n\t\n\t return;\n\t }\n\t\n\t // 4. Calculate the paste result\n\t var caretPositionOnInitialTextAfterPasting = void 0;\n\t var initialUnformattedNumber = void 0;\n\t if (e.target.value === '') {\n\t // autoNumeric 'get' returns '0.00' if the input is empty, hence we need to store the 'real' empty initial value when needed\n\t //FIXME This has been fixed in a previous commit, get should return '' on an empty input. Remove this unneeded 'if'\n\t initialUnformattedNumber = '';\n\t } else {\n\t initialUnformattedNumber = $this.autoNumeric('get');\n\t }\n\t var isInitialValueNegative = isNegativeStrict(initialUnformattedNumber);\n\t var isPasteNegativeAndInitialValueIsPositive = void 0;\n\t var result = void 0;\n\t\n\t // If the pasted content is negative, then the result will be negative too\n\t if (isPasteNegative && !isInitialValueNegative) {\n\t initialUnformattedNumber = '-' + initialUnformattedNumber;\n\t isInitialValueNegative = true;\n\t isPasteNegativeAndInitialValueIsPositive = true;\n\t } else {\n\t isPasteNegativeAndInitialValueIsPositive = false;\n\t }\n\t\n\t var leftPartContainedADot = false;\n\t var leftPart = void 0;\n\t var rightPart = void 0;\n\t switch (holder.settings.onInvalidPaste) {\n\t /* 4a. Truncate paste behavior:\n\t * Insert as many numbers as possible on the right hand side of the caret from the pasted text content, until the input reach its range limit.\n\t * If there is more characters in the clipboard once a limit is reached, drop the extraneous characters.\n\t * Otherwise paste all the numbers in the clipboard.\n\t * While doing so, we check if the result is within the minimum and maximum values allowed, and stop as soon as we encounter one of those.\n\t *\n\t * 4b. Replace paste behavior:\n\t * Idem than the 'truncate' paste behavior, except that when a range limit is hit, we try to replace the subsequent initial numbers with the pasted ones, until we hit the range limit a second (and last) time, or we run out of numbers to paste\n\t */\n\t /* eslint no-case-declarations: 0 */\n\t case 'truncate':\n\t case 'replace':\n\t var leftFormattedPart = initialFormattedValue.slice(0, selectionStart);\n\t var rightFormattedPart = initialFormattedValue.slice(selectionEnd, initialFormattedValue.length);\n\t\n\t if (selectionStart !== selectionEnd) {\n\t // a. If there is a selection, remove the selected part, and return the left and right part\n\t result = preparePastedText(leftFormattedPart + rightFormattedPart, holder);\n\t } else {\n\t // b. Else if this is only one caret (and therefore no selection), then return the left and right part\n\t result = preparePastedText(initialFormattedValue, holder);\n\t }\n\t\n\t // Add back the negative sign if needed\n\t if (isInitialValueNegative) {\n\t result = setRawNegativeSign(result);\n\t }\n\t\n\t // Build the unformatted result string\n\t caretPositionOnInitialTextAfterPasting = convertCharacterCountToIndexPosition(countNumberCharactersOnTheCaretLeftSide(initialFormattedValue, selectionStart, holder.settings.decimalCharacter));\n\t if (isPasteNegativeAndInitialValueIsPositive) {\n\t // If the initial paste is negative and the initial value is not, then I must offset the caret position by one place to the right to take the additional hyphen into account\n\t caretPositionOnInitialTextAfterPasting++;\n\t //TODO Quid if the negative sign is not on the left (negativePositiveSignPlacement and currencySymbolPlacement)?\n\t }\n\t\n\t leftPart = result.slice(0, caretPositionOnInitialTextAfterPasting);\n\t rightPart = result.slice(caretPositionOnInitialTextAfterPasting, result.length);\n\t if (pastedText === '.') {\n\t if (contains(leftPart, '.')) {\n\t // If I remove a dot here, then I need to update the caret position (decrement it by 1) when positioning it\n\t // To do so, we keep that info in order to modify the caret position later\n\t leftPartContainedADot = true;\n\t leftPart = leftPart.replace('.', '');\n\t }\n\t rightPart = rightPart.replace('.', '');\n\t }\n\t // -- Here, we are good to go to continue on the same basis\n\t\n\t // c. Add numbers one by one at the caret position, while testing if the result is valid and within the range of the minimum and maximum value\n\t // Continue until you either run out of numbers to paste, or that you get out of the range limits\n\t var minParse = parseStr(holder.settings.minimumValue);\n\t var maxParse = parseStr(holder.settings.maximumValue);\n\t var lastGoodKnownResult = result; // This is set as the default, in case we do not add even one number\n\t var pastedTextIndex = 0;\n\t var modifiedLeftPart = leftPart;\n\t\n\t while (pastedTextIndex < pastedText.length) {\n\t // Modify the result with another pasted character\n\t modifiedLeftPart += pastedText[pastedTextIndex];\n\t result = modifiedLeftPart + rightPart;\n\t\n\t // Check the range limits\n\t if (!checkIfInRange(result, minParse, maxParse)) {\n\t // The result is out of the range limits, stop the loop here\n\t break;\n\t }\n\t\n\t // Save the last good known result\n\t lastGoodKnownResult = result;\n\t\n\t // Update the local variables for the next loop\n\t pastedTextIndex++;\n\t }\n\t\n\t // Update the last caret position where to insert a new number\n\t caretPositionOnInitialTextAfterPasting += pastedTextIndex;\n\t\n\t //XXX Here we have the result for the `truncate` option\n\t if (holder.settings.onInvalidPaste === 'truncate') {\n\t //TODO If the user as defined a truncate callback and there are still some numbers (that will be dropped), then call this callback with the initial paste as well as the remaining numbers\n\t result = lastGoodKnownResult;\n\t\n\t if (leftPartContainedADot) {\n\t // If a dot has been removed for the part on the left of the caret, we decrement the caret index position\n\t caretPositionOnInitialTextAfterPasting--;\n\t }\n\t break;\n\t }\n\t //XXX ...else we need to continue modifying the result for the 'replace' option\n\t\n\t // d. Until there are numbers to paste, replace the initial numbers one by one, and still do the range test.\n\t // Stop when you have no more numbers to paste, or if you are out of the range limits.\n\t // If you do get to the range limits, use the previous known good value within those limits.\n\t // Note: The numbers are replaced one by one, in the integer then decimal part, while ignoring the decimal character\n\t //TODO What should happen if the user try to paste a decimal number? Should we override the current initial decimal character in favor of this new one? If we do, then we have to recalculate the vMin/vMax from the start in order to take into account this new decimal character position..\n\t var lastGoodKnownResultIndex = caretPositionOnInitialTextAfterPasting;\n\t var lastGoodKnownResultSize = lastGoodKnownResult.length;\n\t\n\t while (pastedTextIndex < pastedText.length && lastGoodKnownResultIndex < lastGoodKnownResultSize) {\n\t if (lastGoodKnownResult[lastGoodKnownResultIndex] === '.') {\n\t // We skip the decimal character 'replacement'. That way, we do not change the decimal character position regarding the remaining numbers.\n\t lastGoodKnownResultIndex++;\n\t continue;\n\t }\n\t\n\t // This replace one character at a time\n\t result = replaceCharAt(lastGoodKnownResult, lastGoodKnownResultIndex, pastedText[pastedTextIndex]);\n\t\n\t // Check the range limits\n\t if (!checkIfInRange(result, minParse, maxParse)) {\n\t // The result is out of the range limits, stop the loop here\n\t break;\n\t }\n\t\n\t // Save the last good known result\n\t lastGoodKnownResult = result;\n\t\n\t // Update the local variables for the next loop\n\t pastedTextIndex++;\n\t lastGoodKnownResultIndex++;\n\t }\n\t\n\t // Update the last caret position where to insert a new number\n\t caretPositionOnInitialTextAfterPasting = lastGoodKnownResultIndex;\n\t\n\t if (leftPartContainedADot) {\n\t // If a dot has been removed for the part on the left of the caret, we decrement the caret index position\n\t caretPositionOnInitialTextAfterPasting--;\n\t }\n\t\n\t result = lastGoodKnownResult;\n\t\n\t break;\n\t /* 4c. Normal paste behavior:\n\t * Insert the pasted number inside the current unformatted text, at the right caret position or selection\n\t */\n\t case 'error':\n\t case 'ignore':\n\t case 'clamp':\n\t default:\n\t // 1. Generate the unformatted result\n\t var leftFormattedPart2 = initialFormattedValue.slice(0, selectionStart);\n\t var rightFormattedPart2 = initialFormattedValue.slice(selectionEnd, initialFormattedValue.length);\n\t\n\t if (selectionStart !== selectionEnd) {\n\t // a. If there is a selection, remove the selected part, and return the left and right part\n\t result = preparePastedText(leftFormattedPart2 + rightFormattedPart2, holder);\n\t } else {\n\t // b. Else if this is only one caret (and therefore no selection), then return the left and right part\n\t result = preparePastedText(initialFormattedValue, holder);\n\t }\n\t\n\t // Add back the negative sign if needed\n\t if (isInitialValueNegative) {\n\t result = setRawNegativeSign(result);\n\t }\n\t\n\t // Build the unformatted result string\n\t caretPositionOnInitialTextAfterPasting = convertCharacterCountToIndexPosition(countNumberCharactersOnTheCaretLeftSide(initialFormattedValue, selectionStart, holder.settings.decimalCharacter));\n\t if (isPasteNegativeAndInitialValueIsPositive) {\n\t // If the initial paste is negative and the initial value is not, then I must offset the caret position by one place to the right to take the additional hyphen into account\n\t caretPositionOnInitialTextAfterPasting++;\n\t //TODO Quid if the negative sign is not on the left (negativePositiveSignPlacement and currencySymbolPlacement)?\n\t }\n\t\n\t leftPart = result.slice(0, caretPositionOnInitialTextAfterPasting);\n\t rightPart = result.slice(caretPositionOnInitialTextAfterPasting, result.length);\n\t if (pastedText === '.') {\n\t // If the user only paste a single decimal character, then we remove the previously existing one (if any)\n\t if (contains(leftPart, '.')) {\n\t // If I remove a dot here, then I need to update the caret position (decrement it by 1) when positioning it\n\t // To do so, we keep that info in order to modify the caret position later\n\t leftPartContainedADot = true;\n\t leftPart = leftPart.replace('.', '');\n\t }\n\t rightPart = rightPart.replace('.', '');\n\t }\n\t // -- Here, we are good to go to continue on the same basis\n\t\n\t // Generate the unformatted result\n\t result = '' + leftPart + pastedText + rightPart;\n\t\n\t // 2. Calculate the caret position in the unformatted value, for later use\n\t if (selectionStart === selectionEnd) {\n\t // There is no selection, then the caret position is set after the pasted text\n\t var indexWherePastedTextHasBeenInserted = convertCharacterCountToIndexPosition(countNumberCharactersOnTheCaretLeftSide(initialFormattedValue, selectionStart, holder.settings.decimalCharacter));\n\t caretPositionOnInitialTextAfterPasting = indexWherePastedTextHasBeenInserted + pastedText.length; // I must not count the characters that have been removed from the pasted text (ie. '.')\n\t } else {\n\t if (isAllInputTextSelected) {\n\t // Special case when all the input text is selected before pasting, which means we'll completely erase its content and paste only the clipboard content\n\t caretPositionOnInitialTextAfterPasting = result.length;\n\t } else if (rightPart === '') {\n\t // If the user selected from the caret position to the end of the input (on the far right)\n\t caretPositionOnInitialTextAfterPasting = convertCharacterCountToIndexPosition(countNumberCharactersOnTheCaretLeftSide(initialFormattedValue, selectionStart, holder.settings.decimalCharacter)) + pastedText.length;\n\t } else {\n\t // Normal case\n\t var indexSelectionEndInRawValue = convertCharacterCountToIndexPosition(countNumberCharactersOnTheCaretLeftSide(initialFormattedValue, selectionEnd, holder.settings.decimalCharacter));\n\t\n\t // Here I must not count the characters that have been removed from the pasted text (ie. '.'), or the thousand separators in the initial selected text\n\t var selectedText = e.target.value.slice(selectionStart, selectionEnd);\n\t caretPositionOnInitialTextAfterPasting = indexSelectionEndInRawValue - selectionSize + countCharInText(holder.settings.digitGroupSeparator, selectedText) + pastedText.length;\n\t }\n\t }\n\t\n\t // Modify the caret position for special cases, only if the whole input has not been selected\n\t if (!isAllInputTextSelected) {\n\t if (isPasteNegativeAndInitialValueIsPositive) {\n\t // If the pasted value has a '-' sign, but the initial value does not, offset the index by one\n\t caretPositionOnInitialTextAfterPasting++;\n\t }\n\t\n\t if (leftPartContainedADot) {\n\t // If a dot has been removed for the part on the left of the caret, we decrement the caret index position\n\t caretPositionOnInitialTextAfterPasting--;\n\t }\n\t }\n\t }\n\t\n\t // 5. Check if the result is a valid number, if not, drop the paste and do nothing.\n\t if (!isNumber(result) || result === '') {\n\t if (holder.settings.onInvalidPaste === 'error') {\n\t throwError('The pasted value \\'' + rawPastedText + '\\' would result into an invalid content \\'' + result + '\\'.'); //TODO Should we send a warning instead of throwing an error?\n\t //TODO This is not DRY ; refactor with above\n\t }\n\t return;\n\t }\n\t\n\t // 6. If it's a valid number, check if it falls inside the minimum and maximum value. If this fails, modify the value following this procedure :\n\t /*\n\t * If 'error' (this is the default) :\n\t * - Normal paste behavior.\n\t * - Try to set the new value, if it fails, then throw an error in the console.\n\t * - Do not change the input value, do not change the current selection.\n\t * If 'ignore' :\n\t * - Normal paste behavior.\n\t * - Try to set the new value, if it fails, do nothing more.\n\t * - Do not change the input value, do not change the current selection.\n\t * If 'clamp' :\n\t * - Normal paste behavior.\n\t * - Try to set the new value, if it fails, set the value to the minimum or maximum limit, whichever is closest to the\n\t * paste result.\n\t * - Change the caret position to be positioned on the left hand side of the decimal character.\n\t * If 'truncate' :\n\t * - Truncate paste behavior.\n\t * - Try to set the new value, until it fails (if the result is out of the min and max value limits).\n\t * - Drop the remaining non-pasted numbers, and keep the last known non-failing result.\n\t * - Change the caret position to be positioned after the last pasted character.\n\t * If 'replace' :\n\t * - Replace paste behavior.\n\t * - Try to set the new value, until it fails (if the result is out of the min and max value limits).\n\t * - Then try to replace as many numbers as possible with the pasted ones. Once it fails, keep the last known non-failing result.\n\t * - Change the caret position to be positioned after the last pasted character.\n\t */\n\t var valueHasBeenSet = false;\n\t var valueHasBeenClamped = false;\n\t try {\n\t $this.autoNumeric('set', result);\n\t valueHasBeenSet = true;\n\t } catch (error) {\n\t var clampedValue = void 0;\n\t switch (holder.settings.onInvalidPaste) {\n\t case 'clamp':\n\t clampedValue = clampToRangeLimits(result, holder.settings);\n\t try {\n\t $this.autoNumeric('set', clampedValue);\n\t } catch (error) {\n\t throwError('Fatal error: Unable to set the clamped value \\'' + clampedValue + '\\'.');\n\t }\n\t\n\t valueHasBeenClamped = true;\n\t valueHasBeenSet = true;\n\t result = clampedValue; // This is used only for setting the caret position later\n\t break;\n\t case 'error':\n\t case 'truncate':\n\t case 'replace':\n\t // Throw an error message\n\t throwError('The pasted value \\'' + rawPastedText + '\\' results in a value \\'' + result + '\\' that is outside of the minimum [' + holder.settings.minimumValue + '] and maximum [' + holder.settings.maximumValue + '] value range.');\n\t // falls through\n\t case 'ignore':\n\t // Do nothing\n\t // falls through\n\t default:\n\t return; // ...and nothing else should be changed\n\t }\n\t }\n\t\n\t // 7. Then lastly, set the caret position at the right logical place\n\t var caretPositionInFormattedNumber = void 0;\n\t if (valueHasBeenSet) {\n\t switch (holder.settings.onInvalidPaste) {\n\t case 'clamp':\n\t if (valueHasBeenClamped) {\n\t if (holder.settings.currencySymbolPlacement === 's') {\n\t setElementSelection(e.target, e.target.value.length - holder.settings.currencySymbol.length); // This puts the caret on the right of the last decimal place\n\t } else {\n\t setElementSelection(e.target, e.target.value.length); // ..and this on the far right\n\t }\n\t\n\t break;\n\t } // else if the value has not been clamped, the default behavior is used...\n\t // falls through\n\t case 'error':\n\t case 'ignore':\n\t case 'truncate':\n\t case 'replace':\n\t default:\n\t // Whenever one or multiple characters are pasted, this means we have to manage the potential thousand separators that could be added by the formatting\n\t caretPositionInFormattedNumber = findCaretPositionInFormattedNumber(result, caretPositionOnInitialTextAfterPasting, e.target.value, holder.settings.decimalCharacter);\n\t setElementSelection(e.target, caretPositionInFormattedNumber);\n\t }\n\t }\n\t\n\t // 8. We make sure we send an input event only if the result is different than the initial value before the paste\n\t if (valueHasBeenSet && initialFormattedValue !== e.target.value) {\n\t // On a 'normal' non-autoNumeric input, an `input` event is sent when a paste is done. We mimic that.\n\t triggerEvent('input', e.target);\n\t }\n\t }\n\t\n\t /**\n\t * When focusing out of the input, we check if the value has changed, and if it has, then we send a `change` event (since the native one would have been prevented by `e.preventDefault()` called in the other event listeners).\n\t *\n\t * @param {AutoNumericHolder} holder\n\t * @param {Event} e\n\t */\n\t function onBlur(holder, e) {\n\t if (e.target.value !== holder.valueOnFocus) {\n\t triggerEvent('change', e.target);\n\t // e.preventDefault(); // ...and immediately prevent the browser to send a second change event (that somehow gets picked up by jQuery, but not by `addEventListener()` //FIXME KNOWN BUG : This does not prevent the second change event to be picked up by jQuery, which adds '.00' at the end of an integer\n\t }\n\t }\n\t\n\t /**\n\t * Handler for 'submit' events\n\t *\n\t * @param {object} $this jQuery-selected DOM element\n\t * @param {AutoNumericHolder} holder\n\t */\n\t function onSubmit($this, holder) {\n\t $this.closest('form').on('submit.autoNumeric', function () {\n\t if (holder) {\n\t var $settings = holder.settingsClone;\n\t\n\t if ($settings.unformatOnSubmit) {\n\t $this.val($settings.rawValue);\n\t }\n\t }\n\t });\n\t }\n\t\n\t /**\n\t * Return the jQuery selected input if the tag and type are supported by autoNumeric.\n\t *\n\t * @param {object} $this jQuery-selected DOM element\n\t * @returns {boolean|*}\n\t */\n\t function getInputIfSupportedTagAndType($this) {\n\t // Supported input type\n\t var $input = $this.is('input[type=text], input[type=hidden], input[type=tel], input:not([type])');\n\t\n\t // Checks for non-supported input types\n\t if (!$input && $this.prop('tagName').toLowerCase() === 'input') {\n\t throwError('The input type \"' + $this.prop('type') + '\" is not supported by autoNumeric');\n\t }\n\t\n\t // Checks for non-supported tags\n\t var currentElementTag = $this.prop('tagName').toLowerCase();\n\t if (currentElementTag !== 'input' && !isInArray(currentElementTag, allowedTagList)) {\n\t throwError('The <' + currentElementTag + '> tag is not supported by autoNumeric');\n\t }\n\t\n\t return $input;\n\t }\n\t\n\t /**\n\t * Formats the default value on page load.\n\t * This is called only if the `formatOnPageLoad` option is set to `true`.\n\t *\n\t * @param {object} settings\n\t * @param {object} $input jQuery-selected element\n\t * @param {object} $this jQuery-selected DOM element\n\t */\n\t function formatDefaultValueOnPageLoad(settings, $input, $this) {\n\t var setValue = true;\n\t\n\t if ($input) {\n\t var currentValue = $this.val();\n\t /*\n\t * If the input value has been set by the dev, but not directly as an attribute in the html, then it takes\n\t * precedence and should get formatted on init (if this input value is a valid number and that the\n\t * developer wants it formatted on init (cf. `settings.formatOnPageLoad`)).\n\t * Note; this is true whatever the developer has set for `data-an-default` in the html (asp.net users).\n\t *\n\t * In other words : if `defaultValueOverride` is not null, it means the developer is trying to prevent postback problems.\n\t * But if `input.value` is set to a number, and `$this.attr('value')` is not set, then it means the dev has\n\t * changed the input value, and then it means we should not overwrite his own decision to do so.\n\t * Hence, if `defaultValueOverride` is not null, but `input.value` is a number and `$this.attr('value')` is not set,\n\t * we should ignore `defaultValueOverride` altogether.\n\t */\n\t var unLocalizedCurrentValue = toNumericValue(currentValue, settings); // This allows to use a localized value on startup oDec\n\t if (settings.formatOnPageLoad && currentValue !== '' && isUndefinedOrNullOrEmpty($this.attr('value'))) {\n\t // Check if the `value` is valid or not\n\t if (!isNaN(unLocalizedCurrentValue) && Infinity !== unLocalizedCurrentValue) {\n\t $this.autoNumeric('set', unLocalizedCurrentValue);\n\t setValue = false;\n\t } else {\n\t // If not, inform the developer that nothing usable has been provided\n\t throwError('The value [' + currentValue + '] used in the input is not a valid value autoNumeric can work with.');\n\t }\n\t } else {\n\t /* Checks for :\n\t * - page reload from back button, and\n\t * - ASP.net form post back\n\t * The following HTML data attribute is REQUIRED (data-an-default=\"same value as the value attribute\")\n\t * example: \n\t */\n\t if (settings.defaultValueOverride !== null && settings.defaultValueOverride.toString() !== currentValue || settings.defaultValueOverride === null && currentValue !== '' && currentValue !== $this.attr('value') || currentValue !== '' && $this.attr('type') === 'hidden' && !isNumber(unLocalizedCurrentValue)) {\n\t if (settings.decimalPlacesShownOnFocus !== null && settings.saveValueToSessionStorage || settings.scaleDivisor && settings.saveValueToSessionStorage) {\n\t settings.rawValue = saveValueToPersistentStorage($this[0], settings, 'get');\n\t }\n\t\n\t // If the decimalPlacesShownOnFocus value should NOT be saved in sessionStorage\n\t if (!settings.saveValueToSessionStorage) {\n\t var toStrip = void 0;\n\t\n\t if (settings.negativeBracketsTypeOnBlur !== null && settings.negativeSignCharacter !== '') {\n\t settings.hasFocus = true;\n\t toStrip = toggleNegativeBracket(currentValue, settings);\n\t } else {\n\t toStrip = currentValue;\n\t }\n\t\n\t if ((settings.negativePositiveSignPlacement === 's' || settings.negativePositiveSignPlacement !== 'p' && settings.currencySymbolPlacement === 's') && settings.negativeSignCharacter !== '' && isNegative(currentValue)) {\n\t settings.rawValue = settings.negativeSignCharacter + stripAllNonNumberCharacters(toStrip, settings, true);\n\t } else {\n\t settings.rawValue = stripAllNonNumberCharacters(toStrip, settings, true);\n\t }\n\t }\n\t\n\t setValue = false;\n\t }\n\t }\n\t\n\t if (currentValue === '') {\n\t switch (settings.emptyInputBehavior) {\n\t case 'focus':\n\t setValue = false;\n\t break;\n\t case 'always':\n\t $this.val(settings.currencySymbol);\n\t setValue = false;\n\t break;\n\t case 'zero':\n\t $this.autoNumeric('set', '0');\n\t setValue = false;\n\t break;\n\t default:\n\t //\n\t }\n\t } else if (setValue && currentValue === $this.attr('value')) {\n\t $this.autoNumeric('set', currentValue);\n\t }\n\t }\n\t\n\t if (isInArray($this.prop('tagName').toLowerCase(), settings.tagList) && $this.text() !== '') {\n\t if (settings.defaultValueOverride !== null) {\n\t if (settings.defaultValueOverride === $this.text()) {\n\t $this.autoNumeric('set', $this.text());\n\t }\n\t } else {\n\t $this.autoNumeric('set', $this.text());\n\t }\n\t }\n\t }\n\t\n\t /**\n\t * Enhance the user experience by modifying the default `negativePositiveSignPlacement` option depending on `currencySymbol` and `currencySymbolPlacement`.\n\t *\n\t * If the user has not set the placement of the negative sign (`negativePositiveSignPlacement`), but has set a currency symbol (`currencySymbol`),\n\t * then we modify the default value of `negativePositiveSignPlacement` in order to keep the resulting output logical by default :\n\t * - \"$-1,234.56\" instead of \"-$1,234.56\" ({currencySymbol: \"$\", negativePositiveSignPlacement: \"r\"})\n\t * - \"-1,234.56$\" instead of \"1,234.56-$\" ({currencySymbol: \"$\", currencySymbolPlacement: \"s\", negativePositiveSignPlacement: \"p\"})\n\t *\n\t * @param {object} settings\n\t */\n\t function correctNegativePositiveSignPlacementOption(settings) {\n\t // If negativePositiveSignPlacement is already set, we do not overwrite it\n\t if (!isNull(settings.negativePositiveSignPlacement)) {\n\t return;\n\t }\n\t\n\t if (!isUndefined(settings) && isUndefinedOrNullOrEmpty(settings.negativePositiveSignPlacement) && !isUndefinedOrNullOrEmpty(settings.currencySymbol)) {\n\t switch (settings.currencySymbolPlacement) {\n\t case 's':\n\t settings.negativePositiveSignPlacement = 'p'; // Default -1,234.56 €\n\t break;\n\t case 'p':\n\t settings.negativePositiveSignPlacement = 'l'; // Default -$1,234.56\n\t break;\n\t default:\n\t //\n\t }\n\t } else {\n\t // Sets the default value if `negativePositiveSignPlacement` is `null`\n\t settings.negativePositiveSignPlacement = 'l';\n\t }\n\t }\n\t\n\t /**\n\t * Analyze and save the minimumValue and maximumValue integer size for later uses\n\t *\n\t * @param {object} settings\n\t */\n\t function calculateVMinAndVMaxIntegerSizes(settings) {\n\t var _settings$maximumValu = settings.maximumValue.toString().split('.'),\n\t _settings$maximumValu2 = _slicedToArray(_settings$maximumValu, 1),\n\t maximumValueIntegerPart = _settings$maximumValu2[0];\n\t\n\t var _ref3 = !settings.minimumValue && settings.minimumValue !== 0 ? [] : settings.minimumValue.toString().split('.'),\n\t _ref4 = _slicedToArray(_ref3, 1),\n\t minimumValueIntegerPart = _ref4[0];\n\t\n\t maximumValueIntegerPart = maximumValueIntegerPart.replace('-', '');\n\t minimumValueIntegerPart = minimumValueIntegerPart.replace('-', '');\n\t\n\t settings.mIntPos = Math.max(maximumValueIntegerPart.length, 1);\n\t settings.mIntNeg = Math.max(minimumValueIntegerPart.length, 1);\n\t }\n\t\n\t /**\n\t * Modify `decimalPlacesOverride` as needed\n\t *\n\t * @param {object} settings\n\t */\n\t function correctDecimalPlacesOverrideOption(settings) {\n\t if (isNull(settings.decimalPlacesOverride)) {\n\t settings.decimalPlacesOverride = maximumVMinAndVMaxDecimalLength(settings.minimumValue, settings.maximumValue);\n\t }\n\t settings.oDec = String(settings.decimalPlacesOverride);\n\t\n\t // Most calculus assume `decimalPlacesOverride` is an integer, the following statement makes it clear (otherwise having it as a string leads to problems in rounding for instance)\n\t settings.decimalPlacesOverride = Number(settings.decimalPlacesOverride);\n\t }\n\t\n\t /**\n\t * Sets the alternative decimal separator key.\n\t *\n\t * @param {object} settings\n\t */\n\t function setsAlternativeDecimalSeparatorCharacter(settings) {\n\t if (isNull(settings.decimalCharacterAlternative) && Number(settings.decimalPlacesOverride) > 0) {\n\t if (settings.decimalCharacter === '.' && settings.digitGroupSeparator !== ',') {\n\t settings.decimalCharacterAlternative = ',';\n\t } else if (settings.decimalCharacter === ',' && settings.digitGroupSeparator !== '.') {\n\t settings.decimalCharacterAlternative = '.';\n\t }\n\t }\n\t }\n\t\n\t /**\n\t * Caches regular expressions for stripAllNonNumberCharacters\n\t *\n\t * @param {object} settings\n\t */\n\t function cachesUsualRegularExpressions(settings) {\n\t var allNumbersReg = '[0-9]';\n\t var noAllNumbersReg = '[^0-9]';\n\t\n\t // Test if there is a negative character in the string\n\t var aNegReg = settings.negativeSignCharacter ? '([-\\\\' + settings.negativeSignCharacter + ']?)' : '(-?)';\n\t settings.aNegRegAutoStrip = aNegReg;\n\t\n\t var negativeSignRegPart = void 0;\n\t if (settings.negativeSignCharacter) {\n\t negativeSignRegPart = '\\\\' + settings.negativeSignCharacter;\n\t } else {\n\t negativeSignRegPart = '';\n\t }\n\t settings.skipFirstAutoStrip = new RegExp(aNegReg + '[^-' + negativeSignRegPart + '\\\\' + settings.decimalCharacter + allNumbersReg + '].*?(' + allNumbersReg + '|\\\\' + settings.decimalCharacter + allNumbersReg + ')');\n\t settings.skipLastAutoStrip = new RegExp('(' + allNumbersReg + '\\\\' + settings.decimalCharacter + '?)[^\\\\' + settings.decimalCharacter + allNumbersReg + ']' + noAllNumbersReg + '*$');\n\t\n\t var allowed = '-0123456789\\\\' + settings.decimalCharacter;\n\t settings.allowedAutoStrip = new RegExp('[^' + allowed + ']', 'g');\n\t settings.numRegAutoStrip = new RegExp(aNegReg + '(?:\\\\' + settings.decimalCharacter + '?(' + allNumbersReg + '+\\\\' + settings.decimalCharacter + allNumbersReg + '+)|(' + allNumbersReg + '*(?:\\\\' + settings.decimalCharacter + allNumbersReg + '*)?))');\n\t\n\t // Using this regex version `^${settings.aNegRegAutoStrip}0*(\\\\d|$)` entirely clear the input on blur\n\t settings.stripReg = new RegExp('^' + settings.aNegRegAutoStrip + '0*(' + allNumbersReg + ')');\n\t }\n\t\n\t /**\n\t * Modify the user settings to make them 'exploitable' later.\n\t *\n\t * @param {object} settings\n\t */\n\t function transformOptionsValuesToDefaultTypes(settings) {\n\t $.each(settings, function (key, value) {\n\t // Convert the string 'true' and 'false' to real Boolean\n\t if (value === 'true' || value === 'false') {\n\t settings[key] = value === 'true';\n\t }\n\t\n\t // Convert numbers in options to strings\n\t //TODO if a value is already of type 'Number', shouldn't we keep it as a number for further manipulation, instead of using a string?\n\t if (typeof value === 'number' && key !== 'aScale') {\n\t settings[key] = value.toString();\n\t }\n\t });\n\t }\n\t\n\t /**\n\t * Convert the old settings options name to new ones.\n\t *\n\t * @param {object} options\n\t */\n\t function convertOldOptionsToNewOnes(options) {\n\t //TODO Delete this function once the old options are not used anymore\n\t var oldOptionsConverter = {\n\t // Old option name, with their corresponding new option\n\t aSep: 'digitGroupSeparator',\n\t nSep: 'noSeparatorOnFocus',\n\t dGroup: 'digitalGroupSpacing',\n\t aDec: 'decimalCharacter',\n\t altDec: 'decimalCharacterAlternative',\n\t aSign: 'currencySymbol',\n\t pSign: 'currencySymbolPlacement',\n\t pNeg: 'negativePositiveSignPlacement',\n\t aSuffix: 'suffixText',\n\t oLimits: 'overrideMinMaxLimits',\n\t vMax: 'maximumValue',\n\t vMin: 'minimumValue',\n\t mDec: 'decimalPlacesOverride',\n\t eDec: 'decimalPlacesShownOnFocus',\n\t scaleDecimal: 'scaleDecimalPlaces',\n\t aStor: 'saveValueToSessionStorage',\n\t mRound: 'roundingMethod',\n\t aPad: 'allowDecimalPadding',\n\t nBracket: 'negativeBracketsTypeOnBlur',\n\t wEmpty: 'emptyInputBehavior',\n\t lZero: 'leadingZero',\n\t aForm: 'formatOnPageLoad',\n\t sNumber: 'selectNumberOnly',\n\t anDefault: 'defaultValueOverride',\n\t unSetOnSubmit: 'unformatOnSubmit',\n\t outputType: 'outputFormat',\n\t debug: 'showWarnings',\n\t // Current options :\n\t digitGroupSeparator: true,\n\t noSeparatorOnFocus: true,\n\t digitalGroupSpacing: true,\n\t decimalCharacter: true,\n\t decimalCharacterAlternative: true,\n\t currencySymbol: true,\n\t currencySymbolPlacement: true,\n\t negativePositiveSignPlacement: true,\n\t showPositiveSign: true,\n\t suffixText: true,\n\t overrideMinMaxLimits: true,\n\t maximumValue: true,\n\t minimumValue: true,\n\t decimalPlacesOverride: true,\n\t decimalPlacesShownOnFocus: true,\n\t scaleDivisor: true,\n\t scaleDecimalPlaces: true,\n\t scaleSymbol: true,\n\t saveValueToSessionStorage: true,\n\t onInvalidPaste: true,\n\t roundingMethod: true,\n\t allowDecimalPadding: true,\n\t negativeBracketsTypeOnBlur: true,\n\t emptyInputBehavior: true,\n\t leadingZero: true,\n\t formatOnPageLoad: true,\n\t selectNumberOnly: true,\n\t defaultValueOverride: true,\n\t unformatOnSubmit: true,\n\t outputFormat: true,\n\t showWarnings: true,\n\t failOnUnknownOption: true,\n\t //FIXME Find a way to exclude those internal data from the settings object (ideally by using another object, or better yet, class attributes) -->\n\t hasFocus: true,\n\t runOnce: true,\n\t rawValue: true,\n\t trailingNegative: true,\n\t caretFix: true,\n\t throwInput: true,\n\t strip: true,\n\t tagList: true,\n\t negativeSignCharacter: true,\n\t positiveSignCharacter: true,\n\t mIntPos: true,\n\t mIntNeg: true,\n\t oDec: true,\n\t oPad: true,\n\t oBracket: true,\n\t oSep: true,\n\t oSign: true,\n\t oSuffix: true,\n\t aNegRegAutoStrip: true,\n\t skipFirstAutoStrip: true,\n\t skipLastAutoStrip: true,\n\t allowedAutoStrip: true,\n\t numRegAutoStrip: true,\n\t stripReg: true,\n\t holder: true\n\t };\n\t\n\t for (var option in options) {\n\t if (options.hasOwnProperty(option)) {\n\t if (oldOptionsConverter[option] === true) {\n\t // If the option is a 'new' option, we continue looping\n\t continue;\n\t }\n\t\n\t if (oldOptionsConverter.hasOwnProperty(option)) {\n\t // Else we have an 'old' option name\n\t warning('You are using the deprecated option name \\'' + option + '\\'. Please use \\'' + oldOptionsConverter[option] + '\\' instead from now on. The old option name will be dropped soon.', true);\n\t\n\t // Then we modify the initial option object to use the new options instead of the old ones\n\t options[oldOptionsConverter[option]] = options[option];\n\t delete options[option];\n\t } else if (options.failOnUnknownOption) {\n\t // ...or the option name is unknown. This means there is a problem with the options object, therefore we throw an error.\n\t throwError('Option name \\'' + option + '\\' is unknown. Please fix the options passed to autoNumeric');\n\t }\n\t }\n\t }\n\t }\n\t\n\t /**\n\t * Analyse the settings/options passed by the user, validate and clean them, then return them.\n\t * Note: This returns `null` if somehow the settings returned by jQuery is not an object.\n\t *\n\t * @param {object} options\n\t * @param {object} $this jQuery-selected DOM element\n\t * @param {boolean} update - If TRUE, then the settings already exists and this function only updates them instead of recreating them from scratch\n\t * @returns {object|null}\n\t */\n\t function getInitialSettings(options, $this) {\n\t var update = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;\n\t\n\t // Attempt to grab \"autoNumeric\" settings. If they do not exist, it returns \"undefined\".\n\t var settings = $this.data('autoNumeric');\n\t\n\t // If the user used old options, we convert them to new ones\n\t if (update || !isNull(options)) {\n\t convertOldOptionsToNewOnes(options);\n\t }\n\t\n\t if (update || isUndefined(settings)) {\n\t if (update) {\n\t // The settings are updated\n\t settings = $.extend(settings, options);\n\t } else {\n\t // If we couldn't grab any settings, create them from the default ones and combine them with the options passed\n\t // The settings are generated for the first time\n\t // This also attempt to grab the HTML5 data. If it doesn't exist, we'll get \"undefined\"\n\t var tagData = $this.data();\n\t settings = $.extend({}, defaultSettings, tagData, options, {\n\t hasFocus: false,\n\t runOnce: false,\n\t rawValue: '',\n\t trailingNegative: false,\n\t caretFix: false,\n\t androidSelectionStart: null,\n\t throwInput: true, // Throw input event\n\t strip: true,\n\t tagList: allowedTagList\n\t });\n\t }\n\t\n\t // Modify the user settings to make them 'exploitable'\n\t transformOptionsValuesToDefaultTypes(settings);\n\t\n\t // Improve the `negativePositiveSignPlacement` option if needed\n\t correctNegativePositiveSignPlacementOption(settings);\n\t\n\t // Set the negative and positive signs, as needed\n\t settings.negativeSignCharacter = settings.minimumValue < 0 ? '-' : '';\n\t settings.positiveSignCharacter = settings.maximumValue >= 0 ? '+' : '';\n\t\n\t // Additional changes to the settings object (from the original autoCode() function)\n\t runCallbacksFoundInTheSettingsObject($this, settings);\n\t calculateVMinAndVMaxIntegerSizes(settings);\n\t correctDecimalPlacesOverrideOption(settings);\n\t setsAlternativeDecimalSeparatorCharacter(settings);\n\t cachesUsualRegularExpressions(settings);\n\t\n\t // Validate the settings\n\t validate(settings, false); // Throws if necessary\n\t\n\t // Original settings saved for use when decimalPlacesShownOnFocus, scaleDivisor & noSeparatorOnFocus options are being used\n\t keepAnOriginalSettingsCopy(settings);\n\t\n\t // Save our new settings\n\t $this.data('autoNumeric', settings);\n\t\n\t return settings;\n\t } else {\n\t return null;\n\t }\n\t }\n\t\n\t /**\n\t * Convert the `value` parameter that can either be :\n\t * - a real number,\n\t * - a string representing a real number, or\n\t * - a string representing a localized number (with specific group separators and decimal character),\n\t * ...to a string representing a real 'javascript' number (ie. '1234' or '1234.567').\n\t *\n\t * This function returns `NaN` if such conversion fails.\n\t *\n\t * @param {int|float|string} value\n\t * @param {object} settings\n\t * @returns {string|NaN}\n\t */\n\t function toNumericValue(value, settings) {\n\t var result = void 0;\n\t if (isNumber(Number(value))) {\n\t // The value has either already been stripped, or a 'real' javascript number is passed as a parameter\n\t result = value;\n\t } else {\n\t // Else if it's a string that `Number()` cannot typecast, then we try to convert the localized numeric string to a numeric one\n\t // Convert the value to a numeric string, stripping unnecessary characters in the process\n\t result = convertToNumericString(value.toString(), settings);\n\t\n\t // If the result is still not a numeric string, then we throw a warning\n\t if (!isNumber(Number(result))) {\n\t warning('The value \"' + value + '\" being \"set\" is not numeric and therefore cannot be used appropriately.', settings.showWarnings);\n\t result = NaN;\n\t }\n\t }\n\t\n\t return result;\n\t }\n\t\n\t /**\n\t * Methods supported by autoNumeric\n\t */\n\t var methods = {\n\t /**\n\t * Method to initialize autoNumeric and attach the settings (options can be passed as a parameter)\n\t * The options passed as a parameter is an object that contains the settings (ie. {digitGroupSeparator: \".\", decimalCharacter: \",\", currencySymbol: '€ '})\n\t *\n\t * @example\n\t * $(someSelector).autoNumeric('init'); // Initiate autoNumeric with defaults\n\t * $(someSelector).autoNumeric(); // Initiate autoNumeric with defaults\n\t * $(someSelector).autoNumeric('init', {options}); // Initiate autoNumeric with options\n\t * $(someSelector).autoNumeric({options}); // Initiate autoNumeric with options\n\t *\n\t * @param {object} options\n\t * @returns {*|{statements, branches, lines, functions, excludes, overrides}|{statements, branches, lines, functions, excludes}|{statements, lines, branches, functions, excludes}}\n\t */\n\t init: function init(options) {\n\t return this.each(function () {\n\t var $this = $(this);\n\t var $input = getInputIfSupportedTagAndType($this);\n\t\n\t var settings = getInitialSettings(options, $this, false);\n\t if (isNull(settings)) {\n\t return this;\n\t }\n\t\n\t // Create the AutoNumericHolder object that store the field properties\n\t var holder = getAutoNumericHolder($this, settings, false);\n\t\n\t if (!settings.runOnce && settings.formatOnPageLoad) {\n\t formatDefaultValueOnPageLoad(settings, $input, $this);\n\t }\n\t\n\t settings.runOnce = true;\n\t\n\t // Add the events listeners to supported input types (\"text\", \"hidden\", \"tel\" and no type)\n\t if ($input) {\n\t this.addEventListener('focusin', function (e) {\n\t onFocusInAndMouseEnter($this, holder, e);\n\t }, false);\n\t this.addEventListener('mouseenter', function (e) {\n\t onFocusInAndMouseEnter($this, holder, e);\n\t }, false);\n\t this.addEventListener('blur', function (e) {\n\t onFocusOutAndMouseLeave($this, holder, e);\n\t }, false);\n\t this.addEventListener('mouseleave', function (e) {\n\t onFocusOutAndMouseLeave($this, holder, e);\n\t }, false);\n\t this.addEventListener('keydown', function (e) {\n\t onKeydown(holder, e);\n\t }, false);\n\t this.addEventListener('keypress', function (e) {\n\t onKeypress(holder, e);\n\t }, false);\n\t this.addEventListener('input', function (e) {\n\t onInput(holder, e);\n\t }, false);\n\t this.addEventListener('keyup', function (e) {\n\t onKeyup(holder, settings, e);\n\t }, false);\n\t this.addEventListener('blur', function (e) {\n\t onBlur(holder, e);\n\t }, false);\n\t this.addEventListener('paste', function (e) {\n\t onPaste($this, holder, e);\n\t }, false);\n\t onSubmit($this, holder); //TODO Switch to `addEventListener'\n\t }\n\t });\n\t },\n\t\n\t\n\t /**\n\t * Method to stop and remove autoNumeric for the current element.\n\t * Note: this does not remove the formatting.\n\t *\n\t * @example $(someSelector).autoNumeric(\"destroy\"); // Destroys autoNumeric on this selected element\n\t *\n\t * @returns {*|jQuery}\n\t */\n\t destroy: function destroy() {\n\t return $(this).each(function () {\n\t var $this = getCurrentElement(this);\n\t var settings = $this.data('autoNumeric');\n\t if ((typeof settings === 'undefined' ? 'undefined' : _typeof(settings)) === 'object') {\n\t $this.val('');\n\t saveValueToPersistentStorage($this[0], settings, 'wipe');\n\t $this.removeData('autoNumeric');\n\t $this.off('.autoNumeric');\n\t }\n\t });\n\t },\n\t\n\t\n\t /**\n\t * Method to clear the value from sessionStorage (or cookie, depending on browser supports).\n\t *\n\t * @example $(someSelector).autoNumeric(\"wipe\"); // Removes session storage and cookies from memory\n\t *\n\t * @returns {*|jQuery}\n\t */\n\t wipe: function wipe() {\n\t return $(this).each(function () {\n\t var $this = getCurrentElement(this);\n\t var settings = $this.data('autoNumeric');\n\t if ((typeof settings === 'undefined' ? 'undefined' : _typeof(settings)) === 'object') {\n\t $this.val('');\n\t settings.rawValue = '';\n\t saveValueToPersistentStorage($this[0], settings, 'wipe');\n\t }\n\t });\n\t },\n\t\n\t\n\t /**\n\t * Method that updates the autoNumeric settings.\n\t * It can be called multiple times if needed.\n\t * The options passed as a parameter is an object that contains the settings (ie. {digitGroupSeparator: \".\", decimalCharacter: \",\", currencySymbol: '€ '}).\n\t *\n\t * @example $(someSelector).autoNumeric(\"update\", {options}); // Updates the settings\n\t *\n\t * @param {object} options\n\t * @returns {*|jQuery}\n\t */\n\t update: function update(options) {\n\t return $(this).each(function () {\n\t // Retrieve the current unformatted input value\n\t var $this = getCurrentElement(this);\n\t var strip = $this.autoNumeric('get');\n\t\n\t // Update the settings\n\t var settings = getInitialSettings(options, $this, true);\n\t\n\t // Update the AutoNumericHolder object that store the field properties\n\t getAutoNumericHolder($this, settings, true);\n\t\n\t // Reformat the input value with the new settings\n\t if ($this.val() !== '' || $this.text() !== '') {\n\t return $this.autoNumeric('set', strip);\n\t }\n\t });\n\t },\n\t\n\t\n\t /**\n\t * Method to format the value passed as a parameter.\n\t * If the value is passed as a string, it can be an integer '1234' or a double '1234.56789'\n\t * and must contain only numbers and one decimal (period) character\n\t *\n\t * @example $(someSelector).autoNumeric('set', '12345.67'); // Formats the value being passed as the second parameter\n\t *\n\t * @param {*} newValue\n\t * @returns {*|jQuery}\n\t */\n\t set: function set(newValue) {\n\t return $(this).each(function () {\n\t if (newValue === null || isUndefined(newValue)) {\n\t return;\n\t }\n\t\n\t //TODO This looks a lot like `getInputIfSupportedTagAndType()`. Is that necessary? Can the input element be changed since autoNumeric has been initialized?\n\t var $this = getCurrentElement(this);\n\t var settings = $this.data('autoNumeric');\n\t if ((typeof settings === 'undefined' ? 'undefined' : _typeof(settings)) !== 'object') {\n\t throwError('Initializing autoNumeric is required prior to calling the \"set\" method.');\n\t }\n\t // Reset the trailing negative settings, since it's possible the previous value was negative, but not the newly set one\n\t settings.trailingNegative = false;\n\t\n\t var $input = $this.is('input[type=text], input[type=hidden], input[type=tel], input:not([type])');\n\t\n\t var value = toNumericValue(newValue, settings);\n\t if (isNaN(value)) {\n\t return $this.val('');\n\t }\n\t\n\t if (value !== '') {\n\t var _checkIfInRangeWithOv5 = checkIfInRangeWithOverrideOption(value, settings),\n\t _checkIfInRangeWithOv6 = _slicedToArray(_checkIfInRangeWithOv5, 2),\n\t minTest = _checkIfInRangeWithOv6[0],\n\t maxTest = _checkIfInRangeWithOv6[1];\n\t // This test is needed by the showPositiveSign option\n\t\n\t\n\t var isZero = isZeroOrHasNoValue(value);\n\t if (isZero) {\n\t value = '0';\n\t }\n\t\n\t if (minTest && maxTest) {\n\t if ($input || isInArray($this.prop('tagName').toLowerCase(), settings.tagList)) {\n\t // to ensure rounding does not happen twice\n\t var hasBeenRounded = false;\n\t\n\t // rounds the the extended decimal places\n\t var tempDecimal = void 0;\n\t if (settings.decimalPlacesShownOnFocus) {\n\t tempDecimal = settings.decimalPlacesOverride;\n\t settings.decimalPlacesOverride = Number(settings.decimalPlacesShownOnFocus);\n\t value = roundValue(value, settings);\n\t hasBeenRounded = true;\n\t settings.decimalPlacesOverride = tempDecimal;\n\t }\n\t\n\t if (settings.scaleDivisor && !settings.onOff) {\n\t value = roundValue(value, settings);\n\t settings.rawValue = cleanLeadingTrailingZeros(value.replace(settings.decimalCharacter, '.'), settings);\n\t value = toNumericValue(value, settings);\n\t value = value / settings.scaleDivisor;\n\t value = value.toString();\n\t if (settings.scaleDecimalPlaces) {\n\t tempDecimal = settings.decimalPlacesOverride;\n\t settings.decimalPlacesOverride = Number(settings.scaleDecimalPlaces);\n\t value = roundValue(value, settings);\n\t hasBeenRounded = true;\n\t }\n\t }\n\t\n\t // Rounds if this has not been done already\n\t if (!hasBeenRounded) {\n\t value = roundValue(value, settings);\n\t }\n\t\n\t // Stores rawValue including the decimalPlacesShownOnFocus\n\t if (!settings.scaleDivisor) {\n\t settings.rawValue = cleanLeadingTrailingZeros(value.replace(settings.decimalCharacter, '.'), settings);\n\t }\n\t\n\t value = modifyNegativeSignAndDecimalCharacterForFormattedValue(value, settings);\n\t value = addGroupSeparators(value, settings);\n\t\n\t if (settings.scaleDivisor && settings.scaleDecimalPlaces && !settings.onOff) {\n\t settings.decimalPlacesOverride = tempDecimal;\n\t }\n\t }\n\t\n\t if (settings.saveValueToSessionStorage && (settings.decimalPlacesShownOnFocus || settings.scaleDivisor)) {\n\t saveValueToPersistentStorage($this[0], settings, 'set');\n\t }\n\t } else {\n\t settings.rawValue = '';\n\t saveValueToPersistentStorage($this[0], settings, 'wipe');\n\t var attemptedValue = value;\n\t value = '';\n\t if (!minTest) {\n\t $this.trigger('autoNumeric:minExceeded');\n\t }\n\t\n\t if (!maxTest) {\n\t $this.trigger('autoNumeric:maxExceeded');\n\t }\n\t\n\t throwError('The value [' + attemptedValue + '] being set falls outside of the minimumValue [' + settings.minimumValue + '] and maximumValue [' + settings.maximumValue + '] range set for this element');\n\t\n\t return $this.val('');\n\t }\n\t } else {\n\t return $this.val('');\n\t }\n\t\n\t if (!settings.hasFocus && settings.scaleSymbol) {\n\t value = value + settings.scaleSymbol;\n\t }\n\t\n\t if ($input) {\n\t return $this.val(value);\n\t }\n\t\n\t if (isInArray($this.prop('tagName').toLowerCase(), settings.tagList)) {\n\t return $this.text(value);\n\t }\n\t\n\t return false;\n\t });\n\t },\n\t\n\t\n\t /**\n\t * Method to un-format inputs.\n\t * This is handy to use right before form submission.\n\t *\n\t * By default, values are returned as ISO numeric strings (ie. \"1234.56\" or \"-1234.56\"), where the decimal character is a period.\n\t * Locale formats are supported \"1234.56-\" or \"1234,56\" or \"-1234,56 or \"1234,56-\", or even plain numbers.\n\t * Please see option \"outputFormat\" for more details\n\t *\n\t * @example $(someSelector).autoNumeric('unSet');\n\t *\n\t * @returns {*|jQuery}\n\t */\n\t unSet: function unSet() {\n\t return $(this).each(function () {\n\t var $this = getCurrentElement(this);\n\t var settings = $this.data('autoNumeric');\n\t if ((typeof settings === 'undefined' ? 'undefined' : _typeof(settings)) === 'object') {\n\t settings.hasFocus = true;\n\t $this.val($this.autoNumeric('getLocalized'));\n\t }\n\t });\n\t },\n\t\n\t\n\t /**\n\t * Method to re-format inputs.\n\t * This is handy to use right after form submission.\n\t *\n\t * This is called after the 'unSet' method to reformat the input\n\t *\n\t * @example $(someSelector).autoNumeric('reSet');\n\t *\n\t * @returns {*|jQuery}\n\t */\n\t reSet: function reSet() {\n\t return $(this).each(function () {\n\t var $this = getCurrentElement(this);\n\t var settings = $this.data('autoNumeric');\n\t if ((typeof settings === 'undefined' ? 'undefined' : _typeof(settings)) === 'object') {\n\t $this.autoNumeric('set', $this.val());\n\t }\n\t });\n\t },\n\t\n\t\n\t /**\n\t * Return the unformatted value as a string.\n\t *\n\t * @usage $(someSelector).autoNumeric('get');\n\t *\n\t * @returns {string}\n\t */\n\t get: function get() {\n\t //TODO Why would we need to get a new reference to $this since it has been done in `init()`?\n\t var $this = getCurrentElement(this);\n\t //TODO This looks a lot like `getInputIfSupportedTagAndType()`. Is that necessary? Can the input element be changed since autoNumeric has been initialized?\n\t var $input = $this.is('input[type=text], input[type=hidden], input[type=tel], input:not([type])');\n\t var settings = $this.data('autoNumeric');\n\t if ((typeof settings === 'undefined' ? 'undefined' : _typeof(settings)) !== 'object') {\n\t throwError('Initializing autoNumeric is required prior to calling the \"get\" method.');\n\t }\n\t\n\t // determine the element type then use .eq(0) selector to grab the value of the first element in selector\n\t var value = '';\n\t if ($input) {\n\t value = $this.eq(0).val();\n\t } else if (isInArray($this.prop('tagName').toLowerCase(), settings.tagList)) {\n\t value = $this.eq(0).text();\n\t } else {\n\t throwError('The \"<' + $this.prop('tagName').toLowerCase() + '>\" tag is not supported by autoNumeric');\n\t }\n\t\n\t if (settings.decimalPlacesShownOnFocus || settings.scaleDivisor) {\n\t value = settings.rawValue;\n\t } else {\n\t // Test if the value is negative\n\t var isValueNegative = isNegative(value);\n\t\n\t if (!/\\d/.test(value) && settings.emptyInputBehavior === 'focus') {\n\t return '';\n\t }\n\t\n\t if (value !== '' && settings.negativeBracketsTypeOnBlur !== null) {\n\t settings.hasFocus = true;\n\t value = toggleNegativeBracket(value, settings);\n\t }\n\t\n\t if (settings.runOnce || settings.formatOnPageLoad === false) {\n\t // Strips trailing negative symbol\n\t value = stripAllNonNumberCharacters(value, settings, true);\n\t // Trims leading and trailing zeros when leadingZero does NOT equal \"keep\".\n\t value = cleanLeadingTrailingZeros(value.replace(settings.decimalCharacter, '.'), settings);\n\t\n\t // Places the negative symbol in front of the trailing negative\n\t if (settings.trailingNegative && isValueNegative && !isNegative(value) && Number(value) !== 0) {\n\t value = '-' + value;\n\t }\n\t }\n\t\n\t if (value !== '' || value === '' && settings.emptyInputBehavior === 'zero') {\n\t value = modifyNegativeSignAndDecimalCharacterForRawValue(value, settings);\n\t }\n\t }\n\t\n\t // Always return a numeric string\n\t // This gets rid of the trailing zeros in the decimal places since `get` does not pad decimals\n\t return trimPaddedZerosFromDecimalPlaces(value);\n\t },\n\t\n\t\n\t /**\n\t * Returns the unformatted value, but following the `outputFormat` setting, which means the output can either be :\n\t * - a string (that could or could not represent a number (ie. \"12345,67-\")), or\n\t * - a plain number (if the setting 'number' is used).\n\t *\n\t * By default the returned values are an ISO numeric string \"1234.56\" or \"-1234.56\" where the decimal character is a period.\n\t * Check the \"outputFormat\" option definition for more details.\n\t *\n\t * @usage $(someSelector).autoNumeric('getLocalized');\n\t *\n\t * @returns {*}\n\t */\n\t getLocalized: function getLocalized() {\n\t var $this = getCurrentElement(this);\n\t var value = $this.autoNumeric('get');\n\t var settings = $this.data('autoNumeric');\n\t\n\t if (Number(value) === 0 && settings.leadingZero !== 'keep') {\n\t value = '0';\n\t }\n\t\n\t return toLocale(value, settings.outputFormat);\n\t },\n\t\n\t\n\t /**\n\t * Return the input unformatted value as a real Javascript number.\n\t *\n\t * @usage $(someSelector).autoNumeric('getNumber');\n\t *\n\t * @returns {number}\n\t */\n\t getNumber: function getNumber() {\n\t var $this = getCurrentElement(this);\n\t var value = $this.autoNumeric('get');\n\t\n\t return toLocale(value, 'number');\n\t },\n\t\n\t\n\t /**\n\t * Return the current formatted value of the autoNumeric element.\n\t * @usage aNInput.autoNumeric('getFormatted'))\n\t *\n\t * @returns {string}\n\t */\n\t getFormatted: function getFormatted() {\n\t // Make sure `this[0]` exists as well as `.value` before trying to access that property\n\t if (!this.hasOwnProperty('0') || !('value' in this[0])) {\n\t throwError('Unable to get the formatted string from the element.');\n\t }\n\t\n\t return this[0].value;\n\t },\n\t\n\t\n\t /**\n\t * The \"getString\" method uses jQuery's .serialize() method that creates a text string in standard URL-encoded notation.\n\t *\n\t * It then loops through the string and un-formats the inputs with autoNumeric.\n\t * By defaults values returned as ISO numeric string \"1234.56\" or \"-1234.56\" where the decimal character is a period\n\t * Locale formats are supported \"1234.56-\" or \"1234,56\" or \"-1234,56 or \"1234,56-\" or plain numbers => please see option \"outputFormat\" for details\n\t *\n\t * @returns {string}\n\t */\n\t getString: function getString() {\n\t return _getStringOrArray(false, this);\n\t },\n\t\n\t\n\t /**\n\t * The \"getArray\" method on the other hand uses jQuery's .serializeArray() method that creates array or objects that can be encoded as a JSON string.\n\t *\n\t * It then loops through the string and un-formats the inputs with autoNumeric.\n\t * By defaults values returned as ISO numeric string \"1234.56\" or \"-1234.56\" where the decimal character is a period\n\t * Locale formats are supported \"1234.56-\" or \"1234,56\" or \"-1234,56 or \"1234,56-\" or plain numbers => please see option \"outputFormat\" for details\n\t *\n\t * @returns {{}|[]}\n\t */\n\t getArray: function getArray() {\n\t return _getStringOrArray(true, this);\n\t },\n\t\n\t\n\t /**\n\t * The 'getSettings' function returns an object containing all the current autoNumeric settings.\n\t *\n\t * @example\n\t * $(someSelector).autoNumeric('getSettings');\n\t * $(someSelector).autoNumeric('getSettings').decimalCharacter; // Return the decimalCharacter setting as a string - any valid option name can be used\n\t *\n\t * @returns {object}\n\t */\n\t getSettings: function getSettings() {\n\t //TODO Add an option argument `optionName` to this function so that it return only the value of that option, not the entire settings object\n\t return this.data('autoNumeric');\n\t }\n\t };\n\t\n\t /**\n\t * The autoNumeric function accepts methods names (in string format) and those method parameters if needed.\n\t * It initialize autoNumeric on the given element.\n\t *\n\t * @param {string} method The method name (ie. 'set', 'get', etc.)\n\t * @param {*} args\n\t * @returns {*}\n\t */\n\t $.fn.autoNumeric = function (method) {\n\t if (methods[method]) {\n\t for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n\t args[_key - 1] = arguments[_key];\n\t }\n\t\n\t return methods[method].apply(this, args);\n\t }\n\t\n\t if ((typeof method === 'undefined' ? 'undefined' : _typeof(method)) === 'object' || !method) {\n\t // The options have been passed directly, without using a named method\n\t return methods.init.apply(this, [method]);\n\t }\n\t\n\t throwError('Method \"' + method + '\" is not supported by autoNumeric');\n\t };\n\t\n\t /**\n\t * Return the default autoNumeric settings.\n\t *\n\t * @returns {object}\n\t */\n\t getDefaultConfig = function getDefaultConfig() {\n\t return defaultSettings;\n\t };\n\t\n\t $.fn.autoNumeric.defaults = defaultSettings; // Make those settings public via jQuery too.\n\t\n\t /**\n\t * Return all the predefined language options in one object.\n\t * You can also access a specific language object directly by using `an.getLanguages().French` for instance.\n\t *\n\t * @returns {object}\n\t */\n\t getLanguages = function getLanguages() {\n\t return languageOption;\n\t };\n\t\n\t $.fn.autoNumeric.lang = languageOption; // Make those predefined language options public via jQuery too.\n\t\n\t /**\n\t * Public function that allows formatting without an element trigger.\n\t *\n\t * @param {number|string} value A number, or a string that represent a javascript number\n\t * @param {object|null} options\n\t * @returns {*}\n\t */\n\t autoFormat = function autoFormat(value) {\n\t var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n\t\n\t if (isUndefined(value) || value === null) {\n\t return null;\n\t }\n\t\n\t if (!isString(value) && !isNumber(value)) {\n\t throwError('The value \"' + value + '\" being \"set\" is not numeric and therefore cannot be used appropriately.');\n\t }\n\t\n\t // Initiate a very basic settings object\n\t var settings = $.extend({}, defaultSettings, { strip: false }, options);\n\t if (value < 0) {\n\t settings.negativeSignCharacter = '-';\n\t }\n\t\n\t if (isNull(settings.decimalPlacesOverride)) {\n\t settings.decimalPlacesOverride = maximumVMinAndVMaxDecimalLength(settings.minimumValue, settings.maximumValue);\n\t }\n\t\n\t // Check the validity of the `value` parameter\n\t // Convert the value to a numeric string, stripping unnecessary characters in the process\n\t var valueString = toNumericValue(value, settings);\n\t if (isNaN(valueString)) {\n\t throwError('The value [' + valueString + '] that you are trying to format is not a recognized number.');\n\t }\n\t\n\t // Basic tests to check if the given valueString is valid\n\t\n\t var _checkIfInRangeWithOv7 = checkIfInRangeWithOverrideOption(valueString, settings),\n\t _checkIfInRangeWithOv8 = _slicedToArray(_checkIfInRangeWithOv7, 2),\n\t minTest = _checkIfInRangeWithOv8[0],\n\t maxTest = _checkIfInRangeWithOv8[1];\n\t\n\t if (!minTest || !maxTest) {\n\t // Throw a custom event\n\t triggerEvent('autoFormat.autoNumeric', document, 'Range test failed');\n\t throwError('The value [' + valueString + '] being set falls outside of the minimumValue [' + settings.minimumValue + '] and maximumValue [' + settings.maximumValue + '] range set for this element');\n\t }\n\t\n\t // Everything is ok, proceed to rounding, formatting and grouping\n\t valueString = roundValue(valueString, settings);\n\t valueString = modifyNegativeSignAndDecimalCharacterForFormattedValue(valueString, settings);\n\t valueString = addGroupSeparators(valueString, settings);\n\t\n\t return valueString;\n\t };\n\t\n\t $.fn.autoFormat = autoFormat; // The jQuery export\n\t\n\t /**\n\t * Public function that allows unformatting without an element.\n\t *\n\t * @param {string|number} value\n\t * @param {object} options\n\t * @returns {*}\n\t */\n\t autoUnFormat = function autoUnFormat(value, options) {\n\t if (isUndefined(value) || value === null) {\n\t return null;\n\t }\n\t\n\t // Giving an unformatted value should return the same unformatted value, whatever the options passed as a parameter\n\t if (isNumber(value)) {\n\t return Number(value);\n\t }\n\t\n\t if (isArray(value) || isObject(value)) {\n\t //TODO Complete the test to throw when given a wrongly formatted number (ie. 'foobar')\n\t // Check the validity of the `value` parameter\n\t throwError('A number or a string representing a number is needed to be able to unformat it, [' + value + '] given.');\n\t }\n\t\n\t var settings = $.extend({}, defaultSettings, { strip: false }, options);\n\t var allowed = '-0123456789\\\\' + settings.decimalCharacter;\n\t var autoStrip = new RegExp('[^' + allowed + ']', 'gi');\n\t value = value.toString();\n\t\n\t // This checks is a negative sign is anywhere in the `value`, not just on the very first character (ie. '12345.67-')\n\t if (isNegative(value)) {\n\t settings.negativeSignCharacter = '-';\n\t } else if (settings.negativeBracketsTypeOnBlur && settings.negativeBracketsTypeOnBlur.split(',')[0] === value.charAt(0)) {\n\t settings.negativeSignCharacter = '-';\n\t settings.hasFocus = true;\n\t value = toggleNegativeBracket(value, settings);\n\t }\n\t\n\t value = value.replace(autoStrip, '');\n\t value = value.replace(settings.decimalCharacter, '.');\n\t value = toLocale(value, settings.outputFormat);\n\t\n\t return value;\n\t };\n\t\n\t $.fn.autoUnformat = autoUnFormat; // The jQuery export\n\t\n\t /**\n\t * Validate the given option object.\n\t * If the options are valid, this function returns nothing, otherwise if the options are invalid, this function throws an error.\n\t *\n\t * This tests if the options are not conflicting and are well formatted.\n\t * This function is lenient since it only tests the settings properties ; it ignores any other properties the options object could have.\n\t *\n\t * @param {*} userOptions\n\t * @param {Boolean} shouldExtendDefaultOptions If TRUE, then this function will extends the `userOptions` passed by the user, with the default options.\n\t * @throws Error\n\t */\n\t validate = function validate(userOptions) {\n\t var shouldExtendDefaultOptions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n\t\n\t if (isUndefinedOrNullOrEmpty(userOptions) || !isObject(userOptions) || isEmptyObj(userOptions)) {\n\t throwError('The userOptions are invalid ; it should be a valid object, [' + userOptions + '] given.');\n\t }\n\t\n\t // If the user used old options, we convert them to new ones\n\t if (!isNull(userOptions)) {\n\t convertOldOptionsToNewOnes(userOptions);\n\t }\n\t\n\t // The user can choose if the `userOptions` has already been extended with the default options, or not\n\t var options = void 0;\n\t if (shouldExtendDefaultOptions) {\n\t options = $.extend({}, defaultSettings, userOptions);\n\t } else {\n\t options = userOptions;\n\t }\n\t\n\t // First things first, we test that the `showWarnings` option is valid\n\t if (!isTrueOrFalseString(options.showWarnings) && !isBoolean(options.showWarnings)) {\n\t throwError('The debug option \\'showWarnings\\' is invalid ; it should be either \\'false\\' or \\'true\\', [' + options.showWarnings + '] given.');\n\t }\n\t\n\t // Define the regular expressions needed for the following tests\n\t var testPositiveInteger = /^[0-9]+$/;\n\t var testNumericalCharacters = /[0-9]+/;\n\t // const testFloatAndPossibleNegativeSign = /^-?[0-9]+(\\.?[0-9]+)$/;\n\t var testFloatOrIntegerAndPossibleNegativeSign = /^-?[0-9]+(\\.?[0-9]+)?$/;\n\t var testPositiveFloatOrInteger = /^[0-9]+(\\.?[0-9]+)?$/;\n\t\n\t // Then tests the options individually\n\t if (!isInArray(options.digitGroupSeparator, [',', // Comma\n\t '.', // Dot\n\t ' ', // Normal space\n\t '\\u2009', // Thin-space\n\t '\\u202F', // Narrow no-break space\n\t '\\xA0', // No-break space\n\t '', // No separator\n\t \"'\", // Apostrophe\n\t '٬', // Arabic thousands separator\n\t '˙'])) {\n\t throwError('The thousand separator character option \\'digitGroupSeparator\\' is invalid ; it should be \\',\\', \\'.\\', \\'\\u066C\\', \\'\\u02D9\\', \"\\'\", \\' \\', \\'\\u2009\\', \\'\\u202F\\', \\'\\xA0\\' or empty (\\'\\'), [' + options.digitGroupSeparator + '] given.');\n\t }\n\t\n\t if (!isTrueOrFalseString(options.noSeparatorOnFocus) && !isBoolean(options.noSeparatorOnFocus)) {\n\t throwError('The \\'noSeparatorOnFocus\\' option is invalid ; it should be either \\'false\\' or \\'true\\', [' + options.noSeparatorOnFocus + '] given.');\n\t }\n\t\n\t if (!testPositiveInteger.test(options.digitalGroupSpacing)) {\n\t throwError('The digital grouping for thousand separator option \\'digitalGroupSpacing\\' is invalid ; it should be a positive integer, [' + options.digitalGroupSpacing + '] given.');\n\t }\n\t\n\t if (!isInArray(options.decimalCharacter, [',', // Comma\n\t '.', // Dot\n\t '·', // Middle-dot\n\t '٫', // Arabic decimal separator\n\t '⎖'])) {\n\t throwError('The decimal separator character option \\'decimalCharacter\\' is invalid ; it should be \\'.\\', \\',\\', \\'\\xB7\\', \\'\\u2396\\' or \\'\\u066B\\', [' + options.decimalCharacter + '] given.');\n\t }\n\t\n\t // Checks if the decimal and thousand characters are the same\n\t if (options.decimalCharacter === options.digitGroupSeparator) {\n\t throwError('autoNumeric will not function properly when the decimal character \\'decimalCharacter\\' [' + options.decimalCharacter + '] and the thousand separator \\'digitGroupSeparator\\' [' + options.digitGroupSeparator + '] are the same character.');\n\t }\n\t\n\t if (!isNull(options.decimalCharacterAlternative) && !isString(options.decimalCharacterAlternative)) {\n\t throwError('The alternate decimal separator character option \\'decimalCharacterAlternative\\' is invalid ; it should be a string, [' + options.decimalCharacterAlternative + '] given.');\n\t }\n\t\n\t if (options.currencySymbol !== '' && !isString(options.currencySymbol)) {\n\t throwError('The currency symbol option \\'currencySymbol\\' is invalid ; it should be a string, [' + options.currencySymbol + '] given.');\n\t }\n\t\n\t if (!isInArray(options.currencySymbolPlacement, ['p', 's'])) {\n\t throwError('The placement of the currency sign option \\'currencySymbolPlacement\\' is invalid ; it should either be \\'p\\' (prefix) or \\'s\\' (suffix), [' + options.currencySymbolPlacement + '] given.');\n\t }\n\t\n\t if (!isInArray(options.negativePositiveSignPlacement, ['p', 's', 'l', 'r', null])) {\n\t throwError('The placement of the negative sign option \\'negativePositiveSignPlacement\\' is invalid ; it should either be \\'p\\' (prefix), \\'s\\' (suffix), \\'l\\' (left), \\'r\\' (right) or \\'null\\', [' + options.negativePositiveSignPlacement + '] given.');\n\t }\n\t\n\t if (!isTrueOrFalseString(options.showPositiveSign) && !isBoolean(options.showPositiveSign)) {\n\t throwError('The show positive sign option \\'showPositiveSign\\' is invalid ; it should be either \\'false\\' or \\'true\\', [' + options.showPositiveSign + '] given.');\n\t }\n\t\n\t if (!isString(options.suffixText) || options.suffixText !== '' && (isNegative(options.suffixText) || testNumericalCharacters.test(options.suffixText))) {\n\t throwError('The additional suffix option \\'suffixText\\' is invalid ; it should not contains the negative sign \\'-\\' nor any numerical characters, [' + options.suffixText + '] given.');\n\t }\n\t\n\t if (!isNull(options.overrideMinMaxLimits) && !isInArray(options.overrideMinMaxLimits, ['ceiling', 'floor', 'ignore'])) {\n\t throwError('The override min & max limits option \\'overrideMinMaxLimits\\' is invalid ; it should either be \\'ceiling\\', \\'floor\\' or \\'ignore\\', [' + options.overrideMinMaxLimits + '] given.');\n\t }\n\t\n\t if (!isString(options.maximumValue) || !testFloatOrIntegerAndPossibleNegativeSign.test(options.maximumValue)) {\n\t throwError('The maximum possible value option \\'maximumValue\\' is invalid ; it should be a string that represents a positive or negative number, [' + options.maximumValue + '] given.');\n\t }\n\t\n\t if (!isString(options.minimumValue) || !testFloatOrIntegerAndPossibleNegativeSign.test(options.minimumValue)) {\n\t throwError('The minimum possible value option \\'minimumValue\\' is invalid ; it should be a string that represents a positive or negative number, [' + options.minimumValue + '] given.');\n\t }\n\t\n\t if (parseFloat(options.minimumValue) > parseFloat(options.maximumValue)) {\n\t throwError('The minimum possible value option is greater than the maximum possible value option ; \\'minimumValue\\' [' + options.minimumValue + '] should be smaller than \\'maximumValue\\' [' + options.maximumValue + '].');\n\t }\n\t\n\t if (!(isNull(options.decimalPlacesOverride) || isInt(options.decimalPlacesOverride) && options.decimalPlacesOverride >= 0 || // If integer option\n\t isString(options.decimalPlacesOverride) && testPositiveInteger.test(options.decimalPlacesOverride)) // If string option\n\t ) {\n\t throwError('The maximum number of decimal places option \\'decimalPlacesOverride\\' is invalid ; it should be a positive integer, [' + options.decimalPlacesOverride + '] given.');\n\t }\n\t\n\t // Write a warning message in the console if the number of decimal in minimumValue/maximumValue is overridden by decimalPlacesOverride (and not if decimalPlacesOverride is equal to the number of decimal used in minimumValue/maximumValue)\n\t var vMinAndVMaxMaximumDecimalPlaces = maximumVMinAndVMaxDecimalLength(options.minimumValue, options.maximumValue);\n\t if (!isNull(options.decimalPlacesOverride) && vMinAndVMaxMaximumDecimalPlaces !== Number(options.decimalPlacesOverride)) {\n\t warning('Setting \\'decimalPlacesOverride\\' to [' + options.decimalPlacesOverride + '] will override the decimals declared in \\'minimumValue\\' [' + options.minimumValue + '] and \\'maximumValue\\' [' + options.maximumValue + '].', options.showWarnings);\n\t }\n\t\n\t if (!options.allowDecimalPadding && !isNull(options.decimalPlacesOverride)) {\n\t warning('Setting \\'allowDecimalPadding\\' to [false] will override the current \\'decimalPlacesOverride\\' setting [' + options.decimalPlacesOverride + '].', options.showWarnings);\n\t }\n\t\n\t if (!isNull(options.decimalPlacesShownOnFocus) && (!isString(options.decimalPlacesShownOnFocus) || !testPositiveInteger.test(options.decimalPlacesShownOnFocus))) {\n\t throwError('The number of expanded decimal places option \\'decimalPlacesShownOnFocus\\' is invalid ; it should be a positive integer, [' + options.decimalPlacesShownOnFocus + '] given.');\n\t }\n\t\n\t // Checks if the extended decimal places \"decimalPlacesShownOnFocus\" is greater than the normal decimal places \"decimalPlacesOverride\"\n\t if (!isNull(options.decimalPlacesShownOnFocus) && !isNull(options.decimalPlacesOverride) && Number(options.decimalPlacesOverride) > Number(options.decimalPlacesShownOnFocus)) {\n\t warning('The extended decimal places \\'decimalPlacesShownOnFocus\\' [' + options.decimalPlacesShownOnFocus + '] should be greater than the \\'decimalPlacesOverride\\' [' + options.decimalPlacesOverride + '] value. Currently, this will limit the ability of your client to manually change some of the decimal places. Do you really want to do that?', options.showWarnings);\n\t }\n\t\n\t if (!isNull(options.scaleDivisor) && !testPositiveFloatOrInteger.test(options.scaleDivisor)) {\n\t throwError('The scale divisor option \\'scaleDivisor\\' is invalid ; it should be a positive number, preferably an integer, [' + options.scaleDivisor + '] given.');\n\t }\n\t\n\t if (!isNull(options.scaleDecimalPlaces) && !testPositiveInteger.test(options.scaleDecimalPlaces)) {\n\t throwError('The scale number of decimals option \\'scaleDecimalPlaces\\' is invalid ; it should be a positive integer, [' + options.scaleDecimalPlaces + '] given.');\n\t }\n\t\n\t if (!isNull(options.scaleSymbol) && !isString(options.scaleSymbol)) {\n\t throwError('The scale symbol option \\'scaleSymbol\\' is invalid ; it should be a string, [' + options.scaleSymbol + '] given.');\n\t }\n\t\n\t if (!isTrueOrFalseString(options.saveValueToSessionStorage) && !isBoolean(options.saveValueToSessionStorage)) {\n\t throwError('The save to session storage option \\'saveValueToSessionStorage\\' is invalid ; it should be either \\'false\\' or \\'true\\', [' + options.saveValueToSessionStorage + '] given.');\n\t }\n\t\n\t if (!isInArray(options.onInvalidPaste, ['error', 'ignore', 'clamp', 'truncate', 'replace'])) {\n\t throwError('The paste behavior option \\'onInvalidPaste\\' is invalid ; it should either be \\'error\\', \\'ignore\\', \\'clamp\\', \\'truncate\\' or \\'replace\\' (cf. documentation), [' + options.onInvalidPaste + '] given.');\n\t }\n\t\n\t if (!isInArray(options.roundingMethod, ['S', 'A', 's', 'a', 'B', 'U', 'D', 'C', 'F', 'N05', 'CHF', 'U05', 'D05'])) {\n\t throwError('The rounding method option \\'roundingMethod\\' is invalid ; it should either be \\'S\\', \\'A\\', \\'s\\', \\'a\\', \\'B\\', \\'U\\', \\'D\\', \\'C\\', \\'F\\', \\'N05\\', \\'CHF\\', \\'U05\\' or \\'D05\\' (cf. documentation), [' + options.roundingMethod + '] given.');\n\t }\n\t\n\t if (!isTrueOrFalseString(options.allowDecimalPadding) && !isBoolean(options.allowDecimalPadding)) {\n\t throwError('The control decimal padding option \\'allowDecimalPadding\\' is invalid ; it should be either \\'false\\' or \\'true\\', [' + options.allowDecimalPadding + '] given.');\n\t }\n\t\n\t if (!isNull(options.negativeBracketsTypeOnBlur) && !isInArray(options.negativeBracketsTypeOnBlur, ['(,)', '[,]', '<,>', '{,}'])) {\n\t throwError('The brackets for negative values option \\'negativeBracketsTypeOnBlur\\' is invalid ; it should either be \\'(,)\\', \\'[,]\\', \\'<,>\\' or \\'{,}\\', [' + options.negativeBracketsTypeOnBlur + '] given.');\n\t }\n\t\n\t if (!isInArray(options.emptyInputBehavior, ['focus', 'press', 'always', 'zero'])) {\n\t throwError('The display on empty string option \\'emptyInputBehavior\\' is invalid ; it should either be \\'focus\\', \\'press\\', \\'always\\' or \\'zero\\', [' + options.emptyInputBehavior + '] given.');\n\t }\n\t\n\t if (!isInArray(options.leadingZero, ['allow', 'deny', 'keep'])) {\n\t throwError('The leading zero behavior option \\'leadingZero\\' is invalid ; it should either be \\'allow\\', \\'deny\\' or \\'keep\\', [' + options.leadingZero + '] given.');\n\t }\n\t\n\t if (!isTrueOrFalseString(options.formatOnPageLoad) && !isBoolean(options.formatOnPageLoad)) {\n\t throwError('The format on initialization option \\'formatOnPageLoad\\' is invalid ; it should be either \\'false\\' or \\'true\\', [' + options.formatOnPageLoad + '] given.');\n\t }\n\t\n\t if (!isTrueOrFalseString(options.selectNumberOnly) && !isBoolean(options.selectNumberOnly)) {\n\t throwError('The select number only option \\'selectNumberOnly\\' is invalid ; it should be either \\'false\\' or \\'true\\', [' + options.selectNumberOnly + '] given.');\n\t }\n\t\n\t if (!isNull(options.defaultValueOverride) && options.defaultValueOverride !== '' && !testFloatOrIntegerAndPossibleNegativeSign.test(options.defaultValueOverride)) {\n\t throwError('The unformatted default value option \\'defaultValueOverride\\' is invalid ; it should be a string that represents a positive or negative number, [' + options.defaultValueOverride + '] given.');\n\t }\n\t\n\t if (!isTrueOrFalseString(options.unformatOnSubmit) && !isBoolean(options.unformatOnSubmit)) {\n\t throwError('The remove formatting on submit option \\'unformatOnSubmit\\' is invalid ; it should be either \\'false\\' or \\'true\\', [' + options.unformatOnSubmit + '] given.');\n\t }\n\t\n\t if (!isNull(options.outputFormat) && !isInArray(options.outputFormat, ['string', 'number', '.', '-.', ',', '-,', '.-', ',-'])) {\n\t throwError('The custom locale format option \\'outputFormat\\' is invalid ; it should either be null, \\'string\\', \\'number\\', \\'.\\', \\'-.\\', \\',\\', \\'-,\\', \\'.-\\' or \\',-\\', [' + options.outputFormat + '] given.');\n\t }\n\t\n\t if (!isTrueOrFalseString(options.failOnUnknownOption) && !isBoolean(options.failOnUnknownOption)) {\n\t throwError('The debug option \\'failOnUnknownOption\\' is invalid ; it should be either \\'false\\' or \\'true\\', [' + options.failOnUnknownOption + '] given.');\n\t }\n\t };\n\t\n\t $.fn.autoValidate = validate;\n\t\n\t /**\n\t * Return TRUE is the settings/options are valid, FALSE otherwise.\n\t *\n\t * @param {object} options\n\t * @returns {boolean}\n\t */\n\t areSettingsValid = function areSettingsValid(options) {\n\t var isValid = true;\n\t try {\n\t validate(options);\n\t } catch (error) {\n\t isValid = false;\n\t }\n\t\n\t return isValid;\n\t };\n\t\n\t /**\n\t * Take an arabic number as a string and return a javascript number.\n\t * By default, this function does not try to convert the arabic decimal and thousand separator characters.\n\t * This returns `NaN` is the conversion is not possible.\n\t * Based on http://stackoverflow.com/a/17025392/2834898\n\t *\n\t * @param {string} arabicNumbers\n\t * @param {boolean} returnANumber If `true`, return a Number, otherwise return a String\n\t * @param {boolean} parseDecimalCharacter\n\t * @param {boolean} parseThousandSeparator\n\t * @returns {string|number|NaN}\n\t */\n\t function arabicToLatinNumbers(arabicNumbers) {\n\t var returnANumber = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n\t var parseDecimalCharacter = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;\n\t var parseThousandSeparator = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;\n\t\n\t var result = arabicNumbers.toString();\n\t if (result === '' || result.match(/[٠١٢٣٤٥٦٧٨٩۴۵۶]/g) === null) {\n\t // If no Arabic/Persian numbers are found, return the numeric string directly\n\t return arabicNumbers;\n\t }\n\t\n\t if (parseDecimalCharacter) {\n\t result = result.replace(/٫/, '.'); // Decimal character\n\t }\n\t\n\t if (parseThousandSeparator) {\n\t result = result.replace(/٬/g, ''); // Thousand separator\n\t }\n\t\n\t // Replace the numbers only\n\t result = result.replace(/[٠١٢٣٤٥٦٧٨٩]/g, function (d) {\n\t return d.charCodeAt(0) - 1632;\n\t }) // Arabic numbers\n\t .replace(/[۰۱۲۳۴۵۶۷۸۹]/g, function (d) {\n\t return d.charCodeAt(0) - 1776;\n\t }); // Persian numbers\n\t\n\t // `NaN` has precedence over the string `'NaN'`\n\t var resultAsNumber = Number(result);\n\t if (isNaN(resultAsNumber)) {\n\t return resultAsNumber;\n\t }\n\t\n\t if (returnANumber) {\n\t result = resultAsNumber;\n\t }\n\t\n\t return result;\n\t }\n\t\n\t /**\n\t * Create a custom event and immediately sent it from the given element.\n\t * By default, if no element is given, the event is thrown from `document`.\n\t *\n\t * @param {string} eventName\n\t * @param {Element} element\n\t * @param {object} detail\n\t */\n\t function triggerEvent(eventName) {\n\t var element = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : document;\n\t var detail = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;\n\t\n\t var event = void 0;\n\t if (window.CustomEvent) {\n\t event = new CustomEvent(eventName, { detail: detail, bubbles: false, cancelable: false }); // This is not supported by default by IE ; We use the polyfill for IE9 and later.\n\t } else {\n\t event = document.createEvent('CustomEvent');\n\t event.initCustomEvent(eventName, true, true, { detail: detail });\n\t }\n\t\n\t element.dispatchEvent(event);\n\t }\n\t\n\t /**\n\t * Polyfill from https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent for obsolete browsers (IE)\n\t */\n\t (function () {\n\t if (typeof window.CustomEvent === 'function') {\n\t return false;\n\t }\n\t\n\t function CustomEvent(event, params) {\n\t params = params || { bubbles: false, cancelable: false, detail: void 0 };\n\t var evt = document.createEvent('CustomEvent');\n\t evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);\n\t return evt;\n\t }\n\t\n\t CustomEvent.prototype = window.Event.prototype;\n\t window.CustomEvent = CustomEvent;\n\t })();\n\t});\n\t\n\t/**\n\t * This exports the interface for the autoNumeric object\n\t */\n\texports.default = {\n\t format: autoFormat,\n\t unFormat: autoUnFormat,\n\t getDefaultConfig: getDefaultConfig,\n\t getLanguages: getLanguages,\n\t validate: validate, // an.validate(options) : throws if necessary\n\t areSettingsValid: areSettingsValid };\n\t}.call(window));\n\n/***/ },\n/* 1 */\n/***/ function(module, exports) {\n\n\tmodule.exports = __WEBPACK_EXTERNAL_MODULE_1__;\n\n/***/ }\n/******/ ])\n});\n;\n\n\n// WEBPACK FOOTER //\n// autoNumeric.min.js"," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId])\n \t\t\treturn installedModules[moduleId].exports;\n\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\texports: {},\n \t\t\tid: moduleId,\n \t\t\tloaded: false\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.loaded = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(0);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 28aa359b7d6224364eb0","/**\n * autoNumeric.js\n *\n * @version 2.0.12\n * @date 2017-04-07 UTC 07:00\n *\n * @author Bob Knothe\n * @contributors Alexandre Bonneau, Sokolov Yura and other Github users,\n * cf. AUTHORS.md.\n * @copyright 2009 Robert J. Knothe http://www.decorplanit.com/plugin/\n * @since 2009-08-09\n *\n * @summary autoNumeric is a library that provides live as-you-type\n * formatting for international numbers and currencies.\n *\n * Note : Some functions are borrowed from big.js\n * @link https://github.com/MikeMcl/big.js/\n *\n * Please report any bugs to https://github.com/autoNumeric/autoNumeric\n *\n * @license Released under the MIT License\n * @link http://www.opensource.org/licenses/mit-license.php\n *\n * Permission is hereby granted, free of charge, to any person\n * obtaining a copy of this software and associated documentation\n * files (the \"Software\"), to deal in the Software without\n * restriction, including without limitation the rights to use,\n * copy, modify, merge, publish, distribute, sub license, and/or sell\n * copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following\n * conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\n\n/* global module, require, define */\n\n// Functions names for ES6 exports\nlet autoFormat;\nlet autoUnFormat;\nlet getDefaultConfig;\nlet getLanguages;\nlet validate;\nlet areSettingsValid;\n\n// AutoNumeric default settings\n/**\n * List of allowed tag on which autoNumeric can be used.\n */\nconst allowedTagList = [\n 'b',\n 'caption',\n 'cite',\n 'code',\n 'const',\n 'dd',\n 'del',\n 'div',\n 'dfn',\n 'dt',\n 'em',\n 'h1',\n 'h2',\n 'h3',\n 'h4',\n 'h5',\n 'h6',\n 'ins',\n 'kdb',\n 'label',\n 'li',\n 'option',\n 'output',\n 'p',\n 'q',\n 's',\n 'sample',\n 'span',\n 'strong',\n 'td',\n 'th',\n 'u',\n];\n\n/**\n * Defaults options are public - these can be overridden by the following method:\n * - HTML5 data attributes (ie. ``)\n * - Options passed by the 'init' or 'update' methods (ie. `aNInput.autoNumeric('update', { currencySymbol: ' €' });`)\n * - Use jQuery's `$.extend` method for global changes - also a great way to pass ASP.NET current culture settings\n */\nconst defaultSettings = {\n /* Allowed thousand grouping separator characters :\n * ',' // Comma\n * '.' // Dot\n * ' ' // Normal space\n * '\\u2009' // Thin-space\n * '\\u202f' // Narrow no-break space\n * '\\u00a0' // No-break space\n * '' // No separator\n * \"'\" // Apostrophe\n * '٬' // Arabic thousands separator\n * '˙' // Dot above\n * Deprecated older option name : aSep\n */\n digitGroupSeparator: ',',\n\n /* Remove the thousand separator on focus, currency symbol and suffix on focus\n * example if the input value \"$ 1,999.88 suffix\"\n * on \"focusin\" it becomes \"1999.88\" and back to \"$ 1,999.88 suffix\" on focus out.\n * Deprecated older option name : nSep\n */\n noSeparatorOnFocus: false,\n\n /* Digital grouping for the thousand separator used in Format\n * digitalGroupSpacing: \"2\", results in 99,99,99,999 India's lakhs\n * digitalGroupSpacing: \"2s\", results in 99,999,99,99,999 India's lakhs scaled\n * digitalGroupSpacing: \"3\", results in 999,999,999 default\n * digitalGroupSpacing: \"4\", results in 9999,9999,9999 used in some Asian countries\n * Deprecated older option name : dGroup\n */\n digitalGroupSpacing: '3',\n\n /* Allowed decimal separator characters :\n * ',' : Comma\n * '.' : Dot\n * '·' : Middle-dot\n * '٫' : Arabic decimal separator\n * '⎖' : Decimal separator key symbol\n * Deprecated older option name : aDec\n */\n decimalCharacter: '.',\n\n /* Allow to declare an alternative decimal separator which is automatically replaced by `decimalCharacter` when typed.\n * This is used by countries that use a comma \",\" as the decimal character and have keyboards\\numeric pads that have\n * a period 'full stop' as the decimal characters (France or Spain for instance).\n * Deprecated older option name : altDec\n */\n decimalCharacterAlternative: null,\n\n /* currencySymbol = allowed currency symbol\n * Must be in quotes currencySymbol: \"$\"\n * space to the right of the currency symbol currencySymbol: '$ '\n * space to the left of the currency symbol currencySymbol: ' $'\n * Deprecated older option name : aSign\n */\n currencySymbol: '',\n\n /* currencySymbolPlacement = placement of currency sign as a p=prefix or s=suffix\n * for prefix currencySymbolPlacement: \"p\" (default)\n * for suffix currencySymbolPlacement: \"s\"\n * Deprecated older option name : pSign\n */\n //TODO Rename the options to more explicit names ('p' => 'prefix', etc.)\n currencySymbolPlacement: 'p',\n\n /* Placement of negative/positive sign relative to the currencySymbol option l=left, r=right, p=prefix & s=suffix\n * -1,234.56 => default no options required\n * -$1,234.56 => {currencySymbol: \"$\"} or {currencySymbol: \"$\", negativePositiveSignPlacement: \"l\"}\n * $-1,234.56 => {currencySymbol: \"$\", negativePositiveSignPlacement: \"r\"} // Default if negativePositiveSignPlacement is 'null' and currencySymbol is not empty\n * -1,234.56$ => {currencySymbol: \"$\", currencySymbolPlacement: \"s\", negativePositiveSignPlacement: \"p\"} // Default if negativePositiveSignPlacement is 'null' and currencySymbol is not empty\n * 1,234.56- => {negativePositiveSignPlacement: \"s\"}\n * $1,234.56- => {currencySymbol: \"$\", negativePositiveSignPlacement: \"s\"}\n * 1,234.56-$ => {currencySymbol: \"$\", currencySymbolPlacement: \"s\"}\n * 1,234.56$- => {currencySymbol: \"$\", currencySymbolPlacement: \"s\", negativePositiveSignPlacement: \"r\"}\n * Deprecated older option name : pNeg\n */\n //TODO Rename the options to more explicit names ('p' => 'prefix', etc.)\n negativePositiveSignPlacement: null,\n\n\n /* Allow the positive sign symbol `+` to be displayed for positive numbers.\n * By default, this positive sign is not shown.\n * The sign placement is controlled by the 'negativePositiveSignPlacement' option, mimicking the negative sign placement rules.\n */\n showPositiveSign: false,\n\n /* Additional suffix\n * Must be in quotes suffixText: 'gross', a space is allowed suffixText: ' dollars'\n * Numeric characters and negative sign not allowed'\n * Deprecated older option name : aSuffix\n */\n suffixText: '',\n\n /* Override min max limits\n * overrideMinMaxLimits: \"ceiling\" adheres to maximumValue and ignores minimumValue settings\n * overrideMinMaxLimits: \"floor\" adheres to minimumValue and ignores maximumValue settings\n * overrideMinMaxLimits: \"ignore\" ignores both minimumValue & maximumValue\n * Deprecated older option name : oLimits\n */\n overrideMinMaxLimits: null,\n\n /* Maximum possible value\n * value must be enclosed in quotes and use the period for the decimal point\n * value must be larger than minimumValue\n * Deprecated older option name : vMax\n */\n maximumValue: '9999999999999.99', // 9.999.999.999.999,99 ~= 10000 billions\n\n /* Minimum possible value\n * value must be enclosed in quotes and use the period for the decimal point\n * value must be smaller than maximumValue\n * Deprecated older option name : vMin\n */\n minimumValue: '-9999999999999.99', // -9.999.999.999.999,99 ~= 10000 billions\n\n /* Maximum number of decimal places = used to override decimal places set by the minimumValue & maximumValue values\n * Deprecated older option name : mDec\n */\n decimalPlacesOverride: null,\n\n /* Expanded decimal places visible when input has focus - example:\n * {decimalPlacesShownOnFocus: \"5\"} and the default 2 decimal places with focus \"1,000.12345\" without focus \"1,000.12\" the results depends on the rounding method used\n * the \"get\" method returns the extended decimal places\n * Deprecated older option name : eDec\n */\n decimalPlacesShownOnFocus: null,\n\n /* The next three options (scaleDivisor, scaleDecimalPlaces & scaleSymbol) handle scaling of the input when the input does not have focus\n * Please note that the non-scaled value is held in data and it is advised that you use the \"saveValueToSessionStorage\" option to ensure retaining the value\n * [\"divisor\", \"decimal places\", \"symbol\"]\n * Example: with the following options set {scaleDivisor: '1000', scaleDecimalPlaces: '1', scaleSymbol: ' K'}\n * Example: focusin value \"1,111.11\" focusout value \"1.1 K\"\n */\n\n /* The `scaleDivisor` decides the on focus value and places the result in the input on focusout\n * Example {scaleDivisor: '1000'} or \n * The divisor value - does not need to be whole number but please understand that Javascript has limited accuracy in math\n * The \"get\" method returns the full value, including the 'hidden' decimals.\n */\n scaleDivisor: null,\n\n /*\n * The `scaleDecimalPlaces` option is the number of decimal place when not in focus - for this to work, `scaledDivisor` must not be `null`.\n * This is optional ; if omitted the decimal places will be the same when the input has the focus.\n * Deprecated older option name : scaleDecimal\n */\n scaleDecimalPlaces: null,\n\n /*\n * The `scaleSymbol` option is a symbol placed as a suffix when not in focus.\n * This is optional too.\n */\n scaleSymbol: null,\n\n /* Set to true to allow the decimalPlacesShownOnFocus value to be saved with sessionStorage\n * if ie 6 or 7 the value will be saved as a session cookie\n * Deprecated older option name : aStor\n */\n saveValueToSessionStorage: false,\n\n /*\n * Manage how autoNumeric react when the user tries to paste an invalid number.\n * - 'error' : (This is the default behavior) The input value is not changed and an error is output in the console.\n * - 'ignore' : idem than 'error', but fail silently without outputting any error/warning in the console.\n * - 'clamp' : if the pasted value is either too small or too big regarding the minimumValue and maximumValue range, then the result is clamped to those limits.\n * - 'truncate' : autoNumeric will insert as many pasted numbers it can at the initial caret/selection, until everything is pasted, or the range limit is hit.\n * The non-pasted numbers are dropped and therefore not used at all.\n * - 'replace' : autoNumeric will first insert as many pasted numbers it can at the initial caret/selection, then if the range limit is hit, it will try\n * to replace one by one the remaining initial numbers (on the right side of the caret) with the rest of the pasted numbers.\n *\n * Note 1 : A paste content starting with a negative sign '-' will be accepted anywhere in the input, and will set the resulting value as a negative number\n * Note 2 : A paste content starting with a number will be accepted, even if the rest is gibberish (ie. '123foobar456').\n * Only the first number will be used (here '123').\n * Note 3 : The paste event works with the `decimalPlacesShownOnFocus` option too.\n */\n //TODO Shouldn't we use `truncate` as the default value?\n onInvalidPaste: 'error',\n\n /* method used for rounding\n * roundingMethod: \"S\", Round-Half-Up Symmetric (default)\n * roundingMethod: \"A\", Round-Half-Up Asymmetric\n * roundingMethod: \"s\", Round-Half-Down Symmetric (lower case s)\n * roundingMethod: \"a\", Round-Half-Down Asymmetric (lower case a)\n * roundingMethod: \"B\", Round-Half-Even \"Bankers Rounding\"\n * roundingMethod: \"U\", Round Up \"Round-Away-From-Zero\"\n * roundingMethod: \"D\", Round Down \"Round-Toward-Zero\" - same as truncate\n * roundingMethod: \"C\", Round to Ceiling \"Toward Positive Infinity\"\n * roundingMethod: \"F\", Round to Floor \"Toward Negative Infinity\"\n * roundingMethod: \"N05\" Rounds to the nearest .05 => same as \"CHF\" used in 1.9X and still valid\n * roundingMethod: \"U05\" Rounds up to next .05\n * roundingMethod: \"D05\" Rounds down to next .05\n * Deprecated older option name : mRound\n */\n //TODO Rename the options to more explicit names ('S' => 'RoundHalfUpSymmetric', etc.)\n //TODO Add an `an.roundingMethod` object that enum those options clearly\n roundingMethod: 'S',\n\n /* Allow padding the decimal places with zeros\n * allowDecimalPadding: true - always Pad decimals with zeros\n * allowDecimalPadding: false - does not pad with zeros.\n * Note: setting allowDecimalPadding to 'false' will override the 'decimalPlacesOverride' setting.\n *\n * thanks to Jonas Johansson for the suggestion\n * Deprecated older option name : aPad\n */\n allowDecimalPadding: true,\n\n /* Adds brackets on negative values (ie. transforms '-$ 999.99' to '(999.99)')\n * Those brackets are visible only when the field does NOT have the focus.\n * The left and right symbols should be enclosed in quotes and separated by a comma\n * This option can be of the following values :\n * null, // This is the default value, which deactivate this feature\n * '(,)',\n * '[,]',\n * '<,>' or\n * '{,}'\n * Deprecated older option name : nBracket\n */\n //TODO Rename the options to more explicit names ('(,)' => 'parentheses', etc.)\n negativeBracketsTypeOnBlur: null,\n\n /* Displayed on empty string \"\"\n * emptyInputBehavior: \"focus\" - (default) currency sign displayed and the input receives focus\n * emptyInputBehavior: \"press\" - currency sign displays on any key being pressed\n * emptyInputBehavior: \"always\" - always displays the currency sign only\n * emptyInputBehavior: \"zero\" - if the input has no value on focus out displays a zero \"rounded\" with or without a currency sign\n * Deprecated older option name : wEmpty\n */\n emptyInputBehavior: 'focus',\n\n /* Controls leading zero behavior\n * leadingZero: \"allow\", - allows leading zeros to be entered. Zeros will be truncated when entering additional digits. On focusout zeros will be deleted.\n * leadingZero: \"deny\", - allows only one leading zero on values less than one\n * leadingZero: \"keep\", - allows leading zeros to be entered. on focusout zeros will be retained.\n * Deprecated older option name : lZero\n */\n leadingZero: 'deny',\n\n /* Determine if the default value will be formatted on initialization.\n * true = automatically formats the default value on initialization\n * false = will not format the default value on initialization\n * Deprecated older option name : aForm\n */\n formatOnPageLoad: true,\n\n /* Determine if the select all keyboard command will select the complete input text, or only the input numeric value\n * Note : If the currency symbol is between the numeric value and the negative sign, only the numeric value will selected\n * Deprecated older option name : sNumber\n */\n selectNumberOnly: false,\n\n /* Helper option for ASP.NET postback\n * should be the value of the unformatted default value\n * examples:\n * no default value=\"\" {defaultValueOverride: \"\"}\n * value=1234.56 {defaultValueOverride: '1234.56'}\n * Deprecated older option name : anDefault\n */\n defaultValueOverride: null,\n\n /* Removes formatting on submit event\n * this output format: positive nnnn.nn, negative -nnnn.nn\n * review the 'unSet' method for other formats\n * Deprecated older option name : unSetOnSubmit\n */\n unformatOnSubmit: false,\n\n /* Allows the output to be in the locale format via the \"get\", \"getString\" & \"getArray\" methods\n * null or 'string' => 'nnnn.nn' or '-nnnn.nn' as text type. This is the default behavior.\n * 'number' => nnnn.nn or -nnnn.nn as a Number (Warning: this works only for integers inferior to Number.MAX_SAFE_INTEGER)\n * ',' or '-,' => 'nnnn,nn' or '-nnnn,nn'\n * '.-' => 'nnnn.nn' or 'nnnn.nn-'\n * ',-' => 'nnnn,nn' or 'nnnn,nn-'\n * Deprecated older option name : outputType\n */\n outputFormat: null,\n\n /* Defines if warnings should be shown\n * Error handling function\n * true => all warning are shown\n * false => no warnings are shown, only the thrown errors\n * Deprecated older option name : debug\n */\n showWarnings: true,\n\n /*\n * This option is the 'strict mode' (aka 'debug' mode), which allows autoNumeric to strictly analyse the options passed, and fails if an unknown options is used in the settings object.\n * You should set that to 'TRUE' if you want to make sure you are only using 'pure' autoNumeric settings objects in your code.\n * If you see uncaught errors in the console and your code starts to fail, this means somehow those options gets corrupted by another program.\n */\n failOnUnknownOption: false,\n};\n\n/**\n * Wrapper variable that hold named keyboard keys with their respective keyCode as seen in DOM events.\n * //TODO Replace every call to this object with a call to `keyName`\n * @deprecated\n */\nconst keyCode = {\n Backspace: 8,\n Tab: 9,\n Enter: 13,\n Shift: 16,\n Ctrl: 17,\n Alt: 18,\n PauseBreak: 19,\n CapsLock: 20,\n Esc: 27,\n Space: 32,\n PageUp: 33,\n PageDown: 34,\n End: 35,\n Home: 36,\n LeftArrow: 37,\n UpArrow: 38,\n RightArrow: 39,\n DownArrow: 40,\n Insert: 45,\n Delete: 46,\n num0: 48,\n num1: 49,\n num2: 50,\n num3: 51,\n num4: 52,\n num5: 53,\n num6: 54,\n num7: 55,\n num8: 56,\n num9: 57,\n a: 65,\n b: 66,\n c: 67,\n d: 68,\n e: 69,\n f: 70,\n g: 71,\n h: 72,\n i: 73,\n j: 74,\n k: 75,\n l: 76,\n m: 77,\n n: 78,\n o: 79,\n p: 80,\n q: 81,\n r: 82,\n s: 83,\n t: 84,\n u: 85,\n v: 86,\n w: 87,\n x: 88,\n y: 89,\n z: 90,\n Windows: 91,\n RightClick: 93,\n numpad0: 96,\n numpad1: 97,\n numpad2: 98,\n numpad3: 99,\n numpad4: 100,\n numpad5: 101,\n numpad6: 102,\n numpad7: 103,\n numpad8: 104,\n numpad9: 105,\n MultiplyNumpad: 106,\n PlusNumpad: 107,\n MinusNumpad: 109,\n DotNumpad: 110,\n SlashNumpad: 111,\n F1: 112,\n F2: 113,\n F3: 114,\n F4: 115,\n F5: 116,\n F6: 117,\n F7: 118,\n F8: 119,\n F9: 120,\n F10: 121,\n F11: 122,\n F12: 123,\n NumLock: 144,\n ScrollLock: 145,\n MyComputer: 182,\n MyCalculator: 183,\n Semicolon: 186,\n Equal: 187,\n Comma: 188,\n Hyphen: 189,\n Dot: 190,\n Slash: 191,\n Backquote: 192,\n LeftBracket: 219,\n Backslash: 220,\n RightBracket: 221,\n Quote: 222,\n Command: 224,\n AndroidDefault: 229, // Android Chrome returns the same keycode number 229 for all keys pressed\n};\n\n/**\n * Wrapper variable that hold named keyboard keys with their respective key name (as set in KeyboardEvent.key).\n * Those names are listed here :\n * @link https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values\n */\nconst keyName = {\n // Special values\n Unidentified: 'Unidentified',\n\n // Modifier keys\n Alt: 'Alt',\n AltGr: 'AltGraph',\n CapsLock: 'CapsLock', // Under Chrome, e.key is empty for CapsLock\n Ctrl: 'Control',\n Fn: 'Fn',\n FnLock: 'FnLock',\n Hyper: 'Hyper', // 'OS' under Firefox\n Meta: 'Meta', // The Windows, Command or ⌘ key // 'OS' under Firefox and IE9\n Windows: 'Meta', // This is a non-official key name\n Command: 'Meta', // This is a non-official key name\n NumLock: 'NumLock',\n ScrollLock: 'ScrollLock',\n Shift: 'Shift',\n Super: 'Super', // 'OS' under Firefox\n Symbol: 'Symbol',\n SymbolLock: 'SymbolLock',\n\n // Whitespace keys\n Enter: 'Enter',\n Tab: 'Tab',\n Space: ' ', // 'Spacebar' for Firefox <37, and IE9\n\n // Navigation keys\n DownArrow: 'ArrowDown', // 'Down' for Firefox <=36, and IE9\n LeftArrow: 'ArrowLeft', // 'Left' for Firefox <=36, and IE9\n RightArrow: 'ArrowRight', // 'Right' for Firefox <=36, and IE9\n UpArrow: 'ArrowUp', // 'Up' for Firefox <=36, and IE9\n End: 'End',\n Home: 'Home',\n PageDown: 'PageDown',\n PageUp: 'PageUp',\n\n // Editing keys\n Backspace: 'Backspace',\n Clear: 'Clear',\n Copy: 'Copy',\n CrSel: 'CrSel', // 'Crsel' for Firefox <=36, and IE9\n Cut: 'Cut',\n Delete: 'Delete', // 'Del' for Firefox <=36, and IE9\n EraseEof: 'EraseEof',\n ExSel: 'ExSel', // 'Exsel' for Firefox <=36, and IE9\n Insert: 'Insert',\n Paste: 'Paste',\n Redo: 'Redo',\n Undo: 'Undo',\n\n // UI keys\n Accept: 'Accept',\n Again: 'Again',\n Attn: 'Attn', // 'Unidentified' for Firefox, Chrome, and IE9 ('KanaMode' when using the Japanese keyboard layout)\n Cancel: 'Cancel',\n ContextMenu: 'ContextMenu', // 'Apps' for Firefox <=36, and IE9\n Esc: 'Escape', // 'Esc' for Firefox <=36, and IE9\n Execute: 'Execute',\n Find: 'Find',\n Finish: 'Finish', // 'Unidentified' for Firefox, Chrome, and IE9 ('Katakana' when using the Japanese keyboard layout)\n Help: 'Help',\n Pause: 'Pause',\n Play: 'Play',\n Props: 'Props',\n Select: 'Select',\n ZoomIn: 'ZoomIn',\n ZoomOut: 'ZoomOut',\n\n // Device keys\n BrightnessDown: 'BrightnessDown',\n BrightnessUp: 'BrightnessUp',\n Eject: 'Eject',\n LogOff: 'LogOff',\n Power: 'Power',\n PowerOff: 'PowerOff',\n PrintScreen: 'PrintScreen',\n Hibernate: 'Hibernate', // 'Unidentified' for Firefox <=37\n Standby: 'Standby', // 'Unidentified' for Firefox <=36, and IE9\n WakeUp: 'WakeUp',\n\n // IME and composition keys\n Compose: 'Compose',\n Dead: 'Dead',\n\n // Function keys\n F1: 'F1',\n F2: 'F2',\n F3: 'F3',\n F4: 'F4',\n F5: 'F5',\n F6: 'F6',\n F7: 'F7',\n F8: 'F8',\n F9: 'F9',\n F10: 'F10',\n F11: 'F11',\n F12: 'F12',\n\n // Document keys\n Print: 'Print',\n\n // 'Normal' keys\n num0: '0',\n num1: '1',\n num2: '2',\n num3: '3',\n num4: '4',\n num5: '5',\n num6: '6',\n num7: '7',\n num8: '8',\n num9: '9',\n numpad0: '0',\n numpad1: '1',\n numpad2: '2',\n numpad3: '3',\n numpad4: '4',\n numpad5: '5',\n numpad6: '6',\n numpad7: '7',\n numpad8: '8',\n numpad9: '9',\n a: 'a',\n b: 'b',\n c: 'c',\n d: 'd',\n e: 'e',\n f: 'f',\n g: 'g',\n h: 'h',\n i: 'i',\n j: 'j',\n k: 'k',\n l: 'l',\n m: 'm',\n n: 'n',\n o: 'o',\n p: 'p',\n q: 'q',\n r: 'r',\n s: 's',\n t: 't',\n u: 'u',\n v: 'v',\n w: 'w',\n x: 'x',\n y: 'y',\n z: 'z',\n MultiplyNumpad: '*',\n PlusNumpad: '+',\n MinusNumpad: '-',\n DotNumpad: '.',\n SlashNumpad: '/',\n Semicolon: ';',\n Equal: '=',\n Comma: ',',\n Hyphen: '-',\n Minus: '-',\n Plus: '+',\n Dot: '.',\n Slash: '/',\n Backquote: '`',\n LeftBracket: '[',\n RightBracket: ']',\n Backslash: '\\\\',\n Quote: \"'\",\n NumpadDot: '.',\n NumpadDotAlt: ',', // Modern browsers automatically adapt the character sent by this key to the decimal character of the current language\n NumpadMultiply: '*',\n NumpadPlus: '+',\n NumpadMinus: '-',\n NumpadSlash: '/',\n NumpadDotObsoleteBrowsers: 'Decimal',\n NumpadMultiplyObsoleteBrowsers: 'Multiply',\n NumpadPlusObsoleteBrowsers: 'Add',\n NumpadMinusObsoleteBrowsers: 'Subtract',\n NumpadSlashObsoleteBrowsers: 'Divide',\n};\n\nconst defaultMinimumValue = '-999999999999.99';\nconst defaultMaximumValue = '999999999999.99';\nconst defaultRoundingMethod = 'U';\nconst defaultLeadingZero = 'deny';\nconst defaultSelectNumberOnly = true;\n\n/**\n * Predefined options for the most common languages\n */\nconst languageOption = {\n French: { // Français\n digitGroupSeparator : '.', // or '\\u202f'\n decimalCharacter : ',',\n decimalCharacterAlternative: '.',\n currencySymbol : '\\u202f€',\n currencySymbolPlacement : 's',\n selectNumberOnly : defaultSelectNumberOnly,\n roundingMethod : defaultRoundingMethod,\n leadingZero : defaultLeadingZero,\n minimumValue : defaultMinimumValue,\n maximumValue : defaultMaximumValue,\n },\n NorthAmerican: {\n digitGroupSeparator : ',',\n decimalCharacter : '.',\n currencySymbol : '$',\n currencySymbolPlacement: 'p',\n selectNumberOnly : defaultSelectNumberOnly,\n roundingMethod : defaultRoundingMethod,\n leadingZero : defaultLeadingZero,\n minimumValue : defaultMinimumValue,\n maximumValue : defaultMaximumValue,\n },\n British: {\n digitGroupSeparator : ',',\n decimalCharacter : '.',\n currencySymbol : '£',\n currencySymbolPlacement: 'p',\n selectNumberOnly : defaultSelectNumberOnly,\n roundingMethod : defaultRoundingMethod,\n leadingZero : defaultLeadingZero,\n minimumValue : defaultMinimumValue,\n maximumValue : defaultMaximumValue,\n },\n Swiss: { // Suisse\n digitGroupSeparator : `'`,\n decimalCharacter : '.',\n currencySymbol : '\\u202fCHF',\n currencySymbolPlacement: 's',\n selectNumberOnly : defaultSelectNumberOnly,\n roundingMethod : defaultRoundingMethod,\n leadingZero : defaultLeadingZero,\n minimumValue : defaultMinimumValue,\n maximumValue : defaultMaximumValue,\n },\n Japanese: { // 日本語\n digitGroupSeparator : ',',\n decimalCharacter : '.',\n currencySymbol : '¥',\n currencySymbolPlacement: 'p',\n selectNumberOnly : defaultSelectNumberOnly,\n roundingMethod : defaultRoundingMethod,\n leadingZero : defaultLeadingZero,\n minimumValue : defaultMinimumValue,\n maximumValue : defaultMaximumValue,\n },\n};\nlanguageOption.Spanish = languageOption.French; // Español (idem French)\nlanguageOption.Chinese = languageOption.Japanese; // 中国語 (Chinese)\n\n/**\n * UMD structure\n */\n(function(factory) {\n //TODO This surely can be improved by letting webpack take care of generating this UMD part\nif (typeof define === 'function' && define.amd) {\n // AMD. Register as an anonymous module.\n define(['jquery'], factory);\n} else if (typeof module === 'object' && module.exports) {\n // Node/CommonJS\n module.exports = factory(require('jquery'));\n} else {\n // Browser globals\n factory(window.jQuery);\n}\n}($ => {\n // Helper functions\n\n /**\n * Return TRUE if the `value` is null\n *\n * @static\n * @param {*} value The value to test\n * @returns {boolean} Return TRUE if the `value` is null, FALSE otherwise\n */\n function isNull(value) {\n return value === null;\n }\n\n /**\n * Return TRUE if the `value` is undefined\n *\n * @static\n * @param {*} value The value to test\n * @returns {boolean} Return TRUE if the `value` is undefined, FALSE otherwise\n */\n function isUndefined(value) {\n return value === void(0);\n }\n\n /**\n * Return TRUE if the `value` is undefined, null or empty\n *\n * @param {*} value\n * @returns {boolean}\n */\n function isUndefinedOrNullOrEmpty(value) {\n return value === null || value === void(0) || '' === value;\n }\n\n /**\n * Return TRUE if the given parameter is a String\n *\n * @param {*} str\n * @returns {boolean}\n */\n function isString(str) {\n return (typeof str === 'string' || str instanceof String);\n }\n\n /**\n * Return TRUE if the parameter is a boolean\n *\n * @static\n * @param {*} value\n * @returns {boolean}\n */\n function isBoolean(value) {\n return typeof(value) === 'boolean';\n }\n\n /**\n * Return TRUE if the parameter is a string 'true' or 'false'\n *\n * This function accepts any cases for those strings.\n * @param {string} value\n * @returns {boolean}\n */\n function isTrueOrFalseString(value) {\n const lowercaseValue = String(value).toLowerCase();\n return lowercaseValue === 'true' || lowercaseValue === 'false';\n }\n\n /**\n * Return TRUE if the parameter is an object\n *\n * @param {*} reference\n * @returns {boolean}\n */\n function isObject(reference) {\n return typeof reference === 'object' && reference !== null && !Array.isArray(reference);\n }\n\n /**\n * Return TRUE if the given object is empty\n * cf. http://stackoverflow.com/questions/679915/how-do-i-test-for-an-empty-javascript-object and http://jsperf.com/empty-object-test\n *\n * @param {object} obj\n * @returns {boolean}\n */\n function isEmptyObj(obj) {\n for (const prop in obj) {\n if (obj.hasOwnProperty(prop)) {\n return false;\n }\n }\n return true;\n }\n\n /**\n * Return TRUE if the parameter is a number (or a number written as a string).\n *\n * @param {*} n\n * @returns {boolean}\n */\n function isNumber(n) {\n return !isArray(n) && !isNaN(parseFloat(n)) && isFinite(n);\n }\n\n /**\n * Return TRUE if the parameter is an integer (and not a float).\n *\n * @param {*} n\n * @returns {boolean}\n */\n function isInt(n) {\n return typeof n === 'number' && parseFloat(n) === parseInt(n, 10) && !isNaN(n);\n }\n\n /**\n * Return the pasted text that will be used.\n *\n * @param {string} text\n * @param {AutoNumericHolder} holder\n * @returns {string|void|XML|*}\n */\n function preparePastedText(text, holder) {\n return stripAllNonNumberCharacters(text, holder.settingsClone, true).replace(holder.settingsClone.decimalCharacter, '.');\n }\n\n /**\n * Return TRUE is the string `str` contains the string `needle`\n * Note: this function does not coerce the parameters types\n *\n * @param {string} str\n * @param {string} needle\n * @returns {boolean}\n */\n function contains(str, needle) {\n if (!isString(str) || !isString(needle) || str === '' || needle === '') {\n return false;\n }\n\n return str.indexOf(needle) !== -1;\n }\n\n /**\n * Return TRUE if the `needle` is in the array\n *\n * @param {*} needle\n * @param {Array} array\n * @returns {boolean}\n */\n function isInArray(needle, array) {\n if (!isArray(array) || array === [] || isUndefined(needle)) {\n return false;\n }\n\n return array.indexOf(needle) !== -1;\n }\n\n /**\n * Return TRUE if the parameter is an Array\n *\n * @param {*} arr\n * @throws Error\n * @returns {*|boolean}\n */\n function isArray(arr) {\n if (Object.prototype.toString.call([]) === '[object Array]') { // Make sure an array has a class attribute of [object Array]\n // Test passed, now check if is an Array\n return Array.isArray(arr) || (typeof arr === 'object' && Object.prototype.toString.call(arr) === '[object Array]');\n }\n else {\n throw new Error('toString message changed for Object Array'); // Verify that the string returned by `toString` does not change in the future (cf. http://stackoverflow.com/a/8365215)\n }\n }\n\n /**\n * Return TRUE if the parameter is a string that represents a float number, and that number has a decimal part\n *\n * @param {string} str\n * @returns {boolean}\n */\n // function hasDecimals(str) {\n // const [, decimalPart] = str.split('.');\n // return !isUndefined(decimalPart);\n // }\n\n /**\n * Return the number of decimal places if the parameter is a string that represents a float number, and that number has a decimal part.\n *\n * @param {string} str\n * @returns {int}\n */\n function decimalPlaces(str) {\n const [, decimalPart] = str.split('.');\n if (!isUndefined(decimalPart)) {\n return decimalPart.length;\n }\n\n return 0;\n }\n\n /**\n * Return the code for the key used to generate the given event.\n *\n * @param {Event} event\n * @returns {string|Number}\n */\n function keyCodeNumber(event) {\n // `event.keyCode` and `event.which` are deprecated, `KeyboardEvent.key` (https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key) must be used now\n return (typeof event.which === 'undefined')?event.keyCode:event.which;\n }\n\n /**\n * Return the character from the event key code.\n * @example character(50) => '2'\n *\n * @param {Event} event\n * @returns {string}\n */\n function character(event) {\n if (typeof event.key === 'undefined' || event.key === 'Unidentified') {\n return String.fromCharCode(keyCodeNumber(event));\n } else {\n // Special case for obsolete browsers like IE that return the old names\n let result;\n switch (event.key) {\n case 'Decimal':\n result = keyName.NumpadDot;\n break;\n case 'Multiply':\n result = keyName.NumpadMultiply;\n break;\n case 'Add':\n result = keyName.NumpadPlus;\n break;\n case 'Subtract':\n result = keyName.NumpadMinus;\n break;\n case 'Divide':\n result = keyName.NumpadSlash;\n break;\n case 'Del':\n // Special workaround for the obsolete browser IE11 which output a 'Delete' key when using the numpad 'dot' one! This fixes issue #401 //FIXME à terminer\n result = keyName.Dot; // as of version 2.0.8 the character() function is only called on keypress event. The 'Del' does not throw the keypress event.\n break;\n default:\n result = event.key;\n }\n\n return result;\n }\n }\n\n /**\n * Return TRUE if the given value (a number as a string) is within the range set in the settings `minimumValue` and `maximumValue`, FALSE otherwise.\n *\n * @param {string} value\n * @param {object} parsedMinValue Parsed via the `parseStr()` function\n * @param {object} parsedMaxValue Parsed via the `parseStr()` function\n * @returns {boolean}\n */\n function checkIfInRange(value, parsedMinValue, parsedMaxValue) {\n const parsedValue = parseStr(value);\n return testMinMax(parsedMinValue, parsedValue) > -1 && testMinMax(parsedMaxValue, parsedValue) < 1;\n }\n\n /**\n * Return TRUE if the given string contains a negative sign :\n * - everywhere in the string (by default), or\n * - on the first character only if the `checkEverywhere` parameter is set to `false`.\n *\n * @param {string} numericString A number represented by a string\n * @param {boolean} checkEverywhere If TRUE, then the negative sign is search everywhere in the numeric string (this is needed for instance if the string is '1234.56-')\n * @returns {boolean}\n */\n function isNegative(numericString, checkEverywhere = true) {\n //TODO Use the `negativeSignCharacter` from the settings here\n if (checkEverywhere) {\n return contains(numericString, '-');\n }\n\n return isNegativeStrict(numericString);\n }\n\n /**\n * Return TRUE if the given string contains a negative sign on the first character (on the far left).\n *\n * @example isNegativeStrict('1234.56') => false\n * @example isNegativeStrict('1234.56-') => false\n * @example isNegativeStrict('-1234.56') => true\n * @example isNegativeStrict('-1,234.56 €') => true\n *\n * @param {string} numericString\n * @returns {boolean}\n */\n function isNegativeStrict(numericString) {\n //TODO Using the `negativeSignCharacter` from the settings here\n return numericString.charAt(0) === '-';\n }\n\n /**\n * Return TRUE if the formatted or unformatted numeric string represent the value 0 (ie. '0,00 €'), or is empty (' €').\n * This works since we test if there are any numbers from 1 to 9 in the string. If there is none, then the number is zero (or the string is empty).\n *\n * @param {string} numericString\n * @returns {boolean}\n */\n function isZeroOrHasNoValue(numericString) {\n return !(/[1-9]/g).test(numericString);\n }\n\n /**\n * Return the negative version of the value (represented as a string) given as a parameter.\n *\n * @param {string} value\n * @returns {*}\n */\n function setRawNegativeSign(value) {\n if (!isNegativeStrict(value)) {\n return `-${value}`;\n }\n\n return value;\n }\n\n /**\n * Replace the character at the position `index` in the string `string` by the character(s) `newCharacter`.\n *\n * @param {string} string\n * @param {int} index\n * @param {string} newCharacter\n * @returns {string}\n */\n function replaceCharAt(string, index, newCharacter) {\n return `${string.substr(0, index)}${newCharacter}${string.substr(index + newCharacter.length)}`;\n }\n\n /**\n * Return the value clamped to the nearest minimum/maximum value, as defined in the settings.\n *\n * @param {string|number} value\n * @param {object} settings\n * @returns {number}\n */\n function clampToRangeLimits(value, settings) {\n //XXX This function always assume `settings.minimumValue` is lower than `settings.maximumValue`\n return Math.max(settings.minimumValue, Math.min(settings.maximumValue, value));\n }\n\n /**\n * Return the number of number or dot characters on the left side of the caret, in a formatted number.\n *\n * @param {string} formattedNumberString\n * @param {int} caretPosition This must be a positive integer\n * @param {string} decimalCharacter\n * @returns {number}\n */\n function countNumberCharactersOnTheCaretLeftSide(formattedNumberString, caretPosition, decimalCharacter) {\n // Here we count the dot and report it as a number character too, since it will 'stay' in the Javascript number when unformatted\n const numberDotOrNegativeSign = new RegExp(`[0-9${decimalCharacter}-]`); // No need to escape the decimal character here, since it's in `[]`\n\n let numberDotAndNegativeSignCount = 0;\n for (let i = 0; i < caretPosition; i++) {\n // Test if the character is a number, a dot or an hyphen. If it is, count it, otherwise ignore it\n if (numberDotOrNegativeSign.test(formattedNumberString[i])) {\n numberDotAndNegativeSignCount++;\n }\n }\n\n return numberDotAndNegativeSignCount;\n }\n\n /**\n * Walk the `formattedNumberString` from left to right, one char by one, counting the `formattedNumberStringIndex`.\n * If the char is in the `rawNumberString` (starting at index 0), then `rawNumberStringIndex++`, and continue until\n * there is no more characters in `rawNumberString`) or that `rawNumberStringIndex === caretPositionInRawValue`.\n * When you stop, the `formattedNumberStringIndex` is the position where the caret should be set.\n *\n * @example\n * 1234567|89.01 : position 7 (rawNumberString)\n * 123.456.7|89,01 : position 9 (formattedNumberString)\n *\n * @param {string} rawNumberString\n * @param {int} caretPositionInRawValue\n * @param {string} formattedNumberString\n * @param {string} decimalCharacter\n * @returns {*}\n */\n function findCaretPositionInFormattedNumber(rawNumberString, caretPositionInRawValue, formattedNumberString, decimalCharacter) {\n const formattedNumberStringSize = formattedNumberString.length;\n const rawNumberStringSize = rawNumberString.length;\n\n let formattedNumberStringIndex;\n let rawNumberStringIndex = 0;\n for (formattedNumberStringIndex = 0;\n formattedNumberStringIndex < formattedNumberStringSize &&\n rawNumberStringIndex < rawNumberStringSize &&\n rawNumberStringIndex < caretPositionInRawValue;\n formattedNumberStringIndex++) {\n if (rawNumberString[rawNumberStringIndex] === formattedNumberString[formattedNumberStringIndex] ||\n (rawNumberString[rawNumberStringIndex] === '.' && formattedNumberString[formattedNumberStringIndex] === decimalCharacter)) {\n rawNumberStringIndex++;\n }\n }\n\n return formattedNumberStringIndex;\n }\n\n /**\n * Count the number of occurrence of the given character, in the given text.\n *\n * @param {string} character\n * @param {string} text\n * @returns {number}\n */\n function countCharInText(character, text) {\n let charCounter = 0;\n for (let i = 0; i < text.length; i++) {\n if (text[i] === character) {\n charCounter++;\n }\n }\n\n return charCounter;\n }\n\n /**\n * Return the index that can be used to set the caret position.\n * This takes into account that the position is starting at '0', not 1.\n *\n * @param {int} characterCount\n * @returns {number}\n */\n function convertCharacterCountToIndexPosition(characterCount) {\n return Math.max(characterCount, characterCount - 1);\n }\n\n /**\n * Cross browser routine for getting selected range/cursor position\n *\n * @param {HTMLElement|EventTarget} that\n * @returns {{}}\n */\n function getElementSelection(that) {\n const position = {};\n if (isUndefined(that.selectionStart)) {\n that.focus();\n const select = document.selection.createRange();\n position.length = select.text.length;\n select.moveStart('character', -that.value.length);\n position.end = select.text.length;\n position.start = position.end - position.length;\n } else {\n position.start = that.selectionStart;\n position.end = that.selectionEnd;\n position.length = position.end - position.start;\n }\n\n return position;\n }\n\n /**\n * Cross browser routine for setting selected range/cursor position\n *\n * @param {HTMLElement|EventTarget} that\n * @param {int} start\n * @param {int|null} end\n */\n function setElementSelection(that, start, end = null) {\n if (isUndefinedOrNullOrEmpty(end)) {\n end = start;\n }\n\n if (isUndefined(that.selectionStart)) {\n that.focus();\n const range = that.createTextRange();\n range.collapse(true);\n range.moveEnd('character', end);\n range.moveStart('character', start);\n range.select();\n } else {\n that.selectionStart = start;\n that.selectionEnd = end;\n }\n }\n\n /**\n * Function that throw error messages\n *\n * @param {string} message\n */\n function throwError(message) {\n throw new Error(message);\n }\n\n /**\n * Function that display a warning messages, according to the debug level.\n *\n * @param {string} message\n * @param {boolean} showWarning If FALSE, then the warning message is not displayed\n */\n function warning(message, showWarning = true) {\n if (showWarning) {\n /* eslint no-console: 0 */\n console.warn(`Warning: ${message}`);\n }\n }\n\n // autoNumeric-specific functions\n\n /**\n * Run any callbacks found in the settings object.\n * Any parameter could be a callback:\n * - a function, which invoked with jQuery element, parameters and this parameter name and returns parameter value\n * - a name of function, attached to $(selector).autoNumeric.functionName(){} - which was called previously\n * @param {object} $this jQuery-selected DOM element\n * @param {object} settings\n */\n function runCallbacksFoundInTheSettingsObject($this, settings) {\n // Loops through the settings object (option array) to find the following\n $.each(settings, (k, val) => {\n if (typeof val === 'function') {\n settings[k] = val($this, settings, k);\n } else if (typeof $this.autoNumeric[val] === 'function') {\n // Calls the attached function from the html5 data example: data-a-sign=\"functionName\"\n settings[k] = $this.autoNumeric[val]($this, settings, k);\n }\n });\n }\n\n /**\n * Determine the maximum decimal length from the minimumValue and maximumValue settings\n *\n * @param {string} minimumValue\n * @param {string} maximumValue\n * @returns {number}\n */\n function maximumVMinAndVMaxDecimalLength(minimumValue, maximumValue) {\n return Math.max(decimalPlaces(minimumValue), decimalPlaces(maximumValue));\n }\n\n /**\n * Strip all unwanted non-number characters.\n * This keeps the numbers, the negative sign as well as the custom decimal character.\n *\n * @param {string} s\n * @param {object} settings\n * @param {boolean} leftOrAll\n * @returns {string|*}\n */\n function stripAllNonNumberCharacters(s, settings, leftOrAll) {\n //TODO This function is called 10 times (sic!) on each key input, couldn't we lower that number? cf. issue #325\n //TODO Refactor this with `convertToNumericString()` if possible?\n if (settings.currencySymbol !== '') {\n // Remove currency sign\n s = s.replace(settings.currencySymbol, '');\n }\n if (settings.suffixText) {\n // Remove suffix\n while (contains(s, settings.suffixText)) {\n s = s.replace(settings.suffixText, '');\n }\n }\n\n // First replace anything before digits\n s = s.replace(settings.skipFirstAutoStrip, '$1$2');\n\n if ((settings.negativePositiveSignPlacement === 's' ||\n (settings.currencySymbolPlacement === 's' && settings.negativePositiveSignPlacement !== 'p')) &&\n isNegative(s) &&\n s !== '') {\n settings.trailingNegative = true;\n }\n\n // Then replace anything after digits\n s = s.replace(settings.skipLastAutoStrip, '$1');\n\n // Then remove any uninteresting characters\n s = s.replace(settings.allowedAutoStrip, '');\n if (settings.decimalCharacterAlternative) {\n s = s.replace(settings.decimalCharacterAlternative, settings.decimalCharacter);\n }\n\n // Get only number string\n const m = s.match(settings.numRegAutoStrip);\n s = m ? [m[1], m[2], m[3]].join('') : '';\n\n if (settings.leadingZero === 'allow' || settings.leadingZero === 'keep') {\n let nSign = '';\n const [integerPart, decimalPart] = s.split(settings.decimalCharacter);\n let modifiedIntegerPart = integerPart;\n if (contains(modifiedIntegerPart, settings.negativeSignCharacter)) {\n nSign = settings.negativeSignCharacter;\n modifiedIntegerPart = modifiedIntegerPart.replace(settings.negativeSignCharacter, '');\n }\n\n // Strip leading zero on positive value if need\n if (nSign === '' && modifiedIntegerPart.length > settings.mIntPos && modifiedIntegerPart.charAt(0) === '0') {\n modifiedIntegerPart = modifiedIntegerPart.slice(1);\n }\n\n // Strip leading zero on negative value if need\n if (nSign !== '' && modifiedIntegerPart.length > settings.mIntNeg && modifiedIntegerPart.charAt(0) === '0') {\n modifiedIntegerPart = modifiedIntegerPart.slice(1);\n }\n\n s = `${nSign}${modifiedIntegerPart}${isUndefined(decimalPart)?'':settings.decimalCharacter + decimalPart}`;\n }\n\n if ((leftOrAll && settings.leadingZero === 'deny') ||\n (!settings.hasFocus && settings.leadingZero === 'allow')) {\n s = s.replace(settings.stripReg, '$1$2');\n }\n\n return s;\n }\n\n /**\n * Sets or removes brackets on negative values, depending on the focus state.\n * The focus state is 'stored' in the settings object under the `settings.hasFocus` attribute.\n * //TODO Use another object to keep track of internal data that are not settings\n *\n * @param {string} s\n * @param {object} settings\n * @returns {*}\n */\n function toggleNegativeBracket(s, settings) {\n if ((settings.currencySymbolPlacement === 'p' && settings.negativePositiveSignPlacement === 'l') ||\n (settings.currencySymbolPlacement === 's' && settings.negativePositiveSignPlacement === 'p')) {\n //TODO Split the first and last bracket only once during the settings initialization\n const [firstBracket, lastBracket] = settings.negativeBracketsTypeOnBlur.split(',');\n if (!settings.hasFocus) {\n // Add brackets\n s = s.replace(settings.negativeSignCharacter, '');\n s = firstBracket + s + lastBracket;\n } else if (settings.hasFocus && s.charAt(0) === firstBracket) {\n // Remove brackets\n //TODO Quid if the negative sign is not on the left, shouldn't we replace the '-' sign at the right place?\n s = s.replace(firstBracket, settings.negativeSignCharacter);\n s = s.replace(lastBracket, '');\n }\n }\n\n return s;\n }\n\n /**\n * Return a number as a numeric string that can be typecast to a Number that Javascript will understand.\n *\n * This function return the given string by stripping the currency sign (currencySymbol), the grouping separators (digitalGroupSpacing) and by replacing the decimal character (decimalCharacter) by a dot.\n * Lastly, it also put the negative sign back to its normal position if needed.\n *\n * @param {string} s\n * @param {object} settings\n * @returns {string|void|XML|*}\n */\n function convertToNumericString(s, settings) {\n // Remove the currency symbol\n s = s.replace(settings.currencySymbol, '');\n\n // Remove the grouping separators (thousands separators usually)\n s = s.replace(settings.digitGroupSeparator, '');\n\n // Replace the decimal character by a dot\n if (settings.decimalCharacter !== '.') {\n s = s.replace(settings.decimalCharacter, '.');\n }\n\n // Move the trailing negative sign to the right position, if any\n if (isNegative(s) && s.lastIndexOf('-') === s.length - 1) {\n s = s.replace('-', '');\n s = '-' + s;\n }\n\n // Convert any arabic numbers to latin ones\n const temp = arabicToLatinNumbers(s, true, false, false);\n if (!isNaN(temp)) {\n s = temp.toString();\n }\n\n return s;\n }\n\n /**\n * Converts the ISO numeric string to the locale decimal and minus sign placement.\n * See the \"outputFormat\" option definition for more details.\n *\n * @param {string|null} value\n * @param {string} locale\n * @returns {*}\n */\n function toLocale(value, locale) {\n if (isNull(locale) || locale === 'string') {\n return value;\n }\n\n let result;\n switch (locale) {\n case 'number':\n result = Number(value);\n break;\n case '.-':\n result = isNegative(value) ? value.replace('-', '') + '-' : value;\n break;\n case ',':\n case '-,':\n result = value.replace('.', ',');\n break;\n case ',-':\n result = value.replace('.', ',');\n result = isNegative(result) ? result.replace('-', '') + '-' : result;\n break;\n // The default case\n case '.':\n case '-.':\n result = value;\n break;\n default :\n throwError(`The given outputFormat [${locale}] option is not recognized.`);\n }\n\n return result;\n }\n\n /**\n * Modify the negative sign and the decimal character of the given string value to an hyphen (-) and a dot (.) in order to make that value 'typecastable' to a real number.\n *\n * @param {string} s\n * @param {object} settings\n * @returns {string}\n */\n function modifyNegativeSignAndDecimalCharacterForRawValue(s, settings) {\n if (settings.decimalCharacter !== '.') {\n s = s.replace(settings.decimalCharacter, '.');\n }\n if (settings.negativeSignCharacter !== '-' && settings.negativeSignCharacter !== '') {\n s = s.replace(settings.negativeSignCharacter, '-');\n }\n if (!s.match(/\\d/)) {\n // The default value returned by `get` is not formatted with decimals\n s += '0';\n }\n\n return s;\n }\n\n /**\n * Modify the negative sign and the decimal character to use those defined in the settings.\n *\n * @param {string} s\n * @param {object} settings\n * @returns {string}\n */\n function modifyNegativeSignAndDecimalCharacterForFormattedValue(s, settings) {\n if (settings.negativeSignCharacter !== '-' && settings.negativeSignCharacter !== '') {\n s = s.replace('-', settings.negativeSignCharacter);\n }\n if (settings.decimalCharacter !== '.') {\n s = s.replace('.', settings.decimalCharacter);\n }\n\n return s;\n }\n\n /**\n * Private function to check for empty value\n * //TODO Modify this function so that it return either TRUE or FALSE if the value is empty. Then create another function to return the input value if it's not empty.\n *\n * @param {string} inputValue\n * @param {object} settings\n * @param {boolean} signOnEmpty\n * @returns {*}\n */\n function checkEmpty(inputValue, settings, signOnEmpty) {\n if (inputValue === '' || inputValue === settings.negativeSignCharacter) {\n if (settings.emptyInputBehavior === 'always' || signOnEmpty) {\n return (settings.negativePositiveSignPlacement === 'l') ? inputValue + settings.currencySymbol + settings.suffixText : settings.currencySymbol + inputValue + settings.suffixText;\n }\n\n return inputValue;\n }\n\n return null;\n }\n\n /**\n * Modify the input value by adding the group separators, as defined in the settings.\n *\n * @param {string} inputValue\n * @param {object} settings\n * @returns {*}\n */\n function addGroupSeparators(inputValue, settings) {\n if (settings.strip) {\n inputValue = stripAllNonNumberCharacters(inputValue, settings, false);\n }\n\n //TODO This function `addGroupSeparators()` add group separators. Adding the negative sign as well is out of its scope. Move that to another function.\n if (settings.trailingNegative && !isNegative(inputValue)) {\n inputValue = '-' + inputValue;\n }\n\n const empty = checkEmpty(inputValue, settings, true);\n const isValueNegative = isNegative(inputValue);\n const isZero = isZeroOrHasNoValue(inputValue);\n if (isValueNegative) {\n inputValue = inputValue.replace('-', '');\n }\n\n if (!isNull(empty)) {\n return empty;\n }\n\n settings.digitalGroupSpacing = settings.digitalGroupSpacing.toString();\n let digitalGroup;\n switch (settings.digitalGroupSpacing) {\n case '2':\n digitalGroup = /(\\d)((\\d)(\\d{2}?)+)$/;\n break;\n case '2s':\n digitalGroup = /(\\d)((?:\\d{2}){0,2}\\d{3}(?:(?:\\d{2}){2}\\d{3})*?)$/;\n break;\n case '4':\n digitalGroup = /(\\d)((\\d{4}?)+)$/;\n break;\n default :\n digitalGroup = /(\\d)((\\d{3}?)+)$/;\n }\n\n // Splits the string at the decimal string\n let [integerPart, decimalPart] = inputValue.split(settings.decimalCharacter);\n if (settings.decimalCharacterAlternative && isUndefined(decimalPart)) {\n [integerPart, decimalPart] = inputValue.split(settings.decimalCharacterAlternative);\n }\n\n if (settings.digitGroupSeparator !== '') {\n // Re-inserts the thousand separator via a regular expression\n while (digitalGroup.test(integerPart)) {\n integerPart = integerPart.replace(digitalGroup, `$1${settings.digitGroupSeparator}$2`);\n }\n }\n\n if (settings.decimalPlacesOverride !== 0 && !isUndefined(decimalPart)) {\n if (decimalPart.length > settings.decimalPlacesOverride) {\n decimalPart = decimalPart.substring(0, settings.decimalPlacesOverride);\n }\n\n // Joins the whole number with the decimal value\n inputValue = integerPart + settings.decimalCharacter + decimalPart;\n } else {\n // Otherwise if it's an integer\n inputValue = integerPart;\n }\n\n settings.trailingNegative = false;\n\n if (settings.currencySymbolPlacement === 'p') {\n if (isValueNegative) {\n switch (settings.negativePositiveSignPlacement) {\n case 'l':\n inputValue = `${settings.negativeSignCharacter}${settings.currencySymbol}${inputValue}`;\n break;\n case 'r':\n inputValue = `${settings.currencySymbol}${settings.negativeSignCharacter}${inputValue}`;\n break;\n case 's':\n inputValue = `${settings.currencySymbol}${inputValue}${settings.negativeSignCharacter}`;\n settings.trailingNegative = true;\n break;\n default :\n //\n }\n } else if (settings.showPositiveSign && !isZero) {\n switch (settings.negativePositiveSignPlacement) {\n case 'l':\n inputValue = `${settings.positiveSignCharacter}${settings.currencySymbol}${inputValue}`;\n break;\n case 'r':\n inputValue = `${settings.currencySymbol}${settings.positiveSignCharacter}${inputValue}`;\n break;\n case 's':\n inputValue = `${settings.currencySymbol}${inputValue}${settings.positiveSignCharacter}`;\n break;\n default :\n //\n }\n } else {\n inputValue = settings.currencySymbol + inputValue;\n }\n }\n\n if (settings.currencySymbolPlacement === 's') {\n if (isValueNegative) {\n switch (settings.negativePositiveSignPlacement) {\n case 'r':\n inputValue = `${inputValue}${settings.currencySymbol}${settings.negativeSignCharacter}`;\n settings.trailingNegative = true;\n break;\n case 'l':\n inputValue = `${inputValue}${settings.negativeSignCharacter}${settings.currencySymbol}`;\n settings.trailingNegative = true;\n break;\n case 'p':\n inputValue = `${settings.negativeSignCharacter}${inputValue}${settings.currencySymbol}`;\n break;\n default :\n //\n }\n } else if (settings.showPositiveSign && !isZero) {\n switch (settings.negativePositiveSignPlacement) {\n case 'r':\n inputValue = `${inputValue}${settings.currencySymbol}${settings.positiveSignCharacter}`;\n break;\n case 'l':\n inputValue = `${inputValue}${settings.positiveSignCharacter}${settings.currencySymbol}`;\n break;\n case 'p':\n inputValue = `${settings.positiveSignCharacter}${inputValue}${settings.currencySymbol}`;\n break;\n default :\n //\n }\n } else {\n inputValue = inputValue + settings.currencySymbol;\n }\n }\n\n // Removes the negative sign and places brackets\n if (settings.negativeBracketsTypeOnBlur !== null && (settings.rawValue < 0 || isNegativeStrict(inputValue))) {\n inputValue = toggleNegativeBracket(inputValue, settings);\n }\n\n return inputValue + settings.suffixText;\n }\n\n /**\n * Truncate not needed zeros\n *\n * @param {string} roundedInputValue\n * @param {int} temporaryDecimalPlacesOverride\n * @returns {void|XML|string|*}\n */\n function truncateZeros(roundedInputValue, temporaryDecimalPlacesOverride) {\n let regex;\n switch (temporaryDecimalPlacesOverride) {\n case 0:\n // Prevents padding - removes trailing zeros until the first significant digit is encountered\n regex = /(\\.(?:\\d*[1-9])?)0*$/;\n break;\n case 1:\n // Allows padding when decimalPlacesOverride equals one - leaves one zero trailing the decimal character\n regex = /(\\.\\d(?:\\d*[1-9])?)0*$/;\n break;\n default :\n // Removes access zeros to the decimalPlacesOverride length when allowDecimalPadding is set to true\n regex = new RegExp(`(\\\\.\\\\d{${temporaryDecimalPlacesOverride}}(?:\\\\d*[1-9])?)0*`);\n }\n\n // If there are no decimal places, we don't need a decimal point at the end\n roundedInputValue = roundedInputValue.replace(regex, '$1');\n if (temporaryDecimalPlacesOverride === 0) {\n roundedInputValue = roundedInputValue.replace(/\\.$/, '');\n }\n\n return roundedInputValue;\n }\n\n /**\n * Round the input value using the rounding method defined in the settings.\n * This function accepts multiple rounding methods. See the documentation for more details about those.\n *\n * Note : This is handled as text since JavaScript math function can return inaccurate values.\n *\n * @param {string} inputValue\n * @param {object} settings\n * @returns {*}\n */\n function roundValue(inputValue, settings) {\n inputValue = (inputValue === '') ? '0' : inputValue.toString();\n if (settings.roundingMethod === 'N05' || settings.roundingMethod === 'CHF' || settings.roundingMethod === 'U05' || settings.roundingMethod === 'D05') {\n switch (settings.roundingMethod) {\n case 'N05':\n inputValue = (Math.round(inputValue * 20) / 20).toString();\n break;\n case 'U05':\n inputValue = (Math.ceil(inputValue * 20) / 20).toString();\n break;\n default :\n inputValue = (Math.floor(inputValue * 20) / 20).toString();\n }\n\n let result;\n if (!contains(inputValue, '.')) {\n result = inputValue + '.00';\n } else if (inputValue.length - inputValue.indexOf('.') < 3) {\n result = inputValue + '0';\n } else {\n result = inputValue;\n }\n return result;\n }\n\n let ivRounded = '';\n let i = 0;\n let nSign = '';\n let temporaryDecimalPlacesOverride;\n\n // sets the truncate zero method\n if (settings.allowDecimalPadding) {\n temporaryDecimalPlacesOverride = settings.decimalPlacesOverride;\n } else {\n temporaryDecimalPlacesOverride = 0;\n }\n\n // Checks if the inputValue (input Value) is a negative value\n if (isNegativeStrict(inputValue)) {\n nSign = '-';\n\n // Removes the negative sign that will be added back later if required\n inputValue = inputValue.replace('-', '');\n }\n\n // Append a zero if the first character is not a digit (then it is likely to be a dot)\n if (!inputValue.match(/^\\d/)) {\n inputValue = '0' + inputValue;\n }\n\n // Determines if the value is equal to zero. If it is, remove the negative sign\n if (Number(inputValue) === 0) {\n nSign = '';\n }\n\n // Trims leading zero's as needed\n if ((Number(inputValue) > 0 && settings.leadingZero !== 'keep') || (inputValue.length > 0 && settings.leadingZero === 'allow')) {\n inputValue = inputValue.replace(/^0*(\\d)/, '$1');\n }\n\n const dPos = inputValue.lastIndexOf('.');\n const inputValueHasADot = dPos === -1;\n\n // Virtual decimal position\n const vdPos = inputValueHasADot ? inputValue.length - 1 : dPos;\n\n // Checks decimal places to determine if rounding is required :\n // Check if no rounding is required\n let cDec = (inputValue.length - 1) - vdPos;\n\n if (cDec <= settings.decimalPlacesOverride) {\n // Check if we need to pad with zeros\n ivRounded = inputValue;\n if (cDec < temporaryDecimalPlacesOverride) {\n if (inputValueHasADot) {\n ivRounded += settings.decimalCharacter;\n }\n\n let zeros = '000000';\n while (cDec < temporaryDecimalPlacesOverride) {\n zeros = zeros.substring(0, temporaryDecimalPlacesOverride - cDec);\n ivRounded += zeros;\n cDec += zeros.length;\n }\n } else if (cDec > temporaryDecimalPlacesOverride) {\n ivRounded = truncateZeros(ivRounded, temporaryDecimalPlacesOverride);\n } else if (cDec === 0 && temporaryDecimalPlacesOverride === 0) {\n ivRounded = ivRounded.replace(/\\.$/, '');\n }\n\n return (Number(ivRounded) === 0) ? ivRounded : nSign + ivRounded;\n }\n\n // Rounded length of the string after rounding\n let rLength;\n if (inputValueHasADot) {\n rLength = settings.decimalPlacesOverride - 1;\n } else {\n rLength = settings.decimalPlacesOverride + dPos;\n }\n\n const tRound = Number(inputValue.charAt(rLength + 1));\n const odd = (inputValue.charAt(rLength) === '.') ? (inputValue.charAt(rLength - 1) % 2) : (inputValue.charAt(rLength) % 2);\n let ivArray = inputValue.substring(0, rLength + 1).split('');\n\n if ((tRound > 4 && settings.roundingMethod === 'S') || // Round half up symmetric\n (tRound > 4 && settings.roundingMethod === 'A' && nSign === '') || // Round half up asymmetric positive values\n (tRound > 5 && settings.roundingMethod === 'A' && nSign === '-') || // Round half up asymmetric negative values\n (tRound > 5 && settings.roundingMethod === 's') || // Round half down symmetric\n (tRound > 5 && settings.roundingMethod === 'a' && nSign === '') || // Round half down asymmetric positive values\n (tRound > 4 && settings.roundingMethod === 'a' && nSign === '-') || // Round half down asymmetric negative values\n (tRound > 5 && settings.roundingMethod === 'B') || // Round half even \"Banker's Rounding\"\n (tRound === 5 && settings.roundingMethod === 'B' && odd === 1) || // Round half even \"Banker's Rounding\"\n (tRound > 0 && settings.roundingMethod === 'C' && nSign === '') || // Round to ceiling toward positive infinite\n (tRound > 0 && settings.roundingMethod === 'F' && nSign === '-') || // Round to floor toward negative infinite\n (tRound > 0 && settings.roundingMethod === 'U')) { // Round up away from zero\n // Round up the last digit if required, and continue until no more 9's are found\n for (i = (ivArray.length - 1); i >= 0; i -= 1) {\n if (ivArray[i] !== '.') {\n ivArray[i] = +ivArray[i] + 1;\n if (ivArray[i] < 10) {\n break;\n }\n\n if (i > 0) {\n ivArray[i] = '0';\n }\n }\n }\n }\n\n // Reconstruct the string, converting any 10's to 0's\n ivArray = ivArray.slice(0, rLength + 1);\n\n // Return the rounded value\n ivRounded = truncateZeros(ivArray.join(''), temporaryDecimalPlacesOverride);\n\n return (Number(ivRounded) === 0) ? ivRounded : nSign + ivRounded;\n }\n\n /**\n * Truncates the decimal part of a number.\n *\n * @param {string} s\n * @param {object} settings\n * @param {boolean} isPaste\n * @returns {*}\n */\n function truncateDecimal(s, settings, isPaste) {\n s = (isPaste) ? roundValue(s, settings) : s;\n\n if (settings.decimalCharacter && settings.decimalPlacesOverride) {\n const [integerPart, decimalPart] = s.split(settings.decimalCharacter);\n\n // truncate decimal part to satisfying length since we would round it anyway\n if (decimalPart && decimalPart.length > settings.decimalPlacesOverride) {\n if (settings.decimalPlacesOverride > 0) {\n const modifiedDecimalPart = decimalPart.substring(0, settings.decimalPlacesOverride);\n s = `${integerPart}${settings.decimalCharacter}${modifiedDecimalPart}`;\n } else {\n s = integerPart;\n }\n }\n }\n\n return s;\n }\n\n /**\n * Function to parse minimumValue, maximumValue & the input value to prepare for testing to determine if the value falls within the min / max range.\n * Return an object example: minimumValue: \"999999999999999.99\" returns the following \"{s: -1, e: 12, c: Array[15]}\".\n *\n * This function is adapted from Big.js https://github.com/MikeMcl/big.js/. Many thanks to Mike.\n *\n * @param {number|string} n A numeric value.\n * @returns {{}}\n */\n function parseStr(n) {\n const x = {}; // A Big number instance.\n let e;\n let i;\n let nL;\n let j;\n\n // Minus zero?\n if (n === 0 && 1 / n < 0) {\n n = '-0';\n }\n\n // Determine sign. 1 positive, -1 negative\n n = n.toString();\n if (isNegativeStrict(n)) {\n n = n.slice(1);\n x.s = -1;\n } else {\n x.s = 1;\n }\n\n // Decimal point?\n e = n.indexOf('.');\n if (e > -1) {\n n = n.replace('.', '');\n }\n\n // length of string if no decimal character\n if (e < 0) {\n // Integer\n e = n.length;\n }\n\n // Determine leading zeros\n i = (n.search(/[1-9]/i) === -1) ? n.length : n.search(/[1-9]/i);\n nL = n.length;\n if (i === nL) {\n // Zero\n x.e = 0;\n x.c = [0];\n } else {\n // Determine trailing zeros\n for (j = nL - 1; n.charAt(j) === '0'; j -= 1) {\n nL -= 1;\n }\n nL -= 1;\n\n // Decimal location\n x.e = e - i - 1;\n x.c = [];\n\n // Convert string to array of digits without leading/trailing zeros\n for (e = 0; i <= nL; i += 1) {\n x.c[e] = +n.charAt(i);\n e += 1;\n }\n }\n\n return x;\n }\n\n /**\n * Function to test if the input value falls with the Min / Max settings.\n * This uses the parsed strings for the above parseStr function.\n *\n * This function is adapted from Big.js https://github.com/MikeMcl/big.js/. Many thanks to Mike.\n *\n * @param {object} y Big number instance\n * @param {object} x Big number instance\n * @returns {*}\n */\n function testMinMax(y, x) {\n const xc = x.c;\n const yc = y.c;\n let i = x.s;\n let j = y.s;\n let k = x.e;\n let l = y.e;\n\n // Either zero?\n if (!xc[0] || !yc[0]) {\n let result;\n if (!xc[0]) {\n result = !yc[0]?0:-j;\n } else {\n result = i;\n }\n return result;\n }\n\n // Signs differ?\n if (i !== j) {\n return i;\n }\n const xNeg = i < 0;\n\n // Compare exponents\n if (k !== l) {\n return (k > l ^ xNeg)?1:-1;\n }\n i = -1;\n k = xc.length;\n l = yc.length;\n j = (k < l) ? k : l;\n\n // Compare digit by digit\n for (i += 1; i < j; i += 1) {\n if (xc[i] !== yc[i]) {\n return (xc[i] > yc[i] ^ xNeg)?1:-1;\n }\n }\n\n // Compare lengths\n let result;\n if (k === l) {\n result = 0;\n } else {\n result = (k > l ^ xNeg)?1:-1;\n }\n\n return result;\n }\n\n /**\n * Check that the number satisfy the format conditions\n * and lays between settings.minimumValue and settings.maximumValue\n * and the string length does not exceed the digits in settings.minimumValue and settings.maximumValue\n *\n * @param {string} s\n * @param {object} settings\n * @returns {*}\n */\n function checkIfInRangeWithOverrideOption(s, settings) {\n s = s.toString();\n s = s.replace(',', '.');\n const minParse = parseStr(settings.minimumValue);\n const maxParse = parseStr(settings.maximumValue);\n const valParse = parseStr(s);\n\n let result;\n switch (settings.overrideMinMaxLimits) {\n case 'floor':\n result = [testMinMax(minParse, valParse) > -1, true];\n break;\n case 'ceiling':\n result = [true, testMinMax(maxParse, valParse) < 1];\n break;\n case 'ignore':\n result = [true, true];\n break;\n default:\n result = [testMinMax(minParse, valParse) > -1, testMinMax(maxParse, valParse) < 1];\n }\n\n return result;\n }\n\n /**\n * Thanks to Anthony & Evan C\n *\n * @param {Element|string} element\n * @returns {*|jQuery|HTMLElement}\n */\n function getCurrentElement(element) {\n /*\n * If the parameter is a string (and therefore is a CSS selector), then we need to modify this string in order\n * for jQuery to be able to parse the selector correctly.\n * cf. http://learn.jquery.com/using-jquery-core/faq/how-do-i-select-an-element-by-an-id-that-has-characters-used-in-css-notation/\n */\n if (isString(element)) {\n //TODO This block is apparently never entered. We should remove it after making sure that's 100% the case\n element = `#${element.replace(/(:|\\.|\\[|]|,|=)/g, '\\\\$1')}`;\n }\n\n return $(element);\n }\n\n /**\n * Function that attach the autoNumeric field properties to the DOM element via an AutoNumericHolder object.\n *\n * @param {object} $this jQuery-selected DOM element\n * @param {object} settings\n * @param {boolean} update\n * @returns {*}\n */\n function getAutoNumericHolder($this, settings, update = false) {\n let data = $this.data('autoNumeric');\n if (!data) {\n data = {};\n $this.data('autoNumeric', data);\n }\n\n let holder = data.holder;\n if (update || (isUndefined(holder) && settings)) {\n holder = new AutoNumericHolder($this.get(0), settings);\n data.holder = holder;\n }\n\n return holder;\n }\n\n /**\n * Original settings saved for use when decimalPlacesShownOnFocus & noSeparatorOnFocus options are being used.\n * Those original settings are used exclusively in the `focusin` and `focusout` event handlers.\n *\n * @param {object} settings\n */\n function keepAnOriginalSettingsCopy(settings) {\n //TODO Rename the old option names to the new ones\n settings.oDec = settings.decimalPlacesOverride;\n settings.oPad = settings.allowDecimalPadding;\n settings.oBracket = settings.negativeBracketsTypeOnBlur;\n settings.oSep = settings.digitGroupSeparator;\n settings.oSign = settings.currencySymbol;\n settings.oSuffix = settings.suffixText;\n }\n\n /**\n * Original settings saved for use when `decimalPlacesShownOnFocus` & `noSeparatorOnFocus` options are being used.\n * This is taken from Quirksmode.\n *\n * @param {string} name\n * @returns {*}\n */\n function readCookie(name) {\n const nameEQ = name + '=';\n const ca = document.cookie.split(';');\n let c = '';\n for (let i = 0; i < ca.length; i += 1) {\n c = ca[i];\n while (c.charAt(0) === ' ') {\n c = c.substring(1, c.length);\n }\n if (c.indexOf(nameEQ) === 0) {\n return c.substring(nameEQ.length, c.length);\n }\n }\n\n return null;\n }\n\n /**\n * Test if sessionStorage is supported.\n * This is taken from Modernizr.\n *\n * @returns {boolean}\n */\n function storageTest() {\n const mod = 'modernizr';\n try {\n sessionStorage.setItem(mod, mod);\n sessionStorage.removeItem(mod);\n return true;\n } catch (e) {\n return false;\n }\n }\n\n /**\n * properly formats the string to a numeric when leadingZero does not 'keep'.\n *\n * @param {string} value\n * @param {object} settings\n * @returns {string}\n */\n function cleanLeadingTrailingZeros(value, settings) {\n // Return the empty string is the value is already empty. This prevent converting that value to '0'.\n if (value === '') {\n return '';\n }\n\n // Return '0' if the value is zero\n if (Number(value) === 0 && settings.leadingZero !== 'keep') {\n return '0';\n }\n\n if (settings.leadingZero !== 'keep') {\n // Trim leading zero's - leaves one zero to the left of the decimal point\n value = value.replace(/^(-)?0+(?=\\d)/g,'$1');\n\n //TODO remove this from that function and use `trimPaddedZerosFromDecimalPlaces()` instead. Also create a new `trailingZero` option.\n if (contains(value, '.')) {\n // Trims trailing zeros after the decimal point\n value = value.replace(/(\\.[0-9]*?)0+$/, '$1');\n }\n }\n // Strips trailing decimal point\n value = value.replace(/\\.$/, '');\n\n return value;\n }\n\n /**\n * Remove the trailing zeros in the decimal part of a number.\n *\n * @param {string} numericString\n * @returns {*}\n */\n function trimPaddedZerosFromDecimalPlaces(numericString) {\n const [integerPart, decimalPart] = numericString.split('.');\n if (isUndefinedOrNullOrEmpty(decimalPart)) {\n return integerPart;\n }\n\n const trimmedDecimalPart = decimalPart.replace(/0+$/g, '');\n\n let result;\n if (trimmedDecimalPart === '') {\n result = integerPart;\n } else {\n result = `${integerPart}.${trimmedDecimalPart}`;\n }\n\n return result;\n }\n\n /**\n * Creates or removes sessionStorage or cookie depending on what the browser is supporting.\n *\n * @param {Element|EventTarget} element\n * @param {object} settings\n * @param {string} action\n * @returns {*}\n */\n function saveValueToPersistentStorage(element, settings, action) {\n if (settings.saveValueToSessionStorage) {\n const storedName = (element.name !== '' && !isUndefined(element.name)) ?`AUTO_${decodeURIComponent(element.name)}` :`AUTO_${element.id}`;\n let date;\n let expires;\n\n // Sets cookie for browser that do not support sessionStorage IE 6 & IE 7\n if (storageTest() === false) {\n switch (action) {\n case 'set':\n document.cookie = `${storedName}=${settings.rawValue}; expires= ; path=/`;\n break;\n case 'wipe':\n date = new Date();\n date.setTime(date.getTime() + (-1 * 24 * 60 * 60 * 1000));\n expires = '; expires=' + date.toUTCString(); // Note : `toGMTString()` has been deprecated (cf. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toGMTString)\n document.cookie = `${storedName}='' ;${expires}; path=/`;\n break;\n case 'get':\n return readCookie(storedName);\n }\n } else {\n switch (action) {\n case 'set':\n sessionStorage.setItem(storedName, settings.rawValue);\n break;\n case 'wipe':\n sessionStorage.removeItem(storedName);\n break;\n case 'get':\n return sessionStorage.getItem(storedName);\n }\n }\n }\n }\n\n /**\n * Holder object for field properties\n */\n class AutoNumericHolder {\n /**\n * Class constructor\n *\n * @param {HTMLElement} that - A reference to the current DOM element\n * @param {object} settings\n */\n constructor(that, settings) {\n this.settings = settings;\n this.that = that;\n this.$that = $(that);\n this.formatted = false;\n this.settingsClone = settings;\n this.value = that.value;\n }\n\n /**\n * Update the value and the selection values inside the AutoNumericHolder object.\n * This keeps tracks of the input value, as well as the current selection.\n * This also resets the 'processed' and 'formatted' state.\n *\n * Note : Those two can change between the keydown, keypress and keyup events, that's why\n * this function is called on each event handler.\n *\n * @private\n */\n _updateAutoNumericHolderProperties() {\n this.value = this.that.value;\n this.selection = getElementSelection(this.that);\n this.processed = false;\n this.formatted = false;\n }\n\n /**\n * Update the keycode of the key that triggered the given event.\n * Note : e.which is sometimes different than e.keyCode during the keypress event, when entering a printable character key (ie. 't'). `e.which` equals 0 for non-printable characters.\n *\n * //TODO Switch to the non-deprecated e.key attribute, instead of inconsistant e.which and e.keyCode.\n * e.key describe the key name used to trigger the event.\n * e.keyCode being deprecated : https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode\n * How e.key works : https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key\n * The key list is described here\n * @link https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values\n *\n * @param {Event} e\n * @private\n */\n _updateAutoNumericHolderEventKeycode(e) {\n // Note: the keypress event overwrites meaningful value of e.keyCode, hence we do not update that value on 'keypress'\n this.eventKeyCode = keyCodeNumber(e);\n }\n\n /**\n * Set the text selection inside the input with the given start and end position.\n *\n * @param {int} start\n * @param {int} end\n * @param {undefined|boolean} setReal\n * @private\n */\n _setSelection(start, end, setReal) {\n //TODO Modify setReal to be more explicit (and a boolean)\n start = Math.max(start, 0);\n end = Math.min(end, this.that.value.length); //TODO Replace `this.that.value.length` with `this.value.length`\n this.selection = {\n start,\n end,\n length: end - start,\n };\n\n if (isUndefined(setReal) || setReal) {\n setElementSelection(this.that, start, end);\n }\n }\n\n /**\n * Set the caret position inside the input at the given position.\n *\n * @param {int} pos\n * @param {undefined|boolean} setReal\n * @private\n */\n _setCaretPosition(pos, setReal) {\n //TODO Modify setReal to be more explicit (and a boolean)\n this._setSelection(pos, pos, setReal);\n }\n\n /**\n * Return an array containing the string parts located on the left and right side of the caret or selection.\n * Those parts are left 'untouched', ie. formatted by autoNumeric.\n *\n * @returns {[string, string]} The parts on the left and right of the caret or selection\n * @private\n */\n _getLeftAndRightPartAroundTheSelection() {\n const value = this.value;\n const left = value.substring(0, this.selection.start);\n const right = value.substring(this.selection.end, value.length);\n\n return [left, right];\n }\n\n /**\n * Return an array containing the string parts located on the left and right side of the caret or selection.\n * Those parts are unformatted (stripped) of any non-numbers characters.\n *\n * @returns {[string, string]} The parts on the left and right of the caret or selection, unformatted.\n * @private\n */\n _getUnformattedLeftAndRightPartAroundTheSelection() {\n const settingsClone = this.settingsClone;\n let [left, right] = this._getLeftAndRightPartAroundTheSelection();\n if (left === '' && right === '') {\n settingsClone.trailingNegative = false;\n }\n // if changing the sign and left is equal to the number zero - prevents stripping the leading zeros\n let stripZeros = true;\n if (this.eventKeyCode === keyCode.Hyphen && Number(left) === 0) {\n stripZeros = false;\n }\n left = stripAllNonNumberCharacters(left, this.settingsClone, stripZeros);\n right = stripAllNonNumberCharacters(right, this.settingsClone, false);\n\n if (settingsClone.trailingNegative && !isNegative(left)) {\n left = '-' + left;\n right = (right === '-') ? '' : right;\n settingsClone.trailingNegative = false;\n }\n\n return [left, right];\n }\n\n /**\n * Strip parts from excess characters and leading zeros.\n *\n * @param {string} left\n * @param {string} right\n * @returns {[*,*]}\n * @private\n */\n _normalizeParts(left, right) {\n const settingsClone = this.settingsClone;\n\n // if changing the sign and left is equal to the number zero - prevents stripping the leading zeros\n let stripZeros = true;\n if (this.eventKeyCode === keyCode.Hyphen && Number(left) === 0) {\n stripZeros = false;\n }\n left = stripAllNonNumberCharacters(left, settingsClone, stripZeros);\n\n // If right is not empty and first character is not decimalCharacter\n right = stripAllNonNumberCharacters(right, settingsClone, false);\n\n // Prevents multiple leading zeros from being entered\n if (settingsClone.leadingZero === 'deny' &&\n (this.eventKeyCode === keyCode.num0 || this.eventKeyCode === keyCode.numpad0) &&\n Number(left) === 0 &&\n !contains(left, settingsClone.decimalCharacter) && right !== '') {\n left = left.substring(0, left.length - 1);\n }\n\n if (settingsClone.trailingNegative && !isNegative(left)) {\n left = '-' + left;\n settingsClone.trailingNegative = false;\n }\n\n // Insert zero if has leading dot\n this.newValue = left + right;\n if (settingsClone.decimalCharacter) {\n const m = this.newValue.match(new RegExp(`^${settingsClone.aNegRegAutoStrip}\\\\${settingsClone.decimalCharacter}`));\n if (m) {\n left = left.replace(m[1], m[1] + '0');\n this.newValue = left + right;\n }\n }\n\n return [left, right];\n }\n\n /**\n * Set part of number to value while keeping the cursor position. //TODO What about the cursor selection?\n *\n * @param {string} left\n * @param {string} right\n * @param {boolean} isPaste\n * @returns {boolean}\n * @private\n */\n _setValueParts(left, right, isPaste = false) {\n const settingsClone = this.settingsClone;\n const parts = this._normalizeParts(left, right);\n const [minTest, maxTest] = checkIfInRangeWithOverrideOption(this.newValue, settingsClone);\n let position = parts[0].length;\n this.newValue = parts.join('');\n\n if (minTest && maxTest) {\n this.newValue = truncateDecimal(this.newValue, settingsClone, isPaste);\n //TODO Check if we need to replace the hard-coded ',' with settings.decimalCharacter\n const testValue = (contains(this.newValue, ',')) ? this.newValue.replace(',', '.') : this.newValue;\n if (testValue === '' || testValue === settingsClone.negativeSignCharacter) {\n settingsClone.rawValue = (settingsClone.emptyInputBehavior === 'zero') ? '0' : '';\n } else {\n settingsClone.rawValue = cleanLeadingTrailingZeros(testValue, settingsClone);\n }\n\n if (position > this.newValue.length) {\n position = this.newValue.length;\n }\n\n // Make sure when the user enter a '0' on the far left with a leading zero option set to 'deny', that the caret does not moves since the input is dropped (fix issue #283)\n if (position === 1 && parts[0] === '0' && settingsClone.leadingZero === 'deny') {\n // If the user enter `0`, then the caret is put on the right side of it (Fix issue #299)\n if (parts[1] === '' || parts[0] === '0' && parts[1] !== '') {\n position = 1;\n } else {\n position = 0;\n }\n }\n\n this.value = this.newValue;\n this._setCaretPosition(position, false);\n\n return true;\n }\n\n if (!minTest) {\n this.$that.trigger('autoNumeric:minExceeded');\n } else if (!maxTest) {\n this.$that.trigger('autoNumeric:maxExceeded');\n }\n\n return false;\n }\n\n /**\n * Helper function for `_expandSelectionOnSign()`.\n *\n * @returns {*} Sign position of a formatted value\n * @private\n */\n _getSignPosition() {\n const settingsClone = this.settingsClone;\n const currencySymbol = settingsClone.currencySymbol;\n const that = this.that;\n\n if (currencySymbol) {\n const currencySymbolLen = currencySymbol.length;\n if (settingsClone.currencySymbolPlacement === 'p') {\n const hasNeg = settingsClone.negativeSignCharacter && that.value && that.value.charAt(0) === settingsClone.negativeSignCharacter;\n return hasNeg ? [1, currencySymbolLen + 1] : [0, currencySymbolLen];\n }\n const valueLen = that.value.length;\n return [valueLen - currencySymbolLen, valueLen];\n }\n\n return [1000, -1];\n }\n\n /**\n * Expands selection to cover whole sign\n * Prevents partial deletion/copying/overwriting of a sign\n *\n * @param {undefined|boolean} setReal\n * @private\n */\n _expandSelectionOnSign(setReal) {\n //TODO Modify setReal to be more explicit (and a boolean only)\n //TODO Use array destructuring here to set signPosition to more explicit variables\n const signPosition = this._getSignPosition();\n const selection = this.selection;\n\n // If selection catches something except sign and catches only space from sign\n if (selection.start < signPosition[1] && selection.end > signPosition[0]) {\n // Then select without empty space\n if ((selection.start < signPosition[0] || selection.end > signPosition[1]) && this.value.substring(Math.max(selection.start, signPosition[0]), Math.min(selection.end, signPosition[1])).match(/^\\s*$/)) {\n if (selection.start < signPosition[0]) {\n this._setSelection(selection.start, signPosition[0], setReal);\n } else {\n this._setSelection(signPosition[1], selection.end, setReal);\n }\n } else {\n // Else select with whole sign\n this._setSelection(Math.min(selection.start, signPosition[0]), Math.max(selection.end, signPosition[1]), setReal);\n }\n }\n }\n\n /**\n * Try to strip pasted value to digits\n */\n _checkPaste() {\n if (!isUndefined(this.valuePartsBeforePaste)) {\n const oldParts = this.valuePartsBeforePaste;\n const [left, right] = this._getLeftAndRightPartAroundTheSelection();\n\n // Try to strip the pasted value first\n delete this.valuePartsBeforePaste;\n\n const modifiedLeftPart = left.substr(0, oldParts[0].length) + stripAllNonNumberCharacters(left.substr(oldParts[0].length), this.settingsClone, true);\n if (!this._setValueParts(modifiedLeftPart, right, true)) {\n this.value = oldParts.join('');\n this._setCaretPosition(oldParts[0].length, false);\n }\n }\n }\n\n /**\n * Process pasting, cursor moving and skipping of not interesting keys.\n * If this function returns TRUE, then further processing is not performed.\n *\n * @param {Event} e\n * @returns {boolean}\n * @private\n */\n _skipAlways(e) {\n // Catch the ctrl up on ctrl-v\n if (((e.ctrlKey || e.metaKey) && e.type === 'keyup' && !isUndefined(this.valuePartsBeforePaste)) || (e.shiftKey && this.eventKeyCode === keyCode.Insert)) {\n //TODO Move this test inside the `onKeyup` handler\n this._checkPaste();\n return false;\n }\n\n // Skip all function keys (F1-F12), Windows keys, tab and other special keys\n if ((this.eventKeyCode >= keyCode.F1 && this.eventKeyCode <= keyCode.F12) ||\n (this.eventKeyCode >= keyCode.Windows && this.eventKeyCode <= keyCode.RightClick) ||\n (this.eventKeyCode >= keyCode.Tab && this.eventKeyCode < keyCode.Space) ||\n // `e.which` is sometimes different than `this.eventKeyCode` during the keypress event when entering a printable character key (ie. 't'). Also, `e.which` equals 0 for non-printable characters.\n (this.eventKeyCode < keyCode.Backspace &&\n (e.which === 0 || e.which === this.eventKeyCode)) ||\n this.eventKeyCode === keyCode.NumLock ||\n this.eventKeyCode === keyCode.ScrollLock ||\n this.eventKeyCode === keyCode.Insert ||\n this.eventKeyCode === keyCode.Command) {\n return true;\n }\n\n // If a \"Select all\" keyboard shortcut is detected (ctrl + a)\n if ((e.ctrlKey || e.metaKey) && this.eventKeyCode === keyCode.a) {\n if (this.settings.selectNumberOnly) {\n // `preventDefault()` is used here to prevent the browser to first select all the input text (including the currency sign), otherwise we would see that whole selection first in a flash, then the selection with only the number part without the currency sign.\n e.preventDefault();\n const valueLen = this.that.value.length;\n const currencySymbolLen = this.settings.currencySymbol.length;\n const negLen = (!isNegative(this.that.value))?0:1;\n const suffixTextLen = this.settings.suffixText.length;\n const currencySymbolPlacement = this.settings.currencySymbolPlacement;\n const negativePositiveSignPlacement = this.settings.negativePositiveSignPlacement;\n\n let start;\n if (currencySymbolPlacement === 's') {\n start = 0;\n } else {\n start = (negativePositiveSignPlacement === 'l' && negLen === 1 && currencySymbolLen > 0)?currencySymbolLen + 1:currencySymbolLen;\n }\n\n let end;\n if (currencySymbolPlacement === 'p') {\n end = valueLen - suffixTextLen;\n } else {\n switch (negativePositiveSignPlacement) {\n case 'l':\n end = valueLen - (suffixTextLen + currencySymbolLen);\n break;\n case 'r':\n end = (currencySymbolLen > 0)?valueLen - (currencySymbolLen + negLen + suffixTextLen):valueLen - (currencySymbolLen + suffixTextLen);\n break;\n default :\n end = valueLen - (currencySymbolLen + suffixTextLen);\n }\n }\n\n setElementSelection(this.that, start, end);\n }\n\n return true;\n }\n\n // If a \"Copy\", \"Paste\" or \"Cut\" keyboard shortcut is detected (respectively 'ctrl + c', 'ctrl + v' or 'ctrl + x')\n if ((e.ctrlKey || e.metaKey) && (this.eventKeyCode === keyCode.c || this.eventKeyCode === keyCode.v || this.eventKeyCode === keyCode.x)) {\n if (e.type === 'keydown') {\n this._expandSelectionOnSign();\n }\n\n // Try to prevent wrong paste\n if (this.eventKeyCode === keyCode.v || this.eventKeyCode === keyCode.Insert) {\n if (e.type === 'keydown' || e.type === 'keypress') {\n if (isUndefined(this.valuePartsBeforePaste)) {\n this.valuePartsBeforePaste = this._getLeftAndRightPartAroundTheSelection();\n }\n } else {\n this._checkPaste();\n }\n }\n\n return e.type === 'keydown' || e.type === 'keypress' || this.eventKeyCode === keyCode.c;\n }\n\n if (e.ctrlKey || e.metaKey) {\n return true;\n }\n\n // Jump over thousand separator\n //TODO Move this test inside the `onKeydown` handler\n if (this.eventKeyCode === keyCode.LeftArrow || this.eventKeyCode === keyCode.RightArrow) {\n if (e.type === 'keydown' && !e.shiftKey) {\n if (this.eventKeyCode === keyCode.LeftArrow &&\n (this.that.value.charAt(this.selection.start - 2) === this.settingsClone.digitGroupSeparator ||\n this.that.value.charAt(this.selection.start - 2) === this.settingsClone.decimalCharacter)) {\n this._setCaretPosition(this.selection.start - 1);\n } else if (this.eventKeyCode === keyCode.RightArrow &&\n (this.that.value.charAt(this.selection.start + 1) === this.settingsClone.digitGroupSeparator ||\n this.that.value.charAt(this.selection.start + 1) === this.settingsClone.decimalCharacter)) {\n this._setCaretPosition(this.selection.start + 1);\n }\n }\n return true;\n }\n\n return this.eventKeyCode >= keyCode.PageDown && this.eventKeyCode <= keyCode.DownArrow;\n }\n\n /**\n * Process deletion of characters when the minus sign is to the right of the numeric characters.\n *\n * @param {string} left The part on the left of the caret or selection\n * @param {string} right The part on the right of the caret or selection\n * @returns {[string, string]}\n * @private\n */\n _processCharacterDeletionIfTrailingNegativeSign([left, right]) {\n const settingsClone = this.settingsClone;\n if (settingsClone.currencySymbolPlacement === 'p' && settingsClone.negativePositiveSignPlacement === 's') {\n if (this.eventKeyCode === keyCode.Backspace) {\n settingsClone.caretFix = (this.selection.start >= this.value.indexOf(settingsClone.suffixText) && settingsClone.suffixText !== '');\n if (this.value.charAt(this.selection.start - 1) === '-') {\n left = left.substring(1);\n } else if (this.selection.start <= this.value.length - settingsClone.suffixText.length) {\n left = left.substring(0, left.length - 1);\n }\n } else {\n settingsClone.caretFix = (this.selection.start >= this.value.indexOf(settingsClone.suffixText) && settingsClone.suffixText !== '');\n if (this.selection.start >= this.value.indexOf(settingsClone.currencySymbol) + settingsClone.currencySymbol.length) {\n right = right.substring(1, right.length);\n }\n if (isNegative(left) && this.value.charAt(this.selection.start) === '-') {\n left = left.substring(1);\n }\n }\n }\n\n //TODO Merge the two following 'if' blocks into one `if (settingsClone.currencySymbolPlacement === 's') {` and a switch on settingsClone.negativePositiveSignPlacement\n if (settingsClone.currencySymbolPlacement === 's' && settingsClone.negativePositiveSignPlacement === 'l') {\n settingsClone.caretFix = (this.selection.start >= this.value.indexOf(settingsClone.negativeSignCharacter) + settingsClone.negativeSignCharacter.length);\n if (this.eventKeyCode === keyCode.Backspace) {\n if (this.selection.start === (this.value.indexOf(settingsClone.negativeSignCharacter) + settingsClone.negativeSignCharacter.length) && contains(this.value, settingsClone.negativeSignCharacter)) {\n left = left.substring(1);\n } else if (left !== '-' && ((this.selection.start <= this.value.indexOf(settingsClone.negativeSignCharacter)) || !contains(this.value, settingsClone.negativeSignCharacter))) {\n left = left.substring(0, left.length - 1);\n }\n } else {\n if (left[0] === '-') {\n right = right.substring(1);\n }\n if (this.selection.start === this.value.indexOf(settingsClone.negativeSignCharacter) && contains(this.value, settingsClone.negativeSignCharacter)) {\n left = left.substring(1);\n }\n }\n }\n\n if (settingsClone.currencySymbolPlacement === 's' && settingsClone.negativePositiveSignPlacement === 'r') {\n settingsClone.caretFix = (this.selection.start >= this.value.indexOf(settingsClone.negativeSignCharacter) + settingsClone.negativeSignCharacter.length);\n if (this.eventKeyCode === keyCode.Backspace) {\n if (this.selection.start === (this.value.indexOf(settingsClone.negativeSignCharacter) + settingsClone.negativeSignCharacter.length)) {\n left = left.substring(1);\n } else if (left !== '-' && this.selection.start <= (this.value.indexOf(settingsClone.negativeSignCharacter) - settingsClone.currencySymbol.length)) {\n left = left.substring(0, left.length - 1);\n } else if (left !== '' && !contains(this.value, settingsClone.negativeSignCharacter)) {\n left = left.substring(0, left.length - 1);\n }\n } else {\n settingsClone.caretFix = (this.selection.start >= this.value.indexOf(settingsClone.currencySymbol) && settingsClone.currencySymbol !== '');\n if (this.selection.start === this.value.indexOf(settingsClone.negativeSignCharacter)) {\n left = left.substring(1);\n }\n right = right.substring(1);\n }\n }\n\n return [left, right];\n }\n\n /**\n * Process the deletion of characters.\n */\n _processCharacterDeletion() {\n const settingsClone = this.settingsClone;\n\n let left;\n let right;\n\n if (!this.selection.length) {\n [left, right] = this._getUnformattedLeftAndRightPartAroundTheSelection();\n if (left === '' && right === '') {\n settingsClone.throwInput = false;\n }\n\n if (((settingsClone.currencySymbolPlacement === 'p' && settingsClone.negativePositiveSignPlacement === 's') ||\n (settingsClone.currencySymbolPlacement === 's' && (settingsClone.negativePositiveSignPlacement === 'l' || settingsClone.negativePositiveSignPlacement === 'r'))) &&\n isNegative(this.value)) { //TODO Change `this.value` to `this.that.value`?\n [left, right] = this._processCharacterDeletionIfTrailingNegativeSign([left, right]);\n } else {\n if (this.eventKeyCode === keyCode.Backspace) {\n left = left.substring(0, left.length - 1);\n } else {\n right = right.substring(1, right.length);\n }\n }\n } else {\n this._expandSelectionOnSign(false);\n [left, right] = this._getUnformattedLeftAndRightPartAroundTheSelection();\n }\n\n this._setValueParts(left, right);\n }\n\n /**\n * This function decides if the key pressed should be dropped or accepted, and modify the value 'on-the-fly' accordingly.\n * Returns TRUE if the keycode is allowed.\n * This functions also modify the value on-the-fly. //FIXME This should use another function in order to separate the test and the modification\n *\n * @param {Event|string} eventOrChar The event object, or the character entered (from an android device)\n * @returns {boolean}\n */\n _processCharacterInsertion(eventOrChar) {\n const settingsClone = this.settingsClone;\n let [left, right] = this._getUnformattedLeftAndRightPartAroundTheSelection();\n\n let eventCharacter;\n if (isString(eventOrChar)) {\n // Android browsers\n eventCharacter = eventOrChar;\n } else {\n // Normal browsers\n settingsClone.throwInput = true;\n\n // Retrieve the real character that has been entered (ie. 'a' instead of the key code)\n eventCharacter = character(eventOrChar);\n }\n\n // Start rules when the decimal character key is pressed always use numeric pad dot to insert decimal separator\n // Do not allow decimal character if no decimal part allowed\n if (eventCharacter === settingsClone.decimalCharacter ||\n (settingsClone.decimalCharacterAlternative && eventCharacter === settingsClone.decimalCharacterAlternative) ||\n ((eventCharacter === '.' || eventCharacter === ',') && this.eventKeyCode === keyCode.DotNumpad)) {\n if (!settingsClone.decimalPlacesOverride || !settingsClone.decimalCharacter) {\n return true;\n }\n\n // Do not allow decimal character before negativeSignCharacter character\n if (settingsClone.negativeSignCharacter && contains(right, settingsClone.negativeSignCharacter)) {\n return true;\n }\n\n // Do not allow decimal character if other decimal character present\n if (contains(left, settingsClone.decimalCharacter)) {\n return true;\n }\n\n if (right.indexOf(settingsClone.decimalCharacter) > 0) {\n return true;\n }\n\n if (right.indexOf(settingsClone.decimalCharacter) === 0) {\n right = right.substr(1);\n }\n\n this._setValueParts(left + settingsClone.decimalCharacter, right);\n\n return true;\n }\n\n // Prevent minus if not allowed\n if ((eventCharacter === '-' || eventCharacter === '+') && settingsClone.negativeSignCharacter === '-') {\n if (!settingsClone) {\n return true;\n }\n\n // Caret is always after minus\n if ((settingsClone.currencySymbolPlacement === 'p' && settingsClone.negativePositiveSignPlacement === 's') || (settingsClone.currencySymbolPlacement === 's' && settingsClone.negativePositiveSignPlacement !== 'p')) {\n if (left === '' && contains(right, settingsClone.negativeSignCharacter)) {\n left = settingsClone.negativeSignCharacter;\n right = right.substring(1, right.length);\n }\n\n // Change number sign, remove part if should\n if (isNegativeStrict(left) || contains(left, settingsClone.negativeSignCharacter)) {\n left = left.substring(1, left.length);\n } else {\n left = (eventCharacter === '-') ? settingsClone.negativeSignCharacter + left : left;\n }\n } else {\n if (left === '' && contains(right, settingsClone.negativeSignCharacter)) {\n left = settingsClone.negativeSignCharacter;\n right = right.substring(1, right.length);\n }\n\n // Change number sign, remove part if should\n if (left.charAt(0) === settingsClone.negativeSignCharacter) {\n left = left.substring(1, left.length);\n } else {\n left = (eventCharacter === '-') ? settingsClone.negativeSignCharacter + left : left;\n }\n }\n\n this._setValueParts(left, right);\n\n return true;\n }\n\n // If the user tries to insert digit before minus sign\n const eventNumber = Number(eventCharacter);\n if (eventNumber >= 0 && eventNumber <= 9) {\n if (settingsClone.negativeSignCharacter && left === '' && contains(right, settingsClone.negativeSignCharacter)) {\n left = settingsClone.negativeSignCharacter;\n right = right.substring(1, right.length);\n }\n\n if (settingsClone.maximumValue <= 0 && settingsClone.minimumValue < settingsClone.maximumValue && !contains(this.value, settingsClone.negativeSignCharacter) && eventCharacter !== '0') {\n left = settingsClone.negativeSignCharacter + left;\n }\n\n this._setValueParts(left + eventCharacter, right);\n\n return true;\n }\n\n // Prevent any other character\n settingsClone.throwInput = false;\n\n return false;\n }\n\n /**\n * Formatting of just processed value while keeping the cursor position\n *\n * @param {Event} e\n * @private\n */\n _formatValue(e) {\n const settingsClone = this.settingsClone;\n const leftLength = this.value;\n let [left] = this._getUnformattedLeftAndRightPartAroundTheSelection();\n\n // No grouping separator and no currency sign\n if ((settingsClone.digitGroupSeparator === '' || (settingsClone.digitGroupSeparator !== '' && !contains(leftLength, settingsClone.digitGroupSeparator))) &&\n (settingsClone.currencySymbol === '' || (settingsClone.currencySymbol !== '' && !contains(leftLength, settingsClone.currencySymbol)))) {\n let [subParts] = leftLength.split(settingsClone.decimalCharacter);\n let nSign = '';\n if (isNegative(subParts)) {\n nSign = '-';\n subParts = subParts.replace('-', '');\n left = left.replace('-', '');\n }\n\n // Strip leading zero on positive value if needed\n if (nSign === '' && subParts.length > settingsClone.mIntPos && left.charAt(0) === '0') {\n left = left.slice(1);\n }\n\n // Strip leading zero on negative value if needed\n if (nSign === '-' && subParts.length > settingsClone.mIntNeg && left.charAt(0) === '0') {\n left = left.slice(1);\n }\n\n left = nSign + left;\n }\n\n const value = addGroupSeparators(this.value, this.settingsClone);\n let position = value.length;\n if (value) {\n // Prepare regexp which searches for cursor position from unformatted left part\n const leftAr = left.split('');\n\n // Fixes caret position with trailing minus sign\n if ((settingsClone.negativePositiveSignPlacement === 's' || (settingsClone.currencySymbolPlacement === 's' && settingsClone.negativePositiveSignPlacement !== 'p')) &&\n leftAr[0] === '-' && settingsClone.negativeSignCharacter !== '') {\n leftAr.shift();\n\n if ((this.eventKeyCode === keyCode.Backspace || this.eventKeyCode === keyCode.Delete) &&\n settingsClone.caretFix) {\n if (settingsClone.currencySymbolPlacement === 's' && settingsClone.negativePositiveSignPlacement === 'l') {\n leftAr.push('-');\n settingsClone.caretFix = e.type === 'keydown';\n }\n\n if (settingsClone.currencySymbolPlacement === 'p' && settingsClone.negativePositiveSignPlacement === 's') {\n leftAr.push('-');\n settingsClone.caretFix = e.type === 'keydown';\n }\n\n if (settingsClone.currencySymbolPlacement === 's' && settingsClone.negativePositiveSignPlacement === 'r') {\n const signParts = settingsClone.currencySymbol.split('');\n const escapeChr = ['\\\\', '^', '$', '.', '|', '?', '*', '+', '(', ')', '['];\n const escapedParts = [];\n $.each(signParts, (i, miniParts) => {\n miniParts = signParts[i];\n if (isInArray(miniParts, escapeChr)) {\n escapedParts.push('\\\\' + miniParts);\n } else {\n escapedParts.push(miniParts);\n }\n });\n\n if (this.eventKeyCode === keyCode.Backspace) {\n escapedParts.push('-');\n }\n\n // Pushing the escaped sign\n leftAr.push(escapedParts.join(''));\n settingsClone.caretFix = e.type === 'keydown';\n }\n }\n }\n\n for (let i = 0; i < leftAr.length; i++) {\n if (!leftAr[i].match('\\\\d')) {\n leftAr[i] = '\\\\' + leftAr[i];\n }\n }\n\n const leftReg = new RegExp('^.*?' + leftAr.join('.*?'));\n\n // Search cursor position in formatted value\n const newLeft = value.match(leftReg);\n if (newLeft) {\n position = newLeft[0].length;\n\n // If the positive sign is shown, calculate the caret position accordingly\n if (settingsClone.showPositiveSign) {\n if (position === 0 && newLeft.input.charAt(0) === settingsClone.positiveSignCharacter) {\n position = (newLeft.input.indexOf(settingsClone.currencySymbol) === 1) ? settingsClone.currencySymbol.length + 1 : 1;\n }\n\n if (position === 0 && newLeft.input.charAt(settingsClone.currencySymbol.length) === settingsClone.positiveSignCharacter) {\n position = settingsClone.currencySymbol.length + 1;\n }\n }\n\n // If we are just before the sign which is in prefix position\n if (((position === 0 && value.charAt(0) !== settingsClone.negativeSignCharacter) || (position === 1 && value.charAt(0) === settingsClone.negativeSignCharacter)) && settingsClone.currencySymbol && settingsClone.currencySymbolPlacement === 'p') {\n // Place caret after prefix sign\n //TODO Should the test be 'isNegative' instead of 'isNegativeStrict' in order to search for '-' everywhere in the string?\n position = this.settingsClone.currencySymbol.length + (isNegativeStrict(value) ? 1 : 0);\n }\n } else {\n if (settingsClone.currencySymbol && settingsClone.currencySymbolPlacement === 's') {\n // If we could not find a place for cursor and have a sign as a suffix\n // Place caret before suffix currency sign\n position -= settingsClone.currencySymbol.length;\n }\n\n if (settingsClone.suffixText) {\n // If we could not find a place for cursor and have a suffix\n // Place caret before suffix\n position -= settingsClone.suffixText.length;\n }\n }\n }\n\n // Only update the value if it has changed. This prevents modifying the selection, if any.\n if (value !== this.that.value ||\n value === this.that.value && (this.eventKeyCode === keyCode.num0 || this.eventKeyCode === keyCode.numpad0)) {\n this.that.value = value;\n this._setCaretPosition(position);\n }\n\n if (settingsClone.androidSelectionStart !== null) {\n // If an Android browser is detected, fix the caret position\n // Unfortunately this does not fix all android browsers, only Android Chrome currently.\n // This is due to the fact those provide different order of events and/or keycodes thrown (this is a real mess :|).\n this._setCaretPosition(settingsClone.androidSelectionStart);\n }\n\n this.formatted = true; //TODO Rename `this.formatted` to `this._formatExecuted`, since it's possible this function does not need to format anything (in the case where the keycode is dropped for instance)\n }\n }\n\n /**\n * This function factorise the `getString()` and `getArray()` functions since they share quite a lot of code.\n *\n * The \"getString\" method uses jQuery's .serialize() method that creates a text string in standard URL-encoded notation.\n * The \"getArray\" method on the other hand uses jQuery's .serializeArray() method that creates array or objects that can be encoded as a JSON string.\n *\n * It then loops through the string and un-formats the inputs with autoNumeric.\n * By defaults values returned as ISO numeric string \"1234.56\" or \"-1234.56\" where the decimal character is a period\n * Locale formats are supported \"1234.56-\" or \"1234,56\" or \"-1234,56 or \"1234,56-\", or even plain numbers => please see option \"outputFormat\" for more details\n *\n * @param {boolean} getArrayBehavior - If set to TRUE, then this function behave like `getArray()`, otherwise if set to FALSE, it behave like `getString()`\n * @param {HTMLElement} that - A reference to the current DOM element\n * @returns {*}\n * @private\n */\n function _getStringOrArray(getArrayBehavior = true, that) {\n const $this = getCurrentElement(that);\n const formIndex = $('form').index($this);\n const allFormElements = $(`form:eq(${formIndex})`)[0];\n const aiIndex = [];\n\n // all input index\n const scIndex = [];\n\n // successful control index\n const rSubmitterTypes = /^(?:submit|button|image|reset|file)$/i;\n\n // from jQuery serialize method\n const rSubmittable = /^(?:input|select|textarea|keygen)/i;\n\n // from jQuery serialize method\n const rCheckableType = /^(?:checkbox|radio)$/i;\n const rNonAutoNumericTypes = /^(?:button|checkbox|color|date|datetime|datetime-local|email|file|image|month|number|password|radio|range|reset|search|submit|time|url|week)/i;\n\n let count = 0;\n\n // index of successful elements\n $.each(allFormElements, (i, field) => {\n if (field.name !== '' && rSubmittable.test(field.localName) && !rSubmitterTypes.test(field.type) && !field.disabled && (field.checked || !rCheckableType.test(field.type))) {\n scIndex.push(count);\n count++;\n } else {\n scIndex.push(-1);\n }\n });\n\n // index of all inputs tags except checkbox\n count = 0;\n $.each(allFormElements, (i, field) => {\n if (field.localName === 'input' && (field.type === '' || field.type === 'text' || field.type === 'hidden' || field.type === 'tel')) {\n aiIndex.push(count);\n count++;\n } else {\n aiIndex.push(-1);\n if (field.localName === 'input' && rNonAutoNumericTypes.test(field.type)) {\n count++;\n }\n }\n });\n\n if (getArrayBehavior) {\n const formFields = $this.serializeArray();\n\n $.each(formFields, (i, field) => {\n const scElement = scIndex.indexOf(i);\n\n if (scElement > -1 && aiIndex[scElement] > -1) {\n const testInput = $(`form:eq(${formIndex}) input:eq(${aiIndex[scElement]})`);\n const settings = testInput.data('autoNumeric');\n\n if (typeof settings === 'object') {\n field.value = testInput.autoNumeric('getLocalized').toString();\n }\n }\n });\n\n return formFields;\n }\n else {\n // getString() behavior\n const formFields = $this.serialize();\n const formParts = formFields.split('&');\n\n $.each(formParts, i => {\n const [inputName, inputValue] = formParts[i].split('=');\n const scElement = scIndex.indexOf(i);\n\n // If the current element is a valid element\n if (scElement > -1 && aiIndex[scElement] > -1) {\n const testInput = $(`form:eq(${formIndex}) input:eq(${aiIndex[scElement]})`);\n const settings = testInput.data('autoNumeric');\n\n if (typeof settings === 'object') {\n if (inputValue !== null) {\n const modifiedInputValue = testInput.autoNumeric('getLocalized').toString();\n formParts[i] = `${inputName}=${modifiedInputValue}`;\n }\n }\n }\n });\n\n return formParts.join('&');\n }\n }\n\n /**\n * Handler for 'focusin' events\n *\n * @param {object} $this jQuery-selected DOM element\n * @param {AutoNumericHolder} holder\n * @param {Event} e\n */\n function onFocusInAndMouseEnter($this, holder, e) {\n const settings = holder.settingsClone;\n\n if (e.type === 'focusin' || e.type === 'mouseenter' && !$this.is(':focus') && settings.emptyInputBehavior === 'focus') {\n settings.hasFocus = true;\n\n if (settings.negativeBracketsTypeOnBlur !== null && settings.negativeSignCharacter !== '') {\n $this.val(toggleNegativeBracket(e.target.value, settings));\n }\n\n // clean the value to compare to rawValue\n let result = stripAllNonNumberCharacters(e.target.value, settings, true);\n result = convertToNumericString(result, settings);\n result = cleanLeadingTrailingZeros(result, settings);\n if (settings.trailingNegative) {\n result = '-' + result;\n }\n\n let roundedValue;\n if (settings.decimalPlacesShownOnFocus) {\n settings.decimalPlacesOverride = settings.decimalPlacesShownOnFocus;\n roundedValue = roundValue(settings.rawValue, settings);\n $this.val(addGroupSeparators(roundedValue, settings));\n } else if (settings.scaleDivisor) {\n settings.decimalPlacesOverride = Number(settings.oDec);\n roundedValue = roundValue(settings.rawValue, settings);\n $this.val(addGroupSeparators(roundedValue, settings));\n } else if (settings.noSeparatorOnFocus) {\n settings.digitGroupSeparator = '';\n settings.currencySymbol = '';\n settings.suffixText = '';\n roundedValue = roundValue(settings.rawValue, settings);\n $this.val(addGroupSeparators(roundedValue, settings));\n } else if (result !== settings.rawValue) {\n // updates the rawValue\n $this.autoNumeric('set', result);\n }\n\n // In order to send a 'native' change event when blurring the input, we need to first store the initial input value on focus.\n holder.valueOnFocus = e.target.value;\n holder.lastVal = holder.valueOnFocus;\n const onEmpty = checkEmpty(holder.valueOnFocus, settings, true);\n if ((onEmpty !== null && onEmpty !== '') && settings.emptyInputBehavior === 'focus') {\n $this.val(onEmpty);\n if (onEmpty === settings.currencySymbol && settings.currencySymbolPlacement === 's') {\n setElementSelection(e.target, 0, 0);\n }\n }\n }\n }\n\n /**\n * Handler for 'keydown' events.\n * The user just started pushing any key, hence one event is sent.\n *\n * Note :\n * By default a 'normal' input output those events in the right order when inputting a character key (ie. 'a') :\n * - keydown\n * - keypress\n * - input\n * - keyup\n *\n * ...when inputting a modifier key (ie. 'ctrl') :\n * - keydown\n * - keyup\n *\n * If 'delete' or 'backspace' is entered, the following events are sent :\n * - keydown\n * - input\n * - keyup\n *\n * If 'enter' is entered and the value has not changed, the following events are sent :\n * - keydown\n * - keypress\n * - keyup\n *\n * If 'enter' is entered and the value has been changed, the following events are sent :\n * - keydown\n * - keypress\n * - change\n * - keyup\n *\n * When a paste is done, the following events are sent :\n * - input (if paste is done with the mouse)\n *\n * - keydown (if paste is done with ctrl+v)\n * - keydown\n * - input\n * - keyup\n * - keyup\n *\n * @param {AutoNumericHolder} holder\n * @param {Event} e\n */\n function onKeydown(holder, e) {\n //TODO Create a function that retrieve the element value (either by using `e.target.value` when the element is an , or by using `element.textContent` when the element as its `contenteditable` set to true)\n holder._updateAutoNumericHolderEventKeycode(e);\n holder.initialValueOnKeydown = e.target.value; // This is needed in `onKeyup()` to check if the value as changed during the key press\n\n if (holder.that.readOnly) {\n holder.processed = true;\n\n return;\n }\n\n // The \"enter\" key throws a `change` event if the value has changed since the `focus` event\n if (holder.eventKeyCode === keyCode.Enter && holder.valueOnFocus !== e.target.value) {\n triggerEvent('change', e.target);\n holder.valueOnFocus = e.target.value;\n }\n\n holder._updateAutoNumericHolderProperties(e);\n\n if (holder._skipAlways(e)) {\n holder.processed = true;\n\n return;\n }\n\n // Check if the key is a delete/backspace key\n if (holder.eventKeyCode === keyCode.Backspace || holder.eventKeyCode === keyCode.Delete) {\n holder._processCharacterDeletion(); // Because backspace and delete only triggers keydown and keyup events, not keypress\n holder.processed = true;\n holder._formatValue(e);\n\n // If and only if the resulting value has changed after that backspace/delete, then we have to send an 'input' event like browsers normally do.\n if ((e.target.value !== holder.lastVal) && holder.settingsClone.throwInput) {\n // Throw an input event when a character deletion is detected\n triggerEvent('input', e.target);\n e.preventDefault(); // ...and immediately prevent the browser to delete a second character\n }\n\n holder.lastVal = e.target.value;\n holder.settingsClone.throwInput = true;\n\n return;\n }\n\n holder.formatted = false; //TODO Is this line needed?\n }\n\n /**\n * Handler for 'keypress' events.\n * The user is still pressing the key, which will output a character (ie. '2') continuously until it releases the key.\n * Note: 'keypress' events are not sent for delete keys like Backspace/Delete.\n *\n * @param {AutoNumericHolder} holder\n * @param {Event} e\n */\n function onKeypress(holder, e) {\n // Retrieve the real character that has been entered (ie. 'a' instead of the key code)\n const eventCharacter = character(e);\n\n // Firefox generate a 'keypress' event (e.keyCode === 0) for the keys that do not print a character (ie. 'Insert', 'Delete', 'Fn' keys, 'PageUp', 'PageDown' etc.). 'Shift' on the other hand does not generate a keypress event.\n if (eventCharacter === keyName.Insert) {\n return;\n }\n\n const processed = holder.processed;\n holder._updateAutoNumericHolderProperties(e);\n\n if (holder._skipAlways(e)) {\n return;\n }\n\n if (processed) {\n e.preventDefault();\n\n return;\n }\n\n const isCharacterInsertionAllowed = holder._processCharacterInsertion(e);\n if (isCharacterInsertionAllowed) {\n holder._formatValue(e);\n if ((e.target.value !== holder.lastVal) && holder.settingsClone.throwInput) {\n // Throws input event on adding a character\n triggerEvent('input', e.target);\n e.preventDefault(); // ...and immediately prevent the browser to add a second character\n }\n else {\n if ((eventCharacter === holder.settings.decimalCharacter || eventCharacter === holder.settings.decimalCharacterAlternative) &&\n (getElementSelection(e.target).start === getElementSelection(e.target).end) &&\n getElementSelection(e.target).start === e.target.value.indexOf(holder.settings.decimalCharacter)) {\n const position = getElementSelection(e.target).start + 1;\n setElementSelection(e.target, position, position);\n }\n e.preventDefault();\n }\n\n holder.lastVal = e.target.value;\n holder.settingsClone.throwInput = true;\n\n return;\n }\n\n e.preventDefault();\n\n holder.formatted = false;\n }\n\n /**\n * Handler for 'input' events.\n * added to support android devices with mobile chrome browsers and others\n * Has the potential to replace the keypress event.\n *\n * @param {AutoNumericHolder} holder\n * @param {Event} e\n */\n function onInput(holder, e) {\n const value = e.target.value;\n\n // Fix the caret position on keyup in the `_formatValue()` function\n holder.settings.androidSelectionStart = null;\n\n if (holder.eventKeyCode === keyCode.AndroidDefault) {\n // The keyCode is equal to the default Android Chrome one (which is always equal to `keyCode.AndroidDefault`)\n if (value.length > holder.lastVal.length || value.length >= holder.lastVal.length - holder.selection.length) {\n // Determine the keycode of the character that was entered, and overwrite the faulty `eventKeyCode` info with it\n holder.eventKeyCode = value.charCodeAt(holder.selection.start);\n\n // Capture the actual character entered\n const androidCharEntered = value.charAt(holder.selection.start);\n\n // Check if the given character should be inserted, and if so, do insert it into the current element value\n const isCharacterInsertionAllowed = holder._processCharacterInsertion(androidCharEntered);\n\n if (isCharacterInsertionAllowed) {\n // Allowed character entered (number, decimal or plus/minus sign)\n holder._formatValue(e);\n\n // Capture the new caret position. This is required because on keyup, `_updateAutoNumericHolderEventKeycode()` captures the old caret position\n //TODO Check if this is an Android bug or an autoNumeric one\n holder.settings.androidSelectionStart = holder.selection.start;\n\n const decimalCharacterPosition = e.target.value.indexOf(holder.settings.decimalCharacter);\n const hasDecimalCharacter = decimalCharacterPosition === -1;\n\n // Move the caret to the right if the `androidCharEntered` is the decimal character or if it's on the left of the caret position\n if (androidCharEntered === holder.settings.decimalCharacter ||\n !hasDecimalCharacter && decimalCharacterPosition < holder.settings.androidSelectionStart) {\n holder.settings.androidSelectionStart = holder.selection.start + 1;\n }\n\n if (e.target.value.length > value.length) {\n // Position the caret right now before the 'keyup' event in order to prevent the caret from jumping around\n setElementSelection(e.target, holder.settings.androidSelectionStart, holder.settings.androidSelectionStart);\n }\n\n holder.lastVal = e.target.value;\n\n return;\n } else {\n // The entered character is not allowed ; overwrite the new invalid value with the previous valid one, and set back the caret/selection\n e.target.value = holder.lastVal;\n setElementSelection(e.target, holder.selection.start, holder.selection.end);\n holder.settings.androidSelectionStart = holder.selection.start;\n }\n\n e.preventDefault(); //FIXME How does that affects the normal trigger of the input event?\n\n holder.formatted = false;\n } else {\n // Character deleted\n //TODO What about the `Delete` key?\n holder.eventKeyCode = keyCode.Backspace;\n }\n }\n }\n\n /**\n * Handler for 'keyup' events.\n * The user just released any key, hence one event is sent.\n *\n * @param {AutoNumericHolder} holder\n * @param {object} settings\n * @param {Event} e\n */\n function onKeyup(holder, settings, e) {\n holder._updateAutoNumericHolderProperties(e);\n\n const skip = holder._skipAlways(e);\n delete holder.valuePartsBeforePaste;\n const isOnAndroid = holder.settingsClone.androidSelectionStart !== null;\n if (skip && !isOnAndroid || e.target.value === '') {\n return;\n }\n\n // Added to properly place the caret when only the currency sign is present\n if (e.target.value === holder.settingsClone.currencySymbol) {\n if (holder.settingsClone.currencySymbolPlacement === 's') {\n setElementSelection(e.target, 0, 0);\n } else {\n setElementSelection(e.target, holder.settingsClone.currencySymbol.length, holder.settingsClone.currencySymbol.length);\n }\n } else if (holder.eventKeyCode === keyCode.Tab) {\n setElementSelection(e.target, 0, e.target.value.length);\n }\n\n if ((e.target.value === holder.settingsClone.suffixText) ||\n (holder.settingsClone.rawValue === '' && holder.settingsClone.currencySymbol !== '' && holder.settingsClone.suffixText !== '')) {\n setElementSelection(e.target, 0, 0);\n }\n\n // Saves the extended decimal to preserve the data when navigating away from the page\n if (holder.settingsClone.decimalPlacesShownOnFocus !== null && holder.settingsClone.saveValueToSessionStorage) {\n saveValueToPersistentStorage(e.target, settings, 'set');\n }\n\n if (!holder.formatted) {\n holder._formatValue(e);\n }\n\n // If the input value has changed during the key press event chain, an event is sent to alert that a formatting has been done (cf. Issue #187)\n if (e.target.value !== holder.initialValueOnKeydown) {\n triggerEvent('autoNumeric:formatted', e.target);\n }\n }\n\n /**\n * Handler for 'focusout' events\n *\n * @param {object} $this jQuery-selected DOM element\n * @param {AutoNumericHolder} holder\n * @param {Event} e\n */\n function onFocusOutAndMouseLeave($this, holder, e) {\n if (!$this.is(':focus')) {\n let value = e.target.value;\n const origValue = value;\n const settings = holder.settingsClone;\n settings.hasFocus = false;\n\n if (settings.saveValueToSessionStorage) {\n saveValueToPersistentStorage(e.target, settings, 'set');\n }\n\n if (settings.noSeparatorOnFocus === true) {\n settings.digitGroupSeparator = settings.oSep;\n settings.currencySymbol = settings.oSign;\n settings.suffixText = settings.oSuffix;\n }\n\n if (settings.decimalPlacesShownOnFocus !== null) {\n settings.decimalPlacesOverride = settings.oDec;\n settings.allowDecimalPadding = settings.oPad;\n settings.negativeBracketsTypeOnBlur = settings.oBracket;\n }\n\n value = stripAllNonNumberCharacters(value, settings, true);\n\n if (value !== '') {\n if (settings.trailingNegative && !isNegative(value)) {\n value = '-' + value;\n settings.trailingNegative = false;\n }\n\n const [minTest, maxTest] = checkIfInRangeWithOverrideOption(value, settings);\n if (checkEmpty(value, settings, false) === null && minTest && maxTest) {\n value = modifyNegativeSignAndDecimalCharacterForRawValue(value, settings);\n settings.rawValue = cleanLeadingTrailingZeros(value, settings);\n\n if (settings.scaleDivisor) {\n value = value / settings.scaleDivisor;\n value = value.toString();\n }\n\n settings.decimalPlacesOverride = (settings.scaleDivisor && settings.scaleDecimalPlaces) ? Number(settings.scaleDecimalPlaces) : settings.decimalPlacesOverride;\n value = roundValue(value, settings);\n value = modifyNegativeSignAndDecimalCharacterForFormattedValue(value, settings);\n } else {\n if (!minTest) {\n $this.trigger('autoNumeric:minExceeded');\n }\n if (!maxTest) {\n $this.trigger('autoNumeric:maxExceeded');\n }\n\n value = settings.rawValue;\n }\n } else {\n if (settings.emptyInputBehavior === 'zero') {\n settings.rawValue = '0';\n value = roundValue('0', settings);\n } else {\n settings.rawValue = '';\n }\n }\n\n let groupedValue = checkEmpty(value, settings, false);\n if (groupedValue === null) {\n groupedValue = addGroupSeparators(value, settings);\n }\n\n if (groupedValue !== origValue) {\n groupedValue = (settings.scaleSymbol) ? groupedValue + settings.scaleSymbol : groupedValue;\n $this.val(groupedValue);\n }\n\n if (groupedValue !== holder.valueOnFocus) {\n $this.change();\n delete holder.valueOnFocus;\n }\n }\n }\n\n /**\n * Handler for 'paste' events\n *\n * @param {object} $this jQuery-selected DOM element\n * @param {AutoNumericHolder} holder\n * @param {Event} e\n */\n function onPaste($this, holder, e) {\n //TODO Using ctrl+z after a paste should cancel it -> How would that affect other frameworks/component built with that feature in mind though?\n //FIXME When pasting '000' on a thousand group selection, the whole selection gets deleted, and only one '0' is pasted (cf. issue #302)\n // The event is prevented by default, since otherwise the user would be able to paste invalid characters into the input\n e.preventDefault();\n\n let rawPastedText = e.clipboardData.getData('text/plain');\n\n // 0. Special case if the user has selected all the input text before pasting\n const initialFormattedValue = e.target.value;\n const selectionStart = e.target.selectionStart || 0;\n const selectionEnd = e.target.selectionEnd || 0;\n const selectionSize = selectionEnd - selectionStart;\n let isAllInputTextSelected = false;\n\n if (selectionSize === initialFormattedValue.length) {\n isAllInputTextSelected = true;\n }\n\n // 1. Check if the paste has a negative sign (only if it's the first character), and store that information for later use\n const isPasteNegative = isNegativeStrict(rawPastedText);\n if (isPasteNegative) {\n // 1a. Remove the negative sign from the pasted text\n rawPastedText = rawPastedText.slice(1, rawPastedText.length);\n }\n\n // 2. Strip all thousand separators, brackets and currency sign, and convert the decimal character to a dot\n const untranslatedPastedText = preparePastedText(rawPastedText, holder);\n\n let pastedText;\n if (untranslatedPastedText === '.') {\n // Special case : If the user tries to paste a single decimal character (that has been translated to '.' already)\n pastedText = '.';\n } else {\n // Normal case\n // Allow pasting arabic numbers\n pastedText = arabicToLatinNumbers(untranslatedPastedText, false, false, false);\n }\n\n // 3. Test if the paste is valid (only has numbers and eventually a decimal character). If it's not valid, stop here.\n if (pastedText !== '.' && (!isNumber(pastedText) || pastedText === '')) {\n if (holder.settings.onInvalidPaste === 'error') {\n //TODO Should we send a warning instead of throwing an error?\n throwError(`The pasted value '${rawPastedText}' is not a valid paste content.`);\n }\n\n return;\n }\n\n // 4. Calculate the paste result\n let caretPositionOnInitialTextAfterPasting;\n let initialUnformattedNumber;\n if (e.target.value === '') {\n // autoNumeric 'get' returns '0.00' if the input is empty, hence we need to store the 'real' empty initial value when needed\n //FIXME This has been fixed in a previous commit, get should return '' on an empty input. Remove this unneeded 'if'\n initialUnformattedNumber = '';\n } else {\n initialUnformattedNumber = $this.autoNumeric('get');\n }\n let isInitialValueNegative = isNegativeStrict(initialUnformattedNumber);\n let isPasteNegativeAndInitialValueIsPositive;\n let result;\n\n // If the pasted content is negative, then the result will be negative too\n if (isPasteNegative && !isInitialValueNegative) {\n initialUnformattedNumber = `-${initialUnformattedNumber}`;\n isInitialValueNegative = true;\n isPasteNegativeAndInitialValueIsPositive = true;\n }\n else {\n isPasteNegativeAndInitialValueIsPositive = false;\n }\n\n let leftPartContainedADot = false;\n let leftPart;\n let rightPart;\n switch (holder.settings.onInvalidPaste) {\n /* 4a. Truncate paste behavior:\n * Insert as many numbers as possible on the right hand side of the caret from the pasted text content, until the input reach its range limit.\n * If there is more characters in the clipboard once a limit is reached, drop the extraneous characters.\n * Otherwise paste all the numbers in the clipboard.\n * While doing so, we check if the result is within the minimum and maximum values allowed, and stop as soon as we encounter one of those.\n *\n * 4b. Replace paste behavior:\n * Idem than the 'truncate' paste behavior, except that when a range limit is hit, we try to replace the subsequent initial numbers with the pasted ones, until we hit the range limit a second (and last) time, or we run out of numbers to paste\n */\n /* eslint no-case-declarations: 0 */\n case 'truncate':\n case 'replace':\n const leftFormattedPart = initialFormattedValue.slice(0, selectionStart);\n const rightFormattedPart = initialFormattedValue.slice(selectionEnd, initialFormattedValue.length);\n\n if (selectionStart !== selectionEnd) {\n // a. If there is a selection, remove the selected part, and return the left and right part\n result = preparePastedText(leftFormattedPart + rightFormattedPart, holder);\n } else {\n // b. Else if this is only one caret (and therefore no selection), then return the left and right part\n result = preparePastedText(initialFormattedValue, holder);\n }\n\n // Add back the negative sign if needed\n if (isInitialValueNegative) {\n result = setRawNegativeSign(result);\n }\n\n // Build the unformatted result string\n caretPositionOnInitialTextAfterPasting = convertCharacterCountToIndexPosition(countNumberCharactersOnTheCaretLeftSide(initialFormattedValue, selectionStart, holder.settings.decimalCharacter));\n if (isPasteNegativeAndInitialValueIsPositive) {\n // If the initial paste is negative and the initial value is not, then I must offset the caret position by one place to the right to take the additional hyphen into account\n caretPositionOnInitialTextAfterPasting++;\n //TODO Quid if the negative sign is not on the left (negativePositiveSignPlacement and currencySymbolPlacement)?\n }\n\n leftPart = result.slice(0, caretPositionOnInitialTextAfterPasting);\n rightPart = result.slice(caretPositionOnInitialTextAfterPasting, result.length);\n if (pastedText === '.') {\n if (contains(leftPart, '.')) {\n // If I remove a dot here, then I need to update the caret position (decrement it by 1) when positioning it\n // To do so, we keep that info in order to modify the caret position later\n leftPartContainedADot = true;\n leftPart = leftPart.replace('.', '');\n }\n rightPart = rightPart.replace('.', '');\n }\n // -- Here, we are good to go to continue on the same basis\n\n // c. Add numbers one by one at the caret position, while testing if the result is valid and within the range of the minimum and maximum value\n // Continue until you either run out of numbers to paste, or that you get out of the range limits\n const minParse = parseStr(holder.settings.minimumValue);\n const maxParse = parseStr(holder.settings.maximumValue);\n let lastGoodKnownResult = result; // This is set as the default, in case we do not add even one number\n let pastedTextIndex = 0;\n let modifiedLeftPart = leftPart;\n\n while (pastedTextIndex < pastedText.length) {\n // Modify the result with another pasted character\n modifiedLeftPart += pastedText[pastedTextIndex];\n result = modifiedLeftPart + rightPart;\n\n // Check the range limits\n if (!checkIfInRange(result, minParse, maxParse)) {\n // The result is out of the range limits, stop the loop here\n break;\n }\n\n // Save the last good known result\n lastGoodKnownResult = result;\n\n // Update the local variables for the next loop\n pastedTextIndex++;\n }\n\n // Update the last caret position where to insert a new number\n caretPositionOnInitialTextAfterPasting += pastedTextIndex;\n\n //XXX Here we have the result for the `truncate` option\n if (holder.settings.onInvalidPaste === 'truncate') {\n //TODO If the user as defined a truncate callback and there are still some numbers (that will be dropped), then call this callback with the initial paste as well as the remaining numbers\n result = lastGoodKnownResult;\n\n if (leftPartContainedADot) {\n // If a dot has been removed for the part on the left of the caret, we decrement the caret index position\n caretPositionOnInitialTextAfterPasting--;\n }\n break;\n }\n //XXX ...else we need to continue modifying the result for the 'replace' option\n\n // d. Until there are numbers to paste, replace the initial numbers one by one, and still do the range test.\n // Stop when you have no more numbers to paste, or if you are out of the range limits.\n // If you do get to the range limits, use the previous known good value within those limits.\n // Note: The numbers are replaced one by one, in the integer then decimal part, while ignoring the decimal character\n //TODO What should happen if the user try to paste a decimal number? Should we override the current initial decimal character in favor of this new one? If we do, then we have to recalculate the vMin/vMax from the start in order to take into account this new decimal character position..\n let lastGoodKnownResultIndex = caretPositionOnInitialTextAfterPasting;\n const lastGoodKnownResultSize = lastGoodKnownResult.length;\n\n while (pastedTextIndex < pastedText.length && lastGoodKnownResultIndex < lastGoodKnownResultSize) {\n if (lastGoodKnownResult[lastGoodKnownResultIndex] === '.') {\n // We skip the decimal character 'replacement'. That way, we do not change the decimal character position regarding the remaining numbers.\n lastGoodKnownResultIndex++;\n continue;\n }\n\n // This replace one character at a time\n result = replaceCharAt(lastGoodKnownResult, lastGoodKnownResultIndex, pastedText[pastedTextIndex]);\n\n // Check the range limits\n if (!checkIfInRange(result, minParse, maxParse)) {\n // The result is out of the range limits, stop the loop here\n break;\n }\n\n // Save the last good known result\n lastGoodKnownResult = result;\n\n // Update the local variables for the next loop\n pastedTextIndex++;\n lastGoodKnownResultIndex++;\n }\n\n // Update the last caret position where to insert a new number\n caretPositionOnInitialTextAfterPasting = lastGoodKnownResultIndex;\n\n if (leftPartContainedADot) {\n // If a dot has been removed for the part on the left of the caret, we decrement the caret index position\n caretPositionOnInitialTextAfterPasting--;\n }\n\n result = lastGoodKnownResult;\n\n break;\n /* 4c. Normal paste behavior:\n * Insert the pasted number inside the current unformatted text, at the right caret position or selection\n */\n case 'error':\n case 'ignore':\n case 'clamp':\n default:\n // 1. Generate the unformatted result\n const leftFormattedPart2 = initialFormattedValue.slice(0, selectionStart);\n const rightFormattedPart2 = initialFormattedValue.slice(selectionEnd, initialFormattedValue.length);\n\n if (selectionStart !== selectionEnd) {\n // a. If there is a selection, remove the selected part, and return the left and right part\n result = preparePastedText(leftFormattedPart2 + rightFormattedPart2, holder);\n } else {\n // b. Else if this is only one caret (and therefore no selection), then return the left and right part\n result = preparePastedText(initialFormattedValue, holder);\n }\n\n // Add back the negative sign if needed\n if (isInitialValueNegative) {\n result = setRawNegativeSign(result);\n }\n\n // Build the unformatted result string\n caretPositionOnInitialTextAfterPasting = convertCharacterCountToIndexPosition(countNumberCharactersOnTheCaretLeftSide(initialFormattedValue, selectionStart, holder.settings.decimalCharacter));\n if (isPasteNegativeAndInitialValueIsPositive) {\n // If the initial paste is negative and the initial value is not, then I must offset the caret position by one place to the right to take the additional hyphen into account\n caretPositionOnInitialTextAfterPasting++;\n //TODO Quid if the negative sign is not on the left (negativePositiveSignPlacement and currencySymbolPlacement)?\n }\n\n leftPart = result.slice(0, caretPositionOnInitialTextAfterPasting);\n rightPart = result.slice(caretPositionOnInitialTextAfterPasting, result.length);\n if (pastedText === '.') {\n // If the user only paste a single decimal character, then we remove the previously existing one (if any)\n if (contains(leftPart, '.')) {\n // If I remove a dot here, then I need to update the caret position (decrement it by 1) when positioning it\n // To do so, we keep that info in order to modify the caret position later\n leftPartContainedADot = true;\n leftPart = leftPart.replace('.', '');\n }\n rightPart = rightPart.replace('.', '');\n }\n // -- Here, we are good to go to continue on the same basis\n\n // Generate the unformatted result\n result = `${leftPart}${pastedText}${rightPart}`;\n\n // 2. Calculate the caret position in the unformatted value, for later use\n if (selectionStart === selectionEnd) {\n // There is no selection, then the caret position is set after the pasted text\n const indexWherePastedTextHasBeenInserted = convertCharacterCountToIndexPosition(countNumberCharactersOnTheCaretLeftSide(initialFormattedValue, selectionStart, holder.settings.decimalCharacter));\n caretPositionOnInitialTextAfterPasting = indexWherePastedTextHasBeenInserted + pastedText.length; // I must not count the characters that have been removed from the pasted text (ie. '.')\n } else {\n if (isAllInputTextSelected) {\n // Special case when all the input text is selected before pasting, which means we'll completely erase its content and paste only the clipboard content\n caretPositionOnInitialTextAfterPasting = result.length;\n } else if (rightPart === '') {\n // If the user selected from the caret position to the end of the input (on the far right)\n caretPositionOnInitialTextAfterPasting = convertCharacterCountToIndexPosition(countNumberCharactersOnTheCaretLeftSide(initialFormattedValue, selectionStart, holder.settings.decimalCharacter)) + pastedText.length;\n } else {\n // Normal case\n const indexSelectionEndInRawValue = convertCharacterCountToIndexPosition(countNumberCharactersOnTheCaretLeftSide(initialFormattedValue, selectionEnd, holder.settings.decimalCharacter));\n\n // Here I must not count the characters that have been removed from the pasted text (ie. '.'), or the thousand separators in the initial selected text\n const selectedText = e.target.value.slice(selectionStart, selectionEnd);\n caretPositionOnInitialTextAfterPasting = indexSelectionEndInRawValue - selectionSize + countCharInText(holder.settings.digitGroupSeparator, selectedText) + pastedText.length;\n }\n }\n\n // Modify the caret position for special cases, only if the whole input has not been selected\n if (!isAllInputTextSelected) {\n if (isPasteNegativeAndInitialValueIsPositive) {\n // If the pasted value has a '-' sign, but the initial value does not, offset the index by one\n caretPositionOnInitialTextAfterPasting++;\n }\n\n if (leftPartContainedADot) {\n // If a dot has been removed for the part on the left of the caret, we decrement the caret index position\n caretPositionOnInitialTextAfterPasting--;\n }\n }\n }\n\n // 5. Check if the result is a valid number, if not, drop the paste and do nothing.\n if (!isNumber(result) || result === '') {\n if (holder.settings.onInvalidPaste === 'error') {\n throwError(`The pasted value '${rawPastedText}' would result into an invalid content '${result}'.`); //TODO Should we send a warning instead of throwing an error?\n //TODO This is not DRY ; refactor with above\n }\n return;\n }\n\n // 6. If it's a valid number, check if it falls inside the minimum and maximum value. If this fails, modify the value following this procedure :\n /*\n * If 'error' (this is the default) :\n * - Normal paste behavior.\n * - Try to set the new value, if it fails, then throw an error in the console.\n * - Do not change the input value, do not change the current selection.\n * If 'ignore' :\n * - Normal paste behavior.\n * - Try to set the new value, if it fails, do nothing more.\n * - Do not change the input value, do not change the current selection.\n * If 'clamp' :\n * - Normal paste behavior.\n * - Try to set the new value, if it fails, set the value to the minimum or maximum limit, whichever is closest to the\n * paste result.\n * - Change the caret position to be positioned on the left hand side of the decimal character.\n * If 'truncate' :\n * - Truncate paste behavior.\n * - Try to set the new value, until it fails (if the result is out of the min and max value limits).\n * - Drop the remaining non-pasted numbers, and keep the last known non-failing result.\n * - Change the caret position to be positioned after the last pasted character.\n * If 'replace' :\n * - Replace paste behavior.\n * - Try to set the new value, until it fails (if the result is out of the min and max value limits).\n * - Then try to replace as many numbers as possible with the pasted ones. Once it fails, keep the last known non-failing result.\n * - Change the caret position to be positioned after the last pasted character.\n */\n let valueHasBeenSet = false;\n let valueHasBeenClamped = false;\n try {\n $this.autoNumeric('set', result);\n valueHasBeenSet = true;\n }\n catch (error) {\n let clampedValue;\n switch (holder.settings.onInvalidPaste) {\n case 'clamp':\n clampedValue = clampToRangeLimits(result, holder.settings);\n try {\n $this.autoNumeric('set', clampedValue);\n }\n catch (error) {\n throwError(`Fatal error: Unable to set the clamped value '${clampedValue}'.`);\n }\n\n valueHasBeenClamped = true;\n valueHasBeenSet = true;\n result = clampedValue; // This is used only for setting the caret position later\n break;\n case 'error':\n case 'truncate':\n case 'replace':\n // Throw an error message\n throwError(`The pasted value '${rawPastedText}' results in a value '${result}' that is outside of the minimum [${holder.settings.minimumValue}] and maximum [${holder.settings.maximumValue}] value range.`);\n // falls through\n case 'ignore':\n // Do nothing\n // falls through\n default :\n return; // ...and nothing else should be changed\n }\n }\n\n // 7. Then lastly, set the caret position at the right logical place\n let caretPositionInFormattedNumber;\n if (valueHasBeenSet) {\n switch (holder.settings.onInvalidPaste) {\n case 'clamp':\n if (valueHasBeenClamped) {\n if (holder.settings.currencySymbolPlacement === 's') {\n setElementSelection(e.target, e.target.value.length - holder.settings.currencySymbol.length); // This puts the caret on the right of the last decimal place\n } else {\n setElementSelection(e.target, e.target.value.length); // ..and this on the far right\n }\n\n break;\n } // else if the value has not been clamped, the default behavior is used...\n // falls through\n case 'error':\n case 'ignore':\n case 'truncate':\n case 'replace':\n default :\n // Whenever one or multiple characters are pasted, this means we have to manage the potential thousand separators that could be added by the formatting\n caretPositionInFormattedNumber = findCaretPositionInFormattedNumber(result, caretPositionOnInitialTextAfterPasting, e.target.value, holder.settings.decimalCharacter);\n setElementSelection(e.target, caretPositionInFormattedNumber);\n }\n }\n\n // 8. We make sure we send an input event only if the result is different than the initial value before the paste\n if (valueHasBeenSet && initialFormattedValue !== e.target.value) {\n // On a 'normal' non-autoNumeric input, an `input` event is sent when a paste is done. We mimic that.\n triggerEvent('input', e.target);\n }\n }\n\n /**\n * When focusing out of the input, we check if the value has changed, and if it has, then we send a `change` event (since the native one would have been prevented by `e.preventDefault()` called in the other event listeners).\n *\n * @param {AutoNumericHolder} holder\n * @param {Event} e\n */\n function onBlur(holder, e) {\n if (e.target.value !== holder.valueOnFocus) {\n triggerEvent('change', e.target);\n // e.preventDefault(); // ...and immediately prevent the browser to send a second change event (that somehow gets picked up by jQuery, but not by `addEventListener()` //FIXME KNOWN BUG : This does not prevent the second change event to be picked up by jQuery, which adds '.00' at the end of an integer\n }\n }\n\n /**\n * Handler for 'submit' events\n *\n * @param {object} $this jQuery-selected DOM element\n * @param {AutoNumericHolder} holder\n */\n function onSubmit($this, holder) {\n $this.closest('form').on('submit.autoNumeric', () => {\n if (holder) {\n const $settings = holder.settingsClone;\n\n if ($settings.unformatOnSubmit) {\n $this.val($settings.rawValue);\n }\n }\n });\n }\n\n /**\n * Return the jQuery selected input if the tag and type are supported by autoNumeric.\n *\n * @param {object} $this jQuery-selected DOM element\n * @returns {boolean|*}\n */\n function getInputIfSupportedTagAndType($this) {\n // Supported input type\n const $input = $this.is('input[type=text], input[type=hidden], input[type=tel], input:not([type])');\n\n // Checks for non-supported input types\n if (!$input && $this.prop('tagName').toLowerCase() === 'input') {\n throwError(`The input type \"${$this.prop('type')}\" is not supported by autoNumeric`);\n }\n\n // Checks for non-supported tags\n const currentElementTag = $this.prop('tagName').toLowerCase();\n if (currentElementTag !== 'input' && !isInArray(currentElementTag, allowedTagList)) {\n throwError(`The <${currentElementTag}> tag is not supported by autoNumeric`);\n }\n\n return $input;\n }\n\n /**\n * Formats the default value on page load.\n * This is called only if the `formatOnPageLoad` option is set to `true`.\n *\n * @param {object} settings\n * @param {object} $input jQuery-selected element\n * @param {object} $this jQuery-selected DOM element\n */\n function formatDefaultValueOnPageLoad(settings, $input, $this) {\n let setValue = true;\n\n if ($input) {\n const currentValue = $this.val();\n /*\n * If the input value has been set by the dev, but not directly as an attribute in the html, then it takes\n * precedence and should get formatted on init (if this input value is a valid number and that the\n * developer wants it formatted on init (cf. `settings.formatOnPageLoad`)).\n * Note; this is true whatever the developer has set for `data-an-default` in the html (asp.net users).\n *\n * In other words : if `defaultValueOverride` is not null, it means the developer is trying to prevent postback problems.\n * But if `input.value` is set to a number, and `$this.attr('value')` is not set, then it means the dev has\n * changed the input value, and then it means we should not overwrite his own decision to do so.\n * Hence, if `defaultValueOverride` is not null, but `input.value` is a number and `$this.attr('value')` is not set,\n * we should ignore `defaultValueOverride` altogether.\n */\n const unLocalizedCurrentValue = toNumericValue(currentValue, settings); // This allows to use a localized value on startup oDec\n if (settings.formatOnPageLoad && currentValue !== '' && isUndefinedOrNullOrEmpty($this.attr('value'))) {\n // Check if the `value` is valid or not\n if (!isNaN(unLocalizedCurrentValue) && Infinity !== unLocalizedCurrentValue) {\n $this.autoNumeric('set', unLocalizedCurrentValue);\n setValue = false;\n } else {\n // If not, inform the developer that nothing usable has been provided\n throwError(`The value [${currentValue}] used in the input is not a valid value autoNumeric can work with.`);\n }\n } else {\n /* Checks for :\n * - page reload from back button, and\n * - ASP.net form post back\n * The following HTML data attribute is REQUIRED (data-an-default=\"same value as the value attribute\")\n * example: \n */\n if ((settings.defaultValueOverride !== null && settings.defaultValueOverride.toString() !== currentValue) ||\n (settings.defaultValueOverride === null && currentValue !== '' && currentValue !== $this.attr('value')) ||\n (currentValue !== '' && $this.attr('type') === 'hidden' && !isNumber(unLocalizedCurrentValue))) {\n if ((settings.decimalPlacesShownOnFocus !== null && settings.saveValueToSessionStorage) ||\n (settings.scaleDivisor && settings.saveValueToSessionStorage)) {\n settings.rawValue = saveValueToPersistentStorage($this[0], settings, 'get');\n }\n\n // If the decimalPlacesShownOnFocus value should NOT be saved in sessionStorage\n if (!settings.saveValueToSessionStorage) {\n let toStrip;\n\n if (settings.negativeBracketsTypeOnBlur !== null && settings.negativeSignCharacter !== '') {\n settings.hasFocus = true;\n toStrip = toggleNegativeBracket(currentValue, settings);\n } else {\n toStrip = currentValue;\n }\n\n if ((settings.negativePositiveSignPlacement === 's' ||\n (settings.negativePositiveSignPlacement !== 'p' && settings.currencySymbolPlacement === 's')) &&\n settings.negativeSignCharacter !== '' &&\n isNegative(currentValue)) {\n settings.rawValue = settings.negativeSignCharacter + stripAllNonNumberCharacters(toStrip, settings, true);\n } else {\n settings.rawValue = stripAllNonNumberCharacters(toStrip, settings, true);\n }\n }\n\n setValue = false;\n }\n }\n\n if (currentValue === '') {\n switch (settings.emptyInputBehavior) {\n case 'focus':\n setValue = false;\n break;\n case 'always':\n $this.val(settings.currencySymbol);\n setValue = false;\n break;\n case 'zero':\n $this.autoNumeric('set', '0');\n setValue = false;\n break;\n default :\n //\n }\n } else if (setValue && currentValue === $this.attr('value')) {\n $this.autoNumeric('set', currentValue);\n }\n }\n\n if (isInArray($this.prop('tagName').toLowerCase(), settings.tagList) && $this.text() !== '') {\n if (settings.defaultValueOverride !== null) {\n if (settings.defaultValueOverride === $this.text()) {\n $this.autoNumeric('set', $this.text());\n }\n } else {\n $this.autoNumeric('set', $this.text());\n }\n }\n }\n\n /**\n * Enhance the user experience by modifying the default `negativePositiveSignPlacement` option depending on `currencySymbol` and `currencySymbolPlacement`.\n *\n * If the user has not set the placement of the negative sign (`negativePositiveSignPlacement`), but has set a currency symbol (`currencySymbol`),\n * then we modify the default value of `negativePositiveSignPlacement` in order to keep the resulting output logical by default :\n * - \"$-1,234.56\" instead of \"-$1,234.56\" ({currencySymbol: \"$\", negativePositiveSignPlacement: \"r\"})\n * - \"-1,234.56$\" instead of \"1,234.56-$\" ({currencySymbol: \"$\", currencySymbolPlacement: \"s\", negativePositiveSignPlacement: \"p\"})\n *\n * @param {object} settings\n */\n function correctNegativePositiveSignPlacementOption(settings) {\n // If negativePositiveSignPlacement is already set, we do not overwrite it\n if (!isNull(settings.negativePositiveSignPlacement)) {\n return;\n }\n\n if (!isUndefined(settings) &&\n isUndefinedOrNullOrEmpty(settings.negativePositiveSignPlacement) &&\n !isUndefinedOrNullOrEmpty(settings.currencySymbol)) {\n switch (settings.currencySymbolPlacement) {\n case 's':\n settings.negativePositiveSignPlacement = 'p'; // Default -1,234.56 €\n break;\n case 'p':\n settings.negativePositiveSignPlacement = 'l'; // Default -$1,234.56\n break;\n default :\n //\n }\n } else {\n // Sets the default value if `negativePositiveSignPlacement` is `null`\n settings.negativePositiveSignPlacement = 'l';\n }\n }\n\n /**\n * Analyze and save the minimumValue and maximumValue integer size for later uses\n *\n * @param {object} settings\n */\n function calculateVMinAndVMaxIntegerSizes(settings) {\n let [maximumValueIntegerPart] = settings.maximumValue.toString().split('.');\n let [minimumValueIntegerPart] = (!settings.minimumValue && settings.minimumValue !== 0)?[]:settings.minimumValue.toString().split('.');\n maximumValueIntegerPart = maximumValueIntegerPart.replace('-', '');\n minimumValueIntegerPart = minimumValueIntegerPart.replace('-', '');\n\n settings.mIntPos = Math.max(maximumValueIntegerPart.length, 1);\n settings.mIntNeg = Math.max(minimumValueIntegerPart.length, 1);\n }\n\n /**\n * Modify `decimalPlacesOverride` as needed\n *\n * @param {object} settings\n */\n function correctDecimalPlacesOverrideOption(settings) {\n if (isNull(settings.decimalPlacesOverride)) {\n settings.decimalPlacesOverride = maximumVMinAndVMaxDecimalLength(settings.minimumValue, settings.maximumValue);\n }\n settings.oDec = String(settings.decimalPlacesOverride);\n\n // Most calculus assume `decimalPlacesOverride` is an integer, the following statement makes it clear (otherwise having it as a string leads to problems in rounding for instance)\n settings.decimalPlacesOverride = Number(settings.decimalPlacesOverride);\n }\n\n /**\n * Sets the alternative decimal separator key.\n *\n * @param {object} settings\n */\n function setsAlternativeDecimalSeparatorCharacter(settings) {\n if (isNull(settings.decimalCharacterAlternative) && Number(settings.decimalPlacesOverride) > 0) {\n if (settings.decimalCharacter === '.' && settings.digitGroupSeparator !== ',') {\n settings.decimalCharacterAlternative = ',';\n } else if (settings.decimalCharacter === ',' && settings.digitGroupSeparator !== '.') {\n settings.decimalCharacterAlternative = '.';\n }\n }\n }\n\n /**\n * Caches regular expressions for stripAllNonNumberCharacters\n *\n * @param {object} settings\n */\n function cachesUsualRegularExpressions(settings) {\n const allNumbersReg = '[0-9]';\n const noAllNumbersReg = '[^0-9]';\n\n // Test if there is a negative character in the string\n const aNegReg = settings.negativeSignCharacter?`([-\\\\${settings.negativeSignCharacter}]?)`:'(-?)';\n settings.aNegRegAutoStrip = aNegReg;\n\n let negativeSignRegPart;\n if (settings.negativeSignCharacter) {\n negativeSignRegPart = `\\\\${settings.negativeSignCharacter}`;\n } else {\n negativeSignRegPart = '';\n }\n settings.skipFirstAutoStrip = new RegExp(`${aNegReg}[^-${negativeSignRegPart}\\\\${settings.decimalCharacter}${allNumbersReg}].*?(${allNumbersReg}|\\\\${settings.decimalCharacter}${allNumbersReg})`);\n settings.skipLastAutoStrip = new RegExp(`(${allNumbersReg}\\\\${settings.decimalCharacter}?)[^\\\\${settings.decimalCharacter}${allNumbersReg}]${noAllNumbersReg}*$`);\n\n const allowed = `-0123456789\\\\${settings.decimalCharacter}`;\n settings.allowedAutoStrip = new RegExp(`[^${allowed}]`, 'g');\n settings.numRegAutoStrip = new RegExp(`${aNegReg}(?:\\\\${settings.decimalCharacter}?(${allNumbersReg}+\\\\${settings.decimalCharacter}${allNumbersReg}+)|(${allNumbersReg}*(?:\\\\${settings.decimalCharacter}${allNumbersReg}*)?))`);\n\n // Using this regex version `^${settings.aNegRegAutoStrip}0*(\\\\d|$)` entirely clear the input on blur\n settings.stripReg = new RegExp(`^${settings.aNegRegAutoStrip}0*(${allNumbersReg})`);\n }\n\n /**\n * Modify the user settings to make them 'exploitable' later.\n *\n * @param {object} settings\n */\n function transformOptionsValuesToDefaultTypes(settings) {\n $.each(settings, (key, value) => {\n // Convert the string 'true' and 'false' to real Boolean\n if (value === 'true' || value === 'false') {\n settings[key] = value === 'true';\n }\n\n // Convert numbers in options to strings\n //TODO if a value is already of type 'Number', shouldn't we keep it as a number for further manipulation, instead of using a string?\n if (typeof value === 'number' && key !== 'aScale') {\n settings[key] = value.toString();\n }\n });\n }\n\n /**\n * Convert the old settings options name to new ones.\n *\n * @param {object} options\n */\n function convertOldOptionsToNewOnes(options) {\n //TODO Delete this function once the old options are not used anymore\n const oldOptionsConverter = {\n // Old option name, with their corresponding new option\n aSep : 'digitGroupSeparator',\n nSep : 'noSeparatorOnFocus',\n dGroup : 'digitalGroupSpacing',\n aDec : 'decimalCharacter',\n altDec : 'decimalCharacterAlternative',\n aSign : 'currencySymbol',\n pSign : 'currencySymbolPlacement',\n pNeg : 'negativePositiveSignPlacement',\n aSuffix : 'suffixText',\n oLimits : 'overrideMinMaxLimits',\n vMax : 'maximumValue',\n vMin : 'minimumValue',\n mDec : 'decimalPlacesOverride',\n eDec : 'decimalPlacesShownOnFocus',\n scaleDecimal : 'scaleDecimalPlaces',\n aStor : 'saveValueToSessionStorage',\n mRound : 'roundingMethod',\n aPad : 'allowDecimalPadding',\n nBracket : 'negativeBracketsTypeOnBlur',\n wEmpty : 'emptyInputBehavior',\n lZero : 'leadingZero',\n aForm : 'formatOnPageLoad',\n sNumber : 'selectNumberOnly',\n anDefault : 'defaultValueOverride',\n unSetOnSubmit : 'unformatOnSubmit',\n outputType : 'outputFormat',\n debug : 'showWarnings',\n // Current options :\n digitGroupSeparator : true,\n noSeparatorOnFocus : true,\n digitalGroupSpacing : true,\n decimalCharacter : true,\n decimalCharacterAlternative : true,\n currencySymbol : true,\n currencySymbolPlacement : true,\n negativePositiveSignPlacement: true,\n showPositiveSign : true,\n suffixText : true,\n overrideMinMaxLimits : true,\n maximumValue : true,\n minimumValue : true,\n decimalPlacesOverride : true,\n decimalPlacesShownOnFocus : true,\n scaleDivisor : true,\n scaleDecimalPlaces : true,\n scaleSymbol : true,\n saveValueToSessionStorage : true,\n onInvalidPaste : true,\n roundingMethod : true,\n allowDecimalPadding : true,\n negativeBracketsTypeOnBlur : true,\n emptyInputBehavior : true,\n leadingZero : true,\n formatOnPageLoad : true,\n selectNumberOnly : true,\n defaultValueOverride : true,\n unformatOnSubmit : true,\n outputFormat : true,\n showWarnings : true,\n failOnUnknownOption : true,\n //FIXME Find a way to exclude those internal data from the settings object (ideally by using another object, or better yet, class attributes) -->\n hasFocus : true,\n runOnce : true,\n rawValue : true,\n trailingNegative : true,\n caretFix : true,\n throwInput : true,\n strip : true,\n tagList : true,\n negativeSignCharacter: true,\n positiveSignCharacter: true,\n mIntPos : true,\n mIntNeg : true,\n oDec : true,\n oPad : true,\n oBracket : true,\n oSep : true,\n oSign : true,\n oSuffix : true,\n aNegRegAutoStrip : true,\n skipFirstAutoStrip : true,\n skipLastAutoStrip : true,\n allowedAutoStrip : true,\n numRegAutoStrip : true,\n stripReg : true,\n holder : true,\n };\n\n for (const option in options) {\n if (options.hasOwnProperty(option)) {\n if (oldOptionsConverter[option] === true) {\n // If the option is a 'new' option, we continue looping\n continue;\n }\n\n if (oldOptionsConverter.hasOwnProperty(option)) {\n // Else we have an 'old' option name\n warning(`You are using the deprecated option name '${option}'. Please use '${oldOptionsConverter[option]}' instead from now on. The old option name will be dropped soon.`, true);\n\n // Then we modify the initial option object to use the new options instead of the old ones\n options[oldOptionsConverter[option]] = options[option];\n delete options[option];\n } else if (options.failOnUnknownOption) {\n // ...or the option name is unknown. This means there is a problem with the options object, therefore we throw an error.\n throwError(`Option name '${option}' is unknown. Please fix the options passed to autoNumeric`);\n }\n }\n }\n }\n\n /**\n * Analyse the settings/options passed by the user, validate and clean them, then return them.\n * Note: This returns `null` if somehow the settings returned by jQuery is not an object.\n *\n * @param {object} options\n * @param {object} $this jQuery-selected DOM element\n * @param {boolean} update - If TRUE, then the settings already exists and this function only updates them instead of recreating them from scratch\n * @returns {object|null}\n */\n function getInitialSettings(options, $this, update = false) {\n // Attempt to grab \"autoNumeric\" settings. If they do not exist, it returns \"undefined\".\n let settings = $this.data('autoNumeric');\n\n // If the user used old options, we convert them to new ones\n if (update || !isNull(options)) {\n convertOldOptionsToNewOnes(options);\n }\n\n if (update || isUndefined(settings)) {\n if (update) {\n // The settings are updated\n settings = $.extend(settings, options);\n } else {\n // If we couldn't grab any settings, create them from the default ones and combine them with the options passed\n // The settings are generated for the first time\n // This also attempt to grab the HTML5 data. If it doesn't exist, we'll get \"undefined\"\n const tagData = $this.data();\n settings = $.extend({}, defaultSettings, tagData, options, {\n hasFocus : false,\n runOnce : false,\n rawValue : '',\n trailingNegative : false,\n caretFix : false,\n androidSelectionStart: null,\n throwInput : true, // Throw input event\n strip : true,\n tagList : allowedTagList,\n });\n }\n\n // Modify the user settings to make them 'exploitable'\n transformOptionsValuesToDefaultTypes(settings);\n\n // Improve the `negativePositiveSignPlacement` option if needed\n correctNegativePositiveSignPlacementOption(settings);\n\n // Set the negative and positive signs, as needed\n settings.negativeSignCharacter = settings.minimumValue < 0 ? '-' : '';\n settings.positiveSignCharacter = settings.maximumValue >= 0 ? '+' : '';\n\n // Additional changes to the settings object (from the original autoCode() function)\n runCallbacksFoundInTheSettingsObject($this, settings);\n calculateVMinAndVMaxIntegerSizes(settings);\n correctDecimalPlacesOverrideOption(settings);\n setsAlternativeDecimalSeparatorCharacter(settings);\n cachesUsualRegularExpressions(settings);\n\n // Validate the settings\n validate(settings, false); // Throws if necessary\n\n // Original settings saved for use when decimalPlacesShownOnFocus, scaleDivisor & noSeparatorOnFocus options are being used\n keepAnOriginalSettingsCopy(settings);\n\n // Save our new settings\n $this.data('autoNumeric', settings);\n\n return settings;\n } else {\n return null;\n }\n }\n\n /**\n * Convert the `value` parameter that can either be :\n * - a real number,\n * - a string representing a real number, or\n * - a string representing a localized number (with specific group separators and decimal character),\n * ...to a string representing a real 'javascript' number (ie. '1234' or '1234.567').\n *\n * This function returns `NaN` if such conversion fails.\n *\n * @param {int|float|string} value\n * @param {object} settings\n * @returns {string|NaN}\n */\n function toNumericValue(value, settings) {\n let result;\n if (isNumber(Number(value))) {\n // The value has either already been stripped, or a 'real' javascript number is passed as a parameter\n result = value;\n } else {\n // Else if it's a string that `Number()` cannot typecast, then we try to convert the localized numeric string to a numeric one\n // Convert the value to a numeric string, stripping unnecessary characters in the process\n result = convertToNumericString(value.toString(), settings);\n\n // If the result is still not a numeric string, then we throw a warning\n if (!isNumber(Number(result))) {\n warning(`The value \"${value}\" being \"set\" is not numeric and therefore cannot be used appropriately.`, settings.showWarnings);\n result = NaN;\n }\n }\n\n return result;\n }\n\n /**\n * Methods supported by autoNumeric\n */\n const methods = {\n /**\n * Method to initialize autoNumeric and attach the settings (options can be passed as a parameter)\n * The options passed as a parameter is an object that contains the settings (ie. {digitGroupSeparator: \".\", decimalCharacter: \",\", currencySymbol: '€ '})\n *\n * @example\n * $(someSelector).autoNumeric('init'); // Initiate autoNumeric with defaults\n * $(someSelector).autoNumeric(); // Initiate autoNumeric with defaults\n * $(someSelector).autoNumeric('init', {options}); // Initiate autoNumeric with options\n * $(someSelector).autoNumeric({options}); // Initiate autoNumeric with options\n *\n * @param {object} options\n * @returns {*|{statements, branches, lines, functions, excludes, overrides}|{statements, branches, lines, functions, excludes}|{statements, lines, branches, functions, excludes}}\n */\n init(options) {\n return this.each(function() {\n const $this = $(this);\n const $input = getInputIfSupportedTagAndType($this);\n\n const settings = getInitialSettings(options, $this, false);\n if (isNull(settings)) {\n return this;\n }\n\n // Create the AutoNumericHolder object that store the field properties\n const holder = getAutoNumericHolder($this, settings, false);\n\n if (!settings.runOnce && settings.formatOnPageLoad) {\n formatDefaultValueOnPageLoad(settings, $input, $this);\n }\n\n settings.runOnce = true;\n\n // Add the events listeners to supported input types (\"text\", \"hidden\", \"tel\" and no type)\n if ($input) {\n this.addEventListener('focusin', e => { onFocusInAndMouseEnter($this, holder, e); }, false);\n this.addEventListener('mouseenter', e => { onFocusInAndMouseEnter($this, holder, e); }, false);\n this.addEventListener('blur', e => { onFocusOutAndMouseLeave($this, holder, e); }, false);\n this.addEventListener('mouseleave', e => { onFocusOutAndMouseLeave($this, holder, e); }, false);\n this.addEventListener('keydown', e => { onKeydown(holder, e); }, false);\n this.addEventListener('keypress', e => { onKeypress(holder, e); }, false);\n this.addEventListener('input', e => { onInput(holder, e); }, false);\n this.addEventListener('keyup', e => { onKeyup(holder, settings, e); }, false);\n this.addEventListener('blur', e => { onBlur(holder, e); }, false);\n this.addEventListener('paste', e => { onPaste($this, holder, e); }, false);\n onSubmit($this, holder); //TODO Switch to `addEventListener'\n }\n });\n },\n\n /**\n * Method to stop and remove autoNumeric for the current element.\n * Note: this does not remove the formatting.\n *\n * @example $(someSelector).autoNumeric(\"destroy\"); // Destroys autoNumeric on this selected element\n *\n * @returns {*|jQuery}\n */\n destroy() {\n return $(this).each(function() {\n const $this = getCurrentElement(this);\n const settings = $this.data('autoNumeric');\n if (typeof settings === 'object') {\n $this.val('');\n saveValueToPersistentStorage($this[0], settings, 'wipe');\n $this.removeData('autoNumeric');\n $this.off('.autoNumeric');\n }\n });\n },\n\n /**\n * Method to clear the value from sessionStorage (or cookie, depending on browser supports).\n *\n * @example $(someSelector).autoNumeric(\"wipe\"); // Removes session storage and cookies from memory\n *\n * @returns {*|jQuery}\n */\n wipe() {\n return $(this).each(function() {\n const $this = getCurrentElement(this);\n const settings = $this.data('autoNumeric');\n if (typeof settings === 'object') {\n $this.val('');\n settings.rawValue = '';\n saveValueToPersistentStorage($this[0], settings, 'wipe');\n }\n });\n },\n\n /**\n * Method that updates the autoNumeric settings.\n * It can be called multiple times if needed.\n * The options passed as a parameter is an object that contains the settings (ie. {digitGroupSeparator: \".\", decimalCharacter: \",\", currencySymbol: '€ '}).\n *\n * @example $(someSelector).autoNumeric(\"update\", {options}); // Updates the settings\n *\n * @param {object} options\n * @returns {*|jQuery}\n */\n update(options) {\n return $(this).each(function() {\n // Retrieve the current unformatted input value\n const $this = getCurrentElement(this);\n const strip = $this.autoNumeric('get');\n\n // Update the settings\n const settings = getInitialSettings(options, $this, true);\n\n // Update the AutoNumericHolder object that store the field properties\n getAutoNumericHolder($this, settings, true);\n\n // Reformat the input value with the new settings\n if ($this.val() !== '' || $this.text() !== '') {\n return $this.autoNumeric('set', strip);\n }\n });\n },\n\n /**\n * Method to format the value passed as a parameter.\n * If the value is passed as a string, it can be an integer '1234' or a double '1234.56789'\n * and must contain only numbers and one decimal (period) character\n *\n * @example $(someSelector).autoNumeric('set', '12345.67'); // Formats the value being passed as the second parameter\n *\n * @param {*} newValue\n * @returns {*|jQuery}\n */\n set(newValue) {\n return $(this).each(function() {\n if (newValue === null || isUndefined(newValue)) {\n return;\n }\n\n //TODO This looks a lot like `getInputIfSupportedTagAndType()`. Is that necessary? Can the input element be changed since autoNumeric has been initialized?\n const $this = getCurrentElement(this);\n const settings = $this.data('autoNumeric');\n if (typeof settings !== 'object') {\n throwError(`Initializing autoNumeric is required prior to calling the \"set\" method.`);\n }\n // Reset the trailing negative settings, since it's possible the previous value was negative, but not the newly set one\n settings.trailingNegative = false;\n\n const $input = $this.is('input[type=text], input[type=hidden], input[type=tel], input:not([type])');\n\n let value = toNumericValue(newValue, settings);\n if (isNaN(value)) {\n return $this.val('');\n }\n\n if (value !== '') {\n const [minTest, maxTest] = checkIfInRangeWithOverrideOption(value, settings);\n // This test is needed by the showPositiveSign option\n const isZero = isZeroOrHasNoValue(value);\n if (isZero) {\n value = '0';\n }\n\n if (minTest && maxTest) {\n if ($input || isInArray($this.prop('tagName').toLowerCase(), settings.tagList)) {\n // to ensure rounding does not happen twice\n let hasBeenRounded = false;\n\n // rounds the the extended decimal places\n let tempDecimal;\n if (settings.decimalPlacesShownOnFocus) {\n tempDecimal = settings.decimalPlacesOverride;\n settings.decimalPlacesOverride = Number(settings.decimalPlacesShownOnFocus);\n value = roundValue(value, settings);\n hasBeenRounded = true;\n settings.decimalPlacesOverride = tempDecimal;\n }\n\n if (settings.scaleDivisor && !settings.onOff) {\n value = roundValue(value, settings);\n settings.rawValue = cleanLeadingTrailingZeros(value.replace(settings.decimalCharacter, '.'), settings);\n value = toNumericValue(value, settings);\n value = value / settings.scaleDivisor;\n value = value.toString();\n if (settings.scaleDecimalPlaces) {\n tempDecimal = settings.decimalPlacesOverride;\n settings.decimalPlacesOverride = Number(settings.scaleDecimalPlaces);\n value = roundValue(value, settings);\n hasBeenRounded = true;\n }\n }\n\n // Rounds if this has not been done already\n if (!hasBeenRounded) {\n value = roundValue(value, settings);\n }\n\n // Stores rawValue including the decimalPlacesShownOnFocus\n if (!settings.scaleDivisor) {\n settings.rawValue = cleanLeadingTrailingZeros(value.replace(settings.decimalCharacter, '.'), settings);\n }\n\n value = modifyNegativeSignAndDecimalCharacterForFormattedValue(value, settings);\n value = addGroupSeparators(value, settings);\n\n if (settings.scaleDivisor && settings.scaleDecimalPlaces && !settings.onOff) {\n settings.decimalPlacesOverride = tempDecimal;\n }\n }\n\n if (settings.saveValueToSessionStorage && (settings.decimalPlacesShownOnFocus || settings.scaleDivisor)) {\n saveValueToPersistentStorage($this[0], settings, 'set');\n }\n } else {\n settings.rawValue = '';\n saveValueToPersistentStorage($this[0], settings, 'wipe');\n const attemptedValue = value;\n value = '';\n if (!minTest) {\n $this.trigger('autoNumeric:minExceeded');\n }\n\n if (!maxTest) {\n $this.trigger('autoNumeric:maxExceeded');\n }\n\n throwError(`The value [${attemptedValue}] being set falls outside of the minimumValue [${settings.minimumValue}] and maximumValue [${settings.maximumValue}] range set for this element`);\n\n return $this.val('');\n }\n } else {\n return $this.val('');\n }\n\n if (!settings.hasFocus && settings.scaleSymbol) {\n value = value + settings.scaleSymbol;\n }\n\n if ($input) {\n return $this.val(value);\n }\n\n if (isInArray($this.prop('tagName').toLowerCase(), settings.tagList)) {\n return $this.text(value);\n }\n\n return false;\n });\n },\n\n /**\n * Method to un-format inputs.\n * This is handy to use right before form submission.\n *\n * By default, values are returned as ISO numeric strings (ie. \"1234.56\" or \"-1234.56\"), where the decimal character is a period.\n * Locale formats are supported \"1234.56-\" or \"1234,56\" or \"-1234,56 or \"1234,56-\", or even plain numbers.\n * Please see option \"outputFormat\" for more details\n *\n * @example $(someSelector).autoNumeric('unSet');\n *\n * @returns {*|jQuery}\n */\n unSet() {\n return $(this).each(function() {\n const $this = getCurrentElement(this);\n const settings = $this.data('autoNumeric');\n if (typeof settings === 'object') {\n settings.hasFocus = true;\n $this.val($this.autoNumeric('getLocalized'));\n }\n });\n },\n\n /**\n * Method to re-format inputs.\n * This is handy to use right after form submission.\n *\n * This is called after the 'unSet' method to reformat the input\n *\n * @example $(someSelector).autoNumeric('reSet');\n *\n * @returns {*|jQuery}\n */\n reSet() {\n return $(this).each(function() {\n const $this = getCurrentElement(this);\n const settings = $this.data('autoNumeric');\n if (typeof settings === 'object') {\n $this.autoNumeric('set', $this.val());\n }\n });\n },\n\n /**\n * Return the unformatted value as a string.\n *\n * @usage $(someSelector).autoNumeric('get');\n *\n * @returns {string}\n */\n get() {\n //TODO Why would we need to get a new reference to $this since it has been done in `init()`?\n const $this = getCurrentElement(this);\n //TODO This looks a lot like `getInputIfSupportedTagAndType()`. Is that necessary? Can the input element be changed since autoNumeric has been initialized?\n const $input = $this.is('input[type=text], input[type=hidden], input[type=tel], input:not([type])');\n const settings = $this.data('autoNumeric');\n if (typeof settings !== 'object') {\n throwError(`Initializing autoNumeric is required prior to calling the \"get\" method.`);\n }\n\n // determine the element type then use .eq(0) selector to grab the value of the first element in selector\n let value = '';\n if ($input) {\n value = $this.eq(0).val();\n } else if (isInArray($this.prop('tagName').toLowerCase(), settings.tagList)) {\n value = $this.eq(0).text();\n } else {\n throwError(`The \"<${$this.prop('tagName').toLowerCase()}>\" tag is not supported by autoNumeric`);\n }\n\n if (settings.decimalPlacesShownOnFocus || settings.scaleDivisor) {\n value = settings.rawValue;\n } else {\n // Test if the value is negative\n const isValueNegative = isNegative(value);\n\n if (!(/\\d/).test(value) && settings.emptyInputBehavior === 'focus') {\n return '';\n }\n\n if (value !== '' && settings.negativeBracketsTypeOnBlur !== null) {\n settings.hasFocus = true;\n value = toggleNegativeBracket(value, settings);\n }\n\n if (settings.runOnce || settings.formatOnPageLoad === false) {\n // Strips trailing negative symbol\n value = stripAllNonNumberCharacters(value, settings, true);\n // Trims leading and trailing zeros when leadingZero does NOT equal \"keep\".\n value = cleanLeadingTrailingZeros(value.replace(settings.decimalCharacter, '.'), settings);\n\n // Places the negative symbol in front of the trailing negative\n if (settings.trailingNegative && isValueNegative && !isNegative(value) && Number(value) !== 0) {\n value = '-' + value;\n }\n }\n\n if (value !== '' || value === '' && settings.emptyInputBehavior === 'zero') {\n value = modifyNegativeSignAndDecimalCharacterForRawValue(value, settings);\n }\n }\n\n // Always return a numeric string\n // This gets rid of the trailing zeros in the decimal places since `get` does not pad decimals\n return trimPaddedZerosFromDecimalPlaces(value);\n },\n\n /**\n * Returns the unformatted value, but following the `outputFormat` setting, which means the output can either be :\n * - a string (that could or could not represent a number (ie. \"12345,67-\")), or\n * - a plain number (if the setting 'number' is used).\n *\n * By default the returned values are an ISO numeric string \"1234.56\" or \"-1234.56\" where the decimal character is a period.\n * Check the \"outputFormat\" option definition for more details.\n *\n * @usage $(someSelector).autoNumeric('getLocalized');\n *\n * @returns {*}\n */\n getLocalized() {\n const $this = getCurrentElement(this);\n let value = $this.autoNumeric('get');\n const settings = $this.data('autoNumeric');\n\n if (Number(value) === 0 && settings.leadingZero !== 'keep') {\n value = '0';\n }\n\n return toLocale(value, settings.outputFormat);\n },\n\n /**\n * Return the input unformatted value as a real Javascript number.\n *\n * @usage $(someSelector).autoNumeric('getNumber');\n *\n * @returns {number}\n */\n getNumber() {\n const $this = getCurrentElement(this);\n const value = $this.autoNumeric('get');\n\n return toLocale(value, 'number');\n },\n\n /**\n * Return the current formatted value of the autoNumeric element.\n * @usage aNInput.autoNumeric('getFormatted'))\n *\n * @returns {string}\n */\n getFormatted() {\n // Make sure `this[0]` exists as well as `.value` before trying to access that property\n if (!this.hasOwnProperty('0') || !('value' in this[0])) {\n throwError('Unable to get the formatted string from the element.');\n }\n\n return this[0].value;\n },\n\n /**\n * The \"getString\" method uses jQuery's .serialize() method that creates a text string in standard URL-encoded notation.\n *\n * It then loops through the string and un-formats the inputs with autoNumeric.\n * By defaults values returned as ISO numeric string \"1234.56\" or \"-1234.56\" where the decimal character is a period\n * Locale formats are supported \"1234.56-\" or \"1234,56\" or \"-1234,56 or \"1234,56-\" or plain numbers => please see option \"outputFormat\" for details\n *\n * @returns {string}\n */\n getString() {\n return _getStringOrArray(false, this);\n },\n\n /**\n * The \"getArray\" method on the other hand uses jQuery's .serializeArray() method that creates array or objects that can be encoded as a JSON string.\n *\n * It then loops through the string and un-formats the inputs with autoNumeric.\n * By defaults values returned as ISO numeric string \"1234.56\" or \"-1234.56\" where the decimal character is a period\n * Locale formats are supported \"1234.56-\" or \"1234,56\" or \"-1234,56 or \"1234,56-\" or plain numbers => please see option \"outputFormat\" for details\n *\n * @returns {{}|[]}\n */\n getArray() {\n return _getStringOrArray(true, this);\n },\n\n /**\n * The 'getSettings' function returns an object containing all the current autoNumeric settings.\n *\n * @example\n * $(someSelector).autoNumeric('getSettings');\n * $(someSelector).autoNumeric('getSettings').decimalCharacter; // Return the decimalCharacter setting as a string - any valid option name can be used\n *\n * @returns {object}\n */\n getSettings() {\n //TODO Add an option argument `optionName` to this function so that it return only the value of that option, not the entire settings object\n return this.data('autoNumeric');\n },\n };\n\n /**\n * The autoNumeric function accepts methods names (in string format) and those method parameters if needed.\n * It initialize autoNumeric on the given element.\n *\n * @param {string} method The method name (ie. 'set', 'get', etc.)\n * @param {*} args\n * @returns {*}\n */\n $.fn.autoNumeric = function(method, ...args) {\n if (methods[method]) {\n return methods[method].apply(this, args);\n }\n\n if (typeof method === 'object' || !method) {\n // The options have been passed directly, without using a named method\n return methods.init.apply(this, [method]);\n }\n\n throwError(`Method \"${method}\" is not supported by autoNumeric`);\n };\n\n /**\n * Return the default autoNumeric settings.\n *\n * @returns {object}\n */\n getDefaultConfig = () => defaultSettings;\n\n $.fn.autoNumeric.defaults = defaultSettings; // Make those settings public via jQuery too.\n\n /**\n * Return all the predefined language options in one object.\n * You can also access a specific language object directly by using `an.getLanguages().French` for instance.\n *\n * @returns {object}\n */\n getLanguages = () => languageOption;\n\n $.fn.autoNumeric.lang = languageOption; // Make those predefined language options public via jQuery too.\n\n /**\n * Public function that allows formatting without an element trigger.\n *\n * @param {number|string} value A number, or a string that represent a javascript number\n * @param {object|null} options\n * @returns {*}\n */\n autoFormat = (value, options = null) => {\n if (isUndefined(value) || value === null) {\n return null;\n }\n\n if (!isString(value) && !isNumber(value)) {\n throwError(`The value \"${value}\" being \"set\" is not numeric and therefore cannot be used appropriately.`);\n }\n\n // Initiate a very basic settings object\n const settings = $.extend({}, defaultSettings, { strip: false }, options);\n if (value < 0) {\n settings.negativeSignCharacter = '-';\n }\n\n if (isNull(settings.decimalPlacesOverride)) {\n settings.decimalPlacesOverride = maximumVMinAndVMaxDecimalLength(settings.minimumValue, settings.maximumValue);\n }\n\n // Check the validity of the `value` parameter\n // Convert the value to a numeric string, stripping unnecessary characters in the process\n let valueString = toNumericValue(value, settings);\n if (isNaN(valueString)) {\n throwError(`The value [${valueString}] that you are trying to format is not a recognized number.`);\n }\n\n // Basic tests to check if the given valueString is valid\n const [minTest, maxTest] = checkIfInRangeWithOverrideOption(valueString, settings);\n if (!minTest || !maxTest) {\n // Throw a custom event\n triggerEvent('autoFormat.autoNumeric', document, `Range test failed`);\n throwError(`The value [${valueString}] being set falls outside of the minimumValue [${settings.minimumValue}] and maximumValue [${settings.maximumValue}] range set for this element`);\n }\n\n // Everything is ok, proceed to rounding, formatting and grouping\n valueString = roundValue(valueString, settings);\n valueString = modifyNegativeSignAndDecimalCharacterForFormattedValue(valueString, settings);\n valueString = addGroupSeparators(valueString, settings);\n\n return valueString;\n };\n\n $.fn.autoFormat = autoFormat; // The jQuery export\n\n /**\n * Public function that allows unformatting without an element.\n *\n * @param {string|number} value\n * @param {object} options\n * @returns {*}\n */\n autoUnFormat = (value, options) => {\n if (isUndefined(value) || value === null) {\n return null;\n }\n\n // Giving an unformatted value should return the same unformatted value, whatever the options passed as a parameter\n if (isNumber(value)) {\n return Number(value);\n }\n\n if (isArray(value) || isObject(value)) { //TODO Complete the test to throw when given a wrongly formatted number (ie. 'foobar')\n // Check the validity of the `value` parameter\n throwError(`A number or a string representing a number is needed to be able to unformat it, [${value}] given.`);\n }\n\n const settings = $.extend({}, defaultSettings, { strip: false }, options);\n const allowed = `-0123456789\\\\${settings.decimalCharacter}`;\n const autoStrip = new RegExp(`[^${allowed}]`, 'gi');\n value = value.toString();\n\n // This checks is a negative sign is anywhere in the `value`, not just on the very first character (ie. '12345.67-')\n if (isNegative(value)) {\n settings.negativeSignCharacter = '-';\n } else if (settings.negativeBracketsTypeOnBlur && settings.negativeBracketsTypeOnBlur.split(',')[0] === value.charAt(0)) {\n settings.negativeSignCharacter = '-';\n settings.hasFocus = true;\n value = toggleNegativeBracket(value, settings);\n }\n\n value = value.replace(autoStrip, '');\n value = value.replace(settings.decimalCharacter, '.');\n value = toLocale(value, settings.outputFormat);\n\n return value;\n };\n\n $.fn.autoUnformat = autoUnFormat; // The jQuery export\n\n /**\n * Validate the given option object.\n * If the options are valid, this function returns nothing, otherwise if the options are invalid, this function throws an error.\n *\n * This tests if the options are not conflicting and are well formatted.\n * This function is lenient since it only tests the settings properties ; it ignores any other properties the options object could have.\n *\n * @param {*} userOptions\n * @param {Boolean} shouldExtendDefaultOptions If TRUE, then this function will extends the `userOptions` passed by the user, with the default options.\n * @throws Error\n */\n validate = (userOptions, shouldExtendDefaultOptions = true) => {\n if (isUndefinedOrNullOrEmpty(userOptions) || !isObject(userOptions) || isEmptyObj(userOptions)) {\n throwError(`The userOptions are invalid ; it should be a valid object, [${userOptions}] given.`);\n }\n\n // If the user used old options, we convert them to new ones\n if (!isNull(userOptions)) {\n convertOldOptionsToNewOnes(userOptions);\n }\n\n // The user can choose if the `userOptions` has already been extended with the default options, or not\n let options;\n if (shouldExtendDefaultOptions) {\n options = $.extend({}, defaultSettings, userOptions);\n } else {\n options = userOptions;\n }\n\n // First things first, we test that the `showWarnings` option is valid\n if (!isTrueOrFalseString(options.showWarnings) && !isBoolean(options.showWarnings)) {\n throwError(`The debug option 'showWarnings' is invalid ; it should be either 'false' or 'true', [${options.showWarnings}] given.`);\n }\n\n // Define the regular expressions needed for the following tests\n const testPositiveInteger = /^[0-9]+$/;\n const testNumericalCharacters = /[0-9]+/;\n // const testFloatAndPossibleNegativeSign = /^-?[0-9]+(\\.?[0-9]+)$/;\n const testFloatOrIntegerAndPossibleNegativeSign = /^-?[0-9]+(\\.?[0-9]+)?$/;\n const testPositiveFloatOrInteger = /^[0-9]+(\\.?[0-9]+)?$/;\n\n // Then tests the options individually\n if (!isInArray(options.digitGroupSeparator, [\n ',', // Comma\n '.', // Dot\n ' ', // Normal space\n '\\u2009', // Thin-space\n '\\u202f', // Narrow no-break space\n '\\u00a0', // No-break space\n '', // No separator\n \"'\", // Apostrophe\n '٬', // Arabic thousands separator\n '˙', // Dot above\n ])) {\n throwError(`The thousand separator character option 'digitGroupSeparator' is invalid ; it should be ',', '.', '٬', '˙', \"'\", ' ', '\\u2009', '\\u202f', '\\u00a0' or empty (''), [${options.digitGroupSeparator}] given.`);\n }\n\n if (!isTrueOrFalseString(options.noSeparatorOnFocus) && !isBoolean(options.noSeparatorOnFocus)) {\n throwError(`The 'noSeparatorOnFocus' option is invalid ; it should be either 'false' or 'true', [${options.noSeparatorOnFocus}] given.`);\n }\n\n if (!testPositiveInteger.test(options.digitalGroupSpacing)) {\n throwError(`The digital grouping for thousand separator option 'digitalGroupSpacing' is invalid ; it should be a positive integer, [${options.digitalGroupSpacing}] given.`);\n }\n\n if (!isInArray(options.decimalCharacter, [\n ',', // Comma\n '.', // Dot\n '·', // Middle-dot\n '٫', // Arabic decimal separator\n '⎖', // Decimal separator key symbol\n ])) {\n throwError(`The decimal separator character option 'decimalCharacter' is invalid ; it should be '.', ',', '·', '⎖' or '٫', [${options.decimalCharacter}] given.`);\n }\n\n // Checks if the decimal and thousand characters are the same\n if (options.decimalCharacter === options.digitGroupSeparator) {\n throwError(`autoNumeric will not function properly when the decimal character 'decimalCharacter' [${options.decimalCharacter}] and the thousand separator 'digitGroupSeparator' [${options.digitGroupSeparator}] are the same character.`);\n }\n\n if (!isNull(options.decimalCharacterAlternative) && !isString(options.decimalCharacterAlternative)) {\n throwError(`The alternate decimal separator character option 'decimalCharacterAlternative' is invalid ; it should be a string, [${options.decimalCharacterAlternative}] given.`);\n }\n\n if (options.currencySymbol !== '' && !isString(options.currencySymbol)) {\n throwError(`The currency symbol option 'currencySymbol' is invalid ; it should be a string, [${options.currencySymbol}] given.`);\n }\n\n if (!isInArray(options.currencySymbolPlacement, ['p', 's'])) {\n throwError(`The placement of the currency sign option 'currencySymbolPlacement' is invalid ; it should either be 'p' (prefix) or 's' (suffix), [${options.currencySymbolPlacement}] given.`);\n }\n\n if (!isInArray(options.negativePositiveSignPlacement, ['p', 's', 'l', 'r', null])) {\n throwError(`The placement of the negative sign option 'negativePositiveSignPlacement' is invalid ; it should either be 'p' (prefix), 's' (suffix), 'l' (left), 'r' (right) or 'null', [${options.negativePositiveSignPlacement}] given.`);\n }\n\n if (!isTrueOrFalseString(options.showPositiveSign) && !isBoolean(options.showPositiveSign)) {\n throwError(`The show positive sign option 'showPositiveSign' is invalid ; it should be either 'false' or 'true', [${options.showPositiveSign}] given.`);\n }\n\n if (!isString(options.suffixText) || (options.suffixText !== '' && (isNegative(options.suffixText) || testNumericalCharacters.test(options.suffixText)))) {\n throwError(`The additional suffix option 'suffixText' is invalid ; it should not contains the negative sign '-' nor any numerical characters, [${options.suffixText}] given.`);\n }\n\n if (!isNull(options.overrideMinMaxLimits) && !isInArray(options.overrideMinMaxLimits, ['ceiling', 'floor', 'ignore'])) {\n throwError(`The override min & max limits option 'overrideMinMaxLimits' is invalid ; it should either be 'ceiling', 'floor' or 'ignore', [${options.overrideMinMaxLimits}] given.`);\n }\n\n if (!isString(options.maximumValue) || !testFloatOrIntegerAndPossibleNegativeSign.test(options.maximumValue)) {\n throwError(`The maximum possible value option 'maximumValue' is invalid ; it should be a string that represents a positive or negative number, [${options.maximumValue}] given.`);\n }\n\n if (!isString(options.minimumValue) || !testFloatOrIntegerAndPossibleNegativeSign.test(options.minimumValue)) {\n throwError(`The minimum possible value option 'minimumValue' is invalid ; it should be a string that represents a positive or negative number, [${options.minimumValue}] given.`);\n }\n\n if (parseFloat(options.minimumValue) > parseFloat(options.maximumValue)) {\n throwError(`The minimum possible value option is greater than the maximum possible value option ; 'minimumValue' [${options.minimumValue}] should be smaller than 'maximumValue' [${options.maximumValue}].`);\n }\n\n if (!(isNull(options.decimalPlacesOverride) ||\n (isInt(options.decimalPlacesOverride) && options.decimalPlacesOverride >= 0) || // If integer option\n (isString(options.decimalPlacesOverride) && testPositiveInteger.test(options.decimalPlacesOverride))) // If string option\n ) {\n throwError(`The maximum number of decimal places option 'decimalPlacesOverride' is invalid ; it should be a positive integer, [${options.decimalPlacesOverride}] given.`);\n }\n\n // Write a warning message in the console if the number of decimal in minimumValue/maximumValue is overridden by decimalPlacesOverride (and not if decimalPlacesOverride is equal to the number of decimal used in minimumValue/maximumValue)\n const vMinAndVMaxMaximumDecimalPlaces = maximumVMinAndVMaxDecimalLength(options.minimumValue, options.maximumValue);\n if (!isNull(options.decimalPlacesOverride) && vMinAndVMaxMaximumDecimalPlaces !== Number(options.decimalPlacesOverride)) {\n warning(`Setting 'decimalPlacesOverride' to [${options.decimalPlacesOverride}] will override the decimals declared in 'minimumValue' [${options.minimumValue}] and 'maximumValue' [${options.maximumValue}].`, options.showWarnings);\n }\n\n if (!options.allowDecimalPadding && !isNull(options.decimalPlacesOverride)) {\n warning(`Setting 'allowDecimalPadding' to [false] will override the current 'decimalPlacesOverride' setting [${options.decimalPlacesOverride}].`, options.showWarnings);\n }\n\n if (!isNull(options.decimalPlacesShownOnFocus) && (!isString(options.decimalPlacesShownOnFocus) || !testPositiveInteger.test(options.decimalPlacesShownOnFocus))) {\n throwError(`The number of expanded decimal places option 'decimalPlacesShownOnFocus' is invalid ; it should be a positive integer, [${options.decimalPlacesShownOnFocus}] given.`);\n }\n\n // Checks if the extended decimal places \"decimalPlacesShownOnFocus\" is greater than the normal decimal places \"decimalPlacesOverride\"\n if (!isNull(options.decimalPlacesShownOnFocus) && !isNull(options.decimalPlacesOverride) && Number(options.decimalPlacesOverride) > Number(options.decimalPlacesShownOnFocus)) {\n warning(`The extended decimal places 'decimalPlacesShownOnFocus' [${options.decimalPlacesShownOnFocus}] should be greater than the 'decimalPlacesOverride' [${options.decimalPlacesOverride}] value. Currently, this will limit the ability of your client to manually change some of the decimal places. Do you really want to do that?`, options.showWarnings);\n }\n\n if (!isNull(options.scaleDivisor) && !testPositiveFloatOrInteger.test(options.scaleDivisor)) {\n throwError(`The scale divisor option 'scaleDivisor' is invalid ; it should be a positive number, preferably an integer, [${options.scaleDivisor}] given.`);\n }\n\n if (!isNull(options.scaleDecimalPlaces) && !testPositiveInteger.test(options.scaleDecimalPlaces)) {\n throwError(`The scale number of decimals option 'scaleDecimalPlaces' is invalid ; it should be a positive integer, [${options.scaleDecimalPlaces}] given.`);\n }\n\n if (!isNull(options.scaleSymbol) && !isString(options.scaleSymbol)) {\n throwError(`The scale symbol option 'scaleSymbol' is invalid ; it should be a string, [${options.scaleSymbol}] given.`);\n }\n\n if (!isTrueOrFalseString(options.saveValueToSessionStorage) && !isBoolean(options.saveValueToSessionStorage)) {\n throwError(`The save to session storage option 'saveValueToSessionStorage' is invalid ; it should be either 'false' or 'true', [${options.saveValueToSessionStorage}] given.`);\n }\n\n if (!isInArray(options.onInvalidPaste, [\n 'error',\n 'ignore',\n 'clamp',\n 'truncate',\n 'replace',\n ])) {\n throwError(`The paste behavior option 'onInvalidPaste' is invalid ; it should either be 'error', 'ignore', 'clamp', 'truncate' or 'replace' (cf. documentation), [${options.onInvalidPaste}] given.`);\n }\n\n if (!isInArray(options.roundingMethod, [\n 'S',\n 'A',\n 's',\n 'a',\n 'B',\n 'U',\n 'D',\n 'C',\n 'F',\n 'N05',\n 'CHF',\n 'U05',\n 'D05',\n ])) {\n throwError(`The rounding method option 'roundingMethod' is invalid ; it should either be 'S', 'A', 's', 'a', 'B', 'U', 'D', 'C', 'F', 'N05', 'CHF', 'U05' or 'D05' (cf. documentation), [${options.roundingMethod}] given.`);\n }\n\n if (!isTrueOrFalseString(options.allowDecimalPadding) && !isBoolean(options.allowDecimalPadding)) {\n throwError(`The control decimal padding option 'allowDecimalPadding' is invalid ; it should be either 'false' or 'true', [${options.allowDecimalPadding}] given.`);\n }\n\n if (!isNull(options.negativeBracketsTypeOnBlur) && !isInArray(options.negativeBracketsTypeOnBlur, ['(,)', '[,]', '<,>', '{,}'])) {\n throwError(`The brackets for negative values option 'negativeBracketsTypeOnBlur' is invalid ; it should either be '(,)', '[,]', '<,>' or '{,}', [${options.negativeBracketsTypeOnBlur}] given.`);\n }\n\n if (!isInArray(options.emptyInputBehavior, ['focus', 'press', 'always', 'zero'])) {\n throwError(`The display on empty string option 'emptyInputBehavior' is invalid ; it should either be 'focus', 'press', 'always' or 'zero', [${options.emptyInputBehavior}] given.`);\n }\n\n if (!isInArray(options.leadingZero, ['allow', 'deny', 'keep'])) {\n throwError(`The leading zero behavior option 'leadingZero' is invalid ; it should either be 'allow', 'deny' or 'keep', [${options.leadingZero}] given.`);\n }\n\n if (!isTrueOrFalseString(options.formatOnPageLoad) && !isBoolean(options.formatOnPageLoad)) {\n throwError(`The format on initialization option 'formatOnPageLoad' is invalid ; it should be either 'false' or 'true', [${options.formatOnPageLoad}] given.`);\n }\n\n if (!isTrueOrFalseString(options.selectNumberOnly) && !isBoolean(options.selectNumberOnly)) {\n throwError(`The select number only option 'selectNumberOnly' is invalid ; it should be either 'false' or 'true', [${options.selectNumberOnly}] given.`);\n }\n\n if (!isNull(options.defaultValueOverride) && (options.defaultValueOverride !== '' && !testFloatOrIntegerAndPossibleNegativeSign.test(options.defaultValueOverride))) {\n throwError(`The unformatted default value option 'defaultValueOverride' is invalid ; it should be a string that represents a positive or negative number, [${options.defaultValueOverride}] given.`);\n }\n\n if (!isTrueOrFalseString(options.unformatOnSubmit) && !isBoolean(options.unformatOnSubmit)) {\n throwError(`The remove formatting on submit option 'unformatOnSubmit' is invalid ; it should be either 'false' or 'true', [${options.unformatOnSubmit}] given.`);\n }\n\n if (!isNull(options.outputFormat) && !isInArray(options.outputFormat, [\n 'string',\n 'number',\n '.',\n '-.',\n ',',\n '-,',\n '.-',\n ',-',\n ])) {\n throwError(`The custom locale format option 'outputFormat' is invalid ; it should either be null, 'string', 'number', '.', '-.', ',', '-,', '.-' or ',-', [${options.outputFormat}] given.`);\n }\n\n if (!isTrueOrFalseString(options.failOnUnknownOption) && !isBoolean(options.failOnUnknownOption)) {\n throwError(`The debug option 'failOnUnknownOption' is invalid ; it should be either 'false' or 'true', [${options.failOnUnknownOption}] given.`);\n }\n };\n\n $.fn.autoValidate = validate;\n\n /**\n * Return TRUE is the settings/options are valid, FALSE otherwise.\n *\n * @param {object} options\n * @returns {boolean}\n */\n areSettingsValid = function(options) {\n let isValid = true;\n try {\n validate(options);\n }\n catch (error) {\n isValid = false;\n }\n\n return isValid;\n };\n\n /**\n * Take an arabic number as a string and return a javascript number.\n * By default, this function does not try to convert the arabic decimal and thousand separator characters.\n * This returns `NaN` is the conversion is not possible.\n * Based on http://stackoverflow.com/a/17025392/2834898\n *\n * @param {string} arabicNumbers\n * @param {boolean} returnANumber If `true`, return a Number, otherwise return a String\n * @param {boolean} parseDecimalCharacter\n * @param {boolean} parseThousandSeparator\n * @returns {string|number|NaN}\n */\n function arabicToLatinNumbers(arabicNumbers, returnANumber = true, parseDecimalCharacter = false, parseThousandSeparator = false) {\n let result = arabicNumbers.toString();\n if (result === '' || result.match(/[٠١٢٣٤٥٦٧٨٩۴۵۶]/g) === null) {\n // If no Arabic/Persian numbers are found, return the numeric string directly\n return arabicNumbers;\n }\n\n if (parseDecimalCharacter) {\n result = result.replace(/٫/, '.'); // Decimal character\n }\n\n if (parseThousandSeparator) {\n result = result.replace(/٬/g, ''); // Thousand separator\n }\n\n // Replace the numbers only\n result = result.replace(/[٠١٢٣٤٥٦٧٨٩]/g, d => d.charCodeAt(0) - 1632) // Arabic numbers\n .replace(/[۰۱۲۳۴۵۶۷۸۹]/g, d => d.charCodeAt(0) - 1776); // Persian numbers\n\n // `NaN` has precedence over the string `'NaN'`\n const resultAsNumber = Number(result);\n if (isNaN(resultAsNumber)) {\n return resultAsNumber;\n }\n\n if (returnANumber) {\n result = resultAsNumber;\n }\n\n return result;\n }\n\n /**\n * Create a custom event and immediately sent it from the given element.\n * By default, if no element is given, the event is thrown from `document`.\n *\n * @param {string} eventName\n * @param {Element} element\n * @param {object} detail\n */\n function triggerEvent(eventName, element = document, detail = null) {\n let event;\n if (window.CustomEvent) {\n event = new CustomEvent(eventName, { detail, bubbles: false, cancelable: false }); // This is not supported by default by IE ; We use the polyfill for IE9 and later.\n } else {\n event = document.createEvent('CustomEvent');\n event.initCustomEvent(eventName, true, true, { detail });\n }\n\n element.dispatchEvent(event);\n }\n\n /**\n * Polyfill from https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent for obsolete browsers (IE)\n */\n (function() {\n if (typeof window.CustomEvent === 'function') {\n return false;\n }\n\n function CustomEvent(event, params) {\n params = params || { bubbles: false, cancelable: false, detail: void(0) };\n const evt = document.createEvent('CustomEvent');\n evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);\n return evt;\n }\n\n CustomEvent.prototype = window.Event.prototype;\n window.CustomEvent = CustomEvent;\n })();\n}));\n\n/**\n * This exports the interface for the autoNumeric object\n */\nexport default {\n format : autoFormat,\n unFormat: autoUnFormat,\n getDefaultConfig,\n getLanguages,\n validate, // an.validate(options) : throws if necessary\n areSettingsValid, // an.areSettingsValid(options) : return true or false //TODO Is this redundant? Should we let the developers wrap each autoNumeric.validate() calls in try/catch block? Or should we just facilitate their life by doing it already?\n\n //TODO Complete the interface with functions having the following signatures :\n //init : an.init(options, input)\n //get : an.get(input)\n //set : an.set(value, input)\n //formString : an.formString(form)\n //formArray : an.formArray(form)\n //getFormatted : an.getFormatted(input)\n //unset : an.unset(input) //to rename to 'unformat'? (and merge with autoUnFormat/unFormat?)\n //reformat : an.reformat(input) // 'reSet' is very to close to 'reset' and therefore should be renamed. We could still expose 'reSet', but add a @deprecated tag on its declaration.\n //settings : an.settings(input)\n //update : an.update(options, input)\n //wipe : an.wipe(input)\n //destroy : an.destroy(input)\n\n //raw : an.raw(input) // Return the unformatted value as a string\n //number : an.number(input) // Return the unformatted value as a number (Warning: This can lead to precision problems with big numbers)\n};\n\n\n\n// WEBPACK FOOTER //\n// ./src/autoNumeric.js","module.exports = __WEBPACK_EXTERNAL_MODULE_1__;\n\n\n//////////////////\n// WEBPACK FOOTER\n// external {\"root\":\"jQuery\",\"commonjs\":\"jquery\",\"commonjs2\":\"jquery\",\"amd\":\"jquery\"}\n// module id = 1\n// module chunks = 0"],"sourceRoot":""}