コンテキストはChrome 37.0.2062.120 mです。
ExecCommandを使用して、編集可能なdivにhtmlを挿入しています。私のexecCommand呼び出しは次のようになります。
function insertHTML(){
document.execCommand('insertHTML', false, '<span id="myId">hi</span>');
}
編集可能なdivが次のようになっている場合:
<div contenteditable="true">
some [insertion point] content
</div>
そしてexecCommandを使用してhtmlをcontenteditable divに挿入します。HTMLのすべての属性が期待どおりに挿入され、次のようになります。
<div contenteditable="true">
some <span id="myId">hi</span> content
</div>
ただし、この構造にまったく同じhtmlを挿入すると、
<div contenteditable="true">
some content
<div>more [insertion point] content</div>
</div>
挿入されるスパンから属性が削除され、最終的には次のようになります。
<div contenteditable="true">
some content
<div>more <span style="font-size: 10pt;">hi</span> content</div>
</div>
これを起こさないようにする方法はありますか?
この特定のケースでは、 Range.insertNode
代わりに、何を挿入するかを完全に制御できます。
function insertHTML() {
var sel, range;
if (window.getSelection && (sel = window.getSelection()).rangeCount) {
range = sel.getRangeAt(0);
range.collapse(true);
var span = document.createElement("span");
span.id = "myId";
span.appendChild( document.createTextNode("hi") );
range.insertNode(span);
// Move the caret immediately after the inserted span
range.setStartAfter(span);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
}
}
function isOrIsAncestorOf(ancestor, descendant) {
var n = descendant;
while (n) {
if (n === ancestor) {
return true;
} else {
n = n.parentNode;
}
}
return false;
}
function nodeContainsSelection(node) {
var sel, range;
if (window.getSelection && (sel = window.getSelection()).rangeCount) {
range = sel.getRangeAt(0);
return isOrIsAncestorOf(node, range.commonAncestorContainer);
}
return false;
}
function insertHTML() {
var sel, range;
if (window.getSelection && (sel = window.getSelection()).rangeCount) {
range = sel.getRangeAt(0);
range.collapse(true);
var span = document.createElement("span");
span.id = "myId";
span.appendChild( document.createTextNode("hi") );
range.insertNode(span);
// Move the caret immediately after the inserted span
range.setStartAfter(span);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
}
}
window.onload = function() {
document.getElementById("inserter").onmousedown = function() {
var editor = document.getElementById("editor");
if (nodeContainsSelection(editor)) {
insertHTML();
return false;
}
};
};
span {
font-weight: bold;
color: green;
}
<input type="button" id="inserter" value="Insert span">
<div contenteditable="true" id="editor">
some content
</div>
1つの解決策は、スパンを使用しない、つまり非スパン要素を使用することです。代わりに要素<em>
を使用して、Chromeでの同様の問題を解決しました。イタリック体は私自身で問題ないためです。その結果、Chromeの<span>
- fiddling "bug"は影響しません。ここでの議論を参照してください: CKeditバグに関する議論ですが、ここでも関連があります