Ogólne#

Range#

W tym miejscu umieszczam powtarzające się specyficzne pojęcia i algorytmy w interfejsie Range.

Pojęcia#

Obiekty typu Range mogą zostać użyte do zaznaczenia pewnej części w drzewie węzłów.

boundary point

offset

Punkt graniczny # (boundary point) jest krotką w postaci (węzeł, przesunięcie # [offset]), np. (node, offset), gdzie offset jest nienegatywną liczbą typu całkowitego.

Generalnie rzecz biorąc, przesunięcie w punkcie granicznym będzie między zerem a długością dla węzła w punkcie granicznym, włącznie. Algorytmy modyfikujące drzewo węzłów (w szczególności wstawianie, usuwanie, normalizacja, zastępowanie danych tekstowych czy podział) również modyfikują zakresy rozciągnięte na tym drzewie (szczegóły).

start

end

content

Każdy zakres jest skojarzony z dwoma punktami granicznymi - początkiem # (start) i końcem # (end). Między nimi znajduje się jego zawartość # (content).

start node

start offset

end node

end offset

Dla wygody niech węzeł początkowy # (start node) wskazuje na węzeł w początku, przesunięcie początkowe # (start offset) wskazuje na przesunięcie w początku, węzeł końcowy # (end node) wskazuje na węzeł w końcu , i przesunięcie końcowe # (end offset) wskazuje na przesunięcie w końcu.

root

Korzeniem # (root) w zakresie jest korzeń jego węzła początkowego.

collapsed

Zakres jest zwinięty # (collapsed) kiedy jego początek i koniec to jeden i ten sam punkt graniczny. Zawartość w takim zakresie nie istnieje (jest pusta), co z perspektywy niektórych poleceń będzie równoważne ze zwracaniem pustego fragmentu dokumentu.

Oto kilka faktów dla lepszego zrozumienia tych definicji: #

Algorytmy#

contained

Węzeł node jest zawarty # (contained) w zakresie range jeśli korzeń w node jest taki sam jak korzeń w range, i (node, 0) jest za początkiem w range oraz (node, długość w node) jest przed końcem w range.

partially contained

Węzeł node jest częściowo zawarty # (partially contained) w zakresie range jeśli jest to przodek obejmujący dla węzła początkowego w range, ale nie jego węzła końcowego, lub odwrotnie.

position

Jeśli dwa węzły w punktach granicznych (node A, offset A) i (node B, offset B) mają ten sam korzeń, to pozycja # (position) pierwszego względem drugiego jest przed # (before), równa # (equal) lub za # (after), zwracana zgodnie z poniższym algorytmem:

  1. Jeśli node A jest taki sam jak node B, to zwróć równy jeśli offset A jest taki sam jak offset B, przed jeśli offset A jest mniejszy niż offset B, i za jeśli offset A jest większy niż offset B.
  2. Jeśli node A następuje po node B, to oblicz pozycję (node B, offset B) względem (node A, offset A). Jeśli jest przed, to zwróć za. Jeśli jest za, to zwróć przed.
  3. Jeśli node A jest przodkiem dla node B:

    1. Niech child będzie równe node B.
    2. Dopóki (while) child nie jest dzieckiem w node A, to ustaw child na swojego rodzica.
    3. Jeśli indeks w child jest mniejszy od offset A, to zwróć za.
  4. Zwróć przed.

set the start or end

Aby ustawić początek lub koniec # (set the start or end) w zakresie range na punkt graniczny (node, offset) należy wykonać następujące kroki:

  1. Jeśli node jest typu DocumentType, to zrzuć wyjątek "InvalidNodeTypeError".
  2. Jeśli offset jest większy od długości w node, to zrzuć wyjątek "IndexSizeError".
  3. Niech bp będzie punktem granicznym (node, offset).
  4. Jeśli te kroki wywołane zostały jako "ustaw początek"
    1. Jeśli bp jest za końcem w range lub jeśli korzeń w range nie jest równy korzeniu w node, to ustaw koniec w range na bp.
    2. Ustaw początek w range na bp.
    Jeśli te kroki wywołane zostały jako "ustaw koniec"
    1. Jeśli bp jest przed początkiem w range lub jeśli korzeń w range nie jest równy korzeniu w node, to ustaw początek w range na bp.
    2. Ustaw koniec w range na bp.

select

Aby wybrać # (select) węzeł node w zakresie range należy wykonać następujące kroki:

  1. Niech parent będzie rodzicem w node.
  2. Jeśli parent ma wartość null, to zrzuć wyjątek "InvalidNodeTypeError".
  3. Niech index będzie indeksem w node.
  4. Ustaw początek w range na punkt graniczny (parent, index).
  5. Ustaw koniec w range na punkt graniczny (parent, index plus jeden).

