Disable TR onclick event

D

dan_williams

I have the following test web page:-

<html>
<head><title>Test</title>
<script language="Javascript">
<!--
function fnTR() {
alert("TR");
}

function fnSelect() {
alert("Select");
}
-->
</script>
</head>
<body>
<table width="300" height="50" border="1">
<tr onclick="javascript:fnTR();">
<td align="center">
<select onclick="javascript:fnSelect();">
<option>option 1</option>
<option>option 2</option>
</select>
</td>
</tr>
</table>
</body>
</html>

When clicking on my select dropdownlist, does anyone know how i can get
my page to only execute the fnSelect function, and not the fnTR
function aswell?

In my real page, my functions perform other operations (i.e. fnTR
highlights the selected row), but i've just put in alerts to
demonstrate.

Is it possible to do this without having to put onClick events in all
my TD elements instead?
Is there some sort of void function or return false; i could do? Or is
it possible to add some functionality to my fnTR function that would
check if I clicked on the dropdown box, and if so, not to perform the
rest of the function?

Thanks in advance for any suggestions

Dan.
 
P

petermichaux

When clicking on my select dropdownlist, does anyone know how i can get
my page to only execute the fnSelect function, and not the fnTR
function aswell?

In my real page, my functions perform other operations (i.e. fnTR
highlights the selected row), but i've just put in alerts to
demonstrate.

Is it possible to do this without having to put onClick events in all
my TD elements instead?
Is there some sort of void function or return false; i could do? Or is
it possible to add some functionality to my fnTR function that would
check if I clicked on the dropdown box, and if so, not to perform the
rest of the function?

Thanks in advance for any suggestions

Hi Dan,

It would be nice if there is some thing clean like a return false that
would stop the tr handler from firing. I don't know if there is.
Following from your last idea I just tested the following file

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Test</title>

<script type='text/javascript'>

var flag = false;

function fnTR() {
if (flag) {
flag = false;
} else {
alert("TR");
}
}

function fnSelect() {
flag = true;
alert("Select");
}

</script>

</head>
<body>

<table width="300" height="50" border="1">
<tr onclick="fnTR();">
<td align="center">
<select onclick="fnSelect();">
<option>option 1</option>
<option>option 2</option>
</select>
</td>
</tr>
</table>

</body>
</html>

(Note no use of the deprecated language attribute or the <!-- -->
hiding trick. I don't use "javascript:" and never have. Also I added a
doctype.)

I'm sure there are many ways to do this but if your situation is
relatively simple this might be ok.

Peter
 
R

RobG

When clicking on my select dropdownlist, does anyone know how i can get
my page to only execute the fnSelect function, and not the fnTR
function aswell?
[...]

It would be nice if there is some thing clean like a return false that
would stop the tr handler from firing. I don't know if there is.

Yes, there is - you cancel event propagation to stop it bubbling up to
objects higher in the DOM tree. Unfortunately IE and the W3C
implemented different event models so it's a bit messy, but not to
tough.

If event handlers are coded in the HTML, pass 'event' to the function:

<select onclick="fnSelect(event);">


Now W3C browsers will have a reference to the event that called the
function. IE makes it a property of the window object, so in the
function declaration do:

function fnSelect( e )
{
if ( !e ) {
var e = window.event;
}
// can also do: var e = e || window.event;

/* rest of function... */

}


Now 'e' is a reference to the event that called the function in both
event models. To cancel bubbling, IE uses:

window.event.cancelBubble = true;

W3C browsers use:

e.stopPropagation()

so now the function looks like:

function fnSelect(e){
var e = e || window.event;
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();

/* rest of function... */

}

That will cancel bubbling for the function regardless of which element
calls it, if you want it to bubble for other elements you may need to
create a non-bubbling caller for elements whose events you don't want
to bubble.

Read more about events and event order at quirksmode:

<URL:http://www.quirksmode.org/js/events_order.html>

If adding event handlers from a function rather than in the HTML,
things are a little different. A reference to the event is passed as
the first argument to the function in the W3C model but not in IEs, so
the function looks the same but the attachment process looks a little
different. ie. to attach the function stick with:

someEl.onclick = fnSelect;

You don't have to do:

someEl.onclick = function (){fnSelect(event);}

or similar kludge. In the W3C model you can also specify whether the
function fires in bubbling or capturing phases using addEventListener -
it's all covered at quirksmode.

[...]
 
R

Richard Cornford

RobG wrote:
<select onclick="fnSelect(event);">


Now W3C browsers will have a reference to the event that
called the function. IE makes it a property of the window
object,

