count
is increasing by more than one each time there is a click on #next
because you are adding multiple anonymous listeners to the click
event of the #next
element. Each of those functions is independently adding 1
to count
. Thus, when #next
is clicked, count
goes up 1 for each anonymous listener you have added to the click
event on the #next
element.
Every time there is a click on #submit
and $('#value').val() == words[randomNumber][1]
you execute:
$('#next').click(function(){
count = count + 1;
$('#score').text(count);
nextQuestion();
});
This results in a new anonymous function being added as a listener to the #next
element's click
event in addition to any ones already listening for that event. Thus, each time there is a click
event on #next
tehre are multiple functions called which each increases the count
by 1. The total amount of the increase for each click on #next
depends on how many functions you have listening to that event.
You have the same problem with the click
event for the #submit
element. This causes count
to increase even further by adding even more listeners to the click
event of the #next
element. The first time #submit
is clicked one listener is added. On the the second #submit
click two listeners to the #submit
click
event each add another listener to the #next
click
event making a total of 3 listeners on that event. Thus, count
goes up by 3. This continues to scale as you add more and more listeners to each event.
Have your code add the event listeners only once
The solution to this is to only assign those click events once:
$('#submit').click(function(){
if ($('#value').val() == words[randomNumber][1])
{
$('#result').text("You are correct, well done");
$('#submit').hide();
$('#next').show();
}
else
{
$('#result').text("That is incorrect, try again");
count = 0;
$('#score').text(count);
}
});
$('#next').click(function(){
count = count + 1;
$('#score').text(count);
nextQuestion();
});
function nextQuestion(){
$('#submit').show();
$('#next').hide();
$('#result').text('');
$('#value').val('');
randomNumber = Math.floor((Math.random() * words.length));
$('#englishWord').text(words[randomNumber][0]);
}
Alternately, use a named function and rely on addEventListener()
to ignore your attempts to add identical listeners.
An alternate solution is to use a single named function, which is defined in a scope such that it is not redefined each time the code adding it is called. Listeners which are not added using event attributes (e.g. <div onclick="doSomething();">
) are added using addEventListener()
(jQuery uses this method inside the various methods it provides for adding event listeners). If you try to add the same function, using the same values for the other parameters to addEventListener()
, then the additional listeners are discarded. That means that even if you try to add the same function, with the same parameters, more than once, it will only be called once per event. With an anonymous function, the function is separately defined each time that code is run. Thus, while the code is the same, the function that is defined is separate from any prior time the code has run. As a result, multiple copies get added.
However, just because the function has a name does not mean that it is defined in a scope that will result in it not being redefined each time it is added. For instance, in the above code, if the function for the #next
listener was defined within the #submit
listener, and even if it had a name, it would still be redefined every time the #submit
listener was run. To prevent the function from being redefined, the key is how and where the function is defined, not just that it is a named function. However, in order to refer to that function it must have a name, or otherwise be associated with a variable. Thus, you will generally find that there is an assumption made when someone says a "named function" that it is defined in a way that it is not, normally, redefined.