Skip to content

Instantly share code, notes, and snippets.

@zdennis
Last active February 1, 2018 18:07
Show Gist options
  • Save zdennis/c30edc957f8899335093032b56205330 to your computer and use it in GitHub Desktop.
Save zdennis/c30edc957f8899335093032b56205330 to your computer and use it in GitHub Desktop.
JavaScript spike into finding node at a position within another, and then returning a result that supplies information that can be used to construct a selection/range for moving the cursor
function findNodeAtPosition(node, position) {
const result = { node: undefined, offset: undefined, found: false, currentPosition: 0 };
return findNodeAtPositionWithResult(result, node, position);
}
function findNodeAtPositionWithResult(result, node, position, indent = ' ') {
console.log(indent + 'findNodeAtPositionWithResult: ', result, node, position);
let currentPosition = result.currentPosition;
let childNode;
let offset;
for (childNode of node.childNodes) {
console.log(indent + ' childNode: ', childNode);
offset = 0;
if (childNode.nodeType === Node.ELEMENT_NODE) {
result = findNodeAtPositionWithResult({
node: undefined,
offset: undefined,
found: false,
currentPosition: currentPosition
}, childNode, position);
if (result.found) {
return result;
} else {
currentPosition = result.currentPosition + 1; // for a new line
childNode = result.node;
}
console.log(indent + ' after element', result);
} else if (childNode.nodeType === Node.TEXT_NODE) {
if (currentPosition + childNode.length >= position) {
offset = position - currentPosition;
currentPosition = position;
console.log(indent + ' text', currentPosition, ' offset ', offset);
result = { node: childNode, offset: offset, currentPosition: currentPosition, found: true };
console.log(indent + 'got it: ', result);
return result;
} else {
currentPosition = currentPosition + childNode.length;
}
}
}
result = { node: childNode, offset: undefined, currentPosition: currentPosition, found: false };
console.log(indent + ' return', result);
return result;
}
function findPositionOfCursorInNode(node, result = null, sel = null, range = null, indent = ''){
if (!result) {
result = { position: 0, found: false };
}
if(!sel) {
sel = window.getSelection();
}
if (!range) {
range = sel.getRangeAt(0);
console.log('range: ', range);
}
for (childNode of node.childNodes) {
console.log(indent + 'childNode: ', childNode);
if (childNode === range.startContainer) {
console.log('found start', childNode)
return { position: result.position + range.startOffset, found: true };
}
if (childNode === range.endContainer) {
// no-op
}
if (childNode.nodeType === Node.ELEMENT_NODE) {
result = findPositionOfCursorInNode(childNode, result, sel, range, indent + ' ');
if(result.found) {
return result;
} else {
result = { position: result.position + 1, found: false }; // add 1 for newline
}
} else if (childNode.nodeType === Node.TEXT_NODE) {
console.log(indent + 'result.position + childNode.length: ', result.position + childNode.length, childNode);
result = { position: result.position + childNode.length, found: false };
}
}
return result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment