Jak mogę sprawdzić, czy jeden element DOM jest dzieckiem innego elementu DOM? Czy istnieją jakieś wbudowane metody do tego? Na przykład coś takiego:
if (element1.hasDescendant(element2))
lub
if (element2.hasParent(element1))
Jeśli nie to jakieś pomysły, jak to zrobić? Musi to również być przeglądarka. Powinienem również wspomnieć, że dziecko może być zagnieżdżone na wielu poziomach poniżej rodzica.
javascript
dom
AJ
źródło
źródło
Odpowiedzi:
Aktualizacja: Istnieje teraz natywny sposób na osiągnięcie tego.
Node.contains()
. Wspomniany w komentarzu i poniżej również odpowiedzi.Stara odpowiedź:
Korzystanie z
parentNode
właściwości powinno działać. Jest to również całkiem bezpieczne z punktu widzenia różnych przeglądarek. Jeśli wiadomo, że związek ma głębokość jednego poziomu, możesz to sprawdzić po prostu:Jeśli dziecko może zostać dowolnie zagnieżdżone głęboko w rodzicu, możesz użyć funkcji podobnej do poniższej, aby przetestować relację:
źródło
Node.contains
(nie ma strony caniuse)Node.contains
? :)Powinieneś użyć
Node.contains
, ponieważ jest teraz standardowy i dostępny we wszystkich przeglądarkach.https://developer.mozilla.org/en-US/docs/Web/API/Node.contains
źródło
var parent = document.getElementById('menu'); var allElements = document.getElementsByTagName('a'); if (parent.contains(allElements[i]) { alert('Link is inside meni'); }
Po prostu musiałem podzielić się „moim”.
Chociaż koncepcyjnie to samo co odpowiedź Asafa (korzystająca z tej samej kompatybilności między przeglądarkami, nawet IE6), jest o wiele mniejsza i przydaje się, gdy rozmiar jest na wagę złota i / lub gdy nie jest tak często potrzebny.
.. lub jako jedna linijka ( tylko 64 znaki !):
i jsfiddle tutaj .
Użycie:
childOf(child, parent)
zwraca wartość logicznątrue
|false
.Objaśnienie:
while
ocenia tak długo, jak ocenia warunek whiletrue
.Operator
&&
(AND) zwraca wartość logiczną „prawda / fałsz” po ocenie lewej i prawej strony, ale tylko wtedy, gdy po lewej stronie była prawda (left-hand && right-hand
) .Strona lewa (z
&&
) wynosi:(c=c.parentNode)
.Będzie to pierwszy przypisać
parentNode
odc
doc
, a następnie operator AND oceni uzyskanyc
jako wartość logiczną.Ponieważ
parentNode
zwraca,null
jeśli nie ma już rodzica inull
jest konwertowanyfalse
, pętla while poprawnie zatrzyma się, gdy nie będzie już rodziców.Z boku po prawej stronie (z
&&
) wynosi:c!==p
. Operator porównania jest „ nie dokładnie równa”. Więc jeśli rodzic dziecka nie jest rodzicem (podałeś), to ocenia , ale jeśli rodzic dziecka jest rodzicem, to ocenia . Jeśli więc zostanie ustawiona wartość false, operator powróci jako warunek while, a pętla while zatrzyma się. (Zauważ, że nie ma potrzeby używania ciała chwilowego i wymagany jest średnik zamykający .)!==
true
false
c!==p
&&
false
;
Więc kiedy pętla while kończy się,
c
jest albo węzłem (nienull
), kiedy znajduje nadrzędny OR, albo jestnull
(kiedy pętla biegnie do końca bez znalezienia dopasowania).W ten sposób tylko
return
fakt (konwertowane wartości logicznej, natomiast węzła) o:return !!c;
: z!
(NOT
operator) odwraca wartość logiczną (true
staje sięfalse
i vice versa).!c
konwertujec
(węzeł lub null) na wartość logiczną, zanim będzie mógł odwrócić tę wartość. Tak więc dodanie second!
(!!c
) konwertuje to fałsz z powrotem na true (dlatego podwójne!!
jest często używane do „konwersji wszystkiego na boolean”).Dodatkowo:
treść / ładunek funkcji jest tak mały, że w zależności od wielkości liter (np. Kiedy nie jest często używany i pojawia się tylko raz w kodzie), można nawet pominąć funkcję (zawijanie) i po prostu użyć pętli while:
zamiast:
źródło
!==
) może poprawić prędkość, dając kompilatorowi do zrozumienia, że może pominąć sprawdzanie typu i opcjonalne niejawne kroki konwersji, które wystąpiłyby w luźnym porównaniu równości, a tym samym poprawić prędkość (dokładniej opisując, co chcesz się wydarzyć, co jest również korzystne dla programisty). Wydaje mi się również, że pamiętam z czasu, gdy to napisałem, że samo luźne porównanie (!=
) było albo bardzo podatne na błędy, albo w ogóle nie działało w niektórych starszych przeglądarkach (podejrzewam, że było w IE6, ale zapomniałem ).Kolejne rozwiązanie, o którym nie wspomniano:
Przykład tutaj
Nie ma znaczenia, czy element jest bezpośrednim dzieckiem, będzie działał na dowolnej głębokości.
Alternatywnie, stosując
.contains()
metodę :Przykład tutaj
źródło
Spójrz na Node # CompareDocumentPosition .
Inne związki obejmują
DOCUMENT_POSITION_DISCONNECTED
,DOCUMENT_POSITION_PRECEDING
iDOCUMENT_POSITION_FOLLOWING
.Nieobsługiwany w IE <= 8.
źródło
Możesz użyć metody zawiera
var result = parent.contains(child);
lub możesz spróbować użyć CompareDocumentPosition ()
var result = nodeA.compareDocumentPosition(nodeB);
Ostatni jest bardziej wydajny: w wyniku zwraca maskę bitów.
źródło
Natknąłem się na wspaniały kawałek kodu, aby sprawdzić, czy element jest dzieckiem innego elementu. Muszę tego użyć, ponieważ IE nie obsługuje
.contains
metody element. Mam nadzieję, że pomoże to również innym.Poniżej znajduje się funkcja:
źródło
Spróbuj tego:
źródło
Ostatnio natknąłem się na tę funkcję, która może:
Node.compareDocumentPosition ()
źródło