javascript 如何在设置值后使HTML文本区域中的撤消工作?

41ik7eoe  于 2023-04-04  发布在  Java
关注(0)|答案(1)|浏览(116)

我有一个<textarea>元素,我监听某些按键,比如如果用户键入Tab键,我会阻止改变焦点的默认操作,并在正确的位置添加Tab字符。
问题是,当用户按下我监听的键之一时,撤销有点乱。我如何让撤销/重做功能工作?我想过监听ctrl/cmd-z和ctrl/cmd-shift-z键,记录所有内容,并处理撤销/重做,但然后编辑和上下文菜单选项将无法工作...
您可以通过键入带有制表符和回车符的字母,然后尝试撤消和重做:

const textarea = document.querySelector('textarea')
textarea.addEventListener('keydown', function (event) {
  if (event.key == "Tab") {
    event.preventDefault()
    const cursor = textarea.selectionStart
    textarea.value = textarea.value.slice(0, cursor) + '\t' + textarea.value.slice(textarea.selectionEnd)
    textarea.selectionStart = textarea.selectionEnd = cursor + 1
  } else if (event.key == "Enter") {
    event.preventDefault()
    const cursor = textarea.selectionStart
    textarea.value = textarea.value.slice(0, cursor) + '\n' + textarea.value.slice(textarea.selectionEnd)
    textarea.selectionStart = textarea.selectionEnd = cursor + 1
  }
})
<textarea cols="50" rows="20"></textarea>
wgx48brx

wgx48brx1#

我认为问题的核心是JavaScript和浏览器默认的撤销方法之间缺乏交互。使用JavaScript将文本添加到文本区域并不会以任何方式告诉浏览器的“撤销”删除所添加的文本,因为浏览器的“撤销”只意味着删除用户输入的文本,而不是JavaScript输入的文本。
以你的代码为例,按下Enter键后,你告诉事件监听器preventDefault,这完全阻止了Enter键将用户输入附加到文本区域,然后你使用JavaScript合成输入,浏览器的“undo”不会跟踪。
你可以通过使用document.execCommand()来克服这种缺乏交互的情况。你可以通过链接检查它的浏览器支持。

const textarea = document.querySelector('textarea');

textarea.addEventListener('keydown', function (event) {
  const cursor = textarea.selectionStart;
  if (event.key === "Tab") {
    event.preventDefault();
    // appends a tab and makes the browser's default undo/redo aware and automatically moves cursor
    document.execCommand("insertText", false, '\t');
  } else if (event.key === "Enter") {
    event.preventDefault();
    document.execCommand("insertText", false, '\n');
  }
});
<textarea cols="50" rows="8"></textarea>

相关问题