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.
Related
This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Javascript infamous Loop issue? [duplicate]
(5 answers)
Closed 2 years ago.
I am adding some JS to an HTML, and I have a fragment of code similar to this:
<script>
function ButtonAction(index){
alert("My index is: "+index);
if(window_big){
// Use index to do something
}
else{
// Use index to do something else
}
}
function WindowResize(){
if(window.innerWidth > 1200){
window_big = true;
}
else{
window_big = false;
}
}
var window_big;
if(window.innerWidth > 1200){
window_big = true;
}
else{
window_big = false;
}
buttons = document.getElementsByClassName('MyButtons')
var i;
for (i = 0; i < buttons.length; i++) {
alert(i);
buttons[i].addEventListener("click",function(){ButtonAction(i);},false);
}
window.onresize = WindowResize;
</script>
The idea can be summarized like this:
There is a series of buttons in the page, stored in buttons[].
If the window is bigger than a certain size, those buttons should do one action, and if not, do another one.
To do said actions, I need the button[x].id. In fact, the initial intention was to set the listener to:
buttons[i].addEventListener("click",function(){ButtonAction(i);},false);
The problem is that I cannot retrieve the id, because the argument passed in the event listener seems to be always the last value i was set to.
May I ask for some help, please?
This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
JavaScript Puzzle: Scope
(6 answers)
Closed 7 years ago.
I hope the title makes sense.
I am using a for loop to create one or more $(document).on() elements. Inside each $(document).on() element created, I need it to call a function foo(currentIndex) where the currentIndex is the value of the index at the time of the .on() definition.
Fiddle: https://jsfiddle.net/xLbses7w/
JavaScript/jQuery:
var event = ['click', 'click'];
var element = ['#someId', '#someId2'];
for (i = 0; i < event.length; i++)
{
$(document).on(event[i], element[i], function ()
{
foo(i); // would like this to be the value of i when the function was created
});
}
function foo(arg)
{
alert(arg);
}
HTML:
<div id="someId">div1</div> <br/>
<div id="someId2">div2</div>
The problem: When I click on the element using the .on() function I have created, it uses the latest value of i (which in this case is 2).
Desired Behavior: When I click on div1, it should alert 0, and when I click on div2 it should alert 1 (the current indexes at the time of .on() definition.)
You can use .data() to store the index value
$(element[i]).data('index', i);
$(document).on(event[i], element[i], function () {
foo($(this).data('index'));
});
DEMO
You can create a closure:
for (i = 0; i < event.length; i++) {
(function (i) {
$(document).on(event[i], element[i], function () {
foo(i); // would like this to be the value of i when the function was created
});
})(i);
}
-DEMO-
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
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
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Javascript infamous Loop problem?
For some reason I get "6" inside my function here for every div element:
for(var i = 1; i <= 5; i++){
$('<div class="e-' + i + '"></div>').appendTo(something).click(function(){
alert(i); // <-- it's 6. wtf??
});
}
instead of 1, 2, 3, etc.
The class on the other hand it appears to be correctly set..
What am I doing wrong?
Your for loop is being executed at page load time. The alert only fires when there's a click event which is happening after the for loop has finished. Hence the value of i is now 6.
1) Page loads, for loop does its stuff...
2) Sometime later a click event is fired. the value of i at this time is 6 because the forloop has already completed.
The problem is that you need to create a closure to capture the value of i at the time you bind the click function.
Try this:
for(var i = 1; i <= 5; i++)
{
$('<div class="e-' + i + '"></div>')
.appendTo(something)
.click(function(value)
{
return function() { alert(value) };
}(i));
}