如何使用HTML标签包装window.getSelection().getRangeAt(0)的文本选择?

7
我该如何从window.getSelection().getRangeAt(0)中选择文本,并用HTML标签(如“span”或“mark”)包围它呢? 我更喜欢使用纯javascript或jQuery的解决方案。
我能够通过警报输出所选文本,但尚未找到如何将其与其他标记一起包装的方法。我已经看到了许多运行execCommand以选择的示例,但这不是我想要的。
请参见我的工作示例:jsfiddle 有什么想法?谢谢

我的问题与这个类似,但我没有使用YUI库... http://stackoverflow.com/questions/4077806/yui-editor-rte-how-to-wrap-selection-with-a-span-and-not-lose-formatting - Dan Sorensen
这个问题也有关联,可能可以解决我的问题:http://stackoverflow.com/questions/4891338/how-can-i-use-jquery-to-apply-css-to-savedrange-text-selection - Dan Sorensen
3个回答

17
如果所选文本都包含在单个文本节点中,则可以使用 Range 的 surroundContents() 方法。但是,这在一般情况下不起作用。要做的事情是将范围内的每个文本节点括在一个 <span> 中。我的 Rangy 库有 一个模块可以完成此操作,并且可跨浏览器使用(IE <= 8 不支持 DOM Range)。
使用 Rangy 的示例代码:
<style type="text/css">
    span.highlighted {
        background-color: yellow;
    }
</style>
<script type="text/javascript">
    var highlightApplier;

    window.onload = function() {
        rangy.init();
        highlightApplier = rangy.createCssClassApplier("highlighted ", true);
    };

    function applyHighlight() {
        highlightApplier.applyToSelection();
    }
</script>

1
关于 surroundContents() 的有趣点,我需要尝试一些不同的情况并查看其效果。我会研究你的库的。谢谢! - Dan Sorensen
比起我自己的(hack-ish)尝试,这是一个更好的解决方案... +1 :) - David Thomas

2

根据我发表问题时发现的类似问题,我自己回答这个问题...

这个问答主题中的人们走了一条有趣的路线,只是使用了与我寻找的不同格式。通过修改他们的代码,我能够做到以下几点:

<h3><a href="#" id="btnRange">Display Range</a> |
<a href="#" id="btnMark">Mark Range</a></h3>

<div contenteditable="true" id="editor">
    This is sample text. You should be able to type in this box or select anywhere in this div and then click the link at the top to get the selected range.
</div>

<script type="text/javascript">
    var btnDisplay = $("#btnRange"),
        btnMark = $("#btnMark");

    btnDisplay.click(function() {
        alert(window.getSelection().getRangeAt(0));
        return false;
    });

    btnMark.click(function() {
        var range = window.getSelection().getRangeAt(0);
        var newNode = document.createElement("mark");
        range.surroundContents(newNode);
        return false;
    });

我可以进一步抽象btnMark.click()函数中的代码,接受一个标签名称,然后创建一行按钮来使用mark、pre、blockquote标记代码。

可以在这里找到一个可行的解决方案:http://jsfiddle.net/3tvSL/


3
尽管在我的超级简单的纯文本示例中这很有效,正如Tim Down在另一个答案中指出的那样,“如果所选文本全部包含在单个文本节点中,则可以使用范围(Range)的surroundContents()方法。然而,在一般情况下,这种方法不起作用。” - Dan Sorensen

0

首先获取范围:

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

点击按钮时:

   function formatCode(e){
        var textAreaVal = document.getElementById('divWithContentEditable').innerText;
        if(textAreaVal.length>0){
            var newtxt = '<pre><code>'+savedRange+'</code></pre>'
            replaceIt($('#topicDetails')[0], newtxt);
        }
    }

在文本周围添加/替换元素:

replaceIt(txtarea, newtxt) {
    $(txtarea).text(newtxt));  
}

当然,您可以使用 Rangy,但我认为为了简单的需求而添加额外的500kb并不推荐。

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