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?


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.


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


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/


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?


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


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).


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



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) */});
}

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.


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

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

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!


21
Rien n'est impossible!
jrharshath
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.