How to stop <li> onclick bubble-up...?

J

Joakim Braun

I'd like to show tree structures using collapsible multi-level nested <ul>
lists (with open/closed "disclosure triangles" as list-style-images).
Something like this:

<ul>
<li onclick="alert('Level 1 clicked');">Level 1
<ul>
<li onclick="alert('Level 2 clicked');">Level 2
</li>
</ul>
</li>
</ul>

Clicking on the text following <li> (or on the list-style-image)
collapses/expands the rest of the content of that <li> (not shown here).

The problem is that each click bubbles up to the topmost list item. That is,
a click on "Level 2" first executes the innermost <li> onclick handler, then
the one for the next-outer-level <li> and so on. How can I make it so that
only the handler for the <li> that's clicked is executed? (returning false
from onclick didn't help in IE 6)

(I know I could wrap the text in <span>s and add the onclick handlers to
those instead, but that's a bit ugly, and the list-style-image would be out
of action)

Joakim Braun
 
M

Michael Winter

On Tue, 7 Dec 2004 20:37:26 +0100, Joakim Braun

[snip]
The problem is that each click bubbles up to the topmost list item.
[...] How can I make it so that only the handler for the <li> that's
clicked is executed?

You should be able to stop propagation with

if(evt.stopPropagation) {evt.stopPropagation();}
evt.cancelBubble = true;

It's not going to work with NN4, though it should with IE4.

An alternative solution that would work in other situations (but not this
one) is to check the origin of the event. If it matched the current
element, you know you act on that event. If it didn't, ignore the event.
It is possible to see if the target is an immediate child, but I such a
solution would be more likely to work in more browsers than the one above
(I could be wrong, though).
(returning false from onclick didn't help in IE 6)

Returning false may cancel the action of that event, but it won't stop it
propagating.

[snip]

Mike
 
J

Joakim Braun

Michael Winter said:
On Tue, 7 Dec 2004 20:37:26 +0100, Joakim Braun

[snip]
The problem is that each click bubbles up to the topmost list item.
[...] How can I make it so that only the handler for the <li> that's
clicked is executed?

You should be able to stop propagation with

if(evt.stopPropagation) {evt.stopPropagation();}
evt.cancelBubble = true;

It's not going to work with NN4, though it should with IE4.
<snip>

Thanks, that was helpful. Now to see what Opera says...

(tried tables before, but the non-nestability of <tbody>s (and consequent
use of subtables with multiple spacer columns for indentation) seemed too
hacky)

Joakim Braun
 
M

Michael Winter

"Michael Winter" <[email protected]> skrev i meddelandet

[snip]
if(evt.stopPropagation) {evt.stopPropagation();}
evt.cancelBubble = true;
[snip]

Thanks, that was helpful. Now to see what Opera says...

Opera supports the DOM Events module, so you'll have no problems there.
Any recent DOM-conforming browser should execute the Event.stopPropagation
method. IE is the reason for the second line.

[snip]

Mike
 
J

Joakim Braun

"Rob B" <[email protected]> skrev i meddelandet
Could always use bubbling to your advantage, by processing click events
at a higher level.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>feh!</title>
<style type="text/css">

there { display: block; }
nowhere { display: none; }

</style>
<script type="text/javascript">
//<![CDATA[

function process(e)
{
e = e || (window.event || {});
var el, tgt = e.srcElement || e.target;
if (tgt && (el = tgt.getElementsByTagName('ul').item(0)))
el.className = 'therenowhere'.replace(el.className, '');
}

onload = function()
{
document.getElementsByTagName('body').item(0).onclick = process;
}

//]]>
</script>
</head>
<body>
<ul>
<li>Level 1
<ul class="nowhere">
<li>Level 2
<ul class="nowhere">
<li>Level 3
</li>
</li>
</ul>
</li>
</ul>
</body>
</html>

How cute - no JS handlers at all in the source code. I'll remember that one.

Joakim Braun
 

Ask a Question

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

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

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,162
Latest member
GertrudeMa
Top