Détecter les modifications du contenu des éléments avec jQuery

113

change() La fonction fonctionne et détecte les changements sur les éléments du formulaire, mais y a-t-il un moyen de détecter quand le contenu d'un élément DOM a été modifié?

Cela ne fonctionne pas, sauf s'il #contents'agit d'un élément de formulaire

$("#content").change( function(){
    // do something
});

Je veux que cela se déclenche lorsque vous faites quelque chose comme:

$("#content").html('something');

De plus, html()ou la append()fonction n'a pas de rappel.

Aucune suggestion?

Elzo Valugi
la source
vieille question que je connais, mais vérifiez ma réponse pour une solution élégante stackoverflow.com/a/23826615/744975
Andrew Atkinson

Réponses:

26

Ce sont des événements de mutation .

Je n'ai pas utilisé d'API d'événement de mutation dans jQuery, mais une recherche rapide m'a conduit à ce projet sur GitHub. Je ne connais pas la maturité du projet.

jrharshath
la source
17
Ce plugin d'événements de mutation ne fonctionnera pas, car il accroche simplement les événements dans les méthodes de mutation jQuery. Ils sont déclenchés lorsque jQuery lui-même tente de modifier les éléments, mais pas lorsque les éléments sont modifiés de l'extérieur de jQuery. Ils ne surveillent pas les changements sur le document. Découvrez plutôt ce petit plugin: stackoverflow.com/questions/3233991/jquery-watch-div/...
Sebastián Grignoli
10
Rechercher sur Google et publier un lien vers une bibliothèque que vous n'avez jamais essayée n'est pas très utile. (Commentant parce que j'ai été invité à voter.)
Arrêtez de calomnier Monica Cellio
27
Les événements de mutation sont obsolètes ; ne les utilisez pas.
Brock Adams
L'alternative aux événements de mutation semble être MutationObservers .
WoodrowShigeru
69

Je sais que cet article date d'un an, mais j'aimerais proposer une approche de solution différente à ceux qui ont un problème similaire:

  1. L'événement de modification jQuery est utilisé uniquement sur les champs d'entrée utilisateur car si quelque chose d'autre est manipulé (par exemple, un div), cette manipulation provient du code. Alors, trouvez où la manipulation a lieu, puis ajoutez tout ce dont vous avez besoin.

  2. Mais si ce n'est pas possible pour une raison quelconque (vous utilisez un plugin compliqué ou ne trouvez aucune possibilité de "rappel"), alors l'approche jQuery que je suggérerais est:

    une. Pour une manipulation simple du DOM, utilisez le chaînage et le parcours jQuery,$("#content").html('something').end().find(whatever)....

    b. Si vous souhaitez faire autre chose, utilisez jQuery bindavec un événement personnalisé ettriggerHandler

    $("#content").html('something').triggerHandler('customAction');
    
    $('#content').unbind().bind('customAction', function(event, data) {
       //Custom-action
    });
    

Voici un lien vers le gestionnaire de déclencheurs jQuery: http://api.jquery.com/triggerHandler/

Kyle
la source
1
pensée finale. bien que cela devrait être assez complet ci-dessus: vous pouvez mettre à jour la valeur d'un champ de saisie masqué avec celle du #content html, puis lier l'événement de modification au champ de saisie masqué :) beaucoup d'options
Kyle
7
+1 "Trouvez où la manipulation a lieu, puis ajoutez-y ce dont vous avez besoin." Correction de mon problème en 2 secondes sans aucun hacks / plugins :)
Hartley Brody
Le seul changement que je suggère ici est que l' bindattend votre gestionnaire de renvoyer un fichier bool.
Serj Sagan
15

Le navigateur ne déclenchera pas l'événement onchange pour les <div>éléments.

Je pense que le raisonnement derrière cela est que ces éléments ne changeront pas à moins qu'ils ne soient modifiés par javascript. Si vous devez déjà modifier l'élément vous-même (plutôt que l'utilisateur qui le fait), vous pouvez simplement appeler le code d'accompagnement approprié en même temps que vous modifiez l'élément, comme ceci:

 $("#content").html('something').each(function() { });

Vous pouvez également déclencher manuellement un événement comme celui-ci:

 $("#content").html('something').change();

Si aucune de ces solutions ne convient à votre situation, pourriez-vous s'il vous plaît donner plus d'informations sur ce que vous essayez d'accomplir spécifiquement?

TM.
la source
11
Cela suppose que vous avez écrit tous les javascript, ce qui peut ne pas être le cas.
Myster
MERCI!!!! Cela m'a aidé à résoudre un problème que je fixais depuis 6 heures.
Jordan Parmer
Exactement ce dont j'avais besoin.
smac89
15

qu'en est-il de http://jsbin.com/esepal/2

$(document).bind("DOMSubtreeModified",function(){
  console.log($('body').width() + ' x '+$('body').height());
})

Cet événement est obsolète au profit de l' API Mutation Observer

FDisk
la source
1
ce n'est pas une mauvaise idée, même si je me demande quel est son soutien. developer.mozilla.org/en/DOM/DOM_event_reference/…
Elzo Valugi
Comment surveillez-vous un élément spécifique pour les changements? Actuellement, le document surveille toute la page.
Patoshi パ ト シ
3

Ce n'est pas strictement une réponse jQuery - mais utile à mentionner pour le débogage.

Dans Firebug, vous pouvez cliquer avec le bouton droit de la souris sur un élément de l'arborescence DOM et configurer 'Break on Attribute Change':

Cliquez avec le bouton droit de la souris sur l'élément dans Firebug avec pause lors du changement d'attribut en surbrillance

Lorsqu'un attribut est modifié dans un script, la fenêtre de débogage apparaît et vous pouvez suivre ce qui se passe. Il existe également une option pour l'insertion et la suppression d'éléments ci-dessous (masquée inutilement par la fenêtre contextuelle dans la capture d'écran).

