将焦点放在div contenteditable元素上


73

我有一个<div contenteditable=true>由所见即所得定义一些元素的地方。例如<p><h1>等等。我想直接将重点放在其中一个元素上。

例如在<p id="p_test">。但是似乎focus()函数对<div>元素,<p>元素不起作用...

在我的情况下,还有另一种方法来定义焦点吗?


5
您无法集中处理div或p,因为没有任何操作,您要集中精力做什么?
尼克·克拉弗

3
有人知道这样做的方法吗?
Michael Zaporozhets 2012年

60
@NickCraver该问题提到其内容可编辑,这意味着您可以键入和编辑它的内容。完美有效的问题imo
Blowsie 2012年

@Blowsie我相信原来的问题没有提到contenteditable功能。尼克·克雷弗(Nick Craver)对其进行了编辑,使之有意义。焦点。
Matej Svajger 2015年

var r=new Range(), sel=getSelection(); r.setStart(div.lastChild, div.lastChild.length||1);sel.removeAllRanges();sel.addRange(r)
caub

Answers:


67

旧帖子,但没有解决方案对我有用。我最终弄清楚了:

var div = document.getElementById('contenteditablediv');
setTimeout(function() {
    div.focus();
}, 0);

4
不知道为什么,这完全有效!!!在setTimeout中包装.focus()逻辑就可以了!谢谢!
sga4 '16

@ sga4很高兴它有所帮助:)
chris97ong

真好!一些事情需要先回到调度程序,然后才能正确进行处理。浏览器很奇怪。谢谢!
英国电信

1
我只有在将代码放入其他元素的onClick处理程序中时才遇到这种情况。我的猜测是存在竞争条件:单击按钮-> onClick处理程序会聚焦某些元素->按钮会获得焦点。放置setTimeout将推迟代码,使其保持持久的焦点。
Vilius Paulauskas '18年

1
我来自未来,这也是未来的工作
Bariq Dharmawan

35

在现代浏览器中,您可以使用:

var p = document.getElementById('contentEditableElementId'),
    s = window.getSelection(),
    r = document.createRange();
r.setStart(p, 0);
r.setEnd(p, 0);
s.removeAllRanges();
s.addRange(r);

但是,如果您的元素为空,那么我会遇到一些奇怪的问题,因此对于空元素,您可以这样做:

var p = document.getElementById('contentEditableElementId'),
    s = window.getSelection(),
    r = document.createRange();
p.innerHTML = '\u00a0';
r.selectNodeContents(p);
s.removeAllRanges();
s.addRange(r);
document.execCommand('delete', false, null);

删除nbsp后,光标停留在p元素内

PS只是普通空间对我不起作用


5
您的示例中的变量p是什么?
BT

2
@BT我假定它是根P元素,尽管他应该澄清它,但不要留下任何疑问。
Savas Vedova 2015年

1
在众多建议的解决方案中,这是唯一对我有用的解决方案,使我可以将重点放在jquery对话框中的contenteditable div上。
史蒂夫·罗伯茨

伟大的解决方案..谢谢:)
Sunil Kumar

1
我将零更改为1,r.setStart(p, 1)并将r.setEnd(p, 1)光标置于contenteditablediv的末尾。我不知道为什么行得通,但是行得通。谢谢!
戴夫·兰德

31

我注意到jQuery focus()不适用于宽度和高度为0的内容可编辑DIV。我将其替换为.get(0).focus()(本机javascript焦点方法),并且可以正常工作。


3
哪个浏览器?它似乎在Safari中不起作用,但是Firefox和Chrome可以很好地处理它。
Brian McCutchon

1
哪一部分?选择元素和focus(),例如document.getElementById(“#mydiv”)。focus()
Vlad 2015年

6

很多时候,如果您无法调用.focus()某个元素,这是因为tabIndex为-1,这意味着当您按下Tab键进行导航时,Tab键无法将焦点放在该元素上。

将tabIndex更改为> = 0将使您专注于元素。如果您需要动态地执行此操作,则只需在事件侦听器中向您的元素添加一个tabindex> = 0。


2
这应该是被批准的答案。“除非具有tabindex属性,否则您不能在元素上调用.focus()方法”
IvanHanák20年

5

您可以尝试使用此代码,它可以自动将焦点放在您的上一个插入位置。

let p = document.getElementById('contenteditablediv')
let s = window.getSelection()
let r = document.createRange()
r.setStart(p, p.childElementCount)
r.setEnd(p, p.childElementCount)
s.removeAllRanges()
s.addRange(r)

谢谢,上面的部分答案对我没有用,我需要添加p.childElementCount而不是1您写的那样。
NoxFly

4

如果有人使用管理元素的MediumEditor偶然发现contenteditable此问题,则以下对我有用

editor.selectElement(editorDOMNode);
  1. editor是的实例MediumEditor
  2. editorDOMNode是对实际contenteditableDOM节点的引用。
  3. 还可以集中注意编辑器中的特定子节点,如下所示:

    editor.selectElement(editorDOMNode.childNodes[0]);
    

2

在@Surmon答案上进一步构建。如果您希望在文本中的最后一个字母/数字之后而不是最后一个插入位置之后自动聚焦(如果子节点包含在块类型标记中而不是纯文本中,则最后一个插入位置会将光标移动到新行)然后应用此小修改:

r.setStart(p.lastChild, 1);
r.setEnd(p.lastChild, 1);

这是一个扩展功能,用于检查编辑器/元素是否具有任何子节点,并根据情况在末尾相应地设置光标:

let p = document.getElementById('contenteditablediv');
p.focus();  // alternatively use setTimeout(() => { p.focus(); }, 0);
// this is enough to focus an empty element (at least in Chrome)

if (p.hasChildNodes()) {  // if the element is not empty
  let s = window.getSelection();
  let r = document.createRange();
  let e = p.childElementCount > 0 ? p.lastChild : p;  
  r.setStart(e, 1); 
  r.setEnd(e, 1);    
  s.removeAllRanges();
  s.addRange(r);
} 

1

需要检查的另一件事:如果打开了浏览器的控制台窗口,请确保在加载页面时控制台没有焦点,否则页面上的元素将无法获得预期的焦点。

这似乎也暗示您不能document.querySelector('#your-elem').focus()在控制台中运行(2020年8月在Mac上尝试使用Chrome,Safari和Firefox)。


-8

将“ click”事件处理程序绑定到contenteditable div中的所有元素,并在单击时更改类/样式(即,将“ focused”类添加到元素);

您可以通过添加样式(例如彩色边框或内部方框阴影)来向用户标识哪个元素具有焦点。然后,当您想访问jQuery脚本中的焦点元素时,只需执行以下操作:

var focused = $('.focused');


8
他问的是实际上将用户的插入符号移动到元素上,而不仅仅是样式化选定的元素。
Brian McCutchon

1
这没有任何帮助。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.