30 votes

Pouvez-vous avoir un déclencheur de hook javascript après les changements d'objet de style d'un élément DOM?

Un élément a un javascript style objet qui contient les noms et les valeurs des styles css. J'aimerais déclencher une fonction à chaque fois que cet objet de modifications sans utilisation de bureaux de vote. Est-il possible de le faire d'une manière qui est compatible avec tous les navigateurs et ne fonctionne de manière fiable avec un code tiers (parce que disons que vous êtes fournissant un script)? La liaison d'un événement javascript comme DOMAttrModified ou DOMSubtreeModified ne suffira pas, car ils ne travaillent pas dans google Chrome.

56voto

Vega Points 44724

Edit 4: Démonstration En Direct

$(function() {
  $('#toggleColor').on('click', function() {
    $(this).toggleClass('darkblue');
  }).attrchange({
    trackValues: true,
    callback: function(event) {
      $(this).html("<ul><li><span>Attribute Name: </span>" + event.attributeName + "</li><li><span>Old Value: </span>" + event.oldValue + "</li><li><span>New Value: </span>" + event.newValue + "</li></ul>");
    }
  });
});
body {
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-size: 12px;
}
#toggleColor {
  height: 70px;
  width: 300px;
  padding: 5px;
  border: 1px solid #c2c2c2;
  background-color: #DBEAF9;
}
#toggleColor span {
  font-weight: bold;
}
#toggleColor.darkblue {
  background-color: #1A9ADA;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://meetselva.github.io/attrchange/javascripts/attrchange.js"></script>
<p>Click below div to toggle class darkblue.</p>
<div id="toggleColor"></div>

Edit 3: j'ai mis tout cela ensemble comme un plugin qui peut être téléchargé à partir de git attrchange et voici la page de démonstration.

Edit 2:

  1. Correctif pour propertName dans IE7 & IE8

Edit 1:

  1. Gérer plusieurs éléments
  2. Commandé les conditions MutationObserver, DOMAttrModified et onpropertychange pour une meilleure mise en œuvre.
  3. Modifié ajouté le Nom de l'Attribut à la fonction de rappel.

Grâce à @benvie pour ses commentaires.

DÉMO: http://jsfiddle.net/zFVyv/10/ (Testé dans FF 12, Chrome 19 et IE 7.)

$(function() {
    (function($) {
        var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;

        function isDOMAttrModifiedSupported() {
            var p = document.createElement('p');
            var flag = false;

            if (p.addEventListener) p.addEventListener('DOMAttrModified', function() {
                flag = true
            }, false);
            else if (p.attachEvent) p.attachEvent('onDOMAttrModified', function() {
                flag = true
            });
            else return false;

            p.setAttribute('id', 'target');

            return flag;
        }

        $.fn.attrchange = function(callback) {
            if (MutationObserver) {
                var options = {
                    subtree: false,
                    attributes: true
                };

                var observer = new MutationObserver(function(mutations) {
                    mutations.forEach(function(e) {
                        callback.call(e.target, e.attributeName);
                    });
                });

                return this.each(function() {
                    observer.observe(this, options);
                });

            } else if (isDOMAttrModifiedSupported()) {
                return this.on('DOMAttrModified', function(e) {
                    callback.call(this, e.attrName);
                });
            } else if ('onpropertychange' in document.body) {
                return this.on('propertychange', function(e) {
                    callback.call(this, window.event.propertyName);
                });
            }
        }
    })(jQuery);

    $('.test').attrchange(function(attrName) {
        alert('Attribute: ' + attrName + ' modified ');
    }).css('height', 100);

});

Ref:

  1. Détecter si DOMAttrModified pris en charge
  2. DOMAttrModified pour chrome
  3. La Mutation De L'Observateur
  4. Pourquoi devrions-nous éviter d'utiliser la Mutation des événements?
  5. onPropertyChange IE

La Mutation des Observateurs est le projet de remplacement de la mutation des événements dans DOM4. Ils devraient être inclus dans Firefox 14 et Chrome 18

Prise En Charge Du Navigateur:

onpropertychange - est pris en charge dans IE (testé sous IE 7)

DOMAttrModified - est pris en charge dans IE 9, FF et Opera

MutationObservers - est très nouveau et il a bien fonctionné dans Chrome 18. Pas certain dans quelle mesure il est pris en charge et encore être testée dans Safari.

Merci @benvie sur l'ajout d'infos sur WebkitMutationObserver

1voto

3p3r Points 1115

EDIT2:

Si vous voulez toujours utiliser mutation observer, l'utilisation de cette bibliothèque: mutation-résumé


EDIT:

Comme je l'ai dit dans ma réponse ci-dessous et grâce à Vega de son commentaire, en utilisant des choses comme object.watch ou mutation observers ne sont pas recommandés pour l'utilisation dans des applications importantes. ce qui est réel citation de MDN:

En général, vous devriez éviter d'utiliser des watch() et unwatch()lorsque possible. Ces deux méthodes sont mises en œuvre uniquement dans Gecko, et ils sont destiné principalement à des fins de débogage utilisation. En outre, à l'aide de points d'observation a un grave impact négatif sur les performances, ce qui est particulièrement vrai lorsqu'il est utilisé sur des objets globaux, tels que la fenêtre. Vous pouvez généralement utiliser les setters et getters ou des procurations à la place. Voir Compatibilité pour plus de détails.

Avertissement

Donc, si la compatibilité inter-navigateur est dans votre liste de contrôle, de Nouveau, je vous suggère fortement de primordial setters et getters de styleobjet.


utiliser object.watch et avoir à l'esprit pour une solution de navigateur:

Vous pouvez remplacer getter et setter méthodes de l'élément style objet trop.

Il y a un plugin jQuery disponibles pour cela, jQuery regarder

1voto

Val Points 7050

J'ai trouvé ce petit plugin qui fait exactement cela et il peut être modifié pour ajouter n'importe quelle mutation que vous souhaitez ... Même scrollHeight change listener.

Le plugin: http://www.jqui.net/jquery-projects/jquery-mutate-official/

voici la démo: http://www.jqui.net/demo/mutate/

0voto

Steve Binder Points 542

Même pour tous les browers les plus modernes, il n'existe aucun moyen multi-navigateur pour y parvenir. Vous devez acheminer tous vos changements de style CSS via une fonction qui pourrait déclencher des écouteurs d'événements. Ce serait la méthode la plus propre.

0voto

o.v. Points 11173

Dans une réponse à une question similaire, il a été suggéré que si vous savez ce style d'établissement des interactions serait effectuée via une interface standard (c'est à dire toujours à l'aide de jQuery, etc.) il a été suggéré que les événements personnalisés être déclenché à chaque fois que la bibliothèque de la méthode est appelée.

Cela permettrait à un plus large soutien de la matrice, mais laisserait tout changement de propriété ignorée si elle est effectuée sans l'aide de la méthode de bibliothèque. Il apparaît également qu'une telle approche n'est pas applicable aux indigènes setters ils ne peuvent pas toujours être invoqué.

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