可编辑的变更事件

2020/09/29 16:01 · javascript ·  · 0评论

当用户编辑divwith contenteditable属性的内容时,我想运行一个函数什么相当于一个onchange事件?

我使用的是jQuery,因此首选使用jQuery的解决方案。谢谢!

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

2014年10月29日更新

从长远来看HTML5 input事件是答案。在撰写本文时,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/

这是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

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

优点:

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

缺点:

  • 需要最新版本的Firefox(14.0 +),Chrome(18+)或IE(11+)。
  • 需要了解的新API
  • 关于最佳实践或案例研究的信息还很多

学到更多:

  • 我写了一个小片段来比较使用MutationObserers处理各种事件。我使用balupton的代码,因为他的回答最多。
  • Mozilla在API上有一个很棒的页面
  • 看看MutationSummary

我已经像这样修改了lawwantsin的答案,这对我有用。我使用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')});

非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);
});

两种选择:

1)对于现代(常绿)浏览器:
“输入”事件将作为替代的“更改”事件。

https://developer.mozilla.org/zh-CN/docs/Web/Events/input

document.querySelector('div').addEventListener('input', (e) => {
    // Do something with the "change"-like event
});

要么

<div oninput="someFunc(event)"></div>

或(使用jQuery)

$('div').on('click', function(e) {
    // Do something with the "change"-like event
});

2)考虑到IE11和现代(常绿)浏览器:
该监视div中元素的更改及其内容。

https://developer.mozilla.org/zh-CN/docs/Web/API/MutationObserver

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 });
const p = document.querySelector('p')
const result = document.querySelector('div')
const observer = new MutationObserver((mutationRecords) => {
  result.textContent = mutationRecords[0].target.data
  // result.textContent = p.textContent
})
observer.observe(p, {
  characterData: true,
  subtree: true,
})
<p contenteditable>abc</p>
<div />

这对我有用:

   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插件,因此它是可重用的形式,主要是为了满足我的需求,但其他人可能会喜欢使用ContentEditable标签的更简单的界面来快速入门。

https://gist.github.com/3410122

更新:

由于其日益普及,该插件已被Makesites.org采用

从这里继续开发:

https://github.com/makesites/jquery-contenteditable

为了避免使用计时器和“保存”按钮,可以在元素失去焦点时使用模糊事件触发。但要确保该元素实际上已更改(不仅仅是聚焦和散焦),应将其内容与上一个版本进行比较。或使用keydown事件在此元素上设置一些“脏”标志。

这是我最终使用且效果出色的解决方案。我改用$(this).text(),因为我只是使用内容可编辑的一行div。但是您也可以通过这种方式使用.html(),而不必担心全局/非全局变量的范围,并且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!');
    }
});

在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”的标头元素

makeEditable(document.getElementById('myHeader'))

用户现在可以编辑该元素,直到失去焦点。

当更改具有contentEditable属性的元素时,不会触发onchange事件,建议的方法可能是添加按钮以“保存”版本。

检查以这种方式处理问题的此插件:

在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示例

我建立了一个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();

您还可以根据需要删除/添加事件

在Angular 2+

<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 
 }
}


看看这个想法。
http://pastie.org/1096892

我想快了。HTML 5确实需要将change事件添加到规范中。唯一的问题是,在实际在$(this).html()中更新内容之前,回调函数会评估是否(before == $(this).html())。setTimeout不起作用,这很可悲。让我知道你的想法。

基于@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>
本文地址:http://javascript.askforanswer.com/kebianjidebiangengshijian.html
文章标签: ,   ,   ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!