inputmask.js 179 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266
  1. /*
  2. * Input Mask Core
  3. * http://github.com/RobinHerbots/jquery.inputmask
  4. * Copyright (c) 2010 - Robin Herbots
  5. * Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
  6. * Version: 0.0.0-dev
  7. */
  8. (function (factory) {
  9. if (typeof define === "function" && define.amd) {
  10. define(["./dependencyLibs/inputmask.dependencyLib", "./global/window", "./global/document"], factory);
  11. } else if (typeof exports === "object") {
  12. module.exports = factory(require("./dependencyLibs/inputmask.dependencyLib"), require("./global/window"), require("./global/document"));
  13. } else {
  14. window.Inputmask = factory(window.dependencyLib || jQuery, window, document);
  15. }
  16. }
  17. (function ($, window, document, undefined) {
  18. var ua = navigator.userAgent,
  19. mobile = isInputEventSupported("touchstart"), //not entirely correct but will currently do
  20. iemobile = /iemobile/i.test(ua),
  21. iphone = /iphone/i.test(ua) && !iemobile;
  22. function Inputmask(alias, options, internal) {
  23. //allow instanciating without new
  24. if (!(this instanceof Inputmask)) {
  25. return new Inputmask(alias, options, internal);
  26. }
  27. this.el = undefined;
  28. this.events = {};
  29. this.maskset = undefined;
  30. this.refreshValue = false; //indicate a refresh from the inputvalue is needed (form.reset)
  31. if (internal !== true) {
  32. //init options
  33. if ($.isPlainObject(alias)) {
  34. options = alias;
  35. } else {
  36. options = options || {};
  37. if (alias) options.alias = alias;
  38. }
  39. this.opts = $.extend(true, {}, this.defaults, options);
  40. this.noMasksCache = options && options.definitions !== undefined;
  41. this.userOptions = options || {}; //user passed options
  42. this.isRTL = this.opts.numericInput;
  43. resolveAlias(this.opts.alias, options, this.opts);
  44. }
  45. }
  46. Inputmask.prototype = {
  47. dataAttribute: "data-inputmask", //data attribute prefix used for attribute binding
  48. //options default
  49. defaults: {
  50. placeholder: "_",
  51. optionalmarker: ["[", "]"],
  52. quantifiermarker: ["{", "}"],
  53. groupmarker: ["(", ")"],
  54. alternatormarker: "|",
  55. escapeChar: "\\",
  56. mask: null, //needs tobe null instead of undefined as the extend method does not consider props with the undefined value
  57. regex: null, //regular expression as a mask
  58. oncomplete: $.noop, //executes when the mask is complete
  59. onincomplete: $.noop, //executes when the mask is incomplete and focus is lost
  60. oncleared: $.noop, //executes when the mask is cleared
  61. repeat: 0, //repetitions of the mask: * ~ forever, otherwise specify an integer
  62. greedy: false, //true: allocated buffer for the mask and repetitions - false: allocate only if needed
  63. autoUnmask: false, //automatically unmask when retrieving the value with $.fn.val or value if the browser supports __lookupGetter__ or getOwnPropertyDescriptor
  64. removeMaskOnSubmit: false, //remove the mask before submitting the form.
  65. clearMaskOnLostFocus: true,
  66. insertMode: true, //insert the input or overwrite the input
  67. clearIncomplete: false, //clear the incomplete input on blur
  68. alias: null,
  69. onKeyDown: $.noop, //callback to implement autocomplete on certain keys for example. args => event, buffer, caretPos, opts
  70. onBeforeMask: null, //executes before masking the initial value to allow preprocessing of the initial value. args => initialValue, opts => return processedValue
  71. onBeforePaste: function (pastedValue, opts) {
  72. return $.isFunction(opts.onBeforeMask) ? opts.onBeforeMask.call(this, pastedValue, opts) : pastedValue;
  73. }, //executes before masking the pasted value to allow preprocessing of the pasted value. args => pastedValue, opts => return processedValue
  74. onBeforeWrite: null, //executes before writing to the masked element. args => event, opts
  75. onUnMask: null, //executes after unmasking to allow postprocessing of the unmaskedvalue. args => maskedValue, unmaskedValue, opts
  76. showMaskOnFocus: true, //show the mask-placeholder when the input has focus
  77. showMaskOnHover: true, //show the mask-placeholder when hovering the empty input
  78. onKeyValidation: $.noop, //executes on every key-press with the result of isValid. Params: key, result, opts
  79. skipOptionalPartCharacter: " ", //a character which can be used to skip an optional part of a mask
  80. numericInput: false, //numericInput input direction style (input shifts to the left while holding the caret position)
  81. rightAlign: false, //align to the right
  82. undoOnEscape: true, //pressing escape reverts the value to the value before focus
  83. //numeric basic properties
  84. radixPoint: "", //".", // | ","
  85. _radixDance: false, //dance around the radixPoint
  86. groupSeparator: "", //",", // | "."
  87. //numeric basic properties
  88. keepStatic: null, //try to keep the mask static while typing. Decisions to alter the mask will be posponed if possible - null see auto selection for multi masks
  89. positionCaretOnTab: true, //when enabled the caret position is set after the latest valid position on TAB
  90. tabThrough: false, //allows for tabbing through the different parts of the masked field
  91. supportsInputType: ["text", "tel", "password", "search"], //list with the supported input types
  92. //specify keyCodes which should not be considered in the keypress event, otherwise the preventDefault will stop their default behavior especially in FF
  93. ignorables: [8, 9, 13, 19, 27, 33, 34, 35, 36, 37, 38, 39, 40, 45, 46, 93, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 0, 229],
  94. isComplete: null, //override for isComplete - args => buffer, opts - return true || false
  95. preValidation: null, //hook to preValidate the input. Usefull for validating regardless the definition. args => buffer, pos, char, isSelection, opts => return true/false/command object
  96. postValidation: null, //hook to postValidate the result from isValid. Usefull for validating the entry as a whole. args => buffer, currentResult, opts => return true/false/json
  97. staticDefinitionSymbol: undefined, //specify a definitionSymbol for static content, used to make matches for alternators
  98. jitMasking: false, //just in time masking ~ only mask while typing, can n (number), true or false
  99. nullable: true, //return nothing instead of the buffertemplate when the user hasn't entered anything.
  100. inputEventOnly: false, //dev option - testing inputfallback behavior
  101. noValuePatching: false, //disable value property patching
  102. positionCaretOnClick: "lvp", //none, lvp (based on the last valid position (default), radixFocus (position caret to radixpoint on initial click), select (select the whole input), ignore (ignore the click and continue the mask)
  103. casing: null, //mask-level casing. Options: null, "upper", "lower" or "title" or callback args => elem, test, pos, validPositions return charValue
  104. inputmode: "verbatim", //specify the inputmode - already in place for when browsers will support it
  105. colorMask: false, //enable css styleable mask
  106. disablePredictiveText: false, //disable Predictive Text on mobile devices
  107. importDataAttributes: true //import data-inputmask attributes
  108. },
  109. definitions: {
  110. "9": { //\uFF11-\uFF19 #1606
  111. validator: "[0-9\uFF11-\uFF19]",
  112. definitionSymbol: "*"
  113. },
  114. "a": { //\u0410-\u044F\u0401\u0451\u00C0-\u00FF\u00B5 #76
  115. validator: "[A-Za-z\u0410-\u044F\u0401\u0451\u00C0-\u00FF\u00B5]",
  116. definitionSymbol: "*"
  117. },
  118. "*": {
  119. validator: "[0-9\uFF11-\uFF19A-Za-z\u0410-\u044F\u0401\u0451\u00C0-\u00FF\u00B5]"
  120. }
  121. },
  122. aliases: {}, //aliases definitions
  123. masksCache: {},
  124. mask: function (elems) {
  125. var that = this;
  126. function importAttributeOptions(npt, opts, userOptions, dataAttribute) {
  127. if (opts.importDataAttributes === true) {
  128. var attrOptions = npt.getAttribute(dataAttribute), option, dataoptions, optionData, p;
  129. function importOption(option, optionData) {
  130. optionData = optionData !== undefined ? optionData : npt.getAttribute(dataAttribute + "-" + option);
  131. if (optionData !== null) {
  132. if (typeof optionData === "string") {
  133. if (option.indexOf("on") === 0) optionData = window[optionData]; //get function definition
  134. else if (optionData === "false") optionData = false;
  135. else if (optionData === "true") optionData = true;
  136. }
  137. userOptions[option] = optionData;
  138. }
  139. }
  140. if (attrOptions && attrOptions !== "") {
  141. attrOptions = attrOptions.replace(/'/g, '"');
  142. dataoptions = JSON.parse("{" + attrOptions + "}");
  143. }
  144. //resolve aliases
  145. if (dataoptions) { //pickup alias from dataAttribute
  146. optionData = undefined;
  147. for (p in dataoptions) {
  148. if (p.toLowerCase() === "alias") {
  149. optionData = dataoptions[p];
  150. break;
  151. }
  152. }
  153. }
  154. importOption("alias", optionData); //pickup alias from dataAttribute-alias
  155. if (userOptions.alias) {
  156. resolveAlias(userOptions.alias, userOptions, opts);
  157. }
  158. for (option in opts) {
  159. if (dataoptions) {
  160. optionData = undefined;
  161. for (p in dataoptions) {
  162. if (p.toLowerCase() === option.toLowerCase()) {
  163. optionData = dataoptions[p];
  164. break;
  165. }
  166. }
  167. }
  168. importOption(option, optionData);
  169. }
  170. }
  171. $.extend(true, opts, userOptions);
  172. //handle dir=rtl
  173. if (npt.dir === "rtl" || opts.rightAlign) {
  174. npt.style.textAlign = "right";
  175. }
  176. if (npt.dir === "rtl" || opts.numericInput) {
  177. npt.dir = "ltr";
  178. npt.removeAttribute("dir");
  179. opts.isRTL = true;
  180. }
  181. return Object.keys(userOptions).length;
  182. }
  183. if (typeof elems === "string") {
  184. elems = document.getElementById(elems) || document.querySelectorAll(elems);
  185. }
  186. elems = elems.nodeName ? [elems] : elems;
  187. $.each(elems, function (ndx, el) {
  188. var scopedOpts = $.extend(true, {}, that.opts);
  189. if (importAttributeOptions(el, scopedOpts, $.extend(true, {}, that.userOptions), that.dataAttribute)) {
  190. var maskset = generateMaskSet(scopedOpts, that.noMasksCache);
  191. if (maskset !== undefined) {
  192. if (el.inputmask !== undefined) {
  193. el.inputmask.opts.autoUnmask = true; //force autounmasking when remasking
  194. el.inputmask.remove();
  195. }
  196. //store inputmask instance on the input with element reference
  197. el.inputmask = new Inputmask(undefined, undefined, true);
  198. el.inputmask.opts = scopedOpts;
  199. el.inputmask.noMasksCache = that.noMasksCache;
  200. el.inputmask.userOptions = $.extend(true, {}, that.userOptions);
  201. el.inputmask.isRTL = scopedOpts.isRTL || scopedOpts.numericInput;
  202. el.inputmask.el = el;
  203. el.inputmask.maskset = maskset;
  204. $.data(el, "_inputmask_opts", scopedOpts);
  205. maskScope.call(el.inputmask, {
  206. "action": "mask"
  207. });
  208. }
  209. }
  210. });
  211. return elems && elems[0] ? (elems[0].inputmask || this) : this;
  212. },
  213. option: function (options, noremask) { //set extra options || retrieve value of a current option
  214. if (typeof options === "string") {
  215. return this.opts[options];
  216. } else if (typeof options === "object") {
  217. $.extend(this.userOptions, options); //user passed options
  218. //remask
  219. if (this.el && noremask !== true) {
  220. this.mask(this.el);
  221. }
  222. return this;
  223. }
  224. },
  225. unmaskedvalue: function (value) {
  226. this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache);
  227. return maskScope.call(this, {
  228. "action": "unmaskedvalue",
  229. "value": value
  230. });
  231. },
  232. remove: function () {
  233. return maskScope.call(this, {
  234. "action": "remove"
  235. });
  236. },
  237. getemptymask: function () { //return the default (empty) mask value, usefull for setting the default value in validation
  238. this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache);
  239. return maskScope.call(this, {
  240. "action": "getemptymask"
  241. });
  242. },
  243. hasMaskedValue: function () { //check wheter the returned value is masked or not; currently only works reliable when using jquery.val fn to retrieve the value
  244. return !this.opts.autoUnmask;
  245. },
  246. isComplete: function () {
  247. this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache);
  248. return maskScope.call(this, {
  249. "action": "isComplete"
  250. });
  251. },
  252. getmetadata: function () { //return mask metadata if exists
  253. this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache);
  254. return maskScope.call(this, {
  255. "action": "getmetadata"
  256. });
  257. },
  258. isValid: function (value) {
  259. this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache);
  260. return maskScope.call(this, {
  261. "action": "isValid",
  262. "value": value
  263. });
  264. },
  265. format: function (value, metadata) {
  266. this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache);
  267. return maskScope.call(this, {
  268. "action": "format",
  269. "value": value,
  270. "metadata": metadata //true/false getmetadata
  271. });
  272. },
  273. setValue: function (value) {
  274. if (this.el) {
  275. $(this.el).trigger("setvalue", [value]);
  276. }
  277. },
  278. analyseMask: function (mask, regexMask, opts) {
  279. var tokenizer = /(?:[?*+]|\{[0-9\+\*]+(?:,[0-9\+\*]*)?(?:\|[0-9\+\*]*)?\})|[^.?*+^${[]()|\\]+|./g,
  280. //Thx to https://github.com/slevithan/regex-colorizer for the regexTokenizer regex
  281. regexTokenizer = /\[\^?]?(?:[^\\\]]+|\\[\S\s]?)*]?|\\(?:0(?:[0-3][0-7]{0,2}|[4-7][0-7]?)?|[1-9][0-9]*|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}|c[A-Za-z]|[\S\s]?)|\((?:\?[:=!]?)?|(?:[?*+]|\{[0-9]+(?:,[0-9]*)?\})\??|[^.?*+^${[()|\\]+|./g,
  282. escaped = false,
  283. currentToken = new MaskToken(),
  284. match,
  285. m,
  286. openenings = [],
  287. maskTokens = [],
  288. openingToken,
  289. currentOpeningToken,
  290. alternator,
  291. lastMatch,
  292. groupToken;
  293. function MaskToken(isGroup, isOptional, isQuantifier, isAlternator) {
  294. this.matches = [];
  295. this.openGroup = isGroup || false;
  296. this.alternatorGroup = false;
  297. this.isGroup = isGroup || false;
  298. this.isOptional = isOptional || false;
  299. this.isQuantifier = isQuantifier || false;
  300. this.isAlternator = isAlternator || false;
  301. this.quantifier = {
  302. min: 1,
  303. max: 1
  304. };
  305. }
  306. //test definition => {fn: RegExp/function, optionality: bool, newBlockMarker: bool, casing: null/upper/lower, def: definitionSymbol, placeholder: placeholder, mask: real maskDefinition}
  307. function insertTestDefinition(mtoken, element, position) {
  308. position = position !== undefined ? position : mtoken.matches.length;
  309. var prevMatch = mtoken.matches[position - 1];
  310. if (regexMask) {
  311. if (element.indexOf("[") === 0 || (escaped && /\\d|\\s|\\w]/i.test(element)) || element === ".") {
  312. mtoken.matches.splice(position++, 0, {
  313. fn: new RegExp(element, opts.casing ? "i" : ""),
  314. optionality: false,
  315. newBlockMarker: prevMatch === undefined || prevMatch.def !== element,
  316. casing: null,
  317. def: element,
  318. placeholder: undefined,
  319. nativeDef: element
  320. });
  321. } else {
  322. if (escaped) element = element[element.length - 1];
  323. $.each(element.split(""), function (ndx, lmnt) {
  324. prevMatch = mtoken.matches[position - 1];
  325. mtoken.matches.splice(position++, 0, {
  326. fn: null,
  327. optionality: false,
  328. newBlockMarker: prevMatch === undefined || (prevMatch.def !== lmnt && prevMatch.fn !== null),
  329. casing: null,
  330. def: opts.staticDefinitionSymbol || lmnt,
  331. placeholder: opts.staticDefinitionSymbol !== undefined ? lmnt : undefined,
  332. nativeDef: lmnt
  333. });
  334. });
  335. }
  336. escaped = false;
  337. } else {
  338. var maskdef = (opts.definitions ? opts.definitions[element] : undefined) || Inputmask.prototype.definitions[element];
  339. if (maskdef && !escaped) {
  340. mtoken.matches.splice(position++, 0, {
  341. fn: maskdef.validator ? typeof maskdef.validator == "string" ? new RegExp(maskdef.validator, opts.casing ? "i" : "") : new function () {
  342. this.test = maskdef.validator;
  343. } : new RegExp("."),
  344. optionality: false,
  345. newBlockMarker: prevMatch === undefined || prevMatch.def !== (maskdef.definitionSymbol || element),
  346. casing: maskdef.casing,
  347. def: maskdef.definitionSymbol || element,
  348. placeholder: maskdef.placeholder,
  349. nativeDef: element
  350. });
  351. } else {
  352. mtoken.matches.splice(position++, 0, {
  353. fn: null,
  354. optionality: false,
  355. newBlockMarker: prevMatch === undefined || (prevMatch.def !== element && prevMatch.fn !== null),
  356. casing: null,
  357. def: opts.staticDefinitionSymbol || element,
  358. placeholder: opts.staticDefinitionSymbol !== undefined ? element : undefined,
  359. nativeDef: element
  360. });
  361. escaped = false;
  362. }
  363. }
  364. }
  365. function verifyGroupMarker(maskToken) {
  366. if (maskToken && maskToken.matches) {
  367. $.each(maskToken.matches, function (ndx, token) {
  368. var nextToken = maskToken.matches[ndx + 1];
  369. if ((nextToken === undefined || (nextToken.matches === undefined || nextToken.isQuantifier === false)) && token && token.isGroup) { //this is not a group but a normal mask => convert
  370. token.isGroup = false;
  371. if (!regexMask) {
  372. insertTestDefinition(token, opts.groupmarker[0], 0);
  373. if (token.openGroup !== true) {
  374. insertTestDefinition(token, opts.groupmarker[1]);
  375. }
  376. }
  377. }
  378. verifyGroupMarker(token);
  379. });
  380. }
  381. }
  382. function defaultCase() {
  383. if (openenings.length > 0) {
  384. currentOpeningToken = openenings[openenings.length - 1];
  385. insertTestDefinition(currentOpeningToken, m);
  386. if (currentOpeningToken.isAlternator) { //handle alternator a | b case
  387. alternator = openenings.pop();
  388. for (var mndx = 0; mndx < alternator.matches.length; mndx++) {
  389. if (alternator.matches[mndx].isGroup) alternator.matches[mndx].isGroup = false; //don't mark alternate groups as group
  390. }
  391. if (openenings.length > 0) {
  392. currentOpeningToken = openenings[openenings.length - 1];
  393. currentOpeningToken.matches.push(alternator);
  394. } else {
  395. currentToken.matches.push(alternator);
  396. }
  397. }
  398. } else {
  399. insertTestDefinition(currentToken, m);
  400. }
  401. }
  402. function reverseTokens(maskToken) {
  403. function reverseStatic(st) {
  404. if (st === opts.optionalmarker[0]) st = opts.optionalmarker[1];
  405. else if (st === opts.optionalmarker[1]) st = opts.optionalmarker[0];
  406. else if (st === opts.groupmarker[0]) st = opts.groupmarker[1];
  407. else if (st === opts.groupmarker[1]) st = opts.groupmarker[0];
  408. return st;
  409. }
  410. maskToken.matches = maskToken.matches.reverse();
  411. for (var match in maskToken.matches) {
  412. if (maskToken.matches.hasOwnProperty(match)) {
  413. var intMatch = parseInt(match);
  414. if (maskToken.matches[match].isQuantifier && maskToken.matches[intMatch + 1] && maskToken.matches[intMatch + 1].isGroup) { //reposition quantifier
  415. var qt = maskToken.matches[match];
  416. maskToken.matches.splice(match, 1);
  417. maskToken.matches.splice(intMatch + 1, 0, qt);
  418. }
  419. if (maskToken.matches[match].matches !== undefined) {
  420. maskToken.matches[match] = reverseTokens(maskToken.matches[match]);
  421. } else {
  422. maskToken.matches[match] = reverseStatic(maskToken.matches[match]);
  423. }
  424. }
  425. }
  426. return maskToken;
  427. }
  428. function groupify(matches) {
  429. var groupToken = new MaskToken(true);
  430. groupToken.openGroup = false;
  431. groupToken.matches = matches;
  432. return groupToken;
  433. }
  434. if (regexMask) {
  435. opts.optionalmarker[0] = undefined;
  436. opts.optionalmarker[1] = undefined;
  437. }
  438. while (match = regexMask ? regexTokenizer.exec(mask) : tokenizer.exec(mask)) {
  439. m = match[0];
  440. if (regexMask) {
  441. switch (m.charAt(0)) {
  442. //Quantifier
  443. case "?":
  444. m = "{0,1}";
  445. break;
  446. case "+":
  447. case "*":
  448. m = "{" + m + "}";
  449. break;
  450. }
  451. }
  452. if (escaped) {
  453. defaultCase();
  454. continue;
  455. }
  456. switch (m.charAt(0)) {
  457. case opts.escapeChar:
  458. escaped = true;
  459. if (regexMask) {
  460. defaultCase();
  461. }
  462. break;
  463. case opts.optionalmarker[1]:
  464. // optional closing
  465. case opts.groupmarker[1]:
  466. // Group closing
  467. openingToken = openenings.pop();
  468. openingToken.openGroup = false; //mark group as complete
  469. if (openingToken !== undefined) {
  470. if (openenings.length > 0) {
  471. currentOpeningToken = openenings[openenings.length - 1];
  472. currentOpeningToken.matches.push(openingToken);
  473. if (currentOpeningToken.isAlternator) { //handle alternator (a) | (b) case
  474. alternator = openenings.pop();
  475. for (var mndx = 0; mndx < alternator.matches.length; mndx++) {
  476. alternator.matches[mndx].isGroup = false; //don't mark alternate groups as group
  477. alternator.matches[mndx].alternatorGroup = false;
  478. }
  479. if (openenings.length > 0) {
  480. currentOpeningToken = openenings[openenings.length - 1];
  481. currentOpeningToken.matches.push(alternator);
  482. } else {
  483. currentToken.matches.push(alternator);
  484. }
  485. }
  486. } else {
  487. currentToken.matches.push(openingToken);
  488. }
  489. } else defaultCase();
  490. break;
  491. case opts.optionalmarker[0]:
  492. // optional opening
  493. openenings.push(new MaskToken(false, true));
  494. break;
  495. case opts.groupmarker[0]:
  496. // Group opening
  497. openenings.push(new MaskToken(true));
  498. break;
  499. case opts.quantifiermarker[0]:
  500. //Quantifier
  501. var quantifier = new MaskToken(false, false, true);
  502. m = m.replace(/[{}]/g, "");
  503. var mqj = m.split("|"),
  504. mq = mqj[0].split(","),
  505. mq0 = isNaN(mq[0]) ? mq[0] : parseInt(mq[0]),
  506. mq1 = mq.length === 1 ? mq0 : (isNaN(mq[1]) ? mq[1] : parseInt(mq[1]));
  507. if (mq1 === "*" || mq1 === "+") {
  508. mq0 = mq1 === "*" ? 0 : 1;
  509. }
  510. quantifier.quantifier = {
  511. min: mq0,
  512. max: mq1,
  513. jit: mqj[1]
  514. };
  515. var matches = openenings.length > 0 ? openenings[openenings.length - 1].matches : currentToken.matches;
  516. match = matches.pop();
  517. if (match.isAlternator) { //handle quantifier in an alternation [0-9]{2}|[0-9]{3}
  518. matches.push(match); //push back alternator
  519. matches = match.matches; //remap target matches
  520. var groupToken = new MaskToken(true);
  521. var tmpMatch = matches.pop();
  522. matches.push(groupToken); //push the group
  523. matches = groupToken.matches;
  524. match = tmpMatch;
  525. }
  526. if (!match.isGroup) {
  527. // if (regexMask && match.fn === null) { //why is this needed???
  528. // if (match.def === ".") match.fn = new RegExp(match.def, opts.casing ? "i" : "");
  529. // }
  530. match = groupify([match]);
  531. }
  532. matches.push(match);
  533. matches.push(quantifier);
  534. break;
  535. case opts.alternatormarker:
  536. function groupQuantifier(matches) {
  537. var lastMatch = matches.pop();
  538. if (lastMatch.isQuantifier) {
  539. lastMatch = groupify([matches.pop(), lastMatch]);
  540. }
  541. return lastMatch;
  542. }
  543. if (openenings.length > 0) {
  544. currentOpeningToken = openenings[openenings.length - 1];
  545. var subToken = currentOpeningToken.matches[currentOpeningToken.matches.length - 1];
  546. if (currentOpeningToken.openGroup && //regexp alt syntax
  547. (subToken.matches === undefined || (subToken.isGroup === false && subToken.isAlternator === false))) { //alternations within group
  548. lastMatch = openenings.pop();
  549. } else {
  550. lastMatch = groupQuantifier(currentOpeningToken.matches);
  551. }
  552. } else {
  553. lastMatch = groupQuantifier(currentToken.matches);
  554. }
  555. if (lastMatch.isAlternator) {
  556. openenings.push(lastMatch);
  557. } else {
  558. if (lastMatch.alternatorGroup) {
  559. alternator = openenings.pop();
  560. lastMatch.alternatorGroup = false;
  561. } else {
  562. alternator = new MaskToken(false, false, false, true);
  563. }
  564. alternator.matches.push(lastMatch);
  565. openenings.push(alternator);
  566. if (lastMatch.openGroup) { //regexp alt syntax
  567. lastMatch.openGroup = false;
  568. var alternatorGroup = new MaskToken(true);
  569. alternatorGroup.alternatorGroup = true;
  570. openenings.push(alternatorGroup);
  571. }
  572. }
  573. break;
  574. default:
  575. defaultCase();
  576. }
  577. }
  578. while (openenings.length > 0) {
  579. openingToken = openenings.pop();
  580. currentToken.matches.push(openingToken);
  581. }
  582. if (currentToken.matches.length > 0) {
  583. verifyGroupMarker(currentToken);
  584. maskTokens.push(currentToken);
  585. }
  586. if (opts.numericInput || opts.isRTL) {
  587. reverseTokens(maskTokens[0]);
  588. }
  589. // console.log(JSON.stringify(maskTokens));
  590. return maskTokens;
  591. }
  592. };
  593. //apply defaults, definitions, aliases
  594. Inputmask.extendDefaults = function (options) {
  595. $.extend(true, Inputmask.prototype.defaults, options);
  596. };
  597. Inputmask.extendDefinitions = function (definition) {
  598. $.extend(true, Inputmask.prototype.definitions, definition);
  599. };
  600. Inputmask.extendAliases = function (alias) {
  601. $.extend(true, Inputmask.prototype.aliases, alias);
  602. };
  603. //static fn on inputmask
  604. Inputmask.format = function (value, options, metadata) {
  605. return Inputmask(options).format(value, metadata);
  606. };
  607. Inputmask.unmask = function (value, options) {
  608. return Inputmask(options).unmaskedvalue(value);
  609. };
  610. Inputmask.isValid = function (value, options) {
  611. return Inputmask(options).isValid(value);
  612. };
  613. Inputmask.remove = function (elems) {
  614. if (typeof elems === "string") {
  615. elems = document.getElementById(elems) || document.querySelectorAll(elems);
  616. }
  617. elems = elems.nodeName ? [elems] : elems;
  618. $.each(elems, function (ndx, el) {
  619. if (el.inputmask) el.inputmask.remove();
  620. });
  621. };
  622. Inputmask.setValue = function (elems, value) {
  623. if (typeof elems === "string") {
  624. elems = document.getElementById(elems) || document.querySelectorAll(elems);
  625. }
  626. elems = elems.nodeName ? [elems] : elems;
  627. $.each(elems, function (ndx, el) {
  628. if (el.inputmask) el.inputmask.setValue(value); else $(el).trigger("setvalue", [value]);
  629. });
  630. };
  631. Inputmask.escapeRegex = function (str) {
  632. var specials = ["/", ".", "*", "+", "?", "|", "(", ")", "[", "]", "{", "}", "\\", "$", "^"];
  633. return str.replace(new RegExp("(\\" + specials.join("|\\") + ")", "gim"), "\\$1");
  634. };
  635. Inputmask.keyCode = {
  636. BACKSPACE: 8,
  637. BACKSPACE_SAFARI: 127,
  638. DELETE: 46,
  639. DOWN: 40,
  640. END: 35,
  641. ENTER: 13,
  642. ESCAPE: 27,
  643. HOME: 36,
  644. INSERT: 45,
  645. LEFT: 37,
  646. PAGE_DOWN: 34,
  647. PAGE_UP: 33,
  648. RIGHT: 39,
  649. SPACE: 32,
  650. TAB: 9,
  651. UP: 38,
  652. X: 88,
  653. CONTROL: 17
  654. };
  655. function resolveAlias(aliasStr, options, opts) {
  656. var aliasDefinition = Inputmask.prototype.aliases[aliasStr];
  657. if (aliasDefinition) {
  658. if (aliasDefinition.alias) resolveAlias(aliasDefinition.alias, undefined, opts); //alias is another alias
  659. $.extend(true, opts, aliasDefinition); //merge alias definition in the options
  660. $.extend(true, opts, options); //reapply extra given options
  661. return true;
  662. } else //alias not found - try as mask
  663. if (opts.mask === null) {
  664. opts.mask = aliasStr;
  665. }
  666. return false;
  667. }
  668. function generateMaskSet(opts, nocache) {
  669. function generateMask(mask, metadata, opts) {
  670. var regexMask = false;
  671. if (mask === null || mask === "") {
  672. regexMask = opts.regex !== null;
  673. if (regexMask) {
  674. mask = opts.regex;
  675. mask = mask.replace(/^(\^)(.*)(\$)$/, "$2");
  676. } else {
  677. regexMask = true;
  678. mask = ".*";
  679. }
  680. }
  681. if (mask.length === 1 && opts.greedy === false && opts.repeat !== 0) {
  682. opts.placeholder = "";
  683. } //hide placeholder with single non-greedy mask
  684. if (opts.repeat > 0 || opts.repeat === "*" || opts.repeat === "+") {
  685. var repeatStart = opts.repeat === "*" ? 0 : (opts.repeat === "+" ? 1 : opts.repeat);
  686. mask = opts.groupmarker[0] + mask + opts.groupmarker[1] + opts.quantifiermarker[0] + repeatStart + "," + opts.repeat + opts.quantifiermarker[1];
  687. }
  688. // console.log(mask);
  689. var masksetDefinition,
  690. maskdefKey = regexMask ? "regex_" + opts.regex : (opts.numericInput ? mask.split("").reverse().join("") : mask);
  691. if (Inputmask.prototype.masksCache[maskdefKey] === undefined || nocache === true) {
  692. masksetDefinition = {
  693. "mask": mask,
  694. "maskToken": Inputmask.prototype.analyseMask(mask, regexMask, opts),
  695. "validPositions": {},
  696. "_buffer": undefined,
  697. "buffer": undefined,
  698. "tests": {},
  699. "excludes": {}, //excluded alternations
  700. "metadata": metadata,
  701. maskLength: undefined
  702. };
  703. if (nocache !== true) {
  704. Inputmask.prototype.masksCache[maskdefKey] = masksetDefinition;
  705. masksetDefinition = $.extend(true, {}, Inputmask.prototype.masksCache[maskdefKey]);
  706. }
  707. } else masksetDefinition = $.extend(true, {}, Inputmask.prototype.masksCache[maskdefKey]);
  708. return masksetDefinition;
  709. }
  710. var ms;
  711. if ($.isFunction(opts.mask)) { //allow mask to be a preprocessing fn - should return a valid mask
  712. opts.mask = opts.mask(opts);
  713. }
  714. if ($.isArray(opts.mask)) {
  715. if (opts.mask.length > 1) {
  716. if (opts.keepStatic === null) { //enable by default when passing multiple masks when the option is not explicitly specified
  717. opts.keepStatic = "auto";
  718. for (var i = 0; i < opts.mask.length; i++) {
  719. if (opts.mask[i].charAt(0) !== opts.mask[0].charAt(0)) {
  720. opts.keepStatic = true;
  721. break;
  722. }
  723. }
  724. }
  725. var altMask = opts.groupmarker[0];
  726. $.each(opts.isRTL ? opts.mask.reverse() : opts.mask, function (ndx, msk) {
  727. if (altMask.length > 1) {
  728. altMask += opts.groupmarker[1] + opts.alternatormarker + opts.groupmarker[0];
  729. }
  730. if (msk.mask !== undefined && !$.isFunction(msk.mask)) {
  731. altMask += msk.mask;
  732. } else {
  733. altMask += msk;
  734. }
  735. });
  736. altMask += opts.groupmarker[1];
  737. // console.log(altMask);
  738. return generateMask(altMask, opts.mask, opts);
  739. } else opts.mask = opts.mask.pop();
  740. }
  741. if (opts.mask && opts.mask.mask !== undefined && !$.isFunction(opts.mask.mask)) {
  742. ms = generateMask(opts.mask.mask, opts.mask, opts);
  743. } else {
  744. ms = generateMask(opts.mask, opts.mask, opts);
  745. }
  746. return ms;
  747. };
  748. function isInputEventSupported(eventName) {
  749. var el = document.createElement("input"),
  750. evName = "on" + eventName,
  751. isSupported = (evName in el);
  752. if (!isSupported) {
  753. el.setAttribute(evName, "return;");
  754. isSupported = typeof el[evName] === "function";
  755. }
  756. el = null;
  757. return isSupported;
  758. }
  759. //masking scope
  760. //actionObj definition see below
  761. function maskScope(actionObj, maskset, opts) {
  762. maskset = maskset || this.maskset;
  763. opts = opts || this.opts;
  764. var inputmask = this,
  765. el = this.el,
  766. isRTL = this.isRTL,
  767. undoValue,
  768. $el,
  769. skipKeyPressEvent = false, //Safari 5.1.x - modal dialog fires keypress twice workaround
  770. skipInputEvent = false, //skip when triggered from within inputmask
  771. ignorable = false,
  772. maxLength,
  773. mouseEnter = false,
  774. colorMask,
  775. trackCaret = false;
  776. //maskset helperfunctions
  777. function getMaskTemplate(baseOnInput, minimalPos, includeMode, noJit, clearOptionalTail) {
  778. //includeMode true => input, undefined => placeholder, false => mask
  779. var greedy = opts.greedy;
  780. if (clearOptionalTail) opts.greedy = false;
  781. minimalPos = minimalPos || 0;
  782. var maskTemplate = [],
  783. ndxIntlzr, pos = 0,
  784. test, testPos, lvp = getLastValidPosition();
  785. do {
  786. if (baseOnInput === true && getMaskSet().validPositions[pos]) {
  787. testPos = (clearOptionalTail && getMaskSet().validPositions[pos].match.optionality === true && (getMaskSet().validPositions[pos].generatedInput === true || getMaskSet().validPositions[pos].input == opts.skipOptionalPartCharacter) && getMaskSet().validPositions[pos + 1] === undefined)
  788. ? determineTestTemplate(pos, getTests(pos, ndxIntlzr, pos - 1))
  789. : getMaskSet().validPositions[pos];
  790. test = testPos.match;
  791. ndxIntlzr = testPos.locator.slice();
  792. maskTemplate.push(includeMode === true ? testPos.input : includeMode === false ? test.nativeDef : getPlaceholder(pos, test));
  793. } else {
  794. testPos = getTestTemplate(pos, ndxIntlzr, pos - 1);
  795. test = testPos.match;
  796. ndxIntlzr = testPos.locator.slice();
  797. var jitMasking = noJit === true ? false : (opts.jitMasking !== false ? opts.jitMasking : test.jit);
  798. if (jitMasking === false || jitMasking === undefined || pos < lvp || (typeof jitMasking === "number" && isFinite(jitMasking) && jitMasking > pos)) {
  799. maskTemplate.push(includeMode === false ? test.nativeDef : getPlaceholder(pos, test));
  800. }
  801. }
  802. if (opts.keepStatic === "auto") {
  803. if (test.newBlockMarker && test.fn !== null) {
  804. opts.keepStatic = pos - 1;
  805. }
  806. }
  807. pos++;
  808. } while ((maxLength === undefined || pos < maxLength) && (test.fn !== null || test.def !== "") || minimalPos > pos);
  809. if (maskTemplate[maskTemplate.length - 1] === "") {
  810. maskTemplate.pop(); //drop the last one which is empty
  811. }
  812. if (includeMode !== false || //do not alter the masklength when just retrieving the maskdefinition
  813. getMaskSet().maskLength === undefined) //just make sure the maskLength gets initialized in all cases (needed for isValid)
  814. getMaskSet().maskLength = pos - 1;
  815. opts.greedy = greedy;
  816. return maskTemplate;
  817. }
  818. function getMaskSet() {
  819. return maskset;
  820. }
  821. function resetMaskSet(soft) {
  822. var maskset = getMaskSet();
  823. maskset.buffer = undefined;
  824. if (soft !== true) {
  825. // maskset._buffer = undefined;
  826. maskset.validPositions = {};
  827. maskset.p = 0;
  828. }
  829. }
  830. function getLastValidPosition(closestTo, strict, validPositions) {
  831. var before = -1,
  832. after = -1,
  833. valids = validPositions || getMaskSet().validPositions; //for use in valhook ~ context switch
  834. if (closestTo === undefined) closestTo = -1;
  835. for (var posNdx in valids) {
  836. var psNdx = parseInt(posNdx);
  837. if (valids[psNdx] && (strict || valids[psNdx].generatedInput !== true)) {
  838. if (psNdx <= closestTo) before = psNdx;
  839. if (psNdx >= closestTo) after = psNdx;
  840. }
  841. }
  842. return (before === -1 || before == closestTo) ? after : after == -1 ? before : (closestTo - before) < (after - closestTo) ? before : after;
  843. }
  844. function determineTestTemplate(pos, tests, guessNextBest) {
  845. pos = pos > 0 ? pos - 1 : 0;
  846. var testPos,
  847. altTest = getTest(pos, tests),
  848. altArr = (altTest.alternation !== undefined) ? altTest.locator[altTest.alternation].toString().split(",") : [];
  849. for (var ndx = 0; ndx < tests.length; ndx++) {
  850. testPos = tests[ndx];
  851. if (testPos.match &&
  852. (((opts.greedy && testPos.match.optionalQuantifier !== true) || (testPos.match.optionality === false || testPos.match.newBlockMarker === false) && testPos.match.optionalQuantifier !== true) &&
  853. ((altTest.alternation === undefined || altTest.alternation !== testPos.alternation) ||
  854. (testPos.locator[altTest.alternation] !== undefined && checkAlternationMatch(testPos.locator[altTest.alternation].toString().split(","), altArr))))) {
  855. if (guessNextBest !== true || (testPos.match.fn === null && !/[0-9a-bA-Z]/.test(testPos.match.def))) {
  856. break;
  857. }
  858. }
  859. }
  860. var controlPos = determineTestTemplate2(pos, tests, guessNextBest);
  861. if (controlPos != testPos) {
  862. // debugger;
  863. console.log(pos + " 1) " + JSON.stringify(testPos));
  864. console.log(pos + " 2) " + JSON.stringify(controlPos));
  865. determineTestTemplate2(pos, tests, guessNextBest);
  866. }
  867. return testPos;
  868. }
  869. function getDecisionTaker(tst) {
  870. var decisionTaker = tst.locator[tst.alternation];
  871. if (typeof decisionTaker == "string" && decisionTaker.length > 0) { //no decision taken ~ take first one as decider
  872. decisionTaker = decisionTaker.split(",")[0];
  873. }
  874. return decisionTaker !== undefined ? decisionTaker.toString() : "";
  875. }
  876. function getLocator(tst, align) { //need to align the locators to be correct
  877. var locator = (tst.alternation != undefined ? tst.mloc[getDecisionTaker(tst)] : tst.locator).join("");
  878. if (locator !== "") while (locator.length < align) locator += "0";
  879. return locator;
  880. }
  881. function determineTestTemplate2(pos, tests, guessNextBest) {
  882. pos = pos > 0 ? pos - 1 : 0;
  883. var altTest = getTest(pos), targetLocator = getLocator(altTest), tstLocator, closest, bestMatch;
  884. for (var ndx = 0; ndx < tests.length; ndx++) { //find best matching
  885. var tst = tests[ndx];
  886. tstLocator = getLocator(tst, targetLocator.length);
  887. var distance = Math.abs(tstLocator - targetLocator);
  888. if (closest === undefined
  889. || (tstLocator !== "" && distance < closest)
  890. || (bestMatch && bestMatch.match.optionality && (!tst.match.optionality || !tst.match.newBlockMarker))
  891. || (bestMatch && bestMatch.match.optionalQuantifier && !tst.match.optionalQuantifier)) {
  892. closest = distance;
  893. bestMatch = tst;
  894. }
  895. }
  896. return bestMatch;
  897. }
  898. function getTestTemplate(pos, ndxIntlzr, tstPs) {
  899. return getMaskSet().validPositions[pos] || determineTestTemplate(pos, getTests(pos, ndxIntlzr ? ndxIntlzr.slice() : ndxIntlzr, tstPs));
  900. }
  901. function getTest(pos, tests) {
  902. if (getMaskSet().validPositions[pos]) {
  903. return getMaskSet().validPositions[pos];
  904. }
  905. return (tests || getTests(pos))[0];
  906. }
  907. function positionCanMatchDefinition(pos, def) {
  908. var valid = false,
  909. tests = getTests(pos);
  910. for (var tndx = 0; tndx < tests.length; tndx++) {
  911. if (tests[tndx].match && tests[tndx].match.def === def) {
  912. valid = true;
  913. break;
  914. }
  915. }
  916. return valid;
  917. }
  918. function getTests(pos, ndxIntlzr, tstPs) {
  919. var maskTokens = getMaskSet().maskToken,
  920. testPos = ndxIntlzr ? tstPs : 0,
  921. ndxInitializer = ndxIntlzr ? ndxIntlzr.slice() : [0],
  922. matches = [],
  923. insertStop = false,
  924. latestMatch,
  925. cacheDependency = ndxIntlzr ? ndxIntlzr.join("") : "";
  926. function resolveTestFromToken(maskToken, ndxInitializer, loopNdx, quantifierRecurse) { //ndxInitializer contains a set of indexes to speedup searches in the mtokens
  927. function handleMatch(match, loopNdx, quantifierRecurse) {
  928. function isFirstMatch(latestMatch, tokenGroup) {
  929. var firstMatch = $.inArray(latestMatch, tokenGroup.matches) === 0;
  930. if (!firstMatch) {
  931. $.each(tokenGroup.matches, function (ndx, match) {
  932. if (match.isQuantifier === true) firstMatch = isFirstMatch(latestMatch, tokenGroup.matches[ndx - 1]);
  933. else if (match.isOptional === true) firstMatch = isFirstMatch(latestMatch, match);
  934. else if (match.isAlternate === true) firstMatch = isFirstMatch(latestMatch, match);
  935. if (firstMatch) return false;
  936. });
  937. }
  938. return firstMatch;
  939. }
  940. function resolveNdxInitializer(pos, alternateNdx, targetAlternation) {
  941. var bestMatch, indexPos;
  942. if (getMaskSet().tests[pos] || getMaskSet().validPositions[pos]) {
  943. $.each(getMaskSet().tests[pos] || [getMaskSet().validPositions[pos]], function (ndx, lmnt) {
  944. if (lmnt.mloc[alternateNdx]) {
  945. bestMatch = lmnt;
  946. return false; //break
  947. }
  948. var alternation = targetAlternation !== undefined ? targetAlternation : lmnt.alternation,
  949. ndxPos = lmnt.locator[alternation] !== undefined ? lmnt.locator[alternation].toString().indexOf(alternateNdx) : -1;
  950. if ((indexPos === undefined || ndxPos < indexPos) && ndxPos !== -1) {
  951. bestMatch = lmnt;
  952. indexPos = ndxPos;
  953. }
  954. });
  955. }
  956. if (bestMatch) {
  957. var bestMatchAltIndex = bestMatch.locator[bestMatch.alternation];
  958. var locator = bestMatch.mloc[alternateNdx] || bestMatch.mloc[bestMatchAltIndex] || bestMatch.locator;
  959. return locator.slice((targetAlternation !== undefined ? targetAlternation : bestMatch.alternation) + 1);
  960. } else {
  961. return targetAlternation !== undefined ? resolveNdxInitializer(pos, alternateNdx) : undefined;
  962. }
  963. }
  964. function isSubsetOf(source, target) {
  965. function expand(pattern) {
  966. var expanded = [], start, end;
  967. for (var i = 0, l = pattern.length; i < l; i++) {
  968. if (pattern.charAt(i) === "-") {
  969. end = pattern.charCodeAt(i + 1);
  970. while (++start < end) expanded.push(String.fromCharCode(start));
  971. } else {
  972. start = pattern.charCodeAt(i);
  973. expanded.push(pattern.charAt(i));
  974. }
  975. }
  976. return expanded.join("");
  977. }
  978. if (opts.regex && source.match.fn !== null && target.match.fn !== null) { //is regex a subset
  979. return expand(target.match.def.replace(/[\[\]]/g, "")).indexOf(expand(source.match.def.replace(/[\[\]]/g, ""))) !== -1;
  980. }
  981. return source.match.def === target.match.nativeDef;
  982. }
  983. function staticCanMatchDefinition(source, target) {
  984. return source.match.fn === null && target.match.fn !== null ? target.match.fn.test(source.match.def, getMaskSet(), pos, false, opts, false) : false;
  985. }
  986. //mergelocators for retrieving the correct locator match when merging
  987. function setMergeLocators(targetMatch, altMatch) {
  988. if (altMatch === undefined || (targetMatch.alternation === altMatch.alternation &&
  989. targetMatch.locator[targetMatch.alternation].toString().indexOf(altMatch.locator[altMatch.alternation]) === -1)) {
  990. targetMatch.mloc = targetMatch.mloc || {};
  991. var locNdx = targetMatch.locator[targetMatch.alternation];
  992. if (locNdx === undefined) targetMatch.alternation = undefined;
  993. else {
  994. if (typeof locNdx === "string") locNdx = locNdx.split(",")[0];
  995. if (targetMatch.mloc[locNdx] === undefined) targetMatch.mloc[locNdx] = targetMatch.locator.slice();
  996. if (altMatch !== undefined) {
  997. for (var ndx in altMatch.mloc) {
  998. if (typeof ndx === "string") ndx = ndx.split(",")[0];
  999. if (targetMatch.mloc[ndx] === undefined) targetMatch.mloc[ndx] = altMatch.mloc[ndx];
  1000. }
  1001. targetMatch.locator[targetMatch.alternation] = Object.keys(targetMatch.mloc).join(",");
  1002. }
  1003. return true;
  1004. }
  1005. }
  1006. return false;
  1007. }
  1008. if (testPos > 5000) {
  1009. throw "Inputmask: There is probably an error in your mask definition or in the code. Create an issue on github with an example of the mask you are using. " + getMaskSet().mask;
  1010. }
  1011. if (testPos === pos && match.matches === undefined) {
  1012. matches.push({
  1013. "match": match,
  1014. "locator": loopNdx.reverse(),
  1015. "cd": cacheDependency,
  1016. "mloc": {}
  1017. });
  1018. return true;
  1019. } else if (match.matches !== undefined) {
  1020. if (match.isGroup && quantifierRecurse !== match) { //when a group pass along to the quantifier
  1021. match = handleMatch(maskToken.matches[$.inArray(match, maskToken.matches) + 1], loopNdx);
  1022. if (match) return true;
  1023. } else if (match.isOptional) {
  1024. var optionalToken = match;
  1025. match = resolveTestFromToken(match, ndxInitializer, loopNdx, quantifierRecurse);
  1026. if (match) {
  1027. //mark optionality in matches
  1028. $.each(matches, function (ndx, mtch) {
  1029. mtch.match.optionality = true;
  1030. });
  1031. latestMatch = matches[matches.length - 1].match;
  1032. if (quantifierRecurse === undefined && isFirstMatch(latestMatch, optionalToken)) { //prevent loop see #698
  1033. insertStop = true; //insert a stop
  1034. testPos = pos; //match the position after the group
  1035. } else return true;
  1036. }
  1037. } else if (match.isAlternator) {
  1038. var alternateToken = match,
  1039. malternateMatches = [],
  1040. maltMatches,
  1041. currentMatches = matches.slice(),
  1042. loopNdxCnt = loopNdx.length;
  1043. var altIndex = ndxInitializer.length > 0 ? ndxInitializer.shift() : -1;
  1044. if (altIndex === -1 || typeof altIndex === "string") {
  1045. var currentPos = testPos,
  1046. ndxInitializerClone = ndxInitializer.slice(),
  1047. altIndexArr = [],
  1048. amndx;
  1049. if (typeof altIndex == "string") {
  1050. altIndexArr = altIndex.split(",");
  1051. } else {
  1052. for (amndx = 0; amndx < alternateToken.matches.length; amndx++) {
  1053. altIndexArr.push(amndx.toString());
  1054. }
  1055. }
  1056. if (getMaskSet().excludes[pos]) {
  1057. var altIndexArrClone = altIndexArr.slice();
  1058. for (var i = 0, el = getMaskSet().excludes[pos].length; i < el; i++) {
  1059. altIndexArr.splice(altIndexArr.indexOf(getMaskSet().excludes[pos][i].toString()), 1);
  1060. }
  1061. if (altIndexArr.length === 0) { //fully alternated => reset
  1062. getMaskSet().excludes[pos] = undefined;
  1063. altIndexArr = altIndexArrClone;
  1064. }
  1065. }
  1066. if (opts.keepStatic === true || (isFinite(parseInt(opts.keepStatic)) && currentPos >= opts.keepStatic)) altIndexArr = altIndexArr.slice(0, 1);
  1067. var unMatchedAlternation = false;
  1068. for (var ndx = 0; ndx < altIndexArr.length; ndx++) {
  1069. amndx = parseInt(altIndexArr[ndx]);
  1070. matches = [];
  1071. //set the correct ndxInitializer
  1072. ndxInitializer = typeof altIndex === "string" ? resolveNdxInitializer(testPos, amndx, loopNdxCnt) || ndxInitializerClone.slice() : ndxInitializerClone.slice();
  1073. if (alternateToken.matches[amndx] && handleMatch(alternateToken.matches[amndx], [amndx].concat(loopNdx), quantifierRecurse))
  1074. match = true;
  1075. else if (ndx === 0) {
  1076. unMatchedAlternation = true;
  1077. }
  1078. maltMatches = matches.slice();
  1079. testPos = currentPos;
  1080. matches = [];
  1081. //fuzzy merge matches
  1082. for (var ndx1 = 0; ndx1 < maltMatches.length; ndx1++) {
  1083. var altMatch = maltMatches[ndx1],
  1084. dropMatch = false;
  1085. altMatch.match.jit = altMatch.match.jit || unMatchedAlternation; //mark jit when there are unmatched alternations ex: mask: "(a|aa)"
  1086. altMatch.alternation = altMatch.alternation || loopNdxCnt;
  1087. setMergeLocators(altMatch);
  1088. for (var ndx2 = 0; ndx2 < malternateMatches.length; ndx2++) {
  1089. var altMatch2 = malternateMatches[ndx2];
  1090. if (typeof altIndex !== "string" || (altMatch.alternation !== undefined && $.inArray(altMatch.locator[altMatch.alternation].toString(), altIndexArr) !== -1)) {
  1091. if (altMatch.match.nativeDef === altMatch2.match.nativeDef) {
  1092. dropMatch = true;
  1093. setMergeLocators(altMatch2, altMatch);
  1094. break;
  1095. } else if (isSubsetOf(altMatch, altMatch2)) {
  1096. if (setMergeLocators(altMatch, altMatch2)) {
  1097. dropMatch = true;
  1098. malternateMatches.splice(malternateMatches.indexOf(altMatch2), 0, altMatch);
  1099. }
  1100. break;
  1101. } else if (isSubsetOf(altMatch2, altMatch)) {
  1102. setMergeLocators(altMatch2, altMatch);
  1103. break;
  1104. } else if (staticCanMatchDefinition(altMatch, altMatch2)) {
  1105. if (setMergeLocators(altMatch, altMatch2)) {
  1106. //insert match above general match
  1107. dropMatch = true;
  1108. malternateMatches.splice(malternateMatches.indexOf(altMatch2), 0, altMatch);
  1109. }
  1110. break;
  1111. }
  1112. }
  1113. }
  1114. if (!dropMatch) {
  1115. malternateMatches.push(altMatch);
  1116. }
  1117. }
  1118. }
  1119. matches = currentMatches.concat(malternateMatches);
  1120. testPos = pos;
  1121. insertStop = matches.length > 0; //insert a stopelemnt when there is an alternate - needed for non-greedy option
  1122. match = malternateMatches.length > 0; //set correct match state
  1123. //cloneback
  1124. ndxInitializer = ndxInitializerClone.slice();
  1125. } else match = handleMatch(alternateToken.matches[altIndex] || maskToken.matches[altIndex], [altIndex].concat(loopNdx), quantifierRecurse);
  1126. if (match) return true;
  1127. } else if (match.isQuantifier && quantifierRecurse !== maskToken.matches[$.inArray(match, maskToken.matches) - 1]) {
  1128. var qt = match;
  1129. for (var qndx = (ndxInitializer.length > 0) ? ndxInitializer.shift() : 0;
  1130. (qndx < (isNaN(qt.quantifier.max) ? qndx + 1 : qt.quantifier.max)) && testPos <= pos; qndx++) {
  1131. var tokenGroup = maskToken.matches[$.inArray(qt, maskToken.matches) - 1];
  1132. match = handleMatch(tokenGroup, [qndx].concat(loopNdx), tokenGroup); //set the tokenGroup as quantifierRecurse marker
  1133. if (match) {
  1134. //get latest match
  1135. latestMatch = matches[matches.length - 1].match;
  1136. latestMatch.optionalQuantifier = qndx > (qt.quantifier.min - 1);
  1137. latestMatch.jit = qndx + tokenGroup.matches.indexOf(latestMatch) >= qt.quantifier.jit;
  1138. if (isFirstMatch(latestMatch, tokenGroup) && qndx > (qt.quantifier.min - 1)) {
  1139. insertStop = true;
  1140. testPos = pos; //match the position after the group
  1141. break; //stop quantifierloop && search for next possible match
  1142. }
  1143. if (qt.quantifier.jit !== undefined && isNaN(qt.quantifier.max) && latestMatch.optionalQuantifier && getMaskSet().validPositions[pos - 1] === undefined) {
  1144. matches.pop()
  1145. insertStop = true;
  1146. testPos = pos; //match the position after the group
  1147. cacheDependency = undefined; //enforce revalidation when requested
  1148. break; //stop quantifierloop && search for next possible match
  1149. }
  1150. return true;
  1151. }
  1152. }
  1153. } else {
  1154. match = resolveTestFromToken(match, ndxInitializer, loopNdx, quantifierRecurse);
  1155. if (match) return true;
  1156. }
  1157. } else {
  1158. testPos++;
  1159. }
  1160. }
  1161. for (var tndx = (ndxInitializer.length > 0 ? ndxInitializer.shift() : 0); tndx < maskToken.matches.length; tndx++) {
  1162. if (maskToken.matches[tndx].isQuantifier !== true) {
  1163. var match = handleMatch(maskToken.matches[tndx], [tndx].concat(loopNdx), quantifierRecurse);
  1164. if (match && testPos === pos) {
  1165. return match;
  1166. } else if (testPos > pos) {
  1167. break;
  1168. }
  1169. }
  1170. }
  1171. }
  1172. function mergeLocators(pos, tests) {
  1173. var locator = [];
  1174. if (!$.isArray(tests)) tests = [tests];
  1175. if (tests.length > 0) {
  1176. if (tests[0].alternation === undefined) {
  1177. locator = determineTestTemplate(pos, tests.slice()).locator.slice();
  1178. if (locator.length === 0) locator = tests[0].locator.slice();
  1179. } else {
  1180. $.each(tests, function (ndx, tst) {
  1181. if (tst.def !== "") {
  1182. if (locator.length === 0) locator = tst.locator.slice();
  1183. else {
  1184. for (var i = 0; i < locator.length; i++) {
  1185. if (tst.locator[i] && locator[i].toString().indexOf(tst.locator[i]) === -1) {
  1186. locator[i] += "," + tst.locator[i];
  1187. }
  1188. }
  1189. }
  1190. }
  1191. });
  1192. }
  1193. }
  1194. return locator;
  1195. }
  1196. if (pos > -1) {
  1197. if (ndxIntlzr === undefined) { //determine index initializer
  1198. var previousPos = pos - 1,
  1199. test;
  1200. while ((test = getMaskSet().validPositions[previousPos] || getMaskSet().tests[previousPos]) === undefined && previousPos > -1) {
  1201. previousPos--;
  1202. }
  1203. if (test !== undefined && previousPos > -1) {
  1204. ndxInitializer = mergeLocators(previousPos, test);
  1205. cacheDependency = ndxInitializer.join("");
  1206. testPos = previousPos;
  1207. }
  1208. }
  1209. if (getMaskSet().tests[pos] && getMaskSet().tests[pos][0].cd === cacheDependency) { //cacheDependency is set on all tests, just check on the first
  1210. //console.log("cache hit " + pos + " - " + ndxIntlzr);
  1211. return getMaskSet().tests[pos];
  1212. }
  1213. for (var mtndx = ndxInitializer.shift(); mtndx < maskTokens.length; mtndx++) {
  1214. var match = resolveTestFromToken(maskTokens[mtndx], ndxInitializer, [mtndx]);
  1215. if ((match && testPos === pos) || testPos > pos) {
  1216. break;
  1217. }
  1218. }
  1219. }
  1220. if (matches.length === 0 || insertStop) {
  1221. matches.push({
  1222. match: {
  1223. fn: null,
  1224. optionality: false,
  1225. casing: null,
  1226. def: "",
  1227. placeholder: ""
  1228. },
  1229. locator: [],
  1230. mloc: {},
  1231. cd: cacheDependency
  1232. });
  1233. }
  1234. if (ndxIntlzr !== undefined && getMaskSet().tests[pos]) { //prioritize full tests for caching
  1235. return $.extend(true, [], matches);
  1236. }
  1237. getMaskSet().tests[pos] = $.extend(true, [], matches); //set a clone to prevent overwriting some props
  1238. // console.log(pos + " - " + JSON.stringify(matches));
  1239. return getMaskSet().tests[pos];
  1240. }
  1241. function getBufferTemplate() {
  1242. if (getMaskSet()._buffer === undefined) {
  1243. //generate template
  1244. getMaskSet()._buffer = getMaskTemplate(false, 1);
  1245. if (getMaskSet().buffer === undefined) getMaskSet().buffer = getMaskSet()._buffer.slice();
  1246. }
  1247. return getMaskSet()._buffer;
  1248. }
  1249. function getBuffer(noCache) {
  1250. if (getMaskSet().buffer === undefined || noCache === true) {
  1251. getMaskSet().buffer = getMaskTemplate(true, getLastValidPosition(), true);
  1252. }
  1253. return getMaskSet().buffer;
  1254. }
  1255. function refreshFromBuffer(start, end, buffer) {
  1256. var i, p;
  1257. if (start === true) {
  1258. resetMaskSet();
  1259. start = 0;
  1260. end = buffer.length;
  1261. } else {
  1262. for (i = start; i < end; i++) {
  1263. delete getMaskSet().validPositions[i];
  1264. }
  1265. }
  1266. p = start;
  1267. for (i = start; i < end; i++) {
  1268. resetMaskSet(true); //prevents clobber from the buffer
  1269. if (buffer[i] !== opts.skipOptionalPartCharacter) {
  1270. var valResult = isValid(p, buffer[i], true, true);
  1271. if (valResult !== false) {
  1272. resetMaskSet(true);
  1273. p = valResult.caret !== undefined ? valResult.caret : valResult.pos + 1;
  1274. }
  1275. }
  1276. }
  1277. }
  1278. function casing(elem, test, pos) {
  1279. switch (opts.casing || test.casing) {
  1280. case "upper":
  1281. elem = elem.toUpperCase();
  1282. break;
  1283. case "lower":
  1284. elem = elem.toLowerCase();
  1285. break;
  1286. case "title":
  1287. var posBefore = getMaskSet().validPositions[pos - 1];
  1288. if (pos === 0 || posBefore && posBefore.input === String.fromCharCode(Inputmask.keyCode.SPACE)) {
  1289. elem = elem.toUpperCase();
  1290. } else {
  1291. elem = elem.toLowerCase();
  1292. }
  1293. break;
  1294. default:
  1295. if ($.isFunction(opts.casing)) {
  1296. var args = Array.prototype.slice.call(arguments);
  1297. args.push(getMaskSet().validPositions);
  1298. elem = opts.casing.apply(this, args);
  1299. }
  1300. }
  1301. return elem;
  1302. }
  1303. function checkAlternationMatch(altArr1, altArr2, na) {
  1304. var altArrC = opts.greedy ? altArr2 : altArr2.slice(0, 1),
  1305. isMatch = false,
  1306. naArr = na !== undefined ? na.split(",") : [],
  1307. naNdx;
  1308. //remove no alternate indexes from alternation array
  1309. for (var i = 0; i < naArr.length; i++) {
  1310. if ((naNdx = altArr1.indexOf(naArr[i])) !== -1) {
  1311. altArr1.splice(naNdx, 1);
  1312. }
  1313. }
  1314. for (var alndx = 0; alndx < altArr1.length; alndx++) {
  1315. if ($.inArray(altArr1[alndx], altArrC) !== -1) {
  1316. isMatch = true;
  1317. break;
  1318. }
  1319. }
  1320. return isMatch;
  1321. }
  1322. function alternate(pos, c, strict, fromSetValid, rAltPos) { //pos == true => generalize
  1323. var validPsClone = $.extend(true, {}, getMaskSet().validPositions),
  1324. lastAlt,
  1325. alternation,
  1326. isValidRslt = false,
  1327. altPos, prevAltPos, i, validPos,
  1328. decisionPos,
  1329. lAltPos = rAltPos !== undefined ? rAltPos : getLastValidPosition();
  1330. if (lAltPos === -1 && rAltPos === undefined) { //do not recurse when already paste the beginning
  1331. lastAlt = 0;
  1332. prevAltPos = getTest(lastAlt);
  1333. alternation = prevAltPos.alternation;
  1334. } else {
  1335. //find last modified alternation
  1336. for (; lAltPos >= 0; lAltPos--) {
  1337. altPos = getMaskSet().validPositions[lAltPos];
  1338. if (altPos && altPos.alternation !== undefined) {
  1339. if (prevAltPos && prevAltPos.locator[altPos.alternation] !== altPos.locator[altPos.alternation]) {
  1340. break;
  1341. }
  1342. lastAlt = lAltPos;
  1343. alternation = getMaskSet().validPositions[lastAlt].alternation;
  1344. prevAltPos = altPos;
  1345. }
  1346. }
  1347. }
  1348. if (alternation !== undefined) {
  1349. decisionPos = parseInt(lastAlt);
  1350. getMaskSet().excludes[decisionPos] = getMaskSet().excludes[decisionPos] || [];
  1351. if (pos !== true) { //generalize
  1352. getMaskSet().excludes[decisionPos].push(getDecisionTaker(prevAltPos));
  1353. }
  1354. var validInputsClone = [], staticInputsBeforePos = 0;
  1355. for (i = decisionPos; i < getLastValidPosition(undefined, true) + 1; i++) {
  1356. validPos = getMaskSet().validPositions[i];
  1357. if (validPos && validPos.generatedInput !== true /*&& /[0-9a-bA-Z]/.test(validPos.input)*/) {
  1358. validInputsClone.push(validPos.input);
  1359. } else if (i < pos) staticInputsBeforePos++;
  1360. delete getMaskSet().validPositions[i];
  1361. }
  1362. while (getMaskSet().excludes[decisionPos] && getMaskSet().excludes[decisionPos].length < 10) {
  1363. var posOffset = staticInputsBeforePos * -1, //negate
  1364. validInputs = validInputsClone.slice();
  1365. getMaskSet().tests[decisionPos] = undefined; //clear decisionPos
  1366. resetMaskSet(true); //clear getbuffer
  1367. isValidRslt = true;
  1368. while (validInputs.length > 0) {
  1369. var input = validInputs.shift();
  1370. // if (input !== opts.skipOptionalPartCharacter) {
  1371. if (!(isValidRslt = isValid(getLastValidPosition(undefined, true) + 1, input, false, fromSetValid, true))) {
  1372. break;
  1373. }
  1374. // }
  1375. }
  1376. if (isValidRslt && c !== undefined) {
  1377. var targetLvp = getLastValidPosition(pos) + 1;
  1378. for (i = decisionPos; i < getLastValidPosition() + 1; i++) {
  1379. validPos = getMaskSet().validPositions[i];
  1380. if ((validPos === undefined || validPos.match.fn == null) && i < (pos + posOffset)) {
  1381. posOffset++;
  1382. }
  1383. }
  1384. pos = pos + posOffset;
  1385. isValidRslt = isValid(pos > targetLvp ? targetLvp : pos, c, strict, fromSetValid, true);
  1386. }
  1387. if (!isValidRslt) {
  1388. resetMaskSet();
  1389. prevAltPos = getTest(decisionPos); //get the current decisionPos to exclude ~ needs to be before restoring the initial validation
  1390. //reset & revert
  1391. getMaskSet().validPositions = $.extend(true, {}, validPsClone);
  1392. if (getMaskSet().excludes[decisionPos]) {
  1393. var decisionTaker = getDecisionTaker(prevAltPos);
  1394. if (getMaskSet().excludes[decisionPos].indexOf(decisionTaker) !== -1) {
  1395. isValidRslt = alternate(pos, c, strict, fromSetValid, decisionPos - 1);
  1396. break;
  1397. }
  1398. getMaskSet().excludes[decisionPos].push(decisionTaker);
  1399. for (i = decisionPos; i < getLastValidPosition(undefined, true) + 1; i++) delete getMaskSet().validPositions[i];
  1400. } else { //latest alternation
  1401. isValidRslt = alternate(pos, c, strict, fromSetValid, decisionPos - 1);
  1402. break;
  1403. }
  1404. } else break;
  1405. }
  1406. }
  1407. //reset alternation excludes
  1408. getMaskSet().excludes[decisionPos] = undefined;
  1409. return isValidRslt;
  1410. }
  1411. function isValid(pos, c, strict, fromSetValid, fromAlternate, validateOnly) { //strict true ~ no correction or autofill
  1412. function isSelection(posObj) {
  1413. return isRTL ? (posObj.begin - posObj.end) > 1 || ((posObj.begin - posObj.end) === 1) :
  1414. (posObj.end - posObj.begin) > 1 || ((posObj.end - posObj.begin) === 1);
  1415. }
  1416. strict = strict === true; //always set a value to strict to prevent possible strange behavior in the extensions
  1417. var maskPos = pos;
  1418. if (pos.begin !== undefined) { //position was a position object - used to handle a delete by typing over a selection
  1419. maskPos = isRTL ? pos.end : pos.begin;
  1420. }
  1421. function _isValid(position, c, strict) {
  1422. var rslt = false;
  1423. $.each(getTests(position), function (ndx, tst) {
  1424. var test = tst.match;
  1425. //make sure the buffer is set and correct
  1426. getBuffer(true);
  1427. //return is false or a json object => { pos: ??, c: ??} or true
  1428. rslt = test.fn != null ?
  1429. test.fn.test(c, getMaskSet(), position, strict, opts, isSelection(pos)) : (c === test.def || c === opts.skipOptionalPartCharacter) && test.def !== "" ? //non mask
  1430. {
  1431. c: getPlaceholder(position, test, true) || test.def,
  1432. pos: position
  1433. } : false;
  1434. if (rslt !== false) {
  1435. var elem = rslt.c !== undefined ? rslt.c : c, validatedPos = position;
  1436. elem = (elem === opts.skipOptionalPartCharacter && test.fn === null) ?
  1437. (getPlaceholder(position, test, true) || test.def) : elem;
  1438. if (rslt.remove !== undefined) { //remove position(s)
  1439. if (!$.isArray(rslt.remove)) rslt.remove = [rslt.remove];
  1440. $.each(rslt.remove.sort(function (a, b) {
  1441. return b - a;
  1442. }), function (ndx, lmnt) {
  1443. revalidateMask({begin: lmnt, end: lmnt + 1});
  1444. });
  1445. }
  1446. if (rslt.insert !== undefined) { //insert position(s)
  1447. if (!$.isArray(rslt.insert)) rslt.insert = [rslt.insert];
  1448. $.each(rslt.insert.sort(function (a, b) {
  1449. return a - b;
  1450. }), function (ndx, lmnt) {
  1451. isValid(lmnt.pos, lmnt.c, true, fromSetValid);
  1452. });
  1453. }
  1454. if (rslt !== true && rslt.pos !== undefined && rslt.pos !== position) { //their is a position offset
  1455. validatedPos = rslt.pos;
  1456. }
  1457. if (rslt !== true && rslt.pos === undefined && rslt.c === undefined) {
  1458. return false; //breakout if nothing to insert
  1459. }
  1460. if (!revalidateMask(pos, $.extend({}, tst, {
  1461. "input": casing(elem, test, validatedPos)
  1462. }), fromSetValid, validatedPos)) {
  1463. rslt = false;
  1464. }
  1465. return false; //break from $.each
  1466. }
  1467. });
  1468. return rslt;
  1469. }
  1470. var result = true,
  1471. positionsClone = $.extend(true, {}, getMaskSet().validPositions); //clone the currentPositions
  1472. if ($.isFunction(opts.preValidation) && !strict && fromSetValid !== true && validateOnly !== true) {
  1473. result = opts.preValidation(getBuffer(), maskPos, c, isSelection(pos), opts, getMaskSet());
  1474. }
  1475. if (result === true) {
  1476. trackbackPositions(undefined, maskPos, true);
  1477. if (maxLength === undefined || maskPos < maxLength) {
  1478. result = _isValid(maskPos, c, strict);
  1479. if ((!strict || fromSetValid === true) && result === false && validateOnly !== true) {
  1480. var currentPosValid = getMaskSet().validPositions[maskPos];
  1481. if (currentPosValid && currentPosValid.match.fn === null && (currentPosValid.match.def === c || c === opts.skipOptionalPartCharacter)) {
  1482. result = {
  1483. "caret": seekNext(maskPos)
  1484. };
  1485. } else if ((opts.insertMode || getMaskSet().validPositions[seekNext(maskPos)] === undefined) && !isMask(maskPos, true)) { //does the input match on a further position?
  1486. for (var nPos = maskPos + 1, snPos = seekNext(maskPos); nPos <= snPos; nPos++) {
  1487. // if (!isMask(nPos, true)) {
  1488. // continue;
  1489. // }
  1490. result = _isValid(nPos, c, strict);
  1491. if (result !== false) {
  1492. result = trackbackPositions(maskPos, result.pos !== undefined ? result.pos : nPos) || result;
  1493. maskPos = nPos;
  1494. break;
  1495. }
  1496. }
  1497. }
  1498. }
  1499. }
  1500. if (result === false && opts.keepStatic !== false && (opts.regex == null || isComplete(getBuffer())) && !strict && fromAlternate !== true) { //try fuzzy alternator logic
  1501. result = alternate(maskPos, c, strict, fromSetValid);
  1502. }
  1503. if (result === true) {
  1504. result = {
  1505. "pos": maskPos
  1506. };
  1507. }
  1508. }
  1509. if ($.isFunction(opts.postValidation) && result !== false && !strict && fromSetValid !== true && validateOnly !== true) {
  1510. var postResult = opts.postValidation(getBuffer(true), result, opts);
  1511. if (postResult !== undefined) {
  1512. if (postResult.refreshFromBuffer && postResult.buffer) {
  1513. var refresh = postResult.refreshFromBuffer;
  1514. refreshFromBuffer(refresh === true ? refresh : refresh.start, refresh.end, postResult.buffer);
  1515. }
  1516. result = postResult === true ? result : postResult;
  1517. }
  1518. }
  1519. if (result && result.pos === undefined) {
  1520. result.pos = maskPos;
  1521. }
  1522. if (result === false || validateOnly === true) {
  1523. resetMaskSet(true);
  1524. getMaskSet().validPositions = $.extend(true, {}, positionsClone); //revert validation changes
  1525. }
  1526. return result;
  1527. }
  1528. //fill in best positions according the current input
  1529. function trackbackPositions(originalPos, newPos, fillOnly) {
  1530. var result;
  1531. if (originalPos === undefined) {
  1532. //find previous valid
  1533. for (originalPos = newPos - 1; originalPos > 0; originalPos--) {
  1534. if (getMaskSet().validPositions[originalPos]) break;
  1535. }
  1536. }
  1537. for (var ps = originalPos; ps < newPos; ps++) {
  1538. if (getMaskSet().validPositions[ps] === undefined && !isMask(ps, true)) {
  1539. var vp = ps == 0 ? getTest(ps) : getMaskSet().validPositions[ps - 1];
  1540. if (vp) {
  1541. var targetLocator = getLocator(vp), tests = getTests(ps).slice(),
  1542. tstLocator, closest = undefined, bestMatch = getTest(ps);
  1543. if (tests[tests.length - 1].match.def === "") tests.pop(); //remove stop from matches
  1544. $.each(tests, function (ndx, tst) { //find best matching
  1545. tstLocator = getLocator(tst, targetLocator.length);
  1546. var distance = Math.abs(tstLocator - targetLocator);
  1547. if ((closest === undefined || distance < closest) && tst.match.fn === null && tst.match.optionality !== true && tst.match.optionalQuantifier !== true) {
  1548. closest = distance;
  1549. bestMatch = tst;
  1550. }
  1551. });
  1552. bestMatch = $.extend({}, bestMatch, {
  1553. "input": getPlaceholder(ps, bestMatch.match, true) || bestMatch.match.def
  1554. });
  1555. bestMatch.generatedInput = true;
  1556. revalidateMask(ps, bestMatch, true);
  1557. if (fillOnly !== true) {
  1558. //revalidate the new position to update the locator value
  1559. var cvpInput = getMaskSet().validPositions[newPos].input;
  1560. getMaskSet().validPositions[newPos] = undefined;
  1561. result = isValid(newPos, cvpInput, true, true);
  1562. }
  1563. }
  1564. }
  1565. }
  1566. return result;
  1567. }
  1568. function revalidateMask(pos, validTest, fromSetValid, validatedPos) {
  1569. function IsEnclosedStatic(pos, valids, selection) {
  1570. var posMatch = valids[pos];
  1571. if (posMatch !== undefined && ((posMatch.match.fn === null && posMatch.match.optionality !== true) || posMatch.input === opts.radixPoint)) {
  1572. var prevMatch = selection.begin <= pos - 1 ? valids[pos - 1] && valids[pos - 1].match.fn === null && valids[pos - 1] : valids[pos - 1],
  1573. nextMatch = selection.end > pos + 1 ? valids[pos + 1] && valids[pos + 1].match.fn === null && valids[pos + 1] : valids[pos + 1];
  1574. return prevMatch && nextMatch;
  1575. }
  1576. return false;
  1577. }
  1578. var begin = pos.begin !== undefined ? pos.begin : pos, end = pos.end !== undefined ? pos.end : pos;
  1579. if (pos.begin > pos.end) {
  1580. begin = pos.end;
  1581. end = pos.begin;
  1582. }
  1583. validatedPos = validatedPos !== undefined ? validatedPos : begin;
  1584. if (begin !== end || (opts.insertMode && getMaskSet().validPositions[validatedPos] !== undefined && fromSetValid === undefined)) {
  1585. //reposition & revalidate others
  1586. var positionsClone = $.extend(true, {}, getMaskSet().validPositions),
  1587. lvp = getLastValidPosition(undefined, true),
  1588. i;
  1589. getMaskSet().p = begin; //needed for alternated position after overtype selection
  1590. for (i = lvp; i >= begin; i--) {
  1591. if (getMaskSet().validPositions[i] && getMaskSet().validPositions[i].match.nativeDef === "+") { //REMOVE ME AFTER REFACTORING OF NUMERIC ALIAS
  1592. opts.isNegative = false;
  1593. }
  1594. delete getMaskSet().validPositions[i];
  1595. }
  1596. var valid = true, j = validatedPos,
  1597. vps = getMaskSet().validPositions,
  1598. needsValidation = false, posMatch = j, i = j;
  1599. if (validTest) {
  1600. getMaskSet().validPositions[validatedPos] = $.extend(true, {}, validTest);
  1601. posMatch++;
  1602. j++;
  1603. if (begin < end) i++; //if selection and entry move start by one
  1604. }
  1605. for (; i <= lvp; i++) {
  1606. var t = positionsClone[i];
  1607. if (t !== undefined &&
  1608. (i >= end || (i >= begin && t.generatedInput !== true && IsEnclosedStatic(i, positionsClone, {
  1609. begin: begin,
  1610. end: end
  1611. })))) {
  1612. while (getTest(posMatch).match.def !== "") {
  1613. if (needsValidation === false && positionsClone[posMatch] && positionsClone[posMatch].match.nativeDef === t.match.nativeDef) { //obvious match
  1614. getMaskSet().validPositions[posMatch] = $.extend(true, {}, positionsClone[posMatch]);
  1615. getMaskSet().validPositions[posMatch].input = t.input;
  1616. trackbackPositions(undefined, posMatch, true);
  1617. j = posMatch + 1;
  1618. valid = true;
  1619. } else if (positionCanMatchDefinition(posMatch, t.match.def)) { //validated match
  1620. var result = isValid(posMatch, t.input, true, true);
  1621. valid = result !== false;
  1622. j = (result.caret || result.insert) ? getLastValidPosition() : posMatch + 1;
  1623. needsValidation = true;
  1624. } else {
  1625. valid = t.generatedInput === true || (t.input === opts.radixPoint && opts.numericInput === true);
  1626. if (!valid && getTest(posMatch).match.def === "") break;
  1627. }
  1628. if (valid) break;
  1629. posMatch++;
  1630. }
  1631. if (getTest(posMatch).match.def == "")
  1632. valid = false;
  1633. //restore position
  1634. posMatch = j;
  1635. }
  1636. if (!valid) break;
  1637. }
  1638. if (!valid) {
  1639. getMaskSet().validPositions = $.extend(true, {}, positionsClone);
  1640. resetMaskSet(true);
  1641. return false;
  1642. }
  1643. }
  1644. else if (validTest) {
  1645. getMaskSet().validPositions[validatedPos] = $.extend(true, {}, validTest);
  1646. }
  1647. resetMaskSet(true);
  1648. return true;
  1649. }
  1650. function isMask(pos, strict) {
  1651. var test = getTestTemplate(pos).match;
  1652. if (test.def === "") test = getTest(pos).match;
  1653. if (test.fn != null) {
  1654. return test.fn;
  1655. }
  1656. if (strict !== true && pos > -1) {
  1657. var tests = getTests(pos);
  1658. return tests.length > 1 + (tests[tests.length - 1].match.def === "" ? 1 : 0);
  1659. }
  1660. return false;
  1661. }
  1662. function seekNext(pos, newBlock) {
  1663. var position = pos + 1;
  1664. while (getTest(position).match.def !== "" &&
  1665. ((newBlock === true && (getTest(position).match.newBlockMarker !== true || !isMask(position))) ||
  1666. (newBlock !== true && !isMask(position)))) {
  1667. position++;
  1668. }
  1669. return position;
  1670. }
  1671. function seekPrevious(pos, newBlock) {
  1672. var position = pos,
  1673. tests;
  1674. if (position <= 0) return 0;
  1675. while (--position > 0 &&
  1676. ((newBlock === true && getTest(position).match.newBlockMarker !== true) ||
  1677. (newBlock !== true && !isMask(position) &&
  1678. (tests = getTests(position), tests.length < 2 || (tests.length === 2 && tests[1].match.def === ""))))) {
  1679. }
  1680. return position;
  1681. }
  1682. function getBufferElement(position) {
  1683. return getMaskSet().validPositions[position] === undefined ? getPlaceholder(position) : getMaskSet().validPositions[position].input;
  1684. }
  1685. function writeBuffer(input, buffer, caretPos, event, triggerEvents) {
  1686. if (event && $.isFunction(opts.onBeforeWrite)) {
  1687. // buffer = buffer.slice(); //prevent uncontrolled manipulation of the internal buffer
  1688. var result = opts.onBeforeWrite.call(inputmask, event, buffer, caretPos, opts);
  1689. if (result) {
  1690. if (result.refreshFromBuffer) {
  1691. var refresh = result.refreshFromBuffer;
  1692. refreshFromBuffer(refresh === true ? refresh : refresh.start, refresh.end, result.buffer || buffer);
  1693. buffer = getBuffer(true);
  1694. }
  1695. //only alter when intented !== undefined
  1696. if (caretPos !== undefined) caretPos = result.caret !== undefined ? result.caret : caretPos;
  1697. }
  1698. }
  1699. if (input !== undefined) {
  1700. input.inputmask._valueSet(buffer.join(""));
  1701. if (caretPos !== undefined && (event === undefined || event.type !== "blur")) {
  1702. caret(input, caretPos);
  1703. } else renderColorMask(input, caretPos, buffer.length === 0);
  1704. if (triggerEvents === true) {
  1705. var $input = $(input), nptVal = input.inputmask._valueGet();
  1706. skipInputEvent = true;
  1707. $input.trigger("input");
  1708. setTimeout(function () { //timeout needed for IE
  1709. if (nptVal === getBufferTemplate().join("")) {
  1710. $input.trigger("cleared");
  1711. } else if (isComplete(buffer) === true) {
  1712. $input.trigger("complete");
  1713. }
  1714. }, 0);
  1715. }
  1716. }
  1717. }
  1718. function getPlaceholder(pos, test, returnPL) {
  1719. test = test || getTest(pos).match;
  1720. if (test.placeholder !== undefined || returnPL === true) {
  1721. return $.isFunction(test.placeholder) ? test.placeholder(opts) : test.placeholder;
  1722. } else if (test.fn === null) {
  1723. if (pos > -1 && getMaskSet().validPositions[pos] === undefined) {
  1724. var tests = getTests(pos),
  1725. staticAlternations = [],
  1726. prevTest;
  1727. if (tests.length > 1 + (tests[tests.length - 1].match.def === "" ? 1 : 0)) {
  1728. for (var i = 0; i < tests.length; i++) {
  1729. if (tests[i].match.optionality !== true && tests[i].match.optionalQuantifier !== true &&
  1730. (tests[i].match.fn === null || (prevTest === undefined || tests[i].match.fn.test(prevTest.match.def, getMaskSet(), pos, true, opts) !== false))) {
  1731. staticAlternations.push(tests[i]);
  1732. if (tests[i].match.fn === null) prevTest = tests[i];
  1733. if (staticAlternations.length > 1) {
  1734. if (/[0-9a-bA-Z]/.test(staticAlternations[0].match.def)) {
  1735. return opts.placeholder.charAt(pos % opts.placeholder.length);
  1736. }
  1737. }
  1738. }
  1739. }
  1740. }
  1741. }
  1742. return test.def;
  1743. }
  1744. return opts.placeholder.charAt(pos % opts.placeholder.length);
  1745. }
  1746. var EventRuler = {
  1747. on: function (input, eventName, eventHandler) {
  1748. var ev = function (e) {
  1749. // console.log("triggered " + e.type);
  1750. var that = this;
  1751. if (that.inputmask === undefined && this.nodeName !== "FORM") { //happens when cloning an object with jquery.clone
  1752. var imOpts = $.data(that, "_inputmask_opts");
  1753. if (imOpts) (new Inputmask(imOpts)).mask(that);
  1754. else EventRuler.off(that);
  1755. } else if (e.type !== "setvalue" && this.nodeName !== "FORM" && (that.disabled || (that.readOnly && !(e.type === "keydown" && (e.ctrlKey && e.keyCode === 67) || (opts.tabThrough === false && e.keyCode === Inputmask.keyCode.TAB))))) {
  1756. e.preventDefault();
  1757. } else {
  1758. switch (e.type) {
  1759. case "input":
  1760. if (skipInputEvent === true) {
  1761. skipInputEvent = false;
  1762. return e.preventDefault();
  1763. }
  1764. if (mobile) {
  1765. trackCaret = true;
  1766. var args = arguments;
  1767. setTimeout(function () { //needed for caret selection when entering a char on Android 8 - #1818
  1768. eventHandler.apply(that, args);
  1769. }, 0);
  1770. return false;
  1771. }
  1772. break;
  1773. case "keydown":
  1774. //Safari 5.1.x - modal dialog fires keypress twice workaround
  1775. skipKeyPressEvent = false;
  1776. skipInputEvent = false;
  1777. break;
  1778. case "keypress":
  1779. if (skipKeyPressEvent === true) {
  1780. return e.preventDefault();
  1781. }
  1782. skipKeyPressEvent = true;
  1783. break;
  1784. case "click":
  1785. if (iemobile || iphone) {
  1786. var args = arguments;
  1787. setTimeout(function () {
  1788. eventHandler.apply(that, args);
  1789. }, 0);
  1790. return false;
  1791. }
  1792. break;
  1793. }
  1794. // console.log("executed " + e.type);
  1795. var returnVal = eventHandler.apply(that, arguments);
  1796. if (trackCaret) {
  1797. trackCaret = false;
  1798. setTimeout(function () {
  1799. caret(that, that.inputmask.caretPos, undefined, true);
  1800. // console.log("2 " + JSON.stringify(that.inputmask.caretPos));
  1801. });
  1802. }
  1803. if (returnVal === false) {
  1804. e.preventDefault();
  1805. e.stopPropagation();
  1806. }
  1807. return returnVal;
  1808. }
  1809. };
  1810. //keep instance of the event
  1811. input.inputmask.events[eventName] = input.inputmask.events[eventName] || [];
  1812. input.inputmask.events[eventName].push(ev);
  1813. if ($.inArray(eventName, ["submit", "reset"]) !== -1) {
  1814. if (input.form !== null) $(input.form).on(eventName, ev);
  1815. } else {
  1816. $(input).on(eventName, ev);
  1817. }
  1818. },
  1819. off: function (input, event) {
  1820. if (input.inputmask && input.inputmask.events) {
  1821. var events;
  1822. if (event) {
  1823. events = [];
  1824. events[event] = input.inputmask.events[event];
  1825. } else {
  1826. events = input.inputmask.events;
  1827. }
  1828. $.each(events, function (eventName, evArr) {
  1829. while (evArr.length > 0) {
  1830. var ev = evArr.pop();
  1831. if ($.inArray(eventName, ["submit", "reset"]) !== -1) {
  1832. if (input.form !== null) $(input.form).off(eventName, ev);
  1833. } else {
  1834. $(input).off(eventName, ev);
  1835. }
  1836. }
  1837. delete input.inputmask.events[eventName];
  1838. });
  1839. }
  1840. }
  1841. };
  1842. var EventHandlers = {
  1843. keydownEvent: function (e) {
  1844. var input = this,
  1845. $input = $(input),
  1846. k = e.keyCode,
  1847. pos = caret(input);
  1848. //backspace, delete, and escape get special treatment
  1849. if (k === Inputmask.keyCode.BACKSPACE || k === Inputmask.keyCode.DELETE || (iphone && k === Inputmask.keyCode.BACKSPACE_SAFARI) || (e.ctrlKey && k === Inputmask.keyCode.X && !isInputEventSupported("cut"))) { //backspace/delete
  1850. e.preventDefault(); //stop default action but allow propagation
  1851. handleRemove(input, k, pos);
  1852. writeBuffer(input, getBuffer(true), getMaskSet().p, e, input.inputmask._valueGet() !== getBuffer().join(""));
  1853. } else if (k === Inputmask.keyCode.END || k === Inputmask.keyCode.PAGE_DOWN) { //when END or PAGE_DOWN pressed set position at lastmatch
  1854. e.preventDefault();
  1855. var caretPos = seekNext(getLastValidPosition());
  1856. if (!opts.insertMode && caretPos === getMaskSet().maskLength && !e.shiftKey) caretPos--;
  1857. caret(input, e.shiftKey ? pos.begin : caretPos, caretPos, true);
  1858. } else if ((k === Inputmask.keyCode.HOME && !e.shiftKey) || k === Inputmask.keyCode.PAGE_UP) { //Home or page_up
  1859. e.preventDefault();
  1860. caret(input, 0, e.shiftKey ? pos.begin : 0, true);
  1861. } else if (((opts.undoOnEscape && k === Inputmask.keyCode.ESCAPE) || (k === 90 && e.ctrlKey)) && e.altKey !== true) { //escape && undo && #762
  1862. checkVal(input, true, false, undoValue.split(""));
  1863. $input.trigger("click");
  1864. } else if (k === Inputmask.keyCode.INSERT && !(e.shiftKey || e.ctrlKey)) { //insert
  1865. opts.insertMode = !opts.insertMode;
  1866. caret(input, !opts.insertMode && pos.begin === getMaskSet().maskLength ? pos.begin - 1 : pos.begin);
  1867. } else if (opts.tabThrough === true && k === Inputmask.keyCode.TAB) {
  1868. if (e.shiftKey === true) {
  1869. if (getTest(pos.begin).match.fn === null) {
  1870. pos.begin = seekNext(pos.begin);
  1871. }
  1872. pos.end = seekPrevious(pos.begin, true);
  1873. pos.begin = seekPrevious(pos.end, true);
  1874. } else {
  1875. pos.begin = seekNext(pos.begin, true);
  1876. pos.end = seekNext(pos.begin, true);
  1877. if (pos.end < getMaskSet().maskLength) pos.end--;
  1878. }
  1879. if (pos.begin < getMaskSet().maskLength) {
  1880. e.preventDefault();
  1881. caret(input, pos.begin, pos.end);
  1882. }
  1883. } else if (!e.shiftKey) {
  1884. if (opts.insertMode === false) {
  1885. if (k === Inputmask.keyCode.RIGHT) {
  1886. setTimeout(function () {
  1887. var caretPos = caret(input);
  1888. caret(input, caretPos.begin);
  1889. }, 0);
  1890. } else if (k === Inputmask.keyCode.LEFT) {
  1891. setTimeout(function () {
  1892. var caretPos = caret(input);
  1893. caret(input, isRTL ? caretPos.begin + 1 : caretPos.begin - 1);
  1894. }, 0);
  1895. }
  1896. }
  1897. }
  1898. opts.onKeyDown.call(this, e, getBuffer(), caret(input).begin, opts);
  1899. ignorable = $.inArray(k, opts.ignorables) !== -1;
  1900. },
  1901. keypressEvent: function (e, checkval, writeOut, strict, ndx) {
  1902. var input = this,
  1903. $input = $(input),
  1904. k = e.which || e.charCode || e.keyCode;
  1905. if (checkval !== true && (!(e.ctrlKey && e.altKey) && (e.ctrlKey || e.metaKey || ignorable))) {
  1906. if (k === Inputmask.keyCode.ENTER && undoValue !== getBuffer().join("")) {
  1907. undoValue = getBuffer().join("");
  1908. // e.preventDefault();
  1909. setTimeout(function () {
  1910. $input.trigger("change");
  1911. }, 0);
  1912. }
  1913. return true;
  1914. } else {
  1915. if (k) {
  1916. //special treat the decimal separator
  1917. if (k === 46 && e.shiftKey === false && opts.radixPoint !== "") k = opts.radixPoint.charCodeAt(0);
  1918. var pos = checkval ? {
  1919. begin: ndx,
  1920. end: ndx
  1921. } : caret(input),
  1922. forwardPosition, c = String.fromCharCode(k), offset = 0;
  1923. if (opts._radixDance && opts.numericInput) {
  1924. var caretPos = getBuffer().indexOf(opts.radixPoint.charAt(0)) + 1;
  1925. if (pos.begin <= caretPos) {
  1926. if (k === opts.radixPoint.charCodeAt(0)) offset = 1;
  1927. pos.begin -= 1;
  1928. pos.end -= 1;
  1929. }
  1930. }
  1931. getMaskSet().writeOutBuffer = true;
  1932. var valResult = isValid(pos, c, strict);
  1933. if (valResult !== false) {
  1934. resetMaskSet(true);
  1935. forwardPosition = valResult.caret !== undefined ? valResult.caret : seekNext(valResult.pos.begin ? valResult.pos.begin : valResult.pos);
  1936. getMaskSet().p = forwardPosition; //needed for checkval
  1937. }
  1938. forwardPosition = ((opts.numericInput && valResult.caret === undefined) ? seekPrevious(forwardPosition) : forwardPosition) + offset;
  1939. if (writeOut !== false) {
  1940. setTimeout(function () {
  1941. opts.onKeyValidation.call(input, k, valResult, opts);
  1942. }, 0);
  1943. if (getMaskSet().writeOutBuffer && valResult !== false) {
  1944. var buffer = getBuffer();
  1945. writeBuffer(input, buffer, forwardPosition, e, checkval !== true);
  1946. }
  1947. }
  1948. e.preventDefault();
  1949. if (checkval) {
  1950. if (valResult !== false) valResult.forwardPosition = forwardPosition;
  1951. return valResult;
  1952. }
  1953. }
  1954. }
  1955. },
  1956. pasteEvent: function (e) {
  1957. var input = this,
  1958. ev = e.originalEvent || e,
  1959. $input = $(input),
  1960. inputValue = input.inputmask._valueGet(true),
  1961. caretPos = caret(input),
  1962. tempValue;
  1963. if (isRTL) {
  1964. tempValue = caretPos.end;
  1965. caretPos.end = caretPos.begin;
  1966. caretPos.begin = tempValue;
  1967. }
  1968. var valueBeforeCaret = inputValue.substr(0, caretPos.begin),
  1969. valueAfterCaret = inputValue.substr(caretPos.end, inputValue.length);
  1970. if (valueBeforeCaret === (isRTL ? getBufferTemplate().reverse() : getBufferTemplate()).slice(0, caretPos.begin).join("")) valueBeforeCaret = "";
  1971. if (valueAfterCaret === (isRTL ? getBufferTemplate().reverse() : getBufferTemplate()).slice(caretPos.end).join("")) valueAfterCaret = "";
  1972. if (isRTL) {
  1973. tempValue = valueBeforeCaret;
  1974. valueBeforeCaret = valueAfterCaret;
  1975. valueAfterCaret = tempValue;
  1976. }
  1977. if (window.clipboardData && window.clipboardData.getData) { // IE
  1978. inputValue = valueBeforeCaret + window.clipboardData.getData("Text") + valueAfterCaret;
  1979. } else if (ev.clipboardData && ev.clipboardData.getData) {
  1980. inputValue = valueBeforeCaret + ev.clipboardData.getData("text/plain") + valueAfterCaret;
  1981. } else return true; //allow native paste event as fallback ~ masking will continue by inputfallback
  1982. var pasteValue = inputValue;
  1983. if ($.isFunction(opts.onBeforePaste)) {
  1984. pasteValue = opts.onBeforePaste.call(inputmask, inputValue, opts);
  1985. if (pasteValue === false) {
  1986. return e.preventDefault();
  1987. }
  1988. if (!pasteValue) {
  1989. pasteValue = inputValue;
  1990. }
  1991. }
  1992. checkVal(input, false, false, isRTL ? pasteValue.split("").reverse() : pasteValue.toString().split(""));
  1993. writeBuffer(input, getBuffer(), seekNext(getLastValidPosition()), e, undoValue !== getBuffer().join(""));
  1994. return e.preventDefault();
  1995. },
  1996. inputFallBackEvent: function (e) { //fallback when keypress is not triggered
  1997. function radixPointHandler(input, inputValue, caretPos) {
  1998. //radixpoint tweak
  1999. if (inputValue.charAt(caretPos.begin - 1) === "." && opts.radixPoint !== "") {
  2000. inputValue = inputValue.split("");
  2001. inputValue[caretPos.begin - 1] = opts.radixPoint.charAt(0);
  2002. inputValue = inputValue.join("");
  2003. }
  2004. return inputValue;
  2005. }
  2006. function ieMobileHandler(input, inputValue, caretPos) {
  2007. if (iemobile) { //iemobile just sets the character at the end althought the caret position is correctly set
  2008. var inputChar = inputValue.replace(getBuffer().join(""), "");
  2009. if (inputChar.length === 1) {
  2010. var iv = inputValue.split("");
  2011. iv.splice(caretPos.begin, 0, inputChar);
  2012. inputValue = iv.join("");
  2013. }
  2014. }
  2015. return inputValue;
  2016. }
  2017. var input = this,
  2018. inputValue = input.inputmask._valueGet();
  2019. if (getBuffer().join("") !== inputValue) {
  2020. var caretPos = caret(input);
  2021. inputValue = radixPointHandler(input, inputValue, caretPos);
  2022. inputValue = ieMobileHandler(input, inputValue, caretPos);
  2023. if (getBuffer().join("") !== inputValue) {
  2024. var buffer = getBuffer().join(""),
  2025. offset = (!opts.numericInput && inputValue.length > buffer.length) ? -1 : 0,
  2026. frontPart = inputValue.substr(0, caretPos.begin),
  2027. backPart = inputValue.substr(caretPos.begin),
  2028. frontBufferPart = buffer.substr(0, caretPos.begin + offset),
  2029. backBufferPart = buffer.substr(caretPos.begin + offset);
  2030. //check if thare was a selection
  2031. var selection = caretPos,
  2032. entries = "",
  2033. isEntry = false;
  2034. if (frontPart !== frontBufferPart) {
  2035. var fpl = (isEntry = frontPart.length >= frontBufferPart.length) ? frontPart.length : frontBufferPart.length
  2036. for (var i = 0; frontPart.charAt(i) === frontBufferPart.charAt(i) && i < fpl; i++) {
  2037. }
  2038. if (isEntry) {
  2039. if (offset === 0) selection.begin = i;
  2040. entries += frontPart.slice(i, selection.end);
  2041. }
  2042. }
  2043. if (backPart !== backBufferPart) {
  2044. if (backPart.length > backBufferPart.length) {
  2045. entries += backPart.slice(0, 1);
  2046. } else {
  2047. if (backPart.length < backBufferPart.length) {
  2048. selection.end += backBufferPart.length - backPart.length;
  2049. //hack around numeric alias & radixpoint
  2050. if (!isEntry && opts.radixPoint !== "" && backPart === "" && frontPart.charAt(selection.begin + offset - 1) === opts.radixPoint) {
  2051. selection.begin--;
  2052. entries = opts.radixPoint;
  2053. }
  2054. }
  2055. }
  2056. }
  2057. writeBuffer(input, getBuffer(), {
  2058. "begin": selection.begin + offset,
  2059. "end": selection.end + offset
  2060. });
  2061. if (entries.length > 0) {
  2062. $.each(entries.split(""), function (ndx, entry) {
  2063. var keypress = new $.Event("keypress");
  2064. keypress.which = entry.charCodeAt(0);
  2065. ignorable = false; //make sure ignorable is ignored ;-)
  2066. EventHandlers.keypressEvent.call(input, keypress);
  2067. });
  2068. } else {
  2069. if (selection.begin === selection.end - 1) {
  2070. selection.begin = seekPrevious(selection.begin + 1);
  2071. if (selection.begin === selection.end - 1) {
  2072. caret(input, selection.begin);
  2073. } else {
  2074. caret(input, selection.begin, selection.end);
  2075. }
  2076. }
  2077. var keydown = new $.Event("keydown");
  2078. keydown.keyCode = opts.numericInput ? Inputmask.keyCode.BACKSPACE : Inputmask.keyCode.DELETE;
  2079. EventHandlers.keydownEvent.call(input, keydown);
  2080. if (opts.insertMode === false) {
  2081. caret(input, caret(input).begin - 1);
  2082. }
  2083. }
  2084. // setTimeout(function(){
  2085. // console.log("2 " + JSON.stringify(caret(input)));
  2086. // },0);
  2087. e.preventDefault();
  2088. }
  2089. }
  2090. },
  2091. setValueEvent: function (e) {
  2092. this.inputmask.refreshValue = false;
  2093. var input = this,
  2094. value = (e && e.detail) ? e.detail[0] : arguments[1],
  2095. value = value || input.inputmask._valueGet(true);
  2096. if ($.isFunction(opts.onBeforeMask)) value = opts.onBeforeMask.call(inputmask, value, opts) || value;
  2097. value = value.split("");
  2098. checkVal(input, true, false, isRTL ? value.reverse() : value);
  2099. undoValue = getBuffer().join("");
  2100. if ((opts.clearMaskOnLostFocus || opts.clearIncomplete) && input.inputmask._valueGet() === getBufferTemplate().join("")) {
  2101. input.inputmask._valueSet("");
  2102. }
  2103. }
  2104. ,
  2105. focusEvent: function (e) {
  2106. var input = this,
  2107. nptValue = input.inputmask._valueGet();
  2108. if (opts.showMaskOnFocus && (!opts.showMaskOnHover || (opts.showMaskOnHover && nptValue === ""))) {
  2109. if (input.inputmask._valueGet() !== getBuffer().join("")) {
  2110. writeBuffer(input, getBuffer(), seekNext(getLastValidPosition()));
  2111. } else if (mouseEnter === false) { //only executed on focus without mouseenter
  2112. caret(input, seekNext(getLastValidPosition()));
  2113. }
  2114. }
  2115. if (opts.positionCaretOnTab === true && mouseEnter === false) {
  2116. EventHandlers.clickEvent.apply(input, [e, true]);
  2117. }
  2118. undoValue = getBuffer().join("");
  2119. },
  2120. mouseleaveEvent: function (e) {
  2121. var input = this;
  2122. mouseEnter = false;
  2123. if (opts.clearMaskOnLostFocus && document.activeElement !== input) {
  2124. var buffer = getBuffer().slice(),
  2125. nptValue = input.inputmask._valueGet();
  2126. if (nptValue !== input.getAttribute("placeholder") && nptValue !== "") {
  2127. if (getLastValidPosition() === -1 && nptValue === getBufferTemplate().join("")) {
  2128. buffer = [];
  2129. } else { //clearout optional tail of the mask
  2130. clearOptionalTail(buffer);
  2131. }
  2132. writeBuffer(input, buffer);
  2133. }
  2134. }
  2135. },
  2136. clickEvent: function (e, tabbed) {
  2137. function doRadixFocus(clickPos) {
  2138. if (opts.radixPoint !== "") {
  2139. var vps = getMaskSet().validPositions;
  2140. if (vps[clickPos] === undefined || (vps[clickPos].input === getPlaceholder(clickPos))) {
  2141. if (clickPos < seekNext(-1)) return true;
  2142. var radixPos = $.inArray(opts.radixPoint, getBuffer());
  2143. if (radixPos !== -1) {
  2144. for (var vp in vps) {
  2145. if (radixPos < vp && vps[vp].input !== getPlaceholder(vp)) {
  2146. return false;
  2147. }
  2148. }
  2149. return true;
  2150. }
  2151. }
  2152. }
  2153. return false;
  2154. }
  2155. var input = this;
  2156. setTimeout(function () { //needed for Chrome ~ initial selection clears after the clickevent
  2157. if (document.activeElement === input) {
  2158. var selectedCaret = caret(input);
  2159. if (tabbed) {
  2160. if (isRTL) {
  2161. selectedCaret.end = selectedCaret.begin;
  2162. } else {
  2163. selectedCaret.begin = selectedCaret.end;
  2164. }
  2165. }
  2166. if (selectedCaret.begin === selectedCaret.end) {
  2167. switch (opts.positionCaretOnClick) {
  2168. case "none":
  2169. break;
  2170. case "select":
  2171. caret(input, 0, getBuffer().length);
  2172. break;
  2173. case "radixFocus":
  2174. if (doRadixFocus(selectedCaret.begin)) {
  2175. var radixPos = getBuffer().join("").indexOf(opts.radixPoint);
  2176. caret(input, opts.numericInput ? seekNext(radixPos) : radixPos);
  2177. break;
  2178. }
  2179. case "ignore":
  2180. caret(input, seekNext(getLastValidPosition()));
  2181. break;
  2182. default: //lvp:
  2183. var clickPosition = selectedCaret.begin,
  2184. lvclickPosition = getLastValidPosition(clickPosition, true),
  2185. lastPosition = seekNext(lvclickPosition);
  2186. if (clickPosition < lastPosition) {
  2187. caret(input, !isMask(clickPosition, true) && !isMask(clickPosition - 1, true) ? seekNext(clickPosition) : clickPosition);
  2188. } else {
  2189. var lvp = getMaskSet().validPositions[lvclickPosition],
  2190. tt = getTestTemplate(lastPosition, lvp ? lvp.match.locator : undefined, lvp),
  2191. placeholder = getPlaceholder(lastPosition, tt.match);
  2192. if ((placeholder !== "" && getBuffer()[lastPosition] !== placeholder && tt.match.optionalQuantifier !== true && tt.match.newBlockMarker !== true) || (!isMask(lastPosition, opts.keepStatic) && tt.match.def === placeholder)) {
  2193. var newPos = seekNext(lastPosition);
  2194. if (clickPosition >= newPos || clickPosition === lastPosition) {
  2195. lastPosition = newPos;
  2196. }
  2197. }
  2198. caret(input, lastPosition);
  2199. }
  2200. break;
  2201. }
  2202. }
  2203. }
  2204. }, 0);
  2205. },
  2206. dblclickEvent: function (e) {
  2207. var input = this;
  2208. setTimeout(function () {
  2209. caret(input, 0, seekNext(getLastValidPosition()));
  2210. }, 0);
  2211. },
  2212. cutEvent: function (e) {
  2213. var input = this,
  2214. $input = $(input),
  2215. pos = caret(input),
  2216. ev = e.originalEvent || e;
  2217. //correct clipboardData
  2218. var clipboardData = window.clipboardData || ev.clipboardData,
  2219. clipData = isRTL ? getBuffer().slice(pos.end, pos.begin) : getBuffer().slice(pos.begin, pos.end);
  2220. clipboardData.setData("text", isRTL ? clipData.reverse().join("") : clipData.join(""));
  2221. if (document.execCommand) document.execCommand("copy"); // copy selected content to system clipbaord
  2222. handleRemove(input, Inputmask.keyCode.DELETE, pos);
  2223. writeBuffer(input, getBuffer(), getMaskSet().p, e, undoValue !== getBuffer().join(""));
  2224. },
  2225. blurEvent: function (e) {
  2226. var $input = $(this),
  2227. input = this;
  2228. if (input.inputmask) {
  2229. var nptValue = input.inputmask._valueGet(),
  2230. buffer = getBuffer().slice();
  2231. if (nptValue !== "" || colorMask !== undefined) {
  2232. if (opts.clearMaskOnLostFocus) {
  2233. if (getLastValidPosition() === -1 && nptValue === getBufferTemplate().join("")) {
  2234. buffer = [];
  2235. } else { //clearout optional tail of the mask
  2236. clearOptionalTail(buffer);
  2237. }
  2238. }
  2239. if (isComplete(buffer) === false) {
  2240. setTimeout(function () {
  2241. $input.trigger("incomplete");
  2242. }, 0);
  2243. if (opts.clearIncomplete) {
  2244. resetMaskSet();
  2245. if (opts.clearMaskOnLostFocus) {
  2246. buffer = [];
  2247. } else {
  2248. buffer = getBufferTemplate().slice();
  2249. }
  2250. }
  2251. }
  2252. writeBuffer(input, buffer, undefined, e);
  2253. }
  2254. if (undoValue !== getBuffer().join("")) {
  2255. undoValue = buffer.join("");
  2256. $input.trigger("change");
  2257. }
  2258. }
  2259. },
  2260. mouseenterEvent: function (e) {
  2261. var input = this;
  2262. mouseEnter = true;
  2263. if (document.activeElement !== input && opts.showMaskOnHover) {
  2264. if (input.inputmask._valueGet() !== getBuffer().join("")) {
  2265. writeBuffer(input, getBuffer());
  2266. }
  2267. }
  2268. },
  2269. submitEvent: function (e) { //trigger change on submit if any
  2270. if (undoValue !== getBuffer().join("")) {
  2271. $el.trigger("change");
  2272. }
  2273. if (opts.clearMaskOnLostFocus && getLastValidPosition() === -1 && el.inputmask._valueGet && el.inputmask._valueGet() === getBufferTemplate().join("")) {
  2274. el.inputmask._valueSet(""); //clear masktemplete on submit and still has focus
  2275. }
  2276. if (opts.clearIncomplete && isComplete(getBuffer()) === false) {
  2277. el.inputmask._valueSet("");
  2278. }
  2279. if (opts.removeMaskOnSubmit) {
  2280. el.inputmask._valueSet(el.inputmask.unmaskedvalue(), true);
  2281. setTimeout(function () {
  2282. writeBuffer(el, getBuffer());
  2283. }, 0);
  2284. }
  2285. },
  2286. resetEvent: function (e) {
  2287. el.inputmask.refreshValue = true; //indicate a forced refresh when there is a call to the value before leaving the triggering event fn
  2288. setTimeout(function () {
  2289. $el.trigger("setvalue");
  2290. }, 0);
  2291. }
  2292. };
  2293. function checkVal(input, writeOut, strict, nptvl, initiatingEvent) {
  2294. var inputValue = nptvl.slice(),
  2295. charCodes = "",
  2296. initialNdx = -1,
  2297. result = undefined;
  2298. // console.log(nptvl);
  2299. function isTemplateMatch(ndx, charCodes) {
  2300. var charCodeNdx = getMaskTemplate(true, 0, false).slice(ndx, seekNext(ndx)).join("").indexOf(charCodes);
  2301. return charCodeNdx !== -1 && !isMask(ndx) &&
  2302. (getTest(ndx).match.nativeDef === charCodes.charAt(0) ||
  2303. (getTest(ndx).match.nativeDef === " " && getTest(ndx + 1).match.nativeDef === charCodes.charAt(0)));
  2304. }
  2305. resetMaskSet();
  2306. if (!strict && opts.autoUnmask !== true) {
  2307. var staticInput = getBufferTemplate().slice(0, seekNext(-1)).join(""),
  2308. matches = inputValue.join("").match(new RegExp("^" + Inputmask.escapeRegex(staticInput), "g"));
  2309. if (matches && matches.length > 0) {
  2310. inputValue.splice(0, matches.length * staticInput.length);
  2311. initialNdx = seekNext(initialNdx);
  2312. }
  2313. } else {
  2314. initialNdx = seekNext(initialNdx);
  2315. }
  2316. if (initialNdx === -1) {
  2317. getMaskSet().p = seekNext(initialNdx);
  2318. initialNdx = 0;
  2319. } else getMaskSet().p = initialNdx;
  2320. $.each(inputValue, function (ndx, charCode) {
  2321. // console.log(charCode);
  2322. if (charCode !== undefined) { //inputfallback strips some elements out of the inputarray. $.each logically presents them as undefined
  2323. if (getMaskSet().validPositions[ndx] === undefined && inputValue[ndx] === getPlaceholder(ndx) && isMask(ndx, true) &&
  2324. isValid(ndx, inputValue[ndx], true, undefined, undefined, true) === false) {
  2325. getMaskSet().p++;
  2326. } else {
  2327. var keypress = new $.Event("_checkval");
  2328. keypress.which = charCode.charCodeAt(0);
  2329. charCodes += charCode;
  2330. var lvp = getLastValidPosition(undefined, true),
  2331. prevTest = getTest(lvp),
  2332. nextTest = getTestTemplate(lvp + 1, prevTest ? prevTest.locator.slice() : undefined, lvp);
  2333. if (!isTemplateMatch(initialNdx, charCodes) || strict || opts.autoUnmask) {
  2334. var pos = strict ? ndx : (nextTest.match.fn == null && nextTest.match.optionality && (lvp + 1) < getMaskSet().p ? lvp + 1 : getMaskSet().p);
  2335. result = EventHandlers.keypressEvent.call(input, keypress, true, false, strict, pos);
  2336. if (result) {
  2337. initialNdx = pos + 1;
  2338. charCodes = "";
  2339. }
  2340. } else {
  2341. result = EventHandlers.keypressEvent.call(input, keypress, true, false, true, lvp + 1);
  2342. }
  2343. writeBuffer(undefined, getBuffer(), result.forwardPosition, keypress, false);
  2344. }
  2345. }
  2346. });
  2347. if (writeOut)
  2348. writeBuffer(input, getBuffer(), result ? result.forwardPosition : undefined, initiatingEvent || new $.Event("checkval"), initiatingEvent && initiatingEvent.type === "input");
  2349. }
  2350. function unmaskedvalue(input) {
  2351. if (input) {
  2352. if (input.inputmask === undefined) {
  2353. return input.value;
  2354. }
  2355. if (input.inputmask && input.inputmask.refreshValue) { //forced refresh from the value form.reset
  2356. EventHandlers.setValueEvent.call(input);
  2357. }
  2358. }
  2359. var umValue = [],
  2360. vps = getMaskSet().validPositions;
  2361. for (var pndx in vps) {
  2362. if (vps[pndx].match && vps[pndx].match.fn != null) {
  2363. umValue.push(vps[pndx].input);
  2364. }
  2365. }
  2366. var unmaskedValue = umValue.length === 0 ? "" : (isRTL ? umValue.reverse() : umValue).join("");
  2367. if ($.isFunction(opts.onUnMask)) {
  2368. var bufferValue = (isRTL ? getBuffer().slice().reverse() : getBuffer()).join("");
  2369. unmaskedValue = opts.onUnMask.call(inputmask, bufferValue, unmaskedValue, opts);
  2370. }
  2371. return unmaskedValue;
  2372. }
  2373. function translatePosition(pos) {
  2374. if (isRTL && typeof pos === "number" && (!opts.greedy || opts.placeholder !== "")) {
  2375. pos = el.inputmask._valueGet().length - pos;
  2376. }
  2377. return pos;
  2378. }
  2379. function caret(input, begin, end, notranslate) {
  2380. var range;
  2381. if (begin !== undefined) {
  2382. if ($.isArray(begin)) {
  2383. end = isRTL ? begin[0] : begin[1];
  2384. begin = isRTL ? begin[1] : begin[0];
  2385. }
  2386. if (begin.begin !== undefined) {
  2387. end = isRTL ? begin.begin : begin.end;
  2388. begin = isRTL ? begin.end : begin.begin;
  2389. }
  2390. if (typeof begin === "number") {
  2391. begin = notranslate ? begin : translatePosition(begin);
  2392. end = notranslate ? end : translatePosition(end);
  2393. end = (typeof end == "number") ? end : begin;
  2394. // if (!$(input).is(":visible")) {
  2395. // return;
  2396. // }
  2397. var scrollCalc = parseInt(((input.ownerDocument.defaultView || window).getComputedStyle ? (input.ownerDocument.defaultView || window).getComputedStyle(input, null) : input.currentStyle).fontSize) * end;
  2398. input.scrollLeft = scrollCalc > input.scrollWidth ? scrollCalc : 0;
  2399. if (!iphone && opts.insertMode === false && begin === end) end++; //set visualization for insert/overwrite mode
  2400. input.inputmask.caretPos = {begin: begin, end: end}; //track caret internally
  2401. if (input.setSelectionRange) {
  2402. input.selectionStart = begin;
  2403. input.selectionEnd = end;
  2404. } else if (window.getSelection) {
  2405. range = document.createRange();
  2406. if (input.firstChild === undefined || input.firstChild === null) {
  2407. var textNode = document.createTextNode("");
  2408. input.appendChild(textNode);
  2409. }
  2410. range.setStart(input.firstChild, begin < input.inputmask._valueGet().length ? begin : input.inputmask._valueGet().length);
  2411. range.setEnd(input.firstChild, end < input.inputmask._valueGet().length ? end : input.inputmask._valueGet().length);
  2412. range.collapse(true);
  2413. var sel = window.getSelection();
  2414. sel.removeAllRanges();
  2415. sel.addRange(range);
  2416. //input.focus();
  2417. } else if (input.createTextRange) {
  2418. range = input.createTextRange();
  2419. range.collapse(true);
  2420. range.moveEnd("character", end);
  2421. range.moveStart("character", begin);
  2422. range.select();
  2423. }
  2424. renderColorMask(input, {
  2425. begin: begin,
  2426. end: end
  2427. });
  2428. }
  2429. } else {
  2430. if (input.setSelectionRange) {
  2431. begin = input.selectionStart;
  2432. end = input.selectionEnd;
  2433. } else if (window.getSelection) {
  2434. range = window.getSelection().getRangeAt(0);
  2435. if (range.commonAncestorContainer.parentNode === input || range.commonAncestorContainer === input) {
  2436. begin = range.startOffset;
  2437. end = range.endOffset;
  2438. }
  2439. } else if (document.selection && document.selection.createRange) {
  2440. range = document.selection.createRange();
  2441. begin = 0 - range.duplicate().moveStart("character", -input.inputmask._valueGet().length);
  2442. end = begin + range.text.length;
  2443. }
  2444. /*eslint-disable consistent-return */
  2445. return {
  2446. "begin": notranslate ? begin : translatePosition(begin),
  2447. "end": notranslate ? end : translatePosition(end)
  2448. };
  2449. /*eslint-enable consistent-return */
  2450. }
  2451. }
  2452. function determineLastRequiredPosition(returnDefinition) {
  2453. var buffer = getMaskTemplate(true, getLastValidPosition(), true, true),
  2454. bl = buffer.length,
  2455. pos, lvp = getLastValidPosition(),
  2456. positions = {},
  2457. lvTest = getMaskSet().validPositions[lvp],
  2458. ndxIntlzr = lvTest !== undefined ? lvTest.locator.slice() : undefined,
  2459. testPos;
  2460. for (pos = lvp + 1; pos < buffer.length; pos++) {
  2461. testPos = getTestTemplate(pos, ndxIntlzr, pos - 1);
  2462. ndxIntlzr = testPos.locator.slice();
  2463. positions[pos] = $.extend(true, {}, testPos);
  2464. }
  2465. var lvTestAlt = lvTest && lvTest.alternation !== undefined ? lvTest.locator[lvTest.alternation] : undefined;
  2466. for (pos = bl - 1; pos > lvp; pos--) {
  2467. testPos = positions[pos];
  2468. if ((testPos.match.optionality ||
  2469. (testPos.match.optionalQuantifier && testPos.match.newBlockMarker) ||
  2470. (lvTestAlt &&
  2471. (
  2472. (lvTestAlt !== positions[pos].locator[lvTest.alternation] && testPos.match.fn != null) ||
  2473. (testPos.match.fn === null &&
  2474. testPos.locator[lvTest.alternation] &&
  2475. checkAlternationMatch(testPos.locator[lvTest.alternation].toString().split(","), lvTestAlt.toString().split(",")) &&
  2476. getTests(pos)[0].def !== "")
  2477. )
  2478. )
  2479. ) &&
  2480. buffer[pos] === getPlaceholder(pos, testPos.match)) {
  2481. bl--;
  2482. } else break;
  2483. }
  2484. return returnDefinition ? {
  2485. "l": bl,
  2486. "def": positions[bl] ? positions[bl].match : undefined
  2487. } : bl;
  2488. }
  2489. function clearOptionalTail(buffer) {
  2490. buffer.length = 0;
  2491. var template = getMaskTemplate(true, 0, true, undefined, true), lmnt, validPos;
  2492. while (lmnt = template.shift(), lmnt !== undefined) buffer.push(lmnt);
  2493. return buffer;
  2494. }
  2495. function isComplete(buffer) { //return true / false / undefined (repeat *)
  2496. if ($.isFunction(opts.isComplete)) return opts.isComplete(buffer, opts);
  2497. if (opts.repeat === "*") return undefined;
  2498. var complete = false,
  2499. lrp = determineLastRequiredPosition(true),
  2500. aml = seekPrevious(lrp.l);
  2501. if (lrp.def === undefined || lrp.def.newBlockMarker || lrp.def.optionality || lrp.def.optionalQuantifier) {
  2502. complete = true;
  2503. for (var i = 0; i <= aml; i++) {
  2504. var test = getTestTemplate(i).match;
  2505. if ((test.fn !== null && getMaskSet().validPositions[i] === undefined && test.optionality !== true && test.optionalQuantifier !== true) || (test.fn === null && buffer[i] !== getPlaceholder(i, test))) {
  2506. complete = false;
  2507. break;
  2508. }
  2509. }
  2510. }
  2511. return complete;
  2512. }
  2513. function handleRemove(input, k, pos, strict, fromIsValid) {
  2514. if (opts.numericInput || isRTL) {
  2515. if (k === Inputmask.keyCode.BACKSPACE) {
  2516. k = Inputmask.keyCode.DELETE;
  2517. } else if (k === Inputmask.keyCode.DELETE) {
  2518. k = Inputmask.keyCode.BACKSPACE;
  2519. }
  2520. if (isRTL) {
  2521. var pend = pos.end;
  2522. pos.end = pos.begin;
  2523. pos.begin = pend;
  2524. }
  2525. }
  2526. if (k === Inputmask.keyCode.BACKSPACE && (pos.end - pos.begin < 1 || opts.insertMode === false)) {
  2527. pos.begin = seekPrevious(pos.begin);
  2528. if (getMaskSet().validPositions[pos.begin] !== undefined && getMaskSet().validPositions[pos.begin].input === opts.groupSeparator) {
  2529. pos.begin--;
  2530. }
  2531. if (opts.insertMode === false && pos.end !== getMaskSet().maskLength) {
  2532. pos.end--;
  2533. }
  2534. } else if (k === Inputmask.keyCode.DELETE && pos.begin === pos.end) {
  2535. pos.end = isMask(pos.end, true) && (getMaskSet().validPositions[pos.end] && getMaskSet().validPositions[pos.end].input !== opts.radixPoint) ?
  2536. pos.end + 1 :
  2537. seekNext(pos.end) + 1;
  2538. if (getMaskSet().validPositions[pos.begin] !== undefined && getMaskSet().validPositions[pos.begin].input === opts.groupSeparator) {
  2539. pos.end++;
  2540. }
  2541. }
  2542. revalidateMask(pos);
  2543. if (strict !== true && opts.keepStatic !== false || opts.regex !== null) {
  2544. var result = alternate(true);
  2545. if (result) {
  2546. var newPos = result.caret !== undefined ? result.caret : (result.pos ? seekNext(result.pos.begin ? result.pos.begin : result.pos) : getLastValidPosition(-1, true));
  2547. if (k !== Inputmask.keyCode.DELETE || pos.begin > newPos) {
  2548. pos.begin == newPos;
  2549. }
  2550. }
  2551. }
  2552. var lvp = getLastValidPosition(pos.begin, true);
  2553. if (lvp < pos.begin || pos.begin === -1) {
  2554. //if (lvp === -1) resetMaskSet();
  2555. getMaskSet().p = seekNext(lvp);
  2556. } else if (strict !== true) {
  2557. getMaskSet().p = pos.begin;
  2558. if (fromIsValid !== true) {
  2559. //put position on first valid from pos.begin ~ #1351
  2560. while (getMaskSet().p < lvp && getMaskSet().validPositions[getMaskSet().p] === undefined) {
  2561. getMaskSet().p++;
  2562. }
  2563. }
  2564. }
  2565. }
  2566. function initializeColorMask(input) {
  2567. var computedStyle = (input.ownerDocument.defaultView || window).getComputedStyle(input, null);
  2568. function findCaretPos(clientx) {
  2569. //calculate text width
  2570. var e = document.createElement("span"),
  2571. caretPos;
  2572. for (var style in computedStyle) { //clone styles
  2573. if (isNaN(style) && style.indexOf("font") !== -1) {
  2574. e.style[style] = computedStyle[style];
  2575. }
  2576. }
  2577. e.style.textTransform = computedStyle.textTransform;
  2578. e.style.letterSpacing = computedStyle.letterSpacing;
  2579. e.style.position = "absolute";
  2580. e.style.height = "auto";
  2581. e.style.width = "auto";
  2582. e.style.visibility = "hidden";
  2583. e.style.whiteSpace = "nowrap";
  2584. document.body.appendChild(e);
  2585. var inputText = input.inputmask._valueGet(),
  2586. previousWidth = 0,
  2587. itl;
  2588. for (caretPos = 0, itl = inputText.length; caretPos <= itl; caretPos++) {
  2589. e.innerHTML += inputText.charAt(caretPos) || "_";
  2590. if (e.offsetWidth >= clientx) {
  2591. var offset1 = (clientx - previousWidth);
  2592. var offset2 = e.offsetWidth - clientx;
  2593. e.innerHTML = inputText.charAt(caretPos);
  2594. offset1 -= (e.offsetWidth / 3);
  2595. caretPos = offset1 < offset2 ? caretPos - 1 : caretPos;
  2596. break;
  2597. }
  2598. previousWidth = e.offsetWidth;
  2599. }
  2600. document.body.removeChild(e);
  2601. return caretPos;
  2602. }
  2603. var template = document.createElement("div");
  2604. template.style.width = computedStyle.width;
  2605. template.style.textAlign = computedStyle.textAlign;
  2606. colorMask = document.createElement("div");
  2607. input.inputmask.colorMask = colorMask;
  2608. colorMask.className = "im-colormask";
  2609. input.parentNode.insertBefore(colorMask, input);
  2610. input.parentNode.removeChild(input);
  2611. colorMask.appendChild(input);
  2612. colorMask.appendChild(template);
  2613. input.style.left = template.offsetLeft + "px";
  2614. $(colorMask).on("mouseleave", function (e) {
  2615. return EventHandlers.mouseleaveEvent.call(input, [e]);
  2616. });
  2617. $(colorMask).on("mouseenter", function (e) {
  2618. return EventHandlers.mouseenterEvent.call(input, [e]);
  2619. });
  2620. $(colorMask).on("click", function (e) {
  2621. caret(input, findCaretPos(e.clientX));
  2622. return EventHandlers.clickEvent.call(input, [e]);
  2623. });
  2624. $(input).on("keydown", function (e) {
  2625. if (!e.shiftKey && opts.insertMode !== false) {
  2626. setTimeout(function () {
  2627. renderColorMask(input);
  2628. }, 0);
  2629. }
  2630. });
  2631. }
  2632. Inputmask.prototype.positionColorMask = function (input, template) {
  2633. input.style.left = template.offsetLeft + "px";
  2634. }
  2635. function renderColorMask(input, caretPos, clear) {
  2636. var maskTemplate = [],
  2637. isStatic = false,
  2638. test, testPos, ndxIntlzr, pos = 0;
  2639. function setEntry(entry) {
  2640. if (entry === undefined) entry = "";
  2641. if (!isStatic && (test.fn === null || testPos.input === undefined)) {
  2642. isStatic = true;
  2643. maskTemplate.push("<span class='im-static'>" + entry);
  2644. } else if (isStatic && ((test.fn !== null && testPos.input !== undefined) || test.def === "")) {
  2645. isStatic = false;
  2646. var mtl = maskTemplate.length;
  2647. maskTemplate[mtl - 1] = maskTemplate[mtl - 1] + "</span>";
  2648. maskTemplate.push(entry);
  2649. } else
  2650. maskTemplate.push(entry);
  2651. }
  2652. function setCaret() {
  2653. if (document.activeElement === input) {
  2654. maskTemplate.splice(caretPos.begin, 0,
  2655. (caretPos.begin === caretPos.end || caretPos.end > getMaskSet().maskLength) ?
  2656. '<mark class="im-caret" style="border-right-width: 1px;border-right-style: solid;">' :
  2657. '<mark class="im-caret-select">');
  2658. maskTemplate.splice(caretPos.end + 1, 0, "</mark>");
  2659. }
  2660. }
  2661. if (colorMask !== undefined) {
  2662. var buffer = getBuffer();
  2663. if (caretPos === undefined) {
  2664. caretPos = caret(input);
  2665. } else if (caretPos.begin === undefined) {
  2666. caretPos = {
  2667. begin: caretPos,
  2668. end: caretPos
  2669. };
  2670. }
  2671. if (clear !== true) {
  2672. var lvp = getLastValidPosition();
  2673. do {
  2674. if (getMaskSet().validPositions[pos]) {
  2675. testPos = getMaskSet().validPositions[pos];
  2676. test = testPos.match;
  2677. ndxIntlzr = testPos.locator.slice();
  2678. setEntry(buffer[pos]);
  2679. } else {
  2680. testPos = getTestTemplate(pos, ndxIntlzr, pos - 1);
  2681. test = testPos.match;
  2682. ndxIntlzr = testPos.locator.slice();
  2683. if (opts.jitMasking === false || pos < lvp || (typeof opts.jitMasking === "number" && isFinite(opts.jitMasking) && opts.jitMasking > pos)) {
  2684. setEntry(getPlaceholder(pos, test));
  2685. } else isStatic = false; //break infinite loop
  2686. }
  2687. pos++;
  2688. } while ((maxLength === undefined || pos < maxLength) && (test.fn !== null || test.def !== "") || lvp > pos || isStatic);
  2689. if (isStatic) setEntry();
  2690. setCaret();
  2691. }
  2692. var template = colorMask.getElementsByTagName("div")[0];
  2693. template.innerHTML = maskTemplate.join("");
  2694. input.inputmask.positionColorMask(input, template);
  2695. }
  2696. }
  2697. function mask(elem) {
  2698. function isElementTypeSupported(input, opts) {
  2699. function patchValueProperty(npt) {
  2700. var valueGet;
  2701. var valueSet;
  2702. function patchValhook(type) {
  2703. if ($.valHooks && ($.valHooks[type] === undefined || $.valHooks[type].inputmaskpatch !== true)) {
  2704. var valhookGet = $.valHooks[type] && $.valHooks[type].get ? $.valHooks[type].get : function (elem) {
  2705. return elem.value;
  2706. };
  2707. var valhookSet = $.valHooks[type] && $.valHooks[type].set ? $.valHooks[type].set : function (elem, value) {
  2708. elem.value = value;
  2709. return elem;
  2710. };
  2711. $.valHooks[type] = {
  2712. get: function (elem) {
  2713. if (elem.inputmask) {
  2714. if (elem.inputmask.opts.autoUnmask) {
  2715. return elem.inputmask.unmaskedvalue();
  2716. } else {
  2717. var result = valhookGet(elem);
  2718. return getLastValidPosition(undefined, undefined, elem.inputmask.maskset.validPositions) !== -1 || opts.nullable !== true ? result : "";
  2719. }
  2720. } else return valhookGet(elem);
  2721. },
  2722. set: function (elem, value) {
  2723. var $elem = $(elem),
  2724. result;
  2725. result = valhookSet(elem, value);
  2726. if (elem.inputmask) {
  2727. $elem.trigger("setvalue", [value]);
  2728. }
  2729. return result;
  2730. },
  2731. inputmaskpatch: true
  2732. };
  2733. }
  2734. }
  2735. function getter() {
  2736. if (this.inputmask) {
  2737. return this.inputmask.opts.autoUnmask ?
  2738. this.inputmask.unmaskedvalue() :
  2739. (getLastValidPosition() !== -1 || opts.nullable !== true ?
  2740. (document.activeElement === this && opts.clearMaskOnLostFocus ?
  2741. (isRTL ? clearOptionalTail(getBuffer().slice()).reverse() : clearOptionalTail(getBuffer().slice())).join("") :
  2742. valueGet.call(this)) :
  2743. "");
  2744. } else return valueGet.call(this);
  2745. }
  2746. function setter(value) {
  2747. valueSet.call(this, value);
  2748. if (this.inputmask) {
  2749. $(this).trigger("setvalue", [value]);
  2750. }
  2751. }
  2752. function installNativeValueSetFallback(npt) {
  2753. EventRuler.on(npt, "mouseenter", function (event) {
  2754. var $input = $(this),
  2755. input = this,
  2756. value = input.inputmask._valueGet();
  2757. if (value !== getBuffer().join("") /*&& getLastValidPosition() > 0*/) {
  2758. $input.trigger("setvalue");
  2759. }
  2760. });
  2761. }
  2762. if (!npt.inputmask.__valueGet) {
  2763. if (opts.noValuePatching !== true) {
  2764. if (Object.getOwnPropertyDescriptor) {
  2765. if (typeof Object.getPrototypeOf !== "function") {
  2766. Object.getPrototypeOf = typeof "test".__proto__ === "object" ? function (object) {
  2767. return object.__proto__;
  2768. } : function (object) {
  2769. return object.constructor.prototype;
  2770. };
  2771. }
  2772. var valueProperty = Object.getPrototypeOf ? Object.getOwnPropertyDescriptor(Object.getPrototypeOf(npt), "value") : undefined;
  2773. if (valueProperty && valueProperty.get && valueProperty.set) {
  2774. valueGet = valueProperty.get;
  2775. valueSet = valueProperty.set;
  2776. Object.defineProperty(npt, "value", {
  2777. get: getter,
  2778. set: setter,
  2779. configurable: true
  2780. });
  2781. } else if (npt.tagName !== "INPUT") {
  2782. valueGet = function () {
  2783. return this.textContent;
  2784. };
  2785. valueSet = function (value) {
  2786. this.textContent = value;
  2787. };
  2788. Object.defineProperty(npt, "value", {
  2789. get: getter,
  2790. set: setter,
  2791. configurable: true
  2792. });
  2793. }
  2794. } else if (document.__lookupGetter__ && npt.__lookupGetter__("value")) {
  2795. valueGet = npt.__lookupGetter__("value");
  2796. valueSet = npt.__lookupSetter__("value");
  2797. npt.__defineGetter__("value", getter);
  2798. npt.__defineSetter__("value", setter);
  2799. }
  2800. npt.inputmask.__valueGet = valueGet; //store native property getter
  2801. npt.inputmask.__valueSet = valueSet; //store native property setter
  2802. }
  2803. npt.inputmask._valueGet = function (overruleRTL) {
  2804. return isRTL && overruleRTL !== true ? valueGet.call(this.el).split("").reverse().join("") : valueGet.call(this.el);
  2805. };
  2806. npt.inputmask._valueSet = function (value, overruleRTL) { //null check is needed for IE8 => otherwise converts to "null"
  2807. valueSet.call(this.el, (value === null || value === undefined) ? "" : ((overruleRTL !== true && isRTL) ? value.split("").reverse().join("") : value));
  2808. };
  2809. if (valueGet === undefined) { //jquery.val fallback
  2810. valueGet = function () {
  2811. return this.value;
  2812. };
  2813. valueSet = function (value) {
  2814. this.value = value;
  2815. };
  2816. patchValhook(npt.type);
  2817. installNativeValueSetFallback(npt);
  2818. }
  2819. }
  2820. }
  2821. var elementType = input.getAttribute("type");
  2822. var isSupported = (input.tagName === "INPUT" && $.inArray(elementType, opts.supportsInputType) !== -1) || input.isContentEditable || input.tagName === "TEXTAREA";
  2823. if (!isSupported) {
  2824. if (input.tagName === "INPUT") {
  2825. var el = document.createElement("input");
  2826. el.setAttribute("type", elementType);
  2827. isSupported = el.type === "text"; //apply mask only if the type is not natively supported
  2828. el = null;
  2829. } else isSupported = "partial";
  2830. }
  2831. if (isSupported !== false) {
  2832. patchValueProperty(input);
  2833. } else input.inputmask = undefined;
  2834. return isSupported;
  2835. }
  2836. //unbind all events - to make sure that no other mask will interfere when re-masking
  2837. EventRuler.off(elem);
  2838. var isSupported = isElementTypeSupported(elem, opts);
  2839. if (isSupported !== false) {
  2840. el = elem;
  2841. $el = $(el);
  2842. //read maxlength prop from el
  2843. maxLength = el !== undefined ? el.maxLength : undefined;
  2844. if (maxLength === -1) maxLength = undefined;
  2845. if (opts.colorMask === true) {
  2846. initializeColorMask(el);
  2847. }
  2848. if (mobile) {
  2849. if ("inputmode" in el) {
  2850. el.inputmode = opts.inputmode;
  2851. el.setAttribute("inputmode", opts.inputmode);
  2852. }
  2853. if (opts.disablePredictiveText === true) {
  2854. if ("autocorrect" in el) { //safari
  2855. el.autocorrect = false;
  2856. } else {
  2857. if (opts.colorMask !== true) {
  2858. initializeColorMask(el);
  2859. }
  2860. el.type = "password";
  2861. }
  2862. }
  2863. }
  2864. if (isSupported === true) {
  2865. //bind events
  2866. EventRuler.on(el, "submit", EventHandlers.submitEvent);
  2867. EventRuler.on(el, "reset", EventHandlers.resetEvent);
  2868. EventRuler.on(el, "blur", EventHandlers.blurEvent);
  2869. EventRuler.on(el, "focus", EventHandlers.focusEvent);
  2870. if (opts.colorMask !== true) {
  2871. EventRuler.on(el, "click", EventHandlers.clickEvent);
  2872. EventRuler.on(el, "mouseleave", EventHandlers.mouseleaveEvent);
  2873. EventRuler.on(el, "mouseenter", EventHandlers.mouseenterEvent);
  2874. }
  2875. EventRuler.on(el, "dblclick", EventHandlers.dblclickEvent);
  2876. EventRuler.on(el, "paste", EventHandlers.pasteEvent);
  2877. EventRuler.on(el, "dragdrop", EventHandlers.pasteEvent);
  2878. EventRuler.on(el, "drop", EventHandlers.pasteEvent);
  2879. EventRuler.on(el, "cut", EventHandlers.cutEvent);
  2880. EventRuler.on(el, "complete", opts.oncomplete);
  2881. EventRuler.on(el, "incomplete", opts.onincomplete);
  2882. EventRuler.on(el, "cleared", opts.oncleared);
  2883. if (!mobile && opts.inputEventOnly !== true) {
  2884. EventRuler.on(el, "keydown", EventHandlers.keydownEvent);
  2885. EventRuler.on(el, "keypress", EventHandlers.keypressEvent);
  2886. } else {
  2887. el.removeAttribute("maxLength");
  2888. }
  2889. EventRuler.on(el, "compositionstart", $.noop);
  2890. EventRuler.on(el, "compositionupdate", $.noop);
  2891. EventRuler.on(el, "compositionend", $.noop);
  2892. EventRuler.on(el, "keyup", $.noop);
  2893. EventRuler.on(el, "input", EventHandlers.inputFallBackEvent);
  2894. EventRuler.on(el, "beforeinput", $.noop); //https://github.com/w3c/input-events - to implement
  2895. }
  2896. EventRuler.on(el, "setvalue", EventHandlers.setValueEvent);
  2897. //apply mask
  2898. undoValue = getBufferTemplate().join(""); //initialize the buffer and getmasklength
  2899. if (el.inputmask._valueGet(true) !== "" || opts.clearMaskOnLostFocus === false || document.activeElement === el) {
  2900. var initialValue = $.isFunction(opts.onBeforeMask) ? (opts.onBeforeMask.call(inputmask, el.inputmask._valueGet(true), opts) || el.inputmask._valueGet(true)) : el.inputmask._valueGet(true);
  2901. if (initialValue !== "") checkVal(el, true, false, isRTL ? initialValue.split("").reverse() : initialValue.split(""));
  2902. var buffer = getBuffer().slice();
  2903. undoValue = buffer.join("");
  2904. // Wrap document.activeElement in a try/catch block since IE9 throw "Unspecified error" if document.activeElement is undefined when we are in an IFrame.
  2905. if (isComplete(buffer) === false) {
  2906. if (opts.clearIncomplete) {
  2907. resetMaskSet();
  2908. }
  2909. }
  2910. if (opts.clearMaskOnLostFocus && document.activeElement !== el) {
  2911. if (getLastValidPosition() === -1) {
  2912. buffer = [];
  2913. } else {
  2914. clearOptionalTail(buffer);
  2915. }
  2916. }
  2917. if (opts.clearMaskOnLostFocus === false || (opts.showMaskOnFocus && document.activeElement === el) || el.inputmask._valueGet(true) !== "")
  2918. writeBuffer(el, buffer);
  2919. if (document.activeElement === el) { //position the caret when in focus
  2920. caret(el, seekNext(getLastValidPosition()));
  2921. }
  2922. }
  2923. }
  2924. }
  2925. //action object
  2926. var valueBuffer;
  2927. if (actionObj !== undefined) {
  2928. switch (actionObj.action) {
  2929. case "isComplete":
  2930. el = actionObj.el;
  2931. return isComplete(getBuffer());
  2932. case "unmaskedvalue":
  2933. if (el === undefined || actionObj.value !== undefined) {
  2934. valueBuffer = actionObj.value;
  2935. valueBuffer = ($.isFunction(opts.onBeforeMask) ? (opts.onBeforeMask.call(inputmask, valueBuffer, opts) || valueBuffer) : valueBuffer).split("");
  2936. checkVal(undefined, false, false, isRTL ? valueBuffer.reverse() : valueBuffer);
  2937. if ($.isFunction(opts.onBeforeWrite)) opts.onBeforeWrite.call(inputmask, undefined, getBuffer(), 0, opts);
  2938. }
  2939. return unmaskedvalue(el);
  2940. case "mask":
  2941. mask(el);
  2942. break;
  2943. case "format":
  2944. valueBuffer = ($.isFunction(opts.onBeforeMask) ? (opts.onBeforeMask.call(inputmask, actionObj.value, opts) || actionObj.value) : actionObj.value).split("");
  2945. checkVal(undefined, true, false, isRTL ? valueBuffer.reverse() : valueBuffer);
  2946. if (actionObj.metadata) {
  2947. return {
  2948. value: isRTL ? getBuffer().slice().reverse().join("") : getBuffer().join(""),
  2949. metadata: maskScope.call(this, {
  2950. "action": "getmetadata"
  2951. }, maskset, opts)
  2952. };
  2953. }
  2954. return isRTL ? getBuffer().slice().reverse().join("") : getBuffer().join("");
  2955. case "isValid":
  2956. if (actionObj.value) {
  2957. valueBuffer = actionObj.value.split("");
  2958. checkVal(undefined, true, true, isRTL ? valueBuffer.reverse() : valueBuffer);
  2959. } else {
  2960. actionObj.value = getBuffer().join("");
  2961. }
  2962. var buffer = getBuffer();
  2963. var rl = determineLastRequiredPosition(),
  2964. lmib = buffer.length - 1;
  2965. for (; lmib > rl; lmib--) {
  2966. if (isMask(lmib)) break;
  2967. }
  2968. buffer.splice(rl, lmib + 1 - rl);
  2969. return isComplete(buffer) && actionObj.value === getBuffer().join("");
  2970. case "getemptymask":
  2971. return getBufferTemplate().join("");
  2972. case "remove":
  2973. if (el && el.inputmask) {
  2974. $.data(el, "_inputmask_opts", null); //invalidate
  2975. $el = $(el);
  2976. //writeout the value
  2977. el.inputmask._valueSet(opts.autoUnmask ? unmaskedvalue(el) : el.inputmask._valueGet(true));
  2978. //unbind all events
  2979. EventRuler.off(el);
  2980. //remove colormask if used
  2981. if (el.inputmask.colorMask) {
  2982. colorMask = el.inputmask.colorMask;
  2983. colorMask.removeChild(el);
  2984. colorMask.parentNode.insertBefore(el, colorMask);
  2985. colorMask.parentNode.removeChild(colorMask);
  2986. }
  2987. //restore the value property
  2988. var valueProperty;
  2989. if (Object.getOwnPropertyDescriptor && Object.getPrototypeOf) {
  2990. valueProperty = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(el), "value");
  2991. if (valueProperty) {
  2992. if (el.inputmask.__valueGet) {
  2993. Object.defineProperty(el, "value", {
  2994. get: el.inputmask.__valueGet,
  2995. set: el.inputmask.__valueSet,
  2996. configurable: true
  2997. });
  2998. }
  2999. }
  3000. } else if (document.__lookupGetter__ && el.__lookupGetter__("value")) {
  3001. if (el.inputmask.__valueGet) {
  3002. el.__defineGetter__("value", el.inputmask.__valueGet);
  3003. el.__defineSetter__("value", el.inputmask.__valueSet);
  3004. }
  3005. }
  3006. //clear data
  3007. el.inputmask = undefined;
  3008. }
  3009. return el;
  3010. break;
  3011. case "getmetadata":
  3012. if ($.isArray(maskset.metadata)) {
  3013. var maskTarget = getMaskTemplate(true, 0, false).join("");
  3014. $.each(maskset.metadata, function (ndx, mtdt) {
  3015. if (mtdt.mask === maskTarget) {
  3016. maskTarget = mtdt;
  3017. return false;
  3018. }
  3019. });
  3020. return maskTarget;
  3021. }
  3022. return maskset.metadata;
  3023. }
  3024. }
  3025. }
  3026. //make inputmask available
  3027. return Inputmask;
  3028. }
  3029. ))
  3030. ;