Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Cross-Browser Mouse Event Handling

60 views
Skip to first unread message

Martin Rinehart

unread,
Feb 2, 2009, 1:11:33 PM2/2/09
to
I have written a short article on handling mouse events in a standards-
based, cross-browser way. It's here:

http://www.martinrinehart.com/examples/cross-browser-mouse-events.html

Sadly, quirksmode.org is quite obsolete on this subject.

Thomas 'PointedEars' Lahn

unread,
Feb 2, 2009, 1:22:10 PM2/2/09
to

Why is it that so often clueless wannabes think they need to write
*articles* about those subjects? Example:

| 1. Never assign event handlers in your markup. Assign functions via
| JavaScript.
|
| Wrong:
| <tag id='myObject' onclick='myOnClickHandler()'>
|
| Right:
| obj = document.getElementById( 'myObject' );
| obj.onclick=myClickHandler; // no parens

That is utter nonsense already. Using methods to retrieve element object
references, particularly untested ones without fallback, and then even
proprietary event handler properties referring to global functions is *way*
more problematic (as in: not interoperable, having side effects aso.) than a
standards-compliant event-handler attribute.

NOT recommended.


PointedEars

Doug Gunnoe

unread,
Feb 2, 2009, 1:22:48 PM2/2/09
to

You said:
1. Never assign event handlers in your markup. Assign functions via
JavaScript.
Wrong:
<tag id='myObject' onclick='myOnClickHandler()'>

So, why is it "wrong"? “Wrong” is kind of strong don’t you think?
Wouldn’t it be better to say “preferred”?

Thomas 'PointedEars' Lahn

unread,
Feb 2, 2009, 1:24:06 PM2/2/09
to
Thomas 'PointedEars' Lahn wrote:
> Martin Rinehart wrote:
>> I have written a short article on handling mouse events in a standards-
>> based, cross-browser way. It's here:
>>
>> http://www.martinrinehart.com/examples/cross-browser-mouse-events.html
>> [...]
>
> [...]

>
> | 1. Never assign event handlers in your markup. Assign functions via
> | JavaScript.
> |
> | Wrong:
> | <tag id='myObject' onclick='myOnClickHandler()'>
> |
> | Right:
> | obj = document.getElementById( 'myObject' );
> | obj.onclick=myClickHandler; // no parens
>
> [...]
> NOT recommended.

Correction: Recommended AGAINST.


PointedEars

Thomas 'PointedEars' Lahn

unread,
Feb 2, 2009, 1:25:43 PM2/2/09
to
Doug Gunnoe wrote:
> On Feb 2, 12:11 pm, Martin Rinehart <MartinRineh...@gmail.com> wrote:
>> http://www.martinrinehart.com/examples/cross-browser-mouse-events.html
>> [...]

>
> You said:
> 1. Never assign event handlers in your markup. Assign functions via
> JavaScript.
> Wrong:
> <tag id='myObject' onclick='myOnClickHandler()'>
>
> So, why is it "wrong"? “Wrong” is kind of strong don’t you think?
> Wouldn’t it be better to say “preferred”?

If yes, *why*, given the *more* compatible and *more* reliable alternative
that has *less* side effects?


PointedEars

Erwin Moller

unread,
Feb 2, 2009, 1:28:37 PM2/2/09
to
Martin Rinehart schreef:

Hi Martin,

Nice article. Nice simple easy-to-understand fix-up routine as far as I
can judge.

I have one remark: You start with the following:

[quote]


Never assign event handlers in your markup. Assign functions via JavaScript.
Wrong:
<tag id='myObject' onclick='myOnClickHandler()'>

Right:


obj = document.getElementById( 'myObject' );
obj.onclick=myClickHandler; // no parens

[/quote]

But you don't explain that at all.
I have no clue why you state that so boldly.
I use eventhandlers everywhere in my code in the way you call wrong, and
never had much trouble with them. ;-)

So maybe you could add a few thoughts about that too?


Regards,
Erwin Moller


--
"There are two ways of constructing a software design: One way is to
make it so simple that there are obviously no deficiencies, and the
other way is to make it so complicated that there are no obvious
deficiencies. The first method is far more difficult."
-- C.A.R. Hoare

Doug Gunnoe

unread,
Feb 2, 2009, 1:36:57 PM2/2/09
to
On Feb 2, 12:25 pm, Thomas 'PointedEars' Lahn <PointedE...@web.de>
wrote:

> If yes, *why*, given the *more* compatible and *more* reliable alternative
> that has *less* side effects?
>
> PointedEars

I can see where either way could be more convenient given a particular
situation, but I agree with you that the OP's characterization of it
being 'wrong' is strange.

And he starts off with a negative comment about quirksmode…??

Thomas 'PointedEars' Lahn

unread,
Feb 2, 2009, 1:48:44 PM2/2/09
to
Doug Gunnoe wrote:

> Thomas 'PointedEars' Lahn wrote:
>> If yes, *why*, given the *more* compatible and *more* reliable alternative
>> that has *less* side effects?
>> [...]

>
> I can see where either way could be more convenient given a particular
> situation, but I agree with you that the OP's characterization of it
> being 'wrong' is strange.

ACK

> And he starts off with a negative comment about quirksmode…??

The documentation on quirksmode.org is far from being perfect, indeed.
However, with a level of "knowledge" such as this, one better avoids
commenting on that.

When replying, retain the context of the quote and don't quote signatures,
please.


PointedEars

kangax

unread,
Feb 2, 2009, 1:55:12 PM2/2/09
to
Thomas 'PointedEars' Lahn wrote:
> Martin Rinehart wrote:
[...]

> | 1. Never assign event handlers in your markup. Assign functions via
> | JavaScript.
> |
> | Wrong:
> | <tag id='myObject' onclick='myOnClickHandler()'>
> |
> | Right:
> | obj = document.getElementById( 'myObject' );
> | obj.onclick=myClickHandler; // no parens
>
> That is utter nonsense already. Using methods to retrieve element object
> references, particularly untested ones without fallback, and then even
> proprietary event handler properties referring to global functions is *way*
> more problematic (as in: not interoperable, having side effects aso.) than a
> standards-compliant event-handler attribute.

But don't event handler attributes have their own problems - notably a
somewhat idiotic scope augmentation?

Wouldn't it be recommended to use something along these lines:

(function(){
...
var obj = document.getElementById('myObject');
if (obj) {
obj.onclick = someHandler;
}
...
})();


On a side note, looks like author forgot to declare that `obj`.

--
kangax

Thomas 'PointedEars' Lahn

unread,
Feb 2, 2009, 2:08:42 PM2/2/09
to
kangax wrote:
> Thomas 'PointedEars' Lahn wrote:
>> Martin Rinehart wrote:
> [...]
>> | 1. Never assign event handlers in your markup. Assign functions via
>> | JavaScript.
>> |
>> | Wrong:
>> | <tag id='myObject' onclick='myOnClickHandler()'>
>> |
>> | Right:
>> | obj = document.getElementById( 'myObject' );
>> | obj.onclick=myClickHandler; // no parens
>>
>> That is utter nonsense already. Using methods to retrieve element object
>> references, particularly untested ones without fallback, and then even
>> proprietary event handler properties referring to global functions is *way*
>> more problematic (as in: not interoperable, having side effects aso.) than a
>> standards-compliant event-handler attribute.
>
> But don't event handler attributes have their own problems - notably a
> somewhat idiotic scope augmentation?

Are you confusing markup attributes and script properties? -v please

> Wouldn't it be recommended to use something along these lines:
>
> (function(){
> ...
> var obj = document.getElementById('myObject');
> if (obj) {
> obj.onclick = someHandler;
> }
> ...
> })();

Of course not. Why?

> On a side note, looks like author forgot to declare that `obj`.

And he is assigning to host object's properties among all kinds of other
blunders.


PointedEars

Jeff

unread,
Feb 2, 2009, 3:20:01 PM2/2/09
to


I'm twisted around, and not sure where we are. Just what are you
suggesting for handlers?

I tend to either put them inline: <div onclick="someFunction(this)"

or global for the document:

document.onclick=someHandler

