Skip to content

Instantly share code, notes, and snippets.

@tim-evans
Last active June 3, 2024 09:28
Show Gist options
  • Save tim-evans/7965138af5d153256953f63829d44c99 to your computer and use it in GitHub Desktop.
Save tim-evans/7965138af5d153256953f63829d44c99 to your computer and use it in GitHub Desktop.
/**
* Cross-browser support for caretPositionFromPoint.
* This returns a `CaretPosition` like object instead
* of a CaretPosition, since we can't create it for
* browsers that don't support this API.
*/
function caretPositionFromPoint(x: number, y: number): {
offsetNode: Node;
offset: number;
getClientRect(): ClientRect | DOMRect;
} | null {
// @ts-ignore
if (document.caretPositionFromPoint) {
// @ts-ignore
let position = document.caretPositionFromPoint(x, y);
return position ? {
offsetNode: position.offsetNode,
offset: position.offset,
getClientRect() {
return position.getClientRect();
}
} : null;
} else {
let range = document.caretRangeFromPoint(x, y);
return range ? {
offsetNode: range.startContainer,
offset: range.startOffset,
getClientRect() {
return range.getClientRects()[0];
}
} : null;
}
}
function getShadowRoots(node: Node, roots: ShadowRoot[] = []) {
let iter: Node | Element | ShadowRoot | null = node;
while (iter.parentNode || iter.host) {
if (iter instanceof ShadowRoot) {
roots.push(iter);
iter = iter.host!;
continue;
}
iter = iter.parentNode!;
}
return roots;
}
/**
* Cross-browser support for caret range from point.
* This is deprecated, but will be supported with a backfill
* from `caretPositionFromPoint`.
*
* @deprecated
*/
export function caretRangeFromPoint(x: number, y: number) {
if (document.caretPositionFromPoint) {
let position = document.caretPositionFromPoint(x, y);
if (position) {
let range = document.createRange();
let offsetNode = position.offsetNode;
let shadowRoots = getShadowRoots(offsetNode);
if (shadowRoots.length) {
offsetNode = shadowRoots[shadowRoots.length - 1].host!;
}
console.log(offsetNode);
debugger;
range.setStart(offsetNode, position.offset);
range.setEnd(offsetNode, position.offset);
return range;
}
return null;
} else {
return document.caretRangeFromPoint(x, y);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment