开发者

remove selected (highlighted elements) except for input#cursor

开发者 https://www.devze.com 2023-04-11 00:35 出处:网络
I have this function which removes selected (cursor) highlighted element开发者_StackOverflow社区s:

I have this function which removes selected (cursor) highlighted element开发者_StackOverflow社区s:

function deleteSelection() {
    if (window.getSelection) {
        // Mozilla
        var selection = window.getSelection();
        if (selection.rangeCount > 0) {
            window.getSelection().deleteFromDocument();
            window.getSelection().removeAllRanges();
        }
    } else if (document.selection) {
        // Internet Explorer
        var ranges = document.selection.createRangeCollection();
        for (var i = 0; i < ranges.length; i++) {
            ranges[i].text = "";
        }
    }
}

What I actually want to do is remove all the cursor- highlighted elements, except for the input#cursor element.

edit:

so lets say if I highlighted these elements with my cursor:

<span>a</span>
<span>b</span>
<input type='text' id = 'cursor' />
<span>c</span>
<span>d</span>

on a keyup, this function should not remove the <input> ...only the <span>


Phew, that was a little harder than expected!

Here's the code, I've tested it in IE8 and Chrome 16/FF5. The JSFiddle I used to test is available here. AFAIK, this is probably the best performance-wise you'll get.

The docs I used for Moz: Selection, Range, DocumentFragment. IE: TextRange

function deleteSelection() {
    // get cursor element
    var cursor = document.getElementById('cursor');

    // mozilla
    if(window.getSelection) {
        var selection = window.getSelection();
        var containsCursor = selection.containsNode(cursor, true);

        if(containsCursor) {
            var cursorFound = false;
            for(var i=0; i < selection.rangeCount; i++) {
                var range = selection.getRangeAt(i);
                if(!cursorFound) {                 
                    // extracts tree from DOM and gives back a fragment
                    var contents = range.extractContents();
                    // check if tree fragment contains our cursor
                    cursorFound = containsChildById(contents, 'cursor');
                    if(cursorFound) range.insertNode(cursor); // put back in DOM
                }
                else {
                    // deletes everything in range
                    range.deleteContents();
                }
            }  
        }
        else {
            selection.deleteFromDocument();
        }
        // removes highlight   
        selection.removeAllRanges();
    }
    // ie
    else if(document.selection) {
        var ranges = document.selection.createRangeCollection();
        var cursorFound = false;
        for(var i=0; i < ranges.length; i++) {
            if(!cursorFound) {
                // hacky but it will work
                cursorFound = (ranges[i].htmlText.indexOf('id=cursor') != -1);
                if(cursorFound)
                    ranges[i].pasteHTML(cursor.outerHTML); // replaces html with parameter
                else
                    ranges[i].text = '';
            }
            else {
                ranges[i].text = '';
            }
        }
    }
}

// simple BFS to find an id in a tree, not sure if you have a 
// library function that does this or not
function containsChildById(source, id) {
    q = [];
    q.push(source);

    while(q.length > 0) {
        var current = q.shift();
        if(current.id == id)
            return true;

        for(var i=0; i < current.childNodes.length; i++) {
            q.push(current.childNodes[i]);
        }
    }

    return false;
}


I would suggest removing the element you want keep, extracting the contents of the selection using Range's extractContents() method and then reinserting the element you want to keep using the range's insertNode() method.

For IE < 9, which doesn't support DOM Range, the code is trickier, so for simplicity you could use my Rangy library, which also adds convenience methods such as the containsNode() method of Range.

Live demo: http://jsfiddle.net/DFxH8/1/

Code:

function deleteSelectedExcept(node) {
    var sel = rangy.getSelection();
    if (!sel.isCollapsed) {
        for (var i = 0, len = sel.rangeCount, range, nodeInRange; i < len; ++i) {
            range = sel.getRangeAt(i);
            nodeInRange = range.containsNode(node);
            range.extractContents();
            if (nodeInRange) {
                range.insertNode(node);
            }
        }
    }
}

deleteSelectedExcept(document.getElementById("cursor"));
0

精彩评论

暂无评论...
验证码 换一张
取 消