contentEditable是一个HTML属性(由Microsoft发明并在HTML5中标准化),用于客户端浏览器内“富文本”编辑。
输出: 嘿 怎么了? 在 Chrome 中输出: <div id="content" contenteditable="true" style="border:1px solid #000;width:500px;height:40px;"> hey <div>what's up?</div> <div> <button id="insert_caret"></button> 我相信FF它看起来像这样: hey <br /> what's up? 并在IE中: hey <p>what's up?</p> 不幸的是,没有好的方法可以让每个浏览器插入 <br /> 而不是 div 或 p 标签,或者至少我在网上找不到任何东西。 无论如何,我现在想做的是,当我点击按钮时,我希望将插入符号设置在文本末尾,所以它应该看起来像这样: hey what's up?| 有什么方法可以做到这一点,使其适用于所有浏览器? 示例: $(document).ready(function() { $('#insert_caret').click(function() { var ele = $('#content'); var length = ele.html().length; ele.focus(); //set caret -> end pos } } 以下功能将在所有主要浏览器中执行此操作: function placeCaretAtEnd(el) { el.focus(); if (typeof window.getSelection != "undefined" && typeof document.createRange != "undefined") { var range = document.createRange(); range.selectNodeContents(el); range.collapse(false); var sel = window.getSelection(); sel.removeAllRanges(); sel.addRange(range); } else if (typeof document.body.createTextRange != "undefined") { var textRange = document.body.createTextRange(); textRange.moveToElementText(el); textRange.collapse(false); textRange.select(); } } placeCaretAtEnd( document.querySelector('p') ); p{ padding:.5em; border:1px solid black; } <p contentEditable>foo bar </p> 将插入符号放在开头几乎是相同的:它只需要将传递到调用中的布尔值更改为collapse()。下面是一个创建将插入符号放在开头和结尾的函数的示例: function createCaretPlacer(atStart) { return function(el) { el.focus(); if (typeof window.getSelection != "undefined" && typeof document.createRange != "undefined") { var range = document.createRange(); range.selectNodeContents(el); range.collapse(atStart); var sel = window.getSelection(); sel.removeAllRanges(); sel.addRange(range); } else if (typeof document.body.createTextRange != "undefined") { var textRange = document.body.createTextRange(); textRange.moveToElementText(el); textRange.collapse(atStart); textRange.select(); } }; } var placeCaretAtStart = createCaretPlacer(true); var placeCaretAtEnd = createCaretPlacer(false); 不幸的是,蒂姆的出色答案对我来说只适用于放在最后,要放在开始时我必须稍微修改它。 function setCaret(target, isStart) { const range = document.createRange(); const sel = window.getSelection(); if (isStart) { const newText = document.createTextNode(''); target.appendChild(newText); range.setStart(target.childNodes[0], 0); } else { range.selectNodeContents(target); } range.collapse(isStart); sel.removeAllRanges(); sel.addRange(range); target.focus(); target.select(); } 不确定是否确实需要 focus() 和 select()。 这个(实时)示例显示了一个简短的简单函数,setCaretAtStartEnd,它有两个参数;用于放置插入符号的(可编辑)节点和一个指示放置位置的布尔值(节点的开始或结束) const editableElm = document.querySelector('[contenteditable]'); document.querySelectorAll('button').forEach((elm, idx) => elm.addEventListener('click', () => { editableElm.focus() setCaretAtStartEnd(editableElm, idx) }) ) function setCaretAtStartEnd( node, atEnd ){ const sel = document.getSelection(); node = node.firstChild; if( sel.rangeCount ){ ['Start', 'End'].forEach(pos => sel.getRangeAt(0)["set" + pos](node, atEnd ? node.length : 0) ) } } [contenteditable]{ padding:5px; border:1px solid; } <h1 contenteditable>Place the caret anywhere</h1> <br> <button>Move caret to start</button> <button>Move caret to end</button> 如果您使用的是谷歌闭包编译器,您可以执行以下操作(从 Tim 的答案中进行了一些简化): function placeCaretAtEnd(el) { el.focus(); range = goog.dom.Range.createFromNodeContents(el); range.collapse(false); range.select(); } ClojureScript 中也有同样的事情: (defn place-caret-at-end [el] (.focus el) (doto (.createFromNodeContents goog.dom.Range el) (.collapse false) .select)) 我已经在 Chrome、Safari 和 FireFox 中测试过这个,不确定 IE...
我知道有例子,但我似乎不够聪明,无法弄清楚该怎么做。 我正在开发一个 JavaScript 应用程序,用户可以在其中创建带有标签的笔记。我正在使用 Tagify 库...
我正在尝试使div在单击时变为contentEditable,然后在鼠标移开时将contentEditable设置为false,但到目前为止我还没有成功。单击链接似乎会突出显示它,但除此之外...
我正在尝试在无状态反应组件中实现一个可内容编辑的div。 我不断收到以下警告: warning.js:36 警告:组件是 `contentEditable` 并且包含 `children`
我有一个设置了 contentEditable 属性的 div。 我遇到的问题是我输入的第一行没有包含在标签中,但后续行却包含在标签中。 所以输入: 全键盘 兹西CV 阿斯达夫格
有没有一种方法可以轻松地在可内容编辑的 div 中添加新行?
我正在构建一个文本编辑器并为其使用 contenteditable div。 一切都很顺利,除非我想通过在行开头按回车键来降低一行文本。 在我的应用程序中,我对
contenteditable LI 中的光标在单击时不会转到 EOL (Chrome)
我正在使用内容可编辑列表。目前我无法解决以下 chrome 问题(至少在 FF 中工作正常)。 当您单击以下行末尾后,光标为...
在 php 生成的表中使用 contenteditable 来更新 mysql
假设你有一个通过 php 从 mysql 数据库生成的表, 例如, ...
有什么办法可以有一个受控的输入内容可编辑的div吗? 我正在寻找这种确切的行为,但我需要使用 contentEditable div 而不是输入: 有什么办法可以有一个受控的输入内容可编辑的div吗? 我正在寻找这种确切的行为,但我需要使用 contentEditable div 而不是输入: <input value={this.state.text}></input> 输入不显示输入的内容,而是显示 this.state.text 中的内容。 仅用 contentEditable div 进行交换是行不通的,它显示的是键入的内容,而不是 this.state.text 中的内容: <div contentEditable={true} value={this.state.text}></div> Stackblitz:https://stackblitz.com/edit/react-q4xoya 值不是 div 的有效属性。这是可以做到的,但没有得到官方支持,而且肯定是非正统的。 我建议你从 stackblitz 中更改此行: <div style={{border: '1px solid black'}} contentEditable={true} value={this.state.text}></div> 对此: <div style={{border: '1px solid black'}} contentEditable={true}>{this.state.text}</div> 如果有人仍在寻找解决方案。 我们无法通过状态来控制可编辑内容,但我们可以在标签上使用 onInput 事件,并控制 contentEditable 标签的内部文本。 onInput={(e) => { let newContent = e.target.innerText; if (newContent.length > 32) { editRef.current.innerText = newContent.substring(0, 32); setCursorToEnd(editRef.current); } }}
我正在尝试编写一个所见即所得的编辑器。我不希望人们能够粘贴外国 html,所以我想我可以将其转换为文本。但我仍然希望粘贴 html(如果它源自...)
如何使用 Selenium 和 Python 在非输入标签中输入文本?
我试图自动化一个网站,这很简单,我只想自动添加我的评论,但问题是没有“输入”标签我已经使用检查元素的搜索来找到它。 .
将插入符位置设置为 contentEditable 元素内的空节点
我的任务是设置一个文本插入符号以显示在 contentEditable div 内的空 span 节点内。 以下内容在 Firefox 3.6 上没有任何问题: 我的任务是设置一个文本插入符以显示在 contentEditable div 内的空跨度节点内。 以下内容在 Firefox 3.6 上没有任何问题: <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <script type="text/javascript" src="js/jquery-1.4.3.min.js"> </script> <style> #multiple { border: 1px solid #ccc; width: 800px; min-height: 20px; padding: 5px; outline: none; } </style> <script> $(document).ready(function(){ var contentEditable = document.getElementById('multiple'); var lastItem = contentEditable.getElementsByTagName('span').item(2); var selectElementText = function(el, win){ win = win || window; var doc = win.document, sel, range; if (win.getSelection && doc.createRange) { range = doc.createRange(); range.selectNodeContents(el); range.collapse(false); sel = win.getSelection(); sel.removeAllRanges(); sel.addRange(range); } else if (doc.body.createTextRange) { range = doc.body.createTextRange(); range.moveToElementText(el); range.select(); } } contentEditable.focus(); selectElementText(lastItem); }); </script> <title>Range Selection Tasks (Make Me Want to Cry)</title> </head> <body> <div id="multiple" contentEditable="true"> <span style="color:red">First</span><span style="color:green">Second</span><span style="color:blue"></span> </div> </body> </html> ...但在 Webkit 和 IE 上,焦点设置为 倒数第二 跨度。不知道为什么。如果我在最后一个跨度内放置一个空格,它会起作用,但随后我会得到一个字符范围选择。 话虽如此,如果插入符号位于最开始,那么最后一个节点中有空格是可以接受的。 如有任何帮助,我们将不胜感激。预先感谢您。 将元素的 innerHTML 设置为零宽度字符: ('element').innerHTML = 'ÈB'; 现在卡雷特可以去那里了。 IE 的选择/范围模型基于文本内容的索引,而不考虑元素边界。我相信在没有文本的内联元素内设置输入焦点可能是不可能的。当然,在您的示例中,我无法通过单击或箭头键将焦点设置在最后一个元素内。 如果将每个跨度设置为display: block,它几乎可以工作,尽管仍然存在一些非常奇怪的行为,这取决于父级中是否存在空格。使用浮动、内联块和绝对位置等技巧使显示看起来内联,使 IE 将每个元素视为单独的编辑框。相对定位的块元素彼此相邻可以工作,但这可能不切实际。 如果让你感觉好一点的话,IE9终于修复了这个不愉快的地方并采用了标准范围模型。 (万岁!) 如果插入符号位于最开始,则最后一个节点中有空格是可以接受的。 那么,除非 IE 选择专家能想到更好的办法,否则我可能会这样做。 (打电话给蒂姆·唐!) 我找到了 Webkit 的解决方法,不知道之前是否有人发现过这一点,但是您可以在所需元素的伪选择器之后使用 css3 内容属性执行相同的操作,而不是以编程方式附加零宽度空格插入插入符号。这样做的优点是额外的字符不会显示在 DOM 中,并且用户无法在其中导航插入符号。所以基本上不需要清理。 要使其适用于内容可编辑元素的任何子元素,它会是这样的: #mycontenteditableelement *:after { content: '\200B'; } 我没有完全检查,但我怀疑这是一个完整的解决方法。 对我来说,将 contenteditable div 的内容设置为 <br> 是有效的。我尝试将其设置为 nbsp; 但这会在我开始编辑之前在 div 中创建额外的字符空间。 希望这有帮助。 聚会有点晚了,但我使用了 Unicode 零宽度无中断空格 ()。然后,在用户输入发生后调用的事件中,删除零宽度无中断空格。 我在使用 Unicode 空间问题时遇到了很多问题,其中大部分是糟糕的用户体验。这可以防止用户知道存在问题。 使用 inline-block 对 contenteditable 内的元素应用最小高度和最小宽度可以起到一些的好处,尽管这种影响会产生意想不到的副作用: #multiple * { min-height: 1em; } span, b, strong, i, em, a, etc { display: inline-block; min-width: 1em; background-color: hsla(0, 50%, 50%, .5); /* this is only a visual aid; discard @ will */ vertical-align: middle; /* so elements w/ inline-block align w/ text correctly */ } 您会发现仍然存在问题,但如果您愿意为一小部分其他问题牺牲一些问题,这可能会有一些好处。 我偶然发现你可以通过添加 CSS 将光标放置在空的“p”元素中 p { border:1px solid transparent; } 问题是,我不知道为什么会这样! 也许有人可以提供一些见解? 如果这只是一个奇怪的副作用,可能会有风险。
Contenteditable Div 展开而不是添加滚动条
我有一个带有 ID 编辑器的 contenteditable div。我遇到一个问题,当我添加内容时,编辑器的高度不断扩大。我将overflow-y设置为auto,但没有添加scrollba...
内容可编辑 Div,附加 HTML 导致问题。以编程方式附加 HTML 后键入的每个文本都会添加到最后一个 HTML 标记中
我正在尝试制作一个内容可编辑的 div,可用于为应用程序生成消息模板。用户可以通过点击按钮将名称等字段的占位符附加到模板中。
我几天来一直在尝试解决这个问题,但我不知道如何解决它。我希望您能帮助我或给我一些提示,引导我解决问题。 我是
我在网上搜索过,但找不到在 Angular 6/7 上处理 contenteditable 事件的方法。 Angular 似乎有一个混乱的解决方案,但所说的功能似乎没有被转移到rec...
react.js 如何自动聚焦 contentEditable 元素
如何在 React 中将焦点设置在 contentEditable 元素上? 我找到了很多关于该主题的页面,但无法让它发挥作用。 示例代码: 从 'react' 导入 React, { useRef, useEffect }; 常量...
如何将光标放在 br 和 non-contenteditable 之间?
这是 HTML 你好世界 世界你好 ... 这是 HTML <div contenteditable="true" style="padding: 8px;"> hello world <br> <div contenteditable="false" style="display: inline-block;">hello world</div> </div> 我无法将光标放在此处的不可内容编辑的开头(或在 br 和不可内容编辑之间)。请给我 HTML、CSS 和 JavaScript 来完成此操作。 我尝试过的: br 和不可内容编辑之间的 0 宽度空格。我不喜欢这个,因为你必须按额外的箭头才能移动。而且每次删除不可内容编辑时都必须删除 0 宽度的空格。 我没有找到如何在没有 0 宽度空格的情况下实现它,但也许你可以尝试在移动插入符号时自动跳过 0 宽度空格,并在删除旁边的节点时删除它。 这是我在按箭头键时尝试处理插入符号的方法(codepen,在 Firefox 中,您无法将插入符号放置在可编辑父项末尾的不可内容编辑之后,因此我在结束): editable.addEventListener('keydown', (e) => { const selection = window.getSelection() const position = selection.getRangeAt(0) if (e.key === 'ArrowLeft') { if (position.startOffset === 1 && position.startContainer.textContent.startsWith('\u200b')) { createSelection(position.startContainer.previousSibling, true) } } if (e.key === 'ArrowRight') { if (position.startOffset === 0 && position.startContainer.textContent.startsWith('\u200b')) { selection.collapse(position.startContainer, 1) } } }) function createSelection(element) { const newSelection = window.getSelection(); newSelection.removeAllRanges(); const range = document.createRange(); range.selectNode(element); newSelection.addRange(range); } 遗憾的是它效果不太好,我还没有弄清楚如何自动删除 0 宽度的空格。
Firefox 在按 Enter 键时插入 标签,而其他浏览器则添加 或 。我知道 chrome 和 safari 正在插入第一个孩子的相同标签...... Firefox 在按 Enter 键时插入 <br /> 标签,而其他浏览器则添加 <p> 或 <div>。我知道 chrome 和 safari 正在插入 contentEditable div 的第一个子元素的相同标签。 Firefox 也是如此,但是,如果第一个标签的innerHTML 为空,则 Firefox 只是忽略该标签并通过在第二行中推送默认节点来创建新行,并直接在编辑器内写入而不是在子节点内写入。所以基本上,我希望 Firefox 在给定的标签内写入,并继续在每次按 Enter 时插入这种节点。如何做呢?有什么建议么? 我找到了解决方案:) 为了使这项工作有效,您必须为插入符的父元素提供一个 id。然后你可以使用下面的代码。请注意,我从 c# 获取 browsernName 并将其放入隐藏字段中。这就是为什么我将其等同于“firefox”。以下代码在FF 3.6上测试,完美运行。唯一的事情是,您必须检查插入符号的父元素,如果它不等于当前行的 id,那么您必须使用选择函数将插入符号放置在当前行内。另外,在 keyup 事件上执行此代码,并确保如果您在 keyup 事件上执行其他一些代码,请将此代码放在其末尾!无论如何,享受吧:) // The code works good in the following cases: // 1) If there is text inside the editor and the user selects the whole text // and replace it with a single character, the <p> tag will be placed and the // text will place inside the p tag // 2) If the user selects the whole code and deletes it and begins to type again // 3) If the user types normally and press enter // NB: Please note me if you find any bug if (browserName == "firefox") { //remove all br tags var brs = txteditor.getElementsByTagName("br"); for (var i = 0; i < brs.length; i++) { brs[i].parentNode.removeChild(brs[i]); } //check whether there is a p tag inside var para = txteditor.getElementsByTagName("p"); if (para.length == 0) { var inner = txteditor.innerHTML.replace(/^\s+|\s+$/g, ''); var str = (inner == "") ? "​" : txteditor.innerHTML; var nText = "<p id=\"" + cRow + "\">" + str + "</p>"; // in order to prevent a dublicate row clear inside the text editor txteditor.innerHTML = ""; document.execCommand('insertHTML', false, nText); } else { // always make sure that the current row's innerHTML is never empty if (document.getElementById(cRow).innerHTML == "") document.getElementById(cRow).innerHTML = "​"; } } 尝试在元素内插入 <p></p>。那么几乎可以肯定每个换行符都会是一个新段落。 如果将 contenteditable 元素更改为 <span> 而不是 <div>,则新行将带有 <br>。我还没有用其他元素对此进行测试,但看看不同元素的行为方式会很有趣。 可以使用 <span> 设置 display: block 元素的样式,使其看起来像 <div> 元素。 我遇到了类似的问题,导致 Firefox 中出现额外的 <br>,但没有找到任何 <p> 或 <div>。当内容为空或按空格后插入 <br>。 无论如何,我尝试通过 MutationObserver API 来解决它。它工作得并不完美,但我未能找到满足我要求的其他解决方案。 if (navigator.userAgent.includes('Firefox')) { const observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { // when a <br> inserted if (mutation.addedNodes.length === 1 && mutation.addedNodes[0].tagName === 'BR') { // if at the beginning, remove it if (mutation.previousSibling === null) return mutation.addedNodes[0].remove() // or if after a space, remove it and add a space // since it seems Firefox need the <br> to keep that space if (mutation.previousSibling.nodeValue?.endsWith(' ')) { mutation.target.insertAdjacentText('beforeend', ' ') mutation.addedNodes[0].remove() } } }) }) observer.observe(contentEditableDiv, { childList: true }) } 副作用: 必须输入两次才能添加新行,或者有时需要添加空格 无法将内容换行 该问题也被提及为 Firefox 问题跟踪器中的错误:https://bugzilla.mozilla.org/show_bug.cgi?id=1615852 可能有帮助的摘录: <br> 元素在以下情况下是必需的: 块元素是空的,以便使它们的高度非零并放置第一行以获得良好的插入符位置 文本以可折叠的空白结尾,以使其可见