我有一个
<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元素内
附注只是普通的空间不适合我
我注意到 jQuery focus() 不适用于宽度和高度为 0 的 contenteditable DIV。我将其替换为 .get(0).focus() - 原生 javascript focus 方法 - 并且它有效。
很多时候如果你无法在某个元素上调用
.focus()
,那是因为 tabIndex 为 -1,这意味着当你按 Tab 导航时 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)
在@Surmon answer的基础上进一步构建。如果您希望在文本中的最后一个字母/数字而不是最后一个插入位置之后自动聚焦(如果子节点包含在块类型标签而不是纯文本中,则最后一个插入位置会将光标移动到新行)然后应用这个小修改:
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
是 MediumEditor
的实例。editorDOMNode
是对实际 contenteditable
DOM 节点的引用。还可以关注编辑器中的特定子节点,如下所示:
editor.selectElement(editorDOMNode.childNodes[0]);
还有一件事需要检查:如果您打开了浏览器的控制台窗口,请确保加载页面时控制台没有焦点,否则页面上的元素将不会按预期获得焦点。
这似乎也意味着您无法在控制台中运行
document.querySelector('#your-elem').focus()
(于 2020 年 8 月在 Mac 上使用 Chrome、Safari 和 Firefox 进行了尝试)。
请注意,
click
事件处理程序将需要单击一次来聚焦元素(不触发插入符号),然后再单击一次来触发插入符号。 setTimeout
和 .get(0)
等方法将无法按预期工作。
使用
mousedown
事件处理程序只需使用 focus()
调用即可按预期工作。无需其他解决方法。在 Windows/Chrome(鼠标)和 Android/Chrome(触摸)上进行了测试。
jQuery 示例:
const ns = {
focus: e => {
let el = $(e.currentTarget);
el.focus();
}
}
$(document).ready(() => {
$('body').on('mousedown', '[contenteditable]', ns.focus); //use mousedown instead of click
});
[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: .7;
font-weight: normal;
color: lightgray;
}
<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>
将“click”事件处理程序绑定到 contenteditable div 中的所有元素,并更改单击时的类/样式(即向元素添加“focused”类);
您可以通过添加彩色边框或内部框阴影等样式来向用户标识哪个元素具有焦点。然后,当您想要访问 jQuery 脚本中的焦点元素时,只需执行以下操作:
var focused = $('.focused');