inputHandling.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. import keyCode from "./keycode.json";
  2. import {getMaskTemplate, getPlaceholder, getTest} from "./validation-tests";
  3. import {
  4. caret,
  5. determineNewCaretPosition,
  6. getBuffer, getBufferTemplate,
  7. getLastValidPosition,
  8. isMask,
  9. resetMaskSet,
  10. seekNext
  11. } from "./positioning";
  12. import {isComplete, isValid, refreshFromBuffer} from "./validation";
  13. import {ie} from "./environment";
  14. import {EventHandlers} from "./eventhandlers";
  15. export {applyInputValue, clearOptionalTail, checkVal, HandleNativePlaceholder, unmaskedvalue, writeBuffer};
  16. function applyInputValue(input, value) {
  17. const inputmask = input ? input.inputmask : this, opts = inputmask.opts;
  18. input.inputmask.refreshValue = false;
  19. if (typeof opts.onBeforeMask === "function") value = opts.onBeforeMask.call(inputmask, value, opts) || value;
  20. value = value.toString().split("");
  21. checkVal(input, true, false, value);
  22. inputmask.undoValue = getBuffer.call(inputmask).join("");
  23. if ((opts.clearMaskOnLostFocus || opts.clearIncomplete) && input.inputmask._valueGet() === getBufferTemplate.call(inputmask).join("") && getLastValidPosition.call(inputmask) === -1) {
  24. input.inputmask._valueSet("");
  25. }
  26. }
  27. //todo put on prototype?
  28. function clearOptionalTail(buffer) {
  29. const inputmask = this;
  30. buffer.length = 0;
  31. var template = getMaskTemplate.call(inputmask, true, 0, true, undefined, true), lmnt;
  32. while ((lmnt = template.shift()) !== undefined) buffer.push(lmnt);
  33. return buffer;
  34. }
  35. function checkVal(input, writeOut, strict, nptvl, initiatingEvent) {
  36. const inputmask = input ? input.inputmask : this,
  37. maskset = inputmask.maskset,
  38. opts = inputmask.opts, $ = inputmask.dependencyLib;
  39. var inputValue = nptvl.slice(),
  40. charCodes = "",
  41. initialNdx = -1,
  42. result = undefined, skipOptionalPartCharacter = opts.skipOptionalPartCharacter;
  43. opts.skipOptionalPartCharacter = ""; //see issue #2311
  44. function isTemplateMatch(ndx, charCodes) {
  45. var targetTemplate = getMaskTemplate.call(inputmask, true, 0).slice(ndx, seekNext.call(inputmask, ndx, false, false)).join("").replace(/'/g, ""),
  46. charCodeNdx = targetTemplate.indexOf(charCodes);
  47. //strip spaces from targetTemplate
  48. while (charCodeNdx > 0 && targetTemplate[charCodeNdx - 1] === " ") charCodeNdx--;
  49. var match = charCodeNdx === 0 && !isMask.call(inputmask, ndx)
  50. && (getTest.call(inputmask, ndx).match.nativeDef === charCodes.charAt(0)
  51. || (getTest.call(inputmask, ndx).match.static === true && getTest.call(inputmask, ndx).match.nativeDef === ("'" + charCodes.charAt(0)))
  52. || (getTest.call(inputmask, ndx).match.nativeDef === " " && (getTest.call(inputmask, ndx + 1).match.nativeDef === charCodes.charAt(0)
  53. || (getTest.call(inputmask, ndx + 1).match.static === true && getTest.call(inputmask, ndx + 1).match.nativeDef === ("'" + charCodes.charAt(0))))));
  54. if (!match && charCodeNdx > 0 && !isMask.call(inputmask, ndx, false, true)) {
  55. var nextPos = seekNext.call(inputmask, ndx);
  56. if (inputmask.caretPos.begin < nextPos) {
  57. inputmask.caretPos = {begin: nextPos};
  58. }
  59. }
  60. return match;
  61. }
  62. resetMaskSet.call(inputmask);
  63. maskset.tests = {}; //reset tests ~ possible after alternating
  64. initialNdx = opts.radixPoint ? determineNewCaretPosition.call(inputmask, {begin: 0, end: 0}).begin : 0;
  65. maskset.p = initialNdx;
  66. inputmask.caretPos = {begin: initialNdx};
  67. var staticMatches = [], prevCaretPos = inputmask.caretPos;
  68. inputValue.forEach(function (charCode, ndx) {
  69. if (charCode !== undefined) { //inputfallback strips some elements out of the inputarray. $.each logically presents them as undefined
  70. /*if (maskset.validPositions[ndx] === undefined && inputValue[ndx] === getPlaceholder.call(inputmask, ndx) && isMask.call(inputmask, ndx, true) &&
  71. isValid.call(inputmask, ndx, inputValue[ndx], true, undefined, true, true) === false) {
  72. inputmask.caretPos.begin++;
  73. } else*/
  74. {
  75. var keypress = new $.Event("_checkval");
  76. keypress.which = charCode.toString().charCodeAt(0);
  77. charCodes += charCode;
  78. var lvp = getLastValidPosition.call(inputmask, undefined, true);
  79. if (!isTemplateMatch(initialNdx, charCodes)) {
  80. result = EventHandlers.keypressEvent.call(inputmask, keypress, true, false, strict, inputmask.caretPos.begin);
  81. if (result) {
  82. initialNdx = inputmask.caretPos.begin + 1;
  83. charCodes = "";
  84. }
  85. } else {
  86. result = EventHandlers.keypressEvent.call(inputmask, keypress, true, false, strict, lvp + 1);
  87. }
  88. if (result) {
  89. if (result.pos !== undefined && maskset.validPositions[result.pos] && maskset.validPositions[result.pos].match.static === true && maskset.validPositions[result.pos].alternation === undefined) {
  90. staticMatches.push(result.pos);
  91. if (!inputmask.isRTL) {
  92. result.forwardPosition = result.pos + 1;
  93. }
  94. }
  95. writeBuffer.call(inputmask, undefined, getBuffer.call(inputmask), result.forwardPosition, keypress, false);
  96. inputmask.caretPos = {begin: result.forwardPosition, end: result.forwardPosition};
  97. prevCaretPos = inputmask.caretPos;
  98. } else {
  99. if (maskset.validPositions[ndx] === undefined && inputValue[ndx] === getPlaceholder.call(inputmask, ndx) && isMask.call(inputmask, ndx, true)) {
  100. inputmask.caretPos.begin++;
  101. } else inputmask.caretPos = prevCaretPos; //restore the caret position from before the failed validation
  102. }
  103. }
  104. }
  105. });
  106. if (staticMatches.length > 0) {
  107. var sndx, validPos, nextValid = seekNext.call(inputmask, -1, undefined, false);
  108. if ((!isComplete.call(inputmask, getBuffer.call(inputmask)) && staticMatches.length <= nextValid)
  109. || (isComplete.call(inputmask, getBuffer.call(inputmask)) && staticMatches.length > 0 && (staticMatches.length !== nextValid && staticMatches[0] === 0))) { //should check if is sequence starting from 0
  110. var nextSndx = nextValid;
  111. while ((sndx = staticMatches.shift()) !== undefined) {
  112. var keypress = new $.Event("_checkval");
  113. validPos = maskset.validPositions[sndx];
  114. validPos.generatedInput = true;
  115. keypress.which = validPos.input.charCodeAt(0);
  116. result = EventHandlers.keypressEvent.call(inputmask, keypress, true, false, strict, nextSndx);
  117. if (result && result.pos !== undefined && result.pos !== sndx && maskset.validPositions[result.pos] && maskset.validPositions[result.pos].match.static === true) {
  118. staticMatches.push(result.pos);
  119. } else if (!result) break;
  120. nextSndx++;
  121. }
  122. } else { //mark al statics as generated
  123. // while ((sndx = staticMatches.pop())) {
  124. // validPos = maskset.validPositions[sndx];
  125. // if (validPos) {
  126. // validPos.generatedInput = true;
  127. // }
  128. // }
  129. }
  130. }
  131. if (writeOut) {
  132. writeBuffer.call(inputmask, input, getBuffer.call(inputmask), result ? result.forwardPosition : inputmask.caretPos.begin, initiatingEvent || new $.Event("checkval"), initiatingEvent && initiatingEvent.type === "input" && inputmask.undoValue !== getBuffer.call(inputmask).join(""));
  133. // for (var vndx in maskset.validPositions) {
  134. // if (maskset.validPositions[vndx].match.generated !== true) { //only remove non forced generated
  135. // delete maskset.validPositions[vndx].generatedInput; //clear generated markings ~ consider initializing with a value as fully typed
  136. // }
  137. // }
  138. }
  139. opts.skipOptionalPartCharacter = skipOptionalPartCharacter;
  140. }
  141. function HandleNativePlaceholder(npt, value) {
  142. const inputmask = npt ? npt.inputmask : this;
  143. if (ie) {
  144. if (npt.inputmask._valueGet() !== value && (npt.placeholder !== value || npt.placeholder === "")) {
  145. var buffer = getBuffer.call(inputmask).slice(),
  146. nptValue = npt.inputmask._valueGet();
  147. if (nptValue !== value) {
  148. var lvp = getLastValidPosition.call(inputmask);
  149. if (lvp === -1 && nptValue === getBufferTemplate.call(inputmask).join("")) {
  150. buffer = [];
  151. } else if (lvp !== -1) { //clearout optional tail of the mask
  152. clearOptionalTail.call(inputmask, buffer);
  153. }
  154. writeBuffer(npt, buffer);
  155. }
  156. }
  157. } else if (npt.placeholder !== value) {
  158. npt.placeholder = value;
  159. if (npt.placeholder === "") npt.removeAttribute("placeholder");
  160. }
  161. }
  162. function unmaskedvalue(input) {
  163. const inputmask = input ? input.inputmask : this,
  164. opts = inputmask.opts,
  165. maskset = inputmask.maskset;
  166. if (input) {
  167. if (input.inputmask === undefined) {
  168. return input.value;
  169. }
  170. if (input.inputmask && input.inputmask.refreshValue) { //forced refresh from the value form.reset
  171. applyInputValue(input, input.inputmask._valueGet(true));
  172. }
  173. }
  174. var umValue = [],
  175. vps = maskset.validPositions;
  176. for (var pndx in vps) {
  177. if (vps[pndx] && vps[pndx].match && (vps[pndx].match.static != true || (Array.isArray(maskset.metadata) && vps[pndx].generatedInput !== true))) {
  178. //only include generated input with multiple masks (check on metadata)
  179. umValue.push(vps[pndx].input);
  180. }
  181. }
  182. var unmaskedValue = umValue.length === 0 ? "" : (inputmask.isRTL ? umValue.reverse() : umValue).join("");
  183. if (typeof opts.onUnMask === "function") {
  184. var bufferValue = (inputmask.isRTL ? getBuffer.call(inputmask).slice().reverse() : getBuffer.call(inputmask)).join("");
  185. unmaskedValue = opts.onUnMask.call(inputmask, bufferValue, unmaskedValue, opts);
  186. }
  187. return unmaskedValue;
  188. }
  189. function writeBuffer(input, buffer, caretPos, event, triggerEvents) {
  190. const inputmask = input ? input.inputmask : this,
  191. opts = inputmask.opts,
  192. $ = inputmask.dependencyLib;
  193. if (event && typeof opts.onBeforeWrite === "function") {
  194. // buffer = buffer.slice(); //prevent uncontrolled manipulation of the internal buffer
  195. var result = opts.onBeforeWrite.call(inputmask, event, buffer, caretPos, opts);
  196. if (result) {
  197. if (result.refreshFromBuffer) {
  198. var refresh = result.refreshFromBuffer;
  199. refreshFromBuffer.call(inputmask, refresh === true ? refresh : refresh.start, refresh.end, result.buffer || buffer);
  200. buffer = getBuffer.call(inputmask, true);
  201. }
  202. if (caretPos !== undefined) caretPos = result.caret !== undefined ? result.caret : caretPos;
  203. }
  204. }
  205. if (input !== undefined) {
  206. input.inputmask._valueSet(buffer.join(""));
  207. if (caretPos !== undefined && (event === undefined || event.type !== "blur")) {
  208. // console.log(caretPos);
  209. caret.call(inputmask, input, caretPos, undefined, undefined, (event !== undefined && event.type === "keydown" && (event.keyCode === keyCode.DELETE || event.keyCode === keyCode.BACKSPACE)));
  210. }
  211. if (triggerEvents === true) {
  212. var $input = $(input), nptVal = input.inputmask._valueGet();
  213. input.inputmask.skipInputEvent = true;
  214. $input.trigger("input");
  215. setTimeout(function () { //timeout needed for IE
  216. if (nptVal === getBufferTemplate.call(inputmask).join("")) {
  217. $input.trigger("cleared");
  218. } else if (isComplete.call(inputmask, buffer) === true) {
  219. $input.trigger("complete");
  220. }
  221. }, 0);
  222. }
  223. }
  224. }