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
after this button.
The button gets removed in Chrome/Safari/Firefox when you hit backspace (after first removing the
), 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
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
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
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
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;
}
};
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