You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

contenteditable div调用focus()后光标为何定位至开头?

问题描述

开发基于PHP的书籍写作网站,点击「Chapter Title」按钮触发addChapter()函数,AJAX请求完成后向带contenteditable属性的#content div追加章节标题内容,预期光标定位到div内容末尾,但实际光标移至div开头。

相关信息

  • 浏览器:Chrome 107.0.5304.62(64位)
  • 控制台无任何错误提示
  • 手动将光标移至末尾后添加第二个章节,光标会定位到最新追加内容的开头
  • 需求:尽量避免使用textarea,防止PHP处理时产生多余空白

解决方案

直接调用focus()只能让元素获得焦点,无法自动将光标定位到内容末尾。需要手动创建文本选区,强制将光标移到contenteditable元素的最后位置。

1. 新增光标定位函数

添加一个通用函数,专门处理contenteditable元素的光标末尾定位:

function placeCursorAtEnd(el) {
    el.focus();
    const range = document.createRange();
    const selection = window.getSelection();
    range.selectNodeContents(el);
    range.collapse(false); // 折叠选区到内容末尾
    selection.removeAllRanges();
    selection.addRange(range);
}

2. 修改原addChapter()函数

把原来的div.focus()替换为调用上述函数:

function addChapter() {
    let chapter = prompt("New Chapter Name?");
    if (chapter != null) {
        $.get("editor.php?newchapter=" + chapter, function (data, status) {
            $("#toc_base").html("<li>" + chapter + "</li>");
            $("#content").append("[b]" + chapter + "[/b]\n\n");

            var div = document.getElementById('content');
            placeCursorAtEnd(div); // 替换原有的div.focus()
        });
    }
}

原理说明

  • document.createRange()创建范围对象,用于选中元素内容
  • range.selectNodeContents(el)选中目标元素的全部内容
  • range.collapse(false)将选区折叠到末尾(传true会折叠到开头)
  • 通过window.getSelection()获取当前选区,移除原有选区后添加新的范围,就能强制光标定位到内容末尾

如果遇到AJAX后DOM更新延迟导致函数不生效的情况,可以给定位函数加个微小延迟:

setTimeout(() => placeCursorAtEnd(div), 10);

内容的提问来源于stack exchange,提问作者jpgerb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 20:50:54