By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
438,384 Members | 1,886 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 438,384 IT Pros & Developers. It's quick & easy.

isElement - determining if an object is an element

P: n/a
Due to M$'s stupidity in not making DOMElements first class citizens the
following will not work :-

function isElement( o)
{
return o instanceof Element
}

It works for FF, Opera and Safari.

What prototype does is this :-

isElement: function(object) {
return object && object.nodeType == 1
}

My version used Browser sniffing :-

function isElement( o)
{
if (!isIE)
return o instanceof Element
else
return o && o.nodeType == 1 && o.tagName != undefined
}

Test case :-

http://www.aarongray.org/Test/JavaSc...ment-test.html

The actual 'isIE' test code is not the best but is used for brevity.

Any crevats, problems or enhancements most welcome.

Thanks,

Aaron
Jul 30 '08 #1
Share this Question
Share on Google+
53 Replies


P: n/a
On Jul 30, 2:46 pm, Aaron Gray wrote:
<snip>
function isElement( o)
{
if (!isIE)
return o instanceof Element
else
return o && o.nodeType == 1 && o.tagName != undefined
}
<snip>

Why branch for this? If the second test is ever good enough it is
always good enough.

Exact equality (===) with 1 would be more precise than type-converting
equality and reduce the possible false positives.

But overall what it the point? If you inferred from a true result from
a call to your - isElement - method that the object implemented the
whole W3C Core DOM (Level 1 or 2) Element interface you would be wrong
in a number of cases. It would make more sense to decide what features
you wanted from such an element and test for those alone on a basis
driven by need.
Jul 30 '08 #2

P: n/a
"Henry" <rc*******@raindrop.co.ukwrote in message
news:35**********************************@2g2000hs n.googlegroups.com...
On Jul 30, 2:46 pm, Aaron Gray wrote:
<snip>
> function isElement( o)
{
if (!isIE)
return o instanceof Element
else
return o && o.nodeType == 1 && o.tagName != undefined
}
<snip>

Why branch for this? If the second test is ever good enough it is
always good enough.
Because I would like to use "conforming" browser traits, not that this is
actually one, but it should have been in my view. I take your point. But the
first test is faster and more accurate and runs on more browsers.
Exact equality (===) with 1 would be more precise than type-converting
equality and reduce the possible false positives.
Yes forgot to change that. Thanks,
But overall what it the point? If you inferred from a true result from
a call to your - isElement - method that the object implemented the
whole W3C Core DOM (Level 1 or 2) Element interface you would be wrong
in a number of cases. It would make more sense to decide what features
you wanted from such an element and test for those alone on a basis
driven by need.
Basically my library widget constructors either take a DOM structure,
normally the enclosing DIV (which is what I was wanting to test for) or a
JSON like object which describes the object, directly (or over AJAX).

Thanks for the feedback,

Aaron
Jul 30 '08 #3

P: n/a
"Aaron Gray" <an********@gmail.comwrote in message
news:6f************@mid.individual.net...
"Henry" <rc*******@raindrop.co.ukwrote in message
news:35**********************************@2g2000hs n.googlegroups.com...
>On Jul 30, 2:46 pm, Aaron Gray wrote:
<snip>
>> function isElement( o)
{
if (!isIE)
return o instanceof Element
else
return o && o.nodeType == 1 && o.tagName != undefined
}
<snip>

Why branch for this? If the second test is ever good enough it is
always good enough.

Because I would like to use "conforming" browser traits, not that this is
actually one, but it should have been in my view. I take your point. But
the first test is faster and more accurate and runs on more browsers.
>Exact equality (===) with 1 would be more precise than type-converting
equality and reduce the possible false positives.

Yes forgot to change that. Thanks,
>But overall what it the point? If you inferred from a true result from
a call to your - isElement - method that the object implemented the
whole W3C Core DOM (Level 1 or 2) Element interface you would be wrong
in a number of cases. It would make more sense to decide what features
you wanted from such an element and test for those alone on a basis
driven by need.

Basically my library widget constructors either take a DOM structure,
normally the enclosing DIV (which is what I was wanting to test for) or a
JSON like object which describes the object, directly (or over AJAX).
So here's a more effiecient version

if (!isIE)
var isElement = function( o)
{
return o instanceof Element
}
else
var isElement = function( o)
{
return o && o.nodeType === 1 && o.tagName !== undefined
}

As per usual any critisms are welcome :)

Thanks,

Aaron
Jul 30 '08 #4

P: n/a
"Aaron Gray" <an********@gmail.comwrote in message
news:6f************@mid.individual.net...
"Aaron Gray" <an********@gmail.comwrote in message
news:6f************@mid.individual.net...
>"Henry" <rc*******@raindrop.co.ukwrote in message
news:35**********************************@2g2000h sn.googlegroups.com...
>>On Jul 30, 2:46 pm, Aaron Gray wrote:
<snip>
function isElement( o)
{
if (!isIE)
return o instanceof Element
else
return o && o.nodeType == 1 && o.tagName != undefined
}
<snip>

Why branch for this? If the second test is ever good enough it is
always good enough.

Because I would like to use "conforming" browser traits, not that this is
actually one, but it should have been in my view. I take your point. But
the first test is faster and more accurate and runs on more browsers.
>>Exact equality (===) with 1 would be more precise than type-converting
equality and reduce the possible false positives.

Yes forgot to change that. Thanks,
>>But overall what it the point? If you inferred from a true result from
a call to your - isElement - method that the object implemented the
whole W3C Core DOM (Level 1 or 2) Element interface you would be wrong
in a number of cases. It would make more sense to decide what features
you wanted from such an element and test for those alone on a basis
driven by need.

Basically my library widget constructors either take a DOM structure,
normally the enclosing DIV (which is what I was wanting to test for) or a
JSON like object which describes the object, directly (or over AJAX).

So here's a more effiecient version

if (!isIE)
var isElement = function( o)
{
return o instanceof Element
}
else
var isElement = function( o)
{
return o && o.nodeType === 1 && o.tagName !== undefined
}

As per usual any critisms are welcome :)
There's an updated test here :-

http://www.aarongray.org/Test/JavaSc...ent-test2.html

Thanks,

Aaron
Jul 30 '08 #5

P: n/a
On Jul 30, 11:52*am, "Aaron Gray" <ang.use...@gmail.comwrote:
"Aaron Gray" <ang.use...@gmail.comwrote in message

news:6f************@mid.individual.net...
"Henry" <rcornf...@raindrop.co.ukwrote in message
news:35**********************************@2g2000hs n.googlegroups.com...
On Jul 30, 2:46 pm, Aaron Gray wrote:
<snip>
* * function isElement( o)
* * {
* * * * if (!isIE)
* * * * * * return o instanceof Element
* * * * else
* * * * * * return o && o.nodeType == 1 && o.tagName != undefined
* * }
<snip>
Why branch for this? If the second test is ever good enough it is
always good enough.
Because I would like to use "conforming" browser traits, not that this is
actually one, but it should have been in my view. I take your point. But
the first test is faster and more accurate and runs on more browsers.
Exact equality (===) with 1 would be more precise than type-converting
equality and reduce the possible false positives.
Yes forgot to change that. Thanks,
But overall what it the point? If you inferred from a true result from
a call to your - isElement - method that the object implemented the
whole W3C Core DOM (Level 1 or 2) Element interface you would be wrong
in a number of cases. It would make more sense to decide what features
you wanted from such an element and test for those alone on a basis
driven by need.
Basically my library widget constructors either take a DOM structure,
normally the enclosing DIV (which is what I was wanting to test for) ora
JSON like object which describes the object, directly (or over AJAX).

