views:

33

answers:

2

So I have an issue, when I load a document, I have a class called .active which changes depending on what list item you are viewing using keyboard navigation. The problem is when that list item has the class active assigned to it, I would like that list item only, on hover, to display another piece of content.. But the problem is, I believe, that my hover function is only firing on page load, and only attaching to whatever list item has .active assigned to it on load..

<ul>
<li class="active">Foo <a class="more-info" href="#">Click Me</a></li>
<li>Bar <a class="more-info" href="#">Click Me</a></li>
<li>Pie <a class="more-info" href="#">Click Me</a></li>
</ul>

When a user uses their keyboard navigation the previous list item will not longer have .active and the next one will be assigned the class as follows:

<ul>
<li>Foo <a class="more-info" href="#">Click Me</a></li>
<li class="active">Bar <a class="more-info" href="#">Click Me</a></li>
<li>Pie <a class="more-info" href="#">Click Me</a></li>
</ul>

What I would like to happen is that when a user hovers the new list item, they are presented with the a.more-info but it does not work. I believe again, this is because the .hover(); only runs once on page load and is not listening the whole time..

 $("li.active").hover(
    function () {
        $('li.active a.more-info').fadeIn();
    },
    function () {
        $('li.active a.more-info').fadeOut();
    });

Any ideas?

A: 
$("li.active").live({
   mouseenter: function()  {
        $('li.active a.more-info').fadeIn();
   },
   mouseleave: function() {
        $('li.active a.more-info').fadeOut();
   }
});

http://api.jquery.com/live/

jQuery's live is designed to handle your exact situation.

Mark
I knew it had to be the .live function, just didn't know how to execute. Thank you.
Bruno
+1  A: 

(...) and only attaching to whatever list item has .active assigned to it on load

You are right, the handler is only attached to those li elements, that have a class active. But you can check which class they have at runtime:

 $("li").hover( // attach the handler all li elements
    function () {
        if($(this).hasClass('active'))  // check for 'active' class
            $('a.more-info', this).fadeIn();
    },
    function () {
        if($(this).hasClass('active'))
            $('a.more-info', this).fadeOut();
 });

Assuming that all list elements are present when you load the page. Otherwise you have to combine it with live(). Note, you don't need live() if you don't load the lists via Ajax.

I believe again, this is because the .hover(); only runs once on page load and is not listening the whole time..

That is not correct. The handler is only attached on page load (so yes your function call is only executed once). But the event is fired always when the mouse cursor is over an <li> element. Then the handler is called.

Felix Kling
Felix - I'm sure the OP meant that the `.hover()` call with the function parameters only runs once at page load, which is correct.
patrick dw
@patrick: I interpret *and is not listening the whole time* differently, but maybe it is just me...
Felix Kling
While it's true you don't _need_ live... isn't event delegation worthwhile anyway?
Mark
Felix - Good point. That does make it sound different. I've got to say though that AJAX is not the only reason to use live/delegate (especially delegate). But don't mind me. I'm just a sore loser. ;o)
patrick dw
@Mark - I agree. Especially with `delegate()` where it is more localized, it can be a very efficient way to go.
patrick dw
@Mark: Well, with `live`, the event handler is attached to the window (or document? not sure) and catches the events that bubble up. So imho it is better to attach the handler directly to the element if possible. And although `delegate()` can come pretty handy, event delegation is not always the best choice and adds some performance overhead.
Felix Kling