在用户选择上插入自定义标签

Tin*_*wal 5 javascript

我想在所选文本周围插入自己的自定义标记和脚本.像这样的东西

var range = window.getSelection().getRangeAt(0);
var sel = window.getSelection();
range.setStart( sel.anchorNode, sel.anchorOffset );
range.setEnd(sel.focusNode,sel.focusOffset);

highlightSpan = document.createElement("abbr");
highlightSpan.setAttribute("style","background-color: yellow;");
highlightSpan.setAttribute("onmouseout","javascript:HideContentFade(\"deleteHighlight\");");
highlightSpan.setAttribute("onmouseover","javascript:ShowHighlighter(\"deleteHighlight\",\""+id_val+"\");");  
highlightSpan.appendChild(range.extractContents()); 
range.insertNode(highlightSpan);
Run Code Online (Sandbox Code Playgroud)

这适用于正常情况,但如果我在不同段落中选择一些文本,extractContents API将验证返回的HTML并添加其他标记以使其成为有效的HTML.我想要选择的确切HTML,而不需要javascript做的额外验证.

有什么办法可以做到吗?我已经按照如何突出显示DOM Range对象的文本中提到的方式尝试了它但事情是我想要用户特定的亮点,所以如果A添加了一些亮点B应该无法看到它.为此我准备好了我的后端代码.

Wat*_*oll 0

如果您使用标签包裹属于不同段落的选定文本,则会创建无效的 HTML 代码。

这是您将生成的无效 HTML 代码的示例。

<p>notselected <span>selected</p><p>selected</span> notselected</p>
Run Code Online (Sandbox Code Playgroud)

为了完成您的任务,您需要用标签包装所选内容的每个段落中的每个文本,从而产生如下代码。

<p>notselected <span>selected</span></p><p><span>selected</span> notselected</p>
Run Code Online (Sandbox Code Playgroud)

要实现此目的,您必须迭代所有选定的节点并将选定的文本换行,如下所示:

function wrapSelection() {
    var range, start, end, nodes, children;

    range = window.getSelection().getRangeAt(0);
    start = range.startContainer;
    end = range.endContainer;

    children = function (parent) {
        var child, nodes;

        nodes = [];
        child = parent.firstChild;

        while (child) {
            nodes.push(child);
            nodes = nodes.concat(children(child));
            child = child.nextSibling;
        }

        return nodes;
    }

    nodes = children(range.commonAncestorContainer);
    nodes = nodes.filter(function (node) {
        return node.nodeType === Node.TEXT_NODE;
    });
    nodes = nodes.slice(nodes.indexOf(start) + 1, nodes.indexOf(end));
    nodes.forEach(function (node) {
        wrap = window.document.createElement("span");
        node.parentNode.insertBefore(wrap, node);
        wrap.appendChild(node);
    });

    start = new Range();
    start.setStart(range.startContainer, range.startOffset);
    start.setEnd(range.startContainer, range.startContainer.length);
    start.surroundContents(window.document.createElement("span"));

    end = new Range();
    end.setStart(range.endContainer, 0);
    end.setEnd(range.endContainer, range.endOffset);
    end.surroundContents(window.document.createElement("span"));
}
Run Code Online (Sandbox Code Playgroud)