Related
How can I check the existence of an element in jQuery?
The current code that I have is this:
if ($(selector).length > 0) {
// Do something
}
Is there a more elegant way to approach this? Perhaps a plugin or a function?
In JavaScript, everything is 'truthy' or 'falsy', and for numbers 0 means false, everything else true. So you could write:
if ($(selector).length)
You don't need that >0 part.
Yes!
jQuery.fn.exists = function(){ return this.length > 0; }
if ($(selector).exists()) {
// Do something
}
This is in response to: Herding Code podcast with Jeff Atwood
If you used
jQuery.fn.exists = function(){return ($(this).length > 0);}
if ($(selector).exists()) { }
you would imply that chaining was possible when it is not.
This would be better:
jQuery.exists = function(selector) {return ($(selector).length > 0);}
if ($.exists(selector)) { }
Alternatively, from the FAQ:
if ( $('#myDiv').length ) { /* Do something */ }
You could also use the following. If there are no values in the jQuery object array then getting the first item in the array would return undefined.
if ( $('#myDiv')[0] ) { /* Do something */ }
You can use this:
// if element exists
if($('selector').length){ /* do something */ }
// if element does not exist
if(!$('selector').length){ /* do something */ }
The fastest and most semantically self explaining way to check for existence is actually by using plain JavaScript:
if (document.getElementById('element_id')) {
// Do something
}
It is a bit longer to write than the jQuery length alternative, but executes faster since it is a native JS method.
And it is better than the alternative of writing your own jQuery function. That alternative is slower, for the reasons #snover stated. But it would also give other programmers the impression that the exists() function is something inherent to jQuery. JavaScript would/should be understood by others editing your code, without increased knowledge debt.
NB: Notice the lack of an '#' before the element_id (since this is plain JS, not jQuery).
You can save a few bytes by writing:
if ($(selector)[0]) { ... }
This works because each jQuery object also masquerades as an array, so we can use the array dereferencing operator to get the first item from the array. It returns undefined if there is no item at the specified index.
You can use:
if ($(selector).is('*')) {
// Do something
}
A little more elegant, perhaps.
This plugin can be used in an if statement like if ($(ele).exist()) { /* DO WORK */ } or using a callback.
Plugin
;;(function($) {
if (!$.exist) {
$.extend({
exist: function() {
var ele, cbmExist, cbmNotExist;
if (arguments.length) {
for (x in arguments) {
switch (typeof arguments[x]) {
case 'function':
if (typeof cbmExist == "undefined") cbmExist = arguments[x];
else cbmNotExist = arguments[x];
break;
case 'object':
if (arguments[x] instanceof jQuery) ele = arguments[x];
else {
var obj = arguments[x];
for (y in obj) {
if (typeof obj[y] == 'function') {
if (typeof cbmExist == "undefined") cbmExist = obj[y];
else cbmNotExist = obj[y];
}
if (typeof obj[y] == 'object' && obj[y] instanceof jQuery) ele = obj[y];
if (typeof obj[y] == 'string') ele = $(obj[y]);
}
}
break;
case 'string':
ele = $(arguments[x]);
break;
}
}
}
if (typeof cbmExist == 'function') {
var exist = ele.length > 0 ? true : false;
if (exist) {
return ele.each(function(i) { cbmExist.apply(this, [exist, ele, i]); });
}
else if (typeof cbmNotExist == 'function') {
cbmNotExist.apply(ele, [exist, ele]);
return ele;
}
else {
if (ele.length <= 1) return ele.length > 0 ? true : false;
else return ele.length;
}
}
else {
if (ele.length <= 1) return ele.length > 0 ? true : false;
else return ele.length;
}
return false;
}
});
$.fn.extend({
exist: function() {
var args = [$(this)];
if (arguments.length) for (x in arguments) args.push(arguments[x]);
return $.exist.apply($, args);
}
});
}
})(jQuery);
jsFiddle
You may specify one or two callbacks. The first one will fire if the element exists, the second one will fire if the element does not exist. However, if you choose to pass only one function, it will only fire when the element exists. Thus, the chain will die if the selected element does not exist. Of course, if it does exist, the first function will fire and the chain will continue.
Keep in mind that using the callback variant helps maintain chainability – the element is returned and you can continue chaining commands as with any other jQuery method!
Example Uses
if ($.exist('#eleID')) { /* DO WORK */ } // param as STRING
if ($.exist($('#eleID'))) { /* DO WORK */ } // param as jQuery OBJECT
if ($('#eleID').exist()) { /* DO WORK */ } // enduced on jQuery OBJECT
$.exist('#eleID', function() { // param is STRING && CALLBACK METHOD
/* DO WORK */
/* This will ONLY fire if the element EXIST */
}, function() { // param is STRING && CALLBACK METHOD
/* DO WORK */
/* This will ONLY fire if the element DOES NOT EXIST */
})
$('#eleID').exist(function() { // enduced on jQuery OBJECT with CALLBACK METHOD
/* DO WORK */
/* This will ONLY fire if the element EXIST */
})
$.exist({ // param is OBJECT containing 2 key|value pairs: element = STRING, callback = METHOD
element: '#eleID',
callback: function() {
/* DO WORK */
/* This will ONLY fire if the element EXIST */
}
})
I see most of the answers here are not accurate as they should be, they check element length, it can be OK in many cases, but not 100%, imagine if number pass to the function instead, so I prototype a function which check all conditions and return the answer as it should be:
$.fn.exists = $.fn.exists || function() {
return !!(this.length && (this[0] instanceof HTMLDocument || this[0] instanceof HTMLElement));
}
This will check both length and type, Now you can check it this way:
$(1980).exists(); //return false
$([1,2,3]).exists(); //return false
$({name: 'stackoverflow', url: 'http://www.stackoverflow.com'}).exists(); //return false
$([{nodeName: 'foo'}]).exists() // returns false
$('div').exists(); //return true
$('.header').exists(); //return true
$(document).exists(); //return true
$('body').exists(); //return true
There's no need for jQuery really. With plain JavaScript it's easier and semantically correct to check for:
if(document.getElementById("myElement")) {
//Do something...
}
If for any reason you don't want to put an id to the element, you can still use any other JavaScript method designed to access the DOM.
jQuery is really cool, but don't let pure JavaScript fall into oblivion...
You could use this:
jQuery.fn.extend({
exists: function() { return this.length }
});
if($(selector).exists()){/*do something*/}
The reason all of the previous answers require the .length parameter is that they are mostly using jquery's $() selector which has querySelectorAll behind the curtains (or they are using it directly). This method is rather slow because it needs to parse the entire DOM tree looking for all matches to that selector and populating an array with them.
The ['length'] parameter is not needed or useful and the code will be a lot faster if you directly use document.querySelector(selector) instead, because it returns the first element it matches or null if not found.
function elementIfExists(selector){ //named this way on purpose, see below
return document.querySelector(selector);
}
/* usage: */
var myelement = elementIfExists("#myid") || myfallbackelement;
However this method leaves us with the actual object being returned; which is fine if it isn't going to be saved as variable and used repeatedly (thus keeping the reference around if we forget).
var myel=elementIfExists("#myid");
// now we are using a reference to the element which will linger after removal
myel.getParentNode.removeChild(myel);
console.log(elementIfExists("#myid")); /* null */
console.log(myel); /* giant table lingering around detached from document */
myel=null; /* now it can be garbage collected */
In some cases this may be desired. It can be used in a for loop like this:
/* locally scoped myel gets garbage collected even with the break; */
for (var myel; myel = elementIfExist(sel); myel.getParentNode.removeChild(myel))
if (myel == myblacklistedel) break;
If you don't actually need the element and want to get/store just a true/false, just double not it !! It works for shoes that come untied, so why knot here?
function elementExists(selector){
return !!document.querySelector(selector);
}
/* usage: */
var hastables = elementExists("table"); /* will be true or false */
if (hastables){
/* insert css style sheet for our pretty tables */
}
setTimeOut(function (){if (hastables && !elementExists("#mytablecss"))
alert("bad table layouts");},3000);
Is $.contains() what you want?
jQuery.contains( container, contained )
The $.contains() method returns true if the DOM element provided by the second argument is a descendant of the DOM element provided by the first argument, whether it is a direct child or nested more deeply. Otherwise, it returns false. Only element nodes are supported; if the second argument is a text or comment node, $.contains() will return false.
Note: The first argument must be a DOM element, not a jQuery object or plain JavaScript object.
You can check element is present or not using length in java script.
If length is greater than zero then element is present if length is zero then
element is not present
// These by Id
if ($("#elementid").length > 0) {
// Element is Present
} else {
// Element is not Present
}
// These by Class
if ($(".elementClass").length > 0) {
// Element is Present
} else {
// Element is not Present
}
I have found if ($(selector).length) {} to be insufficient. It will silently break your app when selector is an empty object {}.
var $target = $({});
console.log($target, $target.length);
// Console output:
// -------------------------------------
// [▼ Object ] 1
// ► __proto__: Object
My only suggestion is to perform an additional check for {}.
if ($.isEmptyObject(selector) || !$(selector).length) {
throw new Error('Unable to work with the given selector.');
}
I'm still looking for a better solution though as this one is a bit heavy.
Edit: WARNING! This doesn't work in IE when selector is a string.
$.isEmptyObject('hello') // FALSE in Chrome and TRUE in IE
Checking for existence of an element is documented neatly in the official jQuery website itself!
Use the .length property of the jQuery collection returned by your
selector:
if ($("#myDiv").length) {
$("#myDiv").show();
}
Note that it isn't always necessary to test whether an element exists.
The following code will show the element if it exists, and do nothing
(with no errors) if it does not:
$("#myDiv").show();
this is very similar to all of the answers, but why not use the ! operator twice so you can get a boolean:
jQuery.fn.exists = function(){return !!this.length};
if ($(selector).exists()) {
// the element exists, now what?...
}
No need for jQuery (basic solution)
if(document.querySelector('.a-class')) {
// do something
}
Much more performant option below (notice the lack of a dot before a-class).
if(document.getElementsByClassName('a-class')[0]) {
// do something
}
querySelector uses a proper matching engine like $() (sizzle) in jQuery and uses more computing power but in 99% of cases will do just fine. The second option is more explicit and tells the code exactly what to do. It's much faster according to JSBench https://jsbench.me/65l2up3t8i
$(selector).length && //Do something
Try testing for DOM element
if (!!$(selector)[0]) // do stuff
Inspired by hiway's answer I came up with the following:
$.fn.exists = function() {
return $.contains( document.documentElement, this[0] );
}
jQuery.contains takes two DOM elements and checks whether the first one contains the second one.
Using document.documentElement as the first argument fulfills the semantics of the exists method when we want to apply it solely to check the existence of an element in the current document.
Below, I've put together a snippet that compares jQuery.exists() against the $(sel)[0] and $(sel).length approaches which both return truthy values for $(4) while $(4).exists() returns false. In the context of checking for existence of an element in the DOM this seems to be the desired result.
$.fn.exists = function() {
return $.contains(document.documentElement, this[0]);
}
var testFuncs = [
function(jq) { return !!jq[0]; },
function(jq) { return !!jq.length; },
function(jq) { return jq.exists(); },
];
var inputs = [
["$()",$()],
["$(4)",$(4)],
["$('#idoexist')",$('#idoexist')],
["$('#idontexist')",$('#idontexist')]
];
for( var i = 0, l = inputs.length, tr, input; i < l; i++ ) {
input = inputs[i][1];
tr = "<tr><td>" + inputs[i][0] + "</td><td>"
+ testFuncs[0](input) + "</td><td>"
+ testFuncs[1](input) + "</td><td>"
+ testFuncs[2](input) + "</td></tr>";
$("table").append(tr);
}
td { border: 1px solid black }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="idoexist">#idoexist</div>
<table style>
<tr>
<td>Input</td><td>!!$(sel)[0]</td><td>!!$(sel).length</td><td>$(sel).exists()</td>
</tr>
</table>
<script>
$.fn.exists = function() {
return $.contains(document.documentElement, this[0]);
}
</script>
I just like to use plain vanilla javascript to do this.
function isExists(selector){
return document.querySelectorAll(selector).length>0;
}
I stumbled upon this question and i'd like to share a snippet of code i currently use:
$.fn.exists = function(callback) {
var self = this;
var wrapper = (function(){
function notExists () {}
notExists.prototype.otherwise = function(fallback){
if (!self.length) {
fallback.call();
}
};
return new notExists;
})();
if(self.length) {
callback.call();
}
return wrapper;
}
And now i can write code like this -
$("#elem").exists(function(){
alert ("it exists");
}).otherwise(function(){
alert ("it doesn't exist");
});
It might seem a lot of code, but when written in CoffeeScript it is quite small:
$.fn.exists = (callback) ->
exists = #length
callback.call() if exists
new class
otherwise: (fallback) ->
fallback.call() if not exists
I had a case where I wanted to see if an object exists inside of another so I added something to the first answer to check for a selector inside the selector..
// Checks if an object exists.
// Usage:
//
// $(selector).exists()
//
// Or:
//
// $(selector).exists(anotherSelector);
jQuery.fn.exists = function(selector) {
return selector ? this.find(selector).length : this.length;
};
How about:
function exists(selector) {
return $(selector).length;
}
if (exists(selector)) {
// do something
}
It's very minimal and saves you having to enclose the selector with $() every time.
I'm using this:
$.fn.ifExists = function(fn) {
if (this.length) {
$(fn(this));
}
};
$("#element").ifExists(
function($this){
$this.addClass('someClass').animate({marginTop:20},function(){alert('ok')});
}
);
Execute the chain only if a jQuery element exist - http://jsfiddle.net/andres_314/vbNM3/2/
$("selector") returns an object which has the length property. If the selector finds any elements, they will be included in the object. So if you check its length you can see if any elements exist. In JavaScript 0 == false, so if you don't get 0 your code will run.
if($("selector").length){
//code in the case
}
Here is my favorite exist method in jQuery
$.fn.exist = function(callback) {
return $(this).each(function () {
var target = $(this);
if (this.length > 0 && typeof callback === 'function') {
callback.call(target);
}
});
};
and other version which supports callback when selector does not exist
$.fn.exist = function(onExist, onNotExist) {
return $(this).each(function() {
var target = $(this);
if (this.length > 0) {
if (typeof onExist === 'function') {
onExist.call(target);
}
} else {
if (typeof onNotExist === 'function') {
onNotExist.call(target);
}
}
});
};
Example:
$('#foo .bar').exist(
function () {
// Stuff when '#foo .bar' exists
},
function () {
// Stuff when '#foo .bar' does not exist
}
);
You don't have to check if it's greater than 0 like $(selector).length > 0, $(selector).length it's enough and an elegant way to check the existence of elements. I don't think that it is worth to write a function only for this, if you want to do more extra things, then yes.
if($(selector).length){
// true if length is not 0
} else {
// false if length is 0
}
Here is the complete example of different situations and way to check if element exists using direct if on jQuery selector may or may not work because it returns array or elements.
var a = null;
var b = []
var c = undefined ;
if(a) { console.log(" a exist")} else { console.log("a doesn't exit")}
// output: a doesn't exit
if(b) { console.log(" b exist")} else { console.log("b doesn't exit")}
// output: b exist
if(c) { console.log(" c exist")} else { console.log("c doesn't exit")}
// output: c doesn't exit
FINAL SOLUTION
if($("#xysyxxs").length){ console.log("xusyxxs exist")} else { console.log("xusyxxs doesnn't exist") }
//output : xusyxxs doesnn't exist
if($(".xysyxxs").length){ console.log("xusyxxs exist")} else { console.log("xusyxxs doesnn't exist") }
//output : xusyxxs doesnn't exist
Demo
console.log("existing id", $('#id-1').length)
console.log("non existing id", $('#id-2').length)
console.log("existing class single instance", $('.cls-1').length)
console.log("existing class multiple instance", $('.cls-2').length)
console.log("non existing class", $('.cls-3').length)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="id-1">
<div class="cls-1 cls-2"></div>
<div class="cls-2"></div>
</div>
So as im building a small plugin I can across a small issue, when filtering the selectors I check if the selector is an Array, which in most cases works but when using a attribute(dataset in this case) it sees the selector as an array.
Is there a way to fix this?
var Constructor = function (selector) {
if (!selector) return;
if (selector === 'document') {
this.nodes = [document];
} else if (selector === 'window') {
this.nodes = [window];
} else if(typeof selector === 'string') {
this.nodes = document.querySelectorAll(selector);
}else{
this.nodes = Array.isArray ? selector : [selector];// it will return as an array
}
};
partofanplugin.find('[data-id="12"]')// will be seen as an array instead of a string.
You need to actually call the function, right now you are just checking if the function exists
Array.isArray(selector) ? selector : [selector];
instead of
Array.isArray ? selector : [selector];
Is it possible to have object extensions in JavaScript? For example
Extensions.js
function any.isNullOrEmpty() {
if (this == null || this == "") {
return true
}
return false
}
app.js
var x = ""
console.log(x.isNullOrEmpty()) //should log true
is this possible? How do I do it?
You could add a method to the Object prototype, and use the valueOf method to get the value of the string:
...but, because null is a primitive that cannot have a method, the only way I can think of to get the target to be null would be to use call, apply or bind.
But you would never do this in production code, because modifying the prototype of built-in objects is discouraged.
'use strict' // important for the use of `call` and `null`
Object.prototype.isNullOrEmpty = function() { return this === null || this.valueOf() === '' }
const s = ''
console.log(s.isNullOrEmpty())
const t = null
console.log(Object.prototype.isNullOrEmpty.call(t))
You could use Object.prototype to extend this type of functionality in JavaScript.
Object.prototype.isNullOrEmpty = function() {
if (this == null || this == "") {
return true
}
return false
}
var x = "";
x.isNullOrEmpty(); // returns true
you need to add your custom method into prop type of object or array or everything u want to use your method on it.
but in your case you need to this like code below:
Object.prototype.isNullOrEmpty = function(){
if (this === null || this == "") {
return true
}
return false
}
let a = {a:'10'}
console.log(a.isNullOrEmpty())
function validateValue(value){
function isNullEmpty(){
return (value === void (0) || value == null)
}
return { isNullOrEmpty }
}
}
I have a function that checks to see whether or not a request has any queries, and does different actions based off that. Currently, I have if(query) do this else something else. However, it seems that when there is no query data, I end up with a {} JSON object. As such, I need to replace if(query) with if(query.isEmpty()) or something of that sort. Can anybody explain how I could go about doing this in NodeJS? Does the V8 JSON object have any functionality of this sort?
You can use either of these functions:
// This should work in node.js and other ES5 compliant implementations.
function isEmptyObject(obj) {
return !Object.keys(obj).length;
}
// This should work both there and elsewhere.
function isEmptyObject(obj) {
for (var key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
return false;
}
}
return true;
}
Example usage:
if (isEmptyObject(query)) {
// There are no queries.
} else {
// There is at least one query,
// or at least the query object is not empty.
}
You can use this:
var isEmpty = function(obj) {
return Object.keys(obj).length === 0;
}
or this:
function isEmpty(obj) {
return !Object.keys(obj).length > 0;
}
You can also use this:
function isEmpty(obj) {
for(var prop in obj) {
if(obj.hasOwnProperty(prop))
return false;
}
return true;
}
If using underscore or jQuery, you can use their isEmpty or isEmptyObject calls.
Object.keys(myObj).length === 0;
As there is need to just check if Object is empty it will be better to directly call a native method Object.keys(myObj).length which returns the array of keys by internally iterating with for..in loop.As Object.hasOwnProperty returns a boolean result based on the property present in an object which itself iterates with for..in loop and will have time complexity O(N2).
On the other hand calling a UDF which itself has above two implementations or other will work fine for small object but will block the code which will have severe impact on overall perormance if Object size is large unless nothing else is waiting in the event loop.
If you have compatibility with Object.keys, and node does have compatibility, you should use that for sure.
However, if you do not have compatibility, and for any reason using a loop function is out of the question - like me, I used the following solution:
JSON.stringify(obj) === '{}'
Consider this solution a 'last resort' use only if must.
See in the comments "there are many ways in which this solution is not ideal".
I had a last resort scenario, and it worked perfectly.
My solution:
let isEmpty = (val) => {
let typeOfVal = typeof val;
switch(typeOfVal){
case 'object':
return (val.length == 0) || !Object.keys(val).length;
break;
case 'string':
let str = val.trim();
return str == '' || str == undefined;
break;
case 'number':
return val == '';
break;
default:
return val == '' || val == undefined;
}
};
console.log(isEmpty([1,2,4,5])); // false
console.log(isEmpty({id: 1, name: "Trung",age: 29})); // false
console.log(isEmpty('TrunvNV')); // false
console.log(isEmpty(8)); // false
console.log(isEmpty('')); // true
console.log(isEmpty(' ')); // true
console.log(isEmpty([])); // true
console.log(isEmpty({})); // true
const isEmpty = (value) => (
value === undefined ||
value === null ||
(typeof value === 'object' && Object.keys(value).length === 0) ||
(typeof value === 'string' && value.trim().length === 0)
)
module.exports = isEmpty;
I'm trying to get:
document.createElement('div') //=> true
{tagName: 'foobar something'} //=> false
In my own scripts, I used to just use this since I never needed tagName as a property:
if (!object.tagName) throw ...;
So for the second object, I came up with the following as a quick solution -- which mostly works. ;)
The problem is, it depends on browsers enforcing read-only properties, which not all do.
function isDOM(obj) {
var tag = obj.tagName;
try {
obj.tagName = ''; // Read-only for DOM, should throw exception
obj.tagName = tag; // Restore for normal objects
return false;
} catch (e) {
return true;
}
}
Is there a good substitute?
This might be of interest:
function isElement(obj) {
try {
//Using W3 DOM2 (works for FF, Opera and Chrome)
return obj instanceof HTMLElement;
}
catch(e){
//Browsers not supporting W3 DOM2 don't have HTMLElement and
//an exception is thrown and we end up here. Testing some
//properties that all elements have (works on IE7)
return (typeof obj==="object") &&
(obj.nodeType===1) && (typeof obj.style === "object") &&
(typeof obj.ownerDocument ==="object");
}
}
It's part of the DOM, Level2.
Update 2: This is how I implemented it in my own library:
(the previous code didn't work in Chrome, because Node and HTMLElement are functions instead of the expected object. This code is tested in FF3, IE7, Chrome 1 and Opera 9).
//Returns true if it is a DOM node
function isNode(o){
return (
typeof Node === "object" ? o instanceof Node :
o && typeof o === "object" && typeof o.nodeType === "number" && typeof o.nodeName==="string"
);
}
//Returns true if it is a DOM element
function isElement(o){
return (
typeof HTMLElement === "object" ? o instanceof HTMLElement : //DOM2
o && typeof o === "object" && o !== null && o.nodeType === 1 && typeof o.nodeName==="string"
);
}
The accepted answer is a bit complicated, and does not detect all types of HTML elements. For example, SVG elements are not supported. In contrast, this answer works for HTML as well as SVG, etc.
See it in action here: https://jsfiddle.net/eLuhbu6r/
function isElement(element) {
return element instanceof Element || element instanceof HTMLDocument;
}
Cherry on top: the above code is IE8 compatible.
No need for hacks, you can just ask if an element is an instance of the DOM Element:
const isDOM = el => el instanceof Element
All solutions above and below (my solution including) suffer from possibility of being incorrect, especially on IE — it is quite possible to (re)define some objects/methods/properties to mimic a DOM node rendering the test invalid.
So usually I use the duck-typing-style testing: I test specifically for things I use. For example, if I want to clone a node I test it like this:
if(typeof node == "object" && "nodeType" in node &&
node.nodeType === 1 && node.cloneNode){
// most probably this is a DOM node, we can clone it safely
clonedNode = node.cloneNode(false);
}
Basically it is a little sanity check + the direct test for a method (or a property) I am planning to use.
Incidentally the test above is a good test for DOM nodes on all browsers. But if you want to be on the safe side always check the presence of methods and properties and verify their types.
EDIT: IE uses ActiveX objects to represent nodes, so their properties do not behave as true JavaScript object, for example:
console.log(typeof node.cloneNode); // object
console.log(node.cloneNode instanceof Function); // false
while it should return "function" and true respectively. The only way to test methods is to see if the are defined.
A simple way to test if a variable is a DOM element (verbose, but more traditional syntax :-)
function isDomEntity(entity) {
if(typeof entity === 'object' && entity.nodeType !== undefined){
return true;
}
else{
return false;
}
}
Or as HTMLGuy suggested (short and clean syntax):
const isDomEntity = entity =>
typeof entity === 'object' && entity.nodeType !== undefined
You could try appending it to a real DOM node...
function isDom(obj)
{
var elm = document.createElement('div');
try
{
elm.appendChild(obj);
}
catch (e)
{
return false;
}
return true;
}
How about Lo-Dash's _.isElement?
$ npm install lodash.iselement
And in the code:
var isElement = require("lodash.iselement");
isElement(document.body);
This is from the lovely JavaScript library MooTools:
if (obj.nodeName){
switch (obj.nodeType){
case 1: return 'element';
case 3: return (/\S/).test(obj.nodeValue) ? 'textnode' : 'whitespace';
}
}
The using the root detection found here, we can determine whether e.g. alert is a member of the object's root, which is then likely to be a window:
function isInAnyDOM(o) {
return (o !== null) && !!(o.ownerDocument && (o.ownerDocument.defaultView || o.ownerDocument.parentWindow).alert); // true|false
}
To determine whether the object is the current window is even simpler:
function isInCurrentDOM(o) {
return (o !== null) && !!o.ownerDocument && (window === (o.ownerDocument.defaultView || o.ownerDocument.parentWindow)); // true|false
}
This seems to be less expensive than the try/catch solution in the opening thread.
Don P
old thread, but here's an updated possibility for ie8 and ff3.5 users:
function isHTMLElement(o) {
return (o.constructor.toString().search(/\object HTML.+Element/) > -1);
}
var IsPlainObject = function ( obj ) { return obj instanceof Object && ! ( obj instanceof Function || obj.toString( ) !== '[object Object]' || obj.constructor.name !== 'Object' ); },
IsDOMObject = function ( obj ) { return obj instanceof EventTarget; },
IsDOMElement = function ( obj ) { return obj instanceof Node; },
IsListObject = function ( obj ) { return obj instanceof Array || obj instanceof NodeList; },
// In fact I am more likely t use these inline, but sometimes it is good to have these shortcuts for setup code
I think prototyping is not a very good solution but maybe this is the fastest one:
Define this code block;
Element.prototype.isDomElement = true;
HTMLElement.prototype.isDomElement = true;
than check your objects isDomElement property:
if(a.isDomElement){}
I hope this helps.
This could be helpful: isDOM
//-----------------------------------
// Determines if the #obj parameter is a DOM element
function isDOM (obj) {
// DOM, Level2
if ("HTMLElement" in window) {
return (obj && obj instanceof HTMLElement);
}
// Older browsers
return !!(obj && typeof obj === "object" && obj.nodeType === 1 && obj.nodeName);
}
In the code above, we use the double negation operator to get the boolean value of the object passed as argument, this way we ensure that each expression evaluated in the conditional statement be boolean, taking advantage of the Short-Circuit Evaluation, thus the function returns true or false
According to mdn
Element is the most general base class from which all objects in a Document inherit. It only has methods and properties common to all kinds of elements.
We can implement isElement by prototype. Here is my advice:
/**
* #description detect if obj is an element
* #param {*} obj
* #returns {Boolean}
* #example
* see below
*/
function isElement(obj) {
if (typeof obj !== 'object') {
return false
}
let prototypeStr, prototype
do {
prototype = Object.getPrototypeOf(obj)
// to work in iframe
prototypeStr = Object.prototype.toString.call(prototype)
// '[object Document]' is used to detect document
if (
prototypeStr === '[object Element]' ||
prototypeStr === '[object Document]'
) {
return true
}
obj = prototype
// null is the terminal of object
} while (prototype !== null)
return false
}
console.log(isElement(document)) // true
console.log(isElement(document.documentElement)) // true
console.log(isElement(document.body)) // true
console.log(isElement(document.getElementsByTagName('svg')[0])) // true or false, decided by whether there is svg element
console.log(isElement(document.getElementsByTagName('svg'))) // false
console.log(isElement(document.createDocumentFragment())) // false
I think that what you have to do is make a thorough check of some properties that will always be in a dom element, but their combination won't most likely be in another object, like so:
var isDom = function (inp) {
return inp && inp.tagName && inp.nodeName && inp.ownerDocument && inp.removeAttribute;
};
In Firefox, you can use the instanceof Node. That Node is defined in DOM1.
But that is not that easy in IE.
"instanceof ActiveXObject" only can tell that it is a native object.
"typeof document.body.appendChild=='object'" tell that it may be DOM object, but also can be something else have same function.
You can only ensure it is DOM element by using DOM function and catch if any exception. However, it may have side effect (e.g. change object internal state/performance/memory leak)
Perhaps this is an alternative? Tested in Opera 11, FireFox 6, Internet Explorer 8, Safari 5 and Google Chrome 16.
function isDOMNode(v) {
if ( v===null ) return false;
if ( typeof v!=='object' ) return false;
if ( !('nodeName' in v) ) return false;
var nn = v.nodeName;
try {
// DOM node property nodeName is readonly.
// Most browsers throws an error...
v.nodeName = 'is readonly?';
} catch (e) {
// ... indicating v is a DOM node ...
return true;
}
// ...but others silently ignore the attempt to set the nodeName.
if ( v.nodeName===nn ) return true;
// Property nodeName set (and reset) - v is not a DOM node.
v.nodeName = nn;
return false;
}
Function won't be fooled by e.g. this
isDOMNode( {'nodeName':'fake'} ); // returns false
You can see if the object or node in question returns a string type.
typeof (array).innerHTML === "string" => false
typeof (object).innerHTML === "string" => false
typeof (number).innerHTML === "string" => false
typeof (text).innerHTML === "string" => false
//any DOM element will test as true
typeof (HTML object).innerHTML === "string" => true
typeof (document.createElement('anything')).innerHTML === "string" => true
This is what I figured out:
var isHTMLElement = (function () {
if ("HTMLElement" in window) {
// Voilà. Quick and easy. And reliable.
return function (el) {return el instanceof HTMLElement;};
} else if ((document.createElement("a")).constructor) {
// We can access an element's constructor. So, this is not IE7
var ElementConstructors = {}, nodeName;
return function (el) {
return el && typeof el.nodeName === "string" &&
(el instanceof ((nodeName = el.nodeName.toLowerCase()) in ElementConstructors
? ElementConstructors[nodeName]
: (ElementConstructors[nodeName] = (document.createElement(nodeName)).constructor)))
}
} else {
// Not that reliable, but we don't seem to have another choice. Probably IE7
return function (el) {
return typeof el === "object" && el.nodeType === 1 && typeof el.nodeName === "string";
}
}
})();
To improve performance I created a self-invoking function that tests the browser's capabilities only once and assigns the appropriate function accordingly.
The first test should work in most modern browsers and was already discussed here. It just tests if the element is an instance of HTMLElement. Very straightforward.
The second one is the most interesting one. This is its core-functionality:
return el instanceof (document.createElement(el.nodeName)).constructor
It tests whether el is an instance of the construcor it pretends to be. To do that, we need access to an element's contructor. That's why we're testing this in the if-Statement. IE7 for example fails this, because (document.createElement("a")).constructor is undefined in IE7.
The problem with this approach is that document.createElement is really not the fastest function and could easily slow down your application if you're testing a lot of elements with it. To solve this, I decided to cache the constructors. The object ElementConstructors has nodeNames as keys with its corresponding constructors as values. If a constructor is already cached, it uses it from the cache, otherwise it creates the Element, caches its constructor for future access and then tests against it.
The third test is the unpleasant fallback. It tests whether el is an object, has a nodeType property set to 1 and a string as nodeName. This is not very reliable of course, yet the vast majority of users shouldn't even fall back so far.
This is the most reliable approach I came up with while still keeping performance as high as possible.
Test if obj inherits from Node.
if (obj instanceof Node){
// obj is a DOM Object
}
Node is a basic Interface from which HTMLElement and Text inherit.
For the ones using Angular:
angular.isElement
https://docs.angularjs.org/api/ng/function/angular.isElement
This will work for almost any browser. (No distinction between elements and nodes here)
function dom_element_check(element){
if (typeof element.nodeType !== 'undefined'){
return true;
}
return false;
}
differentiate a raw js object from a HTMLElement
function isDOM (x){
return /HTML/.test( {}.toString.call(x) );
}
use:
isDOM( {a:1} ) // false
isDOM( document.body ) // true
// OR
Object.defineProperty(Object.prototype, "is",
{
value: function (x) {
return {}.toString.call(this).indexOf(x) >= 0;
}
});
use:
o={}; o.is("HTML") // false
o=document.body; o.is("HTML") // true
here's a trick using jQuery
var obj = {};
var element = document.getElementById('myId'); // or simply $("#myId")
$(obj).html() == undefined // true
$(element).html() == undefined // false
so putting it in a function:
function isElement(obj){
return (typeOf obj === 'object' && !($(obj).html() == undefined));
}
Not to hammer on this or anything but for ES5-compliant browsers why not just:
function isDOM(e) {
return (/HTML(?:.*)Element/).test(Object.prototype.toString.call(e).slice(8, -1));
}
Won't work on TextNodes and not sure about Shadow DOM or DocumentFragments etc. but will work on almost all HTML tag elements.
A absolute right method, check target is a real html element
primary code:
(function (scope) {
if (!scope.window) {//May not run in window scope
return;
}
var HTMLElement = window.HTMLElement || window.Element|| function() {};
var tempDiv = document.createElement("div");
var isChildOf = function(target, parent) {
if (!target) {
return false;
}
if (parent == null) {
parent = document.body;
}
if (target === parent) {
return true;
}
var newParent = target.parentNode || target.parentElement;
if (!newParent) {
return false;
}
return isChildOf(newParent, parent);
}
/**
* The dom helper
*/
var Dom = {
/**
* Detect if target element is child element of parent
* #param {} target The target html node
* #param {} parent The the parent to check
* #returns {}
*/
IsChildOf: function (target, parent) {
return isChildOf(target, parent);
},
/**
* Detect target is html element
* #param {} target The target to check
* #returns {} True if target is html node
*/
IsHtmlElement: function (target) {
if (!X.Dom.IsHtmlNode(target)) {
return false;
}
return target.nodeType === 1;
},
/**
* Detect target is html node
* #param {} target The target to check
* #returns {} True if target is html node
*/
IsHtmlNode:function(target) {
if (target instanceof HTMLElement) {
return true;
}
if (target != null) {
if (isChildOf(target, document.documentElement)) {
return true;
}
try {
tempDiv.appendChild(target.cloneNode(false));
if (tempDiv.childNodes.length > 0) {
tempDiv.innerHTML = "";
return true;
}
} catch (e) {
}
}
return false;
}
};
X.Dom = Dom;
})(this);
Each DOMElement.constructor returns function HTML...Element() or [Object HTML...Element] so...
function isDOM(getElem){
if(getElem===null||typeof getElem==="undefined") return false;
var c = getElem.constructor.toString();
var html = c.search("HTML")!==-1;
var element = c.search("Element")!==-1;
return html&&element;
}
I have a special way to do this that has not yet been mentioned in the answers.
My solution is based on four tests. If the object passes all four, then it is an element:
The object is not null.
The object has a method called "appendChild".
The method "appendChild" was inherited from the Node class, and isn't just an imposter method (a user-created property with an identical name).
The object is of Node Type 1 (Element). Objects that inherit methods from the Node class are always Nodes, but not necessarily Elements.
Q: How do I check if a given property is inherited and isn't just an imposter?
A: A simple test to see if a method was truly inherited from Node is to first verify that the property has a type of "object" or "function". Next, convert the property to a string and check if the result contains the text "[Native Code]". If the result looks something like this:
function appendChild(){
[Native Code]
}
Then the method has been inherited from the Node object. See https://davidwalsh.name/detect-native-function
And finally, bringing all the tests together, the solution is:
function ObjectIsElement(obj) {
var IsElem = true;
if (obj == null) {
IsElem = false;
} else if (typeof(obj.appendChild) != "object" && typeof(obj.appendChild) != "function") {
//IE8 and below returns "object" when getting the type of a function, IE9+ returns "function"
IsElem = false;
} else if ((obj.appendChild + '').replace(/[\r\n\t\b\f\v\xC2\xA0\x00-\x1F\x7F-\x9F ]/ig, '').search(/\{\[NativeCode]}$/i) == -1) {
IsElem = false;
} else if (obj.nodeType != 1) {
IsElem = false;
}
return IsElem;
}
(element instanceof $ && element.get(0) instanceof Element) || element instanceof Element
This will check for even if it is a jQuery or JavaScript DOM element
The only way to guarentee you're checking an actual HTMLEement, and not just an object with the same properties as an HTML Element, is to determine if it inherits from Node, since its impossible to make a new Node() in JavaScript. (unless the native Node function is overwritten, but then you're out of luck). So:
function isHTML(obj) {
return obj instanceof Node;
}
console.log(
isHTML(test),
isHTML(ok),
isHTML(p),
isHTML(o),
isHTML({
constructor: {
name: "HTML"
}
}),
isHTML({
__proto__: {
__proto__: {
__proto__: {
__proto__: {
constructor: {
constructor: {
name: "Function"
},
name: "Node"
}
}
}
}
}
}),
)
<div id=test></div>
<blockquote id="ok"></blockquote>
<p id=p></p>
<br id=o>
<!--think of anything else you want--!>