and sniffing out the event src in the handler and branching code from there

I don't see the problem though in doing this:

some_obj.onclick=myClickHandler;

That would seem better that the attachEvent cross browser mess.

I'm not trying to proselytize one way or another. I do have some new
code to write that will have multiple events to handle and I'd like a
clearer understanding of my options. Just trying to write cleaner code.

Jeff
>
>
> PointedEars

kangax

unread,
Feb 2, 2009, 4:18:44 PM2/2/09
to
Thomas 'PointedEars' Lahn wrote:
> kangax wrote:
[...]

>> But don't event handler attributes have their own problems - notably a
>> somewhat idiotic scope augmentation?
>
> Are you confusing markup attributes and script properties? -v please

I was referring to intrinsic event attributes [1] which augment created
functions with: element, (possibly) containing form element and document
element objects.

AFAIK, this doesn't happen when assigning event handlers directly to
element properties ( as in, `myElement.onclick = myHandler` ).

I considered the latter option to be safer in this regard (no scope
augmentation and so less chance of hard-to-find errors).

Am I missing something that makes former option a better candidate?

--
kangax

[1] http://www.w3.org/TR/REC-html40/interact/scripts.html#events

Garrett Smith

unread,
Feb 2, 2009, 4:34:03 PM2/2/09
to
kangax wrote:
> Thomas 'PointedEars' Lahn wrote:
>> Martin Rinehart wrote:


>
> But don't event handler attributes have their own problems - notably a
> somewhat idiotic scope augmentation?
>
> Wouldn't it be recommended to use something along these lines:
>

[snip]

The approach of assigning an event handler via script separates the
attachment from from the content, so the script can be moved around to
different place in the document.

The script might want to be moved for performance reasons, to lower in
the page, such as before the body tag, to allow the contents to render
without being blocked by one or more top scripts.

The article has an example of augmenting the event object:

| if ( !e.srcElement ) { e.srcElement = e.target; }

There might be an error if the host object does not allow such
modification. Instead, a local variable can be used:

var target = e.target || e.srcElement;

(a reusable function can also do the job)


Also:

| Actually, no browser tested yet returns a middle button click

javascript: void(document.onclick = function(e) {document.title=e.type;})

CLicking on my mouse Microsoft wheel, plugged into my mac.

Result in FF3 and Safari 3:
document's title changes to "click"

Write more tests that the reader can run.

Garrett

--
comp.lang.javascript FAQ <URL: http://jibbering.com/faq/ >

Thomas 'PointedEars' Lahn

unread,
Feb 2, 2009, 4:33:27 PM2/2/09
to
kangax wrote:
> Thomas 'PointedEars' Lahn wrote:
>> kangax wrote:
>>> But don't event handler attributes have their own problems - notably a
>>> somewhat idiotic scope augmentation?
>> Are you confusing markup attributes and script properties? -v please
>
> I was referring to intrinsic event attributes [1] which augment created
> functions with: element, (possibly) containing form element and document
> element objects.

How did you get that idea? Which functions?

<...
onclick="handleClick(typeof event != 'undefined' ? event : null, this)"
>...</...>

and similar works fine (albeit the value of `event' and `this' is somewhat
proprietary behavior), and the Function object referred to by `handleClick'
isn't augmented with anything.

> AFAIK, this doesn't happen when assigning event handlers directly to
> element properties ( as in, `myElement.onclick = myHandler` ).

In contrast, those element *object* properties are host-defined, and
completely proprietary. Chances for support are high for historical
reasons, but they may not be interoperable.

> I considered the latter option to be safer in this regard (no scope
> augmentation and so less chance of hard-to-find errors).
>
> Am I missing something that makes former option a better candidate?

Not writing spaghetti code, apparently.


PointedEars

kangax

unread,
Feb 2, 2009, 4:50:59 PM2/2/09
to
Thomas 'PointedEars' Lahn wrote:
> kangax wrote:
>> Thomas 'PointedEars' Lahn wrote:
>>> kangax wrote:
>>>> But don't event handler attributes have their own problems - notably a
>>>> somewhat idiotic scope augmentation?
>>> Are you confusing markup attributes and script properties? -v please
>> I was referring to intrinsic event attributes [1] which augment created
>> functions with: element, (possibly) containing form element and document
>> element objects.
>
> How did you get that idea? Which functions?
>
> <...
> onclick="handleClick(typeof event != 'undefined' ? event : null, this)"
> >...</...>
>
> and similar works fine (albeit the value of `event' and `this' is somewhat
> proprietary behavior), and the Function object referred to by `handleClick'
> isn't augmented with anything.

`handleClick` is not augmented, but the Function object whose body is
created from the value of attribute ("onclick" in this case) is
augmented with both - element in question and the document (that this
element is contained within) -

<html>
<head>
<title></title>
</head>
<body>
<div title="blah"
onclick="alert([body, title].join('\n'))">test</div>
</body>
</html>

- should demonstrate the issue clearly.

--
kangax

JR

unread,
Feb 2, 2009, 4:58:40 PM2/2/09
to
Hi,
I suppose Martin Rinehart is an unobtrusive javascript evangelist (a
Shiite maybe?). "Never assign event handlers in your markup" resembles
"Never, under any circumstances, add Javascript directly to the
document" from Christian Heilmann (a Yahoo javascript evangelist). I
prefer "never say never"...

> Sadly, quirksmode.org is quite obsolete on this subject.

Man, this line raises antipathy on a javascript newsgroup. Peter-Paul
Koch (ppk), John Resig, Douglas Crockford, Dean Edwards are gods for
me...

Cheers,
João Rodrigues

Garrett Smith

unread,
Feb 2, 2009, 4:58:57 PM2/2/09
to
Thomas 'PointedEars' Lahn wrote:
> kangax wrote:
>> Thomas 'PointedEars' Lahn wrote:
>>> kangax wrote:


> <...
> onclick="handleClick(typeof event != 'undefined' ? event : null, this)"
> >...</...>
>
> and similar works fine (albeit the value of `event' and `this' is somewhat
> proprietary behavior), and the Function object referred to by `handleClick'
> isn't augmented with anything.
>

No, that function isn't augmented. It is the event handler content that
is augmented. Something like:

function onclick(event) {
with(document) {
with(this.form) {
with(this) {
// Event handler attribute value here.
handleClick(typeof event != 'undefined' ? event : null, this);

Thomas 'PointedEars' Lahn

unread,
Feb 2, 2009, 5:01:36 PM2/2/09
to
Garrett Smith wrote:
> kangax wrote:
>> Thomas 'PointedEars' Lahn wrote:
>>> Martin Rinehart wrote:
>> But don't event handler attributes have their own problems - notably a
>> somewhat idiotic scope augmentation?
>>
>> Wouldn't it be recommended to use something along these lines:
>
> [snip]
>
> The approach of assigning an event handler via script separates the
> attachment from from the content, so the script can be moved around to
> different place in the document.

And completely separating the function from the markup it is operating on
(and with) is a Good Thing, because ...?

Assigning event listeners with scripting in fact makes the code less
reliable (because when using DOM features, there is no guarantee that and
how they will work), less efficient (because of more feature-testing that is
required then as script errors should be avoided), and lest you forget, it
makes debugging a lot harder, especially with addEventListener() or
attachEvent(). BTDT. So it should be only done when it is absolutely
necessary. In all other cases, event-handler attributes should be used
instead, and event bubbling should be employed where and when applicable and
interoperable.

> The script might want to be moved for performance reasons, to lower in
> the page, such as before the body tag,

Given that there is no "body tag", where do you think that is, exactly?

> to allow the contents to render without being blocked by one or more
> top scripts.

The `body' element has an intrinsic standards-compliant `onload'
event-handler attribute for that.


PointedEars

Thomas 'PointedEars' Lahn

