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

cal*_*lum 104 javascript selection contenteditable

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

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

我发现我可以做elem.focus(),把插入符号放在一个contenteditable元素中,但随后运行elem.select()不起作用(也没有setSelectionRange).我在网上找不到任何关于它的东西,但也许我正在寻找错误的东西......

顺便说一下,如果它有所不同,我只需要它在谷歌浏览器中工作,因为这是Chrome扩展.

Tim*_*own 158

如果您想在Chrome中选择元素的所有内容(是否可信),请按照以下步骤操作.这也适用于Firefox,Safari 3 +,Opera 9+(也可能是早期版本)和IE 9.您还可以创建字符级别的选择.您需要的API是DOM范围(当前规范是DOM级别2,另请参见MDN)和选择,它被指定为新范围规范(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);
Run Code Online (Sandbox Code Playgroud)

  • 为了额外的兼容性,如果从`onfocus`调用,你应该在`setTimeout()`或`requestAnimationFrame()`中调用`selectElementContents()`.见http://jsfiddle.net/rudiedirkx/MgASG/1/show/ (12认同)
  • @Rudie*兼容性*哪个应用程序? (4认同)

yck*_*art 34

除了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;?
Run Code Online (Sandbox Code Playgroud)

在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();
});
Run Code Online (Sandbox Code Playgroud)

...和谁在互动,这里对所有咖啡迷来说都是一样的:

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
Run Code Online (Sandbox Code Playgroud)

更新:

如果你想选择整个页面或可编辑区域(有标记的内容contentEditable),你可以做到这一点更简单的通过切换到designMode使用document.execCommand:

MDNlittledocumentation有一个很好的起点.

var selectText = function () {
  document.execCommand('selectAll', false, null);
};
Run Code Online (Sandbox Code Playgroud)

(适用于IE6 +,Opera 9 +,Firefoy 3 +,Chrome 2+)http://caniuse.com/#search=execCommand


Dom*_*see 9

由于所有现有的答案都涉及到div元素,我将解释如何用spans 来完成.

在a中选择文本范围时有一个细微的差别span.为了能够通过文本的开始和结束索引,你必须使用一个Text节点,描述在这里:

如果startNode是Text,Comment或CDATASection类型的节点,则startOffset是startNode开头的字符数.对于其他节点类型,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);
Run Code Online (Sandbox Code Playgroud)

  • 在 `<div>` 和 `<span>` 元素中进行选择没有区别。至少,不像你描述的那样。 (2认同)
  • div 和 span 之间存在差异,在某些情况下 div 的解决方案在 span 中不起作用。例如,如果您使用 div 解决方案以编程方式选择文本,然后粘贴新内容,它将不会替换整个文本,而只会替换一部分,并且 chrome 和 firefox 之间存在差异 (2认同)

Tom*_*ell 6

Rangy允许您使用相同的代码执行此跨浏览器.Rangy是用于选择的DOM方法的跨浏览器实现.它经过了充分的测试,使得它不那么痛苦.没有它,我拒绝接触.

你可以在这里找到rangy:

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

在项目中使用rangy,即使浏览器是IE 8或更早版本并且具有完全不同的本机API用于选择,您也可以随时编写此内容:

var range = rangy.createRange();
range.selectNodeContents(contentEditableNode);
var sel = rangy.getSelection();
sel.removeAllRanges();
sel.addRange(range);
Run Code Online (Sandbox Code Playgroud)

其中"contentEditableNode"是具有contenteditable属性的DOM节点.您可以像这样获取它:

var contentEditable = document.getElementById('my-editable-thing');
Run Code Online (Sandbox Code Playgroud)

或者,如果jQuery已经是您项目的一部分,您会发现它很方便:

var contentEditable = $('.some-selector')[0];
Run Code Online (Sandbox Code Playgroud)


小智 6

现代的做事方式是这样的。有关MDN 的更多详细信息

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