Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 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 | 1x 1x 1x 30x 30x 46x 23x 21x 21x 21x 23x 106x 53x 53x 53x 53x 7x 46x 46x 23x | import { isNodeOfType } from '../isNodeOfType';
import { normalizeRect } from '../normalizeRect';
import type { DOMInsertPoint, Rect } from 'roosterjs-content-model-types';
/**
* Get bounding rect of the given DOM insert point
* @param doc The document object
* @param pos The input DOM insert point
*/
export function getDOMInsertPointRect(doc: Document, pos: DOMInsertPoint): Rect | null {
const range = doc.createRange();
return (
tryGetRectFromPos(pos, range) ?? // 1. try get from the pos directly using getBoundingClientRect or getClientRects
tryGetRectFromPos((pos = normalizeInsertPoint(pos)), range) ?? // 2. try get normalized pos, this can work when insert point is inside text node
tryGetRectFromNode(pos.node) // 3. fallback to node rect using getBoundingClientRect
);
}
function normalizeInsertPoint(pos: DOMInsertPoint) {
let { node, offset } = pos;
while (node.lastChild) {
Iif (offset == node.childNodes.length) {
node = node.lastChild;
offset = node.childNodes.length;
} else {
node = node.childNodes[offset];
offset = 0;
}
}
return { node, offset };
}
function tryGetRectFromPos(pos: DOMInsertPoint, range: Range): Rect | null {
const { node, offset } = pos;
range.setStart(node, offset);
range.setEnd(node, offset);
const rect = normalizeRect(range.getBoundingClientRect());
if (rect) {
return rect;
} else {
const rects = range.getClientRects && range.getClientRects();
return rects && rects.length == 1 ? normalizeRect(rects[0]) : null;
}
}
function tryGetRectFromNode(node: Node) {
return isNodeOfType(node, 'ELEMENT_NODE') && node.getBoundingClientRect
? normalizeRect(node.getBoundingClientRect())
: null;
}
|