英文:
Keeping the structure intact in contentEditable Div
问题
我正在尝试从头开始构建一个富文本编辑器,似乎是一个非常庞大且复杂的任务,我知道,编辑器应该使用Range
和选择API而不是execCommand
,具备可扩展性,并支持段落对齐和内联样式等基本编辑功能。
我找到了SlateJs
库,它也允许您构建富文本编辑器。但是,我决心从零开始做这个,尽管我不知道从哪里开始。
问题是,当用户在我的编辑器中输入文本时,文本直接进入具有contentEditable
属性的容器元素中。然而,当用户在SlateJs
编辑器中输入文本时,文本进入了包含在段落
元素内的三个嵌套的span
元素中,您可以在此处查看:https://www.slatejs.org/examples/richtext
我该如何实现这种行为?
preventDefault
在输入上不起作用,但在keydown
上起作用
editor.addEventListener("keydown", (e) => {
e.preventDefault()
// 如果按键是可打印字符
if(event.key.length == 1){
// 这总是将文本追加到段落的最后,即使光标在其他地方
this.topLevelParagraph.innerHTML += event.key
}
})
光标位置不会改变,文本总是添加到末尾。
- 修复此问题的最佳方法是什么?
- 如果您能推荐可以帮助我构建类似于SlateJs的库和富文本编辑器的文章或资源,我将不胜感激。
英文:
I am trying to build a Rich Text Editor from scratch, Seems like a really big & complex task, I know, The editor should make use of Range
& selection apis instead of execCommand
, be extensible and support basic editing features like paragraph alignment and inline styling.
I've found the SlateJs
library which also allows you to build rich text editor. However I am determined to do this from scratch, even though I don't know where to start.
The problem is that when the user types into my editor the text goes directly into container element with contentEditable
div. However when the user types into SlateJs
editor, The text goes into a three nested spans which are contained inside a paragraph
element , You can inspect this here https://www.slatejs.org/examples/richtext
How can I implement this behavior ?
preventDefault
doesn't work on input but works on keydown
editor.addEventListener("keydown",(e)=> {
e.preventDefault()
// if the key is a printable character
if(event.key.length == 1){
// this always appends to the last of paragraph even if the cursor is somewhere else
this.topLevelParagraph.innerHTML += event.key
}
})
The caret position doesn't change, Text always goes at last.
- What's the best way to fix this issue.
- I would appreciate if you could recommend articles or resources that can help me build a library like slatejs, rich text editor
答案1
得分: 1
1 - 保持结构的方法是,首先创建初始元素、包装器和内联格式化元素,并决定哪个元素应该/将接受用户输入。
2 - 在具有contentEditable
属性的容器上触发keydown
事件,现在您可以在事件上使用preventDefault
并将按键放入容器内的确切元素中。您必须过滤掉不是“可打印字符”的按键。您可以使用ascii
代码来过滤掉控制字符,但我建议您使用unicode
。我使用了e.key.length == 1
和一些其他过滤器。
3 - 现在您的输入已经进入了文本框,或者可能没有,因为您使用了preventDefault
。您还必须跟踪用户选择范围,并在每个按键之后进行调整,以使输入位于正确的位置。例如,对于每个按键,您必须将当前的“range”折叠到“endPosition + 1”,以便光标保持在当前键入的字母的旁边。
4 - 您必须处理copy
和paste
操作,不需要处理退格键。但是,每次用户操作后,您必须确保结构保持完整。
您可以选择另一种方法,创建自己的数据结构。您可以从浏览器中获取所有事件,并在您的代码中拥有一个用户更改而不是文本字段的结构,并重新渲染接受输入/已更改的对象。
英文:
I learned that to maintain structure, You need to do some things
1 - Initial structure, You must create initial elements, wrappers and formatting inline elements and decide which element should / will take input from the user
2 - A keydown
event on the container with contentEditable
attribute , Now you can preventDefault
on the event and put the key into the exact element inside the container, You must filter out keys that are not printable characters
, You can filter control characters using ascii
codes but I recommend you use unicode
<br>
I used e.key.length == 1
and some other filters
3 - Now your input has gone into the box, or maybe not because you preventedDefault
, You must also track user selection range and adjust it after every key, so input is at the right position, for example on each key you must collapse the current range
at endPosition + 1
, so the caret remains right next to the current letter typed
4 - You must handle copy
paste
, You don't have to handle backspace key, However after every user action, You must make sure the structure remains intact
You could go a separate way and create your own data structure, You take all the events from the browser and have a structure in your code that user changes instead of the text field and re render the object that takes the input / has changed.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论