For Loop Behaviour - javascript

This question is regarding Javascript for loops, where I've been having some weird behaviour.
My For loop currently looks like this:
var UnitAmount = 2;//(value verified, yet not declared like this)
var DamageAmount = [1,3];//(value verified, yet not declared like this)
function forcerefresh () {
for( i=0 ; i < UnitAmount ; i++ ) {
//(10 lines of Stuff)
var check = 0;
for (c = 0; c < DamageAmount[i] ; c++ ) {
debug[0] = damage[i][c].getElementsByClassName("writedamage")[0];
debug[1] = damage[i][c];
debug[2] = unit[i];
check = check + 1;
console.info("Unit:",i,"Loop:",c,"Debug:",debug,"Check:",check, "Race:",unitrace[i], unit[i].dataset.race);
alert("Debug:"+ debug );
damageCalc(damage[i][c].getElementsByClassName("writedamage")[0],damage[i][c],unit[i]);
}
}
}
In here, debug, alert, Check and the console write call are already added to attempt to find the problem - I'm getting an infinite loop here.
The output im getting in the console shows that while the i constant walks as intended, but the c Iteration count starts at 0, jumps to 2, and then stays 2 - and since the DamageAmount[1] = 3, this creates an infinite loop. And where the c might stick at value 2, the check values does walk up through the iterations.
As for the amount of variables involved, I've checked time and again with the console, and all of them are defined, and the values I expected. The Code is located at http://age-of-wonders-3.wikia.com/wiki/MediaWiki:Units.js, but if any parts are requested I'll of course post them here.
Any help is appreciated!

Try using for of or .forEach on an array

Related

How to access the currently iterated array value in a loop?

Current attempt using an array of objects with properties:
The objective:
I want to automatically fill out emails on behalf of ~30 different people. The form fields are always consistent, but the values I'm filling in will change on an email-to-email basis. I'm using TagUI to do this.
My old code (last code box below) successfully filled out each form by assigning each line in the .csv to a separate array BUT failed to iterate through the values of a specific column within the .csv. Please see the text above the last code box below for further explanation.
Now I'm starting again, this time aiming to create an array of objects (representing each email being sent) with properties (representing each field to be filled within each email).
Here's what I've got so far:
// Using TagUI for browser automation
// https://github.com/kelaberetiv/TagUI
website-to-automate-URL-here.com
// Set up the arrays to be used later
emails = []
// Load in the 'db.csv' file
// Link to .csv: https://docs.google.com/spreadsheets/d/16iF7F-8eh2eE6kDiye0GVlmOCjADQjlVE9W1KH0Y8MM/edit?usp=sharing
csv_file = 'db.csv'
load '+csv_file+' to csv_lines
// Split the string variable "lines" into an array of individual lines
lines = csv_lines.split('\n')
// Split the individual lines up into individual properties
for (i=0; i < lines.length; i++)
{
emails[i].name = properties[1].trim()
emails[i].recipients = properties[2].trim()
properties = lines[i].split(',')
}
EDIT: The below code has been put on the back burner as I attempt to solve this another way. Solutions are still welcome.
I'm having trouble triggering my for loop (the last one in the code below).
My goal for the for loop in question, in plain English, is as follows: Repeat the below code X times, where X is determined by the current iteration of the total_images array.
So if the total_images array looks like this:
[Total Images, 2, 3, 4, 5]
And the parent for loop is on its third iteration, then this for loop should dictate that the following code is executed 4 times.
I'm using TagUI (https://github.com/kelaberetiv/TagUI), so there many be some non-Javascript code here.
https://www.website.com
wait 3s
// Setting up all the arrays that the .csv will load
array_campaign = []
array_subject = []
array_teaser = []
array_recipients = []
array_exclude = []
array_img1src = []
array_img1alt = []
array_img1url = []
array_img2src = []
array_img2alt = []
array_img2url = []
array_img3src = []
array_img3alt = []
array_img3url = []
array_img4src = []
array_img4alt = []
array_img4url = []
total_images = []
// Load in the 'db.csv' file
csv_file = 'db.csv'
load '+csv_file+' to lines
// Chop up the .csv data into individual pieces
// NOTE: Make sure the [#] corresponds to .csv column
// Reminder: Numbers start at 0
array_lines = lines.split('\n')
for (n=0; n<array_lines.length; n++)
{
items = array_lines[n].split(',')
array_campaign[n] = items[1].trim()
array_recipients[n] = items[2].trim()
array_exclude[n] = items[3].trim()
array_subject[n] = items[4].trim()
array_teaser[n] = items[5].trim()
array_img1src[n] = items[6].trim()
array_img1alt[n] = items[7].trim()
array_img1url[n] = items[8].trim()
array_img2src[n] = items[9].trim()
array_img2alt[n] = items[10].trim()
array_img2url[n] = items[11].trim()
array_img3src[n] = items[12].trim()
array_img3alt[n] = items[13].trim()
array_img3url[n] = items[14].trim()
array_img4src[n] = items[15].trim()
array_img4alt[n] = items[16].trim()
array_img4url[n] = items[17].trim()
total_images[n] = items[18].trim()
}
for (i=1; i < array_campaign.length; i++)
{
echo "This is a campaign entry."
wait 2s
}
// This is the problem loop that's being skipped
blocks = total_images[i]
for (image_blocks=0; image_blocks < blocks; image_blocks++)
{
hover vis1_3.png
click visClone.png
}
This is the most coding I've ever done, so if you could point me in the right direction and explain like I'm a beginner it would be much appreciated.
Look like the only reason make your last loop being skipped is that total_images[i] is undefined, which is used for the loop condition. I believe that the value of i at that moment is equal to array_campaign.length from the previous loop, which is actually out of array range.
Here're some example codes:
const arr = [0, 1, 2];
const length = arr.length; // the length is 3, but the last index of this array is 2 (count from 0)
for (i = 0; i < length; i++) {
console.log(i);
}
// output:
// 0
// 1
// 2
console.log(i); // i at this moment is 3, which is = arr.length and made the above loop exit
console.log(arr[i]); // => undefined, because the last index of the above array is 2, so if you reference to an un-existed element of an array, it will return undefined.
"run the following code X times, where X is determined by the value of total_images[i]" - so, if I understand your question correctly, you can use nested loops to do this:
for (i=1; i < array_campaign.length; i++)
{
echo "This is a campaign entry."
wait 2s
// nested loop, the number of iteration is based on the value i of outside loop
for (j=0; j < total_images[i]; j++) {
// do something here
}
}
My old code should have worked. I opened up the .csv file in notepad and noticed there were SEVERAL extra commas interfering with the last column of data, throwing everything for a loop.
Did some searching and apparently this is a common thing. Beware!
I created TagUI but I don't check Stack Overflow for user queries and issues. Try raising issue directly at GitHub next time - https://github.com/kelaberetiv/TagUI/issues
Looks like you found the solution! Yes, if the CSV file contains incorrect number of columns (some rows with more columns than others), it will lead to error when trying to work on it from your automation script. It looks like the extra commas cause extra columns and broke your code.