unread,
Feb 2, 2009, 5:17:50 PM2/2/09
to
kangax wrote:
> Thomas 'PointedEars' Lahn wrote:
>> kangax wrote:
>>> Thomas 'PointedEars' Lahn wrote:
>>>> kangax wrote:
>>>>> But don't event handler attributes have their own problems - notably a
>>>>> somewhat idiotic scope augmentation?
>>>> Are you confusing markup attributes and script properties? -v please
>>> I was referring to intrinsic event attributes [1] which augment created
>>> functions with: element, (possibly) containing form element and document
>>> element objects.
>> How did you get that idea? Which functions?
>>
>> <...
>> onclick="handleClick(typeof event != 'undefined' ? event : null, this)"
>> >...</...>
>>
>> and similar works fine (albeit the value of `event' and `this' is somewhat
>> proprietary behavior), and the Function object referred to by `handleClick'
>> isn't augmented with anything.
>
> `handleClick` is not augmented, but the Function object whose body is
> created from the value of attribute ("onclick" in this case) is
> augmented with both - element in question and the document (that this
> element is contained within) -

No, it isn't. The scope chain of the execution context is different than
when the function was executed elsewhere (you could call that "augmented"),
but that is to be expected. And whether it is really a Function object that
is called remains to be seen; we are dealing with host objects here.

> <html>
> <head>
> <title></title>
> </head>
> <body>
> <div title="blah"
> onclick="alert([body, title].join('\n'))">test</div>
> </body>
> </html>

That's not Valid, BTW.

> - should demonstrate the issue clearly.

And that is a problem, because ...? As I said, simply don't write such
spaghetti code.


PointedEars

Garrett Smith

unread,
Feb 2, 2009, 5:25:26 PM2/2/09
to
Thomas 'PointedEars' Lahn wrote:
> Garrett Smith wrote:
>> kangax wrote:
>>> Thomas 'PointedEars' Lahn wrote:
>>>> Martin Rinehart wrote:
>>> But don't event handler attributes have their own problems - notably a
>>> somewhat idiotic scope augmentation?
>>>
>>> Wouldn't it be recommended to use something along these lines:
>> [snip]
>>
>> The approach of assigning an event handler via script separates the
>> attachment from from the content, so the script can be moved around to
>> different place in the document.
>
> And completely separating the function from the markup it is operating on
> (and with) is a Good Thing, because ...?
>

"so the script can be moved around to different place in the document"

> Assigning event listeners with scripting in fact makes the code less
> reliable (because when using DOM features, there is no guarantee that and

Can you show us an example of the unreliability?

> how they will work), less efficient (because of more feature-testing that is
> required then as script errors should be avoided), and lest you forget, it
> makes debugging a lot harder, especially with addEventListener() or
> attachEvent(). BTDT. So it should be only done when it is absolutely
> necessary. In all other cases, event-handler attributes should be used
> instead, and event bubbling should be employed where and when applicable and
> interoperable.
>
>> The script might want to be moved for performance reasons, to lower in
>> the page, such as before the body tag,
>
> Given that there is no "body tag", where do you think that is, exactly?
>

<!-- here -->
</body>
</html>

>> to allow the contents to render without being blocked by one or more
>> top scripts.
>
> The `body' element has an intrinsic standards-compliant `onload'
> event-handler attribute for that.
>

Adding a body onload event handler will not prevent the blocking nature
of a script.

Thomas 'PointedEars' Lahn

unread,
Feb 2, 2009, 5:28:13 PM2/2/09
to
JR wrote:
> I suppose Martin Rinehart is an unobtrusive javascript evangelist (a
> Shiite maybe?).

I don't suppose, I *know* he is a clueless wannabe, parroting what he has
managed to understand (or thought he had understood), from what he has been
posting so far. Isn't that at least the third article in a row that
promotes practices being marked as "not recommended" and "deprecated" around
here a long time ago?

> "Never assign event handlers in your markup" resembles
> "Never, under any circumstances, add Javascript directly to the
> document" from Christian Heilmann (a Yahoo javascript evangelist). I
> prefer "never say never"...

ACK

>> Sadly, quirksmode.org is quite obsolete on this subject.
>
> Man, this line raises antipathy on a javascript newsgroup. Peter-Paul
> Koch (ppk), John Resig, Douglas Crockford, Dean Edwards are gods for
> me...

I suppose at least one of them wouldn't mind had omitted their name from
this particular ... selection. And it seems few of them, if any, have a
good grasp of ECMAScript *and* DOM scripting. If those are your gods, you
better convert for your own sake ...


PointedEars

Thomas 'PointedEars' Lahn

unread,
Feb 2, 2009, 5:44:03 PM2/2/09
to
Garrett Smith wrote:
> Thomas 'PointedEars' Lahn wrote:
>> Garrett Smith wrote:
>>> kangax wrote:
>>>> Thomas 'PointedEars' Lahn wrote:
>>>>> Martin Rinehart wrote:
>>>> But don't event handler attributes have their own problems - notably a
>>>> somewhat idiotic scope augmentation?
>>>>
>>>> Wouldn't it be recommended to use something along these lines:
>>> [snip]
>>>
>>> The approach of assigning an event handler via script separates the
>>> attachment from from the content, so the script can be moved around to
>>> different place in the document.
>> And completely separating the function from the markup it is operating on
>> (and with) is a Good Thing, because ...?
>
> "so the script can be moved around to different place in the document"

You don't need to do this to have that. Besides, what are the practical
advantages of "moving scripts around"? The mere possibility isn't enough
to support a design decision.

>> Assigning event listeners with scripting in fact makes the code less
>> reliable (because when using DOM features, there is no guarantee that and
>
> Can you show us an example of the unreliability?

Another?

>> how they will work), less efficient (because of more feature-testing that is
>> required then as script errors should be avoided), and lest you forget, it
>> makes debugging a lot harder, especially with addEventListener() or
>> attachEvent(). BTDT. So it should be only done when it is absolutely
>> necessary. In all other cases, event-handler attributes should be used
>> instead, and event bubbling should be employed where and when applicable and
>> interoperable.
>>
>>> The script might want to be moved for performance reasons, to lower in
>>> the page, such as before the body tag,
>> Given that there is no "body tag", where do you think that is, exactly?
>
> <!-- here -->

Since the parse tree is incomplete at this point, there is no guarantee that
all required DOM objects have been created and their associations in the
document tree have been registered. We have been over this several times
already, apparently you have not been paying attention.

> </body>
^^^^^^^
This is the *end tag* of the *BODY/body element*. That element begins with
its start tag, <body ...>.

This is not a Web forum for script-kiddies, but a newsgroup for script
programmers; learn to use proper technical terms.

<http://www.w3.org/TR/html401/intro/sgmltut.html#h-3.2.1>

> </html>
>
>>> to allow the contents to render without being blocked by one or more
>>> top scripts.
>> The `body' element has an intrinsic standards-compliant `onload'
>> event-handler attribute for that.
>
> Adding a body onload event handler will not prevent the blocking nature
> of a script.

