2012-07-15 10 views
38

Potrzebuję oglądać dla zmiany atrybutu na dowolnym z dzieci określonego elementu DOM. Do tej pory używam mutation events.Oglądanie zmian DOM, elegancki sposób

Problem polegał na tym, że były błędne: pod Chromium, DOMAttrModified nie został zwolniony, ale był DOMSubtreeModified. Problem był łatwy do rozwiązania: ponieważ zgodnie ze specyfikacją, DOMSubtreeModified jest wywoływane, jeśli którykolwiek z pozostałych zdarzeń jest uruchamiany, więc właśnie posłuchałem DOMSubtreeModified.

W każdym razie Chromium w najnowszych wersjach przestał wystrzeliwać wszystko, jeśli atrybut został zmodyfikowany.

Nowy Mutation Observer API działa jednak bezbłędnie.

Do chwili obecnej wystarczy wywołać wywołanie zwrotne po DOWOLNEJ zmianie poddrzewa określonego elementu - po prostu dlatego, że nic innego nie powinno się zmienić - więc rozwiązałem swój problem, używając tylko obserwatora mutacji & (jeśli dostępny) w tym samym kawałku kodu.

Jednak teraz potrzebuję silniejszego filtrowania zdarzeń (np. Na nowym węźle, na usuniętym węźle) - tak jest tam biblioteka, prawdopodobnie wtyczka jQuery, która pozwoliłaby mi elegancko używać zarówno tych interfejsów API - MutationObserver, jeśli są dostępne i zdarzenia mutacji jako rezerwowe, z możliwością filtrowania dla określonych typów zdarzeń (np. Element dodany, atrybut zmieniony).

E.g.

$("#test").watch({onNewElement: 1}, function(newElement){}) 
$("#test").watch({onNewAttribute: 1}, function(modifiedElement) {}) 

Albo bez jQuery

watchChanges("#test", {onNewElement: 1}, function(newElement){}) 
watchChanges("#test", {onNewAttribute: 1}, function(modifiedElement){}) 
+0

poszukiwaniach znaleźć to, ale obsługuje tylko nowe API: http://code.google.com/p/mutation-summary/ . Znalazłem także to, co wydaje się być prostą wersją tego, o co prosisz: http://stackoverflow.com/questions/10868104/can-you-have-a-javascript-hook-trigger-aftera-a- dom-elements-style-object-change – thirtydot

+0

Znalazłem także podsumowanie mutacji, ale nie obsługuje ono zdarzeń mutacji jako rezerwowych. Pierwsza odpowiedź na opublikowany wątek jest w zasadzie tym, co robię w moim kodzie, aby obserwować zmiany atrybutów. Na tej samej zasadzie można zbudować bibliotekę, która pozwala oglądać konkretne zdarzenia DOM przy użyciu zarówno obserwatorów mutacji, jak i zdarzeń (jako rezerwowych). Tego właśnie potrzebuję. – Ivo

+2

+1: Naprawdę kopie pytania o "najlepszą praktykę". –

Odpowiedz

2

to będzie działać?

http://darcyclarke.me/development/detect-attribute-changes-with-jquery/

$.fn.watch = function(props, callback, timeout){ 
    if(!timeout) 
     timeout = 10; 
    return this.each(function(){ 
     var el  = $(this), 
      func = function(){ __check.call(this, el) }, 
      data = { props: props.split(","), 
         func: callback, 
         vals: [] }; 
     $.each(data.props, function(i) { data.vals[i] = el.css(data.props[i]); }); 
     el.data(data); 
     if (typeof (this.onpropertychange) == "object"){ 
      el.bind("propertychange", callback); 
     } else if ($.browser.mozilla){ 
      el.bind("DOMAttrModified", callback); 
     } else { 
      setInterval(func, timeout); 
     } 
    }); 
    function __check(el) { 
     var data = el.data(), 
      changed = false, 
      temp = ""; 
     for(var i=0;i < data.props.length; i++) { 
      temp = el.css(data.props[i]); 
      if(data.vals[i] != temp){ 
       data.vals[i] = temp; 
       changed = true; 
       break; 
      } 
     } 
     if(changed && data.func) { 
      data.func.call(el, data); 
     } 
    } 
} 
+0

Widziałem to, ale to tylko dla atrybutów. Dodatkowo, powraca do setInterval, nawet jeśli przeglądarka może obsługiwać DOMAttrModified. – Ivo

+0

@Ivo prawo. Oto jednak myśl - czy kontrolujesz wszystkie zmiany zachodzące w domenie?Czy rozważałeś nadpisanie metod manipulacji jquery, aby wywołać zdarzenie change/append/remove (ale zakładam, że wszystkie zmiany nastąpią przez jquery). Wiem, że to dużo pracy, a nie dokładnie to, czego szukasz, ale dostaje pracę. –

+1

Wykonałem już tę pracę dawno temu - używam zarówno zdarzeń mutacji, jak i obserwatorów do monitorowania atrybutów, i korzystam tylko z tych wydarzeń, aby oglądać nowo dodane rzeczy w DOM - i nie mam dość kontroli, ponieważ jestem obserwowanie zmian wprowadzonych za pomocą edytora contenteditable/WYSIHTML5. Ale wszystko działa dla przeglądarek, które planowałem wspierać. To jest bardziej pytanie "najlepszego podejścia". I poprawianie małp jQuery wydaje się złym pomysłem. Poprawianie małpek DOM API może być bardziej odpowiednie, ale nadal nie jestem pewien. – Ivo

2

Dla skutecznego monitorowania DOM z jQuery, można spojrzeć na jQuery Behavior Plugin (Zastrzeżenie: Jestem autor), który wykorzystuje zoptymalizowaną wersję Live Query. Używam go w kilku produktach od 3 lat, bez żadnych problemów.

Edit: Słuchanie zmian atrybutów będzie działać tak:

$.behavior({ 
    'div:first': { 
     'changeAttr': function (event, data) { 
      console.log('Attribute "' + data.attribute + '" changed from "' + data.from + '" to "' + data.to + '"'); 
     } 
    } 
}); 

$('div:first').attr('foo', 'bar'); 
Powiązane problemy