335

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?

1
  • 5
    Am I being obtuse in wondering whether a "DOM Object" shouldn't cover not only Elements but also all Nodes (Text nodes, Attributes, etc.)? All the answers and the way you've posed the question tend to suggest this question is specifically about Elements... Commented Oct 3, 2017 at 20:21

39 Answers 39

361

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"
);
}
Sign up to request clarification or add additional context in comments.

13 Comments

It's worth noting that this will not work on elements that belong to other windows/frames. Duck typing is the recommended approach
You can fool it with: function Fake() {}; Fake.prototype=document.createElement("div"); alert(new Fake() instanceof HTMLElement);
WTF fact: Firefox 5 and earlier return true for [] instanceof HTMLElement.
Btw, HTMLElement is always a function, so typeof will throw you off the track and will execute the second part of the statement. You could try if you wish instanceof Object, because the function will be an instance of Object, or just check explicitly for typeof === "function", because Node and HTMLElement are both native object functions.
When you call isElement(0), it returns 0, not false... Why is that, and how can I prevent that?
|
127

The accepted answer checks instanceof HTMLElement, which does not cover all types of DOM elements. For example, SVG elements are not supported. In contrast, this answer works for HTML as well as SVG, etc.

function isElement(value) {
    return value instanceof Element;
}

Cherry on top: the above code is IE8 compatible.

Demo:

function isElement(value) {
  return value instanceof Element;  
}

const selectors = ['div', 'a', 'svg', 'g', 'text'];

const nonElements = [1, true, 'text', {}, [], 0, undefined, false, null];

for (const selector of selectors) {
  assert(isElement(document.querySelector(selector)));
}

for (const value of nonElements) {
  assert(!isElement(value));
}

console.log('All tests passed!');

function assert(condition) {
  if (!condition) throw new Error();
}
<div></div>
<a></a>
<svg><g /><text>foo</text></svg>

However, note that this will not work for elements from same-domain iframes, which will not pass instanceof checks.

13 Comments

'Element' is undefined on IE7
I'm of the opinion that anyone still using IE7 should spend the five seconds to download a better browser instead of putting it on us to invest days or weeks working around their refusal to get with the times.
Note that this does not work across multiple windows. I.e. window.open().document.body instanceof Element returns false.
@nik10110 You're checking if the NEW window's body instance is an instance of the OLD window's Element. It works if you adjust your code as below :-) win = window.open(); win.document.body instanceof win.Element; // true
I can appreciate that there are restrictions to a point. However the point of such restrictions is to limit security liabilities. At this point restricting to IE7 for the sake of security is like trying to put a deadbolt lock on a door that is a tarp flap.
|
54

No need for hacks, you can just ask if an element is an instance of the DOM Element:

const isDOM = el => el instanceof Element

9 Comments

Brilliant! Works!
Has almost complete compatibility (caniuse.com/mdn-javascript_operators_instanceof), this should be the accepted answer
@AiShiguang addEventListener("click", ({ target }) => console.log(target, target instanceof Element)); always reports the element (<input>, <div>, <body>, <html>) and true, in the latest Firefox and Chrome. There’s no reason why it wouldn’t. What value of target are you seeing instead? What browser are you using?
Aww~ my bad. Mine was in an iframe. therefore it's not window.Element
I love this simple and working solution!
|
12

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.

1 Comment

"typeof document.body.cloneNode" does return "object" in my IE
10

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

3 Comments

Way too verbose. The comparison will already return a boolean: return typeof entity === 'object' && typeof entity.nodeType !== undefined;
Very interesting! Sometimes, depending on the Types you have on your objects and/or poperties, this can be very handy! Tx, @Roman
Ironically, because null is an "object", you'll see: TypeError: null is not an object (evaluating 'entity.nodeType')
8

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

6 Comments

Does this work? It's still a solution. A creative one at that.
+1 for the creativity and certainty this offers. However, if the node happens to be part of the DOM already, you've just removed it! So ... this answer is incomplete without doing the work to re-add the element to the DOM if necessary.
I'm reading this after almost 5 years, and I think it's one of the coolest. It just needs to be refined. You can try to append a clone of the node to a detached element, for example. If that's not a DOM object. something will surely go wrong. Still quite an expensive solution, though.
This is really expensive and unnecessarily complicated. See my answer below, stackoverflow.com/a/36894871/1204556
It's creative and would be fine except it has the horrible side-effect of altering the object that you are testing! I.e. it potentially removes the valid DOM element from it's current parent! @Greg should alter the answer to mention this explicitly as it is dangerous to use as-is.
|
8

