How to alert numbers in a for loop [duplicate] - javascript

This question already has answers here:
How do JavaScript closures work?
(86 answers)
Looping setTimeout
(3 answers)
Closed 8 years ago.
Please help me fix this code
HTML
<p class="imgclass">Test1</p>
<p class="imgclass">Test2</p>
<p class="imgclass">Test3</p>
JavaScript
imgclassElements = document.getElementsByClassName('imgclass');
for (var i = 0; i < imgclassElements.length; i++){
imgclassElements[i].onmouseover=function(){alert(i);};
}
In browser onmouseover elements with class .imgclass appear alertbox only with text "3". How fix this? I want to pop-up alert window with values appropriate .imgclass elements order.

This is the simplest way to do it, you can use a closure but I'll keep it simple. Also you can access the element and apply styles, or get info from it in the click handler
FIDDLE
http://jsfiddle.net/bz7a2vf5/1/
HTML
<p id="item1" class="imgclass">Test1</p>
<p id="item2" class="imgclass">Test2</p>
<p id="item3" class="imgclass">Test3</p>
JS
imgclassElements = document.getElementsByClassName('imgclass');
for (var i = 0; i < imgclassElements.length; i++) {
click(i);
}
function click(i){
imgclassElements[i].onmouseover = function (e) {
// you can also get the element from e.target
alert(i);
alert(e.target.id);
};
}

This may not be the most elegant way, but
imgclassElements[i].addEventListener('mouseover',function(j){return function(){alert(j);};}(i));
should do it.
That said, you should really read up on JS closures as suggested in the comments to your question.

That problem is occurring because of the time alert is being called, value of i is incremented to 3 that's why it's giving 3 every time.
Try to bind a function with the current value of i like bellow
imgclassElements = document.getElementsByClassName('imgclass');
var printVal = function(i){
return function(){
alert(i);
};
}
for (var i = 0; i < imgclassElements.length; i++){
imgclassElements[i].onmouseover = printVal(i)
}
There can be better solutions also.

The easiest way is to extract the content of your loop in a function
function handleElement(element, i) {
element.onmouseover=function(){alert(i);};
};
for (var i = 0; i < imgclassElements.length; i++){
handleElement(imgclassElements[i], i);
}
Or you can use forEach (Sadly it's a HTMLCollection and not an Array, so it's a bit difficult)
Array.prototype.forEach.call(imgclassElements, function(element, i) {
element.onmouseover=function(){alert(i);};
});
Or give the index as an argument
for (var i = 0; i < imgclassElements.length; i++){
imgclassElements[i].onmouseover=(function(i){alert(i);}).bind(null, i);
}
And always a good thing to learn about closures

Related

