self executing anonymous click function in for loop - javascript

I need a click function in a for loop, so every id element is clickable. But I also need the i in the click function, that's why I thought a self executing anonymous function would be the best way to do so. But for some reason this is not working, maybe because the click function doesn't allow me to forward a parameter? What have I done wrong?
for (var i = 0; i < countItems; i++) {
$("#item-" + i).click(function(idx) {
alert(idx);
})(i)
}

The self executing function must return a function:
for (var i = 0; i < countItems; i++) {
$("#item-" + i).click(function(indx){
return function(){ //must return a function
alert(indx);
}
}(i));
}
JS Fiddle: http://jsfiddle.net/HuHXr/

As a side note, using bind() javascript method:
for (var i = 0; i < countItems; i++) {
$("#item-" + i).click(function(indx){
alert(indx);
}.bind($("#item-" + i)[0],i));
}

you can try something like this
for (var i = 0; i < countItems; i++) {
$("#item-" + i).click(clickFunctn);
}
function clickFunctn(obj){
var i=$(obj).attr('id').split('-')[1];
alert(i);
}
In this way you will optimize the code and your 'i' will be with you as well, and all items are clickable. And you are just binding one handler function.

for (var i = 0; i < countItems; i++) {
(function(i){
$("#item-" + i).click(function(idx) {
alert(idx);
});
})(i);
}
Also note that idx is the event object.
Fiddle: http://jsfiddle.net/2DRLx/

Related

How to increment a number within a variable name in jQuery

I have this javascript for loop:
for (var i=1; i <= 2; i++) {
$(".afterglowplayer"+i).click(function () {$.afterglowplayer+i.toggle(this); return false;});
}
I need to increment the number at the end of a jQuery variable name so that I get this:
$.afterglowplayer1.toggle(this);
$.afterglowplayer2.toggle(this);
I have tried using
$.afterglowplayer+i.toggle(this);
and
$.afterglowplayer+"+i+".toggle(this);
But it is not correct way... is it possible to increment the number at the end of a jQuery variable name?
You can use the let keyword
for (let i=1; i <= 2; i++) {
$(".afterglowplayer"+i).click(function () {
$('.afterglowplayer'+i).toggle(this);
return false;
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='afterglowplayer1'>Foo</div>
<div class='afterglowplayer2'>Bar</div>
Read up on JavaScript closures.
for (var i=1; i <= 2; i++) {
(function(n) {
$('.afterglowplayer'+n).click(function () {
$('.afterglowplayer'+n).toggle(this); return false;
});
})(i);
}
$['afterglowplayer'+i].toggle(this);

Pass Argument to EventListener function

I'm building a simple calculator app. I'm trying to accomplish three things:
Assign an event listener to the buttons.
When the button is clicked, fire an event.
Use the eventListener function to display the value of the clicked button.
for (i = 0; i < btn.length; i++) {
var btnVal = btn[i].value;
btn[i].addEventListener("click", function() { displayNumber(btnVal) }, false);
}
function displayNumber(param) {
displayedNum.innerHTML = param;
}
It seems btnVal is not accessible when passed to the event listener function.
The assignment won't work like that. Instead, use the target's value
for (i = 0; i < btn.length; i++) {
btn[i].addEventListener("click", function(e) {
displayNumber(e.target.value)
}, false);
}
Defining event listeners (or other asynchronous things) inside of a loop is tricky. You may think you're creating several different btnVal variables, one for each time through the loop, but you're not. That var btnVal gets hoisted to the top and reused, so your code ends up behaving like this:
var btnVal;
for (i = 0; i < btn.length; i++) {
btnVal = btn[i].value;
btn[i].addEventListener("click", function() { displayNumber(btnVal) }, false);
}
So all of your event listeners are interacting with the very same variable, and when they eventually get clicked, they'll only see the very last value that was assigned to btnVal, which should be btn[btn.length -1].value. All the values earlier in the array are lost.
There are a few ways you can address this:
1) Rather than depending on a closure variable, you could pull it from the element itself when the event goes off.
for (i = 0; i < btn.length; i++) {
btn[i].addEventListener("click", function (event) {
displayNumber(event.target.value);
});
}
2) Move the event listener creation into a function, and pass btnVal in. Since it's now a function parameter, it gets a new binding.
for (i = 0; i < btn.length; i++) {
createListener(btn[i], btn[i].value);
}
function createListener(element, val) {
element.addEventListener("click", function () { displayNumber(val) }, false);
}
3) you can do it inline using an IIFE.
for (i = 0; i < btn.length; i++) {
(function (button) {
button.addEventListener("click", function () { displayNumber(button.value) }, false);
})(btn[i]);
}
EDIT: added option 4
4) If you can use ES2015, use let. Let has block scope, and will get a new binding each time through the loop
for (i = 0; i < btn.length; i++) {
let btnVal = btn[i].value;
btn[i].addEventListener("click", function() { displayNumber(btnVal) }, false);
}
You cant use btnVal inside the event.
It should look like this
for (i = 0; i < btn.length; i++) {
btn[i].addEventListener("click", function(event) {
var clickedButton = event.target || event.srcElement;
console.log(clickedButton.value)
}, false);
}

