Cross-Browser Mouse Event Handling

  • Thread starter Martin Rinehart
  • Start date
T

Thomas 'PointedEars' Lahn

Martin said:
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.

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
 
D

Doug Gunnoe

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.

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”?
 
T

Thomas 'PointedEars' Lahn

Thomas said:
Martin said:
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
 
T

Thomas 'PointedEars' Lahn

Doug said:

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
 
E

Erwin Moller

Martin Rinehart schreef:
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.

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:

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

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
 
D

Doug Gunnoe

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…??
 
T

Thomas 'PointedEars' Lahn

Doug said:
Thomas said:
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
 
T

Thomas 'PointedEars' Lahn

kangax said:
Thomas said:
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
 
T

Thomas 'PointedEars' Lahn

kangax said:
Thomas said:
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
 
G

Garrett Smith

kangax said:
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
 
J

JR

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
 
G

Garrett Smith

Thomas said:
<...
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);
}
}
}


Garrett
 
T

Thomas 'PointedEars' Lahn

Garrett said:
kangax said:
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
 
T

Thomas 'PointedEars' Lahn

kangax said:
Thomas said:
kangax said:
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
 
G

Garrett Smith

Thomas said:
Garrett said:
kangax said:
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.


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

<!-- here -->
</body>
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.
 
T

Thomas 'PointedEars' Lahn

JR said:
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


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
 
T

Thomas 'PointedEars' Lahn

Garrett said:
Thomas said:
Garrett said:
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.
Can you show us an example of the unreliability?
Another?


<!-- 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.
^^^^^^^
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.

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
 
R

RobG

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

RobG

Garrett said:
Thomas said:
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 ...?
[...]

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.
 

Ask a Question

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

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

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top