Come posso verificare se un elemento jQuery si trova nel DOM?


147

Diciamo che definisco un elemento

$foo = $('#foo');

e poi chiamo

$foo.remove()

da qualche evento. La mia domanda è: come posso verificare se $ foo è stato rimosso o meno dal DOM? Ho scoperto che $foo.is(':hidden')funziona, ma che ovviamente ritornerebbe vero anche se avessi semplicemente chiamato $foo.hide().

Risposte:


238

Come questo:

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

Funzionerà comunque se uno dei genitori dell'elemento fosse rimosso (nel qual caso l'elemento stesso avrà ancora un genitore).


14
fare $foo.closest(document.documentElement)è più veloce (se qualcuno si prende cura di jsperf.com/jquery-element-in-dom )
urraka,

48
@PerroAzul: ho trovato un'alternativa molto più veloce: jsperf.com/jquery-element-in-dom/2
SLaks

3
Le prestazioni sono state la mia preoccupazione immediata per questo metodo, grazie per il collegamento dei benchmark @SLaks. Quindi sembra che $.contains(document.documentElement, $foo.get(0))sia il modo più veloce.
Christof,

10
Esiste un modo pure-DOM per farlo, che è sintatticamente più leggibile e immagino molto simile in termini di prestazioni:document.contains($foo[0])
Joel Cross

3
Tutto questo parlare di performance ...? I benchmark mostrano un metodo che richiede 15 microsecondi e un altro che richiede 0,15 microsecondi. Ma davvero, a chi importa - non noterai alcuna differenza se non lo fai centomila volte. E tutto potrebbe cambiare se jQuery o il motore JavaScript venissero ottimizzati, basta usare qualunque metodo legga meglio per te e per chiunque debba conservare il tuo codice in futuro.
James,


5

Ho appena realizzato una risposta mentre stavo scrivendo la mia domanda: Chiama

$foo.parent()

Se $f00è stato rimosso dal DOM, quindi $foo.parent().length === 0. Altrimenti, la sua lunghezza sarà almeno 1.

[Modifica: questo non è del tutto corretto, perché un elemento rimosso può ancora avere un genitore; per esempio, se rimuovi a <ul>, ognuno dei suoi figli <li>avrà comunque un genitore. Usa invece la risposta di SLaks.


2
... a meno che il nodo rimosso non fosse figlio unico
Álvaro González,

@ Álvaro - Perché dovrebbe importare?
user113716

@patrick: mi sono perso qualcosa? Cosa puoi assicurare se $ foo.parent (). Lunghezza è maggiore di zero?
Álvaro González,

@ Álvaro - l'OP sta testando per assicurarsi che sia $foostato rimosso dal DOM. Se è stato rimosso con successo, non avrà più un elemento padre. Pertanto $foo.parent().length === 0significa che la rimozione ha avuto esito positivo.
user113716

1
$ foo.closest ("body") sarebbe una correzione per questa tecnica
georgephillips

4

Dato che non sono in grado di rispondere come commento (immagino un karma troppo basso), ecco una risposta completa. Il modo più veloce è srotolare facilmente il controllo jQuery per il supporto del browser e ridurre al minimo i fattori costanti.

Come visto anche qui - http://jsperf.com/jquery-element-in-dom/28 - il codice sarebbe simile al seguente:

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

Questo è semanticamente equivalente a jQuery.contains (document.documentElement, elt [0]).


3

Probabilmente il modo più performante è:

document.contains(node); // boolean

Questo funziona anche con jQuery:

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

Fonte da MDN

Nota:


In che modo qualcuno ha ancora visto questa risposta? Ottima risposta +1 (ho suggerito un'edizione, grazie)
Guilherme Nascimento,

1

Mi è piaciuto questo approccio. No jQuery e nessuna ricerca DOM. Per prima cosa trova il genitore principale (antenato). Quindi vedi se questo è documentElement.

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

1

invece di iterare i genitori, puoi semplicemente ottenere il rettangolo di limitazione che è tutto zeri quando l'elemento è staccato da dom

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

se si desidera gestire il caso limite di un elemento di larghezza e altezza zero in alto a zero e zero a sinistra, è possibile verificare due volte ripetendo i genitori fino al documento


Sebbene questo frammento di codice possa risolvere il problema, non spiega perché o come risponde alla domanda. Includi una spiegazione per il tuo codice , in quanto ciò aiuta davvero a migliorare la qualità del tuo post. Ricorda che stai rispondendo alla domanda per i lettori in futuro e che queste persone potrebbero non conoscere i motivi del tuo suggerimento sul codice. Flaggers / recensori: per le risposte di solo codice come questo, downvote, non eliminare!
Luca Kiebel,

Questo non riconosce anche gli elementi nascosti come "non in DOM"? ad es. un elemento con display: nonenon ha limitiRect neanche
Philipp

0

Concordo con il commento di Perro. Può anche essere fatto in questo modo:

$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

Perché non solo if( $('#foo').length === 0)...:?


@stevematdavies La domanda è "come verificare se un elemento in un determinato oggetto jQuery si trova nel DOM", non "come verificare se un elemento che corrisponde a una determinata stringa del selettore si trova nel DOM".
Trevor Burnham,

@TrevorBurnham: in tutta onestà, ri-interrogare usando il selettore che è stato usato per creare $foo, e controllare se il ri-interrogare corrispondeva a qualsiasi elemento, sembra una soluzione praticabile al problema in molti scenari. Può anche essere più veloce di alcune delle altre soluzioni a causa del modo in cui sia jQuery che i browser ottimizzano determinati selettori (ad esempio tramite ID).
Matt,

@Matt $ foo potrebbe essere un elemento in memoria staccato da DOM e potrebbe esserci un elemento con selettore corrispondente in DOM. Le persone in cerca di una risposta a questa domanda probabilmente vogliono verificare se è in DOM o meno. Qualcuno che lavora in cose del genere ovviamente sa come interrogare DOM.
TJ

-1
if($foo.nodeType ){ element is node type}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.