isElement - determining if an object is an element

J

Joost Diepenmaat

Aaron Gray said:

[ someone deleted the name of whoever said this ]
As Henry says this will fail with a typing error if object is not an object.

Can anyone please direct me to:

1. an example of a host object that makes the object &&
object.nodeType == 1 construct fail.

2. some explanation as to how that failure is reconciled with ecma 262.

Please do not view this post as an assertion that there are no
responses to these questions. I'm genuinely interested.
 
R

RobG

Further research shows that
<http://www.w3.org/TR/DOM-Level-3-Core/ecma-script-binding.html> eventually
observes that implementations of ECMAScript Ed. 3 do not support classes and
asserts instead that `ELEMENT_NODE' and so forth would be "Properties of the
Node Constructor function", in contrast to "Properties of objects that
implement the Node interface" defined elsewhere.  So e.g. the Gecko DOM
implementing the former as the latter is indeed a proprietary feature.

Can you suggest an appropriate object to use as the "Node constructor
function", or how to access it?

I have tried:

var a = document.createElement('div');
var msg = '';
if (a) {
msg += 'constructor: ' + typeof a.constructor;
if (a.constructor) {
msg += '\nconstructor.ELEMENT_NODE: '
+ typeof a.constructor.ELEMENT_NODE ;
}
}
alert(msg);

In Firefox, a.constructor is an object but a.constructor.ELEMENT_NODE
is undefined. In IE, a.constructor is undefined.
 
A

Aaron Gray

Joost Diepenmaat said:
Aaron Gray said:

[ someone deleted the name of whoever said this ]
As Henry says this will fail with a typing error if object is not an
object.

Can anyone please direct me to:

1. an example of a host object that makes the object &&
object.nodeType == 1 construct fail.

No !:)

I tried 'new Number(1)' and if fine on IE, FF, Opera, and Safari :-

http://www.aarongray.org/Test/JavaScript/isElement-test3a.html
2. some explanation as to how that failure is reconciled with ecma 262.

Please do not view this post as an assertion that there are no
responses to these questions. I'm genuinely interested.

Yes, we need Thomas on this one.

Aaron
 
D

David Mark

Aaron Gray said:

 [ someone deleted the name of whoever said this ]
As Henry says this will fail with a typing error if object is not an object.

Can anyone please direct me to:

1. an example of a host object that makes the object &&
object.nodeType == 1 construct fail.

In IE, some host objects throw exceptions when their properties are
type-converted. An example of such an object is window.external. In
IE, properties that throw such exceptions are invariably "unknown"
types (and the error message is "unspecified.")

You can use the typeof operator to avert such disasters.

Good:
if (typeof el.href == 'string' && el.href) {

}

Bad:
if (el.href) {

}

In IE7, a reference to a news link will throw an exception on the
second example.

Also, elements removed from the DOM will throw an exception on this:

if (el.offsetParent) {

}

These are just two examples that I know of. You have to assume there
are more.
2. some explanation as to how that failure is reconciled with ecma 262.

Nothing is explicitly wrong with any of this as host objects are
implementation dependent.
 
A

Aaron Gray

David Mark said:
These are just two examples that I know of. You have to assume there
are more.

Good enough reason to keep the test.
Nothing is explicitly wrong with any of this as host objects are
implementation dependent.

Which is a shame, no el.constructor, el instanceof Element, no useful tests
at all. Then we get to Duck Typing and we produce an Element Duck does it
quack on IE, now does it Quack on FF, Opera or Safari ? Will have to test
this one in the morning, quack, quack, quack, ...

Thanks for the good feedback,

Aaron
 
A

Aaron Gray

RobG said:
In Firefox, a.constructor is an object but a.constructor.ELEMENT_NODE
is undefined. In IE, a.constructor is undefined.

We have bee climbing up the same tree !

IE is a BAD, BAD, BAD Browser, it does not follow the others, it does not
implement SVG and it really should have taken the lead and implemented
MathML. No Microsoft ran too fast but did not cover enough ground.

Aaron
 
K

kangax

Duck Typing wins out :-

function isElement( o)
{
    return o && typeof o === "object" && o.nodeType == 1 &&typeof o.tagName
=== "string"

}

When given falsy value, this function will return the value itself
rather than true/false (as I assume it should):

isElement(null); // null (same goes for 0, '', undefined and NaN)

It might make sense to type convert an argument into a boolean first:

function isElement(o) {
return !!o && typeof o == 'object' &&
o.nodeType === 1 && typeof o.tagName == 'string';
}
 
H

Henry

This fails because it cannot be used universally, and will result in
different behaviours accross browsers if used as the general case with a sub
case for |IE.




As Henry says this will fail with a typing error if object
is not an object.

I did not say that. I said that an - in - operation would throw an
exception if its subject (right hand side operand) was not an object.
The above is completely safe in ECMAScript terms when the - object -
parameter is not a host object (and also safe with the vast majority
of host objects) because if the value as a primitive it must have
truness to pass the first type-converting test and if it has truness
it can be implicitly type-converted into an object by the dot
operator.

Duck Typing wins out :-

function isElement( o)
{
return o && typeof o === "object" && o.nodeType == 1 &&
typeof o.tagName === "string"

}
<snip>

There is nothing in the ECMAScript bindings or the DOM documentation
that says that the object implementing any DOM interface may not be a
function object, so - typeof 0 === "object" - is insufficient.

When the last in-depth discussion of the faults of JQuery's -
isFunction - function was held here one of the issues with the code
was the fact that on some Mozilla/Firefox browsers -
document.createElement('object') - returned an object that reported
'function' from a - typeof - operation (and appeared to be callable
(even if an exception was thrown during the call), so apparently that
Element _is_ a function).
 
T

Thomas 'PointedEars' Lahn

RobG said:
Can you suggest an appropriate object to use as the "Node constructor
function", or how to access it?

The object referred to by `Node'. But I have yet to see an implementation
that makes it accessible to scripts as such.
I have tried:

