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,
   ...