Czy istnieje JavaScript / jQuery dom change listener?

Zasadniczo chcę, aby skrypt został uruchomiony, gdy zmieni się zawartość DIV. Ponieważ skrypty są oddzielne (content script in chrome extension & webpage script), potrzebuję sposobu na obserwowanie zmian w stanie DOM. Mogę ustawić sondaże, ale to wygląda niechlujnie.

Author: Xan, 2010-05-16

5 answers

Kilka lat później, teraz jest oficjalnie lepsze rozwiązanie. obserwatorzy mutacji DOM4 zastępują przestarzałe zdarzenia mutacji DOM3. Są one obecnie zaimplementowane w nowoczesnych przeglądarkach jako MutationObserver (lub jako prefiks dostawcy WebKitMutationObserver w starych wersjach Chrome):

MutationObserver = window.MutationObserver || window.WebKitMutationObserver;

var observer = new MutationObserver(function(mutations, observer) {
    // fired when a mutation occurs
    console.log(mutations, observer);
    // ...
});

// define what element should be observed by the observer
// and what types of mutations trigger the callback
observer.observe(document, {
  subtree: true,
  attributes: true
  //...
});

Ten przykład nasłuchuje zmian DOM na document i jego całym poddrzewie, i odpali zmiany atrybutów elementu, jak również zmiany strukturalne. Projekt spec ma pełną lista prawidłowych właściwości mutacji :

ChildList

  • ustawić na true, jeśli mają być obserwowane mutacje u dzieci docelowych.

Atrybuty

  • ustawione na true, jeśli mają być obserwowane mutacje atrybutów celu.

CharacterData

  • ustawić na true, jeśli mają być obserwowane mutacje w danych celu.

Subtree

  • ustawić na {[4] } Jeśli mutacje nie tylko cel, ale także potomków cel mają być obserwowane.

AttributeOldValue

  • ustawione na true Jeśli attributes jest ustawione na true i wartość atrybutu target przed koniecznością zarejestrowania mutacji.

CharacterDataOldValue

  • ustawione na true Jeśli characterData jest ustawione na true i dane target przed potrzebą mutacji do nagrania.

AttributeFilter

  • Ustawia listę nazw lokalnych atrybutów (bez przestrzeni nazw), jeśli nie wszystkie mutacje atrybutów muszą być obserwowane.

(Ta lista jest aktualna od kwietnia 2014; można sprawdzić specyfikację dla wszelkich zmian.)

 403
Author: apsillers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-20 14:03:00

Edit

Ta odpowiedź jest teraz przestarzała. Zobacz odpowiedź apsillers .

Ponieważ dotyczy to rozszerzenia Chrome, równie dobrze możesz użyć standardowego zdarzenia DOM - DOMSubtreeModified. Zobacz obsługę tego zdarzenia w różnych przeglądarkach. Jest obsługiwany w Chrome od 1.0.

$("#someDiv").bind("DOMSubtreeModified", function() {
    alert("tree changed");
});

Zobacz działający przykład tutaj .

 193
Author: Anurag,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-14 02:24:29

Wiele witryn używa AJAX do dynamicznego dodawania/pokazywania/zmieniania treści. Czasami jest używany zamiast nawigacji w witrynie, więc aktualny adres URL jest zmieniany programowo, a Skrypty zawartości nie są automatycznie wykonywane przez przeglądarkę, ponieważ strona nie jest pobierana całkowicie ze zdalnego serwera.


Zwykłe metody js wykrywania zmian strony dostępne w skrypcie content .

  • MutationObserver (docs ) do dosłownego wykrywania DOM zmiany:

  • Detektor zdarzeń dla stron, które sygnalizują zmianę treści poprzez wysłanie zdarzenia DOM:

  • Okresowe sprawdzanie DOM poprzez setInterval :
    Oczywiście będzie to działać tylko w przypadku, gdy poczekasz na konkretny element zidentyfikowany przez jego id / Selektor, i nie pozwoli Ci to na uniwersalne wykrywaj nową dynamicznie dodawaną zawartość, chyba że wymyślisz jakiś rodzaj odcisków palców na istniejącej zawartości.

  • Cloaking History API wewnątrz wstrzykiwanego skryptu DOM:

    document.head.appendChild(document.createElement('script')).text = '(' +
        function() {
            // injected DOM script is not a content script anymore, 
            // it can modify objects and functions of the page
            var _pushState = history.pushState;
            history.pushState = function(state, title, url) {
                _pushState.call(this, state, title, url);
                window.dispatchEvent(new CustomEvent('state-changed', {detail: state}));
            };
            // repeat the above for replaceState too
        } + ')(); this.remove();'; // remove the DOM script element
    
    // And here content script listens to our DOM script custom events
    window.addEventListener('state-changed', function(e) {
        console.log('History state changed', e.detail, location.hash);
        doSomething();
    });
    
  • Listening to hashchange, popstate wydarzenia:

    window.addEventListener('hashchange', function(e) {
        console.log('URL hash changed', e);
        doSomething();
    });
    window.addEventListener('popstate', function(e) {
        console.log('State changed', e);
        doSomething();
    });
    