Nor will moving it within the `body' element. But if larger `script' code
is to be loaded, it does not matter where it is loaded (unless it executes
instead of declares, see above), for in the `onload' attribute value its
references are available.


PointedEars

RobG

unread,
Feb 2, 2009, 6:42:45 PM2/2/09
to
On Feb 3, 4:11 am, Martin Rinehart <MartinRineh...@gmail.com> wrote:
> I have written a short article on handling mouse events in a standards-
> based, cross-browser way. It's here:
>
> http://www.martinrinehart.com/examples/cross-browser-mouse-events.html

The following:

"Most browsers follow the standard, assigning a reference to the
object on which the event occured to e.srcElement. MSIE calls this
reference e.target, so again we're doing extra work to get MSIE
upgraded to standard. "

Is completely backwards - the standards compliant property is
Event.target, the IE proprietary property is Event.srcElement.

W3C Event.target
<URL: http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-Event-target
>

MS Event.srcElement
<URL: http://msdn.microsoft.com/en-us/library/ms534638(VS.85).aspx >

I find it useful to always reference standards or official
documentation where I can, that way errors are easily rectified.

As noted by others, do not assume you can successfully modify host
objects. If your intention is to "fix" a host object, either create
methods that, when called, return appropriate values or your own
object with modified properties and methods.


> Sadly, quirksmode.org is quite obsolete on this subject.

Feel free to contact the author and discuss that with him, he has a
link to his (reasonably active) blog on the quirksmode home page.


--
Rob

Richard Cornford

unread,
Feb 2, 2009, 6:54:21 PM2/2/09
to
Garrett Smith wrote:
> Thomas 'PointedEars' Lahn wrote:
>> Garrett Smith wrote:
>>> kangax wrote:
>>>> Thomas 'PointedEars' Lahn wrote:
>>>>> Martin Rinehart wrote:
>>>> But don't event handler attributes have their own problems
>>>> - notably a somewhat idiotic scope augmentation?
>>>>
>>>> Wouldn't it be recommended to use something along these lines:
>>> [snip]
>>>
>>> The approach of assigning an event handler via script separates
>>> the attachment from from the content, so the script can be moved
>>> around to different place in the document.
>>
>> And completely separating the function from the markup it is
>> operating on (and with) is a Good Thing, because ...?
>
> "so the script can be moved around to different place in the
> document"

That is not much of a justification. For a start it is not true; you can
move the functions that are created from intrinsic event handlers around
if you wanted to. After all, they should not be written to use their
augmented scope chains as the augmentation itself is not guaranteed to
happen at all, and is inconsistent between browsers where it does
happen, and simultaneously that code should be written with the
anticipation of the worst-case augmentation (where the element and all
of its ancestors in the DOM hierarchy are added to the scope chain).

A better justification would being able to use the same code with many
intrinsic events without suffering the overhead of creating many
function objects. Though someone is likely to mention event delegation
in response to that point.

<snip>


>>> to allow the contents to render without being blocked by
>>> one or more top scripts.

<snip>

That story gets put about as if it is some sort of universal panacea.
When the contents that the reader is interested in are at the top of the
document then putting them where they can be read as soon as possible
might be a good ides. But it can be an irritating pain if what you are
interested in is at the bottom of the page (such as the latest comments
on a blog that you have already read) and the loading of the scripts at
the bottom of the page block the ability to scroll. In that case I would
rather not have the top of the page sitting there taunting me while the
browser is not allowing me to scroll to what I am interested in.

It may be that the real issue is attempting to download too much script
code, and playing around with where that code is loaded is just playing
with the symptoms rather than addressing the cause.

Richard.

RobG

unread,
Feb 2, 2009, 7:16:56 PM2/2/09
to
On Feb 3, 9:54 am, "Richard Cornford" <Rich...@litotes.demon.co.uk>
wrote:

> Garrett Smith wrote:
> > Thomas 'PointedEars' Lahn wrote:
> >> Garrett Smith wrote:
> >>> kangax wrote:
> >>>> Thomas 'PointedEars' Lahn wrote:
> >>>>> Martin Rinehart wrote:
> >>>> But don't event handler attributes have their own problems
> >>>> - notably a somewhat idiotic scope augmentation?
>
> >>>> Wouldn't it be recommended to use something along these lines:
> >>> [snip]
>
> >>> The approach of assigning an event handler via script separates
> >>> the attachment from from the content, so the script can be moved
> >>> around to different place in the document.
>
> >> And completely separating the function from the markup it is
> >> operating on (and with) is a Good Thing, because ...?
>
[...]

>
> <snip>>>> to allow the contents to render without being blocked by
> >>> one or more top scripts.
>
> <snip>
>
> That story gets put about as if it is some sort of universal panacea.
> When the contents that the reader is interested in are at the top of the
> document then putting them where they can be read as soon as possible
> might be a good ides. But it can be an irritating pain if what you are
> interested in is at the bottom of the page (such as the latest comments
> on a blog that you have already read) and the loading of the scripts at
> the bottom of the page block the ability to scroll. In that case I would
> rather not have the top of the page sitting there taunting me while the
> browser is not allowing me to scroll to what I am interested in.
>
> It may be that the real issue is attempting to download too much script
> code, and playing around with where that code is loaded is just playing
> with the symptoms rather than addressing the cause.

This philosophy has turned full circle: events added dynamically
during the page load (so-called "unobtrusive javascript") can take so
long that some libraries have block and unblock methods to prevent the
user doing anything until the page is loaded and all initialising
scripts have run.

So much for "unobtrusive"!

A similar model was tried in version 1 browsers over a decade ago[1]
and rejected by users. It seems absurd that "Web 2-point-oh"
applications are reintroducing it as a modern, useful feature when it
is infact an indication of poor design and implementation of
functionality.

1. Early versions of Netscape (and probably other browsers) didn't
show any page content until all the page content had finished loading.


--
Rob

kangax

unread,
Feb 2, 2009, 11:16:07 PM2/2/09
to
Thomas 'PointedEars' Lahn wrote:
> kangax wrote:
[...]

>> `handleClick` is not augmented, but the Function object whose body is
>> created from the value of attribute ("onclick" in this case) is
>> augmented with both - element in question and the document (that this
>> element is contained within) -
>
> No, it isn't. The scope chain of the execution context is different than
> when the function was executed elsewhere (you could call that "augmented"),
> but that is to be expected. And whether it is really a Function object that
> is called remains to be seen; we are dealing with host objects here.

It isn't? Then how can an example above be explained? It is also written
about on jibbering in "Unsafe Names" article [1] which was, IIRC,
reviewed and discussed here. After reading it and then experimenting
with few tests against this behavior, I was pretty sure that's exactly
what's happening. Am I wrong?

[...]

>> - should demonstrate the issue clearly.
>
> And that is a problem, because ...? As I said, simply don't write such
> spaghetti code.

I'm not sure how this is relevant to spaghetti code : )

The code itself - i.e. value of the attribute - can be as "clean" as
possible, yet this wouldn't prevent name collisions (due to scope
augmentation) from happening (unless, of course, the definition of
"clean" code would include such prerequisites as, say, somehow prefixing
all used Identifiers in event handler - to minimize any possible
collisions as much as possible)

I understand that a person who knows what he/she is doing will not
likely run into these issues, but a beginner easily might, so I assumed
that he/she would be better off using object properties (if we are
talking about these two options only, and not about
`addEventListener`/`attachEvent`).

I wasn't aware of proprietary nature of these properties. You also
mentioned side effects. What exactly are those?

[1] http://jibbering.com/faq/names/

--
kangax

Garrett Smith

unread,
Feb 3, 2009, 2:08:55 AM2/3/09
to
Richard Cornford wrote:
> Garrett Smith wrote:
>> Thomas 'PointedEars' Lahn wrote:
>>> Garrett Smith wrote:
>>>> kangax wrote:
>>>>> Thomas 'PointedEars' Lahn wrote:
>>>>>> Martin Rinehart wrote:
>>>>> But don't event handler attributes have their own problems
>>>>> - notably a somewhat idiotic scope augmentation?
>>>>>
>>>>> Wouldn't it be recommended to use something along these lines:
>>>> [snip]
>>>>
>>>> The approach of assigning an event handler via script separates
>>>> the attachment from from the content, so the script can be moved
>>>> around to different place in the document.
>>>
>>> And completely separating the function from the markup it is
>>> operating on (and with) is a Good Thing, because ...?
>>
>> "so the script can be moved around to different place in the
>> document"
>
> That is not much of a justification. For a start it is not true; you can
> move the functions that are created from intrinsic event handlers around
> if you wanted to.

Given a script "a.js" where a function |a| is defined inside it, and
then referenced in an event handler:

<script src="a.js"></script>

</head>
<body>
<p onclick="a()">...</p>

...

no problem, but if someone went and moved the script to the bottom,

</head>
<body>
<p onclick="a()">...</p>
...
<p>a lot of images, iframes, et c in this document...</p>
<script src="a.js"></script>

if the user clicks the p before a.js is loaded, the result would be an
error.

> A better justification would being able to use the same code with many
> intrinsic events without suffering the overhead of creating many
> function objects. Though someone is likely to mention event delegation
> in response to that

Bubbling ("delegation") could be done either way.

>
> <snip>
>>>> to allow the contents to render without being blocked by
>>>> one or more top scripts.
> <snip>
>
> That story gets put about as if it is some sort of universal panacea.

The decision to move the script to the bottom means that the html
elements reference the script via event handlers. The element appears
visually to the user before it is scripted. The interactivity that the
script would provide will appear soon after.

> When the contents that the reader is interested in are at the top of the
> document then putting them where they can be read as soon as possible
> might be a good ides. But it can be an irritating pain if what you are
> interested in is at the bottom of the page (such as the latest comments
> on a blog that you have already read) and the loading of the scripts at
> the bottom of the page block the ability to scroll. In that case I would
> rather not have the top of the page sitting there taunting me while the
> browser is not allowing me to scroll to what I am interested in.
>

Which browser does an external script block scrolling?


> It may be that the real issue is attempting to download too much script
> code, and playing around with where that code is loaded is just playing
> with the symptoms rather than addressing the cause.
>

I have seen network latency for 1x1 gif that took over 7 seconds to
load. This was a feature of an advertisement. It had the effect of
keeping the browsers progress bar from completing.

Reducing the file size matters, but will not prevent blocking. The
blocking includes the duration of latency.

Garrett

Richard Cornford

unread,
Feb 3, 2009, 9:26:36 AM2/3/09
to
On Feb 3, 4:16 am, kangax wrote:
> Thomas 'PointedEars' Lahn wrote:
>> kangax wrote:
> [...]
>>> `handleClick` is not augmented, but the Function object whose
>>> body is created from the value of attribute ("onclick" in this
>>> case) is augmented with both - element in question and the
>>> document (that this element is contained within) -
>
>> No, it isn't. The scope chain of the execution context is
>> different than when the function was executed elsewhere (you
>> could call that "augmented"), but that is to be expected.
>> And whether it is really a Function object that is called
>> remains to be seen; we are dealing with host objects here.
>
> It isn't?

What is a function object in that case? Having a [[Call]] method makes
something callable (capable of being called by javascript) but it
would be possible to argue that a host object that is callable is not
necessarily a function object. Particularly if it could be shown to
have behaviour that was inconsistent with ECMAScript native function
object behaviour. Drawing such fine distinctions is more likely to be
argumentative than useful.

> Then how can an example above be explained? It is also
> written about on jibbering in "Unsafe Names" article [1] which
> was, IIRC, reviewed and discussed here.

Not more than superficially. The account given of scope chain
augmentation barely touches the surface of the subject (asserting, as
it does, a single behaviour where many divergent behaviours have been
observed). See:-

<URL: http://groups.google.co.uk/group/comp.lang.javascript/browse_frm/thread/2d1bd03a4bc47add
>

- which includes some test code for examining what is really going on.

> After reading it and then experimenting with few tests against
> this behavior, I was pretty sure that's exactly what's
> happening. Am I wrong?

Yes, but mostly in the sense that there is more going on that
described.

<snip>


> I understand that a person who knows what he/she is doing
> will not likely run into these issues, but a beginner easily
> might,

And a thousand others.

> so I assumed that he/she would be better off using
> object properties (if we are talking about these two options
> only, and not about `addEventListener`/`attachEvent`).

Surly the best thing for a beginner is to become "a person who knows
what he/she is doing" and avoid the issues in that way? If someone's
browser scripting job can be done through nothing more than the blind
application of a set of rules then that person is ultimately
replaceable with software.

<snip>
> [1]http://jibbering.com/faq/names/

Was there a reason for not linking directly to the section on scope
chain augmentation, or does that resource not support such simple
hypertext concepts?

Richard.

Richard Cornford

unread,
Feb 3, 2009, 9:53:40 AM2/3/09
to

So the "the scripts" you referred to were external script files
imported by a web page rather than intrinsic event functions.

> no problem, but if someone went and moved the script to the bottom,
>
> </head>
> <body>
> <p onclick="a()">...</p>
> ...
> <p>a lot of images, iframes, et c in this document...</p>
> <script src="a.js"></script>
>
> if the user clicks the p before a.js is loaded, the result
> would be an error.

But a pretty much identical case follows when assigning to intrinsic
event properties. If you write - el.onclick = a; - and the code that
defines - a - has not yet been processed you get another error.

In the end there is an order in which things work and an order in
which they don't (or rather, many of each).

>> A better justification would being able to use the same code
>> with many intrinsic events without suffering the overhead
>> of creating many function objects. Though someone is likely
>> to mention event delegation in response to that
>
> Bubbling ("delegation") could be done either way.

Yes, but there is no reason to expect that the function creation
overheads for a single intrinsic event attribute would be
significantly different form the function creation overheads for a
single function in any other context.

>> <snip>
>>>>> to allow the contents to render without being blocked by
>>>>> one or more top scripts.
>> <snip>
>
>> That story gets put about as if it is some sort of universal
> panacea.
>
> The decision to move the script to the bottom means that the
> html elements reference the script via event handlers. The
> element appears visually to the user before it is scripted.
> The interactivity that the script would provide will appear
> soon after.

Or not that soon. And/or not necessarily before the user starts
attempting to interact with the element.

>> When the contents that the reader is interested in are at
>> the top of the document then putting them where they can
>> be read as soon as possible might be a good ides. But it
>> can be an irritating pain if what you are interested in is
>> at the bottom of the page (such as the latest comments on
>> a blog that you have already read) and the loading of the
>> scripts at the bottom of the page block the ability to
>> scroll. In that case I would rather not have the top
>> of the page sitting there taunting me while the browser
>> is not allowing me to scroll to what I am interested in.
>
> Which browser does an external script block scrolling?

Most of them have their UI blocked by javascript processing, which
includes the variable instantiation and global code evaluation
associated with loading an external resource.

>> It may be that the real issue is attempting to download too
>> much script code, and playing around with where that code
>> is loaded is just playing with the symptoms rather than
>> addressing the cause.
>
> I have seen network latency for 1x1 gif that took over 7
> seconds to load. This was a feature of an advertisement.
> It had the effect of keeping the browsers progress bar from
> completing.
>
> Reducing the file size matters, but will not prevent blocking.
> The blocking includes the duration of latency.

So which browsers block the UI while HTTP requests are in progress?

Richard.

Garrett Smith

unread,
Feb 3, 2009, 12:59:36 PM2/3/09
to

The page-specific code can have a reference to both |el| and |a|.

a.js:
var el = document.getElementById('el').
el.onclick = a;

function a() {

}


>
>>> A better justification would being able to use the same code
>>> with many intrinsic events without suffering the overhead
>>> of creating many function objects. Though someone is likely
>>> to mention event delegation in response to that
>> Bubbling ("delegation") could be done either way.
>
> Yes, but there is no reason to expect that the function creation
> overheads for a single intrinsic event attribute would be
> significantly different form the function creation overheads for a
> single function in any other context.
>
>>> <snip>
>>>>>> to allow the contents to render without being blocked by
>>>>>> one or more top scripts.
>>> <snip>
>>> That story gets put about as if it is some sort of universal
>> panacea.
>>
>> The decision to move the script to the bottom means that the
>> html elements reference the script via event handlers. The
>> element appears visually to the user before it is scripted.
>> The interactivity that the script would provide will appear
>> soon after.
>
> Or not that soon. And/or not necessarily before the user starts
> attempting to interact with the element.
>

The user may begin to interact with the element, and in that case, an
acceptable fallback behavior should occur. This can be a better user
experience because the user gets some content/functionality but is not
blocked by the script download.

Content does not need to be loaded in the order in which it appears on
the page. Navigation and especially any ads can be moved down in source
order and arranged on the page using CSS.

>>> When the contents that the reader is interested in are at
>>> the top of the document then putting them where they can
>>> be read as soon as possible might be a good ides. But it
>>> can be an irritating pain if what you are interested in is
>>> at the bottom of the page (such as the latest comments on
>>> a blog that you have already read) and the loading of the
>>> scripts at the bottom of the page block the ability to
>>> scroll. In that case I would rather not have the top
>>> of the page sitting there taunting me while the browser
>>> is not allowing me to scroll to what I am interested in.
>> Which browser does an external script block scrolling?
>
> Most of them have their UI blocked by javascript processing, which
> includes the variable instantiation and global code evaluation
> associated with loading an external resource.
>

Loading an external resource does not freeze the UI.

Executing a script does freeze the UI, for example:

// this will freeze your browser.
for(var s, i = 0; i < 500000; i++) {
s += i + "" + i;
}

That code, as the comment indicates, will freeze up most browsers
temporarily. That would prevent scrolling, typing, et c. Very annoying.

The problem will occur with inline code, with an onload or ondomready
hook regardless of where the script was placed.

However, loading an external resource does not freeze the UI [1].

The execution of the script freezes the UI. The download of a script
does not.

However, the download of a script blocks HTML from rendering [1].

By block, I mean, the browser stops downloading HTML and downloads the
script it encounters. Other than Firefox 3.1 and IE8, all browsers block.

To avoid ambiguity, I am using the term "freeze" to describe a browser
becoming unresponsive to user action when downloading/parsing a script.

A script that does not do a lot of processing would not freeze the UI
noticeably.

Garrett

[1]http://stevesouders.com/hpws/js-middle.php

Thomas 'PointedEars' Lahn

unread,
Feb 3, 2009, 1:03:34 PM2/3/09
to
kangax wrote:
> Thomas 'PointedEars' Lahn wrote:
>> kangax wrote:
> [...]
>>> `handleClick` is not augmented, but the Function object whose body is
>>> created from the value of attribute ("onclick" in this case) is
>>> augmented with both - element in question and the document (that this
>>> element is contained within) -
>> No, it isn't. The scope chain of the execution context is different
>> than when the function was executed elsewhere (you could call that
>> "augmented"), but that is to be expected. And whether it is really a
>> Function object that is called remains to be seen; we are dealing with
>> host objects here.
>
> It isn't? Then how can an example above be explained? It is also written
> about on jibbering in "Unsafe Names" article [1] which was, IIRC,
> reviewed and discussed here. After reading it and then experimenting with
> few tests against this behavior, I was pretty sure that's exactly what's
> happening. Am I wrong?

Yes. Not the called Function object (if that) is "augmented", but the
*scope chain* of the execution context that is entered when calling it.
That is an important difference.

> [...]
>
>>> - should demonstrate the issue clearly.
>> And that is a problem, because ...? As I said, simply don't write such
>> spaghetti code.
>
> I'm not sure how this is relevant to spaghetti code : )

The issue you describe does not arise if you call a method in the attribute
value and only pass the necessary values, for the called method runs in a
different execution context which scope chain is not "augmented" as such.

By the term "spaghetti code" I describe using attribute values contrary to
that approach. (Spaghetti tend to be rather long and intertwined ;-))

> The code itself - i.e. value of the attribute - can be as "clean" as
> possible, yet this wouldn't prevent name collisions (due to scope
> augmentation) from happening

Yes, it would. However, declaring the offending identifier in the attribute
value would likely resolve the issue.

> I understand that a person who knows what he/she is doing will not likely
> run into these issues, but a beginner easily might, so I assumed that
> he/she would be better off using object properties (if we are talking
> about these two options only, and not about
> `addEventListener`/`attachEvent`).

I am afraid you are mistaken.

> I wasn't aware of proprietary nature of these properties. You also
> mentioned side effects. What exactly are those?

The side effect I was referring to was mostly that being caused by using a
reference to a global function in the example when that was not necessary.
Granted, this is negligible when compared to a global function that is
passed `event' and/or `this'. But you don't always need such a function
with event-handler attributes.

