【问题标题】:How to make undo work in an HTML textarea after setting the value?设置值后如何使撤消在 HTML 文本区域中起作用?
【发布时间】:2017-11-12 07:01:13
【问题描述】:

我有一个 <textarea> 元素,我可以监听某些按键。就像用户键入 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>

【问题讨论】:

  • 当我在上面运行它时它对我有用,我使用的是 firefox
  • 它也适用于我的代码,Google Crome 版本 59.0.3071.86(官方版本)(64 位)
  • 有趣的是它对你们有用。在 macOS 10.12.5 上的 Google Chrome 版本 59.0.3071.86(官方构建)(64 位)上,它始终失败。我刚刚在最新的 Firefox 上试用过,撤消/重做效果很好!

标签: javascript html textarea preventdefault


【解决方案1】:

我认为问题的核心在于 Javascript 和浏览器默认的撤销方法之间缺乏交互。使用 Javascript 将文本附加到 textarea 不会以任何方式告诉浏览器的“撤消”删除附加的文本,因为浏览器的“撤消”仅用于删除用户输入的文本,而不是 Javascript 输入的文本。

以您的代码为例。按下 Enter 后,您告诉 eventListener 阻止默认设置,这共同阻止 Enter 键将用户输入附加到文本区域。然后,您使用 Javascript 合成输入,浏览器的“撤消”不会跟踪该输入。

您可以通过使用Document.execCommand() 来克服这种缺乏交互的问题。您可以通过链接查看它的浏览器支持。

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

});

【讨论】:

  • 我不知道document.execCommand 在光标位置插入字符串的机制!我在 Chrome 59 中使用过它,delete 有点搞笑,但总的来说,它确实可以让撤销/重做工作!谢谢。
  • 如果 Stackoverflow 的编辑器中有 Tab 部分,那就太好了! ?
  • 确实严重依赖浏览器,execCommand 应该可以在 Firefox 上运行,但是这个特定的 sn-p 在那里不起作用(我使用的是 v75.0)。该问题因ages而闻名
  • 根据 MDN,execCommand() 现在已弃用。来自W3C Draft“此规范不完整,预计不会超出草稿状态”(根据 Git,自 2015 年 8 月 7 日以来就是这种情况。)话虽如此,这里有一个相关问题没有出现在“相关”侧边栏中:stackoverflow.com/q/13597007
猜你喜欢
  • 2012-02-09
  • 1970-01-01
  • 2011-03-20
  • 2011-06-20
  • 1970-01-01
  • 1970-01-01
  • 2011-08-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多