web-dev-qa-db-ja.com

execCommand( "insertHTML")がクロムの属性を削除しないようにする方法はありますか?

コンテキストは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>

これを起こさないようにする方法はありますか?

17
sonicblis

この特定のケースでは、 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>
24
Tim Down

1つの解決策は、スパンを使用しない、つまり非スパン要素を使用することです。代わりに要素<em>を使用して、Chromeでの同様の問題を解決しました。イタリック体は私自身で問題ないためです。その結果、Chromeの<span>- fiddling "bug"は影響しません。ここでの議論を参照してください: CKeditバグに関する議論ですが、ここでも関連があります

1
Soferio