Lesson Tuesday

So far, the only way we've been able to capture user input is by using confirm() and prompt(). Let's learn about forms so that we can build more interesting pages.

Have you ever played Mad Libs? You're prompted to fill out a list of nouns, verbs, adjectives, etc., and then copy them onto another piece of paper that contains a story, missing those crucial words that you are now providing. The idea is to pick bizarre words without knowing what the story is, and then when you fill them in, the results can be hilarious.

Let's make a page that mimics the Mad Libs format:

mad-libs.html
<!DOCTYPE html>
<html>
  <head>
    <link href="css/bootstrap.css" rel="stylesheet" type="text/css">
    <link href="css/styles.css" rel="stylesheet" type="text/css">
    <script src="js/jquery-1.12.0.js"></script>
    <script src="js/scripts.js"></script>
    <title>A fantastical adventure</title>
  </head>
  <body>
    <div class="container">
      <h1>Fill in the blanks to write your story!</h1>
      <div>
        <form id="formOne">
          <div class="form-group">
            <label for="person1">A name</label>
            <input id="person1" class="form-control" type="text">
          </div>
          <div class="form-group">
            <label for="person2">Another name</label>
            <input id="person2" class="form-control" type="text">
          </div>
          <div class="form-group">
            <label for="animal">An animal</label>
            <input id="animal" class="form-control" type="text">
          </div>
          <div class="form-group">
            <label for="exclamation">An exclamation</label>
            <input id="exclamation" class="form-control" type="text">
          </div>
          <div class="form-group">
            <label for="verb">A past tense verb</label>
            <input id="verb" class="form-control" type="text">
          </div>
          <div class="form-group">
            <label for="noun">A noun</label>
            <input id="noun" class="form-control" type="text">
          </div>

          <button type="submit" class="btn">Show me the story!</button>
        </form>
      </div>

      <div id="story">
        <h1>A fantastical adventure</h1>
        <p>
One day, <span class="person1"></span> and <span class="person2"></span> were walking through the woods, when suddenly a giant <span class="animal"></span> appeared. "<span class="exclamation"></span>", <span class="person1"></span> cried. The two of them <span class="verb"></span> as quickly possible, and when they were safe, <span class="person1"></span> and <span class="person2"></span> gave each other a giant <span class="noun"></span>.
</p>
      </div>
    </div>
  </body>
</html>

Here, I've used some Bootstrap classes to make the form look nice; you can read more about them in the Bootstrap form documentation.

Let's make the story hidden to start:

styles.css
#story {
  display: none;
}

Now, our JavaScript needs to get the value from the form inputs, insert them into the <span>s where the information should go, and then un-hide the story itself. We know how to insert text into our pages, so let's get that working before we try to get the data from the form:

scripts.js
$(document).ready(function() {
  $("#formOne").submit(function() {
    $(".person1").append("blah blah");
    $(".person2").append("blah blah");
    $(".animal").append("blah blah");
    $(".exclamation").append("blah blah");
    $(".verb").append("blah blah");
    $(".noun").append("blah blah");

    $("#story").show();
  });
});

The submit() function attaches an event listener for when a form is submitted. It's different from the click() function because a form can be submitted by clicking the submit button, of course, but it can also be submitted by pressing Enter while a form field is selected.

But when we submit the form, the story briefly flashes and then disappears. What's happening is that, by default, forms try to send the information somewhere, and since we haven't told it where to submit to, the page just refreshes and erases our hard work. If you look in the URL bar, you can see that there's a ? at the end of the address now. This is your clue that the form has been submitted to nowhere and the page refreshed. We need to prevent the default action for the form:

scripts.js
$(document).ready(function() {
  $("#formOne").submit(function(event) {
    $(".person1").append("blah blah");
    $(".person2").append("blah blah");
    $(".animal").append("blah blah");
    $(".exclamation").append("blah blah");
    $(".verb").append("blah blah");
    $(".noun").append("blah blah");

    $("#story").show();

    event.preventDefault();
  });
});

Notice that we've added a parameter event to the callback function we passed to submit() method. When the form is submitted, jQuery runs the callback function and passes in something as an argument. We don't know what this "something" is - we just know that it somehow represents the event of the form being submitted, and so we give the parameter the name event. And we know that if we call the method preventDefault() on this event thing, it will stop the form from submitting.

This is a pretty confusing concept. If you aren't at least 70% clear on the previous paragraph, stop and re-read it, slowly and carefully. If you are at least 70% clear, come back and re-read it a couple more times after you finish this lesson. You might also re-visit the lesson on Writing functions, which includes an explanation of arguments and parameters.

Now, we need to actually get the values from the form. If we open up the JavaScript console on the page and run:

  • $("input#person1").val();

We can see that this jQuery method returns the value from the input as a string. Since the append() method takes a string as an argument, we can update our code like this:

scripts.js
$(document).ready(function() {
  $("#formOne").submit(function(event) {
    var person1Input = $("input#person1").val();
    var person2Input = $("input#person2").val();
    var animalInput= $("input#animal").val();
    var exclamationInput = $("input#exclamation").val();
    var verbInput = $("input#verb").val();
    var nounInput = $("input#noun").val();

    $(".person1").append(person1Input);
    $(".person2").append(person2Input);
    $(".animal").append(animalInput);
    $(".exclamation").append(exclamationInput);
    $(".verb").append(verbInput);
    $(".noun").append(nounInput);

    $("#story").show();

    event.preventDefault();
  });
});

Now our page works. Hooray!

There's one last thing to fix, though. If you don't refresh the page and you change the value of one of the inputs, it just adds it after the first value, instead of replacing it. We need to replace the existing text rather than just appending to it:

scripts.js
$(document).ready(function() {
  $("#formOne").submit(function(event) {
    var person1Input = $("input#person1").val();
    var person2Input = $("input#person2").val();
    var animalInput= $("input#animal").val();
    var exclamationInput = $("input#exclamation").val();
    var verbInput = $("input#verb").val();
    var nounInput = $("input#noun").val();

    $(".person1").text(person1Input);
    $(".person2").text(person2Input);
    $(".animal").text(animalInput);
    $(".exclamation").text(exclamationInput);
    $(".verb").text(verbInput);
    $(".noun").text(nounInput);

    $("#story").show();

    event.preventDefault();
  });
});

Example


Capture input when a form is submitted:

HTML Form:

<form id="some-form">
  <label for="some-input">Your input:</label>
  <input id="some-input" type="text">

  <button type="submit" class="btn">Submit!</button>
</form>

JavaScript to capture form information when form is submitted:

$("form#some-form").submit(function(event) {
  var someInput = $("input#some-input").val();

  event.preventDefault();
});

Replace text in an HTML element using jQuery:

$(".some-class").text("New text");

Tips


  • If you submit your form and then there's a ? at the end of the URL in your address bar, you forgot to put event.preventDefault();, or you attached your event listener to the wrong form.