Other side effects, such that which arise from unconditionally assigning to
the event-handler property and what that would mean for the behavior of
existing markup (if the assigning is effective), however, cannot be denied.


PointedEars

kangax

unread,
Feb 3, 2009, 1:08:53 PM2/3/09
to
Richard Cornford wrote:
> On Feb 3, 4:16 am, kangax wrote:
>> Thomas 'PointedEars' Lahn wrote:
>>> kangax wrote:
>> [...]
>>>> `handleClick` is not augmented, but the Function object whose
>>>> body is created from the value of attribute ("onclick" in this
>>>> case) is augmented with both - element in question and the
>>>> document (that this element is contained within) -
>>> No, it isn't. The scope chain of the execution context is
>>> different than when the function was executed elsewhere (you
>>> could call that "augmented"), but that is to be expected.
>>> And whether it is really a Function object that is called
>>> remains to be seen; we are dealing with host objects here.
>> It isn't?
>
> What is a function object in that case? Having a [[Call]] method makes
> something callable (capable of being called by javascript) but it
> would be possible to argue that a host object that is callable is not
> necessarily a function object. Particularly if it could be shown to
> have behaviour that was inconsistent with ECMAScript native function
> object behaviour. Drawing such fine distinctions is more likely to be
> argumentative than useful.

