Welcome to WebmasterWorld Guest from 54.166.227.36

Forum Moderators: open

Message Too Old, No Replies

Bubbling

I'm going round in circles

     
9:52 am on Oct 2, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



So originally my code looked something like this:

<ul>
<li>1</li>
<li>2</li>
<li>3
<ul>
<li>3.1</li>
<li>3.2</li>
<li>3.3</li>
</ul>
</li>
</ul>

li { background: #fff; }
li:hover { background: #ccc; }

This works fine, up until you hover over the sublist. You then get a grey background on both the <li> you're hovering over and the parent <li>. What I want is just the <li> at the 'front' to be highlighted.

I've tried to rework this in JS but I'm really not having much luck. I think I need the standards-equivalent of IE's onmouseenter and onmouseleave. I suppose I could do something with cancelling the event bubbling to fix this but it's at this point that my understanding gets a little hazy.

Help?

2:03 pm on Oct 2, 2007 (gmt 0)

5+ Year Member



couple options, first you could get fancy with JS and set the parent LI backgroundColor, or you could terminate the third LI before you declare the nested UL (but not proper), but what I would do is put the content of the LI in A tags and put the :hover on the A tag. Then set the A tag to a block element.

li { background: #fff; }
li a:hover { background: #ccc; display:block; }

<ul>
<li><a href="">1</a></li>
<li><a href="">2</a></li>
<li><a href="">3</a>
<ul>
<li><a href="">3.1</a></li>
<li><a href="">3.2</a></li>
<li><a href="">3.3</a></li>
</ul>
</li>
</ul>

2:06 pm on Oct 2, 2007 (gmt 0)

5+ Year Member



btw, it had nothing to do with event bubbling, it just the nested UL is still contained by the parent LI and anything you :hover over in the nested list still triggerst the hover event, as content of the element not bubbling to the parent.
2:30 pm on Oct 2, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



For your first option - yes, I tried that. The problem is that when you mouseout of a child you're not effectively triggering a mouseover of the parent - you were always in the parent - so it won't regain it's initial colour. Maybe I should trigger a re-evaluation on both mouseover and mouseout?

For you second option, being invalid isn't really an option for this project. The <a> trick would be useful, but actually the HTML inside each list item is a little more complex - too complex to nest everything inside an inline <a> (again, this would make it invalid).

The reason why I suggested it was a bubbling issue wasn't the CSS but more the JS equivalent I'd built. This behaves in the same way as :hover in that the mouseover event bubbles up through the <li>s and sets the background colour on each.

2:31 pm on Oct 2, 2007 (gmt 0)

WebmasterWorld Senior Member fotiman is a WebmasterWorld Top Contributor of All Time 5+ Year Member Top Contributors Of The Month



I agree with Drag_Racer that you shouldn't apply the styles to the li item, but instead you should apply it to some inner element (like an <a>). However, if you really need a JavaScript solution, then I've thrown together a quick example for you. Note, the outer list item can still get the hover, but once you hover over the inner list, the event is stopped from getting to the parent.


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset:utf-8">
<title></title>
<style type="text/css">
.hovered {
background: #eee;
}
</style>
</head>
<body>
<ul id="myList">
<li>1</li>
<li>2</li>
<li>3
<ul>
<li>3.1</li>
<li>3.2</li>
<li>3.3</li>
</ul>
</li>
</ul>
<script type="text/javascript" src="http://yui.yahooapis.com/2.3.1/build/yahoo-dom-event/yahoo-dom-event.js"></script>
<script type="text/javascript">
YAHOO.util.Event.on(window, 'load', function() {
// Attach mouseover and mouseout event listeners
var myList = document.getElementById('myList');
var liList = myList.getElementsByTagName('li');
YAHOO.util.Event.on(liList, 'mouseover', function(e) {
YAHOO.util.Event.stopEvent(e);
YAHOO.util.Dom.addClass(this, 'hovered');
});
YAHOO.util.Event.on(liList, 'mouseout', function(e) {
YAHOO.util.Dom.removeClass(this, 'hovered');
});
});
</script>
</body>
</html>
2:37 pm on Oct 2, 2007 (gmt 0)

WebmasterWorld Senior Member fotiman is a WebmasterWorld Top Contributor of All Time 5+ Year Member Top Contributors Of The Month



Note, my example makes use of the Yahoo UI Library [developer.yahoo.com] because its Event and DOM Utilities work across browsers and greatly simplify things. If you didn't want to use the YUI, you would just need to re-write it to create your own window.onload event handler (that's when you'll want to attach your mouseover and mouseout event handlers because the DOM will be ready), and you'd need to attach your mouseover and mouseout event handlers, and use the DOM methods to stop the Event from 'bubbling' up.

Hope that helps.

 

Featured Threads

Hot Threads This Week

Hot Threads This Month