内容可编辑的更改事件

IT技术 javascript jquery html contenteditable
2021-01-25 10:11:18

我想在用户编辑divwithcontenteditable属性的内容时运行一个函数onchange事件的等价物是什么?

我正在使用 jQuery,所以任何使用 jQuery 的解决方案都是首选。谢谢!

6个回答

我建议将侦听器附加到由可编辑元素触发的关键事件,但您需要注意keydownkeypress事件是在内容本身更改之前触发的。这不会涵盖更改内容的所有可能方法:用户还可以使用编辑或上下文浏览器菜单中的剪切、复制和粘贴,因此您可能还想处理cut copypaste事件。此外,用户可以删除文本或其他内容,因此那里有更多事件(mouseup例如)。您可能希望轮询元素的内容作为后备。

2014 年 10 月 29 日更新

HTML5input事件是在长期的答案。在撰写本文时,它支持contenteditable当前 Mozilla(来自 Firefox 14)和 WebKit/Blink 浏览器中的元素,但不支持 IE。

演示:

document.getElementById("editor").addEventListener("input", function() {
    console.log("input event fired");
}, false);
<div contenteditable="true" id="editor">Please type something in here</div>

演示:http : //jsfiddle.net/ch6yn/2691/

@AndroidDev 我测试了 Chrome,并且输入事件也会根据规范的要求在复制粘贴和剪切时触发:w3c.github.io/uievents/#events-inputevents
2021-03-15 10:11:18
您可以使用 keyup,并且不会出现计时问题。
2021-03-19 10:11:18
我还应该补充一点,可以通过使用浏览器的编辑菜单或上下文菜单来剪切、复制或粘贴内容来更改可编辑元素,因此您需要在支持它们的浏览器中处理cut,copypaste事件(IE 5+,Firefox 3.0+、Safari 3+、Chrome)
2021-03-20 10:11:18
我正在用 debounce 做 keyup。
2021-03-23 10:11:18
@Blowsie:是的,但是在事件触发之前,您可能会因自动重复按键而发生很多变化。还有其他更改此答案未考虑的可编辑文本的方法,例如通过“编辑”和上下文菜单进行拖放和编辑。长期来看,这一切都应该被 HTML5input事件覆盖
2021-03-26 10:11:18

这是一个更有效的版本,on用于所有 contenteditables。它基于此处的最佳答案。

$('body').on('focus', '[contenteditable]', function() {
    const $this = $(this);
    $this.data('before', $this.html());
}).on('blur keyup paste input', '[contenteditable]', function() {
    const $this = $(this);
    if ($this.data('before') !== $this.html()) {
        $this.data('before', $this.html());
        $this.trigger('change');
    }
});

该项目在这里:https : //github.com/balupton/html5edit

@jrullmann 是的,我在拖放图像时遇到了此代码的问题,因为它不侦听图像加载(在我的情况下处理调整大小操作是一个问题)
2021-03-24 10:11:18
有一些更改不会被此代码捕获,直到 contenteditable 变得模糊为止。例如:拖放、从上下文菜单中剪切以及从浏览器窗口粘贴。我已经设置了一个使用此代码的示例页面,您可以在此处与之交互
2021-03-26 10:11:18
非常适合我,感谢 CoffeeScript 和 Javascript
2021-03-27 10:11:18
@NadavB 不应该,因为这就是 "if ($this.data('before') !== $this.html()) {" 是为了
2021-03-31 10:11:18
@jrullmann 非常好,即使使用 javascript 更改值也可以工作,请在控制台中尝试:document.getElementById('editor_input').innerHTML = 'ssss'缺点是需要IE11
2021-04-05 10:11:18

考虑使用MutationObserver这些观察者旨在对 DOM 中的变化做出react,并作为Mutation Events的高性能替代品

优点:

  • 发生任何变化时触发,这很难通过听取其他答案建议的关键事件来实现。例如,所有这些都运行良好:通过上下文菜单拖放、斜体、复制/剪切/粘贴。
  • 设计时考虑到性能。
  • 简单直接的代码。与侦听 10 个事件的代码相比,侦听一个事件的代码更容易理解和调试。
  • 谷歌有一个优秀的变异摘要库,这使得使用 MutationObservers 变得非常容易。

缺点:

  • 需要最新版本的 Firefox (14.0+)、Chrome (18+) 或 IE (11+)。
  • 需要理解的新 API
  • 关于最佳实践或案例研究的可用信息并不多

学到更多:

  • 我写了一个小片段来比较使用 MutationObserers 处理各种事件。我使用了 balupton 的代码,因为他的回答获得了最多的支持。
  • Mozilla在 API 上有一个很棒的页面
  • 看一下MutationSummary
我能够验证(至少在 Chrome 43.0.2357.130 中)HTML5input事件在每种情况下都会触发(特别是通过上下文菜单拖放、斜体、复制/剪切/粘贴)。我还用 cmd/ctrl+b 测试了粗体并得到了预期的结果。我还检查并能够验证该input事件不会在程序更改时触发(这看起来很明显,但可以说与相关 MDN 页面上的一些令人困惑的语言相反;请参阅此处的页面底部以了解我的意思:开发人员.mozilla.org/en-US/docs/Web/Events/input )
2021-03-23 10:11:18
它与 HTML5input事件(contenteditable支持突变观察器的所有 WebKit 和 Mozilla 浏览器都支持)并不完全相同,因为 DOM 突变可能通过脚本和用户输入发生,但对于这些浏览器来说,这是一个可行的解决方案。我想它可能比input事件对性能的影响更大,但我没有确凿的证据证明这一点。
2021-03-25 10:11:18
@citykid:那是因为该代码段仅监视字符数据的更改。也可以观察 DOM 结构变化。例如,请参见jsfiddle.net/4n2Gz/1
2021-03-27 10:11:18
Internet Explorer 11+ 支持Mutation Observers
2021-04-06 10:11:18
+1,但是您是否意识到 Mutation Events 不会报告 contenteditable 中换行的影响?在您的代码段中按 Enter。
2021-04-09 10:11:18

非 jQuery快速而肮脏的答案:

function setChangeListener (div, listener) {

    div.addEventListener("blur", listener);
    div.addEventListener("keyup", listener);
    div.addEventListener("paste", listener);
    div.addEventListener("copy", listener);
    div.addEventListener("cut", listener);
    div.addEventListener("delete", listener);
    div.addEventListener("mouseup", listener);

}

var div = document.querySelector("someDiv");

setChangeListener(div, function(event){
    console.log(event);
});
这个删除事件是什么?
2021-04-01 10:11:18

我已经像这样修改了 lawwansin 的答案,这对我有用。我使用 keyup 事件而不是 keypress ,这很好用。

$('#editor').on('focus', function() {
  before = $(this).html();
}).on('blur keyup paste', function() { 
  if (before != $(this).html()) { $(this).trigger('change'); }
});

$('#editor').on('change', function() {alert('changed')});