38 votes

Surveiller les changements de DOM, la manière élégante

J'ai besoin de surveiller un changement d'attribut sur n'importe lequel des enfants d'un élément DOM spécifique. Jusqu'à présent, j'ai utilisé événements de mutation .

Le problème était qu'ils étaient bogués : par exemple sous Chromium, DOMAttrModified n'a pas été renvoyé mais DOMSubtreeModified était. Le problème était facile à résoudre : car selon la spécification, DOMSubtreeModified est déclenché si l'un des autres événements est déclenché, donc j'ai juste écouté les événements suivants DOMSubtreeModified .

Quoi qu'il en soit, Chromium, dans les versions récentes, a cessé de déclencher quoi que ce soit si un attribut a été modifié.

Le nouveau API de l'observateur de mutations Cependant, il fonctionne parfaitement.

Jusqu'à présent, je n'avais besoin de déclencher une fonction de rappel qu'en cas de modification du sous-arbre d'un élément spécifique - tout simplement parce que rien d'autre n'était censé changer - j'ai donc résolu mon problème en utilisant simplement les événements de mutation et l'observateur de mutation (lorsqu'il est disponible) dans le même morceau de code.

Cependant, j'ai maintenant besoin d'effectuer un filtrage plus puissant des événements (par exemple, sur un nouveau nœud, sur un nœud supprimé). une bibliothèque, éventuellement un plug-in jQuery qui me permettrait d'utiliser élégamment les deux de ces API - MutationObserver si disponible et les événements de mutation comme solution de rechange, avec la possibilité de filtrer pour des types d'événements spécifiques (par exemple, élément ajouté, attribut modifié).

Par exemple

$("#test").watch({onNewElement: 1}, function(newElement){})
$("#test").watch({onNewAttribute: 1}, function(modifiedElement) {})

Ou sans jQuery

watchChanges("#test", {onNewElement: 1}, function(newElement){})
watchChanges("#test", {onNewAttribute: 1}, function(modifiedElement){})

2voto

Coffee Bite Points 1284

Est-ce que ça marcherait ?

http://darcyclarke.me/development/detect-attribute-changes-with-jquery/

$.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);
        }
    }
}

2voto

FloHimself Points 151

Pour une surveillance efficace du DOM à l'aide de jQuery, vous pouvez jeter un coup d'œil à l'application Plugin jQuery Behavior (Disclaimer : Je suis l'auteur) qui utilise une version optimisée de Requête en direct . Je l'utilise dans plusieurs produits depuis 3 ans maintenant, sans aucun problème.

Edit : L'écoute des changements d'attributs fonctionnerait comme ceci :

$.behavior({
    'div:first': {
        'changeAttr': function (event, data) {
            console.log('Attribute "' +  data.attribute + '" changed from "' + data.from + '" to "' + data.to + '"');
        }
    }
});

$('div:first').attr('foo', 'bar');

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X