codingYogi codingYogi - 2 months ago 22
Javascript Question

JavaScript Help, assign user input values to an array then to an UL

I am a student and this is a homework assignment for my JavaScript class, I have to make the following code work, it should take five places entered from the user and assign them to an array. Then display them in the list on the page. When I started it was not functional. It currently will only take 4 entries and displays only the first 3 on the list. It should take 5 entries and display 5 entries. I have tried to change the if statement that iterates the counter but it still only takes 4 places. I suspect something is out of order, or not numbered correctly. Any help would be greatly appreciated!

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Hands-on Project 4-3</title>
<link rel="stylesheet" href="styles.css" />
<script src="modernizr.custom.05819.js"></script>
</head>

<body>
<header>
<h1>
Hands-on Project 4-3
</h1>
</header>

<article>
<div id="results">
<p id="resultsExpl"></p>
<ul>
<li id="item1"></li>
<li id="item2"></li>
<li id="item3"></li>
<li id="item4"></li>
<li id="item5"></li>
</ul>
</div>
<form>
<fieldset>
<label for="placeBox" id="placeLabel">
Type the name of a place, then click Submit:
</label>
<input type="text" id="placeBox" />
</fieldset>
<fieldset>
<button type="button" id="button" onclick="processInput()">Submit</button>
</fieldset>
</form>
</article>
<script>
var places = []; // new array to store entered places
var i = 1; // counter variable to track array indexes

// function to add input to array and then generate list after 5th submission
function processInput() {
places[i] = document.getElementById("placeBox").value; // add entered value to array
document.getElementById("placeBox").value = "" // clear text box
if (i < 6) { // iterate counter variable
++i;
}
else { // add entered value to array and write results to document
document.getElementById("resultsExpl").innerHTML = "You entered the following places:";
var listItem = "";
for (j = 1; j < 6; j++) { // write each array element to its corresponding list item
listItem = "item" + j;
document.getElementById(listItem).innerHTML = places[j];
}

}

// add backward compatible event listener to Submit button
var submitButton = document.getElementById("button");
if (submitButton.addEventListener) {
submitButton.addEventListener("click", processInput, false);
} else if (submitButton.attachEvent) {
submitButton.attachEvent("onclick", processInput);
}
}
</script>
</body>
</html>

JCD JCD
Answer

There are several issues I see. The biggest one which is probably tripping you up is the fact that processInput() is running twice every time you click the submit button.

First you assign an event handler inline the HTML itself:

<button type="button" id="button" onclick="processInput()">Submit</button>

onclick="processInput()" assigns that click handler when it parses the HTML. So later on when you do this:

  // add backward compatible event listener to Submit button
  var submitButton = document.getElementById("button");
  if (submitButton.addEventListener) {
    submitButton.addEventListener("click", processInput, false); 
  } else if (submitButton.attachEvent)  {
    submitButton.attachEvent("onclick", processInput);
  }
  }

You're actually adding another duplicate event handler to the button's onclick, causing processInput() to run twice with every click. That causes the array to be filled with some unexpected values.

Another issue is the fact that the above block of code (adding the event listener in JavaScript) is inside of processInput() itself. So this is what happens:

  1. HTML adds event listener to the onclick.
  2. First time the button is clicked, processInput() runs once. processInput() adds a duplicate event listener to the onclick.
  3. Subsequent button clicks fire processInput() twice; once from the HTML and once from the JavaScript.

In conclusion, pick one or the other. Either add the event listener inline in HTML or do it in JavaScript, not both. If you do it in JS, certainly make sure that the code that adds the event listener isn't inside of the function it's adding. Put it in the global context.

There are a couple of other small problems I see but you should be able to figure them out once you fix the event listener issues. A word of advice: when debugging your code it's helpful to add console.log() in certain places so that you can see the state of your variables and track down what is going wrong where.