summaryrefslogtreecommitdiff
path: root/alarm/node_modules/jsdom/lib/jsdom/living/selection/Selection-impl.js
diff options
context:
space:
mode:
Diffstat (limited to 'alarm/node_modules/jsdom/lib/jsdom/living/selection/Selection-impl.js')
-rw-r--r--alarm/node_modules/jsdom/lib/jsdom/living/selection/Selection-impl.js342
1 files changed, 342 insertions, 0 deletions
diff --git a/alarm/node_modules/jsdom/lib/jsdom/living/selection/Selection-impl.js b/alarm/node_modules/jsdom/lib/jsdom/living/selection/Selection-impl.js
new file mode 100644
index 0000000..93f31b4
--- /dev/null
+++ b/alarm/node_modules/jsdom/lib/jsdom/living/selection/Selection-impl.js
@@ -0,0 +1,342 @@
+"use strict";
+
+const DOMException = require("domexception/webidl2js-wrapper");
+
+const NODE_TYPE = require("../node-type");
+const { nodeLength, nodeRoot } = require("../helpers/node");
+const { domSymbolTree } = require("../helpers/internal-constants");
+const { compareBoundaryPointsPosition } = require("../range/boundary-point");
+
+const { setBoundaryPointStart, setBoundaryPointEnd } = require("../range/Range-impl");
+
+const Range = require("../generated/Range");
+const { implForWrapper } = require("../generated/utils");
+
+// https://w3c.github.io/selection-api/#dfn-direction
+const SELECTION_DIRECTION = {
+ FORWARDS: 1,
+ BACKWARDS: -1,
+ DIRECTIONLESS: 0
+};
+
+// https://w3c.github.io/selection-api/#dom-selection
+class SelectionImpl {
+ constructor(globalObject) {
+ this._range = null;
+ this._direction = SELECTION_DIRECTION.DIRECTIONLESS;
+
+ this._globalObject = globalObject;
+ }
+
+ // https://w3c.github.io/selection-api/#dom-selection-anchornode
+ get anchorNode() {
+ const anchor = this._anchor;
+ return anchor ? anchor.node : null;
+ }
+
+ // https://w3c.github.io/selection-api/#dom-selection-anchoroffset
+ get anchorOffset() {
+ const anchor = this._anchor;
+ return anchor ? anchor.offset : 0;
+ }
+
+ // https://w3c.github.io/selection-api/#dom-selection-focusnode
+ get focusNode() {
+ const focus = this._focus;
+ return focus ? focus.node : null;
+ }
+
+ // https://w3c.github.io/selection-api/#dom-selection-focusoffset
+ get focusOffset() {
+ const focus = this._focus;
+ return focus ? focus.offset : 0;
+ }
+
+ // https://w3c.github.io/selection-api/#dom-selection-iscollapsed
+ get isCollapsed() {
+ return this._range === null || this._range.collapsed;
+ }
+
+ // https://w3c.github.io/selection-api/#dom-selection-rangecount
+ get rangeCount() {
+ return this._isEmpty() ? 0 : 1;
+ }
+
+ // https://w3c.github.io/selection-api/#dom-selection-type
+ get type() {
+ if (this._isEmpty()) {
+ return "None";
+ } else if (this._range.collapsed) {
+ return "Caret";
+ }
+
+ return "Range";
+ }
+
+ // https://w3c.github.io/selection-api/#dom-selection-getrangeat
+ getRangeAt(index) {
+ if (index !== 0 || this._isEmpty()) {
+ throw DOMException.create(this._globalObject, ["Invalid range index.", "IndexSizeError"]);
+ }
+
+ return this._range;
+ }
+
+ // https://w3c.github.io/selection-api/#dom-selection-addrange
+ addRange(range) {
+ if (range._root === implForWrapper(this._globalObject._document) && this.rangeCount === 0) {
+ this._associateRange(range);
+ }
+ }
+
+ // https://w3c.github.io/selection-api/#dom-selection-removerange
+ removeRange(range) {
+ if (range !== this._range) {
+ throw DOMException.create(this._globalObject, ["Invalid range.", "NotFoundError"]);
+ }
+
+ this._associateRange(null);
+ }
+
+ // https://w3c.github.io/selection-api/#dom-selection-removeallranges
+ removeAllRanges() {
+ this._associateRange(null);
+ }
+
+ // https://w3c.github.io/selection-api/#dom-selection-empty
+ empty() {
+ this.removeAllRanges();
+ }
+
+ // https://w3c.github.io/selection-api/#dom-selection-collapse
+ collapse(node, offset) {
+ if (node === null) {
+ this.removeAllRanges();
+ return;
+ }
+
+ if (node.nodeType === NODE_TYPE.DOCUMENT_TYPE_NODE) {
+ throw DOMException.create(this._globalObject, [
+ "DocumentType Node can't be used as boundary point.",
+ "InvalidNodeTypeError"
+ ]);
+ }
+
+ if (offset > nodeLength(node)) {
+ throw DOMException.create(this._globalObject, ["Invalid range index.", "IndexSizeError"]);
+ }
+
+ if (nodeRoot(node) !== implForWrapper(this._globalObject._document)) {
+ return;
+ }
+
+ const newRange = Range.createImpl(this._globalObject, [], {
+ start: { node, offset: 0 },
+ end: { node, offset: 0 }
+ });
+
+ setBoundaryPointStart(newRange, node, offset);
+ setBoundaryPointEnd(newRange, node, offset);
+
+ this._associateRange(newRange);
+ }
+
+ // https://w3c.github.io/selection-api/#dom-selection-setposition
+ setPosition(node, offset) {
+ this.collapse(node, offset);
+ }
+
+ // https://w3c.github.io/selection-api/#dom-selection-collapsetostart
+ collapseToStart() {
+ if (this._isEmpty()) {
+ throw DOMException.create(this._globalObject, ["There is no selection to collapse.", "InvalidStateError"]);
+ }
+
+ const { node, offset } = this._range._start;
+ const newRange = Range.createImpl(this._globalObject, [], {
+ start: { node, offset },
+ end: { node, offset }
+ });
+
+ this._associateRange(newRange);
+ }
+
+ // https://w3c.github.io/selection-api/#dom-selection-collapsetoend
+ collapseToEnd() {
+ if (this._isEmpty()) {
+ throw DOMException.create(this._globalObject, ["There is no selection to collapse.", "InvalidStateError"]);
+ }
+
+ const { node, offset } = this._range._end;
+ const newRange = Range.createImpl(this._globalObject, [], {
+ start: { node, offset },
+ end: { node, offset }
+ });
+
+ this._associateRange(newRange);
+ }
+
+ // https://w3c.github.io/selection-api/#dom-selection-extend
+ extend(node, offset) {
+ if (nodeRoot(node) !== implForWrapper(this._globalObject._document)) {
+ return;
+ }
+
+ if (this._isEmpty()) {
+ throw DOMException.create(this._globalObject, ["There is no selection to extend.", "InvalidStateError"]);
+ }
+
+ const { _anchor: oldAnchor } = this;
+ const newFocus = { node, offset };
+
+ const newRange = Range.createImpl(this._globalObject, [], {
+ start: { node, offset: 0 },
+ end: { node, offset: 0 }
+ });
+
+ if (nodeRoot(node) !== this._range._root) {
+ setBoundaryPointStart(newRange, newFocus.node, newFocus.offset);
+ setBoundaryPointEnd(newRange, newFocus.node, newFocus.offset);
+ } else if (compareBoundaryPointsPosition(oldAnchor, newFocus) <= 0) {
+ setBoundaryPointStart(newRange, oldAnchor.node, oldAnchor.offset);
+ setBoundaryPointEnd(newRange, newFocus.node, newFocus.offset);
+ } else {
+ setBoundaryPointStart(newRange, newFocus.node, newFocus.offset);
+ setBoundaryPointEnd(newRange, oldAnchor.node, oldAnchor.offset);
+ }
+
+ this._associateRange(newRange);
+
+ this._direction = compareBoundaryPointsPosition(newFocus, oldAnchor) === -1 ?
+ SELECTION_DIRECTION.BACKWARDS :
+ SELECTION_DIRECTION.FORWARDS;
+ }
+
+ // https://w3c.github.io/selection-api/#dom-selection-setbaseandextent
+ setBaseAndExtent(anchorNode, anchorOffset, focusNode, focusOffset) {
+ if (anchorOffset > nodeLength(anchorNode) || focusOffset > nodeLength(focusNode)) {
+ throw DOMException.create(this._globalObject, ["Invalid anchor or focus offset.", "IndexSizeError"]);
+ }
+
+ const document = implForWrapper(this._globalObject._document);
+ if (document !== nodeRoot(anchorNode) || document !== nodeRoot(focusNode)) {
+ return;
+ }
+
+ const anchor = { node: anchorNode, offset: anchorOffset };
+ const focus = { node: focusNode, offset: focusOffset };
+
+ let newRange;
+ if (compareBoundaryPointsPosition(anchor, focus) === -1) {
+ newRange = Range.createImpl(this._globalObject, [], {
+ start: { node: anchor.node, offset: anchor.offset },
+ end: { node: focus.node, offset: focus.offset }
+ });
+ } else {
+ newRange = Range.createImpl(this._globalObject, [], {
+ start: { node: focus.node, offset: focus.offset },
+ end: { node: anchor.node, offset: anchor.offset }
+ });
+ }
+
+ this._associateRange(newRange);
+
+ this._direction = compareBoundaryPointsPosition(focus, anchor) === -1 ?
+ SELECTION_DIRECTION.BACKWARDS :
+ SELECTION_DIRECTION.FORWARDS;
+ }
+
+ // https://w3c.github.io/selection-api/#dom-selection-selectallchildren
+ selectAllChildren(node) {
+ if (node.nodeType === NODE_TYPE.DOCUMENT_TYPE_NODE) {
+ throw DOMException.create(this._globalObject, [
+ "DocumentType Node can't be used as boundary point.",
+ "InvalidNodeTypeError"
+ ]);
+ }
+
+ const document = implForWrapper(this._globalObject._document);
+ if (document !== nodeRoot(node)) {
+ return;
+ }
+
+ const length = domSymbolTree.childrenCount(node);
+
+ const newRange = Range.createImpl(this._globalObject, [], {
+ start: { node, offset: 0 },
+ end: { node, offset: 0 }
+ });
+
+ setBoundaryPointStart(newRange, node, 0);
+ setBoundaryPointEnd(newRange, node, length);
+
+ this._associateRange(newRange);
+ }
+
+ // https://w3c.github.io/selection-api/#dom-selection-deletefromdocument
+ deleteFromDocument() {
+ if (!this._isEmpty()) {
+ this._range.deleteContents();
+ }
+ }
+
+ // https://w3c.github.io/selection-api/#dom-selection-containsnode
+ containsNode(node, allowPartialContainment) {
+ if (this._isEmpty() || nodeRoot(node) !== implForWrapper(this._globalObject._document)) {
+ return false;
+ }
+
+ const { _start, _end } = this._range;
+
+ const startIsBeforeNode = compareBoundaryPointsPosition(_start, { node, offset: 0 }) === -1;
+ const endIsAfterNode = compareBoundaryPointsPosition(_end, { node, offset: nodeLength(node) }) === 1;
+
+ return allowPartialContainment ?
+ startIsBeforeNode || endIsAfterNode :
+ startIsBeforeNode && endIsAfterNode;
+ }
+
+ // https://w3c.github.io/selection-api/#dom-selection-stringifier
+ toString() {
+ return this._range ? this._range.toString() : "";
+ }
+
+ // https://w3c.github.io/selection-api/#dfn-empty
+ _isEmpty() {
+ return this._range === null;
+ }
+
+ // https://w3c.github.io/selection-api/#dfn-anchor
+ get _anchor() {
+ if (!this._range) {
+ return null;
+ }
+
+ return this._direction === SELECTION_DIRECTION.FORWARDS ?
+ this._range._start :
+ this._range._end;
+ }
+
+ // https://w3c.github.io/selection-api/#dfn-focus
+ get _focus() {
+ if (!this._range) {
+ return null;
+ }
+
+ return this._direction === SELECTION_DIRECTION.FORWARDS ?
+ this._range._end :
+ this._range._start;
+ }
+
+ _associateRange(newRange) {
+ this._range = newRange;
+ this._direction = newRange === null ? SELECTION_DIRECTION.DIRECTIONLESS : SELECTION_DIRECTION.FORWARDS;
+
+ // TODO: Emit "selectionchange" event. At this time, there is currently no test in WPT covering this.
+ // https://w3c.github.io/selection-api/#selectionchange-event
+ }
+}
+
+module.exports = {
+ implementation: SelectionImpl
+};