How about Lo-Dash's _.isElement?

$ npm install lodash.iselement

And in the code:

var isElement = require("lodash.iselement");
isElement(document.body);

3 Comments

I like this solution. It is simple, and it works in Edge and IE, even for elements in separate iframes, unlike most of the highest voted solutions here.
This answer is helpful, though one would need Webpack to run NPM modules in the browser.
Easy to manufacture false positives though: _.isElement(Object.create({}, { nodeType: { value: 1 } })) === true
6

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';
    }
}

3 Comments

This code doesn't assert that the object is a DOM element; only that it looks a little bit like one. Any object can be given a nodeName and nodeType property and satisfy this code.
This answer does not detect all types of HTML elements. For example, SVG elements are not supported. See my answer below.
Doesn't really work on all elements, for example SVG. See my answer below, stackoverflow.com/a/36894871/1204556
4

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

2 Comments

I've tested this in latest Chrome and FF, and also in IE11, and it works everywhere, also for text nodes and objects created via document.createElement() but not inserted in DOM too. Amazing (: Thank you
This looks like a decent answer, though mine does a lot of the same stuff and is less complicated. stackoverflow.com/a/36894871/1204556
4

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

Comments

3
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

1 Comment

obj.constructor.name doesn't work in IE, because in IE, functions do not have the name property. Replace by obj.constructor != Object.
3

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

4 Comments

Anything falsy should short-circuit your boolean. undefined && window.spam("should bork") never evaluates the fake spam function, for instance. So no !! needed, I don't believe. That, can you provide a [non-academic] edge case where its use matters?
Thank you for your aclaration. I used *!!* double negation to convert all expression to boolean value, not truthy or falsy.
Right, but there's no practical reason to do it, I don't think -- see here. And it's certainly not necessary to take advantage of Short-Cut eval here. Even if you didn't buy the "!! is never needed" argument (and if you don't, I'm curious why not), you could edit that line to return !!(obj && typeof obj === "object" && obj.nodeType === 1 && obj.nodeName); and have it operate the same.
That was what I did ;) more clean and same effect. thank you.
2

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

Comments

2

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.

3 Comments

1) changing objects you don't own is not advisable. 2) this doesn't detect elements that aren't not part of the same document.
this will still not be detected js var fake = Object.create(Element.prototype)
First, what we're trying to do on another document which we don't have any control on it? Second, why we're creating a fake object from Element instead of document.createElement? I didn't understand the use cases here.
2

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

Comments

1

In Firefox, you can use the instanceof Node. That Node is defined in DOM1.

But that is not that easy in IE.

  1. "instanceof ActiveXObject" only can tell that it is a native object.
  2. "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)

Comments

1

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

1 Comment

Good try, but exception handling is too expensive a cost if it can be avoided. Also, ES5 allows you to define read-only properties for objects.
1

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

3 Comments

typeof ({innerHTML: ""}).innerHTML === "string"
HOT! This response should be the game winner. if(typeof obj.innerHTML!=='string') //not a dom element.
I initially reacted against @Qtax 's and thomasrutter's critique on an earlier answer, but I'm starting to buy it. Though I haven't run into dogs quacking like ducks exactly like this before, I can see someone not checking if something's a node, running notANode.innerHTML = "<b>Whoops</b>";, then later having that code pass its contaminated obj to this code. Defensive code === better code, all other things equal, and this ultimately isn't defensive.
1

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.

Comments

1

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.

Comments

1

For the ones using Angular:

angular.isElement

https://docs.angularjs.org/api/ng/function/angular.isElement

1 Comment

More useful to include Angular's code: function isElement(node) { return !!(node && (node.nodeName || (node.prop && node.attr && node.find))); } Looks a little like @finpingvin's. Note that it is determining "if a reference is a DOM element (or wrapped jQuery element)."
1

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

2 Comments

first of all, you don't need to return true or return false, just return the if statement. Second, this will return true for {nodeType:1}
I tend to use overly verbose code (on this site) for the purpose of making the intention of the code clearer ;)
1

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

3 Comments

Interesting solution. It would be helpful to have a little more detail on why/how this works. What does the method compare in the end?
js thinks everithing as object , ojects extends by prototype, standard dom elements all share "toString" method that returns 4ex "HTMLDivElement"
Thanks for the details. I've just tested it myself and see document.body.toString() returns the string "[object HTMLBodyElement]". If I get that right, another way to write isDOM could be return -1 !== x.toString().indexOf("[object HTML")
1

