validation-tests.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550
  1. export {
  2. determineTestTemplate,
  3. getDecisionTaker,
  4. getMaskTemplate,
  5. getPlaceholder,
  6. getTest,
  7. getTests,
  8. getTestTemplate,
  9. isSubsetOf
  10. };
  11. function getLocator(tst, align) { //need to align the locators to be correct
  12. var locator = (tst.alternation != undefined ? tst.mloc[getDecisionTaker(tst)] : tst.locator).join("");
  13. if (locator !== "") while (locator.length < align) locator += "0";
  14. return locator;
  15. }
  16. function getDecisionTaker(tst) {
  17. var decisionTaker = tst.locator[tst.alternation];
  18. if (typeof decisionTaker == "string" && decisionTaker.length > 0) { //no decision taken ~ take first one as decider
  19. decisionTaker = decisionTaker.split(",")[0];
  20. }
  21. return decisionTaker !== undefined ? decisionTaker.toString() : "";
  22. }
  23. //tobe put on prototype?
  24. function getPlaceholder(pos, test, returnPL) {
  25. const inputmask = this,
  26. opts = this.opts,
  27. maskset = this.maskset;
  28. test = test || getTest.call(inputmask, pos).match;
  29. if (test.placeholder !== undefined || returnPL === true) {
  30. return typeof test.placeholder === "function" ? test.placeholder(opts) : test.placeholder;
  31. } else if (test.static === true) {
  32. if (pos > -1 && maskset.validPositions[pos] === undefined) {
  33. var tests = getTests.call(inputmask, pos),
  34. staticAlternations = [],
  35. prevTest;
  36. if (tests.length > 1 + (tests[tests.length - 1].match.def === "" ? 1 : 0)) {
  37. for (var i = 0; i < tests.length; i++) {
  38. if (tests[i].match.def !== "" && tests[i].match.optionality !== true && tests[i].match.optionalQuantifier !== true &&
  39. (tests[i].match.static === true || (prevTest === undefined || tests[i].match.fn.test(prevTest.match.def, maskset, pos, true, opts) !== false))) {
  40. staticAlternations.push(tests[i]);
  41. if (tests[i].match.static === true) prevTest = tests[i];
  42. if (staticAlternations.length > 1) {
  43. if (/[0-9a-bA-Z]/.test(staticAlternations[0].match.def)) {
  44. return opts.placeholder.charAt(pos % opts.placeholder.length);
  45. }
  46. }
  47. }
  48. }
  49. }
  50. }
  51. return test.def;
  52. }
  53. return opts.placeholder.charAt(pos % opts.placeholder.length);
  54. }
  55. //tobe put on prototype?
  56. function getMaskTemplate(baseOnInput, minimalPos, includeMode, noJit, clearOptionalTail) {
  57. //includeMode true => input, undefined => placeholder, false => mask
  58. var inputmask = this,
  59. opts = this.opts,
  60. maskset = this.maskset;
  61. var greedy = opts.greedy;
  62. if (clearOptionalTail) opts.greedy = false;
  63. minimalPos = minimalPos || 0;
  64. var maskTemplate = [],
  65. ndxIntlzr, pos = 0,
  66. test, testPos, jitRenderStatic;
  67. do {
  68. if (baseOnInput === true && maskset.validPositions[pos]) {
  69. testPos = (clearOptionalTail && maskset.validPositions[pos].match.optionality === true
  70. && maskset.validPositions[pos + 1] === undefined
  71. && (maskset.validPositions[pos].generatedInput === true || (maskset.validPositions[pos].input == opts.skipOptionalPartCharacter && pos > 0)))
  72. ? determineTestTemplate.call(inputmask, pos, getTests.call(inputmask, pos, ndxIntlzr, pos - 1))
  73. : maskset.validPositions[pos];
  74. test = testPos.match;
  75. ndxIntlzr = testPos.locator.slice();
  76. maskTemplate.push(includeMode === true ? testPos.input : includeMode === false ? test.nativeDef : getPlaceholder.call(inputmask, pos, test));
  77. } else {
  78. testPos = getTestTemplate.call(inputmask, pos, ndxIntlzr, pos - 1);
  79. test = testPos.match;
  80. ndxIntlzr = testPos.locator.slice();
  81. var jitMasking = noJit === true ? false : (opts.jitMasking !== false ? opts.jitMasking : test.jit);
  82. //check for groupSeparator is a hack for the numerics as we don't want the render of the groupSeparator beforehand
  83. jitRenderStatic = ((jitRenderStatic && test.static && test.def !== opts.groupSeparator && test.fn === null) || (maskset.validPositions[pos - 1] && test.static && test.def !== opts.groupSeparator && test.fn === null)) && maskset.tests[pos] && maskset.tests[pos].length === 1;
  84. if (jitRenderStatic || jitMasking === false || jitMasking === undefined /*|| pos < lvp*/ || (typeof jitMasking === "number" && isFinite(jitMasking) && jitMasking > pos)) {
  85. maskTemplate.push(includeMode === false ? test.nativeDef : getPlaceholder.call(inputmask, pos, test));
  86. } else {
  87. jitRenderStatic = false;
  88. }
  89. }
  90. pos++;
  91. } while ((inputmask.maxLength === undefined || pos < inputmask.maxLength) && (test.static !== true || test.def !== "") || minimalPos > pos);
  92. if (maskTemplate[maskTemplate.length - 1] === "") {
  93. maskTemplate.pop(); //drop the last one which is empty
  94. }
  95. if (includeMode !== false || //do not alter the masklength when just retrieving the maskdefinition
  96. maskset.maskLength === undefined) //just make sure the maskLength gets initialized in all cases (needed for isValid)
  97. {
  98. maskset.maskLength = pos - 1;
  99. }
  100. opts.greedy = greedy;
  101. return maskTemplate;
  102. }
  103. //tobe put on prototype?
  104. function getTestTemplate(pos, ndxIntlzr, tstPs) {
  105. var inputmask = this,
  106. maskset = this.maskset;
  107. return maskset.validPositions[pos] || determineTestTemplate.call(inputmask, pos, getTests.call(inputmask, pos, ndxIntlzr ? ndxIntlzr.slice() : ndxIntlzr, tstPs));
  108. }
  109. //tobe put on prototype?
  110. function determineTestTemplate(pos, tests) {
  111. var inputmask = this,
  112. opts = this.opts;
  113. pos = pos > 0 ? pos - 1 : 0;
  114. var altTest = getTest.call(inputmask, pos), targetLocator = getLocator(altTest), tstLocator, closest, bestMatch;
  115. for (var ndx = 0; ndx < tests.length; ndx++) { //find best matching
  116. var tst = tests[ndx];
  117. tstLocator = getLocator(tst, targetLocator.length);
  118. var distance = Math.abs(tstLocator - targetLocator);
  119. if (closest === undefined
  120. || (tstLocator !== "" && distance < closest)
  121. || (bestMatch && !opts.greedy && bestMatch.match.optionality && bestMatch.match.newBlockMarker === "master" && (!tst.match.optionality || !tst.match.newBlockMarker))
  122. || (bestMatch && bestMatch.match.optionalQuantifier && !tst.match.optionalQuantifier)) {
  123. closest = distance;
  124. bestMatch = tst;
  125. }
  126. }
  127. return bestMatch;
  128. }
  129. //tobe put on prototype?
  130. function getTest(pos, tests) {
  131. var inputmask = this,
  132. maskset = this.maskset;
  133. if (maskset.validPositions[pos]) {
  134. return maskset.validPositions[pos];
  135. }
  136. return (tests || getTests.call(inputmask, pos))[0];
  137. }
  138. function isSubsetOf(source, target, opts) {
  139. function expand(pattern) {
  140. var expanded = [], start = -1, end;
  141. for (var i = 0, l = pattern.length; i < l; i++) {
  142. if (pattern.charAt(i) === "-") {
  143. end = pattern.charCodeAt(i + 1);
  144. while (++start < end) expanded.push(String.fromCharCode(start));
  145. } else {
  146. start = pattern.charCodeAt(i);
  147. expanded.push(pattern.charAt(i));
  148. }
  149. }
  150. return expanded.join("");
  151. }
  152. if (source.match.def === target.match.nativeDef) return true;
  153. if ((opts.regex || (source.match.fn instanceof RegExp && target.match.fn instanceof RegExp)) && source.match.static !== true && target.match.static !== true) { //is regex a subset
  154. return expand(target.match.fn.toString().replace(/[[\]/]/g, "")).indexOf(expand(source.match.fn.toString().replace(/[[\]/]/g, ""))) !== -1;
  155. }
  156. return false;
  157. }
  158. //tobe put on prototype?
  159. function getTests(pos, ndxIntlzr, tstPs) {
  160. var inputmask = this,
  161. $ = this.dependencyLib,
  162. maskset = this.maskset,
  163. opts = this.opts,
  164. el = this.el,
  165. maskTokens = maskset.maskToken,
  166. testPos = ndxIntlzr ? tstPs : 0,
  167. ndxInitializer = ndxIntlzr ? ndxIntlzr.slice() : [0],
  168. matches = [],
  169. insertStop = false,
  170. latestMatch,
  171. cacheDependency = ndxIntlzr ? ndxIntlzr.join("") : "";
  172. function resolveTestFromToken(maskToken, ndxInitializer, loopNdx, quantifierRecurse) { //ndxInitializer contains a set of indexes to speedup searches in the mtokens
  173. function handleMatch(match, loopNdx, quantifierRecurse) {
  174. function isFirstMatch(latestMatch, tokenGroup) {
  175. var firstMatch = tokenGroup.matches.indexOf(latestMatch) === 0;
  176. if (!firstMatch) {
  177. tokenGroup.matches.every(function (match, ndx) {
  178. if (match.isQuantifier === true) {
  179. firstMatch = isFirstMatch(latestMatch, tokenGroup.matches[ndx - 1]);
  180. } else if (Object.prototype.hasOwnProperty.call(match, "matches")) firstMatch = isFirstMatch(latestMatch, match);
  181. if (firstMatch) return false;
  182. return true;
  183. });
  184. }
  185. return firstMatch;
  186. }
  187. function resolveNdxInitializer(pos, alternateNdx, targetAlternation) {
  188. var bestMatch, indexPos;
  189. if (maskset.tests[pos] || maskset.validPositions[pos]) {
  190. (maskset.tests[pos] || [maskset.validPositions[pos]]).every(function (lmnt, ndx) {
  191. if (lmnt.mloc[alternateNdx]) {
  192. bestMatch = lmnt;
  193. return false; //break
  194. }
  195. var alternation = targetAlternation !== undefined ? targetAlternation : lmnt.alternation,
  196. ndxPos = lmnt.locator[alternation] !== undefined ? lmnt.locator[alternation].toString().indexOf(alternateNdx) : -1;
  197. if ((indexPos === undefined || ndxPos < indexPos) && ndxPos !== -1) {
  198. bestMatch = lmnt;
  199. indexPos = ndxPos;
  200. }
  201. return true;
  202. });
  203. }
  204. if (bestMatch) {
  205. var bestMatchAltIndex = bestMatch.locator[bestMatch.alternation];
  206. var locator = bestMatch.mloc[alternateNdx] || bestMatch.mloc[bestMatchAltIndex] || bestMatch.locator;
  207. return locator.slice((targetAlternation !== undefined ? targetAlternation : bestMatch.alternation) + 1);
  208. } else {
  209. return targetAlternation !== undefined ? resolveNdxInitializer(pos, alternateNdx) : undefined;
  210. }
  211. }
  212. function staticCanMatchDefinition(source, target) {
  213. return source.match.static === true && target.match.static !== true ? target.match.fn.test(source.match.def, maskset, pos, false, opts, false) : false;
  214. }
  215. //mergelocators for retrieving the correct locator match when merging
  216. function setMergeLocators(targetMatch, altMatch) {
  217. var alternationNdx = targetMatch.alternation,
  218. shouldMerge = altMatch === undefined || (alternationNdx === altMatch.alternation &&
  219. targetMatch.locator[alternationNdx].toString().indexOf(altMatch.locator[alternationNdx]) === -1);
  220. if (!shouldMerge && alternationNdx > altMatch.alternation) {
  221. for (var i = altMatch.alternation; i < alternationNdx; i++) {
  222. if (targetMatch.locator[i] !== altMatch.locator[i]) {
  223. alternationNdx = i;
  224. shouldMerge = true;
  225. break;
  226. }
  227. }
  228. }
  229. if (shouldMerge) {
  230. targetMatch.mloc = targetMatch.mloc || {};
  231. var locNdx = targetMatch.locator[alternationNdx];
  232. if (locNdx === undefined) {
  233. targetMatch.alternation = undefined;
  234. } else {
  235. if (typeof locNdx === "string") locNdx = locNdx.split(",")[0];
  236. if (targetMatch.mloc[locNdx] === undefined) targetMatch.mloc[locNdx] = targetMatch.locator.slice();
  237. if (altMatch !== undefined) {
  238. for (var ndx in altMatch.mloc) {
  239. if (typeof ndx === "string") ndx = ndx.split(",")[0];
  240. if (targetMatch.mloc[ndx] === undefined) targetMatch.mloc[ndx] = altMatch.mloc[ndx];
  241. }
  242. targetMatch.locator[alternationNdx] = Object.keys(targetMatch.mloc).join(",");
  243. }
  244. return true;
  245. }
  246. }
  247. return false;
  248. }
  249. function isSameLevel(targetMatch, altMatch) {
  250. if (targetMatch.locator.length !== altMatch.locator.length) {
  251. return false;
  252. }
  253. for (let locNdx = targetMatch.alternation + 1; locNdx < targetMatch.locator.length; locNdx++) {
  254. if (targetMatch.locator[locNdx] !== altMatch.locator[locNdx]) {
  255. return false;
  256. }
  257. }
  258. return true;
  259. }
  260. if (testPos > (pos + opts._maxTestPos)) {
  261. 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. " + maskset.mask;
  262. }
  263. if (testPos === pos && match.matches === undefined) {
  264. matches.push({
  265. "match": match,
  266. "locator": loopNdx.reverse(),
  267. "cd": cacheDependency,
  268. "mloc": {}
  269. });
  270. return true;
  271. } else if (match.matches !== undefined) {
  272. if (match.isGroup && quantifierRecurse !== match) { //when a group pass along to the quantifier
  273. match = handleMatch(maskToken.matches[maskToken.matches.indexOf(match) + 1], loopNdx, quantifierRecurse);
  274. if (match) return true;
  275. } else if (match.isOptional) {
  276. var optionalToken = match, mtchsNdx = matches.length;
  277. match = resolveTestFromToken(match, ndxInitializer, loopNdx, quantifierRecurse);
  278. if (match) {
  279. //mark optionality in matches
  280. matches.forEach(function (mtch, ndx) {
  281. if (ndx >= mtchsNdx) {
  282. mtch.match.optionality = true;
  283. }
  284. });
  285. latestMatch = matches[matches.length - 1].match;
  286. if (quantifierRecurse === undefined && isFirstMatch(latestMatch, optionalToken)) { //prevent loop see #698
  287. insertStop = true; //insert a stop
  288. testPos = pos; //match the position after the group
  289. } else {
  290. return true;
  291. }
  292. }
  293. } else if (match.isAlternator) {
  294. var alternateToken = match,
  295. malternateMatches = [],
  296. maltMatches,
  297. currentMatches = matches.slice(),
  298. loopNdxCnt = loopNdx.length,
  299. unMatchedAlternation = false;
  300. var altIndex = ndxInitializer.length > 0 ? ndxInitializer.shift() : -1;
  301. if (altIndex === -1 || typeof altIndex === "string") {
  302. var currentPos = testPos,
  303. ndxInitializerClone = ndxInitializer.slice(),
  304. altIndexArr = [],
  305. amndx;
  306. if (typeof altIndex == "string") {
  307. altIndexArr = altIndex.split(",");
  308. } else {
  309. for (amndx = 0; amndx < alternateToken.matches.length; amndx++) {
  310. altIndexArr.push(amndx.toString());
  311. }
  312. }
  313. if (maskset.excludes[pos] !== undefined) {
  314. var altIndexArrClone = altIndexArr.slice();
  315. for (var i = 0, exl = maskset.excludes[pos].length; i < exl; i++) {
  316. var excludeSet = maskset.excludes[pos][i].toString().split(":");
  317. if (loopNdx.length == excludeSet[1]) {
  318. altIndexArr.splice(altIndexArr.indexOf(excludeSet[0]), 1);
  319. }
  320. }
  321. if (altIndexArr.length === 0) { //fully alternated => reset
  322. delete maskset.excludes[pos];
  323. altIndexArr = altIndexArrClone;
  324. }
  325. }
  326. if (opts.keepStatic === true || (isFinite(parseInt(opts.keepStatic)) && currentPos >= opts.keepStatic)) altIndexArr = altIndexArr.slice(0, 1);
  327. for (var ndx = 0; ndx < altIndexArr.length; ndx++) {
  328. amndx = parseInt(altIndexArr[ndx]);
  329. matches = [];
  330. //set the correct ndxInitializer
  331. ndxInitializer = typeof altIndex === "string" ? resolveNdxInitializer(testPos, amndx, loopNdxCnt) || ndxInitializerClone.slice() : ndxInitializerClone.slice();
  332. var tokenMatch = alternateToken.matches[amndx];
  333. if (tokenMatch && handleMatch(tokenMatch, [amndx].concat(loopNdx), quantifierRecurse)) {
  334. match = true;
  335. } else {
  336. if (ndx === 0) {
  337. unMatchedAlternation = true;
  338. }
  339. if (tokenMatch && tokenMatch.matches && tokenMatch.matches.length > alternateToken.matches[0].matches.length) {
  340. break;
  341. }
  342. }
  343. maltMatches = matches.slice();
  344. testPos = currentPos;
  345. matches = [];
  346. //fuzzy merge matches
  347. for (var ndx1 = 0; ndx1 < maltMatches.length; ndx1++) {
  348. var altMatch = maltMatches[ndx1],
  349. dropMatch = false;
  350. altMatch.match.jit = altMatch.match.jit || unMatchedAlternation; //mark jit when there are unmatched alternations ex: mask: "(a|aa)"
  351. altMatch.alternation = altMatch.alternation || loopNdxCnt;
  352. setMergeLocators(altMatch);
  353. for (var ndx2 = 0; ndx2 < malternateMatches.length; ndx2++) {
  354. var altMatch2 = malternateMatches[ndx2];
  355. if (typeof altIndex !== "string" || (altMatch.alternation !== undefined && altIndexArr.includes(altMatch.locator[altMatch.alternation].toString()))) {
  356. if (altMatch.match.nativeDef === altMatch2.match.nativeDef) {
  357. dropMatch = true;
  358. setMergeLocators(altMatch2, altMatch);
  359. break;
  360. } else if (isSubsetOf(altMatch, altMatch2, opts)) {
  361. if (setMergeLocators(altMatch, altMatch2)) {
  362. dropMatch = true;
  363. malternateMatches.splice(malternateMatches.indexOf(altMatch2), 0, altMatch);
  364. }
  365. break;
  366. } else if (isSubsetOf(altMatch2, altMatch, opts)) {
  367. setMergeLocators(altMatch2, altMatch);
  368. break;
  369. } else if (staticCanMatchDefinition(altMatch, altMatch2)) {
  370. if (!isSameLevel(altMatch, altMatch2) && el.inputmask.userOptions.keepStatic === undefined) {
  371. opts.keepStatic = true;
  372. } else if (setMergeLocators(altMatch, altMatch2)) {
  373. //insert match above general match
  374. dropMatch = true;
  375. malternateMatches.splice(malternateMatches.indexOf(altMatch2), 0, altMatch);
  376. }
  377. break;
  378. }
  379. }
  380. }
  381. if (!dropMatch) {
  382. malternateMatches.push(altMatch);
  383. }
  384. }
  385. }
  386. matches = currentMatches.concat(malternateMatches);
  387. testPos = pos;
  388. insertStop = matches.length > 0; //insert a stopelemnt when there is an alternate - needed for non-greedy option
  389. match = malternateMatches.length > 0; //set correct match state
  390. //cloneback
  391. ndxInitializer = ndxInitializerClone.slice();
  392. } else {
  393. match = handleMatch(alternateToken.matches[altIndex] || maskToken.matches[altIndex], [altIndex].concat(loopNdx), quantifierRecurse);
  394. }
  395. if (match) return true;
  396. } else if (match.isQuantifier && quantifierRecurse !== maskToken.matches[maskToken.matches.indexOf(match) - 1]) {
  397. var qt = match;
  398. for (var qndx = (ndxInitializer.length > 0) ? ndxInitializer.shift() : 0; (qndx < (isNaN(qt.quantifier.max) ? qndx + 1 : qt.quantifier.max)) && testPos <= pos; qndx++) {
  399. var tokenGroup = maskToken.matches[maskToken.matches.indexOf(qt) - 1];
  400. match = handleMatch(tokenGroup, [qndx].concat(loopNdx), tokenGroup); //set the tokenGroup as quantifierRecurse marker
  401. if (match) {
  402. //get latest match
  403. latestMatch = matches[matches.length - 1].match;
  404. //mark optionality
  405. //TODO FIX RECURSIVE QUANTIFIERS
  406. latestMatch.optionalQuantifier = qndx >= qt.quantifier.min;
  407. // console.log(pos + " " + qt.quantifier.min + " " + latestMatch.optionalQuantifier);
  408. latestMatch.jit = (qndx || 1) * tokenGroup.matches.indexOf(latestMatch) >= qt.quantifier.jit;
  409. if (latestMatch.optionalQuantifier && isFirstMatch(latestMatch, tokenGroup)) {
  410. insertStop = true;
  411. testPos = pos; //match the position after the group
  412. break; //stop quantifierloop && search for next possible match
  413. }
  414. if (latestMatch.jit /*&& !latestMatch.optionalQuantifier*/) {
  415. //always set jitOffset, isvalid checks when to apply
  416. maskset.jitOffset[pos] = tokenGroup.matches.length - tokenGroup.matches.indexOf(latestMatch);
  417. }
  418. return true;
  419. }
  420. }
  421. } else {
  422. match = resolveTestFromToken(match, ndxInitializer, loopNdx, quantifierRecurse);
  423. if (match) return true;
  424. }
  425. } else {
  426. testPos++;
  427. }
  428. }
  429. //the offset is set in the quantifierloop when git masking is used
  430. for (var tndx = (ndxInitializer.length > 0 ? ndxInitializer.shift() : 0); tndx < maskToken.matches.length; tndx++) {
  431. if (maskToken.matches[tndx].isQuantifier !== true) {
  432. var match = handleMatch(maskToken.matches[tndx], [tndx].concat(loopNdx), quantifierRecurse);
  433. if (match && testPos === pos) {
  434. return match;
  435. } else if (testPos > pos) {
  436. break;
  437. }
  438. }
  439. }
  440. }
  441. function mergeLocators(pos, tests) {
  442. let locator = [], alternation;
  443. if (!Array.isArray(tests)) tests = [tests];
  444. if (tests.length > 0) {
  445. if (tests[0].alternation === undefined || opts.keepStatic === true) {
  446. locator = determineTestTemplate.call(inputmask, pos, tests.slice()).locator.slice();
  447. if (locator.length === 0) locator = tests[0].locator.slice();
  448. } else {
  449. tests.forEach(function (tst) {
  450. if (tst.def !== "") {
  451. if (locator.length === 0) {
  452. alternation = tst.alternation;
  453. locator = tst.locator.slice();
  454. } else {
  455. if (tst.locator[alternation] && locator[alternation].toString().indexOf(tst.locator[alternation]) === -1) {
  456. locator[alternation] += "," + tst.locator[alternation];
  457. }
  458. }
  459. }
  460. });
  461. }
  462. }
  463. return locator;
  464. }
  465. if (pos > -1 && (inputmask.maxLength === undefined || pos < inputmask.maxLength)) {
  466. if (ndxIntlzr === undefined) { //determine index initializer
  467. var previousPos = pos - 1,
  468. test;
  469. while ((test = maskset.validPositions[previousPos] || maskset.tests[previousPos]) === undefined && previousPos > -1) {
  470. previousPos--;
  471. }
  472. if (test !== undefined && previousPos > -1) {
  473. ndxInitializer = mergeLocators(previousPos, test);
  474. cacheDependency = ndxInitializer.join("");
  475. testPos = previousPos;
  476. }
  477. }
  478. if (maskset.tests[pos] && maskset.tests[pos][0].cd === cacheDependency) { //cacheDependency is set on all tests, just check on the first
  479. return maskset.tests[pos];
  480. }
  481. for (var mtndx = ndxInitializer.shift(); mtndx < maskTokens.length; mtndx++) {
  482. var match = resolveTestFromToken(maskTokens[mtndx], ndxInitializer, [mtndx]);
  483. if ((match && testPos === pos) || testPos > pos) {
  484. break;
  485. }
  486. }
  487. }
  488. if (matches.length === 0 || insertStop) {
  489. matches.push({
  490. match: {
  491. fn: null,
  492. static: true,
  493. optionality: false,
  494. casing: null,
  495. def: "",
  496. placeholder: ""
  497. },
  498. locator: [],
  499. mloc: {},
  500. cd: cacheDependency
  501. });
  502. }
  503. if (ndxIntlzr !== undefined && maskset.tests[pos]) { //prioritize full tests for caching
  504. return $.extend(true, [], matches);
  505. }
  506. maskset.tests[pos] = $.extend(true, [], matches); //set a clone to prevent overwriting some props
  507. // console.log(pos + " - " + JSON.stringify(matches));
  508. return maskset.tests[pos];
  509. }