如何使用 JavaScript 将文本插入文本区域而不弄乱编辑历史记录?

Sai*_*uha 8 html javascript textarea undo-redo

基本上我想要的是,如果用户在文本区域中选择一些文本并按 ctrl + b,那么所选内容中的文本应该被星号包围。

所以基本上我想要的是:

1)文本区域内容:“你好,这是一些文本”

2)用户选择一些文本并按ctrl + b“你好,这是一些文本”(假设粗体部分是文本选择)

3)所以我希望文本区域内容为:“你好,这是*一些*文本”

4)如果用户按下 ctrl + z(或任何撤消操作),文本区域内容应返回到“你好,这是一些文本”

我尝试过如何使用 javascript 将文本插入文本区域?并将文本插入光标位置的文本区域(Javascript)和类似的,但问题是,在大多数浏览器上执行撤消(ctrl + z)时,我希望文本返回到步骤 1 中的值。但这不会发生。我了解 stackoverflow 在其编辑器中实现了自己的撤消重做功能。但我希望不要那么复杂。必须支持chrome和safari

我正在考虑的一种方法是定位光标并发出合成键事件。我不知道它是否有效以及是否不会出现问题

Jos*_*son 6

更新后的版本

要在更改文本区域的总体值时保存用户历史记录,而不是:

textarea.value = newText;
Run Code Online (Sandbox Code Playgroud)

使用:

textarea.focus();
document.execCommand('selectAll',false);

var el = document.createElement('p');
el.innerText = newText;

document.execCommand('insertHTML',false,el.innerHTML);
Run Code Online (Sandbox Code Playgroud)

在我的中端游戏设备上,字符串长度超过 4,000 个字符时,大约需要1 秒,因此您必须弄清楚这对于您的用例是否可以接受。

旧版

也许您熟悉execCommand并想知道为什么我们不直接使用这个:

textarea.focus();
document.execCommand('selectAll',false);
document.execCommand('insertText',false,newText);
Run Code Online (Sandbox Code Playgroud)

在 Chromium 上insertText速度非常慢,尤其是对于较长的字符串。对于超过 4,000 个字符的示例,在我的游戏中期,更新版本中使用的相同字符串大约需要 10 秒

不过,它也确实保存了用户历史记录,并且在历史记录状态之间移动仍然是可接受的速度(约 0.5 秒)。

这更慢是否有意义,因为我会假设我在更新版本 Chromium 的后台中明确执行的操作?不。但我想这就是 Chromium 的现状。如果旧版本变得更好,请在下面评论。

一般注意事项

不幸的是,execCommand它在 Firefox 的 textarea 元素内部不起作用。这可能会在即将发布的版本中得到修复。

在 Chromium 和 Firefox 中进行了测试。

如果我找到更快的解决方案(和/或在 Firefox 中工作的解决方案),我一定会分享它。