问题
In a contenteditable element, when execCommand is called with command insertHTML, if selection is inside a node command unwraps the div tag around the inserted html segment.
Sample HTML Code block is as follows:
<div id="editable" contenteditable="true">
<div>Some text</div>
<div>Yet another</div>
<div>and other</div>
</div>
<input id="insert" type="button" value="Insert Segment">
and let javascript handling insertion be as follows
$('#insert').on('mousedown', function (e) { //that is to save selection on blur
e.preventDefault();
}).on('click', function () { // this inserts the sample html segment
document.execCommand('insertHTML', false,
'<div class="new-segment">Text inside Segment</div>');
});
Live example at http://jsfiddle.net/TE4Y6/ Follow the scenario below:
- place caret to the end of all content, press enter to create a new line then press "Insert Segment"
result: New div with gray background contains "Text Inside Segment" inserted
- place caret to the inside any of first three lines, press "Insert Segment"
result: it inserts only the content of segment not surrounding div
expected: New div with gray background contains "Text Inside Segment" inserted
- place caret to the end of any of first three lines, press "Insert Segment"
result: it inserts only the content of segment not surrounding div
expected: New div with gray background contains "Text Inside Segment" inserted
- place caret to the end of any of first three lines, press enter to create a new line then press "Insert Segment"
result: New div with gray background contains "Text Inside Segment" inserted
I have tried to automatically insert <br>
before inserted segment It fixes 3rd step though inserts redundant space.
Do you have any suggestions?
回答1:
You can try Range.insertNode. Proof of concept: http://jsfiddle.net/GYRLf/
var sel = window.getSelection();
if (sel.rangeCount) {
var range = sel.getRangeAt(0);
range.insertNode(yourDivElement);
}
A big disadvantage of this approach is that it breaks undo.
UPD. I think I found a workaround: http://jsfiddle.net/2LCtd/
document.execCommand('insertHTML', false,
'<div class="new-segment">' +
'<h6 class="killme">' + html + '</h6>' +
'</div>'
);
$('.killme').contents().unwrap();
When you add a header inside the div WebKit stops merging the div with surroundings. And because the text content doesn't change when you later remove the header, the browser can undo correctly.
回答2:
It seems to be an issue with Chromium. You can follow the issue at https://code.google.com/p/chromium/issues/detail?id=122062
来源:https://stackoverflow.com/questions/16033737/inserthtml-unwraps-div-while-inserting-when-selection-is-inside-a-node