Perhaps, calling the production of "parsing" intrinsic event handler a
"Function object" is too strong of a statement. It's also, technically,
a false statement, since we know that most of MSHTML host methods, for
example, are missing `Function.prototype` from their prototype chains
(neither do they have a `constructor` referencing Function object).

I wanted, instead, to focus on the scope augmentation peculiarities,
rather than what that production should be called.

>
>> Then how can an example above be explained? It is also
>> written about on jibbering in "Unsafe Names" article [1] which
>> was, IIRC, reviewed and discussed here.
>
> Not more than superficially. The account given of scope chain
> augmentation barely touches the surface of the subject (asserting, as
> it does, a single behaviour where many divergent behaviours have been
> observed). See:-
>
> <URL: http://groups.google.co.uk/group/comp.lang.javascript/browse_frm/thread/2d1bd03a4bc47add
>
> - which includes some test code for examining what is really going on.

That thread is an amazing cradle of knowledge, thanks. It seems useful
to include those results in the "Unsafe Names" article. I also want to
run that test case on the newer browsers whenever I get a chance (as
from the quick look at the results in FF 3.0.5, it seems like element
ancestors other than document and form - i.e. `div`, `table`, `thead`,
`tr`, `th` (from the "first link onclick") - are no longer included in
the chain)

[...]

>> [1]http://jibbering.com/faq/names/
>
> Was there a reason for not linking directly to the section on scope
> chain augmentation, or does that resource not support such simple
> hypertext concepts?

No reason but my sloppiness :)

<URL http://jibbering.com/faq/names/unsafe_names.html >
(under "Example 3: Augmented Scope Chain")

--
kangax

kangax

unread,
Feb 3, 2009, 1:53:39 PM2/3/09
to
Thomas 'PointedEars' Lahn wrote:
> kangax wrote:
[...]
>> It isn't? Then how can an example above be explained? It is also written
>> about on jibbering in "Unsafe Names" article [1] which was, IIRC,
>> reviewed and discussed here. After reading it and then experimenting with
>> few tests against this behavior, I was pretty sure that's exactly what's
>> happening. Am I wrong?
>
> Yes. Not the called Function object (if that) is "augmented", but the
> *scope chain* of the execution context that is entered when calling it.
> That is an important difference.

You're right. That *is* an important difference.

[...]

>> I'm not sure how this is relevant to spaghetti code : )
>
> The issue you describe does not arise if you call a method in the attribute
> value and only pass the necessary values, for the called method runs in a
> different execution context which scope chain is not "augmented" as such.

Ah, yes, that makes sense, of course.

What I somehow missed is an important fact that a scope of a function
declared outside of an event handler is unaffected by the augmented
scope of this event handler (I caught myself making this mistake few
times already :/).

IOW, -

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title></title>
<script type="text/javascript">
function fn() {
alert(typeof title); // alerts `undefined` (duh!)
}
</script>
</head>
<body>
<div title="boo" onclick="fn()">test</div>
</body>
</html>

- since, as I understand, scope chain of `fn`, when called, consists of
`fn`'s Activation Object followed by `fn`'s [[Scope]], and that
[[Scope]] consists of a global object only, as that is where it was
declared.

Is this correct?

[...]

>> The code itself - i.e. value of the attribute - can be as "clean" as
>> possible, yet this wouldn't prevent name collisions (due to scope
>> augmentation) from happening
>
> Yes, it would. However, declaring the offending identifier in the attribute
> value would likely resolve the issue.

Of course.

[...]