So here's a more effiecient version

* * *if (!isIE)
* * * * var isElement = function( o)
* * * * {
* * * * * * *return o instanceof Element
* * * * }
* * else
* * * * var isElement = function( o)
* * * * {
* * * * * * *return o && o.nodeType === 1 && o.tagName !== undefined
* * * * }

As per usual any critisms are welcome :)

Thanks,

Aaron
o.tagName != '!'

Lose the sniffing branch and use typeof to determine if o.tagName is a
string and o.nodeType is a number (IE can blow up otherwise.)

As Richard noted, it is likely that you can design this function out
of your application.
Jul 30 '08 #6

P: n/a
"David Mark" <dm***********@gmail.comwrote in message
news:92**********************************@k37g2000 hsf.googlegroups.com...
On Jul 30, 11:52 am, "Aaron Gray" <ang.use...@gmail.comwrote:
"Aaron Gray" <ang.use...@gmail.comwrote in message

news:6f************@mid.individual.net...
"Henry" <rcornf...@raindrop.co.ukwrote in message
news:35**********************************@2g2000hs n.googlegroups.com...
On Jul 30, 2:46 pm, Aaron Gray wrote:
<snip>
function isElement( o)
{
if (!isIE)
return o instanceof Element
else
return o && o.nodeType == 1 && o.tagName != undefined
}
<snip>
Why branch for this? If the second test is ever good enough it is
always good enough.
Because I would like to use "conforming" browser traits, not that this
is
actually one, but it should have been in my view. I take your point. But
the first test is faster and more accurate and runs on more browsers.
Exact equality (===) with 1 would be more precise than type-converting
equality and reduce the possible false positives.
Yes forgot to change that. Thanks,
But overall what it the point? If you inferred from a true result from
a call to your - isElement - method that the object implemented the
whole W3C Core DOM (Level 1 or 2) Element interface you would be wrong
in a number of cases. It would make more sense to decide what features
you wanted from such an element and test for those alone on a basis
driven by need.
Basically my library widget constructors either take a DOM structure,
normally the enclosing DIV (which is what I was wanting to test for) or
a
JSON like object which describes the object, directly (or over AJAX).

So here's a more effiecient version

if (!isIE)
var isElement = function( o)
{
return o instanceof Element
}
else
var isElement = function( o)
{
return o && o.nodeType === 1 && o.tagName !== undefined
}

As per usual any critisms are welcome :)

Thanks,

Aaron
<o.tagName != '!'

<Lose the sniffing branch and use typeof to determine if o.tagName is a
<string and o.nodeType is a number (IE can blow up otherwise.)

Okay so the IE version is not strict enough checking wise not to fall over,
yes, I had half expected that. Okay I will have to look into this better.
Surely the o.nodeType === 1 check is okay. Heres a mod :-

var isElement = function( o)
{
return o && o.nodeType === 1 && typeof o.tagName === string
}

<As Richard noted, it is likely that you can design this function out
<of your application.

My "App" or widget library really wants a good standard function to do th
job that is easy to read, understand and document for other Widget writters.
I get your point though for apps, but then readability and maintainiabily
also apply there as well.

Thanks,

Aaron
Jul 30 '08 #7

P: n/a
"Aaron Gray" <an********@gmail.comwrote in message
news:6f************@mid.individual.net...
"David Mark" <dm***********@gmail.comwrote in message
news:92**********************************@k37g2000 hsf.googlegroups.com...
On Jul 30, 11:52 am, "Aaron Gray" <ang.use...@gmail.comwrote:
>"Aaron Gray" <ang.use...@gmail.comwrote in message

news:6f************@mid.individual.net...
"Henry" <rcornf...@raindrop.co.ukwrote in message
news:35**********************************@2g2000h sn.googlegroups.com...
On Jul 30, 2:46 pm, Aaron Gray wrote:
<snip>
function isElement( o)
{
if (!isIE)
return o instanceof Element
else
return o && o.nodeType == 1 && o.tagName != undefined
}
<snip>
>Why branch for this? If the second test is ever good enough it is
always good enough.
Because I would like to use "conforming" browser traits, not that this
is
actually one, but it should have been in my view. I take your point.
But
the first test is faster and more accurate and runs on more browsers.
>Exact equality (===) with 1 would be more precise than type-converting
equality and reduce the possible false positives.
Yes forgot to change that. Thanks,
>But overall what it the point? If you inferred from a true result from
a call to your - isElement - method that the object implemented the
whole W3C Core DOM (Level 1 or 2) Element interface you would be wrong
in a number of cases. It would make more sense to decide what features
you wanted from such an element and test for those alone on a basis
driven by need.
Basically my library widget constructors either take a DOM structure,
normally the enclosing DIV (which is what I was wanting to test for) or
a
JSON like object which describes the object, directly (or over AJAX).

So here's a more effiecient version

if (!isIE)
var isElement = function( o)
{
return o instanceof Element
}
else
var isElement = function( o)
{
return o && o.nodeType === 1 && o.tagName !== undefined
}

As per usual any critisms are welcome :)

Thanks,

Aaron

<o.tagName != '!'

<Lose the sniffing branch and use typeof to determine if o.tagName is a
<string and o.nodeType is a number (IE can blow up otherwise.)
What do you mean IE can blow up otherwise ? Sule the instanceof should hold
fine.

I am keeping the IE version for speeds sake mainly.
Okay so the IE version is not strict enough checking wise not to fall
over, yes, I had half expected that. Okay I will have to look into this
better. Surely the o.nodeType === 1 check is okay. Heres a mod :-

var isElement = function( o)
{
return o && o.nodeType === 1 && typeof o.tagName === string
}
Whoopse string needs to be in quotes !

Aaron
Jul 30 '08 #8

P: n/a
On Jul 30, 12:45*pm, "Aaron Gray" <ang.use...@gmail.comwrote:
"David Mark" <dmark.cins...@gmail.comwrote in message

news:92**********************************@k37g2000 hsf.googlegroups.com...
On Jul 30, 11:52 am, "Aaron Gray" <ang.use...@gmail.comwrote:
"Aaron Gray" <ang.use...@gmail.comwrote in message
news:6f************@mid.individual.net...
"Henry" <rcornf...@raindrop.co.ukwrote in message
>news:35**********************************@2g2000h sn.googlegroups.com....
>On Jul 30, 2:46 pm, Aaron Gray wrote:
><snip>
>>function isElement( o)
>>{
>>if (!isIE)
>>return o instanceof Element
>>else
>>return o && o.nodeType == 1 && o.tagName != undefined
>>}
><snip>
>Why branch for this? If the second test is ever good enough it is
>always good enough.
Because I would like to use "conforming" browser traits, not that this
is
actually one, but it should have been in my view. I take your point. But
the first test is faster and more accurate and runs on more browsers.
>Exact equality (===) with 1 would be more precise than type-converting
>equality and reduce the possible false positives.
Yes forgot to change that. Thanks,
>But overall what it the point? If you inferred from a true result from
>a call to your - isElement - method that the object implemented the
>whole W3C Core DOM (Level 1 or 2) Element interface you would be wrong
>in a number of cases. It would make more sense to decide what features
>you wanted from such an element and test for those alone on a basis
>driven by need.
Basically my library widget constructors either take a DOM structure,
normally the enclosing DIV (which is what I was wanting to test for) or
a
JSON like object which describes the object, directly (or over AJAX).
So here's a more effiecient version
if (!isIE)
var isElement = function( o)
{
return o instanceof Element
}
else
var isElement = function( o)
{
return o && o.nodeType === 1 && o.tagName !== undefined
}
As per usual any critisms are welcome :)
Thanks,
Aaron

