FOR - getElementByName and i value [duplicate] - javascript

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 8 years ago.
Following my code:
for(var i =0; i < document.getElementById('test').getElementsByTagName("li").length; i++){
document.getElementById('test').getElementsByTagName("li")[i].onmouseover= function(){
alert(document.getElementById('test').getElementsByTagName("li")[i].innerHTML);
}
}
HTML:
<div id="test">
<ul><li>test</li><li>test2</li><li>test3</li><li>test4</li></ul>
</div>
JSfiddle: http://jsfiddle.net/Pwddf/1/
"i" is always assigned the last value and then does not work. How to solve?

The problem is scoping. If you create a function inside of a loop, the loop variables will always have their last loop values. Basically, the loop executes, but the variables inside the function declaration are not evaluated until the function is called, at which point "i" is equal to the last value. You can use a closure to make the vars resolve immediately.
for(var i =0; i < document.getElementById('test').getElementsByTagName("li").length; i++){
(function(i) {
document.getElementById('test').getElementsByTagName("li")[i].onmouseover= function(){
alert(document.getElementById('test').getElementsByTagName("li")[i].innerHTML);
};
})(i);
}
I also agree with tymeJV that you should store your elements first, rather than reselecting them.

Looks like you want querySelectorAll instead:
var elems = document.querySelectorAll("#test ul li");
for (var i = 0; i < elems.length; i++) {
elems[i].onmouseover = function() {
console.log("See?");
}
}
If you actually need that i value, use a closure inside the for:
(function(i) {
elems[i].onmouseover = function() {
console.log("See?" + i);
}
})(i)
Demo: http://jsfiddle.net/Pwddf/2/

Here is a very concise solution that works in jsfiddle inside Firefox and IE9:
var elems = document.getElementById("test").getElementsByTagName("li");
for(var i =0; i < elems.length; i++){
elems[i].onmouseover= function(e){
console.log(this.innerHTML);
console.log(e);
}
}
http://jsfiddle.net/8LyhN/1/
Not knowing what all you are planning to do inside your mouseover event, I recommend passing in the event so you can reference it as 'e'.

You should do like this if you really want to use javascript than JQuery.
var ul = document.getElementById("test");
var li = ul.getElementsByTagName("li");
for(var i =0; i <li.length; i++){
li[i].onmouseover= function(){
alert(this.innerHTML);
}
}
check here : http://jsfiddle.net/alaminopu/Pwddf/5/

You need to cache i;
for(var i =0; i < document.getElementById('test').getElementsByTagName("li").length; i++)
{
var _i = i;
document.getElementById('test').getElementsByTagName("li")[i].onmouseover= function()
{
alert(document.getElementById('test').getElementsByTagName("li")[_i].innerHTML);
}
}
// Even better;
var elements = document.getElementById('test').getElementsByTagName("li");
for(var i =0; i < elements.length; i++)
{
elements[i].addEventListener('mouseover', function()
{
alert(this.innerHTML);
});
}

Related

Need to duplicate the same element in the DOM 4 times using Jquery

Im using jquery to insert html in the dom. Everything is working fine, now i need to duplicate an element 4 times, and i don't know how.
this is how i use Jquery to insert the element into the DOM.
function Pin(caixaPin){
var $temp;
$temp = $("<div></div>");
$temp.addClass("caixaPin");
$temp.html(caixaPin);
$("body").append($temp);
}
Pin('<div></div>');
Thanks !!
Here you go with jsfiddle https://jsfiddle.net/eL3usbxb/
function Pin(caixaPin){
for(var i=0; i<4; i++){
var $temp;
$temp = $("<div></div>");
$temp.addClass("caixaPin");
$temp.html(caixaPin);
$("body").append($temp);
}
}
Pin('<div></div>');
Another way
Just call Pin function inside a loop
for (var i = 0; i < 4; i++){
Pin('<div></div>');
}
for (var i = 0; i < 4; i++){
Pin('<div></div>');
}
There you go. Basic for loop from 0 to 3 (4 times). And calling Pin inside it.
Just execute your function pin in loop
You can use a for loop to create X amount of Y, like this:
for (var j = 0; j <= 3; j++)
{
$('body').append('<div class="caixaPin"></div>')
}
what this does is define j as 0, when it gets to 3 and including 3, append <div></div> to the body. Hope this helps

Value gets overwritten because of access by reference

