我原本打算使用Document.execCommand()
方法以及contenteditable
属性来构建自定义的所见即所得编辑器,但当我查看Document.execCommand()
的文档时,发现它已经过时了。那么现代化(或现存的)替代方案是什么?
我原本打算使用Document.execCommand()
方法以及contenteditable
属性来构建自定义的所见即所得编辑器,但当我查看Document.execCommand()
的文档时,发现它已经过时了。那么现代化(或现存的)替代方案是什么?
execCommand()
已正式废弃,但没有替代方法。所以,如果你必须拥有丰富文本支持,你只能继续使用 execCommand()
并自己找出适用于要支持的浏览器的有效方法。execCommand()
的支持,因为许多服务需要其支持。事情的可悲状态是,HTML5 无法指定任何通用基础。这是因为浏览器供应商对于 execCommand()
的工作方式没有达成一致意见。因此,在 HTML5 中无法指定任何内容,它的总体目标是为任何新浏览器进入市场而指定所有必需和仅必需的交互操作内容。然而,在我看来,HTML5 在这里失败了,因为任何新浏览器要进入市场,都必须兼容 execCommand()
。因此,至少将其中一个浏览器特定实现标准化为官方实现是有意义的。execCommand()
实际执行的功能(例如撤消/重做、在选择范围内实际更改内容)。beforeinput
事件,从事件中收集待完成的修改信息并阻止浏览器默认行为,而是在 JS 代码中执行自定义内容修改(自定义富文本编辑器逻辑),然后使用 HTML+CSS 渲染结果。这需要在 JS 中实现所有内容,包括撤销/重做和所有操作,因此不需要任何浏览器支持。 - Mikko Rantalainenbeforeinput
之前,请先阅读此文:https://medium.com/content-uneditable/contenteditable-the-good-the-bad-and-the-ugly-261a38555e9c - Mikko Rantalainen我为我的平台创建了一个丰富的编辑器,用于XML(HTML5 + XHTML)编辑目的。我不会说document.execCommand()
已经完全死亡,因为它的某些部分仍然可以正常工作。不幸的是,对我来说,主要问题是浏览器使用许多不同的代码来生成那些屏幕阅读器无法识别的样式,这些阅读器被盲人或近乎盲人使用。
此外,我曾经遇到过最昂贵的时间错误是Gecko/Presto错误,其中视觉和技术选择(为什么它们不是同一件事,请不要问我)将导致DOM的某些部分被更改,而用户并没有打算这样做,这归结于每个字符的像素计数较低,因此如果Rich Editor不尊重视觉选择,用户很快就会离开。这需要四个月的时间才能克服,还有其他的错误。
最终,这是一个艰苦但可实现的努力,如果你打算像我一样构建一个HTML/XML编辑器,你应该计划至少六个月的时间,如果你不仅要做得正确,而且要测试到讨厌蛋糕的程度,然后只有有人指出另一个错误。
你的JavaScript方面的主要重点应该是以下内容:
document.createRange()
(创建 Range 对象)document.createRange().surroundContents()
(包裹范围内的所有节点)Node.cloneNode()
(复制节点)window.getSelection()
(获取用户选择的文本)window.getSelection().getRangeAt(0).commonAncestorContainer
(获取选区公共祖先节点)appendChild
(在父节点末尾插入子节点)insertBefore
(在指定节点之前插入子节点)insertBefore
+ nextSibling
(在指定节点之后插入子节点)replaceChild
(替换子节点)使用execCommand()
从不同的浏览器生成的代码不一致(通常设置内联样式,如果不彻底否定它,则会使您网站的CSS变得复杂),您应该坚持使用以下元素,您不仅可以控制,而且还与屏幕阅读器兼容:
em
用于强调文本(或“斜体”,<i>
已被弃用)。strong
用于强烈的文本(或“粗体”,<b>
已被弃用)。u
用于下划线(确保您的锚点样式与元素不同;u
可能被认为是“已弃用”的,但当我在未来十年左右修复标准时,我会反转这一点,适当使用它)。sub
用于垂直低于正常文本的子行文本。sup
用于垂直高于正常文本的上行文本。我一直打算修改我的富文本编辑器 (虽然它已经得到了修补,但还没有被彻底重写),但你可以在我个人资料中链接的网站上加载博客页面时查看源代码。原始项目花费我11个月的时间,但是现在有了更多的经验,我认为只需要三到四个月的时间就可以完成。如果你是认真的,我强烈建议远离框架和库。"但是…但是,他们会使我的生活变得更轻松!" 直到你想使用新版本并不得不重写整个项目。第一次使用纯 JavaScript 并避免无意义的维护。祝你好运!
anchorNode
和focusNode
根据从左到右或从右到左选择而切换。因为我在我的平台上找不到任何理由说明这很重要,所以我将an
对象(代表anchorNode
)放在左边,将fn
对象(代表focusNode
)始终放在右边。
我使用了约1,700个字符来解决Gecko/Presto问题;您可以先访问一个具有丰富表单的页面,在网站上找到它。
为了解决通过<s>
、<sub>
、<sup>
、<u>
等多种交换选择的问题(您必须测试简单和非常复杂的示例),我最终使用了window.getSelection().getRangeAt(0).commonAncestorContainer
和cloneNode
,然后在处理之前剥离了未包含在选择中的内容。然后,我只需使用window.getSelection().deleteFromDocument();
删除选择,并通过document.createElement
创建新的样式元素,我可以轻松地将其appendChild
到选择中,并将其插入到window.getSelection().getRangeAt(0).insertNode(id_('editor_rich_text').firstChild);
。
Gecko浏览器(例如Waterfox,Pale Moon以及现在已完全摧毁的Firefox)允许您选择多个文本实例。要这样做,只需按住Control
键来创建额外的选择。由于它并没有真正有任何意义的帮助(而且这些东西已经够复杂的了),我没有特别支持它。
我将在今天或本周末更新我的平台(根据此帖子的编辑时间)以反映新的更改。由于Gecko浏览器存在许多问题,我仍保留了许多旧代码。我扩展了功能,并解决了许多错误,而且没有采用任何黑客方式,也没有使用任何车库(框架或库)。
2021年9月26日:对于那些对撤销/重做功能感兴趣的人,你们将不得不使用基本上保留正在编辑的DOM部分的文本版本。当然,也可能有其他实现方式,但这些方式会非常复杂。你只需要使用 .cloneNode
制作编辑器父元素的副本,然后在内存中使用类似于 while(e.firstChild){xml + = new XMLSerializer().serializeToString(e.firstChild);}
的东西。由于您将其存储为文本,因此它不会具有DOM所具有的巨大内存影响。您将完全替换编辑器中的整个DOM,并跟踪每次更改的每个迭代,因此它仍将是一个庞大的项目。对于我的平台来说,现在并不是必要的,但我想提一下这一点,因为有些人在评论中提到了它。
u
,strong
等等,而不是 span
?我的意思是… 屏幕阅读器(如 JAWS)会解释 aria
属性,就像我在开发应用程序时记得那样,这些属性也必须能够被这些程序读取。对,嵌套是真正的麻烦所在……所以我想我也不应该使用 contentEditable
了吧? - IgorcontentEditable
属性是有效的。至于处理复杂嵌套,有两件事要做:1.为最大复杂度设置策略,并在超过时指示用户使用XML编辑器;2.确定最大阈值,使您的项目发布变得现实。如果您决定在复杂性方面走极端,请模仿LibreOffice的行为;我认为它目前是处理这种复杂性的“标准”。 - Johndata-edit
或类似的非侵入式HTML/XML属性来跟踪更改,并根据其相对位置和/或先前元素的内容分配值。撤消/重做是有序执行,因此您只需在JavaScript/CSS属性选择器上向前或向后迭代即可。由于我正在慢慢重写我的富文本编辑器,所以我还没有达到那个点。但是,如果能够胜任,您可能需要查看大约800-1,600字节的JavaScript。 - John您可以使用以下内容:
navigator.clipboard.writeText('text to be copied');
它执行与document.execCommand("copy")
完全相同的操作。
看起来替代方案将是Input Events Level 2。
虽然自己制作所见即所得编辑器非常诱人,但我个人会坚持使用 execCommand 直到新的标准推出。因为我们都只是会自己编写一个完整的编辑器,而不是重用现有的工作解决方案。
execCommand()
的合理部分标准化,以便清晰地前进。 - Mikko Rantalainendocument.execCommand()
的替代方案是 Clipboard API,通过 navigator.clipboard
访问。根据 MDN Web Docs(https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API):
此 API 旨在取代使用 document.execCommand() 访问剪贴板的方式。
编辑:如上面引用的文字所述,这只满足一部分需求(访问剪贴板)。
execCommand()
发出了警告,但它仍然可用,并且直到2022年现在仍没有标准替代方法,除非使用JavaScript版本库。使用编程语言可以制作所见即所得编辑器。
window.getSelection()
但现在继续使用execCommand也不是问题。
document.execCommand
没有问题。问题在于函数底层使用的 HTML 4
标准不再被广泛支持。例如,FontSize
命令使用已经被弃用的 <font>
标签。但是也有好消息。第一个好消息是 document.execCommand
从 javascript 中将永远不会被移除。第二个好消息是 - 你可以使用 insertHTML
命令来插入任何你想要的 HTML。
function FontSize40px(){
var spanString = `
<span
style="font-size: 40px;"
>${ document.getSelection().toString()}
</span>
`
document.execCommand('insertHTML', false, spanString);
}
这只是一个愚蠢的例子 :))
document.execCommand()
... - Peter Bcontenteditable
是一个相当不可预测的东西,所以您可能要考虑根本不使用contenteditable
,而是将元素替换为具有该元素内容预加载的编辑器。 - Mike 'Pomax' Kamermanscontenteditable
提供更多控制。 - Mike 'Pomax' Kamermans