insert

Aby wstawić # (insert) węzeł node do zakresu range należy wykonać następujące kroki:

  1. Jeśli węzeł początkowy w range jest węzłem typu ProcessingInstruction lub Comment, lub węzłem typu Text, którego rodzic ma wartość null, lub samym node, to zrzuć wyjątek "HierarchyRequestError".
  2. Niech referenceNode ma wartość null.
  3. Jeśli węzeł początkowy w range jest węzłem typu Text, to ustaw referenceNode na ten węzłe typu Text.
  4. W przeciwnym razie niech referenceNode będzie dzieckiem w węźle początkowym, którego indeksem jest przesunięcie początkowe, lub wartością null, jeśli nie ma takiego dziecka.
  5. Niech parent będzie węzłem początkowym w range jeśli referenceNode ma wartość null. W przeciwnym razie niech parent będzie rodzicem w referenceNode.
  6. Zagwarantuj poprawność przed wstawieniem node do parent przed referenceNode.
  7. Jeśli węzeł początkowy w range jest węzłem typu Text, to podziel go z początkiem wskazywanym przez przesunięcie początkowe w range i ustaw referenceNode na zwracany wynik.
  8. Jeśli node jest równy referenceNode to ustaw referenceNode na swojego brata następującego.
  9. Jeśli rodzic w node nie ma wartości null to usuń node z jego rodzica.
  10. Niech newOffset będzie długością w parent jeśli referenceNode ma wartość null. W przeciwnym razie niech parent będzie indeksem w referenceNode.
  11. Zwiększ newOffset o długość w node jeśli node jest węzłem typu DocumentFragment. W przeciwnym razie zwiększ newOffset o jeden.
  12. Wykonaj przed wstawienie node do parent przed referenceNode.
  13. Jeśli początek i koniec w range są tacy sami, to ustaw koniec w range na (parent, newOffset).

clone content

Aby sklonować zawartość # (clone the content) zakresu range należy wykonać następujące kroki:

  1. Niech fragment będzie nowym węzłem typu DocumentFragment, którego właścicielem jest ten sam właściciel, jak w przypadku węzła początkowego w range.
  2. Jeśli początek w range i koniec w range są tacy sami, to zwróć fragment.
  3. Niech original start node, original start offset, original end node i original end offset będą odpowiednio węzłem początkowym, przesunięciem początkowym, węzłem końcowym i przesunięciem końcowym w range.
  4. Jeśli original start node i original end node są tacy sami, i są węzłami typu Text, ProcessingInstruction lub Comment, to wykonaj poniższe podkroki:

    1. Niech clone będzie klonem original start node.
    2. Ustaw dane tekstowe w clone na wynik wydobywania część danych tekstowych z węzłem original start node, początkiem original start offset i licznikiem w postaci original end offset minus original start offset.
    3. Dodaj clone do fragment.
    4. Zwróć fragment.
  5. Niech common ancestor będzie referencją do original start node.
  6. Dopóki (while) common ancestor nie jest przodkiem obejmującym dla original end node, to ustaw common ancestor na jego własnego rodzica.
  7. Niech first partially contained child będzie wartością null.
  8. Jeśli original start node nie jest przodkiem obejmującym dla original end node, to ustaw first partially contained child na pierwsze dziecko w common ancestor, które jest częściowo zawarte w range.
  9. Niech last partially contained child będzie wartością null.
  10. Jeśli original end node nie jest przodkiem obejmującym dla original start node, to ustaw last partially contained child na ostatnie dziecko w common ancestor, które jest częściowo zawarte w range.

    Te przypisania zmiennych faktycznie zawsze mają sens. Na przykład, jeśli original start node nie jest przodkiem obejmującym dla original end node, to original start node jest we własnej postaci częściowo zawarty w zakresie, tak samo wszyscy jego przodkowie, aż do dziecka w common ancestor. Sam common ancestor nie może być original start node ponieważ musi być przodkiem obejmującym dla original end node. Drugi przypadek jest bardzo podobny. Zauważ też, że dwoje dzieci nigdy nie będzie równe, jeśli oboje będą zdefiniowani.

  11. Niech contained children będzie listą wszystkich dzieci w common ancestor, którzy są zawarci w range, zgodnie z porządkiem drzewa.
  12. Jeśli którykolwiek z członków w contained children jest węzłem typu DocumentType, to zrzuć wyjątek "HierarchyRequestError".

    Nie musimy się martwić o pierwszy lub ostatni częściowo zawarty węzeł ponieważ węzeł typu DocumentType nigdy nie może być częściowo zawarty. On nie może być punktem granicznym zakresu i nie może być przodkiem dla kogokolwiek.

  13. Jeśli first partially contained child jest węzłem typu Text, ProcessingInstruction lub Comment, to wykonaj poniższe podkroki:

    W tym przypadku first partially contained child jest referencją do original start node.

    1. Niech clone będzie klonem original start node.
    2. Ustaw dane tekstowe w clone na wynik wydobywania część danych tekstowych z węzłem original start node, początkiem original start offset i licznikiem w postaci długość w original start node minus original start offset.
    3. Dodaj clone do fragment.
  14. W przeciwnym razie, jeśli first partially contained child nie ma wartości null, to wykonaj poniższe podkroki:

    1. Niech clone będzie klonem first partially contained child.
    2. Dodaj clone do fragment.
    3. Niech subrange będzie nowym obiektem typu Range z początkiem (original start node, original start offset) i końcem (first partially contained child, długość w first partially contained child).
    4. Niech subfragment będzie rezultatem klonowania zawartości w subrange.
    5. Dodaj subfragment do clone.
  15. Dla każdego (for each) zawartego dziecka contained child w contained children:

    1. Niech clone będzie klonem contained child.
    2. Dodaj clone do fragment.
  16. Jeśli last partially contained child jest węzłem typu Text, ProcessingInstruction lub Comment, to wykonaj poniższe podkroki:

    W tym przypadku last partially contained child jest referencją do original end node.

    1. Niech clone będzie klonem original end node.
    2. Ustaw dane tekstowe w clone na wynik wydobywania część danych tekstowych z węzłem original end node, początkiem 0 i licznikiem original end offset.
    3. Dodaj clone do fragment.
  17. W przeciwnym razie, jeśli last partially contained child nie ma wartości null, to wykonaj poniższe podkroki:

    1. Niech clone będzie klonem last partially contained child.
    2. Dodaj clone do fragment.
    3. Niech subrange będzie nowym obiektem typu Range z początkiem (last partially contained child, 0) i końcem (original end node, original end offset).
    4. Niech subfragment będzie rezultatem klonowania zawartości w subrange.
    5. Dodaj subfragment do clone.
  18. Zwróć fragment.

