【问题标题】:Get innerHTML of #document-fragment instead of textContent获取 #document-fragment 的 innerHTML 而不是 textContent
【发布时间】:2016-04-15 17:24:31
【问题描述】:

我有一个内容可编辑的 p 标签。当 p 标签的内容被提取并插入到另一个标签中时,原始的所有标记都丢失了。有什么方法可以保存标记吗?

请注意,如果 插入符号在段落中的第 i 个 位置,则 字符将从该位置开始提取到结尾

function select() {
    var el = document.getElementById('p');
    el.focus();

    var sel = window.getSelection();
    var selRange = sel.getRangeAt(0);

    var range = selRange.cloneRange();
    range.selectNodeContents(el);
    range.setStart(selRange.endContainer, selRange.endOffset);

    document.getElementById('other').innerHTML = (range.extractContents().textContent);
    // return range.extractContents().textContent;
}
p {
	background-color: #eee;
}

.red {
  color: red;
}
<p id="p" contenteditable="true">This is <i>a</i> <span class="red">paragraph</span> <b>with</b> lots of markup.</p>
<p id="other"></p>
<button onclick="select()">SELECT</button>

【问题讨论】:

    标签: javascript html css contenteditable


    【解决方案1】:

    range.extractContents() 返回一个DocumentFragment

    DocumentFragment 没有 innerHTML 属性。 innerHTML 来自Element 接口,而textContentNode 接口的一部分。 DocumentFragment 继承自 Node,但不是 Element

    这意味着您可以只附加整个片段,因为它是 Node

    function select() {
      var el = document.getElementById('p');
      el.focus();
    
      var sel = window.getSelection();
      var selRange = sel.getRangeAt(0);
    
      var range = selRange.cloneRange();
      range.selectNodeContents(el);
      range.setStart(selRange.endContainer, selRange.endOffset);
    
      //document.getElementById('other').innerHTML = (range.extractContents().textContent);
      var frag = range.extractContents();
      var i;
      var node;
      var other = document.getElementById('other');
      other.innerHTML = '';
      other.appendChild(frag);
    }
    p {
    	background-color: #eee;
    }
    
    .red {
      color: red;
    }
    <p id="p" contenteditable="true">This is <i>a</i> <span class="red">paragraph</span> <b>with</b> lots of markup.</p>
    <p id="other"></p>
    <button onclick="select()">SELECT</button>

    【讨论】:

    • 请再次参考问题。发生了微小的变化。
    • @dorado,找到了更简单的方法,只需附加整个片段。
    【解决方案2】:

    供进一步参考,如果有人真的需要提取片段的innerHTML。

    片段有子节点并且那些有outerHTML属性,所以你必须简单地从所有子节点中获取outerHTML

    const fragment = range.extractContents();
    const htmlContent = [].map.call(fragment.childNodes, x => x.outerHTML).join('')
    

    需要map.call 部分,因为虽然片段具有childNodes 属性,但childNodes 没有map 方法。

    【讨论】:

    • 如果有文字内容const htmlContent = [].map.call(fragment.childNodes, x =&gt; x.nodeType === x.TEXT_NODE ? x.textContent : x.outerHTML).join('')
    • 第二行的可读性小改进(imo):Array.from(fragment.childNodes).map(x =&gt; x.outerHTML).join('');
    【解决方案3】:

    你的意思不是这样吗?

    document.getElementById('other').innerHTML = el.innerHTML;
    

    那么你的 javascript 就很简单了:

    function select() {
        var el = document.getElementById('p');
        el.focus();
    
        document.getElementById('other').innerHTML = el.innerHTML;
    }
    

    编辑:

    嘿,你对我的回答投了反对票,但你能解释一下你想要达到的目标吗?我在上面写的代码你可以在这个 jsfiddle 中看到:https://jsfiddle.net/936zuzky/1/

    您想保存原始标记 - 它已保存,那么您想要实现什么?

    【讨论】:

    • 我没有投反对票。至于上下文,我想要的是从插入符号的位置开始复制 HTML 到末尾并放在另一段中。您可以在接受的答案中看到这一点。
    猜你喜欢
    • 2013-04-07
    • 1970-01-01
    • 2014-12-30
    • 2020-11-10
    • 1970-01-01
    • 1970-01-01
    • 2018-07-09
    • 2021-12-07
    • 2016-01-28
    相关资源
    最近更新 更多