Bagaimana cara memeriksa apakah elemen jQuery ada di DOM?

147

Katakanlah saya mendefinisikan elemen

$foo = $('#foo');

dan kemudian saya menelepon

$foo.remove()

dari beberapa acara. Pertanyaan saya adalah, bagaimana saya memeriksa apakah $ foo telah dihapus dari DOM atau tidak? Saya telah menemukan itu $foo.is(':hidden')berhasil, tetapi tentu saja itu juga akan mengembalikan kebenaran jika saya hanya menelepon $foo.hide().

Trevor Burnham
sumber

Jawaban:

238

Seperti ini:

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

Ini masih akan berfungsi jika salah satu dari orang tua elemen telah dihapus (dalam hal ini elemen itu sendiri akan tetap memiliki orang tua).

Slaks
sumber
14
melakukan $foo.closest(document.documentElement)lebih cepat (jika ada yang peduli jsperf.com/jquery-element-in-dom )
urraka
48
@ PerroAzul: Saya menemukan alternatif yang jauh lebih cepat: jsperf.com/jquery-element-in-dom/2
SLaks
3
Kinerja adalah perhatian saya yang langsung dengan metode ini, terima kasih telah menghubungkan tolok ukur @SLaks. Jadi sepertinya $.contains(document.documentElement, $foo.get(0))ini cara tercepat.
Christof
10
Ada cara DOM murni untuk melakukan ini, yang secara sintaksis lebih mudah dibaca, dan saya membayangkan sangat mirip dalam hal kinerja:document.contains($foo[0])
Joel Cross
3
Semua pembicaraan tentang kinerja ini ...? Tolok ukur menunjukkan satu metode mengambil 15 mikrodetik, dan yang lain mengambil 0,15 mikrodetik. Tapi sungguh, siapa yang peduli - Anda tidak akan melihat perbedaan kecuali Anda melakukannya ratusan ribu kali. Dan itu semua mungkin berubah jika jQuery atau mesin JavaScript dioptimalkan. Gunakan metode apa pun yang lebih baik bagi Anda dan siapa pun yang harus menjaga kode Anda di masa depan.
James
21

Bagaimana dengan melakukan ini:

$element.parents('html').length > 0
Kushagra Gour
sumber
Saya pikir ini jauh lebih cepat
Trio Cheung
5

Saya baru menyadari jawaban ketika saya mengetik pertanyaan saya: Telepon

$foo.parent()

Jika $f00telah dihapus dari DOM, maka $foo.parent().length === 0. Kalau tidak, panjangnya paling tidak 1.

[Sunting: Ini tidak sepenuhnya benar, karena elemen yang dihapus masih dapat memiliki induk; misalnya, jika Anda menghapus a <ul>, masing-masing anaknya <li>masih akan memiliki orangtua. Gunakan jawaban SLaks sebagai gantinya.

Trevor Burnham
sumber
2
... kecuali simpul yang dihapus bukan satu-satunya anak
Álvaro González
@ Álvaro - Mengapa itu penting?
user113716
@ Patrick: Apakah saya melewatkan sesuatu? Apa yang bisa Anda yakinkan jika panjang $ foo.parent (). Lebih besar dari nol?
Álvaro González
@ Álvaro - OP sedang menguji untuk memastikan $footelah dihapus dari DOM. Jika berhasil dihapus, tidak akan lagi memiliki elemen induk. Karena itu $foo.parent().length === 0berarti penghapusan berhasil.
user113716
1
$ foo.closest ("body") akan menjadi perbaikan untuk teknik ini
georgephillips
4

Karena saya tidak dapat menjawab sebagai komentar (saya kira terlalu rendah karma), inilah jawaban lengkapnya. Cara tercepat adalah dengan mudah membuka gulungan jQuery untuk dukungan browser dan mencukur faktor konstan menjadi minimum.

Seperti terlihat juga di sini - http://jsperf.com/jquery-element-in-dom/28 - kode akan terlihat seperti ini:

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

Ini semantik setara dengan jQuery.contains (document.documentElement, elt [0]).

Jaakko Salomaa
sumber
3

Mungkin cara yang paling performatif adalah:

document.contains(node); // boolean

Ini juga berfungsi dengan jQuery:

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

Sumber dari MDN

catatan:

lxg
sumber
Bagaimana orang melihat jawaban ini? Jawaban bagus +1 (Saya menyarankan edisi, terima kasih)
Guilherme Nascimento
1

Saya menyukai pendekatan ini. Tidak ada jQuery dan tidak ada pencarian DOM. Pertama temukan orang tua teratas (leluhur). Kemudian lihat apakah itu documentElement.

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

alih-alih iterasi orang tua Anda hanya bisa mendapatkan kotak pembatas yang semuanya nol ketika elemen dilepaskan dari dom

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

jika Anda ingin menangani kasing tepi elemen lebar dan tinggi nol di atas nol dan di kiri nol, Anda dapat memeriksa ulang dengan mengulangi orang tua hingga dokumen.

Erez Pilosof
sumber
Meskipun potongan kode ini dapat menyelesaikan masalah, itu tidak menjelaskan mengapa atau bagaimana ia menjawab pertanyaan. Harap sertakan penjelasan untuk kode Anda , karena itu sangat membantu untuk meningkatkan kualitas posting Anda. Ingatlah bahwa Anda menjawab pertanyaan untuk pembaca di masa depan, dan orang-orang itu mungkin tidak tahu alasan untuk saran kode Anda. Penanda / pengulas: Untuk jawaban hanya kode seperti ini, downvote, jangan hapus!
Luca Kiebel
Bukankah ini juga mengenali elemen tersembunyi sebagai "tidak di DOM"? misalnya elemen yang display: nonetidak memiliki boundingRect juga
Philipp
0

Setuju dengan komentar Perro. Bisa juga dilakukan seperti ini:

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

Kenapa tidak adil if( $('#foo').length === 0)...:?

stevematdavies
sumber
@stevematdavies Pertanyaannya adalah "bagaimana menguji apakah suatu elemen dalam objek jQuery yang diberikan berada di DOM", bukan "bagaimana menguji apakah suatu elemen yang cocok dengan string pemilih yang diberikan ada di DOM."
Trevor Burnham
@TrevorBurnham: dalam semua kewajaran, meminta kembali menggunakan pemilih yang digunakan untuk membuat $foo, dan memeriksa apakah permintaan ulang cocok dengan elemen apa pun, tampaknya merupakan solusi yang layak untuk masalah dalam banyak skenario. Bahkan mungkin lebih cepat daripada beberapa solusi lain karena bagaimana jQuery dan browser mengoptimalkan penyeleksi tertentu (seperti dengan ID).
Matt
@ Mat $ foo mungkin elemen dalam memori terlepas dari DOM, dan mungkin ada elemen dengan pemilih yang cocok di DOM. Orang yang mencari jawaban untuk pertanyaan ini mungkin ingin memeriksa apakah ada di DOM atau tidak. Seseorang yang bekerja dalam hal-hal seperti itu jelas tahu bagaimana cara menanyakan DOM.
TJ
-1
if($foo.nodeType ){ element is node type}
tharo
sumber