Javascript function: nothing executes after a for(x in y) loop? - javascript

I can't seem to find the answer to this anywhere...
I have a function that needs to set the bg color of two tables. Only the first table in the function is being affected. Is only one for loop allowed in a function? ...or is the 1st for loop maybe never exiting?
I can pretty much work around this by creating multiple functions but I really want to understand why this behaves the way it does!
Thanks!
Here is my simplified code:
function setColor()
{
//This works
var t1rows=document.getElementById("table1").getElementsByTagName("tr");
var x;
for (x in t1rows)
{
t1rows[x].style.backgroundColor='yellow';
}
//this one does not work
var t2rows=document.getElementById("table2").getElementsByTagName("tr");
var y;
for (y in t2rows)
{
t2rows[y].style.backgroundColor='yellow';
}
}

getElementsByTagName() returns a NodeList object, and for-in will iterate its properties which you don't want. You want to use a straight for loop:
for(var i=0; i < t2rows.length; i++) {
t2rows[i].style.backgroundColor='yellow';
}
You're not getting to the second loop because the first is failing when it tries to access a non-existent style property on one of the NodeList's members.

Related

Removing and appending on wrapper in the same loop causes issues

I'm making a simple filtering function where I pass a sorted array into a function which is supposed to clear the wrapper and add the new ordered elements. My natural thought here is to do the removing and adding in the same loop, but I just can't get it to work and I can't really figure out why it wouldn't work.
Function that takes an array as argument. The sorted array is passed inside the function without any issues. The array is an Array.from(nodeList).
function removeAndAdd(sortedArray) {
for (let i = 0; i < allPosts.length; i++) {
const forumPost = allPosts[i]
forumPost.replaceWith(sortedArray[i])
}
}
NOTE: I've also tried (And alot of other stuff)
for (let i = 0; i < allPosts.length; i++) {
const forumPost = allPosts[i]
forumPost.remove()
wrapper.append(orderedArray[i])
}
My expectation is that with a single loop you should be able to clear the elements and at the same time att a new element. I don't want to use two different loops here.
Edit: I solved it by using remove() in an async function outside. I'd still love to learn technically why this didn't work.

for loop calculation syntax within a function is not correct

what is the actual syntax for the for loop?
what I want to do is to calculate 2 number variables inside a function using a for a loop.
I am going over and over the internet and I cannot find anything that can help me specifically for this task I was given to do.
I am not looking for the answers, just for a guideline or a hint.
or just give me the syntax and I will try my best to adjust it to my needs.
just so you have a better understanding of the task, here it is.
Features
Instead of hardcoding Y (the result of the Fibonacci of X), calculate it with a for loop
The calculation should be wrapped in a function, that gets X as an argument, and returns Y
After the function, you should call the function, and assign the returned value in your HTML to present to the user
btw, i know that i did not put the innerHTML correcly, and also i did not do the syntax right, this is actually what i am asking here.
thank you!!
i have tried this:
var answer = document.getElementsByClassName("paragraph")
function calc (x){
for (let a = 2; a <= x; a++){
answer = document.textContent("this is a pr")
}
return calc
}
calc(2)
You should avoid to use classname, instead use .querySelectorAll
You don't need to specify how many answer exists if your calc() is just 2.
let answer = document.querySelectorAll(".paragraph");
function calc(x) {
for (let a = 0; a <= x; a++) {
answer[a].innerText = "this is a pr";
}
}
calc(2);
<p class="paragraph">A</p>
<p class="paragraph">B</p>
<p class="paragraph">C</p>
<p class="paragraph">D</p>
<p class="paragraph">E</p>
I don't know if this is what you're searching for but it's this is the standard for loop function to achieve these types of result.
function calc(x){
let sum = 0;
for (let a=0; a<x; a++){
sum+=a;
}
return sum;
}
console.log(calc(5));
The Syntax of the loop in your code is correct, the thing is that you cannot return your function inside itself without calling it as you have done in your code.
'return calc' is wrong. You should use 'return calc(argument-Variable or value)' as you have a parameter passed in your function, but this should only be used if you are writing a code of recursion. If not you should return a variable.
Refer to the code below for further clarifications

understanding variable scope with FOR vs IF loop

