实现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; /* 可选,给编辑器一个初始高度 */ }
关键逻辑说明
- 输入事件处理:每次输入后检查所有子节点,将裸文本节点替换为带
dir="auto"的div,同时确保已有的div都带有该属性,避免重复包裹。 - 回车键拦截:阻止默认的回车行为,手动创建符合要求的
<div dir="auto"><br></div>,并通过Range API将光标定位到新行内,保证编辑连贯性。 - 初始化处理:编辑器为空时自动插入一个默认的div,避免用户首次输入时出现裸文本。
测试后,输入"Test"回车会生成如下结构:
<div dir="auto">Test</div><div dir="auto"><br></div>
内容的提问来源于stack exchange,提问作者chris oojer
相关产品推荐
相关产品推荐

