views:

35

answers:

1

Pretty new to jquery and having a bit of a problem with a function I wrote, very similar to this problem, and if that's anything to go on then apparently I have a closure problem. As Peter Bailey put it in the above thread, this is what's happening:

  1. Iterate over some values
  2. Define/assign a function in that iteration that uses iterated variables
  3. You learn that every function uses only values from the last iteration.
  4. WTF?

This is my code:

var pages=['home', 'about', 'events', 'info', 'qa', 'photos', 'contact'];

for (i in pages) {

    $link='"'+"[href$='gaction.php?page="+(pages[i])+"']"+'"';
    $source="/images/"+(pages[i])+".png";

    $($link).hoverIntent(function() {
        $('#logo_text').stop(true, true).fadeOut(
        0,
        function() {
            $('#logo_text').attr('src', $source).fadeIn('slow'); // swaps logo
        });
    }, function() {
        $('#logo_text').stop(true, true).pause(300).fadeOut(
        0,
        function () {
            $('#logo_text').attr('src', '/images/name.png').fadeIn('slow'); //swaps back
        });
    });
}

I know the $link definition is pretty messy, but that bit works.

The function's meant to replace the picture in #logo_text with one depending on the link that's hovered over, but by the end of it every link changes the picture to the 'contact' (last) one.

Didn't really understand how to fix it from the other thread so if someone can help out that would be great!

+2  A: 

You can just use the jQuery.each statement, and by its very structure creates a closure. Then, be sure to declare the variables with var and you will be all set:

var pages=['home', 'about', 'events', 'info', 'qa', 'photos', 'contact'];

$.each( pages, function(){
  var $link='"'+"[href$='gaction.php?page="+ this +"']"+'"';
  var $source="/images/"+ this +".png";

  ... rest of function untouched

});

There are a few ways to rewrite the function, but in all honesty, if yours works for you (the selectors) then you are good. Only, instead of using fadeOut(0, function ...) just use hide().attr('src', $source ).fadeIn('slow')

Doug Neiner
You sure about that? Don't you have the problem that the inner functions aren't actually created until the hoverIntent callback gets run?
Bruce
I'm positive :)
Doug Neiner
However, I did still have `pages(i)` instead of `this` so thanks for causing me to reread my function :)
Doug Neiner
Works great, thanks!
Mike