views:

38

answers:

2

Hi Guys,

I have 2 anchor links (a.selector) and when one is clicked it has a class applied to it of 'active-arrow' and the click also removes the class of the same name from the other anchor as well as lowering the opacity to 0.2.

I then want to have a fade effect when the user hovers over the anchor that doesn't have 'active-arrow' applied to it so that it goes to full opacity when mouseenters and back to 0.2 when mouseleaves.

The problem im having is that both .not and :not don't seem to be working as expected, the hover effect works but if I click on the anchor whilst hovering the 'active-arrow' class is applied but when mouseleaves the opacity is faded down to 0.2 again even though the 'active-arrow' class is applied. Also the hover then doesn't work for the other a link which has had 'active-arrow' removed.

Bit of a hard one to explain so heres some code that hopefully helps a bit.

*//If a.selector doesn't have the class 'active-arrow' then run the hoverFade function*
$("a.selector").not(".active-arrow").hoverFade();

//Functions for first element
        $('a.selector-1').click(function () {
            $('a.selector-2').removeClass('active-arrow'); //Remove background image from corresponding element
            $('ul#storage-items-2').fadeOut(1200).addClass('hide'); //Fade out then hide corresponding list
            $(this).addClass('active-arrow', 'fast'); //Add background image to current element
            $('ul#storage-items-1').removeClass('hide').fadeIn(1800); //Unhide and fade in the list
            $('a.selector-2').fadeTo(500, 0.2); //Fade corresponding element
            $(this).fadeTo(800, 1);//Fade this element to full opacity
        });

I only included the code for teh first anchor (a.selector-1) as the code for the second anchor is identical but just changes the class names to a.selector-2.

Also the hoverFade function is in a seperate file so we can re-use it.

    jQuery.fn.hoverFade = function() {
return this.each(function(){
        $(this).hover(
                function () {
                    $(this).fadeTo(500, 0.8);
            }, 
                function () {
                    $(this).fadeTo(500, 0.2);
        });
  });

}

Each anchor link fades in and fades out a UL as well.

Any help is most appreciated

Thanks

Giles

A: 

depending on where you call

$("a.selector").not(".active-arrow").hoverFade();

it will bind the fadeTo effect to all anchors regardless if they own the .active-arrow or not. You should rewrite the hoverFade() function like:

jQuery.fn.hoverFade = function() {
    return this.each(function(){
    if(!$(this).is('.active-arrow'){
       $(this).hover(
               function () {
                   $(this).fadeTo(500, 0.8);
           }, 
               function () {
                   $(this).fadeTo(500, 0.2);
       });
    }
});
}
jAndy
Hi Andy,Thanks for that, I get javascript errors though in Dreamweaver and it doesn't seem to work in firefox. Plus the problem with this is that the hoverFade then cant be used as a plugin if we put the 'active-arrow' class inside it as we would always have to use that class name on every project.ThanksGiles
Giles B
doh, script error should occur because of a missing closing parenthesis. I don't see where else do that check if you really call the .hoverFade() somewhere globally. As I said, this will bind the .hover() to all anchors.
jAndy
Unfortunately that still has the same result mate. The hover works as usual but when I click on the anchor it still fades out on mouseleave even though it now has the 'active-arrow' class and then the hover effect still doesn't work on the other anchor that has had 'active-arrow' removed.ThanksGiles
Giles B
+2  A: 

This is a case where you want to use .live() or .delegate(), like this:

$("a.selector:not(.active-arrow)").live('mouseenter', function () {
  $(this).fadeTo(500, 0.8);
}).live('mouseleave', function () {
  $(this).fadeTo(500, 0.2);
});

If you use .delegate() the top line would look like this (ID = ID of shared parent to all these links):

$("#ID").delegate("a.selector:not(.active-arrow)", 'mouseenter', function () {

The reason what you currently have doesn't work is that it binds the event handler to the elements, the elements only had to match the selector you used when you found them for binding, once that happens, the .hover() mouseenter and mouseleave event handlers are bound on that element. The fact that the class changes later doesn't really matter, the handlers are there to stay.

Using the approach above, the events aren't actually on the elements directly, they sit on a parent, document in the case of .live() or #ID in the case of .delegate(). When the mouse events happen on an element they bubble up, and the parent sees them, checks if the selector that handler is for matches right then, and if so executes. This makes the class changing actually matter, as it's checked when the event happens, rather than when it was bound.

Nick Craver
Excellent thank you Nick!Im quite new to jQuery so didn't know about .live or .delegate, they are very useful. I used .live in the end that worked perfectly for me.Thanks again mate
Giles B
Hmmm sorry, I thought that had fixed it, I think the javascript was running slow in my browser as its still not working.I tried with .delegate and if I use that, when mouseleave's the opacity is applied to the parent element which ID is set.With .live it sort of works, depending on timing. If i hover then click and wait for the other events to run then move my mouse away its fine but if i click and move the mouse off straight away then it fade the a.selector again.Any ideas? Cheers
Giles B
@Giles - I would suggest not animating the `active-arrow` or checking for a different class, because with an animation speed, that class isn't applied (matching the selector like we want) until it's *finshed* animating the class. So either do `$(this).addClass('active-arrow');`, or just add another class for tracking like this `$(this).addClass('aarrow').addClass('active-arrow', 'fast');` and use that in the selector for my answer above, be sure to remove the class the same way, like this: `.removeClass('aarrow active-arrow');` (space between to remove multiple).
Nick Craver
Yep that did the trick, great! We need the 'active-arrow' class animated unfortunately so just using the extra class worked. Thanks again Nick!
Giles B