extract content

Aby wyciągnąć zawartość # (extract content) zakresu range należy wykonać następujące kroki:

  1. Niech fragment będzie nowym węzłem typu DocumentFragment, którego właścicielem jest ten sam właściciel, jak w przypadku węzła początkowego w range.
  2. Jeśli początek w range i koniec w range są tacy sami, to zwróć fragment.
  3. Niech original start node, original start offset, original end node i original end offset będą odpowiednio węzłem początkowym, przesunięciem początkowym, węzłem końcowym i przesunięciem końcowym w range.
  4. Jeśli original start node i original end node są tacy sami, i są węzłami typu Text, ProcessingInstruction lub Comment, to wykonaj poniższe podkroki:

    1. Niech clone będzie klonem original start node.
    2. Ustaw dane tekstowe w clone na wynik wydobywania część danych tekstowych z węzłem original start node, początkiem original start offset i licznikiem w postaci original end offset minus original start offset.
    3. Dodaj clone do fragment.
    4. Zastąp dane tekstowe z węzłem original start node, początkiem original start offset, licznikiem w postaci original end offset minus original start offset i danymi tekstowymi w postaci pustego łańcucha znakowego.
    5. Zwróć fragment.
  5. Niech common ancestor będzie referencją do original start node.
  6. Dopóki (while) common ancestor nie jest przodkiem obejmującym dla original end node, to ustaw common ancestor na jego własnego rodzica.
  7. Niech first partially contained child będzie wartością null.
  8. Jeśli original start node nie jest przodkiem obejmującym dla original end node, to ustaw first partially contained child na pierwsze dziecko w common ancestor, które jest częściowo zawarte w range.
  9. Niech last partially contained child będzie wartością null.
  10. Jeśli original end node nie jest przodkiem obejmującym dla original start node, to ustaw last partially contained child na ostatnie dziecko w common ancestor, które jest częściowo zawarte w range.

    Te przypisania zmiennych faktycznie zawsze mają sens. Na przykład, jeśli original start node nie jest przodkiem obejmującym dla original end node, to original start node jest we własnej postaci częściowo zawarty w zakresie, tak samo wszyscy jego przodkowie, aż do dziecka w common ancestor. Sam common ancestor nie może być original start node ponieważ musi być przodkiem obejmującym dla original end node. Drugi przypadek jest bardzo podobny. Zauważ też, że dwoje dzieci nigdy nie będzie równe, jeśli oboje będą zdefiniowani.

  11. Niech contained children będzie listą wszystkich dzieci w common ancestor, którzy są zawarci w range, zgodnie z porządkiem drzewa.
  12. Jeśli którykolwiek z członków w contained children jest węzłem typu DocumentType, to zrzuć wyjątek "HierarchyRequestError".

    Nie musimy się martwić o pierwszy lub ostatni częściowo zawarty węzeł ponieważ węzeł typu DocumentType nigdy nie może być częściowo zawarty. On nie może być punktem granicznym zakresu i nie może być przodkiem dla kogokolwiek.

  13. Jeśli original start node jest przodkiem obejmującym dla original end node, to ustaw new node na original start node i new offset na original start offset.
  14. W przeciwnym razie wykonaj poniższe podkroki:

    1. Niech reference node będzie referencją do original start node.
    2. Dopóki (while) rodzic w reference node nie ma wartości null i nie jest przodkiem obejmującym dla original end node, to ustaw reference node na jego własnego rodzica.
    3. Ustaw new node na rodzica w reference node i new offset na jeden plus indeks w reference node.

      Jeśli rodzicem w reference node byłaby wartość null, to byłby on korzeniem dla range, więc byłby przodkiem obejmującym dla original end node, i moglibyśmy nie osiągnąć tego punktu.

  15. Jeśli first partially contained child jest węzłem typu Text, ProcessingInstruction lub Comment, to wykonaj poniższe podkroki:

    W tym przypadku first partially contained child jest referencją do original start node.

    1. Niech clone będzie klonem original start node.
    2. Ustaw dane tekstowe w clone na wynik wydobywania część danych tekstowych z węzłem original start node, początkiem original start offset i licznikiem w postaci długość w original start node minus original start offset.
    3. Dodaj clone do fragment.
    4. Zastąp dane tekstowe z węzłem original start node, początkiem original start offset, licznikiem w postaci original end offset minus original start offset i danymi tekstowymi w postaci pustego łańcucha znakowego.
  16. W przeciwnym razie, jeśli first partially contained child nie ma wartości null, to wykonaj poniższe podkroki:

    1. Niech clone będzie klonem first partially contained child.
    2. Dodaj clone do fragment.
    3. Niech subrange będzie nowym obiektem typu Range z początkiem (original start node, original start offset) i końcem (first partially contained child, długość w first partially contained child).
    4. Niech subfragment będzie rezultatem wyciągania zawartości w subrange.
    5. Dodaj subfragment do clone.
  17. Dla każdego (for each) zawartego dziecka contained child w contained children dodaj contained child do fragment:

  18. Jeśli last partially contained child jest węzłem typu Text, ProcessingInstruction lub Comment, to wykonaj poniższe podkroki:

    W tym przypadku last partially contained child jest referencją do original end node.

    1. Niech clone będzie klonem original end node.
    2. Ustaw dane tekstowe w clone na wynik wydobywania część danych tekstowych z węzłem original end node, początkiem 0 i licznikiem original end offset.
    3. Dodaj clone do fragment.
    4. Zastąp dane tekstowe z węzłem original end node, początkiem 0, licznikiem original end offset i danymi tekstowymi w postaci pustego łańcucha znakowego..
  19. W przeciwnym razie, jeśli last partially contained child nie ma wartości null, to wykonaj poniższe podkroki:

    1. Niech clone będzie klonem last partially contained child.
    2. Dodaj clone do fragment.
    3. Niech subrange będzie nowym obiektem typu Range z początkiem (last partially contained child, 0) i końcem (original end node, original end offset).
    4. Niech subfragment będzie rezultatem wyciągania zawartości w subrange.
    5. Dodaj subfragment do clone.
  20. Ustaw początek i koniec w range na (new node, new offset).
  21. Zwróć fragment.
Pasek społecznościowy

SPIS TREŚCI AKTUALNEJ STRONY

Ogólne (H1) Range (H2) Pojęcia (H3) boundary point (H4) offset (H4) start (H4) end (H4) content (H4) start node (H4) start offset (H4) end node (H4) end offset (H4) root (H4) collapsed (H4) Algorytmy (H3) contained (H4) partially contained (H4) position (H4) set the start or end (H4) select (H4) insert (H4) clone content (H4) extract content (H4)