<o.tagName != '!'

<Lose the sniffing branch and use typeof to determine if o.tagName is a
<string and o.nodeType is a number (IE can blow up otherwise.)

Okay so the IE version is not strict enough checking wise not to fall over,
yes, I had half expected that. Okay I will have to look into this better.
Surely the o.nodeType === 1 check is okay. Heres a mod :-
No. Try it with an anchor in IE7 that points to a news resource or an
element in a fragment, etc. Always use typeof to test host object
properties.
>
var isElement = function( o)
{
* * return o && o.nodeType === 1 && typeof o.tagName === string

}

<As Richard noted, it is likely that you can design this function out
<of your application.

My "App" or widget library really wants a good standard function to do th
I'm not sure what a "widget library" is.
job that is easy to read, understand and document for other Widget writters.
You already lost that battle if you must expose such a function in
your API. If you are using it to validate arguments passed to your
methods, document acceptable arguments instead.
Jul 30 '08 #9

P: n/a
On Jul 30, 11:46*pm, "Aaron Gray" <ang.use...@gmail.comwrote:
Due to M$'s stupidity in not making DOMElements first class citizens the
following will not work :-

* * function isElement( o)
* * {
* * * * return o instanceof Element
* * }

It works for FF, Opera and Safari.

What prototype does is this :-

* * * * isElement: function(object) {
* * * * * * return object && object.nodeType == 1
* * * * }

My version used Browser sniffing :-

* * * * function isElement( o)
* * * * {
* * * * * * if (!isIE)
* * * * * * * * return o instanceof Element
* * * * * * else
* * * * * * * * return o && o.nodeType == 1 && o.tagName != undefined
* * * * }
Noting the other advice given here, and that IE 8 will not support
enumeration of nodeType constant values, the following should suit

function isElement(o) {
return o && o.nodeType &&
(o.ELEMENT_NODE === o.nodeType || o.nodeType === 1);
}

Given that you are really trying to distinguish between a DOM node and
a JSON string, why not:

if (typeof o === 'string') {
// assume JSON
} else {
// assume element
}
--
Rob
Jul 30 '08 #10

P: n/a

"RobG" <rg***@iinet.net.auwrote in message
news:57**********************************@r35g2000 prm.googlegroups.com...
On Jul 30, 11:46 pm, "Aaron Gray" <ang.use...@gmail.comwrote:
Due to M$'s stupidity in not making DOMElements first class citizens the
following will not work :-

function isElement( o)
{
return o instanceof Element
}

It works for FF, Opera and Safari.

What prototype does is this :-

isElement: function(object) {
return object && object.nodeType == 1
}

My version used Browser sniffing :-

function isElement( o)
{
if (!isIE)
return o instanceof Element
else
return o && o.nodeType == 1 && o.tagName != undefined
}
<Noting the other advice given here, and that IE 8 will not support
<enumeration of nodeType constant values, the following should suit
<
<function isElement(o) {
< return o && o.nodeType &&
< (o.ELEMENT_NODE === o.nodeType || o.nodeType === 1);
<}

This is messy. My code worked fine on IE8. BTW Just removed IE8 due to other
issues, like behavioual bugs.

<Given that you are really trying to distinguish between a DOM node and
<a JSON string, why not:

Its not a JSON string but an diseminated object at this stage that comes
from a JSON object.

Thanks,

Aaron

Jul 31 '08 #11

P: n/a
"David Mark" <dm***********@gmail.comwrote in message
news:49**********************************@z66g2000 hsc.googlegroups.com...
On Jul 30, 12:45 pm, "Aaron Gray" <ang.use...@gmail.comwrote:
"David Mark" <dmark.cins...@gmail.comwrote in message

news:92**********************************@k37g2000 hsf.googlegroups.com...
On Jul 30, 11:52 am, "Aaron Gray" <ang.use...@gmail.comwrote:
"Aaron Gray" <ang.use...@gmail.comwrote in message
news:6f************@mid.individual.net...
"Henry" <rcornf...@raindrop.co.ukwrote in message
>news:35**********************************@2g2000h sn.googlegroups.com...
>On Jul 30, 2:46 pm, Aaron Gray wrote:
><snip>
>>function isElement( o)
>>{
>>if (!isIE)
>>return o instanceof Element
>>else
>>return o && o.nodeType == 1 && o.tagName != undefined
>>}
><snip>
>Why branch for this? If the second test is ever good enough it is
>always good enough.
Because I would like to use "conforming" browser traits, not that this
is
actually one, but it should have been in my view. I take your point.
But
the first test is faster and more accurate and runs on more browsers.
>Exact equality (===) with 1 would be more precise than
>type-converting
>equality and reduce the possible false positives.
Yes forgot to change that. Thanks,
>But overall what it the point? If you inferred from a true result
>from
>a call to your - isElement - method that the object implemented the
>whole W3C Core DOM (Level 1 or 2) Element interface you would be
>wrong
>in a number of cases. It would make more sense to decide what
>features
>you wanted from such an element and test for those alone on a basis
>driven by need.
Basically my library widget constructors either take a DOM structure,
normally the enclosing DIV (which is what I was wanting to test for)
or
a
JSON like object which describes the object, directly (or over AJAX).
So here's a more effiecient version
if (!isIE)
var isElement = function( o)
{
return o instanceof Element
}
else
var isElement = function( o)
{
return o && o.nodeType === 1 && o.tagName !== undefined
}
As per usual any critisms are welcome :)
Thanks,
Aaron

<o.tagName != '!'

<Lose the sniffing branch and use typeof to determine if o.tagName is a
<string and o.nodeType is a number (IE can blow up otherwise.)

Okay so the IE version is not strict enough checking wise not to fall
over,
yes, I had half expected that. Okay I will have to look into this better.
Surely the o.nodeType === 1 check is okay. Heres a mod :-
<No. Try it with an anchor in IE7 that points to a news resource or an
<element in a fragment, etc. Always use typeof to test host object
<properties.

donot follow could you give me a more explict example or two ?
>
var isElement = function( o)
{
return o && o.nodeType === 1 && typeof o.tagName === string

}

<As Richard noted, it is likely that you can design this function out
<of your application.

My "App" or widget library really wants a good standard function to do th
<I'm not sure what a "widget library" is.

Comes fro Window Gadget, being a tree or a table. See ExtJS 2.0 for a Widget
based library :-

http://extjs.com/
job that is easy to read, understand and document for other Widget
writters.
<You already lost that battle if you must expose such a function in
<your API. If you are using it to validate arguments passed to your
<methods, document acceptable arguments instead.

Its for validation (and the equalient of overloaded function behaviour) and
for core support library functionality. ie other wishing to extend the
library or create new widgets.

Aaron

Jul 31 '08 #12

P: n/a
On Jul 30, 11:52*am, "Aaron Gray" <ang.use...@gmail.comwrote:
[snip]
So here's a more effiecient version

* * *if (!isIE)
* * * * var isElement = function( o)
* * * * {
* * * * * * *return o instanceof Element
* * * * }
* * else
* * * * var isElement = function( o)
* * * * {
* * * * * * *return o && o.nodeType === 1 && o.tagName !== undefined
* * * * }

As per usual any critisms are welcome :)
The double function expression is unnecessary.

It could be rewritten like so:

