Wykrywaj zmiany zawartości elementu za pomocą jQuery

113

change() funkcja działa i wykrywa zmiany w elementach formularza, ale czy istnieje sposób na wykrycie, kiedy zawartość elementu DOM została zmieniona?

To nie działa, chyba że #contentjest elementem formularza

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

Chcę, aby to się uruchamiało, gdy robię coś takiego:

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

Również funkcja html()lub append()nie ma wywołania zwrotnego.

Jakieś sugestie?

Elzo Valugi
źródło
stare pytanie, które znam, ale sprawdź moją odpowiedź na eleganckie rozwiązanie stackoverflow.com/a/23826615/744975
Andrew Atkinson

Odpowiedzi:

26

To są zdarzenia mutacji .

Nie korzystałem z interfejsów API zdarzeń mutacji w jQuery, ale pobieżne wyszukiwanie doprowadziło mnie do tego projektu na GitHub. Nie jestem świadomy dojrzałości projektu.

jrharshath
źródło
17
Ta wtyczka zdarzeń mutacji nie będzie działać, ponieważ po prostu podpina zdarzenia do metod mutacji jQuery. Są uruchamiane, gdy samo jQuery próbuje zmienić elementy, ale nie, gdy elementy są zmieniane z zewnątrz jQuery. Nie obserwują zmian w dokumencie. Zamiast tego sprawdź tę małą wtyczkę: stackoverflow.com/questions/3233991/jquery-watch-div/ ...
Sebastián Grignoli
10
Wyszukiwanie w Google i publikowanie linku do biblioteki, której nigdy nie próbowałeś, nie jest zbyt przydatne. (Komentując, ponieważ zostałem poproszony o oddanie głosu).
Przestań oczerniać Monikę Cellio.
27
Zdarzenia mutacji są przestarzałe ; nie używaj ich.
Brock Adams
Wydaje się, że alternatywą dla zdarzeń mutacji są MutationObservers .
WoodrowShigeru
69

Wiem, że ten post ma rok, ale chciałbym przedstawić inne podejście do rozwiązania tym, którzy mają podobny problem:

  1. Zdarzenie zmiany jQuery jest używane tylko w polach wejściowych użytkownika, ponieważ jeśli coś innego jest manipulowane (np. Div), ta manipulacja pochodzi z kodu. Więc znajdź miejsce manipulacji, a następnie dodaj tam wszystko, czego potrzebujesz.

  2. Ale jeśli z jakiegoś powodu nie jest to możliwe (używasz skomplikowanej wtyczki lub nie możesz znaleźć żadnych możliwości „wywołania zwrotnego”), proponuję podejście jQuery:

    za. W celu prostej manipulacji DOM użyj łańcucha jQuery i przechodzenia przez$("#content").html('something').end().find(whatever)....

    b. Jeśli chcesz zrobić coś innego, użyj jQuery bindz niestandardowym zdarzeniem itriggerHandler

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

Oto link do modułu obsługi wyzwalacza jQuery: http://api.jquery.com/triggerHandler/

Kyle
źródło
1
końcowa myśl. chociaż to powinno być dość obszerne powyżej: możesz zaktualizować wartość ukrytego pola wejściowego z wartością z #content html, a następnie powiązać zdarzenie zmiany z ukrytym polem wejściowym :) wiele opcji
Kyle
7
+1 „Znajdź miejsce manipulacji, a następnie dodaj tam wszystko, czego potrzebujesz”. Naprawiono mój problem w 2 sekundy bez żadnych hacków / wtyczek :)
Hartley Brody
Jedyną zmianą, którą tutaj proponuję, jest to, że program bindoczekuje, że program zwróci plik bool.
Serj Sagan
15

Przeglądarka nie uruchomi zdarzenia onchange dla <div>elementów.

Myślę, że powodem tego jest to, że te elementy nie zmienią się, chyba że zostaną zmodyfikowane przez JavaScript. Jeśli już musisz zmodyfikować element samodzielnie (a nie robiąc to przez użytkownika), możesz po prostu wywołać odpowiedni kod towarzyszący w tym samym czasie, gdy modyfikujesz element, na przykład:

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

Możesz też ręcznie uruchomić takie zdarzenie:

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

Jeśli żadne z tych rozwiązań nie działa w Twojej sytuacji, czy możesz podać więcej informacji na temat tego, co konkretnie próbujesz osiągnąć?

TM.
źródło
11
Zakłada się, że napisałeś cały skrypt javascript, co może nie mieć miejsca.
Myster
DZIĘKUJĘ CI!!!! To właśnie pomogło mi rozwiązać problem, na który patrzyłem przez 6 godzin.
Jordan Parmer
Dokładnie to, czego potrzebowałem.
smac89
15

a co z http://jsbin.com/esepal/2

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

To zdarzenie zostało wycofane na korzyść interfejsu Mutation Observer API

FDisk
źródło
1
niezły pomysł, chociaż zastanawiam się, jakie ma wsparcie. developer.mozilla.org/en/DOM/DOM_event_reference/…
Elzo Valugi
Jak monitorujesz zmiany w konkretnym elemencie? Obecnie dokument monitoruje całą stronę.
Patoshi パ ト シ
3

Nie jest to wyłącznie odpowiedź jQuery - ale warto o niej wspomnieć przy debugowaniu.

