Javascript 以编程方式选择内容可编辑的 HTML 元素中的文本?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6139107/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Programmatically select text in a contenteditable HTML element?
提问by callum
In JavaScript, it's possible to programmatically select text in an input
or textarea
element. You can focus an input with ipt.focus()
, and then select its contents with ipt.select()
. You can even select a specific range with ipt.setSelectionRange(from,to)
.
在 JavaScript 中,可以通过编程方式选择input
或textarea
元素中的文本。您可以使用 聚焦输入ipt.focus()
,然后使用 选择其内容ipt.select()
。您甚至可以使用 选择特定范围ipt.setSelectionRange(from,to)
。
My question is: is there any way to do this in a contenteditable
element too?
我的问题是:有没有办法在contenteditable
元素中做到这一点?
I found that I can do elem.focus()
, to put the caret in a contenteditable
element, but subsequently running elem.select()
doesn't work (and nor does setSelectionRange
). I can't find anything on the web about it, but maybe I'm searching for the wrong thing...
我发现我可以做elem.focus()
, 将插入符号放在一个contenteditable
元素中,但随后运行elem.select()
不起作用(并且也不起作用setSelectionRange
)。我在网上找不到任何关于它的信息,但也许我正在寻找错误的东西......
By the way, if it makes any difference, I only need it to work in Google Chrome, as this is for a Chrome extension.
顺便说一句,如果它有什么不同,我只需要它在谷歌浏览器中工作,因为这是一个 Chrome 扩展。
回答by Tim Down
If you want to select all the content of an element (contenteditable or not) in Chrome, here's how. This will also work in Firefox, Safari 3+, Opera 9+ (possibly earlier versions too) and IE 9. You can also create selections down to the character level. The APIs you need are DOM Range (current spec is DOM Level 2, see also MDN) and Selection, which is being specified as part of a new Range spec(MDN docs).
如果要在 Chrome 中选择元素的所有内容(可编辑或不可编辑),方法如下。这也适用于 Firefox、Safari 3+、Opera 9+(也可能是早期版本)和 IE 9。您还可以创建选择到字符级别。您需要的 API 是 DOM Range(当前规范是DOM Level 2,另见MDN)和 Selection,它被指定为新 Range 规范(MDN docs)的一部分。
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);
回答by yckart
In addition to Tim Downs answer, i made a solution that work even in oldIE:
除了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;?
Tested in IE 8+, Firefox 3+, Opera 9+, & Chrome 2+. Even I've set it up into a jQuery plugin:
在 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();
});
...and who's intereseted in, here's the same for all coffee-junkies:
......谁感兴趣,对于所有咖啡迷来说都是一样的:
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
Update:
更新:
If you want to select the entire page or contents of an editable region (flagged with contentEditable
), you can do it much simpler by switching to designMode
and using document.execCommand
:
如果您想选择整个页面或可编辑区域的内容(标记为contentEditable
),您可以通过切换到designMode
并使用 来更简单地完成document.execCommand
:
There's a good starting point at MDNand a littledocumentation.
var selectText = function () {
document.execCommand('selectAll', false, null);
};
(works well in IE6+, Opera 9+, Firefoy 3+, Chrome 2+) http://caniuse.com/#search=execCommand
(适用于 IE6+、Opera 9+、Firefoy 3+、Chrome 2+)http://caniuse.com/#search=execCommand
回答by Domysee
Since all of the existing answers deal with div
elements, I'll explain how to do it with span
s.
由于所有现有答案都涉及div
元素,因此我将解释如何使用span
s来实现。
There is a subtle difference when selecting a text range in a span
. In order to be able to pass the text start and end index, you have to use a Text
node, as described here:
在span
. 为了能够通过文本的开始和结束索引,你必须使用一个Text
节点,描述在这里:
If the startNode is a Node of type Text, Comment, or CDATASection, then startOffset is the number of characters from the start of startNode. For other Node types, startOffset is the number of child nodes between the start of the startNode.
如果 startNode 是 Text、Comment 或 CDATASection 类型的节点,则 startOffset 是距 startNode 开头的字符数。对于其他 Node 类型,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);
回答by Tom Boutell
Rangy allows you to do this cross-browser with the same code. Rangy is a cross-browser implementation of the DOM methods for selections. It is well tested and makes this a lot less painful. I refuse to touch contenteditable without it.
Rangy 允许您使用相同的代码执行此跨浏览器操作。Rangy 是用于选择的 DOM 方法的跨浏览器实现。它经过了很好的测试,可以减轻很多痛苦。如果没有它,我拒绝触摸 contenteditable。
You can find rangy here:
你可以在这里找到 rangy:
http://code.google.com/p/rangy/
http://code.google.com/p/rangy/
With rangy in your project, you can always write this, even if the browser is IE 8 or earlier and has a completely different native API for selections:
使用 rangy 在您的项目中,您始终可以编写它,即使浏览器是 IE 8 或更早版本并且具有完全不同的本机 API 用于选择:
var range = rangy.createRange();
range.selectNodeContents(contentEditableNode);
var sel = rangy.getSelection();
sel.removeAllRanges();
sel.addRange(range);
Where "contentEditableNode" is the DOM node that has the contenteditable attribute. You might fetch it like this:
其中“contentEditableNode”是具有 contenteditable 属性的 DOM 节点。你可能会像这样获取它:
var contentEditable = document.getElementById('my-editable-thing');
Or if jQuery is part of your project already and you find it convenient:
或者,如果 jQuery 已经是您项目的一部分,并且您觉得它很方便:
var contentEditable = $('.some-selector')[0];
回答by patorjk
[Updated to fix mistake]
[更新以修复错误]
Here is an example that is adapted from this answer that appears to work well in Chrome - Select range in contenteditable div
这是一个改编自此答案的示例,它似乎在 Chrome 中运行良好 - Select range in contenteditable 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 is:
HTML是:
<div id="myText" contenteditable>test</div>