Jak sprawdzić, czy element jQuery znajduje się w DOM?


147

Powiedzmy, że definiuję element

$foo = $('#foo');

a potem dzwonię

$foo.remove()

z jakiegoś wydarzenia. Moje pytanie brzmi, jak sprawdzić, czy $ foo zostało usunięte z DOM, czy nie? Przekonałem się, że to $foo.is(':hidden')działa, ale to oczywiście zwróci prawdę, gdybym tylko zadzwonił $foo.hide().

Odpowiedzi:


238

Lubię to:

if (!jQuery.contains(document, $foo[0])) {
    //Element is detached
}

Będzie to nadal działać, jeśli jeden z elementów nadrzędnych elementu został usunięty (w takim przypadku sam element nadal będzie miał element nadrzędny).


14
robienie $foo.closest(document.documentElement)jest szybsze (jeśli kogoś to obchodzi jsperf.com/jquery-element-in-dom )
urraka

48
@PerroAzul: Znalazłem znacznie szybszą alternatywę: jsperf.com/jquery-element-in-dom/2
SLaks

3
Wydajność była moim bezpośrednim zmartwieniem w przypadku tej metody, dzięki za połączenie testów porównawczych @SLaks. Więc wygląda na to, że $.contains(document.documentElement, $foo.get(0))to najszybszy sposób.
Christof

10
Jest na to sposób oparty na modelu DOM, który jest bardziej czytelny pod względem składni i wyobrażam sobie bardzo podobny pod względem wydajności:document.contains($foo[0])
Joel Cross

3
Cała ta rozmowa o wydajności ...? Testy porównawcze pokazują, że jedna metoda zajmuje 15 mikrosekund, a inna 0,15 mikrosekundy. Ale tak naprawdę, kogo to obchodzi - nie zauważysz żadnej różnicy, chyba że zrobisz to sto tysięcy razy. I wszystko może się zmienić, jeśli jQuery lub silnik JavaScript zostanie zoptymalizowany. Po prostu użyj dowolnej metody, która będzie lepiej czytać Tobie i każdemu, kto będzie musiał utrzymywać Twój kod w przyszłości.
James,


5

Właśnie zrozumiałem odpowiedź, kiedy pisałem swoje pytanie: Zadzwoń

$foo.parent()

Jeśli $f00został usunięty z DOM, to $foo.parent().length === 0. W przeciwnym razie jego długość będzie wynosić co najmniej 1.

