-3

Before you jump onto the duplicate question, I must say I have looked through stackoverflow and other places before I came here.

So basically, I'm using a sprite image and need to loop through the image inside it. In the code block below you'll find the way I have approached it right now. However, after adding the setTimeout function it seems like everything inside the function parameter is no longer executed.

var headerTimeout = 1000/24;

jQuery('.headerGif').hover(function(){
    for(var i = 1; i <= 41; i++){
        setTimeout(function(){
            if (jQuery(this).hasClass('.header-HeaderBedrijfsVideo00' + (i - 1))) {
                jQuery(this).removeClass('.header-HeaderBedrijfsVideo00' + (i - 1));
            }

            jQuery(this).addClass('.header-HeaderBedrijfsVideo00' + i);
        }, headerTimeout);
    }
});

If there is a better way to approach this, I would appreciate it if someone could point me into the right direction. I am already looking into just using a plugin for this purpose.

EDIT: I have tried checking the question that is in the duplicate marking, but that's basically what a closure does is it not? I just added the closure from one of the answers and it still does not work.

Rizky Fakkel
  • 8,703
  • 1
  • 14
  • 20
  • Check what `this` refers to inside the timeout function. – Mackan Jul 06 '15 at 12:35
  • In addition to what has been said regarding the passing of `this` and `i` to the function, http://stackoverflow.com/a/5226333/3984553 – JBux Jul 06 '15 at 12:38

2 Answers2

1

Use closure , for loop would be executed before time out function then you can get last incremented i value 41 ,so in this context you have to use closure like multiple thread

    jQuery('.headerGif').hover(function () {
   var _this=this;
        for (var i = 1; i <= 41; i++) {
            (function (i) {
                setTimeout(function () {
                    if (jQuery(_this).hasClass('.header-HeaderBedrijfsVideo00' + (i - 1))) {
                        jQuery(_this).removeClass('.header-HeaderBedrijfsVideo00' + (i - 1));
                    }

                    jQuery(_this).addClass('.header-HeaderBedrijfsVideo00' + i);
                }, i*100);
            })(i);
        }
    });
Balachandran
  • 9,567
  • 1
  • 16
  • 26
  • I have added the closure, but it still does not execute. I made a [fiddle](http://jsfiddle.net/460hs74u/) for convenience and I'm checking my Chrome developer console to see if anything happens when I hover over the box. – Rizky Fakkel Jul 06 '15 at 12:46
  • In this fiddle there is no sprite image and **header-HeaderBedrijfsVideo00class** is not defined in this fiddle – Balachandran Jul 06 '15 at 12:52
  • That does not really matter when I'm only trying to see if the class is actually added to the html block. I can see that by checking my developer console in chrome or Firebug in Firefox. I could even add a `console.log()` there. – Rizky Fakkel Jul 06 '15 at 12:56
  • 2
    @RizkyFakkel It works now that Balachandran added a higher reference to `this`, as I mentioned in comments to your question. – Mackan Jul 06 '15 at 12:57
  • Yup, it works. Now I'm having a weird issue where my CSS isn't being picked up, but that'll be my own worry. Thanks @Balachandran and @Mackan! – Rizky Fakkel Jul 06 '15 at 13:15
0

Reason

  1. setTimeout function will be called only after i becomes 41(whatever is the end of the for loop)!!

Check out the below fiddle (check the console)

http://jsfiddle.net/szx19hzo/2/

  1. Do not use . inside the hasClass function

You can remove timeout to make it work, check the below link(check console and inspect element to note that class is removed)

http://jsfiddle.net/szx19hzo/3/

Solution

If you want to retain the timeout, then use a different function and call it inside the loop and have the timeout given inside the function Use the below solution if you want to retain the timeout

http://jsfiddle.net/szx19hzo/4/

var headerTimeout = 1000/24;

jQuery('.headerGif').hover(function(){
    for(var i = 1; i <= 41; i++){
        var className='header-HeaderBedrijfsVideo00' + (i - 1);
           removeClass(this,className,i);
    }
});

function removeClass(item,className,i){
 setTimeout(function(){

            console.log(className);
            if (jQuery(item).hasClass(className)) {
                jQuery(item).removeClass('header-HeaderBedrijfsVideo00' + (i - 1));
                console.log("removed");
            }

            jQuery(item).addClass('.header-HeaderBedrijfsVideo00' + i);

        }, headerTimeout);
};
Vignesh Subramanian
  • 7,161
  • 14
  • 87
  • 150
  • It is - both closure and a reference to `this` is required (_this_ will reference _window_ or similar once inside the timeout), but you left those things out in your example. – Mackan Jul 06 '15 at 12:56
  • "*setTimeout function will be called only after i becomes 42!!*" No, it will loop 41 times (`i<=41`), but setTimeout will be called with the same value each time. Hence the need for a closure. This answer is just confusing the OP. "Remove the setTimeout" is **not** a solution. – Mackan Jul 06 '15 at 13:06
  • @RizkyFakkel added solution. Check the updated answer – Vignesh Subramanian Jul 06 '15 at 13:13