For some inexplicable reason, I cannot convert this loop into a more natural for (var player in fizzPlayers) { ... }
loop:
for (var i = 0; i < fizzPlayers.length; i++) {
var player = fizzPlayers[i];
var val = parseInt(player.value);
if (val != 0) {
active.push(player);
actfact.push(parseInt(player.value));
actname.push(capitaliseFirstLetter(player.id));
}
}
I want to write this the more natural for-each way, like this:
for (var player in fizzPlayers) {
var val = parseInt(player.value);
if (val != 0) {
active.push(player);
actfact.push(parseInt(player.value));
actname.push(capitaliseFirstLetter(player.id));
}
}
But it doesn't work, as you can see in the runnable code snippet at the bottom.
For debugging, I inserted this code right before the loop:
// prints undefined... but why?
for (var player in fizzPlayers) {
console.log(player.value);
}
It prints undefined
for the 5 players. Why? There is a similar loop earlier in the program where the for (var player in fizzPlayers) { ... }
loop is working just fine.
Why is this happening? What am I missing?
var fizzLoaded = false;
var fizzDiv, fizzFrom, fizzTo, fizzPlayers;
function fizzLoad() {
if (fizzLoaded) {
return;
}
fizzLoaded = true;
var fizzForm = document.getElementById('fizzbuzz');
fizzFrom = document.getElementById('rangeFrom');
fizzTo = document.getElementById('rangeTo');
fizzPlayers = [
document.getElementById('frodo'),
document.getElementById('sam'),
document.getElementById('merry'),
document.getElementById('pippin'),
document.getElementById('bilbo')
];
fizzDiv = document.getElementById('fizzOut');
}
function restrictRange() {
var rFrom = parseInt(fizzFrom.value);
var rTo = parseInt(fizzTo.value);
fizzTo.min = rFrom;
fizzFrom.max = rTo;
}
function validateValues() {
var rFrom = parseInt(fizzFrom.value);
var rTo = parseInt(fizzTo.value);
if (rTo < rFrom) {
alert("Illegal range from " + rFrom + " to " + rTo);
return false;
}
for (var player in fizzPlayers) {
var val = parseInt(player.value);
if (val < 0 || val > 100) {
alert("Illegal value " + val + " for player " + player.id);
return false;
}
}
return true;
}
function capitaliseFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
function fizzing() {
fizzLoad();
restrictRange();
if (!validateValues()) {
fizzDiv.innerHTML = "Illegal inputs";
return;
}
var table = "";
var rFrom = parseInt(fizzFrom.value);
var rTo = parseInt(fizzTo.value);
var active = [];
var actfact = [];
var actname = [];
// prints undefined... but why?
for (var player in fizzPlayers) {
console.log(player.value);
}
for (var player in fizzPlayers) {
var val = parseInt(player.value);
if (val != 0) {
active.push(player);
actfact.push(parseInt(player.value));
actname.push(capitaliseFirstLetter(player.id));
}
}
table += "<table>\n";
table += " <tr><th>Value</th><th>Message</th></tr>\n";
for (var i = rFrom; i <= rTo; i++) {
var msg = "";
for (var p = 0; p < active.length; p++) {
if (i % actfact[p] == 0) {
msg += actname[p];
}
}
if (msg == "") {
msg = "" + i;
}
table += " <tr><td>" + i + "</td><td>" + msg + "</td></tr>\n";
}
table += "</table>\n";
fizzDiv.innerHTML = table;
}
h1 {
clear: left;
}
hr {
clear: left;
}
label {
display: inline-block;
float: left;
clear: left;
width: 150px;
text-align: left;
}
input {
display: inline-block;
float: right;
text-align: right;
padding-left:10px;
width: 50px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>FizzBuzz</title>
<link rel="stylesheet" href="fizzbuzz.css">
<script src="fizzbuzz.js" type="text/javascript"></script>
</head>
<body>
<h1>Config</h1>
<form id="fizzbuzz">
<fieldset id="fizzControl" oninput="fizzing();">
<label>Range From<input id="rangeFrom" type="number" min="1" max="100" value="1" required></label>
<label>Range To<input id="rangeTo" type="number" min="1" max="1024" value="100" required></label>
<div id="players" >
<label>Frodo<input id="frodo" type="number" min="0" max="100" value="3" required></label>
<label>Sam<input id="sam" type="number" min="0" max="100" value="5" required></label>
<label>Merry<input id="merry" type="number" min="0" max="100" value="0" required></label>
<label>Pippin<input id="pippin" type="number" min="0" max="100" value="0" required></label>
<label>Bilbo<input id="bilbo" type="number" min="0" max="100" value="0" required></label>
</div>
</fieldset>
</form>
<hr>
<h1>Output</h1>
<div id="fizzOut" >Change a value to get output (a snippet thing)</div>
<script>fizzing();</script>
</body>
</html>
The idiomatic way to write a loop that iterates over Array elements is forEach
. As comments have noted, for... in
is for Object keys, not Array elements.
fizzPlayers.forEach(function(player) {
var val = parseInt(player.value);
if (val != 0) {
active.push(player);
actfact.push(parseInt(player.value));
actname.push(capitaliseFirstLetter(player.id));
}
});
You can Array.prototype.forEach
in all modern browsers (IE9 +).
MDN docs
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With