How do I get "I" to increment inside a .click function - javascript

$('#x').click(function() {
var i=1;
$('#y').prepend('<div id='+i+'>x'+i+'</div>');
i++;
});
I want the i to increment, now for some reason it is not. I will agree this is a silly question.

Place var i before the click scope:
var i=1;
$('#x').click(function() {
$('#y').prepend('<div id='+i+'>x'+i+'</div>');
i++;
});

Try not to litter the global scope. This solution will encapsulate i, but still retain its value
$('#x').click((function() {
var i = 1;
return function () {
$('#y').prepend('<div id='+i+'>x'+i+'</div>');
i++;
}
})());
Example: http://jsfiddle.net/Hxw3q/

Related

alert -1 instead of their respective counter inside of the loop?

Why do the anchors, when clicked on, alert -1 instead of their respective counter inside of the loop? How can you fix the code so that it does alert the right number?
text<br>link
<script>
var as = document.getElementsByTagName('a');
for ( var i = as.length; i--; ) {
as[i].onclick = function() {
alert(i);
return false;
}
}
</script>
That's a closure problem: every anonymous function you define inside your loop reads the value of "i" at the end of the for loop.
You need another scope, for example calling a function that sets the onclick handler.
function add_onclick(el, i) {
el.onclick = function() {
alert(i);
return false;
}
}
var as = document.getElementsByTagName('a');
for ( var i = as.length; i--; ) {
add_onclick(as[i],i);
}
An alternative way to achieve the same result as Keeper's answer is to use a function expression for the closure, which you immediately invoke, using your value as a parameter to create the closure
var as = document.getElementsByTagName('a');
for ( var i = as.length; i--; ) (function (i) {
as[i].onclick = function() {
alert(i);
return false;
}
}(i));
This way requires minimal code refactoring
You are printing the value of variable i. After the loop, it's value is -1.

Keep the "i" value when adding functions to elements

My case:
var tds = document.getElementsByTagName("td");
for(i=0;i<tds.length;i++)
{
tds[i].onclick = function()
{
alert(i);
};
}
Expected outcome: Alert the number of TD.
However if there are 6 TDs, the returned value will always be the last value of "i". (6)
How could i make the "i" value to remain at it's value when added to the function?
Thanks!
http://jsfiddle.net/nuKEK/11/
You need to make a closure to capture the i value. Something like this
function createFunction(i){
return function(){
alert(i);
};
}
var tds = document.getElementsByTagName("td");
for(i=0;i<tds.length;i++){
tds[i].onclick = createFunction(i);
}
DEMO: http://jsfiddle.net/nuKEK/12/
You can pass i to another function in order to get its value rather than a reference to it. In javascript, numbers are passed by value.
tds[i].onclick = (function(x) {
return function() {
alert(x); // alerting x, i's value
};
})(i); // passing i as parameter x
If that self-executing anonymous function looks a little hairy in the context of your loop, you could try Array.prototype.forEach() instead:
[].forEach.call(document.getElementsByTagName("td"), function(td, i) {
td.onclick = function() {
alert(i);
};
});
[edit] Have a look at these options and their performance.
This is one of the common mistakes in Javascript in that it is not block scoped like most languages. It is function-scoped.
You need to create a closure around the onclick to achieve this.
for (i = 0; i < tds.length; i++) {
(function (index) {
tds[index].onclick = function() {
alert(index);
};
})(i);
}
var tds = document.getElementsByTagName("td");
for(i=0;i<tds.length;i++)
{
addClick(tds, i);
}
function addClick(where, i) {
where[i].onclick = function()
{
alert(i);
};
}
You will have to force the value into a scope that will still exist when the callback is fired.
for(i=0;i<tds.length;i++){
(function(){
var _i = i;
tds[i].onclick = function(){
alert(_i);
};
})();
}
Otherwise, the value for i will always be the last index

Variable scoping and event handler

