可编辑文本的选定文本保存和恢复

9

我看到了这篇文章,展示了两个函数如何从可编辑的div中保存和恢复所选文本。我已经将以下div设置为contenteditable,并使用另一篇文章中的2个函数。我如何使用这些函数来保存和恢复所选文本。

<div style="width:300px;padding:10px;" contenteditable="true">test test test test</div>

<script>
function saveSelection() {
    if (window.getSelection) {
        sel = window.getSelection();
        if (sel.getRangeAt && sel.rangeCount) {
            return sel.getRangeAt(0);
        }
    } else if (document.selection && document.selection.createRange) {
        return document.selection.createRange();
    }
    return null;
}

function restoreSelection(range) {
    if (range) {
        if (window.getSelection) {
            sel = window.getSelection();
            sel.removeAllRanges();
            sel.addRange(range);
        } else if (document.selection && range.select) {
            range.select();
        }
    }
}
</script>

你需要使用 Range 对象的方法(请参阅 Mozilla 文档:https://developer.mozilla.org/en/DOM/range)。基本上,一个范围由节点和该节点内的偏移量组成。保存 HTML 以及范围的一种方法是使用“插入符号”(请参考 Closure Library 的想法:http://closure-library.googlecode.com/svn/docs/class_goog_dom_SavedCaretRange.html)。 - yonran
2个回答

21

一个典型的用法是显示某种小部件或对话框,以接受用户输入(从而潜在地破坏原始选择),并在该小部件被隐藏后恢复选择。实际使用这些函数非常简单;最大的危险是在销毁选择之后尝试保存选择。

以下是一个简单的示例。它显示一个文本输入,并使用该输入中的文本覆盖可编辑的 <div> 中的选择。请注意,此代码在document.selection分支中支持 Internet Explorer <= 8,现在可以删除:

function saveSelection() {
    if (window.getSelection) {
        sel = window.getSelection();
        if (sel.getRangeAt && sel.rangeCount) {
            return sel.getRangeAt(0);
        }
    } else if (document.selection && document.selection.createRange) {
        return document.selection.createRange();
    }
    return null;
}

function restoreSelection(range) {
    if (range) {
        if (window.getSelection) {
            sel = window.getSelection();
            sel.removeAllRanges();
            sel.addRange(range);
        } else if (document.selection && range.select) {
            range.select();
        }
    }
}

function insertTextAtCursor(text) {
    var sel, range, html;
    if (window.getSelection) {
        sel = window.getSelection();
        if (sel.getRangeAt && sel.rangeCount) {
            range = sel.getRangeAt(0);
            range.deleteContents();
            var textNode = document.createTextNode(text) 
            range.insertNode(textNode);
            sel.removeAllRanges();
            range = range.cloneRange();
            range.selectNode(textNode);
            range.collapse(false);
            sel.addRange(range);
        }
    } else if (document.selection && document.selection.createRange) {
        range = document.selection.createRange();
        range.pasteHTML(text);
        range.select();
    }
}

var selRange;

function displayTextInserter() {
    selRange = saveSelection();
    document.getElementById("textInserter").style.display = "block";
    document.getElementById("textToInsert").focus();
}
 

function insertText() {
    var text = document.getElementById("textToInsert").value;
    document.getElementById("textInserter").style.display = "none";
    restoreSelection(selRange);
    document.getElementById("test").focus();
    insertTextAtCursor(text);
}
#textInserter {
    display: none;
}
<div id="test" contenteditable="true">Some editable text</div>
<input type="button" unselectable="on" onclick="displayTextInserter();" value="Insert text">
<div id="textInserter">
    <input type="text" id="textToInsert">
    <input type="button" onclick="insertText()" value="Insert">
</div>


@TimDown - Tim,你怎样使用 saveSelection()restoreSelection(range) 以便你可以针对 contenteditable div 进行定位?也就是说,像这样使用 saveSelection('mycontentId')restoreSelection(range, 'mycontentId')。我正在尝试在两个不同的 div 上使用它,而且我需要分别进行指定。是否有办法在这两个函数中加入 getElementById,以便我可以进行定位? - Andy
@Andy:选择是绑定到文档而不是单个元素,但是没有阻止您保存多个不同的选择。您能否给出一个具体的例子,说明您想要实现什么? - Tim Down
非常好!但是我该如何使用文本区域而不是具有ID“test”的div? - DiChrist
请注意,在TypeScript中,document.selection会导致编译错误,因为在示例中特别针对IE使用了document.selection - iAmV
天才,你救了我的一天! - undead10
显示剩余3条评论

0

只有一个建议:

使用原生浏览器选择+可编辑内容+处理所有不同的浏览器方面+从头开始保存和恢复选择等工作很难。

我建议使用rangyhttps://code.google.com/p/rangy/wiki/SelectionSaveRestoreModule
这是专门为您处理选择困难而设计的。

查看文档,它很容易使用;) 希望它能帮到你。


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