首页 > 解决方案 > 如何将元素(在可编辑的div内)从光标位置分成两部分,然后在它之间插入一个自定义元素?

问题描述

我需要将光标位置的元素(在可编辑的 div 内)分成两部分,然后在它之间插入一个自定义元素。

修改前:(竖线“|”表示光标的位置。我用“|”表示光标所在的位置给你。但实际上,这个字符在文本中是不存在的。)

<div contenteditable="true">
  <span style="font-size='14px'">this is | a test</span>

  <p>other paragraphs .....</p>
</div>

进行更改后:

<div contenteditable="true">
  <span style="font-size:'14px'">this is </span><span style="font-size:'16px'">new text|</span><span style="font-size:'14px'">a test</span>

<p>other paragraphs .....</p>
</div>

需要注意的是,进行更改后,光标必须插入到新的自定义元素中最后一个字母之后。

我试了一下,但是:

  let sel = window.getSelection();
  let range = sel.getRangeAt(0);
  if (range.startContainer.parentNode.nodeName === 'SPAN') {
    let sel, range, cloneNode1, cloneNode2, cloneText, allContents, contentsBeforeCursor, contentsAfterCursor, newNode
    sel = window.getSelection();
    range = document.createRange();
    range.selectNode(sel.anchorNode);
    cloneNode1 = range.commonAncestorContainer.cloneNode();
    cloneNode2 = cloneNode1.cloneNode();
    cloneText = range.cloneContents();

    allContents = cloneText.textContent;
    contentsBeforeCursor = allContents.substring(0, sel.anchorOffset);
    contentsAfterCursor = allContents.substring(sel.anchorOffset, allContents.length);
    cloneNode1.textContent = contentsBeforeCursor
    cloneNode2.textContent = contentsAfterCursor
    newNode = document.createElement('SPAN');
    for (let i = 0; i < cloneNode1.attributes.length; i++) {
      let attr = cloneNode1.attributes.item(i);
      newNode.setAttribute(attr.nodeName, attr.nodeValue);
    }
    newNode.style.fontSize = '13px';

    range.selectNode(sel.anchorNode.parentNode);
    range.deleteContents();
    range.insertNode(cloneNode1)
    range.insertNode(newNode)
    range.insertNode(cloneNode2)
    newNode.focuse();

https://jsfiddle.net/nekooee/0h8zcfv4/43/

这是为了更改 SPAN 中间的字体。CKEditor 也是如此。

标签: javascripthtml

解决方案


就像我在评论中说的,这不是你想要的吗?

它甚至具有与您相同的 HTML 标记。

此外,您的 HTML 标记全错:

<span style="font-size='14px'">

应该:

 <span style="font-size:14px">

您的示例中的每个样式属性也是如此。

function pasteHtmlAtCaret(html, selectPastedContent) {
    var sel, range;
    if (window.getSelection) {
        // IE9 and non-IE
        sel = window.getSelection();
        if (sel.getRangeAt && sel.rangeCount) {
            range = sel.getRangeAt(0);
            range.deleteContents();

            // Range.createContextualFragment() would be useful here but is
            // only relatively recently standardized and is not supported in
            // some browsers (IE9, for one)
            var el = document.createElement("div");
            el.innerHTML = html;
            var frag = document.createDocumentFragment(), node, lastNode;
            while ( (node = el.firstChild) ) {
                lastNode = frag.appendChild(node);
            }
            var firstNode = frag.firstChild;
            range.insertNode(frag);

            // Preserve the selection
          /*
            if (lastNode) {
                range = range.cloneRange();
                range.setStartAfter(lastNode);
                if (selectPastedContent) {
                    range.setStartBefore(firstNode);
                } else {
                    range.collapse(true);
                }
                sel.removeAllRanges();
                sel.addRange(range);
            }*/
        }
    } else if ( (sel = document.selection) && sel.type != "Control") {
        // IE < 9
        var originalRange = sel.createRange();
        originalRange.collapse(true);
        sel.createRange().pasteHTML(html);
        if (selectPastedContent) {
            range = sel.createRange();
            range.setEndPoint("StartToStart", originalRange);
            range.select();
        }
    }
}

function test()
    {
        var input = '<span style="font-size:25px;color:red"> new text </span>';
        //document.getElementById("myDiv").focus();
        pasteHtmlAtCaret(input, false);
    }
<div contenteditable="true">
  <span style="font-size:14px">this is a test</span>

  <p>other paragraphs .....</p>
  
<button type="button" onclick="test()" unselectable="on">Test</button>
</div>


推荐阅读