Reputation: 223
Some background: I've been working on a Dark Souls II statistical calculator. I have a table with buttons that will allow you to either add or subtract a value to any of the primary stats. This will then update the stats on the page, which will eventually tell you how many souls (experience points) you need to get to that soul level.
Anyway, I want to use pure Javascript to addEventListeners to each of the buttons to achieve this goal. The problem is, I have been adding them with several different calls and I was just curious if there was a more efficient way about doing this. The following code samples will show you my verbose solution, which I'm fairly certain can be trimmed down for brevity. If you can answer my question in pure Javascript it would be regarded higher than with jQuery, but if you come up with a jQuery solution I would still be very appreciative. I think an elegant solution to this problem is quite possible, but I am at a loss.
Here is a code sample with three buttons.
HTML snippet (this is obviously within the body tag):
<tr id="rowVigor">
<td>Vigor</td>
<td id="baseVIG">0</td>
<td class="increased" id="increasedVIG">0</td>
<td id="currentVIG">0</td>
<td><input type="button" value="-" class="buttonSubtract" id="minusVIG"/></td>
<td><input type="button" value="+" class="buttonAdd" id="addVIG"/></td>
</tr>
<tr id="rowEndurance">
<td>Endurance</td>
<td id="baseEND">0</td>
<td class="increased" id="increasedEND">0</td>
<td id="currentEND">0</td>
<td><input type="button" value="-" class="buttonSubtract" id="minusEND"/></td>
<td><input type="button" value="+" class="buttonAdd" id="addEND"/></td>
</tr>
<tr id="rowVitality">
<td>Vitality</td>
<td id="baseVIT">0</td>
<td class="increased" id="increasedVIT">0</td>
<td id="currentVIT">0</td>
<td><input type="button" value="-" class="buttonSubtract" id="minusVIT"/></td>
<td><input type="button" value="+" class="buttonAdd" id="addVIT"/></td>
</tr>
Javascript snippet:
window.onload = function()
{
//Global event listeners - Buttons
//VIGOR
document.getElementById("addVIG").addEventListener("click", function(){ addOne("increasedVIG"); }, false);
document.getElementById("minusVIG").addEventListener("click", function(){ minusOne("increasedVIG"); }, false);
//ENDURANCE
document.getElementById("addEND").addEventListener("click", function() { addOne("increasedEND"); }, false);
document.getElementById("minusEND").addEventListener("click", function() { minusOne("increasedEND"); }, false);
//VITALITY
document.getElementById("addVIT").addEventListener("click", function() { addOne("increasedVIT"); }, false);
document.getElementById("minusVIT").addEventListener("click", function() { minusOne("increasedVIT"); }, false);
}
//The functions calls and objects within these two functions are for updating statistical values.
function addOne(id)
{
console.log(id);
id = document.getElementById(id);
id.innerText = parseInt(id.innerText) + 1;
player.SoulLevel++;
updateAll();
}
function minusOne(id)
{
console.log(id);
id = document.getElementById(id);
if (parseInt(id.innerText) != 0)
{
id.innerText = parseInt(id.innerText) - 1;
player.SoulLevel--;
updateAll();
}
}
Now, the above code works, but the problem is that there are nine statistics (I only showed three) and it's getting very wordy. Is this the proper way to do something like this? Should I even be concerned?
Here's an idea I had that did not end up working...(Same HTML as above)
Javascript snippet:
//suffix has global scope
var suffix = ["VIG", "END", "VIT"];
window.onload = function()
{
for (var i = 0; i < suffix.length; i++)
{
document.getElementById("add" + suffix[i]).addEventListener("click", function(){ addOne("increased" + suffix[i]); }, false);
document.getElementById("minus" + suffix[i]).addEventListener("click", function(){ minusOne("increased" + suffix[i]); }, false);
}
}
When you click the plus or minus buttons, the console.log(id)
returns increasedundefined
, so I'm guessing you can't create event listeners this way. Any ideas?
Upvotes: 1
Views: 308
Reputation: 23873
Here is one option that you might find useful:
Note the use of the new data-*
attribute:
<div id="statsHome">
<tr id="rowVigor">
<td>Vigor</td>
<td id="baseVIG">0</td>
<td class="increased" id="increasedVIG">0</td>
<td id="currentVIG">0</td>
<td><input type="button" value="-" class="buttonSubtract" data-type="increasedVIG"/></td>
<td><input type="button" value="+" class="buttonAdd" data-type="increasedVIG"/></td>
</tr>
</div>
In this case, I'm going to loop and add to the buttons rather than using delegation. It was kind of a toss up, though, really.
function addHandler(button, mode) {
if (mode === "add") {
button.addEventListener("click", function() {
var stat = this.getAttribute("data-type");
addOne(stat);
}, false);
} else {
button.addEventListener("click", function() {
var stat = this.getAttribute("data-type");
minusOne(stat);
}, false);
}
}
var statsHome = docuemt.getElementById("statsHome");
var buttons = statsHome.getElementsByTagName("input");
for (var i = 0; i < buttons.length; i++) {
var button = buttons[i];
if (button.className === "buttonSubtract") {
addHandler(button, "subtract");
}
if (button.className === "buttonAdd") {
addHandler(button, "add");
}
}
Upvotes: 1
Reputation: 1907
Nothing is wrong with your code, other than not calling a named event handler function and a scope issue on your index variable within your current event handler
Upvotes: 0