You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
104 lines
3.1 KiB
104 lines
3.1 KiB
2 years ago
|
"use strict";
|
||
|
|
||
|
Object.defineProperty(exports, "__esModule", {
|
||
|
value: true
|
||
|
});
|
||
|
exports.getSelectionRange = getSelectionRange;
|
||
|
exports.hasSelectionSupport = hasSelectionSupport;
|
||
|
exports.setSelectionRange = setSelectionRange;
|
||
|
|
||
|
var _isElementType = require("../misc/isElementType");
|
||
|
|
||
|
// https://github.com/jsdom/jsdom/blob/c2fb8ff94917a4d45e2398543f5dd2a8fed0bdab/lib/jsdom/living/nodes/HTMLInputElement-impl.js#L45
|
||
|
var selectionSupportType;
|
||
|
|
||
|
(function (selectionSupportType) {
|
||
|
selectionSupportType["text"] = "text";
|
||
|
selectionSupportType["search"] = "search";
|
||
|
selectionSupportType["url"] = "url";
|
||
|
selectionSupportType["tel"] = "tel";
|
||
|
selectionSupportType["password"] = "password";
|
||
|
})(selectionSupportType || (selectionSupportType = {}));
|
||
|
|
||
|
const InputSelection = Symbol('inputSelection');
|
||
|
|
||
|
function hasSelectionSupport(element) {
|
||
|
return (0, _isElementType.isElementType)(element, 'textarea') || (0, _isElementType.isElementType)(element, 'input') && Boolean(selectionSupportType[element.type]);
|
||
|
}
|
||
|
|
||
|
function getSelectionRange(element) {
|
||
|
if (hasSelectionSupport(element)) {
|
||
|
return {
|
||
|
selectionStart: element.selectionStart,
|
||
|
selectionEnd: element.selectionEnd
|
||
|
};
|
||
|
}
|
||
|
|
||
|
if ((0, _isElementType.isElementType)(element, 'input')) {
|
||
|
var _InputSelection;
|
||
|
|
||
|
return (_InputSelection = element[InputSelection]) != null ? _InputSelection : {
|
||
|
selectionStart: null,
|
||
|
selectionEnd: null
|
||
|
};
|
||
|
}
|
||
|
|
||
|
const selection = element.ownerDocument.getSelection(); // there should be no editing if the focusNode is outside of element
|
||
|
// TODO: properly handle selection ranges
|
||
|
|
||
|
if (selection != null && selection.rangeCount && element.contains(selection.focusNode)) {
|
||
|
const range = selection.getRangeAt(0);
|
||
|
return {
|
||
|
selectionStart: range.startOffset,
|
||
|
selectionEnd: range.endOffset
|
||
|
};
|
||
|
} else {
|
||
|
return {
|
||
|
selectionStart: null,
|
||
|
selectionEnd: null
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function setSelectionRange(element, newSelectionStart, newSelectionEnd) {
|
||
|
const {
|
||
|
selectionStart,
|
||
|
selectionEnd
|
||
|
} = getSelectionRange(element);
|
||
|
|
||
|
if (selectionStart === newSelectionStart && selectionEnd === newSelectionEnd) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (hasSelectionSupport(element)) {
|
||
|
element.setSelectionRange(newSelectionStart, newSelectionEnd);
|
||
|
}
|
||
|
|
||
|
if ((0, _isElementType.isElementType)(element, 'input')) {
|
||
|
;
|
||
|
element[InputSelection] = {
|
||
|
selectionStart: newSelectionStart,
|
||
|
selectionEnd: newSelectionEnd
|
||
|
};
|
||
|
} // Moving the selection inside <input> or <textarea> does not alter the document Selection.
|
||
|
|
||
|
|
||
|
if ((0, _isElementType.isElementType)(element, 'input') || (0, _isElementType.isElementType)(element, 'textarea')) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
const range = element.ownerDocument.createRange();
|
||
|
range.selectNodeContents(element); // istanbul ignore else
|
||
|
|
||
|
if (element.firstChild) {
|
||
|
range.setStart(element.firstChild, newSelectionStart);
|
||
|
range.setEnd(element.firstChild, newSelectionEnd);
|
||
|
}
|
||
|
|
||
|
const selection = element.ownerDocument.getSelection(); // istanbul ignore else
|
||
|
|
||
|
if (selection) {
|
||
|
selection.removeAllRanges();
|
||
|
selection.addRange(range);
|
||
|
}
|
||
|
}
|