For Loop repeats first loop twice - javascript

I have this for loop, and it seems to be repeating the first loop twice (x=0) and then not doing the last one (x=2)
for (x=0;x<=2;x++)
{
if (document.getElementById("sub"+catCount+x).value != "")
{
if (nonums.test(document.getElementById("sub"+catCount+x).value))
{
total = total + parseFloat(document.getElementById("sub"+catCount+x).value);
}
}
alert(x);
}
In other words, I get two alert boxes with "0" in them, then one with "1" in it, and that's it.
Can anyone tell me what I'm not seeing here? Why doesn't it just progress through the loop normally (0,1,2)?

that is literally the only spot I use
the variable x on any page.
It works for me.
for (x=0;x<=2;x++)
{
alert(x);
}
You can test it at console.

I don't think you want the variable x to be global in scope. Try it with the "var" keyword:
for (var x=0;x<=2;x++)
...
I can paste this in my address bar and it will produce 0, 1, 2.
javascript:for (var x=0;x<=2;x++) {alert(x);}
I tried it in IE, FF and Chrome.

Related

javascript: var i is not defined? (clearly defined)

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)
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
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();
}
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();
}
}
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

Google Apps Script Writing to Spreadsheet Column One Step Behind

Weird problem here. I'm writing a script using Google Apps Scripts. Part of the script takes values from 1 Range/array ("a"), finds the value in a second Range/array ("b"), and then writes the corresponding value from a 3rd Range/array ("c") into column F in the spreadsheet. It's basically a vlookup.
When I check the code, debugger, etc. everything looks fine. And the output into the sheet looks good too. Except when I ran the program, the last value was missing from the sheet. When I ran the program slowly using the debugger, it seems that for some reason the values aren't being printed to column F until the following round of the loop is complete. This doesn't really make any sense based on the values of the variables at the time. So for example, when i=4, it should be printing to F6. But instead it prints the previous value to F5. All of the correct values are in the correct place in the end (except the last one), but the timing seems to be off on when that happens which is why I'm missing my last value.
Note: I have tried seeing if it's just about a time delay, and that doesn't seem to be the case. I've reloaded the spreadsheet, waited a while, etc. It's just 1 step behind.
Code is below, pretty simple I think. Any help would be appreciated
loop1:
for(i=0;i<a.length;i++){
loop2:
for(j=0;j<b.length;j++){
if(a[i].valueOf() == b[j].valueOf()){
sheet.getRange("F"+(i+2)).setValue(c[j]);
break loop2;
}
}
}
I tried to re-create your situation with the following code:
function myFunction() {
var a = ['one','6','match'];
var b = ['two','Vee','match'];
var c = ['three','Vee','match'];
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getActiveSheet();
loop1:
for(i=0;i<a.length;i++){
loop2:
for(j=0;j<b.length;j++){
//Logger.log('a[i].valueOf() ' + a[i])
//Logger.log('b[j].valueOf() ' + b[j])
Logger.log(a[i].valueOf() == b[j].valueOf());
if (a[i].valueOf() == b[j].valueOf()) {
Logger.log('they match!');
Logger.log('i: ' + i);
Logger.log('j: ' + j);
sh.getRange("F"+(i+2)).setValue(c[j]);
break loop2;
}
}
}
};
The code runs, and it puts a value into cell F4 with the array data provided.
The Log:
false
false
false
false
false
false
false
false
true
they match!
i: 2
j: 2

Keep losing incremental variable within for loop

