Reputation: 77416
Let's say that I define an element
$foo = $('#foo');
and then I call
$foo.remove()
from some event. My question is, how do I check whether $foo has been removed from the DOM or not? I've found that $foo.is(':hidden')
works, but that would of course also return true if I merely called $foo.hide()
.
Upvotes: 158
Views: 62301
Reputation: 81
instead of iterating parents you can just get the bounding rect which is all zeros when the element is detached from dom
function isInDOM(element) {
var rect=element.getBoundingClientRect();
return (rect.top || rect.bottom || rect.height || rect.width)?true:false;
}
if you want to handle the edge case of a zero width and height element at zero top and zero left you can double check by iterating parents till the document.body
Upvotes: 2
Reputation: 13107
Probably the most performative way is:
document.contains(node); // boolean
This also works with jQuery:
document.contains($element[0]); // var $element = $("#some-element")
document.contains(this[0]); // in contexts like $.each(), `this` is the jQ object
Source from MDN
Note:
Upvotes: 9
Reputation: 174
I liked this approach. No jQuery and no DOM search. First find the top parent (ancestor). Then see if that is the documentElement.
function ancestor(HTMLobj){
while(HTMLobj.parentElement){HTMLobj=HTMLobj.parentElement}
return HTMLobj;
}
function inTheDOM(obj){
return ancestor(obj)===document.documentElement;
}
Upvotes: 1
Reputation: 1
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;
};
Upvotes: 0
Reputation: 887275
Like this:
if (!jQuery.contains(document, $foo[0])) {
//Element is detached
}
This will still work if one of the element's parents was removed (in which case the element itself will still have a parent).
Upvotes: 247
Reputation: 146
Since I'm unable to respond as a comment (too low karma I guess), here's a full reply. The fastest way is easily to unroll the jQuery check for browser support and to shave the constant factors to minimum.
As seen also here - http://jsperf.com/jquery-element-in-dom/28 - the code would look like this:
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);
This is semantically equivalent to jQuery.contains(document.documentElement, elt[0]).
Upvotes: 5
Reputation: 9075
Agree with Perro's comment. It can also be done like this:
$foo.parents().last().is(document.documentElement);
Upvotes: 0
Reputation: 77416
I just realized an answer as I was typing my question: Call
$foo.parent()
If $f00
has been removed from the DOM, then $foo.parent().length === 0
. Otherwise, its length will be at least 1.
[Edit: This is not entirely correct, because a removed element can still have a parent; for instance, if you remove a <ul>
, each of its child <li>
s will still have a parent. Use SLaks' answer instead.
Upvotes: 6