Files
Housekeeping-web-admin/node_modules/quilljs/lib/core/selection.js
T
2026-06-24 09:48:54 +02:00

231 lines
7.4 KiB
JavaScript

var Leaf, Normalizer, Range, Selection, dom, _;
_ = require('lodash');
dom = require('../lib/dom');
Leaf = require('./leaf');
Normalizer = require('../lib/normalizer');
Range = require('../lib/range');
Selection = (function() {
function Selection(doc, iframe, emitter) {
this.doc = doc;
this.iframe = iframe;
this.emitter = emitter;
this.document = this.doc.root.ownerDocument;
this.focus = false;
this.range = new Range(0, 0);
this.nullDelay = false;
this.update('silent');
}
Selection.prototype.checkFocus = function() {
return this.document.activeElement === this.doc.root && document.activeElement === this.iframe;
};
Selection.prototype.getRange = function(ignoreFocus) {
var end, nativeRange, start;
if (ignoreFocus == null) {
ignoreFocus = false;
}
if (this.checkFocus()) {
nativeRange = this._getNativeRange();
if (nativeRange == null) {
return null;
}
start = this._positionToIndex(nativeRange.startContainer, nativeRange.startOffset);
if (nativeRange.startContainer === nativeRange.endContainer && nativeRange.startOffset === nativeRange.endOffset) {
end = start;
} else {
end = this._positionToIndex(nativeRange.endContainer, nativeRange.endOffset);
}
return new Range(Math.min(start, end), Math.max(start, end));
} else if (ignoreFocus) {
return this.range;
} else {
return null;
}
};
Selection.prototype.preserve = function(fn) {
var endNode, endOffset, nativeRange, startNode, startOffset, _ref, _ref1, _ref2, _ref3;
nativeRange = this._getNativeRange();
if ((nativeRange != null) && this.checkFocus()) {
_ref = this._encodePosition(nativeRange.startContainer, nativeRange.startOffset), startNode = _ref[0], startOffset = _ref[1];
_ref1 = this._encodePosition(nativeRange.endContainer, nativeRange.endOffset), endNode = _ref1[0], endOffset = _ref1[1];
fn();
_ref2 = this._decodePosition(startNode, startOffset), startNode = _ref2[0], startOffset = _ref2[1];
_ref3 = this._decodePosition(endNode, endOffset), endNode = _ref3[0], endOffset = _ref3[1];
return this._setNativeRange(startNode, startOffset, endNode, endOffset);
} else {
return fn();
}
};
Selection.prototype.setRange = function(range, source) {
var endNode, endOffset, startNode, startOffset, _ref, _ref1, _ref2;
if (range != null) {
_ref = this._indexToPosition(range.start), startNode = _ref[0], startOffset = _ref[1];
if (range.isCollapsed()) {
_ref1 = [startNode, startOffset], endNode = _ref1[0], endOffset = _ref1[1];
} else {
_ref2 = this._indexToPosition(range.end), endNode = _ref2[0], endOffset = _ref2[1];
}
this._setNativeRange(startNode, startOffset, endNode, endOffset);
} else {
this._setNativeRange(null);
}
return this.update(source);
};
Selection.prototype.shiftAfter = function(index, length, fn) {
var range;
range = this.getRange();
fn();
if (range != null) {
range.shift(index, length);
return this.setRange(range, 'silent');
}
};
Selection.prototype.update = function(source) {
var emit, focus, range, toEmit;
focus = this.checkFocus();
range = this.getRange(true);
emit = source !== 'silent' && (!Range.compare(range, this.range) || focus !== this.focus);
toEmit = focus ? range : null;
if (toEmit === null && source === 'user' && !this.nullDelay) {
return this.nullDelay = true;
} else {
this.nullDelay = false;
this.range = range;
this.focus = focus;
if (emit) {
return this.emitter.emit(this.emitter.constructor.events.SELECTION_CHANGE, toEmit, source);
}
}
};
Selection.prototype._decodePosition = function(node, offset) {
var childIndex;
if (dom(node).isElement()) {
childIndex = _.indexOf(dom(node.parentNode).childNodes(), node);
offset += childIndex;
node = node.parentNode;
}
return [node, offset];
};
Selection.prototype._encodePosition = function(node, offset) {
var text;
while (true) {
if (dom(node).isTextNode() || node.tagName === dom.DEFAULT_BREAK_TAG || (dom.EMBED_TAGS[node.tagName] != null)) {
return [node, offset];
} else if (offset < node.childNodes.length) {
node = node.childNodes[offset];
offset = 0;
} else if (node.childNodes.length === 0) {
if (Normalizer.TAGS[node.tagName] == null) {
text = node.ownerDocument.createTextNode('');
node.appendChild(text);
node = text;
}
return [node, 0];
} else {
node = node.lastChild;
if (dom(node).isElement()) {
if (node.tagName === dom.DEFAULT_BREAK_TAG || (dom.EMBED_TAGS[node.tagName] != null)) {
return [node, 1];
} else {
offset = node.childNodes.length;
}
} else {
return [node, dom(node).length()];
}
}
}
};
Selection.prototype._getNativeRange = function() {
var range, selection;
selection = this.document.getSelection();
if ((selection != null ? selection.rangeCount : void 0) > 0) {
range = selection.getRangeAt(0);
if (dom(range.startContainer).isAncestor(this.doc.root, true)) {
if (range.startContainer === range.endContainer || dom(range.endContainer).isAncestor(this.doc.root, true)) {
return range;
}
}
}
return null;
};
Selection.prototype._indexToPosition = function(index) {
var leaf, offset, _ref;
if (this.doc.lines.length === 0) {
return [this.doc.root, 0];
}
_ref = this.doc.findLeafAt(index, true), leaf = _ref[0], offset = _ref[1];
return this._decodePosition(leaf.node, offset);
};
Selection.prototype._positionToIndex = function(node, offset) {
var leaf, leafNode, leafOffset, line, lineOffset, _ref;
_ref = this._encodePosition(node, offset), leafNode = _ref[0], offset = _ref[1];
line = this.doc.findLine(leafNode);
if (line == null) {
return 0;
}
leaf = line.findLeaf(leafNode);
lineOffset = 0;
while (line.prev != null) {
line = line.prev;
lineOffset += line.length;
}
if (leaf == null) {
return lineOffset;
}
leafOffset = 0;
while (leaf.prev != null) {
leaf = leaf.prev;
leafOffset += leaf.length;
}
return lineOffset + leafOffset + offset;
};
Selection.prototype._setNativeRange = function(startNode, startOffset, endNode, endOffset) {
var nativeRange, selection;
selection = this.document.getSelection();
if (!selection) {
return;
}
if (startNode != null) {
if (!this.checkFocus()) {
this.doc.root.focus();
}
nativeRange = this._getNativeRange();
if ((nativeRange == null) || startNode !== nativeRange.startContainer || startOffset !== nativeRange.startOffset || endNode !== nativeRange.endContainer || endOffset !== nativeRange.endOffset) {
selection.removeAllRanges();
nativeRange = this.document.createRange();
nativeRange.setStart(startNode, startOffset);
nativeRange.setEnd(endNode, endOffset);
selection.addRange(nativeRange);
if (!this.checkFocus()) {
return this.doc.root.focus();
}
}
} else {
selection.removeAllRanges();
return this.doc.root.blur();
}
};
return Selection;
})();
module.exports = Selection;