可以理解的变化事件
我想在用户使用contenteditable
属性编辑div
的内容时运行一个函数。 什么是onchange
事件的等价物?
我正在使用jQuery,所以任何使用jQuery的解决scheme是首选。 谢谢!
我build议将侦听器附加到由editable元素触发的关键事件,但是您需要知道在更改内容本身之前触发keydown
和keypress
事件。 这不会涵盖更改内容的所有可能方法:用户也可以使用剪辑,复制和粘贴从编辑或上下文浏览器菜单,所以您可能也想要处理cut
copy
和paste
事件。 而且,用户可以放置文本或其他内容,所以在那里有更多的事件(例如mouseup
)。 您可能需要轮询元素的内容作为后备。
更新2014年10月29日
HTML5 input
事件是长期的答案。 在撰写本文时,它支持当前Mozilla(来自Firefox 14)和WebKit / Blink浏览器(但不包括IE)中的可contenteditable
元素。
演示: http : //jsfiddle.net/ch6yn/
这是一个更有效的版本,用于所有contenteditables。 这是基于这里的最佳答案。
在使用jQuery的CoffeeScript中:
$('body') .on 'focus', '[contenteditable]', -> $this = $(this) $this.data 'before', $this.html() return $this .on 'blur keyup paste input', '[contenteditable]', -> $this = $(this) if $this.data('before') isnt $this.html() $this.data 'before', $this.html() $this.trigger('change') return $this
在使用jQuery的JavaScript中:
$('body').on('focus', '[contenteditable]', function() { var $this = $(this); $this.data('before', $this.html()); return $this; }).on('blur keyup paste input', '[contenteditable]', function() { var $this = $(this); if ($this.data('before') !== $this.html()) { $this.data('before', $this.html()); $this.trigger('change'); } return $this; });
该项目在这里: https : //github.com/balupton/html5edit
考虑使用MutationObserver 。 这些观察者被devise为对DOM中的变化作出反应,并作为突变事件的高性能替代。
优点:
- 发生任何变化时发生,这是通过听其他答案build议的关键事件难以实现的。 例如,所有这些工作都很好:通过上下文菜单拖放,斜体,复制/剪切/粘贴。
- 考虑到性能而devise。
- 简单,直接的代码。 理解和debugging侦听一个事件的代码比监听10个事件的代码要容易得多。
- Google有一个很好的突变概要库 ,使得使用MutationObservers非常容易。
缺点:
- 需要最新版本的Firefox(14.0+),Chrome(18+)或IE(11+)。
- 新API了解
- 关于最佳做法或案例研究的信息还不多
学到更多:
- 我写了一个小片段来比较使用MutationObserer来处理各种事件。 我使用了balupton的代码,因为他的答案是最有价值的。
- Mozilla在API上有非常好的一页
- 看看MutationSummary库
我已经修改了lawwantsin的答案,所以这对我很有用。 我使用keyup事件而不是按键,这很好用。
$('#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')});
非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); });
以下是对我有用的东西:
var clicked = {} $("[contenteditable='true']").each(function(){ var id = $(this).attr("id"); $(this).bind('focus', function() { // store the original value of element first time it gets focus if(!(id in clicked)){ clicked[id] = $(this).html() } }); }); // then once the user clicks on save $("#save").click(function(){ for(var id in clicked){ var original = clicked[id]; var current = $("#"+id).html(); // check if value changed if(original != current) save(id,current); } });
当我调查这个主题的时候,这个主题非常有帮助。
我已经将一些可用的代码修改为一个jQuery插件,所以它是一个可重用的forms,主要是为了满足我的需求,但其他人可能会喜欢更简单的接口来使用contenteditable标签来启动。
https://gist.github.com/3410122
更新:
由于它越来越受欢迎,该插件已被Makesites.org采用
发展将从此继续下去:
这是我最终使用和解决scheme的解决scheme。 我使用$(this).text()来代替,因为我只是使用一个内容可编辑的单行div。 但是,您也可以使用.html()这种方式,您不必担心全局/非全局variables的范围,并且before实际上是连接到编辑器div的。
$('body').delegate('#editor', 'focus', function(){ $(this).data('before', $(this).html()); }); $('#client_tasks').delegate('.task_text', 'blur', function(){ if($(this).data('before') != $(this).html()){ /* do your stuff here - like ajax save */ alert('I promise, I have changed!'); } });
当具有contentEditable属性的元素发生更改时,onchange事件不会触发,build议的方法可能是添加一个button来“保存”版本。
检查以这种方式处理问题的插件:
- 创build一个快速和肮脏的jQuery contentEditable插件
为了避免定时器和“保存”button,当元素失去焦点时,可以使用模糊事件。 但要确保元素实际上已经改变(不仅仅是聚焦和散焦),其内容应该与其最后的版本进行比较。 或者使用keydown事件在这个元素上设置一些“脏”标志。
在MutationEvents下使用DOMCharacterDataModified将导致相同的结果。 超时设置,以防止发送不正确的值(例如在Chrome中,我有空间键的一些问题)
var timeoutID; $('[contenteditable]').bind('DOMCharacterDataModified', function() { clearTimeout(timeoutID); $that = $(this); timeoutID = setTimeout(function() { $that.trigger('change') }, 50) }); $('[contentEditable]').bind('change', function() { console.log($(this).text()); })
JSFIDDLE的例子
我build立了一个jQuery插件来做到这一点。
(function ($) { $.fn.wysiwygEvt = function () { return this.each(function () { var $this = $(this); var htmlold = $this.html(); $this.bind('blur keyup paste copy cut mouseup', function () { var htmlnew = $this.html(); if (htmlold !== htmlnew) { $this.trigger('change') } }) }) } })(jQuery);
你可以直接调用$('.wysiwyg').wysiwygEvt();
您也可以根据需要删除/添加事件
在JQuery中一个简单的答案,我刚刚创build了这个代码,并认为这对其他人也有帮助
var cont; $("div [contenteditable=true]").focus(function() { cont=$(this).html(); }); $("div [contenteditable=true]").blur(function() { if ($(this).html()!=cont) { //Here you can write the code to run when the content change } });
检查这个想法。 http://pastie.org/1096892
我觉得这很接近。 HTML 5确实需要将更改事件添加到规范中。 唯一的问题是,callback函数在$(this).html()中实际更新内容之前评估if(before == $(this).html())。 setTimeout不起作用,而且很伤心。 让我知道你的想法。
非JQuery的答案…
function makeEditable(elem){ elem.setAttribute('contenteditable', 'true'); elem.addEventListener('blur', function (evt) { elem.removeAttribute('contenteditable'); elem.removeEventListener('blur', evt.target); }); elem.focus(); }
要使用它,请打电话(说)一个标题元素与id =“myHeader”
makeEditable(document.getElementById('myHeader'))
该元素现在可以由用户编辑,直到失去焦点。
基于@ balupton的回答:
$(document).on('focus', '[contenteditable]', e => { const self = $(e.target) self.data('before', self.html()) }) $(document).on('blur', '[contenteditable]', e => { const self = $(e.target) if (self.data('before') !== self.html()) { self.trigger('change') } })
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
- 将光标移至CKEditor中的特定位置
- 在包含HTML内容的contentEditable区域中获取插入(光标)位置
- 在contenteditable div中replaceinnerHTML
- 从contentEditable div中提取文本
- 任何所见即所得的富文本编辑器不使用HTML(contenteditable或designMode),一个la(新的)Google文档?
- jquery在contenteditable div中设置光标位置
- 如何使HTML <div>元素可编辑跨浏览器?
- 我如何去除围绕着一个专注的contenteditable pre的边界?
- 使用HTML5,如何在表单提交中使用contenteditable字段?