>> I wasn't aware of proprietary nature of these properties. You also
>> mentioned side effects. What exactly are those?
>
> The side effect I was referring to was mostly that being caused by using a
> reference to a global function in the example when that was not necessary.
> Granted, this is negligible when compared to a global function that is
> passed `event' and/or `this'. But you don't always need such a function
> with event-handler attributes.

Then where should the function (called from the event handler) be
declared, if not globally (and since we don't want to declare it within
an event handler itself for obvious reasons)?

--
kangax

Dr J R Stockton

unread,
Feb 3, 2009, 11:39:36 AM2/3/09
to
In comp.lang.javascript message <498739D2...@PointedEars.de>, Mon,
2 Feb 2009 19:22:10, Thomas 'PointedEars' Lahn <Point...@web.de>
posted:
>
>Why is it that so often clueless wannabes think they need to write
>*articles* about those subjects? Example:

Perhaps it is because they have not succeeded in finding anything
better. Obviously your page on the subject is incomprehensible,
unreliable, or just not effectively published. Try being constructive
in your responses in newsgroups - AIUI, even the Germans don't like you,
although on the average they are nice people (i.e. all the others I know
of are much nicer) - and surprise us all.

--
(c) John Stockton, nr London UK. ???@merlyn.demon.co.uk Turnpike v6.05 MIME.
Web <URL:http://www.merlyn.demon.co.uk/> - FAQish topics, acronyms, & links.
Check boilerplate spelling -- error is a public sign of incompetence.
Never fully trust an article from a poster who gives no full real name.

Thomas 'PointedEars' Lahn

unread,
Feb 3, 2009, 4:33:38 PM2/3/09
to
kangax wrote:
> Thomas 'PointedEars' Lahn wrote:
>> kangax wrote:
>>> I'm not sure how this is relevant to spaghetti code : )
>> The issue you describe does not arise if you call a method in the attribute
>> value and only pass the necessary values, for the called method runs in a
>> different execution context which scope chain is not "augmented" as such.
>
> [...]

> IOW, -
>
> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
> "http://www.w3.org/TR/html4/strict.dtd">
> <html>
> <head>
> <title></title>
> <script type="text/javascript">
> function fn() {
> alert(typeof title); // alerts `undefined` (duh!)
> }
> </script>
> </head>
> <body>
> <div title="boo" onclick="fn()">test</div>
> </body>
> </html>
>
> - since, as I understand, scope chain of `fn`, when called, consists of
> `fn`'s Activation Object followed by `fn`'s [[Scope]], and that
> [[Scope]] consists of a global object only, as that is where it was
> declared.
>
> Is this correct?

Generally, yes. But, to be exact, it depends on the runtime environment.
For example, in MSHTML apparently there is a host object in the scope chain
before the Global Object.

See also: <news:30050051....@PointedEars.de>

>>> I wasn't aware of proprietary nature of these properties. You also
>>> mentioned side effects. What exactly are those?
>> The side effect I was referring to was mostly that being caused by using a
>> reference to a global function in the example when that was not necessary.
>> Granted, this is negligible when compared to a global function that is
>> passed `event' and/or `this'. But you don't always need such a function
>> with event-handler attributes.
>
> Then where should the function (called from the event handler) be
> declared, if not globally (and since we don't want to declare it within
> an event handler itself for obvious reasons)?

If side-effects of declaring global functions are a concern, those functions
can be made methods of user-defined native objects instead of or in addition
to the declaration, of course.

However, I was thinking more along the lines of

<a href="foo"
onclick="return window.confirm('Go to &lt;' + this.href + '&gt;?')"
>bar</a>

(The element does not even need a name or ID then which, given the
aforementioned host object peculiarity, could turn out to be advantageous in
two ways.)

Now, please compare this simple and interoperable code against the following
"unobtrusive" solution, supposed to be equivalent to the former:

<a href="foo" id="foo">bar</a>
...
<script type="text/javascript">
// more feature-testing required here
var o = document.getElementById(...);

// doesn't run if a reference to the element object
// cannot be obtained (at this point)
if (o)
{
// more feature-testing required here;
// also needs support for function expressions
// if one doesn't want to refer to global functions
// or a user-defined method
o.onclick = function(e) {
// more feature testing required here
if (!e) e = window.event;

// doesn't run without an exposed event object
if (e)
{
// more feature-testing required here; that's one advantage
// of this approach for a change because an inline
// feature test could result in spaghetti code
if (!window.confirm('Go to <' + this.href + '>?'))
{
// more feature-testing required here
e.returnValue = false;
e.preventDefault();
return false;
}
}
};
}
</script>

I am pretty sure you will forgive me if I really fail to see why the latter
would be any better, even though some parts could be moved into a wrapper
method.

BTW, it appears to be another underappreciated fact that proprietary
event-handler properties cannot be reliably feature-tested for; a typeof
operation on the property access might yield "undefined" even if the
property is supported (because it has not been assigned a value yet), and
other testing methods are not backwards-compatible to the reference
implementation of Netscape 3.0 (or 4.06, if you wish). As a consequence,
I have removed the corresponding feature test from the
dhtml.addEventListener() wrapper method because it gave false negatives in
runtime environments that did not support addEventListener(), even though
I am risking runtime errors with unconditionally assigning to the property
of a host object.


PointedEars

kangax

unread,
Feb 3, 2009, 9:54:42 PM2/3/09
to
kangax wrote:
[...]

> to include those results in the "Unsafe Names" article. I also want to
> run that test case on the newer browsers whenever I get a chance (as
> from the quick look at the results in FF 3.0.5, it seems like element
> ancestors other than document and form - i.e. `div`, `table`, `thead`,
> `tr`, `th` (from the "first link onclick") - are no longer included in
> the chain)

The following browsers (all run on Mac OSX 10.5.6; IE's - on WinXP SP2
and Konqueror on Ubuntu 8.10 - both in a virtual machine) appear to be
quite consistent -

// Desktop

Opera 9.27, 9.63, 10a;
Safari 3.2.1;
Chrome 1.0.154.46;
Firefox 2.0.0.18, 3.0.5;
IE 7, 8.0RC1;
Konqueror 4.1;

// Mobile

Blackberry 4.7 (9500 model)
MSIEMobile 6.0 (WinCE)

- all produce:

// Button

ex0 = global
ex1 = document #document
ex2 = document #document
ex3 = document #document
ex4 = 4 FORM
ex5 = 4 FORM
ex6 = 4 FORM
ex7 = 7 INPUT
ex8 = 7 INPUT
ex9 = 7 INPUT

// First link

ex0 = global
ex1 = document #document
ex2 = document #document
ex3 = document #document
ex4 = document #document
ex5 = document #document
ex6 = document #document
ex7 = document #document
ex8 = 8 A
ex9 = 8 A

// Second link

ex0 = global
ex1 = document #document
ex2 = document #document
ex3 = document #document
ex4 = document #document
ex5 = document #document
ex6 = document #document
ex7 = document #document
ex8 = document #document
ex9 = 9 A

--
kangax

Richard Cornford

unread,
Feb 10, 2009, 6:49:53 PM2/10/09
to
kangax wrote:
> kangax wrote:
<snip>
>> .... I also want to run that test case on the newer browsers

>> whenever I get a chance (as from the quick look at the results
>> in FF 3.0.5, it seems like element ancestors other than document
>> and form - i.e. `div`, `table`, `thead`, `tr`, `th` (from the
>> "first link onclick") - are no longer included in the chain)

It is a little inevitable that browsers, and especially the 'popular'
browsers that the average web developer has heard of, should migrate
towards consistent behaviour as people report their inconsistencies a
bugs. When we did those experiments back in 2003 we were testing Opera
7.11, and it was not adding the document to the scope chain. As I recall
Opera had changed so that it was adding the document by version 7.2.

And the more elaborate scope chain augmentation has caused 'works in IE
but not Mozilla' questions on this group where people were attempting to
access things like global variables named - rows - from an event handler
on an element in a table and unexpectedly picking up the collection on
the containing TABLE (or TBODY, or whatever).

<snip>


> Blackberry 4.7 (9500 model)
> MSIEMobile 6.0 (WinCE)

<snip>

