Search code examples
javascriptjquerytraversal

How can I find all text nodes between two element nodes with JavaScript/jQuery?


Given the following HTML-Fragment:

<div>
  <p>
    abc <span id="x">[</span> def <br /> ghi
  </p>
  <p>
    <strong> jkl <span id="y">]</span> mno </strong>
  </p>
</div>

I need an algorithm to fetch all nodes of type Text between #x and #y with Javascript. Or is there a JQuery function that does exactly that?

The resulting Text nodes (whitespace nodes ignored) for the example above would then be:

['def', 'ghi', 'jkl']

Solution

  • The following works in all major browsers using DOM methods and no library. It also ignores whitespace text nodes as mentioned in the question.

    Obligatory jsfiddle: http://jsfiddle.net/timdown/a2Fm6/

    function getTextNodesBetween(rootNode, startNode, endNode) {
        var pastStartNode = false, reachedEndNode = false, textNodes = [];
    
        function getTextNodes(node) {
            if (node == startNode) {
                pastStartNode = true;
            } else if (node == endNode) {
                reachedEndNode = true;
            } else if (node.nodeType == 3) {
                if (pastStartNode && !reachedEndNode && !/^\s*$/.test(node.nodeValue)) {
                    textNodes.push(node);
                }
            } else {
                for (var i = 0, len = node.childNodes.length; !reachedEndNode && i < len; ++i) {
                    getTextNodes(node.childNodes[i]);
                }
            }
        }
    
        getTextNodes(rootNode);
        return textNodes;
    }
    
    var x = document.getElementById("x"),
        y = document.getElementById("y");
    
    var textNodes = getTextNodesBetween(document.body, x, y);
    console.log(textNodes);