Javascript 内容可编辑更改事件
我想在用户使用contenteditable属性编辑div的内容时运行一个函数。onchange事件的等价物是什么Javascript 内容可编辑更改事件,javascript,jquery,html,contenteditable,Javascript,Jquery,Html,Contenteditable,我想在用户使用contenteditable属性编辑div的内容时运行一个函数。onchange事件的等价物是什么 我正在使用jQuery,所以任何使用jQuery的解决方案都是首选。谢谢 当具有contentEditable属性的元素发生更改时,onchange事件不会触发,建议的方法是添加一个按钮以保存版本 检查此插件,它以这种方式处理问题: 我建议将监听器附加到可编辑元素触发的关键事件,不过您需要知道,keydown和keypress事件是在内容本身更改之前触发的。这并不能涵盖更改内容的所
我正在使用jQuery,所以任何使用jQuery的解决方案都是首选。谢谢 当具有contentEditable属性的元素发生更改时,onchange事件不会触发,建议的方法是添加一个按钮以保存版本 检查此插件,它以这种方式处理问题:
我建议将监听器附加到可编辑元素触发的关键事件,不过您需要知道,keydown和keypress事件是在内容本身更改之前触发的。这并不能涵盖更改内容的所有可能方法:用户还可以使用“编辑”或“上下文浏览器”菜单中的“剪切”、“复制”和“粘贴”,因此您可能还需要处理“剪切”“复制”和“粘贴”事件。此外,用户还可以删除文本或其他内容,例如mouseup,因此那里有更多的事件。您可能希望轮询元素的内容作为回退 2014年10月29日更新 从长远来看,这就是答案。在撰写本文时,Firefox14和WebKit/Blink浏览器支持当前Mozilla中的contenteditable元素,但IE不支持 演示: document.getElementByIdeditor.addEventListenerinput,函数{ 已激发console.loginput事件; },假;
请在此处键入内容为了避免计时器和保存按钮,您可以使用模糊事件,当元素失去焦点时会触发模糊事件。但为了确保该元素实际上发生了变化,而不仅仅是聚焦和散焦,它的内容应该与上一个版本进行比较。或者使用keydown事件在此元素上设置一些脏标志。查看此想法。
我想差不多了。HTML5确实需要将更改事件添加到规范中。唯一的问题是回调函数在$this.HTML中实际更新内容之前计算before==$this.HTML。我不工作,这很可悲。让我知道你的想法。我已经这样修改了劳万钦的答案,这对我很有用。我使用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')});
以下是对我有效的方法:
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);
}
});
这是我最终使用的解决方案,效果非常好。我改用$this.text,因为我只使用了内容可编辑的单行div。但是您也可以通过这种方式使用.html,您不必担心全局/非全局变量的范围,并且before实际上附加到editordiv
$('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!');
}
});
下面是一个更有效的版本,它对所有contenteditables使用on。这是基于这里的顶级答案
$('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');
}
});
项目在这里:使用将导致相同的结果。设置超时是为了防止发送不正确的值,例如,在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());
})
在我调查这个问题时,这条线索非常有用 我已经将这里提供的一些代码修改为jQuery插件,因此它是一种可重用的形式,主要是为了满足我的需要,但其他人可能会喜欢使用contenteditable标记的简单界面 更新: 由于它越来越受欢迎,该插件已被 发展将从这里继续: 考虑使用。这些观察器旨在对DOM中的更改做出反应,并作为对DOM的性能替代 优点: 当发生任何更改时触发,这很难通过听取其他答案建议的关键事件来实现。例如,所有这些都可以很好地工作:拖放、斜体、通过上下文菜单复制/剪切/粘贴。 设计时考虑到性能。 简单明了的代码。更容易理解和调试侦听一个事件的代码,而不是侦听10个事件的代码。 谷歌有一个很好的解决方案,这使得使用MutationObserver非常容易。 缺点: 需要最新版本的Firefox 14.0+、Chrome 18+或IE 11+。 需要理解的新API 关于最佳实践或案例研究的信息还不多 了解更多信息: 我写了一些比较使用MutationObserers和处理各种事件的文章。我用了巴卢普顿的密码,因为他的投票数最多。 在API上有一个非常好的页面 看看图书馆
为此,我构建了一个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快速脏答:
JQuery中的一个简单答案,我刚刚创建了这段代码,并认为它对其他人也有帮助
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
}
});
非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的header元素
makeEditable(document.getElementById('myHeader'))
用户现在可以编辑该元素,直到它失去焦点。根据@balupton的回答: $document.on'focus','contenteditable',e=>{ 常量self=$e.target self.data'before',self.html } $document.on'blur','contenteditable',e=>{ 常量self=$e.target 如果self.data'before'!==self.html{ 自我。触发“改变” } } 两种选择: 1对于现代evergreen浏览器: 输入事件将充当替代更改事件 或 2考虑IE11和现代evergreen浏览器: 这将监视div中的元素更改及其内容 const p=document.querySelector'p' const result=document.querySelector'div' const observer=新的mutationobserver mutationrecords=>{ result.textContent=mutationRecords[0]。target.data //result.textContent=p.textContent } 观察者,观察者{ characterData:true, 子树:对, } abc 角度2+ 您需要使用输入事件类型 演示 HTML
我还应该补充一点,通过使用浏览器的“编辑”菜单或上下文菜单来剪切、复制或粘贴内容,可以更改可编辑元素,因此您需要在支持IE 5+、Firefox 3.0+、Safari 3+、ChromeYou的浏览器中处理剪切、复制和粘贴事件。您可以使用keyup,并且不会出现计时问题。@Blowsie:Yes,但在事件触发之前,自动重复按键可能会导致很多变化。还有其他更改此答案未考虑的可编辑文本的方法,例如通过“编辑”和上下文菜单进行拖放和编辑。从长远来看,HTML5输入事件应该涵盖这一切。我正在使用debounce进行键控。@AndroidDev I testet Chrome,并且输入事件也会在复制粘贴和剪切时触发,按照规范的要求:+1-当用户修改现有文本时,DOMCharacterDataModified不会触发,例如应用粗体或斜体。在这种情况下,domsubtreemeding更合适。另外,人们应该记住,传统浏览器不支持这些事件。请注意,w3c会因为性能问题而贬低突变事件。更多内容可以在中找到。非常适合我,感谢CoffeeScript和Javascript。在内容模糊之前,此代码不会捕捉到一些更改。例如:拖放、从关联菜单剪切和从浏览器窗口粘贴。我已经设置了一个示例页面,该页面使用此代码,您可以与之交互。@jrullmann是的,我在拖放图像时遇到了此代码问题,因为它不侦听图像加载。在我的case@jrullmann非常好,即使在使用javascript更改值时也可以使用,在控制台中尝试:document.getElementById'editor_input'。innerHTML='ssss'。缺点是它需要IE11@NadavB不应该,因为如果$this.data'before'!=$这个是.html{是因为它与HTML5输入事件不太一样,HTML5输入事件在所有支持变异观察器的WebKit和Mozilla浏览器中都支持contenteditable,因为DOM变异可以通过脚本和用户输入发生,但对于这些浏览器来说,这是一个可行的解决方案。我认为它对性能的损害也可能大于输入事件,但是t我对此没有确凿的证据。+1,但您是否意识到突变事件不会在contenteditable中报告换行的效果?请在您的代码段中按enter键。@citykid:这是因为该代码段仅监视字符数据的更改。也可以观察DOM结构的更改。例如,请参阅Internet Explorer 11+supports。我至少能够在Chrome 43.0.2357.130中验证HTML5输入事件在每种情况下都会触发,特别是通过上下文菜单拖放、斜体、复制/剪切/粘贴。我还测试了粗体w/cmd/ctrl+b,并得到了预期的结果。我还检查并能够验证输入事件不会在progra上触发mmatic更改看起来很明显,但可以说与相关MDN页面上的一些令人困惑的语言相反;请参阅此处页面底部,了解我的意思:尝试使用keyup而不是keypress。随着可编辑内容变长,这将变得缓慢和滞后。innerHTML非常昂贵。我建议在存在输入事件的地方使用输入事件,然后将其删除返回到类似这样的内容,但需要某种程度的去抖动将直接或间接地选择一个div中所有内容可编辑的子元素。呃,为什么没有解释就投反对票?这对写答案的人和以后阅读答案的每个人都是有害的。此代码使元素内容可编辑,直到失去焦点。我认为这不能回答问题。问题on是如何在contenteditable元素更改时运行函数?这是什么删除事件?这看起来很有趣。有人能提供一些解释吗?对于后代,十年以后,不需要保存按钮,请检查接受答案的JSFIDLE。我通常这样做:document.getElementByIdeditor.oninput=function{…}。下面有一个很好的答案:记住,如果你否决了某个答案,你有责任留下评论。解释为什么答案不令人满意,除非有人已经留下了评论 评论,你只是同意他们。只需使用输入事件!如果您需要支持IE11,请使用变异观察者。我喜欢。简明扼要。
makeEditable(document.getElementById('myHeader'))
document.querySelector('div').addEventListener('input', (e) => {
// Do something with the "change"-like event
});
<div oninput="someFunc(event)"></div>
$('div').on('click', function(e) {
// Do something with the "change"-like event
});
var div = document.querySelector('div');
var divMO = new window.MutationObserver(function(e) {
// Do something on change
});
divMO.observe(div, { childList: true, subtree: true, characterData: true });
<div contentEditable (input)="type($event)">
Value
</div>
@Component({
...
})
export class ContentEditableComponent {
...
type(event) {
console.log(event.data) // <-- The pressed key
console.log(event.path[0].innerHTML) // <-- The content of the div
}
}
<div id="editor" contenteditable="true" >Some text here</div>
const input = document.getElementById('editor');
input.addEventListener('input', updateValue);
function updateValue(e) {
console.log(e.target);
}