a = [];
for (var i = 0; i < 3; i++) {
a.push(function() {
console.log(i);
})
}
a[0]() // I want 0, but I get 3
I am trying to write a simple piece of code where I have an array of functions such that when I execute a function at a particular index, the index value should get printed.
However, the piece of code above shows the same result (3 in this case) for all index values. I understand that the value is pointing by reference and therefore points to the last value of i. Could someone point out how to do this in the right manner?
Wrap it around a function. Now each time the loop executes, the wrapper function has its own value of i.
a = [];
for (var i = 0; i < 3; i++) {
(function(i){
a.push(function() {
console.log(i);
})
})(i);
}
a[0]()
You can add a self executing function to act like a module. Doing this, the scope of the variable i is in that function.
a = [];
for (var i = 0; i < 3; i++) {
(function(i){
a.push(function() {
alert(i);
})
})(i);
}
a[0]()
Note: In this block (function(i){ ... })(i), i can have any name, there is no connection between i from loop and i from function, i.e. (function(r){ ... })(r).
Here is an alternate version to an anonymous function that gets created and executed all at once.
The issue that you are having is that when the function gets called, the loop has already been evaluated and the value of i has already reached the max value of 3. You need trap the current value of i while the loop is being evaluated.
var a = [];
for (var i = 0; i < 3; i++) {
var fn = function() {
console.log(arguments.callee.i);
}
fn.i = i; // Pass as 'i' parameter to 'fn'.
a.push(fn);
}
a[0](); // The value 0 will be printed, rather than 3.
There is more than one way to skin a cat. The code above is very similar to:
var a = [];
function fn(i) {
return function() {
console.log(i);
}
}
for (var i = 0; i < 3; i++) {
a.push(fn(i));
}
a[0](); // The value 0 will be printed, rather than 3.

Unable to create multiple droppable elements inside a loop using jquery

I am trying to create many droppable elements inside a loop. Here is the code:
for (var i = 0; i < 10; i++) {
for(var j = 0; j < 20; j++){
$("#main").append( '<a "href="javascript:void(0);" id="click'+i+'-'+j+'" onclick="change_to_blocked('+i+','+j+')"><img id="image'+i+'-'+j+'" src="http://localhost/free.png" />');
$("#main").append('');
tmp1 = i;
tmp2 = j;
$('#image'+i+'-'+j).droppable({
drop: function(e,ui) {
$('#image'+(i)+'-'+(j)).attr('src','/bot.png');
console.log(i);
}
});
}
$("#main").append('<br>'); }
However, it only applies to the last value of the loop.
You need to create a closure otherwise at the time the events occur the values of i and j will be the values of the last iteration of the loop.
One way is to wrap the code within loop in an IIFE - Immediately Invoked Function Expression
for (var i = 0; i < 10; i++) {
for (var j = 0; j < 20; j++) {
(function (i, j) {
$("#main").append('<a "href="javascript:void(0);" onclick="return showIndexes('+i +','+j+')">Item # '+i+'-'+j+'</a><br>');
})(i, j); //params used in the IIFE
}
}
By passing the values as arguments of the function they are closed in the function and won't be changed by subsequent iterations
Some of the html rendering was left out for clarity
When looping over arrays with jQuery, you can create a closure by using $.each which will provide you the index as first argument of the callback
DEMO

How to show current loop iteration in click function, javascript [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 8 years ago.
JSFiddle
var arr = [ [0], [1], [2], [3] ];
for ( var i = 0; i < arr.length; i++ ) {
$('#btn-' + i).click(function() {
console.log(i);
});
}
When I'm clicking on corresponding button console.log always shows me last iteration instead of the current iteration. Why?
Try creating a closure, In other words, create a scope per iteration. Now in your code all the event handlers are created in a single scope and the i inside of that scope would get updated instantly to 4. So as a result, when you clicking on all the buttons the result would be same. That is the updated one of i
for ( var i = 0; i < arr.length; i++ ) {
var j = function(x) {
$('#btn-' + x).click(function() {
console.log(x);
});
}
j(i);
}
DEMO
Because of closure! For that you can do this:
for (var i = 0; i < arr.length; i++) {
(function(n) {
$('#btn-' + i).click(function() {
console.log(n);
});
})(i);
}
DEMO

Why does this for loop not run? jQuery

http://jsfiddle.net/leongaban/BvuT5/
Trying to get the 2nd alert to popup twice, however seems like the for loop isn't even running.
jQuery
var wireRequestorCard = function(jarjar) {
alert('1st alert');
var loop_num = 0;
for (var i = 0, length = jarjar.length; i < length; i++) {
loop_num = i;
alert('Where is this Alert? '+i);
}
alert('Closing Alert');
}
var jarjar = 2;
wireRequestorCard(jarjar);
You aren't passing an array or string to the function, which does not have a length property. Instead jarjar is a number.
jarjar is an integer.
it does not have a length property.
You just need to compare i to jarjar:
for (var i = 0; i < jarjar; i++) {
alert('Here is this Alert! '+i);
}
http://jsfiddle.net/daCrosby/BvuT5/5/

Categories