var isElement = (function(){
var el = document.createElement('div'), fn;
if (el instanceof Element) {
fn = function(o) {
return o instanceof Element;
}
}
else {
fn = function(o) {
return o && typeof 'nodeType' in o && o.nodeType === 1;
}
}
el = null;
return fn;
})();

We don't perform such branching in prototype.js to avoid
inconsistencies across browsers.

isElement(document.createElement('div')); // true in IE and FF
isElement({ nodeType: 1 }); // true in IE, but false in FF

--
kangax
Jul 31 '08 #13

P: n/a
On Jul 31, 12:33*am, kangax <kan...@gmail.comwrote:
[snip]
* else {
* * fn = function(o) {
* * * return o && typeof 'nodeType' in o && o.nodeType === 1;
* * }
* }
That should have been:

...
fn = function(o) {
return o && 'nodeType' in o && o.nodeType === 1;
}
...

--
kangax
Jul 31 '08 #14

P: n/a
On Jul 31, 10:40*am, "Aaron Gray" <ang.use...@gmail.comwrote:
"RobG" <rg...@iinet.net.auwrote in message

news:57**********************************@r35g2000 prm.googlegroups.com...
On Jul 30, 11:46 pm, "Aaron Gray" <ang.use...@gmail.comwrote:
Due to M$'s stupidity in not making DOMElements first class citizens the
following will not work :-
function isElement( o)
{
return o instanceof Element
}
It works for FF, Opera and Safari.
What prototype does is this :-
isElement: function(object) {
return object && object.nodeType == 1
}

That should be sufficient everywhere, there is no need for browser
sniffing. However, the function is pretty useless for the reasons
expressed in other posts.

My version used Browser sniffing :-
function isElement( o)
{
if (!isIE)
return o instanceof Element
else
return o && o.nodeType == 1 && o.tagName != undefined
}
What is the point of the tagName test? Do you know of a case where
the nodeType test returns true but the tagName test returns false
(even if changed to a typeof comparison)?

>
<Noting the other advice given here, and that IE 8 will not support
<enumeration of nodeType constant values, the following should suit
That turned out to be incorrect advice: I downloaded and installed IE8
Beta 1, element.nodeType property returns appropriate values,
element.ELEMENT_NODE returns undefined.

<
<function isElement(o) {
< *return o && o.nodeType &&
< * * * *(o.ELEMENT_NODE === o.nodeType || o.nodeType === 1);
<}

This is messy.
Messy? In hind sight, unnecessarily long.

My code worked fine on IE8.
"Worked" is only sufficient where there is no other criterion that can
be used.

