JavaScript替换所有浏览器的选择

15

有没有一个简单的JavaScript函数,可以用来用我的HTML替换当前文档的选择内容?

比如说,文档中有一个<p>AHAHAHA</p>,用户选择了第一个 "ha" 文本块。

现在我想用像这样的东西替换它:<span><font color="red">hoho</font></span>

当我在谷歌搜索 *javascript replace selection *时,我找不到一个简单明了的答案!

2个回答

26

是的,以下代码可以在所有主流浏览器中实现此功能,并提供选择插入内容的选项,如评论中所要求(尽管在 IE <= 8 中未实现此部分):

演示示例:http://jsfiddle.net/bXsWQ/147/

代码:

function replaceSelection(html, selectInserted) {
    var sel, range, fragment;

    if (typeof window.getSelection != "undefined") {
        // IE 9 and other non-IE browsers
        sel = window.getSelection();

        // Test that the Selection object contains at least one Range
        if (sel.getRangeAt && sel.rangeCount) {
            // Get the first Range (only Firefox supports more than one)
            range = window.getSelection().getRangeAt(0);
            range.deleteContents();

            // Create a DocumentFragment to insert and populate it with HTML
            // Need to test for the existence of range.createContextualFragment
            // because it's non-standard and IE 9 does not support it
            if (range.createContextualFragment) {
                fragment = range.createContextualFragment(html);
            } else {
                // In IE 9 we need to use innerHTML of a temporary element
                var div = document.createElement("div"), child;
                div.innerHTML = html;
                fragment = document.createDocumentFragment();
                while ( (child = div.firstChild) ) {
                    fragment.appendChild(child);
                }
            }
            var firstInsertedNode = fragment.firstChild;
            var lastInsertedNode = fragment.lastChild;
            range.insertNode(fragment);
            if (selectInserted) {
                if (firstInsertedNode) {
                    range.setStartBefore(firstInsertedNode);
                    range.setEndAfter(lastInsertedNode);
                }
                sel.removeAllRanges();
                sel.addRange(range);
            }
        }
    } else if (document.selection && document.selection.type != "Control") {
        // IE 8 and below
        range = document.selection.createRange();
        range.pasteHTML(html);
    }
}

例子:

replaceSelection('<span><font color="red">hoho</font></span>', true);

太棒了!您能否添加一些注释,例如哪些条件适用于IE,哪些适用于其他浏览器,谢谢! - Marco Demaio
对我来说,在雪豹上Safari 5.2.1也可以工作。谢谢,我真的在寻找IE9的东西! - xotix
如何使其保持选择状态?这样,在操作后'hoho'就会被选中。 - Timo Kähkönen
@TimDown:谢谢,它有效!如果选择长度为零,是否可以防止替换?现在,如果我只是单击某些内容,它会添加hoho。 - Timo Kähkönen
@Timo: 在旧版IE中测试!!document.selection.createRange().text,在其他浏览器中测试window.getSelection().isCollapsed - Tim Down

7
您可以使用Rangy库http://code.google.com/p/rangy/。接着,您可以执行:
var sel = rangy.getSelection();
var range = sel.getRangeAt(0);

range.deleteContents();
var node = range.createContextualFragment('<span><font color="red">hoho</font></span>');
range.insertNode(node);

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