以编程方式选择可内容的 HTML 元素中的文本?

在 JavaScript 中,可以通过编程方式选择 inputtextarea元素中的文本。您可以使用 ipt.focus()集中输入,然后使用 ipt.select()选择其内容。你甚至可以用 ipt.setSelectionRange(from,to)选择一个特定的范围。

我的问题是: 有没有办法在 contenteditable元素中也做到这一点?

我发现我可以执行 elem.focus(),将插入符号放在 contenteditable元素中,但随后运行 elem.select()不起作用(setSelectionRange也不起作用)。我在网上找不到任何关于它的东西,但也许我找错了..。

顺便说一下,如果有什么不同的话,我只需要它在谷歌 Chrome 上工作,就像这是一个 Chrome 扩展。

82056 次浏览

[更新修复错误]

下面是根据这个答案改编的一个例子,它在 Chrome-在可内容的 div 中选择范围中运行良好

var elm = document.getElementById("myText"),
fc = elm.firstChild,
ec = elm.lastChild,
range = document.createRange(),
sel;
elm.focus();
range.setStart(fc,1);
range.setEnd(ec,3);
sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);

HTML 为:

<div id="myText" contenteditable>test</div>

如果你想在 Chrome 中选择一个元素的所有内容(不管是否 contenteditable) ,以下是方法。这也适用于 Firefox,Safari 3 + ,Opera 9 + (可能还有更早的版本)和 IE 9。您还可以创建到字符级别的选择。您需要的 API 是 DOM Range (当前规范是 DOM 第二级,也请参阅 MDN)和 Selection,它们被指定为 新的射程规格(MDN 文件)的一部分。

function selectElementContents(el) {
var range = document.createRange();
range.selectNodeContents(el);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
}


var el = document.getElementById("foo");
selectElementContents(el);

除了 Tim Downs 回答之外,我还做了一个甚至可以在 oldIE 中工作的解决方案:

var selectText = function() {
var range, selection;
if (document.body.createTextRange) {
range = document.body.createTextRange();
range.moveToElementText(this);
range.select();
} else if (window.getSelection) {
selection = window.getSelection();
range = document.createRange();
range.selectNodeContents(this);
selection.removeAllRanges();
selection.addRange(range);
}
};


document.getElementById('foo').ondblclick = selectText;​

在 IE 8 + ,Firefox 3 + ,Opera 9 + ,Chrome 2 + 中测试过,甚至我都把它设置成了 jQuery 插件:

jQuery.fn.selectText = function() {
var range, selection;
return this.each(function() {
if (document.body.createTextRange) {
range = document.body.createTextRange();
range.moveToElementText(this);
range.select();
} else if (window.getSelection) {
selection = window.getSelection();
range = document.createRange();
range.selectNodeContents(this);
selection.removeAllRanges();
selection.addRange(range);
}
});
};


$('#foo').on('dblclick', function() {
$(this).selectText();
});

谁对咖啡有兴趣,这对所有咖啡瘾君子来说都一样:

jQuery.fn.selectText = ->
@each ->
if document.body.createTextRange
range = document.body.createTextRange()
range.moveToElementText @
range.select()
else if window.getSelection
selection = window.getSelection()
range = document.createRange()
range.selectNodeContents @
selection.removeAllRanges()
selection.addRange range
return

更新:

如果你想选择一个可编辑区域的整个页面或者内容(标记为 contentEditable) ,你可以通过切换到 designMode并使用 document.execCommand来实现更简单的操作:

有一个良好的 从 MDN 开始一些文件

var selectText = function () {
document.execCommand('selectAll', false, null);
};

(适用于 IE6 + ,Opera 9 + ,Firefoy3 + ,Chrome2 +) http://caniuse.com/#search=execCommand

Rangy 允许您使用相同的代码跨浏览器进行此操作。Rangy 是用于选择的 DOM 方法的跨浏览器实现。它经过了很好的测试,使这个过程少了很多痛苦。没有它,我拒绝接触可以满足的事物。

你可以在这里找到:

Http://code.google.com/p/rangy/

在你的项目中使用 range,你总是可以编写这个,即使浏览器是 IE8或者更早的版本,并且有一个完全不同的本地 API 用于选择:

var range = rangy.createRange();
range.selectNodeContents(contentEditableNode);
var sel = rangy.getSelection();
sel.removeAllRanges();
sel.addRange(range);

其中“ contentEditableNode”是具有 contenteditable 属性的 DOM 节点:

var contentEditable = document.getElementById('my-editable-thing');

或者,如果 jQuery 已经是你项目的一部分,你觉得它很方便:

var contentEditable = $('.some-selector')[0];

由于所有现有的答案都处理 div元素,我将解释如何处理 span

在选择 span中的文本范围时,有一个细微的差别。为了能够传递文本开始和结束索引,必须使用 Text节点,如 给你所述:

如果 startNode 是文本、注释或 CDATASsection 类型的节点, 那么 startOffset 是从 对于其他节点类型,startOffset 是子节点的数目 在 startNode 的开始之间的节点。

var e = document.getElementById("id of the span element you want to select text in");
var textNode = e.childNodes[0]; //text node is the first child node of a span


var r = document.createRange();
var startIndex = 0;
var endIndex = textNode.textContent.length;
r.setStart(textNode, startIndex);
r.setEnd(textNode, endIndex);


var s = window.getSelection();
s.removeAllRanges();
s.addRange(r);

现代的做事方式是这样的。详情请看 MDN

document.addEventListener('dblclick', (event) => {
window.getSelection().selectAllChildren(event.target)
})
<div contenteditable="true">Some text</div>