Erkennen Sie Änderungen des Elementinhalts mit jQuery


113

change() Die Funktion funktioniert und erkennt Änderungen an Formularelementen. Gibt es jedoch eine Möglichkeit zu erkennen, wann der Inhalt eines DOM-Elements geändert wurde?

Dies funktioniert nur, wenn #contentes sich um ein Formularelement handelt

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

Ich möchte, dass dies ausgelöst wird, wenn Folgendes ausgeführt wird:

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

Auch html()oder append()Funktion haben keinen Rückruf.

Irgendwelche Vorschläge?


alte Frage, die ich kenne, aber überprüfen Sie meine Antwort für eine elegante Lösung stackoverflow.com/a/23826615/744975
Andrew Atkinson

Antworten:


26

Dies sind Mutationsereignisse .

Ich habe in jQuery keine Mutationsereignis-APIs verwendet, aber eine flüchtige Suche führte mich zu diesem Projekt auf GitHub. Ich bin mir der Reife des Projekts nicht bewusst.


17
Dieses Plugin für Mutationsereignisse funktioniert nicht, da es die Ereignisse nur in die jQuery-Mutationsmethoden einbindet. Sie werden ausgelöst, wenn jQuery selbst versucht, die Elemente zu ändern, jedoch nicht, wenn die Elemente von außerhalb von jQuery geändert werden. Sie beobachten keine Änderungen am Dokument. Schauen Sie sich stattdessen dieses kleine Plugin an: stackoverflow.com/questions/3233991/jquery-watch-div/…
Sebastián Grignoli

10
Das Googeln und Veröffentlichen eines Links zu einer Bibliothek, die Sie noch nie ausprobiert haben, ist nicht besonders nützlich. (Kommentar, weil ich beim Downvoting dazu aufgefordert wurde.)
Hören Sie auf, Monica Cellio

27

Die Alternative zu Mutationsereignissen scheinen MutationObservers zu sein .
WoodrowShigeru

69

Ich weiß, dass dieser Beitrag ein Jahr alt ist, aber ich möchte denjenigen, die ein ähnliches Problem haben, einen anderen Lösungsansatz bieten:

  1. Das jQuery-Änderungsereignis wird nur für Benutzereingabefelder verwendet, da diese Manipulation von Code stammt, wenn etwas anderes manipuliert wird (z. B. ein Div). Finden Sie also heraus, wo die Manipulation stattfindet, und fügen Sie dort alles hinzu, was Sie benötigen.

  2. Aber wenn dies aus irgendeinem Grund nicht möglich ist (Sie verwenden ein kompliziertes Plugin oder finden keine "Rückruf" -Möglichkeiten), würde ich den jQuery-Ansatz vorschlagen:

    ein. Verwenden Sie für eine einfache DOM-Manipulation die jQuery-Verkettung und -Überquerung.$("#content").html('something').end().find(whatever)....

    b. Wenn Sie etwas anderes tun möchten, setzen Sie jQuery's bindmit benutzerdefiniertem Ereignis und eintriggerHandler

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

Hier ist ein Link zum jQuery-Trigger-Handler: http://api.jquery.com/triggerHandler/


1
letzter Gedanke. obwohl das oben ziemlich umfassend sein sollte: Sie könnten den Wert eines versteckten Eingabefeldes mit dem des #content-HTML aktualisieren und dann das Änderungsereignis an das versteckte Eingabefeld binden :) viele Optionen
Kyle

7
+1 "Finden Sie heraus, wo die Manipulation stattfindet, und fügen Sie dort alles hinzu, was Sie brauchen." Behoben mein Problem in 2 Sekunden ohne Hacks / Plugins :)
Hartley Brody

Die einzige Änderung, die ich hier vorschlage, ist, dass der binderwartet, dass Ihr Handler a zurückgibt bool.
Serj Sagan

15

Der Browser löst das Ereignis onchange für <div>Elemente nicht aus.

Ich denke, der Grund dafür ist, dass sich diese Elemente nur ändern, wenn sie durch Javascript geändert werden. Wenn Sie das Element bereits selbst ändern müssen (und nicht vom Benutzer), können Sie einfach den entsprechenden Begleitcode aufrufen, während Sie das Element ändern, wie folgt:

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

Sie können ein Ereignis wie dieses auch manuell auslösen:

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

Wenn keine dieser Lösungen für Ihre Situation geeignet ist, können Sie bitte weitere Informationen darüber geben, was Sie speziell erreichen möchten?


11
Dies setzt voraus, dass Sie das gesamte Javascript geschrieben haben, was möglicherweise nicht der Fall ist.
Myster

DANKE!!!! Dies half mir nur, ein Problem zu lösen, auf das ich 6 Stunden lang gestarrt hatte.
Jordan Parmer

Genau das, was ich brauchte.
smac89

15

Was ist mit http://jsbin.com/esepal/2?

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

Dieses Ereignis wurde zugunsten der Mutation Observer-API abgelehnt


1
Keine schlechte Idee, obwohl ich mich frage, wie viel Unterstützung es hat. developer.mozilla.org/en/DOM/DOM_event_reference/…
Elzo Valugi

Wie überwachen Sie ein bestimmtes Element auf Änderungen? Derzeit überwacht das Dokument die gesamte Seite.
Patoshi