Is there an alternative to console.log() which lets you print out and update a single line instead of spamming the console?

I am looking for a way to print out a given variable f.ex. the i of a for-loop for each iteration, without it resulting in the entire console being filled with new lines of new values. Is there a console. method for just printing one line, and updating that as we go?
I realise that you could do this by implementing a text-field in your program which you change the with each iteration, but if there is a way of doing this in the console it would be a bit easier (and perhaps quicker? although I am really not sure about that). Thanks in advance.
If there is still confusion about what im asking, what i want is my console to print out:
"i = " i once, and then update the i in that one line, instead of:
i=1
i=2
i=3
1=4
.
.
.
which gets really messy as you go. For the exact example of the i in a for loop, you could get this value from just console.log()'ing the same thing for each iteration, and a number will pop up beside it (in firefox anyway), but i would like to be able to do this with some more useful information.
Option 1: use console.groupCollapsed() and console.groupEnd():
console.groupCollapsed();
for (let i = 0; i < 100; i+= 1) { console.log(`i = ${i}`) }
console.groupEnd();
Option 2: set the values in an array or a string and log the var when the iterations finish:
let valuesToLog = [];
for (let i = 0; i < 100; i+= 1) { valuesToLog.push(`i = ${i}`) }
// see it as an array
console.log(valuesToLog);
// see it as a string, with each value separated by ', '
console.log(valuesToLog.join(', '));
how about JQuery console.clear()?
$(function(){
loop_counter();
});
function loop_counter() {
for (let i = 1; i <= 100; i++){
console.clear();
console.log ("i=", i)
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Not understanding what I'm missing in my forLoop function

I've been trying to figure this out by re-writing my forLoop multiple times, look online for example and even checked out MDN and gotten to the point I need someones help.
Now the test error I get is:
1) loops forLoop(array) adds `"I am ${i} strange loop${i === 0 ? '' : 's'}."` to an array 2
5 times:
ReferenceError: forLoop is not defined
My current code looks like this:
function forLoop(array){
var newArr = [];
for (var i = 0; i < array.length; i++){
if (i === 1) {
newArr.push("I am 1 strange loop.")
} else {
newArr.push(`I am ${i} strange loop${i === 0 ? '' : 's'}.`)
}
}
return newArr
}
Thinking process:
I need a loop to iterate the array being place.
I need a new array to input something each time we loop around.
Call a for loop. Set i to 0 as we will start from there.
Find the end point which is less than array.length
Place increment since we will be going up from 0 each time we loop.
Make if and else statement
Add if statement is true to the new array
Return the new array in the end
Is there something I'm not understanding or missing? Really can't seem to crack this.
For additional information about the test. The test for this problem is:
describe('forLoop(array)', () => {
it('adds `"I am ${i} strange loop${i === 0 ? \'\' : \'s\'}."` to an array 25 times', () => {
const [array, t] = makeArray()
const strangeArray = forLoop(array)
expect(strangeArray.length).to.equal(t + 25)
const testArray = strangeArray.slice(array.length)
for (let i = 0, l = testArray.length; i < l; i++) {
let s = i === 1 ? "I am 1 strange loop." : `I am ${i} strange loops.`
expect(testArray[i]).to.equal(s)
}
})
})
ReferenceError: forLoop is not defined means that the Javascript interpreter can't find the function "forLoop".
Possible causes:
The test and the function are not in the same file and you made a mistake while including the file which contains the function. Make sure you include your file with the function before the test file.
The test doesn't have access to the function because it's in a different scope of your application.
I tested the forLoop function myself and it worked for me. I don't think the problem is in the forLoop function.

Two conditions in for loop

I have this code which im echoing data from jquery success .
for(i = 0;i < dat.id.length; i++){
// im echoing data here
}
and i want check for the highest value in dat.voteup
like that (It works)
var maxvoteup = 0;
if (dat.voteup[i] - dat.votedown[i] ==maxvoteup) {
console.log(maxvoteup);
//i want fetch maxvoteup here
}
But i want make just one For loop not two . How can i do that pls?
EDIT:
var maxvoteup = 0;
for (i = 0;i < (dat.voteup-dat.votedown).length ;i++) {
if (dat.voteup[i] - dat.votedown[i]>maxvoteup) {
maxvoteup = dat.voteup[i] - dat.votedown[i];
console.log(maxvoteup);
//i want fetch maxvoteup here
}
}
EDIT2:
this is what im getting in my jquery response , But actually my max vote is 10 not 8 . 8 is just voted up to 8 , but there is other votes which is 10.
{"status":"success","message":[],"date_edited":[2016-04-21 21:31:25],"voteup":[],"votedown":[8],"id":[]}
Your code is a little hard to read, but if I understand correctly I believe all you need to do is combine both into a single loop with maxvoteup defined outside.
var maxvoteup = 0;
for(i = 0;i < dat.id.length; i++){
// echo data...
// max upvote
if (dat.voteup[i] - dat.votedown[i] == maxvoteup) {
console.log(maxvoteup);
}
}
EDIT:
Unfortunately getting the maximum value from a list requires you to iterate through the list, i.e., a maximum value cannot be found in constant time. I suggest you first find the maximum, and then proceed with your for loop.
Also, if you know your maximum is a list of numbers, you can actually use Javascript's apply to make the code a little cleaner:
var maxvoteup = Math.max.apply(Math, listOfMaxVotes);
See here: How does the Math.max.apply() work?
EDIT2:
If you want to continuously keep track of the maximum, then all you need to do is move the maxvoteup variable to outside of your response handlers so you can always keep track.
// global scope...
var maxvoteup = 0;
// your jquery response handler
var onSuccessData = function(data) {
// get the highest possible max from the `voteup` and `votedown` lists
var responseMax = Math.max.apply(Math, data.voteup.concat(data.votedown));
// check if it's greater than our global maxvoteup
if (responseMax > maxvoteup) {
// if it is, then update our global `maxvoteup` to the new value
maxvoteup = responseMax;
}
// continue with your other processing...
};

Javascript array in loop

I am trying to loop through all elements in an xml file with the name "playerhash" with javascript.
for(var i = 0; i < 4; i++) {
alert(i);
if(getCookie('riskinfo') == xmldoc.getElementsByTagName("playerhash"[i].childNodes[0].nodeValue) {
player = xmldoc.getElementsByTagName("playerhash")[i].getAttribute('color');
break;
}
}
When I try to run the js it gives me Line 3: Uncaught TypeError: Cannot read property 'nodeValue' of undefined With the alert() function I figured out that the error is occurring when i = 0 and I know that there are at least four playerhash elements.
How can I loop through all of the elements without the error?
As deceze said, you have errors in the code. You should write your code in much smaller steps so that it is easier to debug. Also, check each step before proceeding so that if it fails unexpectedly, it will not throw errors at the user. Condition expresssions should not do assignment as that makes debugging more difficult, use them just for testing conditions:
// Should have already checked that xmldoc is a valid document
var riskinfo = getCookie('riskinfo');
var playerhash = xmldoc.getElementsByTagName("playerhash");
var max = 4; // or playerhash.length
var node, player;
for(var i = 0; i < max; i++) {
node = playerhash[i];
if (node && node.nodeValue == riskinfo) {
player = node.getAttribute('color');
i = max; // break out of for loop
}
}
.getElementsByTagName("playerhash"[i].childNodes[0].nodeValue)
You're missing a ) in there. Should be something along the lines of this:
if (getCookie('riskinfo') == xmldoc.getElementsByTagName("playerhash")[i].childNodes[0].nodeValue) {
Of course, repeating xmldoc.getElementsByTagName("playerhash") in every loop is rather expensive, you should do this once before the loop and save the result in a variable.
You should probably also check whether the ith element actually exists and whether it actually has any child nodes before trying to access that child node.

Categories

Resources