John Reid
la source
1
C'est utile, mais pas exactement ce qu'il demandait. Cela détectera des choses comme quand une classe change, ou quand un attribut de style est ajouté ou changé. Il ne vérifie pas quand le contenu à l'intérieur du nœud change. Par exemple, si un javascript quelque part change un nœud de <span> bonjour </span> à <span> Monde </span>, cela ne le détectera pas
Joshua Soileau
2

Je développe une petite bibliothèque JS appelée mutabor ( https://github.com/eskat0n/mutabor ) qui vise à simplifier l'utilisation des événements de mutation DOM. Voir demo.html pour des exemples.

Eskat0n
la source
1

Souvent, un moyen simple et efficace pour y parvenir est de savoir quand et où vous modifiez le DOM.

Vous pouvez le faire en créant une fonction centrale qui est toujours responsable de la modification du DOM. Vous effectuez ensuite le nettoyage dont vous avez besoin sur l'élément modifié à partir de cette fonction.

Dans une application récente, je n'avais pas besoin d'action immédiate, j'ai donc utilisé un rappel pour la fonction handly load (), pour ajouter une classe à tous les éléments modifiés, puis mis à jour tous les éléments modifiés toutes les quelques secondes avec une minuterie setInterval.

$($location).load("my URL", "", $location.addClass("dommodified"));

Ensuite, vous pouvez le gérer comme vous le souhaitez - par exemple

setInterval("handlemodifiedstuff();", 3000); 
function handlemodifiedstuff()
{
    $(".dommodified").each(function(){/* Do stuff with $(this) */});
}
Antoine Carthy
la source
3
Cela suppose que vous avez écrit tous les javascript, ce qui peut ne pas être le cas.
Myster
1

Vous pouvez ajouter une option de rappel à la fonction html (ou toute autre):

$.fn.oldHtml = $.fn.html;
$.fn.html = function(html,fn){
  fn = fn || function(){};
  var result =  this.oldHtml(html);
  fn();
  return result;
};
$('body').html(11,function(){alert("haha");});

Démo ici.

Vous faites le changement sur un élément, pas l'élément est forcé de changer par quelque chose que vous devez attraper.


la source
J'ai dû résoudre ce problème aujourd'hui. Je n'ai pas pu modifier le code qui s'appelait en fait html () car il se trouve dans une bibliothèque tierce. Une version modifiée de ceci était parfaite pour moi. J'ai fait ceci: $ .fn.oldHtml = $ .fn.html (); $ .fn.html = function (e) {var result = this.oldHtml (e); this.trigger ('afterHtmlChange', e);} Maintenant, je peux lier tous les événements que je veux à l'événement afterHtmlChange nouvellement créé sur n'importe quel élément, qui se déclenchera chaque fois que quelque chose appellera html () fn de jQuery.
Daniel Howard
Oups, petite erreur. Fn dans mon commentaire ci-dessus devrait être: function (e) {var result = this.oldHtml (e); this.trigger ('afterHtmlChange', e); return result;}
Daniel Howard
0

J'ai écrit un extrait qui vérifiera la modification d'un élément sur un événement.

Donc, si vous utilisez un code javascript tiers ou quelque chose du genre et que vous avez besoin de savoir quand quelque chose apparaît ou change lorsque vous avez cliqué, vous le pouvez.

Pour l'extrait ci-dessous, disons que vous devez savoir quand le contenu d'un tableau change après avoir cliqué sur un bouton.

$('.button').live('click', function() {

            var tableHtml = $('#table > tbody').html();
            var timeout = window.setInterval(function(){

                if (tableHtml != $('#table > tbody').
                    console.log('no change');
                } else {
                    console.log('table changed!');
                    clearInterval(timeout);
                }

            }, 10);
        });

Pseudo code:

  • Une fois que vous cliquez sur un bouton
  • le html de l'élément que vous vous attendez à changer est capturé
  • on vérifie ensuite continuellement le html de l'élément
  • quand on trouve que le html est différent on arrête la vérification
Andrew Atkinson
la source
0

Nous pouvons y parvenir en utilisant les événements de mutation . Selon www.w3.org, le module d'événement de mutation est conçu pour permettre la notification de tout changement dans la structure d'un document, y compris les modifications d'attr et de texte. Pour plus de détails ÉVÉNEMENTS DE MUTATION

Par exemple :

$("body").on('DOMSubtreeModified', "#content", function() {
    alert('Content Modified'); // do something
});
Sanchit Gupta
la source
Ceci est obsolète depuis un certain temps. On devrait utiliser Mutation Observers (même concept)
Carles Alcolea
-3

Pas possible, je crois que c'est-à-dire a un événement de contenu modifié mais ce n'est certainement pas x-browser

Dois-je dire pas possible sans un mauvais intervalle en arrière-plan!

carré rouge
la source
21
Rien n'est impossible!
jrharshath