| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325 |
- import { iphone, mobile } from "./environment";
- import { EventHandlers } from "./eventhandlers";
- import { EventRuler } from "./eventruler";
- import {
- applyInputValue,
- clearOptionalTail,
- writeBuffer
- } from "./inputHandling";
- import {
- caret,
- getBuffer,
- getBufferTemplate,
- getLastValidPosition,
- resetMaskSet,
- seekNext
- } from "./positioning";
- import { isComplete } from "./validation";
- export { mask };
- // todo put on the prototype?
- function mask() {
- const inputmask = this,
- opts = this.opts,
- el = this.el,
- $ = this.dependencyLib;
- function isElementTypeSupported(input, opts) {
- function patchValueProperty(npt) {
- let valueGet, valueSet;
- function patchValhook(type) {
- if (
- $.valHooks &&
- ($.valHooks[type] === undefined ||
- $.valHooks[type].inputmaskpatch !== true)
- ) {
- const valhookGet =
- $.valHooks[type] && $.valHooks[type].get
- ? $.valHooks[type].get
- : function (elem) {
- return elem.value;
- },
- valhookSet =
- $.valHooks[type] && $.valHooks[type].set
- ? $.valHooks[type].set
- : function (elem, value) {
- elem.value = value;
- return elem;
- };
- $.valHooks[type] = {
- get: function (elem) {
- if (elem.inputmask) {
- if (elem.inputmask.opts.autoUnmask) {
- return elem.inputmask.unmaskedvalue();
- } else {
- const result = valhookGet(elem);
- return getLastValidPosition.call(
- inputmask,
- undefined,
- undefined,
- elem.inputmask.maskset.validPositions
- ) !== -1 || opts.nullable !== true
- ? result
- : "";
- }
- } else {
- return valhookGet(elem);
- }
- },
- set: function (elem, value) {
- const result = valhookSet(elem, value);
- if (elem.inputmask) {
- applyInputValue(elem, value);
- }
- return result;
- },
- inputmaskpatch: true
- };
- }
- }
- function getter() {
- if (this.inputmask) {
- return this.inputmask.opts.autoUnmask
- ? this.inputmask.unmaskedvalue()
- : getLastValidPosition.call(inputmask) !== -1 ||
- opts.nullable !== true
- ? (this.inputmask.shadowRoot || this.ownerDocument)
- .activeElement === this && opts.clearMaskOnLostFocus
- ? (inputmask.isRTL
- ? clearOptionalTail
- .call(inputmask, getBuffer.call(inputmask).slice())
- .reverse()
- : clearOptionalTail.call(
- inputmask,
- getBuffer.call(inputmask).slice()
- )
- ).join("")
- : valueGet.call(this)
- : "";
- } else {
- return valueGet.call(this);
- }
- }
- function setter(value) {
- valueSet.call(this, value);
- if (this.inputmask) {
- applyInputValue(this, value);
- }
- }
- function installNativeValueSetFallback(npt) {
- EventRuler.on(npt, "mouseenter", function () {
- const input = this,
- value = input.inputmask._valueGet(true),
- bufferValue = (
- input.inputmask.isRTL
- ? getBuffer.call(input.inputmask).slice().reverse()
- : getBuffer.call(input.inputmask)
- ).join("");
- if (value != bufferValue) {
- applyInputValue(input, value);
- }
- });
- }
- if (!npt.inputmask.__valueGet) {
- if (opts.noValuePatching !== true) {
- if (Object.getOwnPropertyDescriptor) {
- const valueProperty = Object.getPrototypeOf
- ? Object.getOwnPropertyDescriptor(
- Object.getPrototypeOf(npt),
- "value"
- )
- : undefined;
- if (valueProperty && valueProperty.get && valueProperty.set) {
- valueGet = valueProperty.get;
- valueSet = valueProperty.set;
- Object.defineProperty(npt, "value", {
- get: getter,
- set: setter,
- configurable: true
- });
- } else if (npt.tagName.toLowerCase() !== "input") {
- valueGet = function () {
- return this.textContent;
- };
- valueSet = function (value) {
- this.textContent = value;
- };
- Object.defineProperty(npt, "value", {
- get: getter,
- set: setter,
- configurable: true
- });
- }
- } else if (
- document.__lookupGetter__ &&
- npt.__lookupGetter__("value")
- ) {
- valueGet = npt.__lookupGetter__("value");
- valueSet = npt.__lookupSetter__("value");
- npt.__defineGetter__("value", getter);
- npt.__defineSetter__("value", setter);
- }
- npt.inputmask.__valueGet = valueGet; // store native property getter
- npt.inputmask.__valueSet = valueSet; // store native property setter
- }
- npt.inputmask._valueGet = function (overruleRTL) {
- return inputmask.isRTL && overruleRTL !== true
- ? valueGet.call(this.el).split("").reverse().join("")
- : valueGet.call(this.el);
- };
- npt.inputmask._valueSet = function (value, overruleRTL) {
- // null check is needed for IE8 => otherwise converts to "null"
- valueSet.call(
- this.el,
- value === null || value === undefined
- ? ""
- : overruleRTL !== true && inputmask.isRTL
- ? value.split("").reverse().join("")
- : value
- );
- };
- if (valueGet === undefined) {
- // jquery.val fallback
- valueGet = function () {
- return this.value;
- };
- valueSet = function (value) {
- this.value = value;
- };
- patchValhook(npt.type);
- installNativeValueSetFallback(npt);
- }
- }
- }
- // if (input.tagName.toLowerCase() !== "textarea") {
- // opts.ignorables.push(keys.Enter);
- // }
- let elementType = input.getAttribute("type"),
- isSupported =
- (input.tagName.toLowerCase() === "input" &&
- opts.supportsInputType.includes(elementType)) ||
- input.isContentEditable ||
- input.tagName.toLowerCase() === "textarea";
- if (!isSupported) {
- if (input.tagName.toLowerCase() === "input") {
- let el = document.createElement("input");
- el.setAttribute("type", elementType);
- isSupported = el.type === "text"; // apply mask only if the type is not natively supported
- el = null;
- } else {
- isSupported = "partial";
- }
- }
- if (isSupported !== false) {
- patchValueProperty(input);
- } else {
- input.inputmask = undefined;
- }
- return isSupported;
- }
- // unbind all events - to make sure that no other mask will interfere when re-masking
- EventRuler.off(el);
- const isSupported = isElementTypeSupported(el, opts);
- if (isSupported !== false) {
- inputmask.originalPlaceholder = el.placeholder;
- // read maxlength prop from el
- inputmask.maxLength = el !== undefined ? el.maxLength : undefined;
- if (inputmask.maxLength === -1) inputmask.maxLength = undefined;
- if ("inputMode" in el && el.getAttribute("inputmode") === null) {
- el.inputMode = opts.inputmode;
- el.setAttribute("inputmode", opts.inputmode);
- }
- if (isSupported === true) {
- opts.showMaskOnFocus =
- opts.showMaskOnFocus &&
- ["cc-number", "cc-exp"].indexOf(el.autocomplete) === -1;
- if (iphone) {
- // selecting the caret shows as a selection on iphone
- opts.insertModeVisual = false;
- // disable autocorrect
- el.setAttribute("autocorrect", "off");
- }
- // bind events
- EventRuler.on(el, "submit", EventHandlers.submitEvent);
- EventRuler.on(el, "reset", EventHandlers.resetEvent);
- EventRuler.on(el, "blur", EventHandlers.blurEvent);
- EventRuler.on(el, "focus", EventHandlers.focusEvent);
- EventRuler.on(el, "invalid", EventHandlers.invalidEvent);
- EventRuler.on(el, "click", EventHandlers.clickEvent);
- EventRuler.on(el, "mouseleave", EventHandlers.mouseleaveEvent);
- EventRuler.on(el, "mouseenter", EventHandlers.mouseenterEvent);
- EventRuler.on(el, "paste", EventHandlers.pasteEvent);
- EventRuler.on(el, "cut", EventHandlers.cutEvent);
- EventRuler.on(el, "complete", opts.oncomplete);
- EventRuler.on(el, "incomplete", opts.onincomplete);
- EventRuler.on(el, "cleared", opts.oncleared);
- if (opts.inputEventOnly !== true) {
- EventRuler.on(el, "keydown", EventHandlers.keyEvent);
- }
- if (mobile || opts.inputEventOnly) {
- el.removeAttribute("maxLength");
- }
- EventRuler.on(el, "input", EventHandlers.inputFallBackEvent);
- // EventRuler.on(el, "beforeinput", EventHandlers.beforeInputEvent); //https://github.com/w3c/input-events - to implement
- }
- EventRuler.on(el, "setvalue", EventHandlers.setValueEvent);
- // apply mask
- inputmask.applyMaskHook === undefined || inputmask.applyMaskHook();
- getBufferTemplate.call(inputmask).join(""); // initialize the buffer and getmasklength
- inputmask.undoValue = inputmask._valueGet(true);
- const activeElement = (el.inputmask.shadowRoot || el.ownerDocument)
- .activeElement;
- if (
- el.inputmask._valueGet(true) !== "" ||
- opts.clearMaskOnLostFocus === false ||
- activeElement === el
- ) {
- applyInputValue(el, el.inputmask._valueGet(true), opts);
- let buffer = getBuffer.call(inputmask).slice();
- if (isComplete.call(inputmask, buffer) === false) {
- if (opts.clearIncomplete) {
- resetMaskSet.call(inputmask, false);
- }
- }
- if (opts.clearMaskOnLostFocus && activeElement !== el) {
- if (getLastValidPosition.call(inputmask) === -1) {
- buffer = [];
- } else {
- clearOptionalTail.call(inputmask, buffer);
- }
- }
- if (
- opts.clearMaskOnLostFocus === false ||
- (opts.showMaskOnFocus && activeElement === el) ||
- el.inputmask._valueGet(true) !== ""
- ) {
- writeBuffer(el, buffer);
- }
- if (activeElement === el) {
- // position the caret when in focus
- caret.call(
- inputmask,
- el,
- seekNext.call(inputmask, getLastValidPosition.call(inputmask))
- );
- }
- }
- }
- }
|