Here's a simple solution to this task that checks the most basic important criterias of a DOM HTML element:

const isHTMLEl = o => typeof o === 'object' && !!o.tagName && o instanceof HTMLElement && !!o.nodeType;

const obj = document.createElement('iframe');
console.log( isHTMLEl(obj) ); // returns true
console.log( isHTMLEl([]) ); // return false
console.log( isHTMLEl('<div />') ); // returns false

Comments

1

Most answers use some kind of duck typing, checking for example that the object has a nodeType property. But that's not enough, because non-nodes can also have node-like properties.

The other common approach is instanceof, which can produce false positives e.g. with Object.create(Node), which is not a node despite inheriting node properties. In addition, elements from same-origin iframes will not pass instanceof checks, giving false negatives.

Moreover, both approaches above call internal essential methods, which can be problematic e.g. if the tested value is a proxy.

Instead, what I recommend is borrowing a node attribute getter and calling it on our object. The browser will check that the value is a node by looking at internal slots not customizable in proxies, so even they won't be able to interfere with our check.

/**
 * @param proto The prototype of the Web IDL interface to check.
 * @param prop The name of the Web IDL attribute to check.
 * This must have a getter that throws when called on invalid targets.
 * @returns A type guard for the given Web IDL interface.
 */
function createWebIdlBrandGuard(proto, prop) {
    const getter = Object.getOwnPropertyDescriptor(proto, prop).get;
    return (x) => {
        try {
            getter.call(x);
            return true;
        } catch {
            return false;
        }
    }
}

const isNode = createWebIdlBrandGuard(Node.prototype, 'nodeName');
const isText = createWebIdlBrandGuard(Text.prototype, 'wholeText');
const isElement = createWebIdlBrandGuard(Element.prototype, 'tagName');
const isHTMLElement = createWebIdlBrandGuard(HTMLElement.prototype, 'title');
const isDocument = createWebIdlBrandGuard(Document.prototype, 'contentType');

// tests

test('top', window.document);
// // Uncomment to test iframe.
// // Note that this will fail in the stack snippet due to sandboxing rules,
// // but it will pass if you run the code elsewhere without sandboxing.
// test('iframe', document.body.appendChild(document.createElement('iframe')).contentDocument);

function test(description, document) {
    console.group(description);
    try {
        document.body.innerHTML = ('<div>foo</div><svg></svg>');

        const div = document.querySelector('div');
        const svg = document.querySelector('svg');
        const text = div.firstChild;

        step(() => isNode(document));
        step(() => !isText(document));
        step(() => !isElement(document));
        step(() => !isHTMLElement(document));
        step(() => isDocument(document));

        step(() => isNode(div));
        step(() => !isText(div));
        step(() => isElement(div));
        step(() => isHTMLElement(div));
        step(() => !isDocument(div));

        step(() => isNode(svg));
        step(() => !isText(svg));
        step(() => isElement(svg));
        step(() => !isHTMLElement(svg));
        step(() => !isDocument(svg));

        step(() => isNode(text));
        step(() => isText(text));
        step(() => !isElement(text));
        step(() => !isHTMLElement(text));
        step(() => !isDocument(text));
    } finally {
        console.groupEnd(description);
    }
}

function step(fn) {
    const message = fn.toString().replace(/^\(\)\s*=>\s*/, '');
    if (!fn()) throw new Error(`💥 ${message} failed`);
    console.info(`✅ ${message}`);
}

3 Comments

you isElement may return true for other objects with 'value' property, your isHTMLElement issues a click
@kofifus Can you provide an example which breaks isElement? And about the click, I thought it wasn't much harmful. HTMLElement.prototype does not contain many methods, but of course using a property getter (as shown in the hidden snippet) would be safer, but less clear.
@oriol Great answer, I think this is the most reliable from both false positives (Object.create etc) and false negatives (same-origin iframes). But the usage of click definitely seems like a bad idea, as you'd never expect checking isHTMLElement to have side effects: if (isHTMLElement(document.queryselector('form#sell-your-firstborns-soul-to-satan button[type=submit]'))) { /* do something harmless... */ }
0

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

}

2 Comments

jQuery is internally doing elem.nodeType === 1 so why not save the call overhead and the jQuery dependency and have your isElement function do that itself?
It's 2016, just say "no".
0

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.

Comments

0

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

Test In IE 5

Comments

0

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

Comments

0

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:

  1. The object is not null.

  2. The object has a method called "appendChild".

  3. The method "appendChild" was inherited from the Node class, and isn't just an imposter method (a user-created property with an identical name).

  4. 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;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.