MutationObserver#
MutationObserver.observe()#
Metoda observe()
rejestruje danego obserwatora zmian dla przekazanego węzła, z jednoczesnym określeniem szczegółowych kryteriów rejestracji przyszłych zmian w węźle (lub też jego potomkach). Obserwator zmian, na którym wywołano opisywaną metodę, staje się zarejestrowanym obserwatorem.
Opis działania#
Samo wywołanie i poszczególne jego części najlepiej objaśnić na zapisie składniowym:
mutationObserver.observe(target, options);
gdzie poszczególne człony oznaczają:
- mutationObserver - obserwator zmian będący obiektem kontekstu.
- target - referencja do węzła, dla którego obserwator zmian jest rejestrowany.
- options - słownik typu
MutationObserverInit
określający szczegółowe kryteria rejestrowanych zmian w węźle. W przypadku JS będzie to standardowy obiekt z następującymi właściwościami i wartościami:childList
- boolowskietrue
oznacza obserwację zmian w dzieciach posiadanych przez target. Zmiana w rzeczywistości oznacza modyfikację liczby dzieci w target, np. poprzez usunięcie lub dodanie nowych węzłów.attributes
- boolowskietrue
oznacza obserwację zmian w atrybutach posiadanych przez target. Zmiana w rzeczywistości obejmuje dodanie nowego atrybutu, usunięcie istniejącego atrybutu oraz zmianę wartości istniejącego atrybutu (nawet na taką samą). Można pominąć jeśli właściwościattributeOldValue
i/lubattributeFilter
zostały określone.characterData
- boolowskietrue
oznacza obserwację zmian w danych tekstowych posiadanych przez target. Zmiana w rzeczywistości oznacza modyfikację treści w węzłach znakowych. Można pominąć jeśli właściwośćcharacterDataOldValue
została określona.subtree
- boolowskietrue
oznacza obserwację zmian nie tylko dla samego target, ale również w potomkach posiadanych przez target. Można zatem zarejestrować obserwatora bezpośrednio na target i jednocześnie obserwować zmiany dla wszystkich jego potomków.attributeOldValue
- boolowskietrue
oznacza (jeśli właściwośćattributes
też ma wartośćtrue
lub została pominięta) zapisanie wartości z atrybutów posiadanych przez target, jeszcze przed ich zmianą.characterDataOldValue
- boolowskietrue
oznacza (jeśli właściwośćcharacterData
też ma wartośćtrue
lub została pominięta) zapisanie danych tekstowych posiadanych przez target, jeszcze przed ich zmianą.attributeFilter
- sekwencja lokalnych nazw tych atrybutów (nie mogą mieć przestrzeni nazw), których zmiany będą obserwowane (właściwośćattributes
też musi mieć wartośćtrue
lub została pominięta). W przypadku JS odpowiednikiem sekwencji jest tablica.
Algorytm wywołania metody observe(target, options)
nie jest skomplikowany. Dla lepszego zrozumienia tematu prezentuję go w całości:
- Jeśli właściwość
attributeOldValue
lubattributeFilter
w options jest obecna i właściwośćattributes
w options jest nieobecna, to ustaw właściwośćattributes
w options na boolowską wartośćtrue
. - Jeśli właściwość
characterDataOldValue
w options jest obecna i właściwośćcharacterData
w options jest nieobecna, to ustaw właściwośćcharacterData
w options na boolowską wartośćtrue
. - Jeśli przynajmniej jedna z właściwości
childList
,attributes
lubcharacterData
w options nie ma boolowskiej wartościtrue
, to zrzuć błądTypeError
. - Jeśli właściwość
attributeOldValue
w options ma boolowską wartośćtrue
i właściwośćattributes
w options ma boolowską wartośćfalse
, to zrzuć błądTypeError
. - Jeśli właściwość
attributeFilter
w options jest obecna i właściwośćattributes
w options ma boolowską wartośćfalse
, to zrzuć błądTypeError
. - Jeśli właściwość
characterDataOldValue
w options ma boolowską wartośćtrue
i właściwośćcharacterData
w options ma boolowską wartośćfalse
, to zrzuć błądTypeError
. Dla każdego (for each) zarejestrowanego obserwatora registered w liście zarejestrowanych obserwatorów skojarzonej z target, którego obserwatorem jest obiekt kontekstu, wykonaj poniższe podkroki:
- Usuń wszystkich przejściowych zarejestrowanych obserwatorów, których źródłem jest registered.
- Zastąp opcje w registered przez options.
- W przeciwnym razie dodaj nowego zarejestrowanego obserwatora do listy zarejestrowanych obserwatorów skojarzonej z target, dla którego obiekt kontekstu będzie obserwatorem i options będzie opcjami, a następnie dodaj target do listy węzłów skojarzonej z obiektem kontekstu, na których jest on rejestrowany.
Najciekawsza sytuacja ma miejsce w przypadku drugiego argumentu przekazanego do metody observe()
. W ujęciu Web IDL mamy do czynienia ze słownikiem. Nie ma potrzeby wypisywania wszystkich właściwości w słowniku, no chyba że planujemy szerszą konkretyzację rejestrowanych zmian dla węzłów. Niektórzy członkowie słownika będą ustawiani automatycznie w zależności od wartości/obecności innych członków słownika (co widać w powyższym algorytmie). Jest to zamierzone i ma na celu zwiększenie elastyczności całego mechanizmu.
Prosty przykład:
<script>
// Tworzymy nowego obserwatora 'newObserver'
var newObserver = new MutationObserver(function(records, observer){
// W czasie wywołania funkcji zwrotnej mamy dostęp do:
// records - lista ze wszystkimi obiektami MutationRecord
// observer - nasz newObserwer
var getInfo = "";
var recordsLen = records.length;
for (var i = 0; i < recordsLen; i++){
var record = records[i];
getInfo += "<br><br>" + "records[" + i + "]: " + record
+ "<br>" + "record.type: " + record.type
+ "<br>" + "record.target: " + record.target
+ "<br>" + "record.addedNodes.length: " + record.addedNodes.length
+ "<br>" + "record.attributeName: " + record.attributeName
+ "<br>" + "record.attributeNamespace: " + record.attributeNamespace
+ "<br>" + "record.oldValue: " + record.oldValue;
}
document.documentElement.innerHTML += "Liczba zmian records.length: " + recordsLen
+ "<br><br>" + "Odczytujemy poszczególne dane każdej zmiany:"
+ getInfo;
});
// Tworzymy obiekt konfiguracyjny
var config = {
childList: true,
attributes: true,
attributeOldValue: true,
attributeFilter: ["id", "name"],
subtree: true,
characterDataOldValue: true
};
var new_P = document.createElement("P");
newObserver.observe(new_P, config); // rejestrujemy 'newObserver' na węźle 'new_P'
// Przeprowadzamy różne zmiany na węźle 'new_P' i jego zawartości
new_P.id = "id1";
new_P.id = "id2";
new_P.id = "id2";
new_P.className = "important"; // ten atrybut nie podlega obserwacji
new_P.appendChild(document.createElement("span"));
new_P.textContent = "Start";
new_P.childNodes[0].textContent = "Witam1";
new_P.childNodes[0].textContent = "Witam2";
new_P.childNodes[0].textContent = "Witam2";
</script>
Metoda observe()
pojawia się dopiero w specyfikacji DOM4.
Składnia Web IDL#
interface MutationObserver { void observe(Node target, MutationObserverInit options); }