How to delete an HTML element inside a div with attribute contentEditable?

前端 未结 3 677
旧时难觅i
旧时难觅i 2020-12-02 18:13

have this html:

Text to delete
相关标签:
3条回答
  • 2020-12-02 18:27

    Because you want to delete the whole element, it's better to make it contenteditable="false" so that browser won't let the contents of an element to be deleted.

    Then you can use this attribute for tests in event handler as follows:

    $('#editable').on('keydown', function (event) {
        if (window.getSelection && event.which == 8) { // backspace
            // fix backspace bug in FF
            // https://bugzilla.mozilla.org/show_bug.cgi?id=685445
            var selection = window.getSelection();
            if (!selection.isCollapsed || !selection.rangeCount) {
                return;
            }
    
            var curRange = selection.getRangeAt(selection.rangeCount - 1);
            if (curRange.commonAncestorContainer.nodeType == 3 && curRange.startOffset > 0) {
                // we are in child selection. The characters of the text node is being deleted
                return;
            }
    
            var range = document.createRange();
            if (selection.anchorNode != this) {
                // selection is in character mode. expand it to the whole editable field
                range.selectNodeContents(this);
                range.setEndBefore(selection.anchorNode);
            } else if (selection.anchorOffset > 0) {
                range.setEnd(this, selection.anchorOffset);
            } else {
                // reached the beginning of editable field
                return;
            }
            range.setStart(this, range.endOffset - 1);
    
    
            var previousNode = range.cloneContents().lastChild;
            if (previousNode && previousNode.contentEditable == 'false') {
                // this is some rich content, e.g. smile. We should help the user to delete it
                range.deleteContents();
                event.preventDefault();
            }
        }
    });
    

    demo on jsfiddle

    0 讨论(0)
  • 2020-12-02 18:36

    This turned out to be more complicated than I thought. Or I've made it more complicated than it needs to be. Anyway, this should work in all the big browsers:

    function getLastTextNodeIn(node) {
        while (node) {
            if (node.nodeType == 3) {
                return node;
            } else {
                node = node.lastChild;
            }
        }
    }
    
    function isRangeAfterNode(range, node) {
        var nodeRange, lastTextNode;
        if (range.compareBoundaryPoints) {
            nodeRange = document.createRange();
            lastTextNode = getLastTextNodeIn(node);
            nodeRange.selectNodeContents(lastTextNode);
            nodeRange.collapse(false);
            return range.compareBoundaryPoints(range.START_TO_END, nodeRange) > -1;
        } else if (range.compareEndPoints) {
            if (node.nodeType == 1) {
                nodeRange = document.body.createTextRange();
                nodeRange.moveToElementText(node);
                nodeRange.collapse(false);
                return range.compareEndPoints("StartToEnd", nodeRange) > -1;
            } else {
                return false;
            }
        }
    }
    
    document.getElementById("editable").onkeydown = function(evt) {
        var sel, range, node, nodeToDelete, nextNode, nodeRange;
        evt = evt || window.event;
        if (evt.keyCode == 8) {
            // Get the DOM node containing the start of the selection
            if (window.getSelection && window.getSelection().getRangeAt) {
                range = window.getSelection().getRangeAt(0);
            } else if (document.selection && document.selection.createRange) {
                range = document.selection.createRange();
            }
    
            if (range) {
                node = this.lastChild;
                while (node) {
                    if ( isRangeAfterNode(range, node) ) {
                        nodeToDelete = node;
                        break;
                    } else {
                        node = node.previousSibling;
                    }
                }
    
                if (nodeToDelete) {
                    this.removeChild(nodeToDelete);
                }
            }
            return false;
        }
    };
    
    0 讨论(0)
  • 2020-12-02 18:42

    Seems to work by default (without any javascript) in latest Chrome version (I've tested with 61.0.3163.100).

    0 讨论(0)
提交回复
热议问题