[Edycja: Nie jest to całkowicie poprawne, ponieważ usunięty element może nadal mieć rodzica; na przykład, jeśli usuniesz a <ul>, każde z jego dzieci <li>nadal będzie miało rodzica. Zamiast tego użyj odpowiedzi SLaków.


2
... chyba że usunięty węzeł nie był jedynakiem
Álvaro González

@ Álvaro - Dlaczego miałoby to znaczenie?
user113716

@patrick: Czy coś przegapiłem? Co możesz zapewnić, jeśli długość $ foo.parent (). Jest większa od zera?
Álvaro González

@ Álvaro - OP przeprowadza testy, aby upewnić się, że $foozostał usunięty z DOM. Jeśli zostanie pomyślnie usunięty, nie będzie już miał elementu nadrzędnego. Oznacza $foo.parent().length === 0to, że usunięcie powiodło się.
user113716

1
$ foo.closest ("body") byłoby poprawką dla tej techniki
georgephillips

4

Ponieważ nie mogę odpowiedzieć jako komentarz (wydaje mi się, że jest to zbyt niska karma), oto pełna odpowiedź. Najszybszym sposobem jest łatwe rozwinięcie sprawdzania jQuery pod kątem obsługi przeglądarki i ograniczenie stałych współczynników do minimum.

Jak widać również tutaj - http://jsperf.com/jquery-element-in-dom/28 - kod wyglądałby tak:

var isElementInDOM = (function($) {
  var docElt = document.documentElement, find,
      contains = docElt.contains ?
        function(elt) { return docElt.contains(elt); } :

        docElt.compareDocumentPosition ?
          function(elt) {
            return docElt.compareDocumentPosition(elt) & 16;
          } :
          ((find = function(elt) {
              return elt && (elt == docElt || find(elt.parentNode));
           }), function(elt) { return find(elt); });

  return function(elt) {
    return !!(elt && ((elt = elt.parent) == docElt || contains(elt)));
  };
})(jQuery);

Jest to semantyczne odpowiednik jQuery.contains (document.documentElement, elt [0]).


3

Prawdopodobnie najbardziej performatywny sposób to:

document.contains(node); // boolean

Działa to również z jQuery:

document.contains($element[0]); // var $element = $("#some-element")
document.contains(this[0]); // in contexts like $.each(), `this` is the jQ object

Źródło z MDN

Uwaga:


Jak ktoś jeszcze spojrzał na tę odpowiedź? Świetna odpowiedź +1 (zaproponowałem wydanie, dzięki)
Guilherme Nascimento

1

Podobało mi się to podejście. Bez jQuery i bez wyszukiwania DOM. Najpierw znajdź najwyższego rodzica (przodka). Następnie sprawdź, czy to jest documentElement.

function ancestor(HTMLobj){
  while(HTMLobj.parentElement){HTMLobj=HTMLobj.parentElement}
  return HTMLobj;
}
function inTheDOM(obj){
  return ancestor(obj)===document.documentElement;
}

1

zamiast iterować rodziców, możesz po prostu uzyskać prostokąt ograniczający, który składa się z samych zer, gdy element jest odłączany od domeny

function isInDOM(element) {
    var rect=element.getBoundingClientRect();
    return (rect.top || rect.bottom || rect.height || rect.width)?true:false;
}

jeśli chcesz obsłużyć skrajny przypadek elementu o zerowej szerokości i wysokości na zero na górze i zero po lewej stronie, możesz dwukrotnie sprawdzić, iterując rodziców aż do dokumentu. body


Chociaż ten fragment kodu może rozwiązać problem, nie wyjaśnia, dlaczego ani jak odpowiada na pytanie. Dołącz wyjaśnienie swojego kodu , ponieważ naprawdę pomaga to poprawić jakość Twojego postu. Pamiętaj, że odpowiadasz na pytanie do czytelników w przyszłości, a osoby te mogą nie znać powodów, dla których zaproponowałeś kod. Osoby zgłaszające / recenzujące: w przypadku odpowiedzi zawierających tylko kod, takich jak ta, głosuj przeciw, nie usuwaj!
Luca Kiebel

Czy to również nie rozpoznaje ukrytych elementów jako „nie w DOM”? np. element display: nonebez ograniczeńRect
Filip

0

Zgadzam się z komentarzem Perro. Można to również zrobić w ten sposób:

$foo.parents().last().is(document.documentElement);

0
jQuery.fn.isInDOM = function () {
   if (this.length == 1) {
      var element = this.get(0);
      var rect = element.getBoundingClientRect();
      if (rect.top + rect.bottom + rect.width + rect.height + rect.left + rect.right == 0)
         return false;
      return true;
   }
   return false;
};

-1

Dlaczego nie tylko if( $('#foo').length === 0)...:?


@stevematdavies Pytanie brzmi „jak sprawdzić, czy element w danym obiekcie jQuery jest w DOM”, a nie „jak sprawdzić, czy element pasujący do danego ciągu selektora znajduje się w DOM”.
Trevor Burnham

@TrevorBurnham: z całą uczciwością ponowne zapytanie za pomocą selektora, który został użyty do utworzenia $fooi sprawdzenie, czy ponowne zapytanie pasowało do dowolnego elementu, wydaje się realnym rozwiązaniem problemu w wielu scenariuszach. Może to być nawet szybsze niż niektóre inne rozwiązania ze względu na to, jak zarówno jQuery, jak i przeglądarki optymalizują niektóre selektory (na przykład według identyfikatora).
Matt

@Matt $ foo może być elementem w pamięci odłączonym od DOM, a może tam być element z pasującym selektorem w DOM. Osoby szukające odpowiedzi na to pytanie prawdopodobnie chcą sprawdzić, czy jest w DOM, czy nie. Ktoś, kto zajmuje się takimi rzeczami, oczywiście wie, jak wysyłać zapytania do DOM.
TJ

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.