mirror of
https://github.com/DanielnetoDotCom/YouPHPTube
synced 2025-10-03 09:49:28 +02:00
486 lines
14 KiB
JavaScript
486 lines
14 KiB
JavaScript
import window from "./global/window";
|
|
import { checkAlternationMatch } from "./validation";
|
|
import {
|
|
determineTestTemplate,
|
|
getMaskTemplate,
|
|
getPlaceholder,
|
|
getTest,
|
|
getTests,
|
|
getTestTemplate
|
|
} from "./validation-tests";
|
|
|
|
export {
|
|
caret,
|
|
determineLastRequiredPosition,
|
|
determineNewCaretPosition,
|
|
getBuffer,
|
|
getBufferTemplate,
|
|
getLastValidPosition,
|
|
isMask,
|
|
resetMaskSet,
|
|
seekNext,
|
|
seekPrevious,
|
|
translatePosition
|
|
};
|
|
|
|
// tobe put on prototype?
|
|
function caret(input, begin, end, notranslate, isDelete) {
|
|
const inputmask = this,
|
|
opts = this.opts;
|
|
|
|
let range;
|
|
if (begin !== undefined) {
|
|
if (Array.isArray(begin)) {
|
|
end = inputmask.isRTL ? begin[0] : begin[1];
|
|
begin = inputmask.isRTL ? begin[1] : begin[0];
|
|
}
|
|
if (begin.begin !== undefined) {
|
|
end = inputmask.isRTL ? begin.begin : begin.end;
|
|
begin = inputmask.isRTL ? begin.end : begin.begin;
|
|
}
|
|
if (typeof begin === "number") {
|
|
begin = notranslate ? begin : translatePosition.call(inputmask, begin);
|
|
end = notranslate ? end : translatePosition.call(inputmask, end);
|
|
end = typeof end === "number" ? end : begin;
|
|
// if (!$(input).is(":visible")) {
|
|
// return;
|
|
// }
|
|
|
|
const scrollCalc =
|
|
parseInt(
|
|
((input.ownerDocument.defaultView || window).getComputedStyle
|
|
? (input.ownerDocument.defaultView || window).getComputedStyle(
|
|
input,
|
|
null
|
|
)
|
|
: input.currentStyle
|
|
).fontSize
|
|
) * end;
|
|
input.scrollLeft = scrollCalc > input.scrollWidth ? scrollCalc : 0;
|
|
input.inputmask.caretPos = { begin, end }; // track caret internally
|
|
if (opts.insertModeVisual && opts.insertMode === false && begin === end) {
|
|
if (!isDelete) {
|
|
end++; // set visualization for insert/overwrite mode
|
|
}
|
|
}
|
|
if (
|
|
input ===
|
|
(input.inputmask.shadowRoot || input.ownerDocument).activeElement
|
|
) {
|
|
if ("setSelectionRange" in input) {
|
|
input.setSelectionRange(begin, end);
|
|
} else if (window.getSelection) {
|
|
range = document.createRange();
|
|
if (input.firstChild === undefined || input.firstChild === null) {
|
|
const textNode = document.createTextNode("");
|
|
input.appendChild(textNode);
|
|
}
|
|
range.setStart(
|
|
input.firstChild,
|
|
begin < input.inputmask._valueGet().length
|
|
? begin
|
|
: input.inputmask._valueGet().length
|
|
);
|
|
range.setEnd(
|
|
input.firstChild,
|
|
end < input.inputmask._valueGet().length
|
|
? end
|
|
: input.inputmask._valueGet().length
|
|
);
|
|
range.collapse(true);
|
|
const sel = window.getSelection();
|
|
sel.removeAllRanges();
|
|
sel.addRange(range);
|
|
// input.focus();
|
|
} else if (input.createTextRange) {
|
|
range = input.createTextRange();
|
|
range.collapse(true);
|
|
range.moveEnd("character", end);
|
|
range.moveStart("character", begin);
|
|
range.select();
|
|
}
|
|
|
|
input.inputmask.caretHook === undefined ||
|
|
input.inputmask.caretHook.call(inputmask, { begin, end });
|
|
}
|
|
}
|
|
} else {
|
|
if ("selectionStart" in input && "selectionEnd" in input) {
|
|
begin = input.selectionStart;
|
|
end = input.selectionEnd;
|
|
} else if (window.getSelection) {
|
|
range = window.getSelection().getRangeAt(0);
|
|
if (
|
|
range.commonAncestorContainer.parentNode === input ||
|
|
range.commonAncestorContainer === input
|
|
) {
|
|
begin = range.startOffset;
|
|
end = range.endOffset;
|
|
}
|
|
} else if (document.selection && document.selection.createRange) {
|
|
range = document.selection.createRange();
|
|
begin =
|
|
0 -
|
|
range
|
|
.duplicate()
|
|
.moveStart("character", -input.inputmask._valueGet().length);
|
|
end = begin + range.text.length;
|
|
}
|
|
|
|
// if (opts.insertModeVisual && opts.insertMode === false && begin === (end - 1)) end--; //correct caret for insert/overwrite mode
|
|
|
|
/* eslint-disable consistent-return */
|
|
return {
|
|
begin: notranslate ? begin : translatePosition.call(inputmask, begin),
|
|
end: notranslate ? end : translatePosition.call(inputmask, end)
|
|
};
|
|
/* eslint-enable consistent-return */
|
|
}
|
|
}
|
|
|
|
// tobe put on prototype?
|
|
function determineLastRequiredPosition(returnDefinition) {
|
|
const inputmask = this,
|
|
{ maskset, dependencyLib: $ } = inputmask,
|
|
lvp = getLastValidPosition.call(inputmask),
|
|
positions = {},
|
|
lvTest = maskset.validPositions[lvp],
|
|
buffer = getMaskTemplate.call(
|
|
inputmask,
|
|
true,
|
|
getLastValidPosition.call(inputmask),
|
|
true,
|
|
true
|
|
);
|
|
let bl = buffer.length,
|
|
pos,
|
|
ndxIntlzr = lvTest !== undefined ? lvTest.locator.slice() : undefined,
|
|
testPos;
|
|
for (pos = lvp + 1; pos < buffer.length; pos++) {
|
|
testPos = getTestTemplate.call(inputmask, pos, ndxIntlzr, pos - 1);
|
|
ndxIntlzr = testPos.locator.slice();
|
|
positions[pos] = $.extend(true, {}, testPos);
|
|
}
|
|
|
|
const lvTestAlt =
|
|
lvTest && lvTest.alternation !== undefined
|
|
? lvTest.locator[lvTest.alternation]
|
|
: undefined;
|
|
for (pos = bl - 1; pos > lvp; pos--) {
|
|
testPos = positions[pos];
|
|
if (
|
|
(testPos.match.optionality ||
|
|
(testPos.match.optionalQuantifier && testPos.match.newBlockMarker) ||
|
|
(lvTestAlt &&
|
|
((lvTestAlt !== positions[pos].locator[lvTest.alternation] &&
|
|
testPos.match.static !== true) ||
|
|
(testPos.match.static === true &&
|
|
testPos.locator[lvTest.alternation] &&
|
|
checkAlternationMatch.call(
|
|
inputmask,
|
|
testPos.locator[lvTest.alternation].toString().split(","),
|
|
lvTestAlt.toString().split(",")
|
|
) &&
|
|
getTests.call(inputmask, pos)[0].def !== "")))) &&
|
|
buffer[pos] === getPlaceholder.call(inputmask, pos, testPos.match)
|
|
) {
|
|
bl--;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
return returnDefinition
|
|
? {
|
|
l: bl,
|
|
def: positions[bl] ? positions[bl].match : undefined
|
|
}
|
|
: bl;
|
|
}
|
|
|
|
// tobe put on prototype?
|
|
function determineNewCaretPosition(
|
|
selectedCaret,
|
|
tabbed,
|
|
positionCaretOnClick
|
|
) {
|
|
const inputmask = this,
|
|
{ maskset, opts } = inputmask;
|
|
let clickPosition, lvclickPosition, lastPosition;
|
|
|
|
function doRadixFocus(clickPos) {
|
|
if (opts.radixPoint !== "" && opts.digits !== 0) {
|
|
const vps = maskset.validPositions;
|
|
if (vps[clickPos] === undefined || vps[clickPos].input === undefined) {
|
|
if (clickPos < seekNext.call(inputmask, -1)) return true;
|
|
const radixPos = getBuffer.call(inputmask).indexOf(opts.radixPoint);
|
|
if (radixPos !== -1) {
|
|
for (let vp = 0, vpl = vps.length; vp < vpl; vp++) {
|
|
if (
|
|
vps[vp] &&
|
|
radixPos < vp &&
|
|
vps[vp].input !== getPlaceholder.call(inputmask, vp)
|
|
) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
if (tabbed) {
|
|
if (inputmask.isRTL) {
|
|
selectedCaret.end = selectedCaret.begin;
|
|
} else {
|
|
selectedCaret.begin = selectedCaret.end;
|
|
}
|
|
}
|
|
if (selectedCaret.begin === selectedCaret.end) {
|
|
positionCaretOnClick = positionCaretOnClick || opts.positionCaretOnClick;
|
|
switch (positionCaretOnClick) {
|
|
case "none":
|
|
break;
|
|
case "select":
|
|
selectedCaret = { begin: 0, end: getBuffer.call(inputmask).length };
|
|
break;
|
|
case "ignore":
|
|
selectedCaret.end = selectedCaret.begin = seekNext.call(
|
|
inputmask,
|
|
getLastValidPosition.call(inputmask)
|
|
);
|
|
break;
|
|
case "radixFocus":
|
|
if (inputmask.clicked > 1 && maskset.validPositions.length === 0) break;
|
|
if (doRadixFocus(selectedCaret.begin)) {
|
|
const radixPos = getBuffer
|
|
.call(inputmask)
|
|
.join("")
|
|
.indexOf(opts.radixPoint);
|
|
selectedCaret.end = selectedCaret.begin = opts.numericInput
|
|
? seekNext.call(inputmask, radixPos)
|
|
: radixPos;
|
|
break;
|
|
} // fallback to lvp
|
|
// eslint-disable-next-line no-fallthrough
|
|
default: // lvp:
|
|
clickPosition = selectedCaret.begin;
|
|
lvclickPosition = getLastValidPosition.call(
|
|
inputmask,
|
|
clickPosition,
|
|
true
|
|
);
|
|
lastPosition = seekNext.call(
|
|
inputmask,
|
|
lvclickPosition === -1 && !isMask.call(inputmask, 0)
|
|
? -1
|
|
: lvclickPosition
|
|
);
|
|
|
|
if (clickPosition <= lastPosition) {
|
|
selectedCaret.end = selectedCaret.begin = !isMask.call(
|
|
inputmask,
|
|
clickPosition,
|
|
false,
|
|
true
|
|
)
|
|
? seekNext.call(inputmask, clickPosition)
|
|
: clickPosition;
|
|
} else {
|
|
const lvp = maskset.validPositions[lvclickPosition],
|
|
tt = getTestTemplate.call(
|
|
inputmask,
|
|
lastPosition,
|
|
lvp ? lvp.match.locator : undefined,
|
|
lvp
|
|
),
|
|
placeholder = getPlaceholder.call(
|
|
inputmask,
|
|
lastPosition,
|
|
tt.match
|
|
);
|
|
if (
|
|
(placeholder !== "" &&
|
|
getBuffer.call(inputmask)[lastPosition] !== placeholder &&
|
|
tt.match.optionalQuantifier !== true &&
|
|
tt.match.newBlockMarker !== true) ||
|
|
(!isMask.call(inputmask, lastPosition, opts.keepStatic, true) &&
|
|
tt.match.def === placeholder)
|
|
) {
|
|
const newPos = seekNext.call(inputmask, lastPosition);
|
|
if (clickPosition >= newPos || clickPosition === lastPosition) {
|
|
lastPosition = newPos;
|
|
}
|
|
}
|
|
selectedCaret.end = selectedCaret.begin = lastPosition;
|
|
}
|
|
}
|
|
|
|
return selectedCaret;
|
|
}
|
|
}
|
|
|
|
// tobe put on prototype?
|
|
function getBuffer(noCache) {
|
|
const inputmask = this,
|
|
{ maskset } = inputmask;
|
|
|
|
if (maskset.buffer === undefined || noCache === true) {
|
|
maskset.buffer = getMaskTemplate.call(
|
|
inputmask,
|
|
true,
|
|
getLastValidPosition.call(inputmask),
|
|
true
|
|
);
|
|
if (maskset._buffer === undefined) maskset._buffer = maskset.buffer.slice();
|
|
}
|
|
return maskset.buffer;
|
|
}
|
|
|
|
// tobe put on prototype?
|
|
function getBufferTemplate() {
|
|
const inputmask = this,
|
|
maskset = this.maskset;
|
|
|
|
if (maskset._buffer === undefined) {
|
|
// generate template
|
|
maskset._buffer = getMaskTemplate.call(inputmask, false, 1);
|
|
if (maskset.buffer === undefined) maskset.buffer = maskset._buffer.slice();
|
|
}
|
|
return maskset._buffer;
|
|
}
|
|
|
|
// tobe put on prototype?
|
|
function getLastValidPosition(closestTo, strict, validPositions) {
|
|
const maskset = this.maskset;
|
|
|
|
let before = -1,
|
|
after = -1;
|
|
const valids = validPositions || maskset.validPositions; // for use in valhook ~ context switch
|
|
if (closestTo === undefined) closestTo = -1;
|
|
for (let psNdx = 0, vpl = valids.length; psNdx < vpl; psNdx++) {
|
|
if (valids[psNdx] && (strict || valids[psNdx].generatedInput !== true)) {
|
|
if (psNdx <= closestTo) before = psNdx;
|
|
if (psNdx >= closestTo) after = psNdx;
|
|
}
|
|
}
|
|
return before === -1 || before === closestTo
|
|
? after
|
|
: after === -1
|
|
? before
|
|
: closestTo - before < after - closestTo
|
|
? before
|
|
: after;
|
|
}
|
|
|
|
// tobe put on prototype?
|
|
function isMask(pos, strict, fuzzy) {
|
|
const inputmask = this,
|
|
maskset = this.maskset;
|
|
|
|
let test = getTestTemplate.call(inputmask, pos).match;
|
|
if (test.def === "") test = getTest.call(inputmask, pos).match;
|
|
|
|
if (test.static !== true) {
|
|
return test.fn;
|
|
}
|
|
if (
|
|
fuzzy === true &&
|
|
maskset.validPositions[pos] !== undefined &&
|
|
maskset.validPositions[pos].generatedInput !== true
|
|
) {
|
|
return true;
|
|
}
|
|
|
|
if (strict !== true && pos > -1) {
|
|
if (fuzzy) {
|
|
// check on the number of tests
|
|
const tests = getTests.call(inputmask, pos);
|
|
return (
|
|
tests.length > 1 + (tests[tests.length - 1].match.def === "" ? 1 : 0)
|
|
);
|
|
}
|
|
// else based on the template
|
|
const testTemplate = determineTestTemplate.call(
|
|
inputmask,
|
|
pos,
|
|
getTests.call(inputmask, pos)
|
|
),
|
|
testPlaceHolder = getPlaceholder.call(inputmask, pos, testTemplate.match);
|
|
return testTemplate.match.def !== testPlaceHolder;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// tobe put on prototype?
|
|
// soft ~ undefined reset validpositions; soft = false also reset tests; soft = true only reset the maskset
|
|
function resetMaskSet(soft) {
|
|
const maskset = this.maskset;
|
|
|
|
maskset.buffer = undefined;
|
|
if (soft !== true) {
|
|
maskset.validPositions = [];
|
|
maskset.p = 0;
|
|
}
|
|
if (soft === false) {
|
|
maskset.tests = {};
|
|
maskset.jitOffset = {};
|
|
}
|
|
}
|
|
|
|
// tobe put on prototype?
|
|
function seekNext(pos, newBlock, fuzzy) {
|
|
const inputmask = this;
|
|
|
|
if (fuzzy === undefined) fuzzy = true;
|
|
let position = pos + 1;
|
|
while (
|
|
getTest.call(inputmask, position).match.def !== "" &&
|
|
((newBlock === true &&
|
|
(getTest.call(inputmask, position).match.newBlockMarker !== true ||
|
|
!isMask.call(inputmask, position, undefined, true))) ||
|
|
(newBlock !== true &&
|
|
!isMask.call(inputmask, position, undefined, fuzzy)))
|
|
) {
|
|
position++;
|
|
}
|
|
return position;
|
|
}
|
|
|
|
// tobe put on prototype?
|
|
function seekPrevious(pos, newBlock) {
|
|
const inputmask = this;
|
|
|
|
let position = pos - 1;
|
|
if (pos <= 0) return 0;
|
|
|
|
while (
|
|
position > 0 &&
|
|
((newBlock === true &&
|
|
(getTest.call(inputmask, position).match.newBlockMarker !== true ||
|
|
!isMask.call(inputmask, position, undefined, true))) ||
|
|
(newBlock !== true && !isMask.call(inputmask, position, undefined, true)))
|
|
) {
|
|
position--;
|
|
}
|
|
return position;
|
|
}
|
|
|
|
// tobe put on prototype?
|
|
function translatePosition(pos) {
|
|
const inputmask = this,
|
|
opts = this.opts,
|
|
el = this.el;
|
|
|
|
if (
|
|
inputmask.isRTL &&
|
|
typeof pos === "number" &&
|
|
(!opts.greedy || opts.placeholder !== "") &&
|
|
el
|
|
) {
|
|
pos = inputmask._valueGet().length - pos;
|
|
if (pos < 0) pos = 0;
|
|
}
|
|
return pos;
|
|
}
|