0

I am pretty new to Javascript and have noticed this odd issue come up.

    var dispatchMouseEvent = function(target, var_args) {
        var e = document.createEvent("MouseEvents");
        e.initEvent.apply(e, Array.prototype.slice.call(arguments, 1));
        target.dispatchEvent(e);
    };

    var Level1Cats = document.getElementsByClassName("p-pstctgry-lnk-ctgry "); //GETTING LEVEL 1 CATS

    var Level1CatsLen = Level1Cats.length; //GETTING LEVEL 1 CAT LEN

    for (i = 0; i <= Level1CatsLen-1; i++) {

        var ID1 = Level1Cats[i].id;
        var temp1 = Level1Cats[i].innerHTML;
        temp1.replace(/&amp;/gi, "&").replace(/<[^>]*>/gi, "");

        function GoToLevel2(callback) { //GO TO NEXT LEVEL!
        dispatchMouseEvent(Level1Cats[i], "mouseover", true, true);
        dispatchMouseEvent(Level1Cats[i], "click", true, true);
        }

        function GetLevel2() { //GET NEXT LEVEL
        var Level2Cats = document.getElementsByClassName("p-pstctgry-lnk-ctgry");
        return Level2Cats.length;
        }

        setTimeout(function() { //RUN IT WITH TIMING
            GoToLevel2();
        }, 100);
        var Level2CatsLen = GetLevel2();
}

When the code is executed it gives me an error (Cannot read property 'dispatchEvent' of undefined) I know this is because the i in the function does not seem to work. If I simply replace it with an int value of 1 it will execute and click cat 1, 16 times, as expected..

I would have thought this should work, any ideas how I can work around it?

Matt Biggs
  • 179
  • 1
  • 4
  • 15

1 Answers1

0

Inside the loop, a closure GoToLevel2 is created, closing over the variable i, when i is 1. Then the loop runs through, i is incremented to 2, and the loop is terminated.

Then your setTimeout fires after 100ms, and invokes your closure. It still remembers that there was once a variable i, but it now contains 2. Level1Cats[2] is undefined, and you get an error.

The standard solution is to enclose the contents of the loop into another self-evaluating function that will not close over i:

for (i = 0; i <= Level1CatsLen-1; i++) {
    (function(i) {
         // ...
    })(i);
}

(Note also that setTimeout(function() { GoToLevel2(); }, 200) is identical to, but less efficient than setTimeout(GoToLevel2, 200).)

Amadan
  • 191,408
  • 23
  • 240
  • 301