var a = document.createElement('div');
var msg = '';
if (a) {
msg += 'constructor: ' + typeof a.constructor;
if (a.constructor) {
msg += '\nconstructor.ELEMENT_NODE: '
+ typeof a.constructor.ELEMENT_NODE ;
}
}
alert(msg);

In Firefox, a.constructor is an object but a.constructor.ELEMENT_NODE
is undefined.

My point exactly.
In IE, a.constructor is undefined.

It should not come as a surprise that host objects do not implement the
`constructor' property as ECMAScript does not require them to have one.


PointedEars
 
T

Thomas 'PointedEars' Lahn

Aaron said:
Which is a shame, no el.constructor, el instanceof Element, no useful tests
at all.

I still wonder why you think you need such a test in the first place.
Then we get to Duck Typing and we produce an Element Duck does it
quack on IE, now does it Quack on FF, Opera or Safari ?

That would be the reasonable approach, as different implementations
would provide different properties on objects with the same purpose.


PointedEars
 
A

Aaron Gray

Henry said:
I did not say that. I said that an - in - operation would throw an
exception if its subject (right hand side operand) was not an object.
The above is completely safe in ECMAScript terms when the - object -
parameter is not a host object (and also safe with the vast majority
of host objects) because if the value as a primitive it must have
truness to pass the first type-converting test and if it has truness
it can be implicitly type-converted into an object by the dot
operator.

Sorry Henry, it was late and I did not read your reply properly.

So no Object test then.

Aaron
 
A

Aaron Gray

Henry said:
Whatever you may think, or may prefer, the second branch is the one
based upon documented (W3C) standard behaviour.

The world is upside down in my view :)
The first test is not significantly more accurate, as it is still
trivial to fool. But even so, a more accurate test in one branch is
more likely to result in issues that get through testing unnoticed
that consistent behaviour in all environments. Imagine someone who
only tests on, say, Firefox and Safari and the test successfully
rejecting its subjects, but then being released and exposed to IE
where the test lets objects passed that it should not.

Okay, or not okay :)
<snip>

How does a test that would fail on at least two current browsers and
dozens of older DOM standard browsers 'run on more browsers' than a
test that would work consistently with all?
Right.

Whether the first test is faster is something that you will have to
demonstrate, but the difference is likely to be small compared with
the overheads of the function call and the test for the branching.
Yes.

At the point of getting each of these two structures you knew
precisely which you had. You knew that because mechanism for
retrieving DOM fragments/branches don't retrieve native JS object
structures, and methods for retrieving JSON structures don't result in
DOM branches. If at some later point you have lost that information
then it is because you threw it away. You solve your problem by
keeping the information you had, not trying to recover it through
dubious inferences.

Yes, One is from inline HTML retrieved by using a getElementById the other
Object notation either inline or from AJAX.

So I need two constructors or a constructor and two initializers or two
factories.
Remember that while javascript can do a crude emulation of method
overloading it is clunky when its subjects are native JS objects, and
hugely problematic when they are host objects (nearly all the
'popular' libraries have got themselves into a mess attempting to
handle this).
Right.

We know that you knew what the object was when you acquired it, at
that should always be the case in your javascript code (it is part of
the programmer's discipline to keep track of the object types in their
code, because there is no language type-system to do that for them).
And knowing the type of object you have you are in a position to chose
an appropriate function method to call with that type as an argument.
That is a lot easier to program, and much more efficient, than having
fewer functions/methods buy having them jump through hoop trying to
work out what types of arguments they received and how they should be
behaving as a result.

Okay, I dont like it but thats my problem, if I am going to write a wigets
library and core support library for others to use I am going to have to
follow your advice.

Its a real shame ECMA-262 allowed a spit in the browsers typing system like
this :(

Thanks for your patients Henry,

Aaron
 
H

Henry

Henry wrote in message
So no Object test then.

If you mean the first type-converting test then you need to keep that
in one form or another because you should reject null an undefined
values for the - object - parameter as neither can be type-converted
into an object and so the - object.nodeType - expression will cause an
exception to be thrown.
 
H

Henry

Henry wrote in message


The world is upside down in my view :)

The world is what it is.

Yes, One is from inline HTML retrieved by using a getElementById
the other Object notation either inline or from AJAX.

So I need two constructors or a constructor and two
initializers or two factories.

Or any of 100-odd other possibilities.

Okay, I dont like it but thats my problem, if I am going to
write a wigets library and core support library for others
to use I am going to have to follow your advice.

You don't have to do anything of the sort. Obviously I would take may
own advice but there have been plenty who have had the opportunity and
not done so ;-)
Its a real shame ECMA-262 allowed a spit in the browsers
typing system like this :(
<snip>

What? ECMA has nothing to do with browsers (except by coincidence).
ECMA 262 is the language specification, it is the W3C who do browser
object model specifications, and not always as smartly, completely or
realistically as they could.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,141
Messages
2,570,814
Members
47,360
Latest member
kathdev

Latest Threads

Top