web-dev-qa-db-fra.com

événement de déclenchement lors du changement d'attribut DOM

existe-t-il un moyen de déclencher un événement (peut être personnalisé) lors d'un changement d'attribut?

Disons, quand IMG src est changé ou le innerHtml de DIV?

62
ts.

Remarque: depuis 2012, les événements de mutation ont été supprimés de la norme et sont désormais obsolètes. Voir d'autres réponses ou documentation pour savoir comment utiliser leur remplacement, MutationObserver .

Vous faites référence à Événements de mutation DOM . La prise en charge du navigateur est médiocre (mais en amélioration) pour ces événements. le plugin Mutation Events pour jQuery pourrait vous aider.

51
Dean Burge

Comment configurer un MutationObserver, principalement copié de MDN mais j'ai ajouté mes propres commentaires pour plus de clarté.

window.MutationObserver = window.MutationObserver
    || window.WebKitMutationObserver
    || window.MozMutationObserver;
// Find the element that you want to "watch"
var target = document.querySelector('img'),
// create an observer instance
observer = new MutationObserver(function(mutation) {
     /** this is the callback where you
         do what you need to do.
         The argument is an array of MutationRecords where the affected attribute is
         named "attributeName". There is a few other properties in a record
         but I'll let you work it out yourself.
      **/
}),
// configuration of the observer:
config = {
    attributes: true // this is to watch for attribute changes.
};
// pass in the element you wanna watch as well as the options
observer.observe(target, config);
// later, you can stop observing
// observer.disconnect();

J'espère que cela t'aides.

39
Mats

Si vous n'avez besoin que de quelque chose de spécifique, une simple setInterval() fonctionnera, en vérifiant les attributs cibles toutes les quelques millisecondes:

var imgSrc = null;
setInterval(function () {
   var newImgSrc = $("#myImg").attr("src");
   if (newImgSrc !== imgSrc) {
      imgSrc = newImgSrc;
      $("#myImg").trigger("srcChange");
   }
}, 50);

Liez ensuite à l'événement "srcChange" personnalisé:

$("#myImg").bind("srcChange", function () {....});
5
David Tang

Il n'y a pas d'événement natif modifié par dom auquel vous pouvez vous connecter.

Bon article ici qui essaie de fournir une solution sous la forme d'un plugin jquery.

Code de l'article

$.fn.watch = function(props, callback, timeout){
    if(!timeout)
        timeout = 10;
    return this.each(function(){
        var el      = $(this),
            func    = function(){ __check.call(this, el) },
            data    = { props:  props.split(","),
                        func:   callback,
                        vals:   [] };
        $.each(data.props, function(i) {
              data.vals[i] = el.css(data.props[i]); 
        });
        el.data(data);
        if (typeof (this.onpropertychange) == "object"){
            el.bind("propertychange", callback);
        } else if ($.browser.mozilla){
            el.bind("DOMAttrModified", callback);
        } else {
            setInterval(func, timeout);
        }
    });
    function __check(el) {
        var data    = el.data(),
            changed = false,
            temp    = "";
        for(var i=0;i < data.props.length; i++) {
            temp = el.css(data.props[i]);
            if(data.vals[i] != temp){
                data.vals[i] = temp;
                changed = true;
                break;
            }
        }
        if(changed && data.func) {
            data.func.call(el, data);
        }
    } }
4
redsquare

En plus de réponse de Mats inspiré par tilisation de l'exemple MutationObserver de MDN :

Si vos options contiennent <property>: true et vous envisagez de modifier cette propriété de target inside MutationObserver's callback function, use the following to prevent recursive calls - until script timeout , débordement de pile ou similaire:

...
// Used to prevent recursive calls of observer's callback function
// From https://stackoverflow.com/questions/4561845/firing-event-on-dom-attribute-change
let insideInitialObserverCallback = false

let callback = function(mutationsList) {
    insideInitialObserverCallback = ! insideInitialObserverCallback
    if ( insideInitialObserverCallback ) {

        // ... change target's given property ...       

    }
})

let observer = new MutationObserver(callback);
...
0
Gerold Broser