window.getSelection()可以获取选中的文本,但我想要HTML格式的文本。

39

我正在扩展一个WYSIWYG HTML编辑器(用于Firefox),我想在所选内容周围添加标签。在Mozilla Midas规范中找不到可以实现此功能的函数。

有一种用HTML替换所选内容的命令。
如果我能读取选择内容,我就可以在这个字符串中添加我的标签。

window.getSelection() 差不多可以,但它给我返回的是nsISelection,它会转换为纯文本字符串。

PS:document.getSelection()甚至只返回纯文本字符串,而不是nsISelection


我建议你去看一些(很好的)所见即所得的HTML编辑器,例如TinyMCE,以便理解它 :) - Limbo Peng
嘿,Bob Fanger,你有找到解决方案吗?如果有的话,能告诉我一下吗? - Warrior
不,我们已经转换到TinyMCE,这解决了(商业)问题。附注:TinyMCE有一个很棒的API,可以扩展他们的HTML编辑器。您可以查看http://wiki.moxiecode.com/index.php/TinyMCE:API/tinymce.Editor/selection的实现。 - Bob Fanger
4个回答

49

请查看DOM Range规范。您可以在Firefox中使用以下方法从用户选择中获取Range

var range = window.getSelection().getRangeAt(0);

请注意,包括Firefox在内的某些浏览器允许多选,这可以通过选择区域的getRangeAt()方法进行访问。

Range是基于DOM节点和节点中的偏移量表达的。一旦你获得了Range,要做到完全符合你的意愿并不简单,因为范围的边界可能在DOM树的不同层级的不同节点中,所以仅仅用标签将范围的内容包围起来并不总是可行的。你可以尝试下面的操作,但它会创建一个新的块级元素来包含所选择的内容:

var range = window.getSelection().getRangeAt(0);
var selectionContents = range.extractContents();
var div = document.createElement("div");
div.style.color = "yellow";
div.appendChild(selectionContents);
range.insertNode(div);

另一种非常规的方法是使用documentexecCommand()方法来修改选择内容(例如,将其设置为特定的颜色),然后使用document.querySelectorAll或某个选择器库选择具有该颜色的元素,然后对它们应用样式。


最后一行有一个小错别字,你需要将 s/span/div/ 进行替换。 - Will Moffat
@tim 的问题是,如果我尝试从范围对象中提取起始位置和结束位置,这并不能返回精确的位置,而是通过 window.getSelection() 对象给出的位置。有没有办法获取范围,并且如果我同时使用两者,则 window.getSelection().getRangeAt(0) 的范围起始和结束将覆盖 window.getSelection() 对象的起始和结束值。更多信息,请访问我在此处发布的链接:http://stackoverflow.com/questions/42113694/how-to-get-selected-text-range-and-add-color-to-the-particular-selected-text/42114215#42114215 - Tamaghna Banerjee
这让我一天都很开心 :) 感谢 @TimDown - Lazyexpert

18

Tim Down的回答是正确的。不过,一个问题在于extractContents()会从DOM中移除选择内容。你可以使用

window.getSelection().getRangeAt(0).cloneContents(); 

只需获取所选内容的副本。然后,您可以用新标记包装它,然后用其替换选择内容。Tim Down关于范围跨多个HTML元素的担忧确实是一个有效的问题。我认为一旦获得范围,它会“修复”html,但当您将其放回时可能会引起问题。这里是关于范围对象的良好资源。


2
我在发布时还没有完全完成。现在我已经完成了我的回答。使用 extractContents 是有意的,因为您需要在重新插入内容之前从文档中删除它。 - Tim Down
是的,我想到了一种很好的方法可以使用extractContents来解决这个问题,我只是想指出它是“破坏性的”,还有另一种方法可以获取选定的HTML。不管怎样,回答得很好,加一。 - rosscj2533

9

3
旧答案,但返回了一个裸字符串,没有标记。我已经用alert()进行测试。 - cst1992

0
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>select content of particular element</title>
</head>

<body>
    <div id="div">This is the div tag</div>
    <p>this is the paragraph</p>
    <button id="Btn">Button</button>
    <script>
        let Btn = document.getElementById("Btn");
        Btn.addEventListener("click", function () {
            let selection = document.getSelection();
            if (selection.anchorNode.parentElement.id == "div") {
                let selectionContents = document.getSelection().toString();
                console.log("selected content of div id :", selectionContents)
            }
            else{
                console.log("pls select some text")
            }
        })
    </script>
</body>

</html>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接