contenteditable div: IE8 not happy with backspace remove of HTML element

﹥>﹥吖頭↗ 提交于 2019-12-31 22:35:30

问题


I am making use of a contenteditable div in combination with the rangy Javascript library to insert HTML at the cursor position.

End of the day the contents of the div commonly looks like:

<div contenteditable="true">
    "Hello "
    <button contenteditable="false" data-id="147">@John Smith</button>
    " "
</div>

Users get suggested upon pressing '@' and get subsequently inserted as a button when selected (ala Google Plus). I also insert a &nbsp; after this button.

The button gets removed in Chrome/Safari/Firefox when you hit backspace (after first removing the &nbsp;), but not in IE8. In IE8 the cursor merely jumps over the button without removing it. What's even more bizarre in IE8 is if you leave the &nbsp; next to the button - and rather place the cursor right next to the button - it removes the button on backspace. So it's happy when there's a &nbsp; to the right of the cursor.

Does anyone know what I need in order to make IE8 work i.t.o. removing the button upon backspace without the need for a &nbsp; to the right of the cursor? (some info on this strange behaviour might also help)

P.S. I haven't tested other versions of IE


回答1:


My suggestion would be to first check the caret is positioned after the non-editable node, and if so, create a range that starts immediately after the non-editable element and ends at the caret position. Check whether the text in this range is empty. If it is, that means the caret is placed directly after the non-editable element, so in that case remove the element. Finally, place the caret where the non-editable had been.

Live demo: http://jsfiddle.net/timdown/vu3ub/

Code:

document.onkeypress = function(e) {
    e = e || window.event;
    var keyCode = e.which || e.keyCode;
    if (keyCode !== 8) {
        return;
    }

    var sel = rangy.getSelection();
    if (sel.rangeCount === 0) {
        return;
    }

    var selRange = sel.getRangeAt(0);
    if (!selRange.collapsed) {
        return;
    }

    var nonEditable = document.getElementById("nonEditable");
    if (!nonEditable) {
        return;
    }

    // Check the caret is located after the non-editable element
    var range = rangy.createRange();
    range.collapseAfter(nonEditable);

    if (selRange.compareBoundaryPoints(range.START_TO_END, range) == -1) {
        return;
    }

    // Check whether there is any text between the caret and the
    // non-editable element. If not, delete the element and move
    // the caret to where it had been
    range.setEnd(selRange.startContainer, selRange.startOffset);
    if (range.toString() === "") {
        selRange.collapseBefore(nonEditable);
        nonEditable.parentNode.removeChild(nonEditable);
        sel.setSingleRange(selRange);

        // Prevent the default browser behaviour
        return false;
    }
};



回答2:


I made a jsfiddle with a quick sample of how to look at the range of the selection and use the previousSibling property of the startContainer to find the button: jsfiddle

Put the cursor in aaa and it will show the button is prev sibling. put it in ccc and bbb will show.

So with this you could handle the keydown event of the div, check if key is backspace + previousSibling is your button, and remove it with jQuery.

previousSibling is null if it is a textnode though, just FYI.



来源:https://stackoverflow.com/questions/9983868/contenteditable-div-ie8-not-happy-with-backspace-remove-of-html-element

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!