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

实现contenteditable自动添加带dir="auto"的div标签

实现contenteditable自动用
包裹文本及回车换行

要实现你需要的效果,核心是拦截默认的输入和回车行为,手动控制DOM结构,确保所有文本都被<div dir="auto">包裹,且回车后生成符合要求的新行容器。以下是完整的实现代码:

修改后的HTML(无需大幅改动)

<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" type="text/css" href="style.css">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,700|Roboto+Mono">
</head>
<body leftmargin="0" topmargin="0" rightmargin="0" bottommargin="0">
    <div id="main" class="main" style="padding-left: 13px;">
        <div id="editor" contenteditable="true"></div>
    </div>
    <script type="text/javascript" src="richeditor.js"></script>
</body>
</html>

重写后的JS代码(richeditor.js)

const editor = document.getElementById('editor');

// 监听输入事件,确保文本被正确包裹
editor.addEventListener('input', () => {
    wrapTextInDiv();
});

// 监听回车键,拦截默认行为生成指定div
editor.addEventListener('keydown', (e) => {
    if (e.key === 'Enter') {
        e.preventDefault();
        handleEnterKey();
    }
});

// 辅助函数:将裸文本节点包裹进<div dir="auto">
function wrapTextInDiv() {
    // 遍历编辑器内的所有子节点
    const childNodes = Array.from(editor.childNodes);
    childNodes.forEach(node => {
        // 处理文本节点或没有dir="auto"的div
        if (node.nodeType === Node.TEXT_NODE && node.textContent.trim() !== '') {
            const div = document.createElement('div');
            div.setAttribute('dir', 'auto');
            div.textContent = node.textContent;
            editor.replaceChild(div, node);
        } else if (node.tagName === 'DIV' && node.getAttribute('dir') !== 'auto') {
            node.setAttribute('dir', 'auto');
        }
    });
}

// 处理回车键:生成新的<div dir="auto"><br></div>并定位光标
function handleEnterKey() {
    const selection = window.getSelection();
    const range = selection.getRangeAt(0);
    
    // 创建新的行容器
    const newDiv = document.createElement('div');
    newDiv.setAttribute('dir', 'auto');
    newDiv.innerHTML = '<br>';
    
    // 插入新div到当前光标位置
    range.insertNode(newDiv);
    
    // 将光标移动到新div内
    const newRange = document.createRange();
    newRange.setStart(newDiv.firstChild, 0);
    newRange.collapse(true);
    selection.removeAllRanges();
    selection.addRange(newRange);
    
    // 滚动到底部
    window.scrollTo(0, document.body.scrollHeight);
}

// 初始化:如果编辑器为空,先插入一个默认的div
if (editor.innerHTML.trim() === '') {
    const initDiv = document.createElement('div');
    initDiv.setAttribute('dir', 'auto');
    initDiv.innerHTML = '<br>';
    editor.appendChild(initDiv);
}

CSS保持原代码即可

#editor {
  display: table-cell;
  width: 100%;
  outline: 0px solid transparent;
  background-repeat: no-repeat;
  background-position: center;
  background-size: cover;
  min-height: 200px; /* 可选,给编辑器一个初始高度 */
}

关键逻辑说明

  1. 输入事件处理:每次输入后检查所有子节点,将裸文本节点替换为带dir="auto"的div,同时确保已有的div都带有该属性,避免重复包裹。
  2. 回车键拦截:阻止默认的回车行为,手动创建符合要求的<div dir="auto"><br></div>,并通过Range API将光标定位到新行内,保证编辑连贯性。
  3. 初始化处理:编辑器为空时自动插入一个默认的div,避免用户首次输入时出现裸文本。

测试后,输入"Test"回车会生成如下结构:

<div dir="auto">Test</div><div dir="auto"><br></div>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 06:45:10