Wie überprüfe ich, ob sich ein jQuery-Element im DOM befindet?

147

Angenommen, ich definiere ein Element

$foo = $('#foo');

und dann rufe ich an

$foo.remove()

von einem Ereignis. Meine Frage ist, wie überprüfe ich, ob $ foo aus dem DOM entfernt wurde oder nicht? Ich habe festgestellt, dass das $foo.is(':hidden')funktioniert, aber das würde natürlich auch wahr sein, wenn ich nur anrufe $foo.hide().

Trevor Burnham
quelle

Antworten:

238

So was:

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

Dies funktioniert weiterhin, wenn eines der übergeordneten Elemente des Elements entfernt wurde (in diesem Fall hat das Element selbst weiterhin ein übergeordnetes Element).

SLaks
quelle
14
tun $foo.closest(document.documentElement)ist schneller (wenn es jemanden interessiert jsperf.com/jquery-element-in-dom )
urraka
48
@PerroAzul: Ich habe eine viel schnellere Alternative gefunden: jsperf.com/jquery-element-in-dom/2
SLaks
3
Die Leistung war mein unmittelbares Anliegen bei dieser Methode, danke für die Verknüpfung der Benchmarks @SLaks. Es sieht also so aus, $.contains(document.documentElement, $foo.get(0))als wäre dies der schnellste Weg.
Christof
10
Es gibt einen reinen DOM-Weg, der syntaktisch besser lesbar ist, und ich stelle mir in Bezug auf die Leistung sehr ähnlich vor:document.contains($foo[0])
Joel Cross
3
All das Gerede von Leistung ...? Die Benchmarks zeigen, dass eine Methode 15 Mikrosekunden und eine andere 0,15 Mikrosekunden dauert. Aber wirklich, wen interessiert das? Sie werden keinen Unterschied bemerken, wenn Sie es nicht hunderttausend Mal tun. Und es könnte sich alles ändern, wenn jQuery oder die JavaScript-Engine optimiert werden. Verwenden Sie einfach die Methode, die für Sie und jeden, der Ihren Code in Zukunft warten muss, besser lesbar ist.
James
21

Wie wäre es damit:

$element.parents('html').length > 0
Kushagra Gour
quelle
Ich denke, das ist viel schneller
Trio Cheung
5

Ich habe gerade eine Antwort erhalten, als ich meine Frage tippte: Anruf

$foo.parent()

Wenn $f00aus dem DOM entfernt wurde, dann $foo.parent().length === 0. Andernfalls beträgt seine Länge mindestens 1.

[Bearbeiten: Dies ist nicht ganz korrekt, da ein entferntes Element noch ein übergeordnetes Element haben kann. Wenn Sie beispielsweise a entfernen <ul>, hat jedes seiner Kinder <li>weiterhin ein Elternteil. Verwenden Sie stattdessen die Antwort von SLaks.

Trevor Burnham
quelle
2
... es sei denn, der entfernte Knoten war kein Einzelkind
Álvaro González
@ Álvaro - Warum sollte das wichtig sein?
user113716
@patrick: Habe ich etwas verpasst? Was können Sie sicherstellen, wenn die Länge von $ foo.parent () größer als Null ist?
Álvaro González
@ Álvaro - Das OP testet, um sicherzustellen, dass $fooes aus dem DOM entfernt wurde. Wenn es erfolgreich entfernt wurde, hat es kein übergeordnetes Element mehr. Dies $foo.parent().length === 0bedeutet, dass die Entfernung erfolgreich war.
user113716
1
$ foo.closest ("body") wäre eine Lösung für diese Technik
Georgephillips
4

Da ich nicht als Kommentar antworten kann (zu geringes Karma, denke ich), ist hier eine vollständige Antwort. Der schnellste Weg ist einfach, den jQuery-Check für die Browserunterstützung abzuwickeln und die konstanten Faktoren auf ein Minimum zu reduzieren.

Wie auch hier zu sehen - http://jsperf.com/jquery-element-in-dom/28 - würde der Code folgendermaßen aussehen:

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);

Dies entspricht semantisch jQuery.contains (document.documentElement, elt [0]).

Jaakko Salomaa
quelle
3

Der wahrscheinlich performativste Weg ist:

document.contains(node); // boolean

Dies funktioniert auch mit jQuery:

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

Quelle von MDN

Hinweis:

lxg
quelle
Wie hat jemand diese Antwort schon gesehen? Tolle Antwort +1 (Ich habe eine Ausgabe vorgeschlagen, danke)
Guilherme Nascimento
1

Dieser Ansatz hat mir gefallen. Keine jQuery und keine DOM-Suche. Finden Sie zuerst den obersten Elternteil (Vorfahren). Überprüfen Sie dann, ob dies das documentElement ist.

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

Anstatt Eltern zu iterieren, können Sie einfach das Begrenzungsrecht erhalten, das alle Nullen sind, wenn das Element von dom getrennt wird

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

Wenn Sie den Randfall eines Elements mit der Breite und Höhe Null bei Null oben und Null links behandeln möchten, können Sie dies überprüfen, indem Sie die Eltern bis zum document.body iterieren

Erez Pilosof
quelle
Dieses Codefragment kann das Problem zwar lösen, erklärt jedoch nicht, warum oder wie es die Frage beantwortet. Bitte geben Sie eine Erklärung für Ihren Code an , da dies wirklich zur Verbesserung der Qualität Ihres Beitrags beiträgt. Denken Sie daran, dass Sie die Frage für Leser in Zukunft beantworten und diese Personen möglicherweise die Gründe für Ihren Codevorschlag nicht kennen. Flagger / Rezensenten: Für Nur-Code-Antworten wie diese, Downvote, nicht löschen!
Luca Kiebel
Erkennt dies nicht auch versteckte Elemente als "nicht in DOM"? zB ein Element mit display: nonehat auch kein BoundingRect
Philipp
0

Stimmen Sie Perros Kommentar zu. Es kann auch so gemacht werden:

$foo.parents().last().is(document.documentElement);
Ian Bytchek
quelle
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;
};
Rodrigo Zoff
quelle
-1

Warum nicht einfach : if( $('#foo').length === 0)...?

Stevematdavies
quelle
@stevematdavies Die Frage lautet: "Wie wird getestet, ob sich ein Element in einem bestimmten jQuery-Objekt im DOM befindet?" und nicht, wie wird geprüft, ob sich ein Element, das mit einer bestimmten Auswahlzeichenfolge übereinstimmt, im DOM befindet.
Trevor Burnham
@TrevorBurnham: Um ehrlich zu sein $foo, scheint es in vielen Szenarien eine praktikable Lösung für das Problem zu sein, mit dem Selektor, der zum Erstellen verwendet wurde , erneut abzufragen und zu überprüfen, ob die erneute Abfrage mit einem Element übereinstimmt. Es kann sogar schneller sein als einige der anderen Lösungen, da sowohl jQuery als auch die Browser bestimmte Selektoren optimieren (z. B. nach ID).
Matt
@Matt $ foo ist möglicherweise ein Element im Speicher, das vom DOM getrennt ist, und es gibt möglicherweise ein Element mit einem passenden Selektor im DOM. Leute, die nach einer Antwort auf diese Frage suchen, möchten wahrscheinlich überprüfen, ob sie in DOM ist oder nicht. Jemand, der in solchen Dingen arbeitet, weiß offensichtlich, wie man DOM abfragt.
TJ
-1
if($foo.nodeType ){ element is node type}
Tharo
quelle