Node#
Node.compareDocumentPosition()#
Metoda compareDocumentPosition()
zwraca maskę bitową (liczba całkowita) będącą wynikiem porównania pozycji przekazanego węzła względem danego węzła.
Opis działania#
Samo wywołanie i poszczególne jego części najlepiej objaśnić na zapisie składniowym:
var bit_mask = node.compareDocumentPosition(other);
gdzie poszczególne człony oznaczają:
- bit_mask - liczba całkowita reprezentująca maskę bitową, w której poszczególne bity odzwierciedlają relację między węzłami.
- node - węzeł będący obiektem kontekstu, który musi być rodzicem dla wskazywanego dziecka.
- other - referencja do przekazanego węzła, którego pozycja jest porównywana względem danego węzła.
Algorytm wywołania metody compareDocumentPosition(other)
nie jest skomplikowany. Dla lepszego zrozumienia tematu prezentuję go w całości:
- Niech reference wskazuje na obiekt kontekstu.
- Jeśli other i reference są tym samym obiektem, to zwróć zero.
Jeśli other i reference nie należą do tego samego drzewa węzłów, to zwróć wynik będący zsumowaniem wartości z
DOCUMENT_POSITION_DISCONNECTED
,DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC
iDOCUMENT_POSITION_PRECEDING
lubDOCUMENT_POSITION_FOLLOWING
, z wymuszeniem, że wybór między dwiema ostatnimi wartościami ma być realizowany w sposób zrównoważony..Zwrócenie
DOCUMENT_POSITION_PRECEDING
lubDOCUMENT_POSITION_FOLLOWING
jest zazwyczaj implementowane za pomocą porównania wskaźnika (pointer comparison). W implementacji Javascript można zastosować polecenieMath.random()
, co oznacza, że w masce bitowej stan wysoki dla jednego z tych bitów będzie wybierany losowo.- Jeśli other jest przodkiem w reference, to zwróć wynik będący zsumowaniem wartości z
DOCUMENT_POSITION_CONTAINS
iDOCUMENT_POSITION_PRECEDING
. - Jeśli other jest potomkiem w reference, to zwróć wynik będący zsumowaniem wartości z
DOCUMENT_POSITION_CONTAINED_BY
iDOCUMENT_POSITION_FOLLOWING
. - Jeśli other poprzedza reference, to zwróć wartość z
DOCUMENT_POSITION_PRECEDING
. - Zwróć wartość z
DOCUMENT_POSITION_FOLLOWING
.
Maska bitowa zwracana przez metodę compareDocumentPosition()
to liczba całkowita typu unsigned short
, co oznacza, że może przyjąć wartości od 0
do 65535
(szesnaście bitów), chociaż metoda operuje jedynie na zakresie od 0
do 64
(sześć bitów). Dla osób nieobytych z zapisem dwójkowym pewnym problemem będzie rozpoznanie znaczenia poszczególnych bitów. W poniższej tabeli zamieszczam relację między wartością w zapisie binarnym, dziesiętnym oraz odpowiadającą stałą.
Zapis binarny | Zapis dziesiętny | Odpowiadająca stała | Znaczenie |
---|---|---|---|
000000 | 0 | Brak | Węzły są identyczne (czyli other to referencja do tego samego węzła, co node ). |
000001 | 1 | DOCUMENT_POSITION_DISCONNECTED | Węzły nie należą do tego samego drzewa węzłów. |
000010 | 2 | DOCUMENT_POSITION_PRECEDING | Węzeł other poprzedza węzeł node . |
000100 | 4 | DOCUMENT_POSITION_FOLLOWING | Węzeł other następuje po węźle node . |
001000 | 8 | DOCUMENT_POSITION_CONTAINS | Węzeł other zawiera węzeł node . |
010000 | 16 | DOCUMENT_POSITION_CONTAINED_BY | Węzeł other jest zawarty przez węzeł node . |
100000 | 32 | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | Do prywatnego użytku przez implementację. W praktyce ustawiane na tych samych zasadach, co DOCUMENT_POSITION_DISCONNECTED . |
Po wywołaniu metody compareDocumentPosition()
w zwracanej masce bitowej będziemy mieli zapisane wszystkie informacje na temat relacji między węzłami. Niestety maska bitowa zawsze ma postać dziesiętną, dlatego dla ułatwienia najlepiej zamienić ją na zapis binarny.
Przeanalizujmy jeden teoretyczny przykład, gdzie zwrócona została liczba dziesiętna 20
, którą możemy rozpisać następująco (w nawiasach znajduje się zapis dziesiętny):
010100 (20) = 000100 (4) + 010000 (16)
Z takiego zapisu możemy wywnioskować następujące rzeczy:
- Węzły należą do tego samego drzewa węzłów.
- Węzeł przekazany do metody występuje po węźle, na którym metoda została wywołana.
- Węzeł przekazany do metody jest zawarty przez węzeł, na którym metoda została wywołana.
W zasadzie to wystarczy przeanalizować stan każdego bitu w zwracanej wartości (zero lub jeden) , nie ma konieczności rozbijania tego na równanie, choć dla osób początkujących może być to sporym ułatwieniem. Na masce bitowej najczęściej wykonuje się mnożenie w celu określenia, czy dany bit jest ustawiony, czy też nie. Są to podstawy systemu dwójkowego, które wynosi się ze szkoły o profilach elektroniczno-informatycznych.
Więcej informacji oraz przykłady praktycznego wykorzystania metody compareDocumentPosition()
opisał John Resig w artykule "Comparing Document Position".
Prosty przykład:
<script>
var doc = document; // referencja do document
var newDocXML = document.implementation.createDocument(null, null, null); // nowy dokument XML
// Porównanie tego samego węzła
doc.write(doc.compareDocumentPosition(doc)); // 0(d) 00000000(b)
document.write("<br>");
// Porównanie węzłów w różnych drzewach węzłów
doc.write(doc.compareDocumentPosition(newDocXML)); // 35(d) 100011(b) lub 37(d) 100101(b) - zwracane losowo
document.write("<br>");
// Porównanie węzłów w różnych drzewach węzłów
doc.write(newDocXML.compareDocumentPosition(doc)); // 35(d) 100011(b) lub 37(d) 100101(b) - zwracane losowo
document.write("<br>");
// Porównanie węzłów w różnych drzewach węzłów
doc.write(doc.compareDocumentPosition(doc.createElement("div"))); // 35(d) 100011(b) lub 37(d) 100101(b) - zwracane losowo
document.write("<br>");
// Porównanie węzłów w różnych drzewach węzłów
doc.write(doc.createElement("div").compareDocumentPosition(doc)); // 35(d) 100011(b) lub 37(d) 100101(b) - zwracane losowo
document.write("<br>");
// Porównanie węzłów w różnych drzewach węzłów
doc.write(doc.createElement("div").compareDocumentPosition(doc.createElement("div"))); // 35(d) 100011(b) lub 37(d) 100101(b) - zwracane losowo
document.write("<br>");
// Porównanie węzłów w tym samym drzewie węzłów
doc.write(doc.compareDocumentPosition(doc.documentElement)); // 20(d) 010100(b)
document.write("<br>");
// Porównanie węzłów w tym samym drzewie węzłów
doc.write(doc.documentElement.compareDocumentPosition(doc)); // 10(d) 001010(b)
document.write("<br><br>");
// Pobranie wartości ze stałych
doc.write(doc.DOCUMENT_POSITION_DISCONNECTED); // 1(d) 000001(b)
document.write("<br>");
doc.write(doc.DOCUMENT_POSITION_PRECEDING); // 2(d) 000010(b)
document.write("<br>");
doc.write(doc.DOCUMENT_POSITION_FOLLOWING); // 4(d) 000100(b)
document.write("<br>");
doc.write(doc.DOCUMENT_POSITION_CONTAINS); // 8(d) 001000(b)
document.write("<br>");
doc.write(doc.DOCUMENT_POSITION_CONTAINED_BY); // 16(d) 010000(b)
document.write("<br>");
doc.write(doc.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC); // 32(d) 100000(b)
</script>
Składnia Web IDL#
interface Node : EventTarget { unsigned short compareDocumentPosition(Node other); }