W Firebug możesz kliknąć prawym przyciskiem myszy element w drzewie DOM i ustawić „Przerwij przy zmianie atrybutu”:

Kliknij prawym przyciskiem myszy w Firebug z podświetlonym Przerwij przy zmianie atrybutu

Kiedy atrybut zostanie zmieniony w skrypcie, pojawi się okno debugowania i możesz śledzić, co się dzieje. Istnieje również opcja wstawiania i usuwania elementu poniżej (nieprzydatna zasłonięta przez wyskakujące okienko w screengrab).

John Reid
źródło
1
Jest to pomocne, ale nie jest to dokładnie to, o co prosił. To wykryje takie rzeczy, jak zmiana klasy lub dodanie lub zmiana atrybutu stylu. Nie sprawdza, kiedy zmienia się zawartość wewnątrz węzła. Na przykład, jeśli jakiś skrypt javascript gdzieś zmieni węzeł z <span> witaj </span> na <span> świat </span>, to go nie wykryje
Joshua Soileau
2

Tworzę maleńką bibliotekę JS o nazwie mutabor ( https://github.com/eskat0n/mutabor ), która ma na celu uproszczenie korzystania z DOM Mutation Events. Przykłady można znaleźć na demo.html.

Eskat0n
źródło
1

Często prostym i skutecznym sposobem osiągnięcia tego jest śledzenie, kiedy i gdzie modyfikujesz DOM.

Możesz to zrobić, tworząc jedną centralną funkcję, która jest zawsze odpowiedzialna za modyfikowanie DOM. Następnie wykonujesz dowolne czyszczenie zmodyfikowanego elementu z poziomu tej funkcji.

W niedawnej aplikacji nie potrzebowałem natychmiastowej akcji, więc użyłem wywołania zwrotnego dla funkcji handly load (), aby dodać klasę do dowolnych zmodyfikowanych elementów, a następnie aktualizowałem wszystkie zmodyfikowane elementy co kilka sekund za pomocą timera setInterval.

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

Wtedy możesz sobie z tym poradzić, jak chcesz - np

setInterval("handlemodifiedstuff();", 3000); 
function handlemodifiedstuff()
{
    $(".dommodified").each(function(){/* Do stuff with $(this) */});
}
Antony Carthy
źródło
3
Zakłada się, że napisałeś cały skrypt javascript, co może nie mieć miejsca.
Myster
1

Możesz dodać opcję wywołania zwrotnego do funkcji html (lub dowolnej):

$.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 tutaj.

Dokonujesz zmiany na jakimś elemencie, a nie element jest zmuszony do zmiany przez coś, co musisz złapać.


źródło
Musiałem dziś rozwiązać ten problem. Nie mogłem edytować kodu, który faktycznie nazywa się html (), ponieważ znajduje się w bibliotece innej firmy. Zmodyfikowana wersja tego była dla mnie idealna. Zrobiłem to: $ .fn.oldHtml = $ .fn.html (); $ .fn.html = function (e) {var result = this.oldHtml (e); this.trigger ('afterHtmlChange', e);} Teraz mogę powiązać dowolne zdarzenia, które chcę, z nowo utworzonym zdarzeniem afterHtmlChange na dowolnym elemencie, które będzie uruchamiane, gdy cokolwiek wywoła funkcję html () fn jQuery.
Daniel Howard,
Ups, mały błąd. Fn w moim komentarzu powyżej powinno brzmieć: function (e) {var result = this.oldHtml (e); this.trigger ('afterHtmlChange', e); return result;}
Daniel Howard
0

Napisałem fragment, który sprawdzi zmianę elementu w wydarzeniu.

Więc jeśli używasz kodu javascript innej firmy lub czegoś w tym rodzaju i chcesz wiedzieć, kiedy coś się pojawi lub zmieni po kliknięciu, możesz.

W poniższym fragmencie powiedzmy, że musisz wiedzieć, kiedy zawartość tabeli zmienia się po kliknięciu przycisku.

$('.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 kod:

  • Po kliknięciu przycisku
  • przechwytywany jest kod HTML elementu, który chcesz zmienić
  • następnie nieustannie sprawdzamy kod HTML elementu
  • gdy stwierdzimy, że kod HTML jest inny, przerywamy sprawdzanie
Andrew Atkinson
źródło
0

Możemy to osiągnąć za pomocą Mutation Events . Według www.w3.org, moduł zdarzeń mutacji ma na celu umożliwienie powiadamiania o wszelkich zmianach w strukturze dokumentu, w tym o modyfikacjach atr i tekstu. Więcej szczegółów na temat WYDARZEŃ MUTACJI

Na przykład :

$("body").on('DOMSubtreeModified', "#content", function() {
    alert('Content Modified'); // do something
});
Sanchit Gupta
źródło
Od jakiegoś czasu jest to przestarzałe. Należy użyć obserwatorów mutacji (ta sama koncepcja)
Carles Alcolea
-3

Niemożliwe, myślę, że np. Zmieniło się zdarzenie, ale z pewnością nie jest to przeglądarka x

Powinienem powiedzieć, że nie jest to możliwe bez nieprzyjemnych przerw w tle!

plac Czerwony
źródło
21
Nie ma rzeczy niemożliwych!
jrharshath