Please see the jsfiddle:
http://jsfiddle.net/LsNCa/2/
function MyFunc() {
for (var i = 0; i < 2; i++) { // i= 0, 1
var myDiv = $('<div>');
myDiv.click(function(e) {
alert(i); // both the two divs alert "2", not 0 and 1 as I expected
});
$('body').append(myDiv);
}
}
var myFunc = new MyFunc();
I want the divs to alert "0" and "1" respectively when I click them, but both of them alert "2".
When I click the divs and the event is triggered, how and where do the handler find the value of the variable i?
I'm aware that adding a closure achieves my goal. But why?
function MyFunc() {
for (var i = 0; i < 2; i++) { // i= 0, 1
(function(j) {
var myDiv = $('<div>');
myDiv.click(function(e) {
alert(j);
});
$('body').append(myDiv);
})(i);
}
}
var myFunc = new MyFunc();
The code above is how you get it work correctly. Without an closure, you always the the last value of i. What we do is to post i into the closure and let the runtime "remember" the value of that very moment.
You need a closure because all your event handler functions are referencing the same variable i. The for loop updates this, and when the loop is done the variable contains 2. Then when someone clicks on one of the DIVs, it accesses that variable.
To solve this, each event handler needs to be a closure with its own variable i that contains a snapshot of the value at the time the closure was created.
I suggest that you read this article
JavaScript hoists declarations. This means that both var statements
and function declarations will be moved to the top of their enclosing
scope.
As #Barmar said in his answer above, the variable i is being referenced by both the event handlers.
You should avoid declaring functions inside loops. Below there is some code that does what you need.
I assume that you're using jQuery.
function MyFunc() {
for (var i = 0; i < 2; i++) { // i= 0, 1
var myDiv = $('<div>');
$('body').append(myDiv);
}
$('div').on('click', function() {
alert($(this).index());
});
}
var myFunc = new MyFunc();
The "alert()" call happens after the for-loop completed, which means that the value of "i" will be the last value for anything after that. In order to capture individual values of "i", you must create a closure for each value by creating a new function:
function MyFunc() {
function alertFn(val) {
return function () {
alert(val);
};
}
for (var i = 0; i < 2; i++) {
var myDiv = $('<div>');
myDiv.click(alertFn(i));
$('body').append(myDiv);
}
}
var myFunc = new MyFunc();
The closure captures the value of "i" at the time it was passed into the function, allowing alert() to show the value you expect.

Assigning onclick event to global variables - javascript

I have many divs with class "mypoll". Here is my js code:
var mypoll=[];
$(document).ready(function (){
mypoll=document.getElementsByClassName("mypoll");
});
for(var t=0; t<mypoll.length; t++) {
mypoll[t].getElementsByClassName("deletePoll")[0].onclick=(function() {
var currentI = t;
return function() {
deletedMyPoll(currentI);
};
})();
}
function deletedMyPoll(i){
var a=document.getElementsByClassName("mypoll")[0].innerHTML;
alert(a);
}
The error I get is
cannot set property onclick of undefined.
I have the exact same piece of code on my project (it is big and complicated and I can't post it all here) but it doesn't work.
It works on the jsfiddle though.
Is there any problem with the global variables in javascript? Can I use them that way?
jsfiddle.net/Vwtmu
Thank you
If you're going to use jQuery, you might as well use it:
$(".mypoll").on('click', '.deletePoll', function () {
});
The for loop runs before the dom is ready.
$(document).ready(function (){
mypoll=document.getElementsByClassName("mypoll");
for(var t=0; t<mypoll.length; t++) {
mypoll[t].getElementsByClassName("deletePoll")[0].onclick=(function() {
var currentI = t;
return function() {
deletedMyPoll(currentI);
};
})();
}
});

Why exectuing function doesnt work?

I have an input which when im clicking - i want to see alert with '1,2,3,4...' (each press)
<input type='button' value='press' onclick='Clicked();' />
<script>
var t
function Clicked()
{
t=func;
t();
}
function func()
{
var count=0;
return new function () // <=== new or not new ???
{
count++;
alert(count);
}
}
</script>
If im adding the 'new' in the return and click , it says : '1,1,1,1,...'
If im removing the 'new' it doesnt work...
My goal is to use this to get : '1,2,3,4...'
Can someone explain to me what happens ?
You need to use the returned function:
var t = func()
function Clicked() {
t();
}
function func() {
var count=0;
return function () {
count++;
alert(count);
}
}
Example
You have to put the count declaration out of the "func" function and into the global namespace. Like this:
var count=0;
function func() {
count++;
alert(count);
}
You're creating a new var count every time the clickevent fires.. You should place the var count = 0 outside the function as a global variable..
oh and btw, throw out the return stuff please this will work properly:
var count = 0;
function func()
{
count++;
alert(count);
}
And call this method like this: func();
You are getting 1,1,1,1 because you are redefining count every time you call func().
In your case you will need to either put the count variable in the global scope:
var t;
var count = 0;
or change the way you are doing things a little:
var t = 0;
function Clicked(){
t = func(t);
}
function func(count){
count++;
alert(count)
return count;
}
Personally I like the second one. You have less global variables, one less function declaration, and it is cleaner
var t
function Clicked()
{
t=func;
t();
}
var count=0;
function func()
{
return new function () // <=== new or not new ???
{
count++;
alert(count);
}
}

Categories

Resources