Give arguments to generic eventhandler

I'm creating a bunch of elements with a generic onclick event like
function foo( i , j ) {
alert("foo");
//dostuff
};
for (i = 1; i < 8; i++){
var clas = get_class_for_index( i );
for ( j = 0; j < 96; j++){
// tbody > #(i) is a <tr>
$("#table > tbody > #" + i ).append( function(){
// I want to give ( i , j ) to foo
return $("<td id='" + j + "' class='" + clas + "'></td>").on("click", foo );
});
};
};
So, how could I give these arguments to foo? I could also use the IDs of and due they're (i,j) but how do I get them from inside foo?
You need to use closure with IIFE here, otherwise because of the scoping you will end up passing the last iterated value of i or j to the event handler.
Something like this:
var $anchors = $("a");
function foo(idx) {
alert("foo " + idx);
};
for(var i = 0; i < $anchors.length; i++) {
$anchors.eq(i).on("click", (function(i) {
return function(e) {
foo(i);
}
}(i)));
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Link | Link | Link | Link
In the above example, we are using a function that is immediately executed (with i as a parameter) and returns a function which will then be bound as the click handler and pass the correct i to your foo. This is called an IIFE (immediately-inoked function expression).
Can I pass parameters to event Handler?
No you cant. The event handler function executes when the event occurs, You are not calling foo() to pass i and j, foo() will get executed even after for loop execution finishes and there will not be any existence of i & j.
Then What can I do in my condition.
The best way is add i and j values to DOM element itself so you can access it in event handler function. You can use data() method of jQuery to add extra information to DOM.
function foo(evt) {
$(evt.currentTarget).data() //You will get here all values, i.e. i & j
//dostuff
};
for (i = 1; i < 8; i++) {
var clas = get_class_for_index(i);
for (j = 0; j < 96; j++) {
// tbody > #(i) is a <tr>
$("#table > tbody > #" + i).append(function() {
// I want to give ( i , j ) to foo
return $("<td id='" + j + "' class='" + clas + "'></td>").data({
i: i,
j: j
}).on("click", foo);
});
};
};
Here is updated fiddle.
You need to use jquery on function in order to register the event to the element once created, you can use the Id of the element to attach the event to it and call the foo in the event callback function.
I have added a working snipped that used a combined id with i and j as follows
function foo( i , j ) {
console.log(i+"_"+j);
alert(i+"_"+j);
//dostuff
};
for (i = 1; i < 8; i++){
var clas = "aa_"+i;
$("#table").append("<tr id='" + i + "'></tr>");
for ( j = 0; j < 96; j++){
// tbody > #(i) is a <tr>
$("#table > tbody > #" + i ).append( function(){
// I want to give ( i , j ) to foo
return $("<td id='test_" + i + "_" + j + "' class='" + clas + "'>aa</td>").on("click", function(){
var id = $(this).attr("id").split('_');
//console.log(id);
foo(id[1],id[2]);
} );
});
};
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="table"></table>
When using event handler you may use .on() of jquery for the event handler like this example.
$("#id").on("click", function(){
//do stuff here or call a function;
});
Reference: http://api.jquery.com/on/

Capturing counter value in Javascript closure [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 9 years ago.
The following code creates 10 elements under <body id="container" />. When i click on any element, I always see an alert with the value 10.
How can I get each alert to show the index of each element?
for (var i = 0; i < 10; ++i) {
var id = "#element_" + i;
$("#container").append('<p id="element_' + i + '">foo</p>');
$(id).click(function (e) {
alert(i);
});
}
You need either closure or simply use $.on() with data:
for (var i = 0; i < 10; ++i) {
var id = "#element_" + i;
$("#container").append('<p id="element_' + i + '">foo</p>');
$(id).on("click", i, function (e) { alert(e.data); });
}
Don't make functions inside for loops
for (var i = 0; i < 10; ++i) {
$("#container").append('<p id="element_' + i + '">foo</p>');
}
$("#container > p").click(function (e) {
var idNum = this.id.split('_')[1];
alert(idNum); // 0, 1, 2 ...
});
DEMO
need to create a private closure
for (var i = 0; i < 10; ++i) {
(function(idx){
var id = "#element_" + idx;
$("#container").append('<p id="element_' + idx + '">foo</p>');
$(id).click(function (e) {
alert(idx);
});
})(i)
}
Demo: Plunker

JavaScript set DOM object event dynamically on dynamically created DOM objects

The following script:
var containerDIV = document.getElementById("sampleContainer");
for(var i = 0; i < 5; i++)
{
var dynamicDIV = document.createElement("div");
containerDIV.appendChild(dynamicDIV);
dynamicDIV.onclick = function() { alert(i); };
dynamicDIV.innerHTML = "Row: " + i;
}
when clicking on the dynamically rows the output in the alert box will always be "5" instead of 0, 1, ..
Do anyone knows a proper way to assign the onclick event?
You should use the closure power:
for (var i = 0; i < 5; i++) {
(function(i) {
dynamicDIV.onclick = function() {
alert(i);
};
})(i);
}
DEMO: http://jsfiddle.net/zvPfZ/

Categories