'use strict'; var Util = { noop: function () { }, strip: function (value, re) { return value.replace(re, ''); }, getPostDelimiter: function (value, delimiter, delimiters) { // single delimiter if (delimiters.length === 0) { return value.slice(-delimiter.length) === delimiter ? delimiter : ''; } // multiple delimiters var matchedDelimiter = ''; delimiters.forEach(function (current) { if (value.slice(-current.length) === current) { matchedDelimiter = current; } }); return matchedDelimiter; }, getDelimiterREByDelimiter: function (delimiter) { return new RegExp(delimiter.replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1'), 'g'); }, getNextCursorPosition: function (prevPos, oldValue, newValue, delimiter, delimiters) { // If cursor was at the end of value, just place it back. // Because new value could contain additional chars. if (oldValue.length === prevPos) { return newValue.length; } return prevPos + this.getPositionOffset(prevPos, oldValue, newValue, delimiter ,delimiters); }, getPositionOffset: function (prevPos, oldValue, newValue, delimiter, delimiters) { var oldRawValue, newRawValue, lengthOffset; oldRawValue = this.stripDelimiters(oldValue.slice(0, prevPos), delimiter, delimiters); newRawValue = this.stripDelimiters(newValue.slice(0, prevPos), delimiter, delimiters); lengthOffset = oldRawValue.length - newRawValue.length; return (lengthOffset !== 0) ? (lengthOffset / Math.abs(lengthOffset)) : 0; }, stripDelimiters: function (value, delimiter, delimiters) { var owner = this; // single delimiter if (delimiters.length === 0) { var delimiterRE = delimiter ? owner.getDelimiterREByDelimiter(delimiter) : ''; return value.replace(delimiterRE, ''); } // multiple delimiters delimiters.forEach(function (current) { current.split('').forEach(function (letter) { value = value.replace(owner.getDelimiterREByDelimiter(letter), ''); }); }); return value; }, headStr: function (str, length) { return str.slice(0, length); }, getMaxLength: function (blocks) { return blocks.reduce(function (previous, current) { return previous + current; }, 0); }, // strip prefix // Before type | After type | Return value // PEFIX-... | PEFIX-... | '' // PREFIX-123 | PEFIX-123 | 123 // PREFIX-123 | PREFIX-23 | 23 // PREFIX-123 | PREFIX-1234 | 1234 getPrefixStrippedValue: function (value, prefix, prefixLength, prevResult, delimiter, delimiters, noImmediatePrefix, tailPrefix, signBeforePrefix) { // No prefix if (prefixLength === 0) { return value; } // Value is prefix if (value === prefix && value !== '') { return ''; } if (signBeforePrefix && (value.slice(0, 1) == '-')) { var prev = (prevResult.slice(0, 1) == '-') ? prevResult.slice(1) : prevResult; return '-' + this.getPrefixStrippedValue(value.slice(1), prefix, prefixLength, prev, delimiter, delimiters, noImmediatePrefix, tailPrefix, signBeforePrefix); } // Pre result prefix string does not match pre-defined prefix if (prevResult.slice(0, prefixLength) !== prefix && !tailPrefix) { // Check if the first time user entered something if (noImmediatePrefix && !prevResult && value) return value; return ''; } else if (prevResult.slice(-prefixLength) !== prefix && tailPrefix) { // Check if the first time user entered something if (noImmediatePrefix && !prevResult && value) return value; return ''; } var prevValue = this.stripDelimiters(prevResult, delimiter, delimiters); // New value has issue, someone typed in between prefix letters // Revert to pre value if (value.slice(0, prefixLength) !== prefix && !tailPrefix) { return prevValue.slice(prefixLength); } else if (value.slice(-prefixLength) !== prefix && tailPrefix) { return prevValue.slice(0, -prefixLength - 1); } // No issue, strip prefix for new value return tailPrefix ? value.slice(0, -prefixLength) : value.slice(prefixLength); }, getFirstDiffIndex: function (prev, current) { var index = 0; while (prev.charAt(index) === current.charAt(index)) { if (prev.charAt(index++) === '') { return -1; } } return index; }, getFormattedValue: function (value, blocks, blocksLength, delimiter, delimiters, delimiterLazyShow) { var result = '', multipleDelimiters = delimiters.length > 0, currentDelimiter = ''; // no options, normal input if (blocksLength === 0) { return value; } blocks.forEach(function (length, index) { if (value.length > 0) { var sub = value.slice(0, length), rest = value.slice(length); if (multipleDelimiters) { currentDelimiter = delimiters[delimiterLazyShow ? (index - 1) : index] || currentDelimiter; } else { currentDelimiter = delimiter; } if (delimiterLazyShow) { if (index > 0) { result += currentDelimiter; } result += sub; } else { result += sub; if (sub.length === length && index < blocksLength - 1) { result += currentDelimiter; } } // update remaining string value = rest; } }); return result; }, // move cursor to the end // the first time user focuses on an input with prefix fixPrefixCursor: function (el, prefix, delimiter, delimiters) { if (!el) { return; } var val = el.value, appendix = delimiter || (delimiters[0] || ' '); if (!el.setSelectionRange || !prefix || (prefix.length + appendix.length) <= val.length) { return; } var len = val.length * 2; // set timeout to avoid blink setTimeout(function () { el.setSelectionRange(len, len); }, 1); }, // Check if input field is fully selected checkFullSelection: function(value) { try { var selection = window.getSelection() || document.getSelection() || {}; return selection.toString().length === value.length; } catch (ex) { // Ignore } return false; }, setSelection: function (element, position, doc) { if (element !== this.getActiveElement(doc)) { return; } // cursor is already in the end if (element && element.value.length <= position) { return; } if (element.createTextRange) { var range = element.createTextRange(); range.move('character', position); range.select(); } else { try { element.setSelectionRange(position, position); } catch (e) { // eslint-disable-next-line console.warn('The input element type does not support selection'); } } }, getActiveElement: function(parent) { var activeElement = parent.activeElement; if (activeElement && activeElement.shadowRoot) { return this.getActiveElement(activeElement.shadowRoot); } return activeElement; }, isAndroid: function () { return navigator && /android/i.test(navigator.userAgent); }, // On Android chrome, the keyup and keydown events // always return key code 229 as a composition that // buffers the user’s keystrokes // see https://github.com/nosir/cleave.js/issues/147 isAndroidBackspaceKeydown: function (lastInputValue, currentInputValue) { if (!this.isAndroid() || !lastInputValue || !currentInputValue) { return false; } return currentInputValue === lastInputValue.slice(0, -1); } }; module.exports = Util;