我有一个<div contenteditable=true>
,我通过所见即所得编辑器定义了一些元素。例如<p>
、<h1>
等。我想直接将焦点放在这些元素之一上。
例如,在 <p id="p_test">
上。但似乎 focus()
函数不适用于 <div>
元素、<p>
等元素...
是否有其他方法在我的情况下定义焦点?
我有一个<div contenteditable=true>
,我通过所见即所得编辑器定义了一些元素。例如<p>
、<h1>
等。我想直接将焦点放在这些元素之一上。
例如,在 <p id="p_test">
上。但似乎 focus()
函数不适用于 <div>
元素、<p>
等元素...
是否有其他方法在我的情况下定义焦点?
旧的帖子,但是没有一个解决方案适用于我。不过最终我找到了解决方法:
var div = document.getElementById('contenteditablediv');
setTimeout(function() {
div.focus();
}, 0);
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 元素内
附言:普通空格对我无效
r.setStart(p, 1)
和 r.setEnd(p, 1)
中将零改为了一,以将光标放置在 contenteditable
div 的末尾。我不知道为什么这样做有效,但它确实有效。谢谢! - Dave Land我注意到jQuery的focus()方法不能用于宽度和高度为0的contenteditable DIV。然后我替换成使用原生的javascript focus()方法.get(0).focus(),这样就可以正常工作了。
很多时候,如果无法调用.focus()
方法来聚焦元素,那么这可能是因为该元素的tabIndex属性为-1,这意味着在按下Tab键进行导航时无法将焦点集中于此。
将tabIndex属性改为>=0即可让您聚焦到该元素上。如果需要动态执行此操作,则可以在事件侦听器中向元素添加tabIndex >=0。
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在@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);
}
如果有人使用管理 contenteditable
元素的 MediumEditor 遇到此问题,以下方法适用于我:
editor.selectElement(editorDOMNode);
editor
is an instance of MediumEditor
.editorDOMNode
is a reference to the actual contenteditable
DOM node.It is also possible to focus on a specific child node within the editor as follows:
editor.selectElement(editorDOMNode.childNodes[0]);
还有一件需要检查的事情:如果您已经打开了浏览器的控制台窗口,请确保在加载页面时不要将焦点放在控制台上,否则页面上的元素将无法按预期获取焦点。
这也意味着您不能在控制台中运行document.querySelector('#your-elem').focus()
(在2020年8月的Mac上尝试过Chrome、Safari和Firefox)。
document.querySelector('.pell-content').focus();
完美地为Pell RTE工作。太疯狂了,谢谢! - Vael Victusclick
事件处理程序将需要点击以聚焦元素(而不触发插入符号),然后再次点击以触发插入符号。使用setTimeout
和.get(0)
等方法将无法按预期工作。mousedown
事件处理程序只需使用focus()
调用即可按预期工作。无需其他解决方法。在Windows/Chrome(鼠标)和Android/Chrome(触摸)上进行了测试。const ns = {
focus: e => {
let el = $(e.currentTarget);
el.focus();
}
}
$(document).ready(() => {
$('body').on('mousedown', '[contenteditable]', ns.focus); //use mousedown instead of click
let p = $('#auto_focus').get(0),
s = window.getSelection(),
r = document.createRange(),
e = p.childElementCount > 0 ? p.lastChild : p;
setTimeout(() => p.focus(), 0);
//r.setStart(p, 0);
//r.setEnd(p, 0);
//r.setStart(e, 1);
//r.setEnd(e, 1);
r.setStart(p, p.childElementCount)
r.setEnd(p, p.childElementCount)
s.removeAllRanges();
s.addRange(r);
});
[contenteditable] {
border-bottom: 1px solid lightgray;
/* prevents shifting on select */
line-height: 1.2em;
}
[contenteditable]:focus {
border-bottom: 1px solid black;
/* prevents slight visual shifting on select */
outline: 1px solid transparent;
}
[contenteditable=true]:empty:not(:focus):before {
content: attr(placeholder) '...';
font-style: italic;
font-size: .9em;
text-transform: lowercase;
opacity: .3;
font-weight: normal;
}
[contenteditable]>* {
min-height: 1em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div contenteditable=true placeholder="edit me"></div>
<div contenteditable=true placeholder="edit me, too"></div>
<div contenteditable=true>
<p>paragraph 1</p>
<p id="auto_focus">paragraph 2</p>
</div>
var focused = $('.focused');
var r=new Range(), sel=getSelection(); r.setStart(div.lastChild, div.lastChild.length||1);sel.removeAllRanges();sel.addRange(r)
- caub