BTW Just removed IE8 due to other
issues, like behavioual bugs.
Thanks for the warning... :-(

<Given that you are really trying to distinguish between a DOM node and
<a JSON string, why not:

Its not a JSON string but an diseminated object at this stage that comes
from a JSON object.
The strategy of feature detection is to determine if objects have the
properties you need them to have, rather than whether they have a
particular feature and inferring that they have other features as a
result.

For example, the fact that an object has a nodeType property with a
value of 1 should not infer support for all relevant DOM 2 interface
features (Node, HTMLElement, etc.) which is what might be inferred
from an isElement function.

Therefore, within your code, you might consider a simple test to
distinguish between an element or "diseminated object" such as
(presuming the other object doesn't have a nodeType property):

if (o.nodeType) {
// o is an element
} else {
// o is something else
}

which does not seem to be any more code than an equivalent isElement()
test (and removes all the code for isElement also).
--
Rob
Jul 31 '08 #15

P: n/a
On Jul 31, 2:33*pm, kangax <kan...@gmail.comwrote:
[...]
>
It could be rewritten like so:

var isElement = (function(){
* var el = document.createElement('div'), fn;
* if (el instanceof Element) {
That causes IE8 Beta 1 to barf with "Element is not defined".
Modifying it to:

if (Element && (el instanceof Element))

or

if (Element) {
if (...) {
gets the same result, it wants a more explicit test:

if (typeof Element != 'undefined' && (...))
Perhaps that's documented on one of the IE8 blogs somewhere...

* * fn = function(o) {
* * * return o instanceof Element;
* * }
* }
* else {
* * fn = function(o) {
* * * return o && typeof 'nodeType' in o && o.nodeType === 1;
After applying your fix to the above to remove typeof, what is the
point of the test? Its use as a guard here seems unnecessary: if o
doesn't have a nodeType property, o.nodeType will return undefined and
the test fails (even in IE8b).
* * }
* }
* el = null;
* return fn;

})();

We don't perform such branching in prototype.js to avoid
inconsistencies across browsers.

isElement(document.createElement('div')); // true in IE and FF
isElement({ nodeType: 1 }); // true in IE, but false in FF
But there you have an inconsitency, lending support to the argument
that feature detection is much better than inference (i.e. if you
expect an object to have a particular property, test for that
property, don't test it for some other property to infer that is has
the one you really want).

The instanceof test is open to the same criticism.
--
Rob
Jul 31 '08 #16

P: n/a
kangax meinte:
return o && typeof 'nodeType' in o && o.nodeType === 1;
Wouldn't

return typeof o.nodeType !== "undefined" && o.nodeType === 1;

be sufficient?

Gregor
--
http://photo.gregorkofler.at ::: Landschafts- und Reisefotografie
http://web.gregorkofler.com ::: meine JS-Spielwiese
http://www.image2d.com ::: Bildagentur für den alpinen Raum
Jul 31 '08 #17

P: n/a
Gregor Kofler meinte:
kangax meinte:
> return o && typeof 'nodeType' in o && o.nodeType === 1;

Wouldn't

return typeof o.nodeType !== "undefined" && o.nodeType === 1;
Ooops:

return o && o.nodeType === 1;

Gregor
--
http://photo.gregorkofler.at ::: Landschafts- und Reisefotografie
http://web.gregorkofler.com ::: meine JS-Spielwiese
http://www.image2d.com ::: Bildagentur für den alpinen Raum
Jul 31 '08 #18

P: n/a
RobG <rg***@iinet.net.auwrites:
That causes IE8 Beta 1 to barf with "Element is not defined".
Modifying it to:

if (Element && (el instanceof Element))

or

if (Element) {
if (...) {
gets the same result, it wants a more explicit test:

if (typeof Element != 'undefined' && (...))
Perhaps that's documented on one of the IE8 blogs somewhere...
That's the expected behavior if there is no "Element" variable
defined.
if (Element) { // ...
only works if there *is* an Element variable, and it has a non-falsey
value.

/L
--
Lasse Reichstein Nielsen
DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
'Faith without judgement merely degrades the spirit divine.'
Jul 31 '08 #19

P: n/a
On Jul 30, 3:33 pm, Aaron Gray wrote:
Henry wrote:
>On Jul 30, 2:46 pm, Aaron Gray wrote:
<snip>
>>function isElement( o)
{
if (!isIE)
return o instanceof Element
else
return o && o.nodeType == 1 && o.tagName != undefined
}
<snip>
>Why branch for this? If the second test is ever good enough
it is always good enough.

Because I would like to use "conforming" browser traits, not
that this is actually one, but it should have been in my view.
Whatever you may think, or may prefer, the second branch is the one
based upon documented (W3C) standard behaviour.
I take your point. But the first test is faster and more
accurate and runs on more browsers.
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.
>Exact equality (===) with 1 would be more precise than
type-converting equality and reduce the possible false
positives.

Yes forgot to change that. Thanks,
>But overall what it the point? If you inferred from a true
result from a call to your - isElement - method that the
object implemented the whole W3C Core DOM (Level 1 or 2)
Element interface you would be wrong in a number of cases.
It would make more sense to decide what features you wanted
from such an element and test for those alone on a basis
driven by need.

Basically my library widget constructors either take a DOM
structure, normally the enclosing DIV (which is what I was
wanting to test for) or a JSON like object which describes
the object, directly (or over AJAX).
<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?

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.

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.

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

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.
Jul 31 '08 #20

P: n/a
On Jul 31, 7:28*pm, Lasse Reichstein Nielsen <l...@hotpop.comwrote:
RobG <rg...@iinet.net.auwrites:
That causes IE8 Beta 1 to barf with "Element is not defined".
Modifying it to:
* if (Element && (el instanceof Element))
or
* if (Element) {
* * if (...) {
gets the same result, it wants a more explicit test:
* if (typeof Element != 'undefined' && (...))
Perhaps that's documented on one of the IE8 blogs somewhere...

That's the expected behavior if there is no "Element" variable
defined.
*if (Element) { // ...
only works if there *is* an Element variable, and it has a non-falsey
value.
Ah yes, of course - it fails with a reference error. A falsey test
would be:

if (window.Element && ... ) { ... }

or perhaps:

var global = (function(){return this})();
if (global.Element && ... ){ ... }
--
Rob
Jul 31 '08 #21

P: n/a
On Jul 31, 5:46 am, RobG wrote:
<snip>
That turned out to be incorrect advice: I downloaded and
installed IE8 Beta 1, element.nodeType property returns
appropriate values, element.ELEMENT_NODE returns undefined.
<snip>

Which is correct W3C Core DOM conforming behaviour. The ECMAScript
biddings define the ELEMENT_NODE, ATTRIBUTE_NODE, etc properties as
properties of "The Node class" and list them as "Node. ELEMENT_NODE"
etc. suggesting that if there were a Node constructor it would be the
object that had the properties.

In any event, the dynamic looking up of the values at runtime seems a
bit pointless as changes to this aspect of the DOM are most likely to
represent additions to the list of constants not changes in the value
for any existing type, and changes to the DOM sufficiently far
reaching as to suggest that the value of, for example, -
Node.ELEMENT_NODE - be changed would suggest a radical re-design of
the DOM and little chance of back-compatibility in that redesign.
Jul 31 '08 #22

P: n/a
"kangax" <ka****@gmail.comwrote in message
news:43**********************************@k30g2000 hse.googlegroups.com...
On Jul 30, 11:52 am, "Aaron Gray" <ang.use...@gmail.comwrote:
>[snip]
The double function expression is unnecessary.

It could be rewritten like so:

var isElement = (function(){
var el = document.createElement('div'), fn;
if (Element && el instanceof Element) { // Thanks RobG
fn = function(o) {
return o instanceof Element;
}
}
else {
fn = function(o) {
return o && 'nodeType' in o && o.nodeType === 1;
}
}
el = null;
return fn;
})();

We don't perform such branching in prototype.js to avoid
inconsistencies across browsers.
Right. Is the inconsistancy really that bad as to cause problems with an
example like this ?
>isElement(document.createElement('div')); // true in IE and FF
isElement({ nodeType: 1 }); // true in IE, but false in FF
Yes this is the sort of behaviour that I was trying to avoid, hence adding
in the 'typeof o.tagName === string' to make the test stricter.

If IE had followed the other browsers and made browser types first class we
would not have these problems.

Thanks kangax.

Aaron
Jul 31 '08 #23

P: n/a
On Jul 31, 1:28*am, RobG <rg...@iinet.net.auwrote:
On Jul 31, 2:33*pm, kangax <kan...@gmail.comwrote:
[...]
It could be rewritten like so:
var isElement = (function(){
* var el = document.createElement('div'), fn;
* if (el instanceof Element) {

That causes IE8 Beta 1 to barf with "Element is not defined".
Modifying it to:

* if (Element && (el instanceof Element))

or

* if (Element) {
* * if (...) {

gets the same result, it wants a more explicit test:

* if (typeof Element != 'undefined' && (...))

Perhaps that's documented on one of the IE8 blogs somewhere...
Interesting. Should one really care about such quirks while a browser
is in its early development state?
>
* * fn = function(o) {
* * * return o instanceof Element;
* * }
* }
* else {
* * fn = function(o) {
* * * return o && typeof 'nodeType' in o && o.nodeType === 1;

After applying your fix to the above to remove typeof, what is the
point of the test? *Its use as a guard here seems unnecessary: if o
doesn't have a nodeType property, o.nodeType will return undefined and
I wrongly assumed that `in` doesn't call `GetValue` and so is safer to
use with host objects.
the test fails (even in IE8b).
* * }
* }
* el = null;
* return fn;
})();
We don't perform such branching in prototype.js to avoid
inconsistencies across browsers.
isElement(document.createElement('div')); // true in IE and FF
isElement({ nodeType: 1 }); // true in IE, but false in FF

But there you have an inconsitency, lending support to the argument
that feature detection is much better than inference (i.e. if you
expect an object to have a particular property, test for that
property, don't test it for some other property to infer that is has
the one you really want).
It certainly makes sense to test for a particular property rather than
relying on some generalized helper. It appears, though, that the need
for "isElement" exists. The goal is to implement its behavior in a
most intuitive and generalized way.

--
kangax
Jul 31 '08 #24

P: n/a
On Jul 31, 4:19 pm, kangax wrote:
<snip>
... . It appears, though, that the need
for "isElement" exists.
How does that appear? It appears that there is a desire and that the
desire is being serviced but nothing has yet suggested a need.
The goal is to implement its behavior in a
most intuitive and generalized way.
Pre-supposing the existence of a need might suggest a goal along those
lines, but without first establishing a need pursuing that goal might
be effort wasted.

And why 'most intuitive' or 'most generalised'? If a function/method
is just going to return true or false and third parties, are going to
trust that it does that in the way that its documentation says it
will, then it really doesn't matter that much how unintuitive the code
it contains may be.

While no real situations are truly general so striving to create the
'most general' anything probably is not that good an idea when
'sufficiently general' could be a knowable state and 'most general' an
unachievable (and possibly undesirable) ideal.

Consider the Core DOM's namespace qualified methods. Even in something
as theoretically general as a general-purpose HTML DOM library it will
not be necessary to use namespace qualified Node/Element methods. And
the - isElement - code shown here is certainly no grantee that the
object for which a - true - result is achieved has those methods (as
IE will give true results for objects implementing the Element
interface but does not provide the namespace qualified methods in its
HTML DOM). That is fine because nobody is gong to need to use
namespace qualified methods in an HTML DOM.

However, the more general situation of trying to write a general-
purpose library for both HTML and XHTML DOMs necessitates the use of
the namespace qualified methods in the XHTML DOM, but the - isElement
- code here does not give any relationship between its true results
and the objects having the necessary methods. More general code might
be indicated for that more general situation, but as that situation is
extremely uncommon it probably does not matter if any - isElement -
code is less than the 'most general'.
Jul 31 '08 #25

P: n/a
"Henry" <rc*******@raindrop.co.ukwrote in message
news:bb**********************************@d77g2000 hsb.googlegroups.com...
On Jul 31, 4:19 pm, kangax wrote:
<snip>
>... . It appears, though, that the need
for "isElement" exists.

How does that appear? It appears that there is a desire and that the
desire is being serviced but nothing has yet suggested a need.
You have to double or tripple up on constructors to do the same trick. Its
neater with one constructor and using what in static class languages is
called overoading.

Aaron
Jul 31 '08 #26

P: n/a
On Jul 31, 4:07 pm, Aaron Gray wrote:
<snip>
return o && 'nodeType' in o && o.nodeType === 1;
Don't do this in preference to your previous version. The type-
converting to boolean test on - o - only guarantees it has trueness,
not that it is an object. If the right hand side of an - in -
operation is not an object an exception is thrown. Thus if - o - is a
primitive value that has truness avoidable exceptions will be thrown
in this code rather than false values returned (note that - instanceof
- can handle a primitive type left hand side operand). But once - o -
has been established as having tureness the expression - o.nodeType -
will not fail due to - o - being a primitive value, as it implies
internal type-conversation of the primitive into the corresponding
object (none of which will have - nodeType - properties).

<snip>
isElement(document.createElement('div')); // true in IE and FF
isElement({ nodeType: 1 }); // true in IE, but false in FF

Yes this is the sort of behaviour that I was trying to avoid,
hence adding in the 'typeof o.tagName === string' to make
the test stricter.

If IE had followed the other browsers and made browser types
first class we would not have these problems.
No, you would still have precisely this problem because javascript
objects can still be created to fool - o instanceof Element - into
returning a true result for an object that is not a DOM Element.
Jul 31 '08 #27

P: n/a

"Henry" <rc*******@raindrop.co.ukwrote in message
news:9f**********************************@d45g2000 hsc.googlegroups.com...
On Jul 31, 4:07 pm, Aaron Gray wrote:
<snip>
> return o && 'nodeType' in o && o.nodeType === 1;

Don't do this in preference to your previous version. The type-
converting to boolean test on - o - only guarantees it has trueness,
not that it is an object. If the right hand side of an - in -
operation is not an object an exception is thrown. Thus if - o - is a
primitive value that has truness avoidable exceptions will be thrown
in this code rather than false values returned (note that - instanceof
- can handle a primitive type left hand side operand). But once - o -
has been established as having tureness the expression - o.nodeType -
will not fail due to - o - being a primitive value, as it implies
internal type-conversation of the primitive into the corresponding
object (none of which will have - nodeType - properties).
Opps, not looking what I am doing there, yes I need to sit back and review
this whole thing properly rathr than just responding to the small peices,
badly.
<snip>
>isElement(document.createElement('div')); // true in IE and FF
isElement({ nodeType: 1 }); // true in IE, but false in FF

Yes this is the sort of behaviour that I was trying to avoid,
hence adding in the 'typeof o.tagName === string' to make
the test stricter.

If IE had followed the other browsers and made browser types
first class we would not have these problems.

No, you would still have precisely this problem because javascript
objects can still be created to fool - o instanceof Element - into
returning a true result for an object that is not a DOM Element.
Yes I would not be too bothered about that, its a real side case if it
exists.

How do you do that anyway ?

Thanks Henry,

Aaron
Jul 31 '08 #28

P: n/a
On Jul 31, 5:15 pm, Aaron Gray wrote:
Henry wrote in message
>On Jul 31, 4:19 pm, kangax wrote:
<snip>
>>... . It appears, though, that the need
for "isElement" exists.
>How does that appear? It appears that there is a desire and that
the desire is being serviced but nothing has yet suggested a need.

You have to double or tripple up on constructors to do the same
trick. Its neater with one constructor and using what in static
class languages is called overoading.
That does not follow, and still no need then.
Jul 31 '08 #29

P: n/a
On Jul 31, 11:07*am, "Aaron Gray" <ang.use...@gmail.comwrote:
"kangax" <kan...@gmail.comwrote in message

news:43**********************************@k30g2000 hse.googlegroups.com...
On Jul 30, 11:52 am, "Aaron Gray" <ang.use...@gmail.comwrote:
[snip]
The double function expression is unnecessary.
It could be rewritten like so:
var isElement = (function(){
*var el = document.createElement('div'), fn;

* *if (Element && el instanceof Element) { *// Thanks RobG* *fn = function(o) {
* * *return o instanceof Element;
* *}
*}
*else {
* *fn = function(o) {

* * * return o && 'nodeType' in o && o.nodeType === 1;
* *}
*}
*el = null;
*return fn;
})();
We don't perform such branching in prototype.js to avoid
inconsistencies across browsers.
LOL.
>
Right. Is the inconsistancy really that bad as to cause problems with an
example like this ?
You and the Prototype guy are both trying to solve the same problem
that does not need to be solved. Nobody need a GP function to
discriminate between an Object object and an element.
>
isElement(document.createElement('div')); // true in IE and FF
isElement({ nodeType: 1 }); // true in IE, but false in FF

Yes this is the sort of behaviour that I was trying to avoid, hence adding
in the 'typeof o.tagName === string' to make the test stricter.

If IE had followed the other browsers and made browser types first class we
would not have these problems.
We don't have a problem. It is people who wish to make the language
work more like Java who have a problem. The problem is easily
diagnosed: they do not understand the language they are using or
browser scripting in general.
Jul 31 '08 #30

P: n/a
On Jul 31, 5:33 pm, Aaron Gray wrote:
Henry wrote:
>On Jul 31, 4:07 pm, Aaron Gray wrote:
<snip>
>>>>isElement(document.createElement('div')); // true in IE and FF
isElement({ nodeType: 1 }); // true in IE, but false in FF
>>Yes this is the sort of behaviour that I was trying to avoid,
hence adding in the 'typeof o.tagName === string' to make
the test stricter.
>>If IE had followed the other browsers and made browser
types first class we would not have these problems.
>No, you would still have precisely this problem because
javascript objects can still be created to fool -
o instanceof Element - into returning a true result for
an object that is not a DOM Element.

Yes I would not be too bothered about that, its a real
side case if it exists.
It is hardly going to be a common case to create a javascript object
with a - nodeType - property with the value 1 and a string type -
tagName - property, unless you are creating something that you want to
be treated like an Element in which case the making the discrimination
is pointless.
How do you do that anyway ?
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<head>
<title></title>
</head><body>
<div>
<script type="text/javascript">

function testObj1(){
}
testObj1.prototype = document.createElement('DIV');

var o = new testObj1();

alert((o instanceof Element));

</script>
</body>

Javascript's - instanceof - is not about object types, but rather
about runtime relationships between object on a prototype chain and
the objects referred to by the - prototype - properties of
constructors.
Jul 31 '08 #31

P: n/a
"Henry" <rc*******@raindrop.co.ukwrote in message
news:5e**********************************@d1g2000h sg.googlegroups.com...
On Jul 31, 5:15 pm, Aaron Gray wrote:
>Henry wrote in message
>>On Jul 31, 4:19 pm, kangax wrote:
<snip>
... . It appears, though, that the need
for "isElement" exists.
>>How does that appear? It appears that there is a desire and that
the desire is being serviced but nothing has yet suggested a need.

You have to double or tripple up on constructors to do the same
trick. Its neater with one constructor and using what in static
class languages is called overoading.
That should be 'overloading'.
That does not follow, and still no need then.
Basically take an accordian widget, that either gets initialized from a DIV
or UL,LI structure, hence needing to know its element based, or via a JSON
based approach. Now either you have two constructors one for each casew or
you have one overrided constructor that detects the parameter type. Which is
what I prefer to do until I see any reason not to and to use two
constructors.

Aaron
Jul 31 '08 #32

P: n/a
On Jul 31, 1:42*pm, "Aaron Gray" <ang.use...@gmail.comwrote:
"Henry" <rcornf...@raindrop.co.ukwrote in message

news:5e**********************************@d1g2000h sg.googlegroups.com...
On Jul 31, 5:15 pm, Aaron Gray wrote:
Henry wrote in message
On Jul 31, 4:19 pm, kangax wrote:
<snip>
... . It appears, though, that the need
for "isElement" exists.
>How does that appear? It appears that there is a desire and that
the desire is being serviced but nothing has yet suggested a need.
You have to double or tripple up on constructors to do the same
trick. Its neater with one constructor and using what in static
class languages is called overoading.

That should be 'overloading'.
That does not follow, and still no need then.

Basically take an accordian widget, that either gets initialized from a DIV
or UL,LI structure, hence needing to know its element based, or via a JSON
I don't follow. DIV or UL, LI is a common discrimination for such
widgets and is easily accomplished by checking the tagName (or
nodeName) property of the indicated element.
based approach. Now either you have two constructors one for each casew or
Why would you need two constructors? You could certainly create
options for this, but it seems like an object that creates one of
these widgets from whole cloth should inherit from one that adds
behavior to an existing DOM structure.
you have one overrided constructor that detects the parameter type. Whichis
Overloaded?

A design that forces you to write code to discriminate between Object
objects and random host objects? Not an appropriate strategy for this
(or virtually anything in JavaScript--see jQuery.)
what I prefer to do until I see any reason not to and to use two
constructors.
Those aren't your only two choices.

HTH
Jul 31 '08 #33

P: n/a
Lasse Reichstein Nielsen wrote:
RobG <rg***@iinet.net.auwrites:
>That causes IE8 Beta 1 to barf with "Element is not defined".
Modifying it to:

if (Element && (el instanceof Element))

or

if (Element) {
if (...) {
gets the same result, it wants a more explicit test:

if (typeof Element != 'undefined' && (...))

Perhaps that's documented on one of the IE8 blogs somewhere...

That's the expected behavior if there is no "Element" variable
defined.
if (Element) { // ...
only works if there *is* an Element variable, and it has a non-falsey
value.
Property, not variable. Of an object in the scope chain.
PointedEars
--
Anyone who slaps a 'this page is best viewed with Browser X' label on
a Web page appears to be yearning for the bad old days, before the Web,
when you had very little chance of reading a document written on another
computer, another word processor, or another network. -- Tim Berners-Lee
Jul 31 '08 #34

P: n/a
RobG wrote:
Ah yes, of course - it fails with a reference error. A falsey test
would be:

if (window.Element && ... ) { ... }
This would be based on a false assumption.
or perhaps:

var global = (function(){return this})();
if (global.Element && ... ){ ... }
That would still cause warnings.

Your signature delimiter was borken by Google Groups.
PointedEars
--
Prototype.js was written by people who don't know javascript for people
who don't know javascript. People who don't know javascript are not
the best source of advice on designing systems that use javascript.
-- Richard Cornford, cljs, <f8*******************@news.demon.co.uk>
Jul 31 '08 #35

P: n/a
Henry wrote:
On Jul 31, 5:46 am, RobG wrote:
<snip>
>That turned out to be incorrect advice: I downloaded and
installed IE8 Beta 1, element.nodeType property returns
appropriate values, element.ELEMENT_NODE returns undefined.
<snip>

Which is correct W3C Core DOM conforming behaviour. The ECMAScript
biddings define the ELEMENT_NODE, ATTRIBUTE_NODE, etc properties as
properties of "The Node class" and list them as "Node. ELEMENT_NODE"
etc. suggesting that if there were a Node constructor it would be the
object that had the properties.
Further research shows that
<http://www.w3.org/TR/DOM-Level-3-Core/ecma-script-binding.htmleventually
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.
PointedEars
--
Anyone who slaps a 'this page is best viewed with Browser X' label on
a Web page appears to be yearning for the bad old days, before the Web,
when you had very little chance of reading a document written on another
computer, another word processor, or another network. -- Tim Berners-Lee
Jul 31 '08 #36

P: n/a
On Jul 31, 8:07*am, "Aaron Gray" <ang.use...@gmail.comwrote:
Right. Is the inconsistancy really that bad as to cause problems with an
example like this ?
isElement(document.createElement('div')); // true in IE and FF
isElement({ nodeType: 1 }); // true in IE, but false in FF

Yes this is the sort of behaviour that I was trying to avoid, hence adding
in the 'typeof o.tagName === string' to make the test stricter.
I think this could then be fooled by:

isElement({ nodeType: 1, tagName: 'div' })

It seems to me the that a major point here is that any test you do
like this will be trivial to fool because you're looking for
properties of this object which are not directly related to what you
want to do with the object. As you can see if you keep testing the
same way, it is trivial to construct a new property on the object
which passes the test. So the test will only become "stricter" in the
same sense that adding 1 to an integer makes it closer to infinity.

I think the suggestion is that you either use "duck typing" to find
out if whatever you're working with is capable of doing what you want
to do with it, or that you track the object itself (if it's JSON then
you either created it or used AJAX to pull it in, if it's a DOM
element then you either queried the DOM or used a DOM method to create
it). In either case you knew what the JSON/DOM object was when it was
created, so as Henry said, you already had that information and threw
it away/lost it. If you can just retain that information you won't
need to do this imprecise test.

I'm aware that I'm echoing what others have said, but I hope that I've
said it in a way that helps foster understanding.

--
Dan Evans
Jul 31 '08 #37

P: n/a
"Henry" <rc*******@raindrop.co.ukwrote in message
news:65**********************************@y21g2000 hsf.googlegroups.com...
On Jul 31, 5:33 pm, Aaron Gray wrote:
>Henry wrote:
>>On Jul 31, 4:07 pm, Aaron Gray wrote:
<snip>
>>>>>isElement(document.createElement('div')); // true in IE and FF
>isElement({ nodeType: 1 }); // true in IE, but false in FF
>>>Yes this is the sort of behaviour that I was trying to avoid,
hence adding in the 'typeof o.tagName === string' to make
the test stricter.
>>>If IE had followed the other browsers and made browser
types first class we would not have these problems.
>>No, you would still have precisely this problem because
javascript objects can still be created to fool -
o instanceof Element - into returning a true result for
an object that is not a DOM Element.

Yes I would not be too bothered about that, its a real
side case if it exists.

It is hardly going to be a common case to create a javascript object
with a - nodeType - property with the value 1 and a string type -
tagName - property, unless you are creating something that you want to
be treated like an Element in which case the making the discrimination
is pointless.
Yes, I am inclined to agree with you.
>How do you do that anyway ?

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<head>
<title></title>
</head><body>
<div>
<script type="text/javascript">

function testObj1(){
}
testObj1.prototype = document.createElement('DIV');

var o = new testObj1();

alert((o instanceof Element));

</script>
</body>
Okay that looks a good method. They have to make that much effort, and does
not allow Object Notation to fake it; which I did not want. But it can be
faked on IE leading to difference in behaviour. Horrrible :(
Javascript's - instanceof - is not about object types, but rather
about runtime relationships between object on a prototype chain and
the objects referred to by the - prototype - properties of
constructors.
Yes.

May have to agree with you on this one and go for a member and value based
test then :(

Thanks Henry, you have convinced me, shame, but there you go, I'll post a
new single pronged attempt tommorow.

Aaron

Jul 31 '08 #38

P: n/a

"Dan Evans" <Th*********@gmail.comwrote in message
news:63**********************************@i24g2000 prf.googlegroups.com...
On Jul 31, 8:07 am, "Aaron Gray" <ang.use...@gmail.comwrote:
Right. Is the inconsistancy really that bad as to cause problems with an
example like this ?
isElement(document.createElement('div')); // true in IE and FF
isElement({ nodeType: 1 }); // true in IE, but false in FF

Yes this is the sort of behaviour that I was trying to avoid, hence adding
in the 'typeof o.tagName === string' to make the test stricter.
>I think this could then be fooled by:

isElement({ nodeType: 1, tagName: 'div' })
Only on IE which shows IE is BAD !!!
>created, so as Henry said, you already had that information and threw
it away/lost it. If you can just retain that information you won't
need to do this imprecise test.
Yes this is the case but it does not go for really nice libraries and kind
of transparent sparation you can get with static typing and overloading.
>I'm aware that I'm echoing what others have said, but I hope that I've
said it in a way that helps foster understanding.
Yes, I have came round to this argument only because IE is BAD and did not
follow the other browsers behaviour.

Aaron

Aug 1 '08 #39

P: n/a
"Aaron Gray" <an********@gmail.comwrote in message
news:6f************@mid.individual.net...
Due to M$'s stupidity in not making DOMElements first class citizens the
following will not work :-

function isElement( o)
{
return o instanceof Element
}
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.
It works for FF, Opera and Safari.

What prototype does is this :-

isElement: function(object) {
return object && object.nodeType == 1
}
As Henry says this will fail with a typing error if object is not an object.
My version used Browser sniffing :-

function isElement( o)
{
if (!isIE)
return o instanceof Element
else
return o && o.nodeType == 1 && o.tagName != undefined
}
This fails too for the above reasons.

Duck Typing wins out :-

function isElement( o)
{
return o && typeof o === "object" && o.nodeType == 1 && typeof o.tagName
=== "string"
}
Test case :-

http://www.aarongray.org/Test/JavaSc...ent-test3.html

A bit of a verbose and stringent test but I think it is for the best. It
allow overriding behaviour to be done realatively safely.

Any comments, cristisms, or general flac welcome :)

Aaron

Aug 1 '08 #40

P: n/a
"Aaron Gray" <an********@gmail.comwrites:
"Aaron Gray" <an********@gmail.comwrote in message
news:6f************@mid.individual.net...
[ someone deleted the name of whoever said this ]
>It works for FF, Opera and Safari.

What prototype does is this :-

isElement: function(object) {
return object && object.nodeType == 1
}

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.

--
Joost Diepenmaat | blog: http://joost.zeekat.nl/ | work: http://zeekat.nl/
Aug 1 '08 #41

P: n/a
On Aug 1, 5:17*am, Thomas 'PointedEars' Lahn <PointedE...@web.de>
wrote:
Henry wrote:
On Jul 31, 5:46 am, RobG wrote:
<snip>
That turned out to be incorrect advice: I downloaded and
installed IE8 Beta 1, element.nodeType property returns
appropriate values, element.ELEMENT_NODE returns undefined.
<snip>
Which is correct W3C Core DOM conforming behaviour. The ECMAScript
biddings define the ELEMENT_NODE, ATTRIBUTE_NODE, etc properties as
properties of "The Node class" and list them as "Node. ELEMENT_NODE"
etc. suggesting that if there were a Node constructor it would be the
object that had the properties.

Further research shows that
<http://www.w3.org/TR/DOM-Level-3-Core/ecma-script-binding.htmleventually
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.
--
Rob
Aug 1 '08 #42

P: n/a

"Joost Diepenmaat" <jo***@zeekat.nlwrote in message
news:87************@zeekat.nl...
"Aaron Gray" <an********@gmail.comwrites:
>"Aaron Gray" <an********@gmail.comwrote in message
news:6f************@mid.individual.net...

[ someone deleted the name of whoever said this ]
>>It works for FF, Opera and Safari.

What prototype does is this :-

isElement: function(object) {
return object && object.nodeType == 1
}

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/JavaSc...nt-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

Aug 1 '08 #43

P: n/a
On Jul 31, 8:35*pm, Joost Diepenmaat <jo...@zeekat.nlwrote:
"Aaron Gray" <ang.use...@gmail.comwrites:
"Aaron Gray" <ang.use...@gmail.comwrote in message
news:6f************@mid.individual.net...

*[ someone deleted the name of whoever said this ]
It works for FF, Opera and Safari.
What prototype does is this :-
* * * *isElement: function(object) {
* * * * * *return object && object.nodeType == 1
* * * *}
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.
Aug 1 '08 #44

P: n/a
"David Mark" <dm***********@gmail.comwrote in message
news:c77d746c-1d94-4e4d-8443->1e**********@y21g2000hsf.googlegroups.com...
>On Jul 31, 8:35 pm, Joost Diepenmaat <jo...@zeekat.nlwrote:
>"Aaron Gray" <ang.use...@gmail.comwrites:
"Aaron Gray" <ang.use...@gmail.comwrote in message
news:6f************@mid.individual.net...
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.

These are just two examples that I know of. You have to assume there
are more.
Good enough reason to keep the test.
>>
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.
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

Aug 1 '08 #45

P: n/a
"RobG" <rg***@iinet.net.auwrote in message
news:e6**********************************@a8g2000p rf.googlegroups.com...
>
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

Aug 1 '08 #46

P: n/a
On Jul 31, 8:22*pm, "Aaron Gray" <ang.use...@gmail.comwrote:
[snip]
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';
}

--
kangax

Aug 1 '08 #47

P: n/a
On Aug 1, 1:22 am, Aaron Gray wrote:
"Aaron Gray" wrote:
>Due to M$'s stupidity in not making DOMElements first class citizens the
following will not work :-
> function isElement( o)
{
return o instanceof Element
}

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.
>It works for FF, Opera and Safari.
>What prototype does is this :-
> isElement: function(object) {
return object && object.nodeType == 1
}

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.

<snip>
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).
Aug 1 '08 #48

P: n/a
RobG wrote:
Thomas 'PointedEars' Lahn wrote:
>Henry wrote:
>>On Jul 31, 5:46 am, RobG wrote:
<snip>
That turned out to be incorrect advice: I downloaded and
installed IE8 Beta 1, element.nodeType property returns
appropriate values, element.ELEMENT_NODE returns undefined.
<snip>
Which is correct W3C Core DOM conforming behaviour. The ECMAScript
biddings define the ELEMENT_NODE, ATTRIBUTE_NODE, etc properties as
properties of "The Node class" and list them as "Node. ELEMENT_NODE"
etc. suggesting that if there were a Node constructor it would be the
object that had the properties.
Further research shows that
<http://www.w3.org/TR/DOM-Level-3-Core/ecma-script-binding.htmleventually
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?
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
--
var bugRiddenCrashPronePieceOfJunk = (
navigator.userAgent.indexOf('MSIE 5') != -1
&& navigator.userAgent.indexOf('Mac') != -1
) // Plone, register_function.js:16
Aug 1 '08 #49

P: n/a
Aaron Gray wrote:
"David Mark" <dm***********@gmail.comwrote [...]:
>On Jul 31, 8:35 pm, Joost Diepenmaat <jo...@zeekat.nlwrote:
>>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.

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
--
Use any version of Microsoft Frontpage to create your site.
(This won't prevent people from viewing your source, but no one
will want to steal it.)
-- from <http://www.vortex-webdesign.com/help/hidesource.htm>
Aug 1 '08 #50

53 Replies

This discussion thread is closed

Replies have been disabled for this discussion.