2021-10-11 Text in Range
by Ttt Yyy
HTML
<div>
<div>
<span id="start"> Hello </span>
<div>
<img src="http://placehold.it/100x75" />
</div>
<div>
<span> include me </span>
</div>
<span id="end">World</span>
<span>don't include me</span>
</div>
<br />
<div id="console-1"></div>
<div id="console-2"></div>
</div>
JavaScript
// most optimized solution
function getHighlighted(nodeA, nodeB) {
// nodeValue returns value of node;
let result = nodeA.nodeValue;
let current = nodeA;
while (current !== nodeB) {
if (current.firstChild !== null) {
// if have children, traverse into child
current = current.firstChild;
} else {
while (current.nextSibling === null) {
// already at child, if no next sibling, go back to parent
current = current.parentNode;
}
current = current.nextSibling;
}
// if equals to text node
if (current.nodeType === 3) {
result += current.nodeValue;
}
}
return result;
}
const getHighlightedTextLCA = (nodeA, nodeB) => {
const getPath = node => {
const path = [];
let pointer = node;
while (pointer) {
path.push(pointer);
pointer = pointer.parentNode;
}
path.reverse();
return path;
};
const findLCA = (nodeA, nodeB) => {
let nodeAPath = getPath(nodeA);
let nodeBPath = getPath(nodeB);
let lca;
let index = 0;
while (index < nodeAPath.length && nodeAPath[index] === nodeBPath[index]) {
lca = nodeAPath[index];
index++;
}
return lca;
};
// start here
let lca = findLCA(nodeA, nodeB);
let isPassedNodeA = false;
let isPassedNodeB = false;
let result = "";
const traverse = node => {
if (node === nodeA) {
isPassedNodeA = true;
}
// only want to add to result if passed A
if (isPassedNodeA && node.nodeType === 3) {
result += node.nodeValue;
}
if (node === nodeB) {
isPassedNodeB = true;
return;
}
let pointer = node.firstChild;
while (pointer !== null && !isPassedNodeB) {
traverse(pointer);
pointer = pointer.nextSibling;
}
};
traverse(lca);
return result;
};
document.getElementById('console-1').innerHTML = 'Result 1: ' +
getHighlighted(
document.getElementById('start').firstChild,
...