views:

3720

answers:

6

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 2nd object, I came up with the following as a quick solution -- which mostly works. ;)

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

Does anyone know a good substitute?

A: 

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';
    }
}
finpingvin
A: 

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;
};
Andreas Grech
A: 

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;
}
Greg
+7  A: 

This might be of interest:

function isElement(obj) {
  try {
    //Using W3 DOM2 (works for FF, Opera and Chrom)
    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 Crome because Node and HTMLElement are functions instead of the expected object. This code is tested in FF3, IE7, Crome 1 and Opera 9)

//Returns true if it is a DOM node
function isNode(o){
  return (
    typeof Node === "object" ? o instanceof Node : 
    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
    typeof o === "object" && o.nodeType === 1 && typeof o.nodeName==="string"
);
}
some
The non W3 DOM2 should probably be return (typeof obj==="object") to work in all browsers.
some
A: 

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)

Dennis Cheung
A: 
Eugene Lazutkin
"typeof document.body.cloneNode" does return "object" in my IE
Dennis Cheung
good catch -- corrected
Eugene Lazutkin