I've been fiddling with this for way too long and can't seem to get it working as it should.
The problem I'm having is that I'm losing the value of my incremental variable in a for loop, specifically when it goes in to the if statement that I have inside of it. Ideally i want to iterate through an array until I find the correct value, attach a variable to that value and use it outside of the for loop. This is the structure of the array I'm working with.
var dXId = [
{url:"url1", dId:"id1"},
{url:"url2", dId:"id2"},
{url:"url3", dId:"id3"}
];
And here is the loop that I'm running everything through:
for(i=0; i < dXId.length; i++) {
if (dXId[i].url == currentUrl){
var dataXuId = dXId[i].dId;
break;
}
}
The incremental 'i' variable always reverts back to 0 within the if statement. It's odd, the dXId[i].url comes up correctly, but the dXId[i].dId pulls the first entry and 'i' seems to be lost after that. I'm sure there is a very simple solution to this, but javascript is something that I just always seem to have trouble with.
You are setting dXId[i].url = currentUrl inside your for loop instead of comparing with '=='. That could be part of the problem.
EDIT
As suggested by Eric...
The == Operator is to loosely compare the value of things, and the === is to strictly compare the value and type of things.
Examples:
Given x=10;
x == '10' // true
x == 10 // true
x === '10' // false
x === 10 // true
You have mistake in your if syntax.. you are assigning value of currentUrl to variable dXId[i].url
if (dXId[i].url = currentUrl){
...
}
It should be changed to === to compare string values.
if (dXId[i].url === currentUrl){
...
}
After that, it works! Example also here: js fiddle
Thus, it is rather funny that JavaScript lets do such things in the first place: Assigning value to a variable in if block should definitely not be allowed.
For example consider the following snippet:
var foo = 1, // change to 0 and console.log will not be displayed
bar; // undefined
// Assigning value of foo to bar
if (bar = foo){
// Will print out 1
console.log("bar is: " + bar);
}
Will result to a printing following output to the console:
bar is: 1
The reason being that if (bar = foo){ is equals to if (1){ which allows program to continue inside the if block :) ... if value of 0 is used for foo, console.log will not be displayed. (This is the behaviour at least which I tested using google chrome.)
Example about this in js fiddle

Why the eval() is not working with array

What's wrong with this code? Can anyone help out?
var read=new Array("i=10","j=20","k=i*j");
for(var i=0;i<read.length;i++)
{
alert(eval(read[i]));
}
Expecting output:
alert three times with values 10,20,200.
But actual output:
But alert Once with value 10.
When the loop executes the first time, you are setting i = 10, with eval. So the loop breaks out immediately.
So, you might want to change the loop variable to something else, like this
var read = new Array("i=10","j=20","k=i*j");
for(var idx=0; idx < read.length; idx++)
{
console.log(eval(read[idx]));
}
Output
10
20
200
Note: Please make sure that you read this question and the answers to that question, before using eval in your code.
Try this code
var read=new Array("i=10","j=20","k=i*j");
for(var index=0;index<read.length;index++)
{
alert(eval(read[index]));
}
while the loop is executing, at the first execution of i=10 the i variable is set to 10; so loop will be terminated because of the condition i<read.length (here... 10<3) remains false.
see the eval() tutorial.

For loop issue in FireFox

Im working on a script which removes the default values in form elements using Prototype and LightView. The scripts works fine in Safari, but not at all in FireFox (3.5.5).
This fires when a lightview is triggered.
document.observe('lightview:opened', function() {
if($('contact_form')) {
var defaults = new Array();
var ins = $('contact_form').getElements();
var inlen = ins.length;
for(i=0; i < inlen; i++) {
alert(i)
if($(ins[i]).readAttribute('type') != 'image') {
defaults[ins[i].name] = $(ins[i]).value;
$(ins[i]).observe('focus', checkDefault.bind(event, ins[i]));
}
}
function checkDefault(name, event) {
alert(name.name)
if($(name).value == defaults[name.name]) {
alert(defaults[name.name])
$(name).value = '';
}
}
}
});
The strange this is, when I check for the length of inlen the proper number is alerted, but when I alert 'i', only the first number is alerted. I can't figure out why this is happening.
Any ideas what's wrong here?
Here is the address of the problem:
http://bearing.krd-design.net/
Thanks
Rich
I'm not sure if this would cause that problem, but you are missing var:
for(var i=0; i < inlen; i++) {
Also, there are no semi-colon's after any of your alert()s.
Try correcting those, and see if it makes a difference.
EDIT:
As pointed out by Matt, in the comments: neglecting var creates the variable in the global scope. This could cause a problem if prototypejs also uses a global variable i (but I sincerely doubt that).
EDIT 2:
Another possibility is the array accessing by input name:
defaults[ins[i].name] = $(ins[i]).value;
Try declaring defaults as an object:
var defaults = {};
It sounds like a timing issue; the alerts slow execution to the point where your code works in FF. Do you use FireBug?
First of all, I think it is only going to i=0 is probably because the JS broke during the first iteration. To troubleshoot, I'd put alert() in between lines and see which line is breaking it.
My guess of the problem should be in the line:
$(ins[i]).observe('focus', checkDefault.bind(event, ins[i]));
The first parameter of the 'bind' function should be context and you are passing in 'event'. 'event' isn't defined and it should be the context or scope.
In your case, I think you can just use:
$(ins[i]).observe('focus', checkDefault(ins[i]));

Categories

Resources