Do you know which browser the Blackberry is using? Is it a re-barged
NetFront? Back in 2003 NetFront was one of the browsers that did not
augment the scope chain at all. I noticed that NetFront was still
shipping on new Nokia phones last year so it would be nice to know where
they are at now.

Richard.

David Mark

unread,
Feb 10, 2009, 6:55:49 PM2/10/09
to
On Feb 10, 6:49 pm, "Richard Cornford" <Rich...@litotes.demon.co.uk>
wrote:

IIRC, some version of NetFront is used in the PS3, so it doesn't seem
to be going anywhere.

kangax

unread,
Feb 10, 2009, 7:37:19 PM2/10/09
to
Richard Cornford wrote:
> kangax wrote:
>> kangax wrote:
> <snip>
>>> .... I also want to run that test case on the newer browsers
>>> whenever I get a chance (as from the quick look at the results
>>> in FF 3.0.5, it seems like element ancestors other than document
>>> and form - i.e. `div`, `table`, `thead`, `tr`, `th` (from the
>>> "first link onclick") - are no longer included in the chain)
>
> It is a little inevitable that browsers, and especially the 'popular'
> browsers that the average web developer has heard of, should migrate
> towards consistent behaviour as people report their inconsistencies a
> bugs. When we did those experiments back in 2003 we were testing Opera
> 7.11, and it was not adding the document to the scope chain. As I recall
> Opera had changed so that it was adding the document by version 7.2.
>
> And the more elaborate scope chain augmentation has caused 'works in IE
> but not Mozilla' questions on this group where people were attempting to
> access things like global variables named - rows - from an event handler
> on an element in a table and unexpectedly picking up the collection on
> the containing TABLE (or TBODY, or whatever).

Yes, it's good to see at least some kind of consistency in this regard.
Not that it makes relying on scope augmentation a viable solution of course.

There's now a separate section on scope augmentation in "Unsafe Names"
article <URL http://jibbering.com/faq/names/event_handler.html >. It
features a test and results based on your original experiment. It also
mentions deviations observed in older browsers.

Is there anything you would add/change in that section?

>
> <snip>
>> Blackberry 4.7 (9500 model)
>> MSIEMobile 6.0 (WinCE)
> <snip>
>
> Do you know which browser the Blackberry is using? Is it a re-barged
> NetFront? Back in 2003 NetFront was one of the browsers that did not
> augment the scope chain at all. I noticed that NetFront was still
> shipping on new Nokia phones last year so it would be nice to know where
> they are at now.

AFAK, latest (if not all) Blackberry are based on WebKit. The DOM
implementation in older models leave much to be desired. For example, in
version 4.2 (8100 "Pearl" model) `document.body` and
`document.documentElement` are `null`. `Array.prototype.indexOf` is
missing; so do Element::appendChild, Element::insertBefore and most of
other Element interface. It nevertheless supports `__proto__` extension : )


Newer models (e.g. 9000 "Bold" model), based on v. 4.7 already have a
pretty decent DOM2 support (also implement XMLHttpRequest and Style
module). I haven't done thorough testing, though - only a very
superficial look, mostly based on object presence, rather than object
behavior (so it's not clear how many bugs are hidden under the cover)

--
kangax

David Mark

unread,
Feb 10, 2009, 8:40:36 PM2/10/09
to
On Feb 10, 7:37 pm, kangax <kan...@gmail.com> wrote:
> Richard Cornford wrote:
> > kangax wrote:
> >> kangax wrote:
> > <snip>
> >>> .... I also want to run that test case on the newer browsers
> >>> whenever I get a chance (as from the quick look at the results
> >>> in FF 3.0.5, it seems like element ancestors other than document
> >>> and form - i.e. `div`, `table`, `thead`, `tr`, `th` (from the
> >>> "first link onclick") - are no longer included in  the chain)
>
> > It is a little inevitable that browsers, and especially the 'popular'
> > browsers that the average web developer has heard of, should migrate
> > towards consistent behaviour as people report their inconsistencies a
> > bugs. When we did those experiments back in 2003 we were testing Opera
> > 7.11, and it was not adding the document to the scope chain. As I recall
> > Opera had changed so that it was adding the document by version 7.2.
>
> > And the more elaborate scope chain augmentation has caused 'works in IE
> > but not Mozilla' questions on this group where people were attempting to
> > access things like global variables named - rows - from an event handler
> > on an element in a table and unexpectedly picking up the collection on
> > the containing TABLE (or TBODY, or whatever).
>
> Yes, it's good to see at least some kind of consistency in this regard.
> Not that it makes relying on scope augmentation a viable solution of course.
>
> There's now a separate section on scope augmentation in "Unsafe Names"
> article <URLhttp://jibbering.com/faq/names/event_handler.html>. It

> features a test and results based on your original experiment. It also
> mentions deviations observed in older browsers.
>
> Is there anything you would add/change in that section?
>
>
>
> > <snip>
> >> Blackberry 4.7 (9500 model)
> >> MSIEMobile 6.0 (WinCE)
> > <snip>
>
> > Do you know which browser the Blackberry is using? Is it a re-barged
> > NetFront? Back in 2003 NetFront was one of the browsers that did not
> > augment the scope chain at all. I noticed that NetFront was still
> > shipping on new Nokia phones last year so it would be nice to know where
> > they are at now.
>
> AFAK, latest (if not all) Blackberry are based on WebKit. The DOM
> implementation in older models leave much to be desired. For example, in
> version 4.2 (8100 "Pearl" model) `document.body` and
> `document.documentElement` are `null`.

That's why we detect features. The average browser script should bail
out immediately when confronted with such a DOM implementation.

> `Array.prototype.indexOf` is
> missing; so do Element::appendChild, Element::insertBefore and most of
> other Element interface. It nevertheless supports `__proto__` extension : )

I've never used the first or last of those in my life. But, as with
document.body, appendChild and the like must be detected. If they
aren't there, don't create functions that require them.

>
> Newer models (e.g. 9000 "Bold" model), based on v. 4.7 already have a
> pretty decent DOM2 support (also implement XMLHttpRequest and Style
> module). I haven't done thorough testing, though - only a very
> superficial look, mostly based on object presence, rather than object
> behavior (so it's not clear how many bugs are hidden under the cover)

Yes, the next step is feature testing. Of course, your functions
should have that built in at this point, so all you have to do is test
the presence (or lack thereof) of your API's methods to determine
whether specific features of your application (or the app in its
entirety) will fly or not.

kangax

unread,
Feb 10, 2009, 10:56:46 PM2/10/09
to
David Mark wrote:
> On Feb 10, 7:37 pm, kangax <kan...@gmail.com> wrote:
[...]

>> AFAK, latest (if not all) Blackberry are based on WebKit. The DOM
>> implementation in older models leave much to be desired. For example, in
>> version 4.2 (8100 "Pearl" model) `document.body` and
>> `document.documentElement` are `null`.
>
> That's why we detect features. The average browser script should bail
> out immediately when confronted with such a DOM implementation.

Do you think it would make sense to try to fall back on some other means
of accessing those elements (e.g. body), and if so, what are these other
means?

>
>> `Array.prototype.indexOf` is
>> missing; so do Element::appendChild, Element::insertBefore and most of
>> other Element interface. It nevertheless supports `__proto__` extension : )
>
> I've never used the first or last of those in my life. But, as with
> document.body, appendChild and the like must be detected. If they
> aren't there, don't create functions that require them.

"First or last" are `indexOf` and `__proto__`?

>
>> Newer models (e.g. 9000 "Bold" model), based on v. 4.7 already have a
>> pretty decent DOM2 support (also implement XMLHttpRequest and Style
>> module). I haven't done thorough testing, though - only a very
>> superficial look, mostly based on object presence, rather than object
>> behavior (so it's not clear how many bugs are hidden under the cover)
>
> Yes, the next step is feature testing. Of course, your functions
> should have that built in at this point, so all you have to do is test
> the presence (or lack thereof) of your API's methods to determine
> whether specific features of your application (or the app in its
> entirety) will fly or not.

Yes, I've seen this in both - your library and Peter's one.

--
kangax

0 new messages