3

Es ist nicht unbedingt eine jQuery-Antwort - aber nützlich, um sie beim Debuggen zu erwähnen.

In Firebug können Sie mit der rechten Maustaste auf ein Element in der DOM-Struktur klicken und "Bei Attributänderung unterbrechen" einrichten:

Element Rechtsklick in Firebug mit hervorgehobener Unterbrechung bei Attributänderung

Wenn ein Attribut in einem Skript geändert wird, wird das Debug-Fenster angezeigt und Sie können nachverfolgen, was gerade passiert. Im Folgenden finden Sie auch eine Option zum Einfügen und Entfernen von Elementen (die durch das Popup im Bildschirmgrab nicht hilfreich verdeckt wird).


1
Das ist hilfreich, aber nicht genau das, wonach er gefragt hat. Dadurch werden Dinge erkannt, z. B. wenn sich eine Klasse ändert oder wenn ein Stilattribut hinzugefügt oder geändert wird. Es wird nicht überprüft, wann sich der Inhalt im Inneren des Knotens ändert. Wenn beispielsweise ein Javascript irgendwo einen Knoten von <span> Hallo </ span> in <span> World </ span> ändert, wird dies nicht
Joshua Soileau



1

Eine einfache und effektive Möglichkeit, dies zu erreichen, besteht häufig darin, zu verfolgen, wann und wo Sie das DOM ändern.

Sie können dies tun, indem Sie eine zentrale Funktion erstellen, die immer für die Änderung des DOM verantwortlich ist. Innerhalb dieser Funktion führen Sie dann alle erforderlichen Bereinigungen für das geänderte Element durch.

In einer neueren Anwendung war keine sofortige Aktion erforderlich, daher habe ich einen Rückruf für die Funktion handly load () verwendet, um geänderten Elementen eine Klasse hinzuzufügen, und dann alle geänderten Elemente alle paar Sekunden mit einem setInterval-Timer aktualisiert.

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

Dann können Sie damit umgehen, wie Sie wollen - z

setInterval("handlemodifiedstuff();", 3000); 
function handlemodifiedstuff()
{
    $(".dommodified").each(function(){/* Do stuff with $(this) */});
}

3
Dies setzt voraus, dass Sie das gesamte Javascript geschrieben haben, was möglicherweise nicht der Fall ist.
Myster

1

Sie können der HTML-Funktion (oder einer beliebigen Funktion) eine Rückrufoption hinzufügen:

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

Demo hier.

Sie nehmen die Änderung an einem Element vor, nicht das Element muss sich durch etwas ändern, das Sie abfangen müssen.


Ich musste dieses Problem heute lösen. Ich konnte den Code mit dem Namen html () nicht bearbeiten, da er sich in einer Bibliothek eines Drittanbieters befindet. Eine modifizierte Version davon war perfekt für mich. Ich habe dies getan: $ .fn.oldHtml = $ .fn.html (); $ .fn.html = Funktion (e) {var result = this.oldHtml (e); this.trigger ('afterHtmlChange', e);} Jetzt kann ich alle gewünschten Ereignisse an das neu erstellte afterHtmlChange-Ereignis für jedes Element binden, das ausgelöst wird, wenn etwas jQuerys html () fn aufruft.
Daniel Howard

Hoppla, kleiner Fehler. Fn in meinem obigen Kommentar sollte lauten: function (e) {var result = this.oldHtml (e); this.trigger ('afterHtmlChange', e); Ergebnis zurückgeben;}
Daniel Howard

0

Ich habe ein Snippet geschrieben, das die Änderung eines Elements in einem Ereignis überprüft.

Wenn Sie also Javascript-Code von Drittanbietern oder ähnliches verwenden und wissen müssen, wann etwas angezeigt wird oder sich ändert, wenn Sie darauf geklickt haben, können Sie dies tun.

Angenommen, Sie müssen für das folgende Snippet wissen, wann sich der Inhalt einer Tabelle ändert, nachdem Sie auf eine Schaltfläche geklickt haben.

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

Pseudocode:

  • Sobald Sie auf eine Schaltfläche klicken
  • Das HTML des Elements, dessen Änderung Sie erwarten, wird erfasst
  • Wir überprüfen dann kontinuierlich das HTML des Elements
  • Wenn wir feststellen, dass das HTML anders ist, beenden wir die Überprüfung

0

Wir können dies erreichen, indem wir Mutationsereignisse verwenden . Laut www.w3.org soll das Mutationsereignismodul die Benachrichtigung über Änderungen an der Struktur eines Dokuments ermöglichen, einschließlich Änderungen von Attributen und Texten. Für mehr Details MUTATION EVENTS

Zum Beispiel :

$("body").on('DOMSubtreeModified', "#content", function() {
    alert('Content Modified'); // do something
});

Dies ist seit einiger Zeit veraltet. Man sollte Mutation Observers verwenden (gleiches Konzept)
Carles Alcolea

-3

Nicht möglich, ich glaube dh hat ein inhaltsverändertes Ereignis, aber es ist sicherlich kein X-Browser

Sollte ich sagen, nicht möglich, ohne dass ein böses Intervall im Hintergrund tuckert!


21
nichts ist unmöglich!
Jrharshath
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.