NodeFilter#

NodeFilter.acceptNode()#

Metoda acceptNode() jest dodatkową opcją testującą używaną przez filtr w obiektach typu NodeIterator oraz TreeWalker.

Interfejs NodeFilter jest specyficzny ponieważ jest typu zwrotnego (callback interface). W praktyce oznacza to tyle, że nie istnieje żadna gotowa metoda pozwalająca utworzyć taki obiekt. To my musimy utworzyć dowolny obiekt JS i rozszerzyć go o pewne elementy (w tym wypadku metodą o nazwie "acceptNode"). W praktyce całość można rozwiązać na kilka sposobów, dlatego w dalszej części przedstawię ich najpopularniejsze warianty.

Opis działania#

Samo wywołanie i poszczególne jego części najlepiej objaśnić na zapisie składniowym:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
// Wariant obiektowy (obiekt klasyczny)
var filtr1 = {
	acceptNode: function(node){
		kod funkcji
	}
};

// Wariant funkcyjny (obiekt funkcyjny)
var filtr2 = function(node){
	kod funkcji
};

gdzie poszczególne człony oznaczają:

Najlepiej omówić wszystko od podstaw jeszcze raz. Maska bitowa jest tylko wstępną filtracją, gdyż pozwala z grubsza przefiltrować węzły jedynie pod kątem ich typu. Filtr pozwala wprowadzić dodatkową filtrację węzłów z dowolnymi kryteriami testującymi. Korzeń, maskę bitową oraz filtr przekazujemy bezpośrednio do metod Document.createNodeItearor() oraz Document.createNodeWalker() przy tworzeniu obiektów typu NodeIterator i TreeWalker.

Z przekazaniem korzenia (węzeł) i maski bitowej (liczba dziesiętna lub szesnastkowa) nie ma żadnego problemu. Inaczej wygląda sytuacja w przypadku filtra. W zasadzie należy tutaj przekazać obiekt, który będzie zwracał konkretną liczbę (lub odpowiadającą stałą z tabelki), której wartość oznacza akceptację lub odrzucenie danego węzła (z ewentualnym uwzględnieniem lub pominięciem jego potomków). Obiekt ten należy utworzyć samodzielnie przy wykorzystaniu podstawowych poleceń danego środowiska uruchomieniowego.

Zgodnie z zapisem składniowym umieszczonym wyżej można to zrobić na dwa podstawowe sposoby:

Obydwa sposoby dają dużą swobodę. Do metod tworzących obiekty typu NodeIterator i TreeWalker, jako filtr, można bezpośrednio przekazywać obiekty anonimowe, funkcje anonimowe, wyrażenia funkcji jak i deklaracje funkcji. Nie ma w tej kwestii żadnych ograniczeń.

Przy każdym kolejnym przejściu do innego węzła nastąpi automatyczne wywołanie filtra (testu) i w zależności od zwróconego wyniku węzeł jest brany pod uwagę lub pomijany.

Prosty przykład z wykorzystaniem standardowego obiektu JS:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
<div id="box">
	<p>Pierwszy akapit.</p>
	<P>Drugi akapit.</p>
	<P>Trzeci akapit.</P>
</div>

<script>

	var filter = {

		acceptNode: function(node){

			// Akceptujemy każdy węzeł
			return NodeFilter.FILTER_ACCEPT;

		}

	};

	var root = document.getElementById("box");
	var iterator = document.createNodeIterator(root, NodeFilter.SHOW_ALL, filter);

	var node = iterator.nextNode(); // pierwszy element w obiekcie 'iterator'

	document.write("Odczytane węzły w kontenerze DIV za pomocą NodeIterator:" + "<br><br>");

	while (node){

		document.write(node.nodeName + "<br>");
		node = iterator.nextNode();

	}

</script>

Prosty przykład z wykorzystaniem funkcji anonimowej i dodatkowych kryteriów filtracji:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
<div id="box">
	<p>Pierwszy akapit.</p>
	<P>Drugi akapit.</p>
	<P>Trzeci akapit.</P>
</div>

<script>

	var root = document.getElementById("box");
	var iterator = document.createNodeIterator(root, NodeFilter.SHOW_ALL, function(node){

		if (node.nodeName.toLowerCase() == "p"){
			return 1;
		}

	});

	var node = iterator.nextNode(); // pierwszy element w obiekcie 'iterator'

	document.write("Odczytane węzły w kontenerze DIV za pomocą NodeIterator:" + "<br><br>");

	while (node){

		document.write(node.nodeName + "<br>");
		node = iterator.nextNode();

	}

</script>

W powyższym przykładzie wybieramy tylko akapity, dlatego zwróconych zostanie zdecydowanie mniej węzłów (3) niż w przykładzie pierwszym, gdzie akceptowane były dowolne węzły (11).

Na zakończenie przypominam, że ten rodzaj filtracji odbywa się po stronie JS dlatego jest bardzo powolny. Jeśli tylko to możliwe należy stosować predefiniowane metody filtrujące implementowane bezpośrednio w przeglądarce.

Składnia Web IDL#

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
callback interface NodeFilter {
	unsigned short acceptNode(Node node);
};

Specyfikacje i inne materiały#

Pasek społecznościowy

SPIS TREŚCI AKTUALNEJ STRONY

NodeFilter (H1) NodeFilter.acceptNode() (H2) Opis działania (H3) Składnia Web IDL (H3) Specyfikacje i inne materiały (H3)