Extensions-specific: detect URL changes in a background / wydarzenie strona .

Istnieją zaawansowane API do pracy z nawigacją: webNavigation, webRequest , ale użyjemy simple chrome.tabs.onUpdated słuchacz zdarzeń, który wysyła wiadomość do skryptu treści:

  • Manifest.json:
    declare background / event page
    declare content script
    dodaj "tabs" pozwolenie .

  • Tło.js

    var rxLookfor = /^https?:\/\/(www\.)?google\.(com|\w\w(\.\w\w)?)\/.*?[?#&]q=/;
    chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
        if (rxLookfor.test(changeInfo.url)) {
            chrome.tabs.sendMessage(tabId, 'url-update');
        }
    });
    
  • Treść.js

    chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) {
        if (msg === 'url-update') {
            doSomething();
        }
    });
    
 26
Author: wOxxOm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-15 10:42:17

Inne podejście w zależności od tego, jak zmieniasz div. Jeśli używasz JQuery do zmiany zawartości div za pomocą metody html (), możesz rozszerzyć tę metodę i wywołać funkcję rejestracji za każdym razem, gdy umieścisz html w div.

(function( $, oldHtmlMethod ){
    // Override the core html method in the jQuery object.
    $.fn.html = function(){
        // Execute the original HTML method using the
        // augmented arguments collection.

        var results = oldHtmlMethod.apply( this, arguments );
        com.invisibility.elements.findAndRegisterElements(this);
        return results;

    };
})( jQuery, jQuery.fn.html );

Po prostu przechwytywamy wywołania html (), wywołujemy za pomocą tego funkcję rejestracji, która w kontekście odnosi się do elementu docelowego otrzymującego nową zawartość, a następnie przekazujemy wywołanie do oryginalnego jquery.funkcja html (). Pamiętaj, aby zwrócić wyniki oryginalnej metody html (), ponieważ jQuery oczekuje jej do łańcuchowania metod.

Aby uzyskać więcej informacji na temat nadpisywania i rozszerzania metod, sprawdź http://www.bennadel.com/blog/2009-Using-Self-Executing-Function-Arguments-To-Override-Core-jQuery-Methods.htm, czyli tam, gdzie zakryłem funkcję zamknięcia. Sprawdź również samouczek wtyczek na stronie JQuery.

 24
Author: Zac Imboden,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-04 00:47:37

Oprócz "surowych" narzędzi dostarczanych przez MutationObserver API, istnieją "wygodne" biblioteki do pracy z mutacjami DOM.

Rozważmy: MutationObserver reprezentuje każdą zmianę DOM pod względem poddziałów. Jeśli więc, na przykład, czekasz na wstawienie pewnego elementu, może on znajdować się głęboko wewnątrz dzieci mutations.mutation[i].addedNodes[j].

Inny problem polega na tym, że twój własny kod, w reakcji na mutacje, zmienia DOM - często chcesz go odfiltrować.

Dobra wygoda biblioteka, która rozwiązuje takie problemy to mutation-summary (disclaimer: nie jestem autorem, tylko zadowolonym użytkownikiem), co pozwala określić zapytania tego, co Cię interesuje, i uzyskać dokładnie to.

Podstawowy przykład użycia z dokumentów:

var observer = new MutationSummary({
  callback: updateWidgets,
  queries: [{
    element: '[data-widget]'
  }]
});

function updateWidgets(summaries) {
  var widgetSummary = summaries[0];
  widgetSummary.added.forEach(buildNewWidget);
  widgetSummary.removed.forEach(cleanupExistingWidget);
}
 3
Author: Xan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-10 12:00:26