All browsers will pass a reference to the event object to the -
fnSelect - function as an argument. This is due to the way in which the
Identifier - event - is resolved in the context of the internally
generated event handling function created by the browser from the value
of the intrinsic event attribute. In W3C standard browsers that function
has a formal parameter with the name 'event', so the Identifier resolves
as the value of that parameter, the event object. The equivalent
function generated by IE does not have a formal parameter so the
Identifier - event - is not found at the top of the scope chain, instead
IE goes on up- the scope chain until it gets to the global object where
it finds (and resolves as) the global - event - property.
so in the function declaration do:

function fnSelect( e )
{
if ( !e ) {
var e = window.event;
}
<snip>

This is used in functions programmatically assigned as an event handler
but not in functions called from an internally generated event handler
where - event - is passed as an argument to that function. (It is, of
course, harmless here as - e - will be false so - window.event - will
never be evaluated.)

Richard.
 
R

Richard Cornford

It would be nice if there is some thing clean like a
return false that would stop the tr handler from firing.
I don't know if there is.
<snip>

Understanding how events work in web browsers is fairly fundamental to
programming a browser as a GUI. It is difficult to see how anyone
learning to script web browsers could avoid learning this aspect of the
task within a few months of starting to make the effort (with the
exceptions of being VK or placing an unreasonable reliance on the
internal details of a library/framework, the internals of which they did
not understand).

I hope you will remember the outcome of this thread next time you are
considering directing people to particular sources of information, or
recommending particular libraries/frameworks. If you really were
qualified to judge you would not be expected to be deficient in the
fundamentals of browser scripting.

Richard.
 
P

petermichaux

Richard said:
<snip>

Understanding how events work in web browsers is fairly fundamental to
programming a browser as a GUI. It is difficult to see how anyone
learning to script web browsers could avoid learning this aspect of the
task within a few months of starting to make the effort (with the
exceptions of being VK or placing an unreasonable reliance on the
internal details of a library/framework, the internals of which they did
not understand).

I hope you will remember the outcome of this thread next time you are
considering directing people to particular sources of information, or
recommending particular libraries/frameworks. If you really were
qualified to judge you would not be expected to be deficient in the
fundamentals of browser scripting.

Hi Richard,

I only use DOM Level 2 event handling and have never looked at how
stopping event propogation works with the attribute event handlers. I
said it would be nice if there was a way and there is. That's nice. I
learned something by joining in the discussion. I'm pleased to be using
DOM level 2 event handling daily and using it well.

People here have been very unfriendly to those asking about
Prototype.js. They may not have a choice in using it or not. Recently
I've never said much more than "you might have better luck asking on
the rails spinoffs list".

Peter
 
P

petermichaux

Hi Dan,

It would be nice if there is some thing clean like a return false that
would stop the tr handler from firing. I don't know if there is.
Following from your last idea I just tested the following file

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Test</title>

<script type='text/javascript'>

var flag = false;

function fnTR() {
if (flag) {
flag = false;
} else {
alert("TR");
}
}

function fnSelect() {
flag = true;
alert("Select");
}

</script>

</head>
<body>

<table width="300" height="50" border="1">
<tr onclick="fnTR();">
<td align="center">
<select onclick="fnSelect();">
<option>option 1</option>
<option>option 2</option>
</select>
</td>
</tr>
</table>

</body>
</html>

(Note no use of the deprecated language attribute or the <!-- -->
hiding trick. I don't use "javascript:" and never have. Also I added a
doctype.)

I'm sure there are many ways to do this but if your situation is
relatively simple this might be ok.

I should point out that there is one bonus of using a flag to stop the
tr onclick event handler from firing. If you have other listeners
higher up the DOM than tr that you also want to have fire when either
tr or td are clicked, then the flag will just bypass one level in the
bubble up when td is clicked. If you stop the event altogether you
can't do this, as far as I know.

Peter
 
R

Richard Cornford

Hi Richard,

I only use DOM Level 2 event handling

That would be your choice if you can get away with it, but commercial
script authors cannot afford to disregard the IE event handling
mechanisms.
and have never looked at how stopping event propogation
works with the attribute event handlers.

Which just happens to be identical to the DOM events method on DOM
standard browsers.
I said it would be nice if there was a way and there is.
That's nice. I learned something by joining in the discussion.

You learnt something by joining the discussion _here_.
I'm pleased to be
using DOM level 2 event handling daily and using it well.

But at some point you may find an advantage in becoming qualified to do
commercial browser script development, for which you must learn how IE
does it.
People here have been very unfriendly to those asking about
Prototype.js.

Some people have. I have been attempting to get them to present their
questions in a form that can be answered (i.e. in the form recommended
in the expansion on the FAQ provided in the linked notes). To date
nobody has managed to do that, but if anyone ever does we may manage to
get past the generalities of Prototype.js and down to the actual code.
They may not have a choice in using it or not.

Maybe, but even if they had to use it that doesn't mean they have to use
it badly, and my impression of the Prototype.js questions that have been
answered here is that the answered presented have all been seriously
sub-optimal. But that will remain just an impression while the questions
asked are insufficient to receive a fully informed answer.
Recently I've never said much more than "you might have better
luck asking on the rails spinoffs list".

Yes, you are proposing they ask browser scripting questions in the place
where you have been falling to learn the basics of browser event
handling. Greater benefit would follow for all if you encouraged people
to ask their questions in a form that they could/would be answered here.

Richard.
 
R

Richard Cornford

I should point out that there is one bonus of using a flag
to stop the tr onclick event handler from firing. If you have
other listeners higher up the DOM than tr that you also want to
have fire when either tr or td are clicked, then the flag will
just bypass one level in the bubble up when td is clicked. If
you stop the event altogether you can't do this, as far as I
know.

If you stop an event propagating then you stop it propagating, but that
does no necessitate the use of a global variable. The handler on the TR
could make an informed decision not to act when it received the event,
letting it carry on bubbling if necessary. It could, for example,
observe the that target of the event was either a TD, or contained
within an TD, that had a function assigned to the pertinent event
handler property, and so elect not to act.

Richard.
 
P

petermichaux

Richard said:
If you stop an event propagating then you stop it propagating, but that
does no necessitate the use of a global variable. The handler on the TR
could make an informed decision not to act when it received the event,
letting it carry on bubbling if necessary. It could, for example,
observe the that target of the event was either a TD, or contained
within an TD, that had a function assigned to the pertinent event
handler property, and so elect not to act.

I'm working with a situation like this right now and can't find a clean
way to make the type of decision you are suggesting. I have nested divs
of various depth, some of which are listeners. It isn't as simple as
looking to see if the target was within a TD. I suppose I could use a
classname "listener" on each listening div. Then check if the event
already bubbled through another "listener" before reaching the one
currently handling the event. I don't really like the idea of using a
classname for this. Seems like clutter.

Is there a cross browser way to tag a particular event object as
handled? It would be very clean if the event itself could carry
information about which handlers have already seen the event.

Thanks,
Peter
 
P

petermichaux

I'm working with a situation like this right now and can't find a clean
way to make the type of decision you are suggesting. I have nested divs
of various depth, some of which are listeners. It isn't as simple as
looking to see if the target was within a TD. I suppose I could use a
classname "listener" on each listening div. Then check if the event
already bubbled through another "listener" before reaching the one
currently handling the event. I don't really like the idea of using a
classname for this. Seems like clutter.

Is there a cross browser way to tag a particular event object as
handled? It would be very clean if the event itself could carry
information about which handlers have already seen the event.

I found a completely different approach to my problem. I'm curious
about tagging a property onto the event object but I think this object
is read only in Internet Explorer at least. Seems possible to add
properties to the event object in Firefox.

Thanks,
Peter
 
R

Richard Cornford

(e-mail address removed) wrote:
... . I'm curious about tagging a property onto the event
object but I think this object is read only in Internet
Explorer at least. ...
<snip>

In IE the events are not read-only. You can assign properties to an
event object and successfully read them back. The problem is that every
time you read the value of the global - event - property you get a
reference to a unique event object, so assigning values to priorities of
event objects cannot be used to pass values between event handlers on
IE, as each must read the global event property to get an event object,
and so each gets a different event object.

Still, if you must pass information in an event related way it would be
possible to add the properties to another object that is common to all
the event objects IE will create, such as the - srcElement - object.
Though if sets of event handlers need some private channels of
communication it would probably make more sense to implement that in the
script and avoid any reliance upon the ability to add properties to host
objects.

Richard.
 
P

petermichaux

Richard said:
In IE the events are not read-only. You can assign properties to an
event object and successfully read them back. The problem is that every
time you read the value of the global - event - property you get a
reference to a unique event object, so assigning values to priorities of
event objects cannot be used to pass values between event handlers on
IE, as each must read the global event property to get an event object,
and so each gets a different event object.

Ahh. Ok. Thanks.
Still, if you must pass information in an event related way it would be
possible to add the properties to another object that is common to all
the event objects IE will create, such as the - srcElement - object.
Though if sets of event handlers need some private channels of
communication it would probably make more sense to implement that in the
script and avoid any reliance upon the ability to add properties to host
objects.

I found a nice way to avoid adding properties to the event object.
Probably nicer than even if I could. Each event handler has a chance to
claim "first responder" status along the bubble up. When the event
reaches the "document" listener the first responder is called to
actually handle the event.

Thanks again for the information.

Peter
 

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,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top