JavaScript Why does the index of a for loop add one when adding eventlisteners [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 4 years ago.
I have a question which might sound silly. In the code below there are 2 console.log(i) statements. I want to know why does the second console.log(i) statement returns value of 2 and not 1 as the former on the first iteration (i.e. 1st statement i=n, 2nd: i=n+1). Shouldn't both be equal to 1 until the end of the loop?
function toggleWrapper(){
var el1 = document.querySelectorAll('[class="tCell entryDesc"]');
for (var i = 1; i < el1.length; i++) {
console.log(i);
el1[i].addEventListener('click', function(ev){
console.log(i);
var el2=document.querySelectorAll('[class="additionalInfoContainer"]');
if (el2[i-2].clientHeight) {
el2[i-2].style.maxHeight = 0;
}
else{
el2[i-2].style.maxHeight = el2[i-2].scrollHeight +"px";
}
},
false);
}
}
The problem is that the variable i, within each of your addEventListener() functions, is bound to the same variable outside of the function. simply change your for loop to :
for (let i = 1; i < el1.length; i++)
In the loop with let based index, each iteration through the loop will have a new value of i where each value is scoped inside the loop, so your code would work fine.
i think is something in your code because if you try to make a for loop with two "console.log()" it doesn't do that

Adding class to div with onclick function [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 7 years ago.
I tried to find some way to solve my problem, which is to add class to the divs when I click on them, but I can't make it work.
var el = document.getElementsByClassName('applications');
var i;
for (i = 0; i < el.length; i++) {
el[i].addEventListener("click", function() {
if (el[i]) {
el[i].className += el[i].className ? ' openDiv' : 'openDiv';
}
});
}
I have the 'for loop' because I used getElementsByClassName which gives a node list. I also created a codepen example:
http://codepen.io/anon/pen/dGqmMy
Instead of using complex string manipulation, use classList:
el[i].classList.add('openDiv');
I believe you might need to add a closure for the eventListeners to work.
So this would be considered as a solution:
var el = document.getElementsByClassName('applications');
var i;
for (i = 0; i < el.length; i++) {
(function (i) {
el[i].addEventListener("click", function() {
if (el[i]) {
el[i].classList.add('openDiv');
}
});
})(i);
}

Loop through a set of elements jQuery [duplicate]

This question already has answers here:
jQuery Looping and Attaching Click Events
(4 answers)
Closed 7 years ago.
I'm trying to loop through 12 classes, named .video-link0 through video-link11, where each one gets the treatment:
$('.video-link[n]').click(function() {
$('.video-link[n]').addClass('show');
});
Essentially, I want the following behavior:
When .video-link1 is clicked, addClass('show') to video-link1
When .video-link2 is clicked, addClass('show') to video-link2
and so on, as if I had 12 functions that looked like this:
$('.video-link1').click(function() {
$('.video-link1').addClass('show');
});
$('.video-link2').click(function() {
$('.video-link2').addClass('show');
});
... and so on
I want to write a single loop that replaces the need to write this out as 12 separate cases.
The following does not yield the result I'm looking for:
var elems = 12;
for(var i = 0; i < elems; i++){
$('.video-link' + i).click(function() {
$('.video-link' + i).addClass('show');
});
};
** UPDATE **
This is not a duplicate question, or else the above question referenced does not address my requirement. I am not trying to move up and down the DOM with next. Rather, I want to write a single loop that iterates through 12 classes numbered 0-11 using i to enumerate the cases.
** UPDATE **
This works for me, and is using a suggestion by Lloyd Banks (I needed the i enumerator PLUS the this keyword):
for (var i = 0; i < 12; i++) {
$('.video-link'+i).click(function() {
$(this).addClass('show');
});
}
You can use starts with ^= selector and reference each with $(this)
$("[class^='video-link']").click(function() {
$(this).addClass('show');
});
You can use $(this) to reference the current (targeted) element inside of a event callback:
$('.video-link').click(function() {
$(this).addClass('show');
});
You can use
function(numberOfElements){
for(var i = 1; i <= numberOfElements; i++){
$('.video-link' + i).on('click', function(){
$(this).addClass('show');
});
}
}
You should also be using the .on binding event instead of .click. If you are generating your element after initial page load and use .click, the event handler wouldn't be registered.

Add onclick event to array items [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I'm trying to iterate over an array and apply an onclick event to each item. I'm hoping to be able to click each of my divs and have them console log their value. Right now I'm stuck on how to apply the onclick to each div. I'm new to JS, so I'm not completely of why I shouldn't make a function inside of a loop like JSBin is complaining about. I've messed around with a lot of different ways to do this, but am truly stuck...
JSBin
function numberTrack() {
var gridItems = document.getElementsByClassName("grid");
for (var i = 0; i < gridItems[0].length; i ++) {
gridItems.onclick = function(){
alert("hello");
};
}
}
numberTrack();
var c = document.getElementsByClassName("divs"); <--- array of divs
for (var i = 0; i < c.length; i++) {
c[i].onclick = function() {
console.log(this.value);
}
}
JSBin is complaining because it wants you to declare the function outside the for loop and then assign it inside the for loop. This is more efficient then what you are currently doing, which is assigning a new anonymous function to each item in the array. All those identical functions will have to be created and stored separately in memory.
You can do something like this instead:
function alertHello() {
alert("hello");
}
for (var i = 0; i < gridItems.length; i++) {
gridItems[i].onclick = alertHello;
}
You need to loop through all the items in the gridItems collection, And inside the loop, get each item using the iterator i value.
function handleClick()
{
alert("hello");
}
function numberTrack() {
var gridItems = document.getElementsByClassName("grid");
for (var i = 0; i < gridItems.length; i ++) {
gridItems[i].onclick = handleClick;
}
}
numberTrack();
If you are allowed to use jQuery, you can bind the event to items like this.
$(function(){
$(document).on("click",".grid",function(e){
var item =$(this);
alert(item.html())
})
})
Here is a working jsBin sample

Javascript get dynamically set data-* attribute [duplicate]

This question already has answers here:
Javascript infamous Loop issue? [duplicate]
(5 answers)
Closed 8 years ago.
Let's say I have multiple elements with the class game_join_a, with their respective data-tbl attributes set dynamically from a database. I want to retrieve those atrributes to further use them in my code.
The code I'm using below returns tells me that a[i] is undefined.
a = document.getElementsByClassName("game_join_a");
for(i = 0; i < a.length; i++){
a[i].addEventListener("click", function(){
console.log(a[i].getAttribute("data-tbl"));
});
}
a = document.getElementsByClassName("game_join_a");
for(i = 0; i < a.length; i++){
a[i].addEventListener("click", function(){
console.log(this.getAttribute("data-tbl"));
});
}
this refers to the element that the click event is binded to. If you're dynamically adding the elements rather than just the data- attributes, you could also try this:
var a = document.getElementById('game_join_container'); // just something that contains all the elements that will be dynamically added
a.addEventListener('click', function (event) {
// check to see if original element clicked is a "game_join_a" element first
if(event.target.classList.contains('game_join_a')) {
console.log(event.target.getAttribute('data-tbl'));
}
});
Try this
var a = document.getElementsByClassName("game_join_a");
for(i = 0; i < a.length; i++) {
a[i].addEventListener("click", function (e) {
console.log(e.currentTarget.getAttribute("data-tbl"));
}, false);
}
Example

Categories