JS: Get array of all selected nodes in contentEditable div

html, javascript, wysiwyg

Solution

Here's a version that gives you the actual selected and partially selected nodes rather than clones. Alternatively you could use my Rangy library, which has a `getNodes()` method of its Range objects and works in IE < 9.

function nextNode(node) {
    if (node.hasChildNodes()) {
        return node.firstChild;
    } else {
        while (node && !node.nextSibling) {
            node = node.parentNode;
        }
        if (!node) {
            return null;
        }
        return node.nextSibling;
    }
}

function getRangeSelectedNodes(range) {
    var node = range.startContainer;
    var endNode = range.endContainer;

    // Special case for a range that is contained within a single node
    if (node == endNode) {
        return [node];
    }

    // Iterate nodes until we hit the end container
    var rangeNodes = [];
    while (node && node != endNode) {
        rangeNodes.push( node = nextNode(node) );
    }

    // Add partially selected nodes at the start of the range
    node = range.startContainer;
    while (node && node != range.commonAncestorContainer) {
        rangeNodes.unshift(node);
        node = node.parentNode;
    }

    return rangeNodes;
}

function getSelectedNodes() {
    if (window.getSelection) {
        var sel = window.getSelection();
        if (!sel.isCollapsed) {
            return getRangeSelectedNodes(sel.getRangeAt(0));
        }
    }
    return [];
}

Problem

Hi I've been working with contentEditable for a while now and I think I have a pretty good handle on it. One thing that's evading me is how to get an array of references to all nodes that are partially or fully within the user's selection. Anyone got an idea? Here's something to start from: ``` <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script type="text/javascript"> function getSelectedNodes(){ var sel = window.getSelection(); try{var frag=sel.getRangeAt(0).cloneContents()}catch(e){return(false);} var tempspan = document.createElement("span"); tempspan.appendChild(frag); var selnodes = Array() //<<- how do I fill this array?? var output = '' for(i in selnodes){ output += "A "+selnodes[i].tagName+" was found\n" //do something cool with each element here... } return(output) } </script> </head> <body contentEditable="true" onkeypress="return(keypress(event))"> <div>This <strong>div</strong> is <em>content</em> <span class='red'>editable</span> and has a couple of <em><strong>child nodes</strong></em> within it</div> <br /> <br /> <a href="#" onmouseover="alert(getSelectedNodes())">hover here</a> </body> </html> ```

Original source

Related problems