0

WHAT I WANT TO HAPPEN

So what I want to happen is function partA() to click button [z] every 2 seconds. The button that is being clicked should change, because the script is a looping script, so for instance. The first loop, it would click button 1, then button 2, then button 3, because var z = 1 + i++. Is this possible? z is supposed to equal the number 1, plus the loop number. This should loop as long as variable i is less than 50.

WHAT IS HAPPENING

It works properly, looping and all, if I test the script without variable z. However, without variable z, I have to manually change the number that would equal z, which is painstaking, and annoying.

var z = 1 + i++
for(i=0;i<50;i++) {
  setInterval(partA, 2000);
  function partA() {
    buttons = document.getElementsByTagName('button');
    document.getElementsByTagName('button')[z].click();
  }
}

Should i++ be defined another way? The error I'm getting when running the script in console is:

Uncaught ReferenceError: i is not defined (...)

at :2:13

at Object.InjectedScript._evaluateOn (:878:140)

at Object.InjectedScript._evaluateAndWrap (:811:34)

at Object.InjectedScript.evaluate (:667:21)

Mike Cluck
  • 31,869
  • 13
  • 80
  • 91
Michael B
  • 23
  • 1
  • 5
  • 3
    Here is how you define a variable: `var i = 0;` (local scope) or `i = 0;` (global scope), or simply `var i;` (no initial value - i'm assuming that's not what you want). Doing `i++` without defining `i` previously will always get you an error. – blex Mar 21 '16 at 22:34
  • 3
    `var z = 1 + i++` does **not** establish a long-term dynamic relationship between `z` and `i`. It does not mean, "whenever I use `z`, treat it as if I had used `1 + i++`". It means, "assign to `z` the computed value `1 + i++` right now". – Pointy Mar 21 '16 at 22:37
  • @Pointy Would there be a way to create a dynamic relationship between the two? – Michael B Mar 21 '16 at 22:42
  • In JavaScript you could create a function to do it, but it would (in my opinion) probably make the code uglier. (Also, a binding like that, with the side-effect of changing the value of `i`, would generally be considered a bad idea.) Most common programming languages are like that, though not all. – Pointy Mar 21 '16 at 22:48

4 Answers4

1

There's a couple of suggestions I could advise with your code so I'll try and address each one individually.

Firstly define your function outside of your loop. If you would like to know the reasons behind this please read: Don't make functions within a loop

Secondly you should really declare i as a variable to set the scope to which it applies. Some good information on this is at: Declaring variables without var keyword

Thirdly when you run your loop you could run the code inside an IIFE. The reason for this is when you run setInterval, by the time it runs i will actually be 3 (or the last number of your loop). This is due to the asynchronous nature of setInterval, and that the reference to i is bound to the function, not the value of i.

Example

for(var i=0;i<3;i++) {
  (function(i) {
    setInterval(clickButton(i), 2000);
  })(i)
}

function clickButton(idx) {
  return function() {
      buttons = document.getElementsByTagName('button');
      document.getElementsByTagName('button')[idx].click();    
  }
}

JSBin Demo

http://jsbin.com/harigewuze/edit?html,js,output

Community
  • 1
  • 1
Mark
  • 2,184
  • 1
  • 16
  • 28
0

Why are you trying to define z outside the loop? Just use i.

for (var i = 0; i < 50; i++) {
    ...
    document.getElementsByTagName('button')[i].click();
}
Ted Noelker
  • 171
  • 3
  • This doesn't tell the OP why they got the reference error, nor why this makes it go away, nor does it fix the closure issue. All functions will attempt to click the 50th button (unless *i* is modified again before the function completes). – RobG Mar 21 '16 at 23:32
0

without changing your code too much I would write it like this... you know its looping 50 times, you know i is incrementing from 0 to 49, use i to change the button name and you don't need z...

for(i=0;i<50;i++) {
  setInterval(partA, 2000);
  function partA() {
    buttons = document.getElementsByTagName('button');
    document.getElementsByTagName('button')[i + 1].click();
  }
}

zachkadish
  • 472
  • 5
  • 7
  • I already attempted this and it did not seem to work, I also retried ti again, and it does not work, which is why I attempted to use z. – Michael B Mar 21 '16 at 22:46
  • I would also add the var declaration before i in the for loop... other wise it gets declared globally and might interfere with other loops you write using the variable i. – zachkadish Mar 21 '16 at 23:02
0

1) This is how you want your code to look like :

var z;

for(i=0;i<50;i++) {
z=i;
setInterval(partA, 2000);
}

function partA() {
buttons = document.getElementsByTagName('button');
document.getElementsByTagName('button')[z].click();
}

2) Unfortunately, in javascript you have a problem with this code due to the fact of scopes. My recommendation is to read this link first http://www.mennovanslooten.nl/blog/post/62 and understand how it works. If you did understand it, then thumb up..you just promoted yourself to a higher level in javascript ;)

3) If you are still having issues, post it on JSFiddle

Qaddura
  • 177
  • 6
  • The reference error is because *i* hasn't been declared or otherwise created before attempting to use it in an assignment. This also doesn't change the closure issue, all functions have a closure to *z* and when run will read its last assigned value (the name of the variable is irrelevant). Not declaring *i*, or *buttons*, is not a good idea. – RobG Mar 21 '16 at 23:36
  • Your #2 mentions scope (the reference error isn't about scope) and has a link, it doesn't actually say what the issue is. Links break or change, so far better to post the pertinent information here and use the link as a reference. – RobG Mar 22 '16 at 00:56