-
Notifications
You must be signed in to change notification settings - Fork 54
/
Copy pathselection.js
65 lines (56 loc) · 2.04 KB
/
selection.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import { closest, contains } from "./dom.js";
export function isSelectionForward(selection) {
if (selection.isCollapsed) return true;
const comparedPositions = selection.anchorNode.compareDocumentPosition(selection.focusNode);
if (!comparedPositions) {
// It's the same node
return selection.anchorOffset < selection.focusOffset;
}
// eslint-disable-next-line no-bitwise
return (comparedPositions & 4 /* === Node.DOCUMENT_POSITION_FOLLOWING */) > 0;
}
export function getEndLineRect(range, isForward) {
let endLineRects;
const rangeRects = range.getClientRects();
const sliceRects = [].slice.bind(rangeRects);
if (isForward) {
let lastLeft = Infinity;
let i = rangeRects.length;
while (i--) {
const rect = rangeRects[i];
if (rect.left > lastLeft) break;
lastLeft = rect.left;
}
endLineRects = sliceRects(i + 1);
} else {
let lastRight = -Infinity;
let i = 0;
for (; i < rangeRects.length; i++) {
const rect = rangeRects[i];
if (rect.right < lastRight) break;
lastRight = rect.right;
}
endLineRects = sliceRects(0, i);
}
return {
top: Math.min(...endLineRects.map(rect => rect.top)),
bottom: Math.max(...endLineRects.map(rect => rect.bottom)),
left: endLineRects[0].left,
right: endLineRects[endLineRects.length - 1].right
};
}
export function constrainRange(range, selector) {
const constrainedRange = range.cloneRange();
if (range.collapsed || !selector) return constrainedRange;
let ancestor = closest(range.startContainer, selector);
if (ancestor) {
if (!contains(ancestor, range.endContainer)) {
constrainedRange.setEnd(ancestor, ancestor.childNodes.length);
}
} else {
ancestor = closest(range.endContainer, selector);
if (ancestor) constrainedRange.setStart(ancestor, 0);
else constrainedRange.collapse();
}
return constrainedRange;
}