Skip to content

Instantly share code, notes, and snippets.

@waterplea
Created July 10, 2020 10:22
Show Gist options
  • Save waterplea/fcb68a1fc39b677c33c0446159b46a6b to your computer and use it in GitHub Desktop.
Save waterplea/fcb68a1fc39b677c33c0446159b46a6b to your computer and use it in GitHub Desktop.
Setting range in characters, traversing nodes
// Filtering SVGElements for TreeWalker
// Filter must be a function in IE, other modern browsers are compliant to this format
export const svgNodeFilter: NodeFilter = ((node: Node) =>
'ownerSVGElement' in node
? NodeFilter.FILTER_REJECT
: NodeFilter.FILTER_ACCEPT) as any;
/**
* Range.setStart/setEnd, except it uses offset in characters only
*/
export function setRangeOffset(
range: Range,
node: HTMLElement,
offset: number,
method: 'setStart' | 'setEnd',
) {
const {ownerDocument} = node;
if (!ownerDocument) {
return;
}
const treeWalker = ownerDocument.createTreeWalker(
node,
NodeFilter.SHOW_TEXT,
svgNodeFilter,
false,
);
treeWalker.currentNode = node;
while (treeWalker.nextNode()) {
if (treeWalker.currentNode.nodeType === Node.TEXT_NODE) {
const length = treeWalker.currentNode.nodeValue
? treeWalker.currentNode.nodeValue.length
: 0;
if (offset > length) {
offset -= length;
} else {
range[method](treeWalker.currentNode, offset);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment