javascript 在 contentEditable 元素中插入 HTML 元素

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4823691/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 14:59:23  来源:igfitidea点击:

Insert an HTML element in a contentEditable element

javascriptjquerycontenteditable

提问by Elie

I have a contentEditable div where I want to insert HTML tags (a simple span element).

我有一个 contentEditable div,我想在其中插入 HTML 标签(一个简单的 span 元素)。

Is there a cross browser solution that allows me to insert those tags over my div selection or cursor position. If something else is selected on the page (not in the div), I want to append the tag to the end of the div.

是否有跨浏览器解决方案允许我在 div 选择或光标位置上插入这些标签。如果在页面上选择了其他内容(不在 div 中),我想将标签附加到 div 的末尾。

Thanks

谢谢

回答by Mauricio

Here is a kickstart

这是一个启动

// get the selection range (or cursor     position)
var range = window.getSelection().getRangeAt(0); 
// create a span
var newElement = document.createElement('span');
newElement.id = 'myId';
newElement.innerHTML = 'Hello World!';

// if the range is in #myDiv ;)
if(range.startContainer.parentNode.id==='myDiv') {
   // delete whatever is on the range
   range.deleteContents();
   // place your span
   range.insertNode(newElement);
}

I don't have IE but works fine on firefox, chrome and safari. Maybe you want to play with range.startContainer to proceed only if the selection is made on the contentEditable div.

我没有 IE,但在 Firefox、chrome 和 safari 上运行良好。也许您想使用 range.startContainer 来继续,只有在 contentEditable div 上进行了选择。

EDIT:According to quirksmode range introyou have to change the window.getSelection() part to be IE compatible.

编辑:根据quirksmode range intro,您必须将 window.getSelection() 部分更改为与 IE 兼容。

var userSelection;
if (window.getSelection) {
    userSelection = window.getSelection();
}
else if (document.selection) { // should come last; Opera!
    userSelection = document.selection.createRange();
}

回答by Tim Down

The following will do this in all major browsers (including IE 6). It will also handle cases where the end of the selection is outside your <div>and cases where the selection is contained within a child (or more deeply nested) element inside the <div>.

以下将在所有主要浏览器(包括 IE 6)中执行此操作。它还将处理选择的结尾在您之外的<div>情况以及选择包含在<div>.

2019 addendum: The second branch of insertNodeOverSelectionis for IE <= 8 only and could be removed now.

2019 年附录:的第二个分支insertNodeOverSelection仅适用于 IE <= 8,现在可以删除。

function isOrContainsNode(ancestor, descendant) {
    var node = descendant;
    while (node) {
        if (node === ancestor) return true;
        node = node.parentNode;
    }
    return false;
}

function insertNodeOverSelection(node, containerNode) {
    var sel, range, html;
    if (window.getSelection) {
        sel = window.getSelection();
        if (sel.getRangeAt && sel.rangeCount) {
            range = sel.getRangeAt(0);
            if (isOrContainsNode(containerNode, range.commonAncestorContainer)) {
                range.deleteContents();
                range.insertNode(node);
            } else {
                containerNode.appendChild(node);
            }
        }
    } else if (document.selection && document.selection.createRange) {
        range = document.selection.createRange();
        if (isOrContainsNode(containerNode, range.parentElement())) {
            html = (node.nodeType == 3) ? node.data : node.outerHTML;
            range.pasteHTML(html);
        } else {
            containerNode.appendChild(node);
        }
    }
}
<input type="button" onmousedown="insertNodeOverSelection(document.createTextNode('[NODE]'), document.getElementById('test'));" value="insert">

<div contenteditable="true">
    <div id="test" style="background-color: lightgoldenrodyellow">
        This is the editable element where the insertion will happen. Select something or place the cursor in here, then hit the button above
    </div>
    <div>
        No insertion will happen here
    </div>
</div>