保持 contentEditable Div 中的结构不变

huangapple go评论63阅读模式
英文:

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 - 您必须处理copypaste操作,不需要处理退格键。但是,每次用户操作后,您必须确保结构保持完整。

您可以选择另一种方法,创建自己的数据结构。您可以从浏览器中获取所有事件,并在您的代码中拥有一个用户更改而不是文本字段的结构,并重新渲染接受输入/已更改的对象。

英文:

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.

huangapple
  • 本文由 发表于 2023年7月23日 21:31:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/76748504.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定