UNPKG

580 kBSource Map (JSON)View Raw
1{"version":3,"sources":["webpack:///webpack/universalModuleDefinition","webpack:///autoNumeric.min.js","webpack:///webpack/bootstrap d156ddd43b09a3d6c23d","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","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","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","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","result","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","valueOnFocus","lastVal","onEmpty","onKeydown","_updateAutoNumericHolderEventKeycode","initialValueOnKeydown","readOnly","processed","eventKeyCode","triggerEvent","_updateAutoNumericHolderProperties","_skipAlways","_processCharacterDeletion","_formatValue","throwInput","preventDefault","formatted","onKeypress","eventCharacter","isCharacterInsertionAllowed","_processCharacterInsertion","onKeyup","skip","valuePartsBeforePaste","onFocusOutAndMouseLeave","origValue","_checkIfInRangeWithOv3","_checkIfInRangeWithOv4","minTest","maxTest","trigger","groupedValue","change","onPaste","rawPastedText","clipboardData","getData","initialFormattedValue","selectionSize","isAllInputTextSelected","isPasteNegative","untranslatedPastedText","pastedText","caretPositionOnInitialTextAfterPasting","initialUnformattedNumber","isInitialValueNegative","isPasteNegativeAndInitialValueIsPositive","leftPartContainedADot","leftFormattedPart","rightFormattedPart","leftPart","rightPart","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","charCodeAt","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","_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.0\n\t * @date 2017-01-23 UTC 22: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/BobKnothe/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. `<input type=\"text\" data-currency-symbol=\" €\">`)\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 <input data-scale-divisor=\"1000\">\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};\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};\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 return event.key;\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} e\n\t * @returns {boolean}\n\t */\n\t\n\t }, {\n\t key: '_processCharacterInsertion',\n\t value: function _processCharacterInsertion(e) {\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 settingsClone.throwInput = true;\n\t\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 // 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 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 if (settings.decimalPlacesShownOnFocus) {\n\t settings.decimalPlacesOverride = settings.decimalPlacesShownOnFocus;\n\t $this.autoNumeric('set', settings.rawValue);\n\t } else if (settings.scaleDivisor) {\n\t settings.decimalPlacesOverride = settings.oDec;\n\t $this.autoNumeric('set', settings.rawValue);\n\t } else if (settings.noSeparatorOnFocus) {\n\t settings.digitGroupSeparator = '';\n\t settings.currencySymbol = '';\n\t settings.suffixText = '';\n\t $this.autoNumeric('set', settings.rawValue);\n\t } else if (result !== settings.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 <input>, 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 '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 if (skip || 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 ? +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 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 var leftPart = result.slice(0, caretPositionOnInitialTextAfterPasting);\n\t var 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 <input> 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\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: <asp:TextBox runat=\"server\" id=\"someID\" text=\"1234.56\" data-an-default=\"1234.56\">\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.scaleDivisor) && !isNull(settings.scaleDecimalPlaces)) {\n\t // Override the maximum number of decimal places with the one defined with the number of decimals to show when not in focus, if set\n\t settings.decimalPlacesOverride = settings.scaleDecimalPlaces;\n\t } else 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 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('focusout', 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('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 if (settings.decimalPlacesShownOnFocus) {\n\t var tempDecimal = settings.decimalPlacesOverride;\n\t settings.decimalPlacesOverride = 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 = toNumericValue(value, settings);\n\t value = value / settings.scaleDivisor;\n\t value = value.toString();\n\t if (settings.scaleDecimalPlaces) {\n\t var _tempDecimal = settings.decimalPlacesOverride;\n\t settings.decimalPlacesOverride = settings.scaleDecimalPlaces;\n\t value = roundValue(value, settings);\n\t hasBeenRounded = true;\n\t settings.decimalPlacesOverride = _tempDecimal;\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 settings.rawValue = cleanLeadingTrailingZeros(value.replace(settings.decimalCharacter, '.'), settings);\n\t\n\t value = modifyNegativeSignAndDecimalCharacterForFormattedValue(value, settings);\n\t value = addGroupSeparators(value, settings);\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 === '') {\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 d156ddd43b09a3d6c23d","/**\n * autoNumeric.js\n *\n * @version 2.0.0\n * @date 2017-01-23 UTC 22: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/BobKnothe/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. `<input type=\"text\" data-currency-symbol=\" €\">`)\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 <input data-scale-divisor=\"1000\">\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};\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};\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 return event.key;\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} e\n * @returns {boolean}\n */\n _processCharacterInsertion(e) {\n const settingsClone = this.settingsClone;\n let [left, right] = this._getUnformattedLeftAndRightPartAroundTheSelection();\n settingsClone.throwInput = true;\n\n // Retrieve the real character that has been entered (ie. 'a' instead of the key code)\n const eventCharacter = character(e);\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 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 if (settings.decimalPlacesShownOnFocus) {\n settings.decimalPlacesOverride = settings.decimalPlacesShownOnFocus;\n $this.autoNumeric('set', settings.rawValue);\n } else if (settings.scaleDivisor) {\n settings.decimalPlacesOverride = settings.oDec;\n $this.autoNumeric('set', settings.rawValue);\n } else if (settings.noSeparatorOnFocus) {\n settings.digitGroupSeparator = '';\n settings.currencySymbol = '';\n settings.suffixText = '';\n $this.autoNumeric('set', settings.rawValue);\n } else if (result !== settings.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 <input>, 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 '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 if (skip || 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) ? +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 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 let leftPart = result.slice(0, caretPositionOnInitialTextAfterPasting);\n let 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 <input> 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\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: <asp:TextBox runat=\"server\" id=\"someID\" text=\"1234.56\" data-an-default=\"1234.56\">\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.scaleDivisor) && !isNull(settings.scaleDecimalPlaces)) {\n // Override the maximum number of decimal places with the one defined with the number of decimals to show when not in focus, if set\n settings.decimalPlacesOverride = settings.scaleDecimalPlaces;\n }\n else 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 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('focusout', 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('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 if (settings.decimalPlacesShownOnFocus) {\n const tempDecimal = settings.decimalPlacesOverride;\n settings.decimalPlacesOverride = settings.decimalPlacesShownOnFocus;\n value = roundValue(value, settings);\n hasBeenRounded = true;\n settings.decimalPlacesOverride = tempDecimal;\n }\n\n if (settings.scaleDivisor && !settings.onOff) {\n value = toNumericValue(value, settings);\n value = value / settings.scaleDivisor;\n value = value.toString();\n if (settings.scaleDecimalPlaces) {\n const tempDecimal = settings.decimalPlacesOverride;\n settings.decimalPlacesOverride = settings.scaleDecimalPlaces;\n value = roundValue(value, settings);\n hasBeenRounded = true;\n settings.decimalPlacesOverride = tempDecimal;\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 settings.rawValue = cleanLeadingTrailingZeros(value.replace(settings.decimalCharacter, '.'), settings);\n\n value = modifyNegativeSignAndDecimalCharacterForFormattedValue(value, settings);\n value = addGroupSeparators(value, settings);\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 === '') {\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":""}
\No newline at end of file