JS: Get array of all selected nodes in contentEditable div

后端 未结 3 1450
既然无缘
既然无缘 2020-11-28 11:12

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 t

相关标签:
3条回答
  • 2020-11-28 11:55

    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 [];
    }
    
    0 讨论(0)
  • 2020-11-28 12:03

    You're so close! When you append the Document Fragment to the temporary span element, you've turned them into a manageable group, accessible through the trusty childNodes array.

        var selnodes = tempspan.childNodes;
    

    Additionally, you're setting yourself up for some trouble with that for(i in selnodes) loop, which would return the elements in the array, PLUS the length property, and the __proto__ property, and any other properties the object may have.

    You should really only use those kinds of for loops when looping over the properties in an object, and then always with if (obj.hasOwnProperty[i]) to filter out properties inherited from the prototype.

    When looping through arrays, use:

        for(var i=0,u=selnodes.length;i<u;i++)
    

    Finally, once you load that array, you'll actually need to check each element to see if it's a DOM node or a Text node before you can handle it. We can do that by checking to see if it supports the tagName property.

        if (typeof selnodes[i].tagName !== 'undefined')
    

    Here's the whole thing:

    <!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);
        console.log(tempspan);
        window.selnodes = tempspan.childNodes;
        var output = ''
        for(var i=0, u=selnodes.length;i<u;i++){
            if (typeof selnodes[i].tagName !== 'undefined'){
              output += "A "+selnodes[i].tagName+" was found\n"
            }
            else output += "Some text was found: '"+selnodes[i].textContent+"'\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>
    
    0 讨论(0)
  • 2020-11-28 12:07

    Below Code is sample to solve your problem, below code return all selected node that in range

    <!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" />
    <title>payam jabbari</title>
    <script src="http://code.jquery.com/jquery-2.0.2.min.js" type="text/javascript"></script>
    <script type="text/javascript">
    
    $(document).ready(function(){
        var startNode = $('p.first').contents().get(0);
    var endNode = $('span.second').contents().get(0);
    var range = document.createRange();
    range.setStart(startNode, 0);
    range.setEnd(endNode, 5);
    var selection = document.getSelection();
    selection.addRange(range);
    // below code return all nodes in selection range. this code work in all browser
    var nodes = range.cloneContents().querySelectorAll("*");
    for(var i=0;i<nodes.length;i++)
    {
       alert(nodes[i].innerHTML);
    }
    });
    </script>
    </head>
    
    <body>
    <div>
    
    <p class="first">Even a week ago, the idea of a Russian military intervention in Ukraine seemed far-fetched if not totally alarmist. But the arrival of Russian troops in Crimea over the weekend has shown that he is not averse to reckless adventures, even ones that offer little gain. In the coming days and weeks</p>
    
    <ol>
        <li>China says military will respond to provocations.</li>
        <li >This Man Has Served 20 <span class="second"> Years—and May Die—in </span> Prison for Marijuana.</li>
        <li>At White House, Israel's Netanyahu pushes back against Obama diplomacy.</li>
    </ol>
    </div>
    </body>
    </html>
    
    0 讨论(0)
提交回复
热议问题