My goal was to create a function for a click event that would count up on each click, and use that counter as an array index in order to increment through an array. Can someone help me understand why the first code block produced the desired result, but the second does not. I have a feeling it has to do with variable scope, but this is my first JavaScript project. Thank you.
var i = 0;
function click(){
if(i < Questions.length-1){
i++;
div.innerHTML = Questions[i].question;
}
}
Does not produce them saves results as this code:
function click(){
for(var i = 0; i < Questions.length-1; i++){
div.innerHTML = Questions[i].question;
}
}
In the first one you have a global i.
This means:
If anything else uses i it will clobber the value used in click, and
After you call click the first time you're using the value of i as set by the last call of click, or whatever modified it outside of click.
In the second one you have an i local only to the click function. It's initialized, used, and discarded when the method completes.
You set the innerHTML to all the questions, and the last one set will be the one you see.
Even though the first one works (at the moment) having a global variable named i is pretty risky, and brittle. You'd be better off encapsulating the question index.
It doesn't have anything to do with the scope.
The first method is correct because, on each click i is incremented once, and the ith question is displayed.
In the second method, on every click you're iterating through all the questions in one go. Hence, in the end only the last question would be printed in the div.
Javascript arrays begin at index 0, so you need to access the array before incrementing your counter. For instance, your first code should look like :
var i = 0;
function click(){
if (i <= Questions.length-1) {
div.innerHTML = Questions[i].question;
i++;
}
}
or even better (more concise) :
var i = 0;
function click(){
if (i <= Questions.length-1) {
div.innerHTML = Questions[i++].question;
}
}
Note the <= instead of = because if your have a 2-sized array, index 1 is good (and the last entry, actually).
Your second code iterates over the whole array at each click (an then displays only the before-last question in array) whereas the first code only increment when the element is clicked on.
Here is an interpretation. Not sure if that is what you're looking for.
The code block has nothing special to do with javascript.
The first block simply increment i once and the second loops through it until array ends.
Here are some excerpts from my Chrome console:
var i=0;
function callMe(){
if (i < arr.length-1){
i++;
console.log(arr[i]);
}
}
arr = ["one", "two", "three", "four"]
function callMe2(){
for (var j=0; j < arr.length; j++){
console.log(arr[j]);
}
}
And then..
callMe()
two
callMe()
three
callMe()
four
callMe()
<blank>
callMe2()
one
two
three
four
Hope this helps!

Why can't I assign for loop to a variable?

So I am just wondering why the following code dosen't work. I am looking for a similar strategy to put the for loop in a variable.
var whatever = for (i=1;i<6;i++) {
console.log(i)
};
Thanks!
Because a for loop is a statement and in JavaScript statements don't have values. It's simply not something provided for in the syntax and semantics of the language.
In some languages, every statement is treated as an expression (Erlang for example). In others, that's not the case. JavaScript is in the latter category.
It's kind-of like asking why horses have long stringy tails and no wings.
edit — look into things like the Underscore library or the "modern" add-ons to the Array prototype for "map" and "reduce" and "forEach" functionality. Those allow iterative operations in an expression evaluation context (at a cost, of course).
I suppose what you look for is function:
var whatever = function(min, max) {
for (var i = min; i < max; ++i) {
console.log(i);
}
}
... and later ...
whatever(1, 6);
This approach allows you to encapsulate the loop (or any other code, even declaring another functions) within a variable.
Your issue is that for loops do not return values. You could construct an array with enough elements to hold all the iterations of your loop, then assign to it within the loop:
arry[j++] = i;
You can do this, but it seems that you might want to check out anonymous functions. With an anonymous function you could do this:
var whatever = function(){
for (var i=1;i<6;i++) {
console.log(i);
}
};
and then
whatever(); //runs console.log(i) i times.

jquery name selector not working in ie6

var brands = document.getElementsByName("brand");
for(var brand in brands){
$("input[name='brand']").eq(brand).click(function(){
alert("hello22");
loadDataFN(1);
});
}
This code is not executing in ie6,
Any help would be appreciated.
The problem is likely that you are trying to use a for-in construct to iterate over a numeric array. This often won't give expected results. Use an incremental for loop instead:
var brands = document.getElementsByName("brand");
// Use an incremental for loop to iterate an array
for(var i=0; i<brands.length; i++){
$("input[name='brand']").eq(brands[i]).click(function(){
alert("hello22");
loadDataFN(1);
});
}
However,
after seeing the first part of your code, the loop appears unnecessary. You should only need the following, since you are assigning the same function to all brand inputs.
// These will return the same list of elements (as long as you don't have non-input elements named brand)
// though the jQuery version will return them as jQuery objects
// rather than plain DOM nodes
var brands = document.getElementsByName("brand");
$("input[name='brand']");
Therefore, the getElementsByName() and loop are not necessary.
$("input[name='brand']").click(function() {
alert("hello22");
loadDataFN(1);
});
for-in loops are used for iterating over the properties of an object, not over the elements of an array.
Why don't you write the code without jQuery if this doesn't work?
Something like this:
function getInputByName(name) {
var i, j = document.getElementsByTagName('input').length;
for(i=0;i<j;++i) { // You can also use getAttribute, but maybe it won't work in IE6
if(document.getElementsByTagName('input')[i].name === name) {
return document.getElementsByTagName('input')[i];
}
}
return null;
}
I don't know jQuery, but maybe you can do something like this:
$(getInputByName('brand')).eq(brand).click(function(){
alert("hello22");
loadDataFN(1);
});

Categories