JavaScript I – Day 10

Geekwise Academy

 

 

Instructors:

Corey Shuman

Aaron Lurz

 

 

Slack Channel:

https://geekwise-js1.slack.com

Github:

https://github.com/coreyshuman/Geekwise-JavaScript-I

Lesson plans:

http://coreyshuman.github.io/Geekwise-JavaScript-I/html/

 


 

Today’s Topics

·        Review Day 9 DOM and assignment

·        Handling Events

o   Event Listeners

o   Working with Forms

o   Submit Event

o   Working with radio buttons and check boxes


Event Listeners

 

In JavaScript, Event listeners are how we can react to user interaction on the page. For instance, alert something to a user when they try and delete an element, or run an arbitrary JavaScript function when a user clicks a button.

The DOM has built in methods that allow for registering "handlers" for a given "event", like click or mouse over.

Let's start by creating a simple html page with a button. We'll assign an event handler to the button.

    
        <button id="alert">Alert something</button>
    

 

Now that we have a button we can add a click handler for, let's actually add the listener. We will use the element.addEventListener(event, handler) function where event is a string for a named event, and the handler is a function to call when the event happens. In this way, the function is referred to as a callback.

Try it: Add the button markup, and write some JS that will select the button, and then use the button to add an event listener.

    
        var button = document.getElementById("alert");
 
        button.addEventListener("click", function () {
        alert("hello world");
        console.log(this); //what is the context to our callback function?
        });
    

 

Now, if you've added the button markup and run that JavaScript, you should now be able to click on the button and see an alert. Notice the console.log there? What is the this of the function?

In callbacks, it's usually the case that the context will be the node element itself.

Let's make this a little more dynamic. Add an attribute to your button called rel="..."

    
        <button id="alert" rel="This is some text">Alert something</button>
    

 

Use that new rel attribute as the content of our alert. Since we know that the context of our function is going to be the node itself, we can use all of our node related functions on this object.

Try it: Use the this inside your callback to get the attribute value and alert that instead of the hard coded text.

    
        var button = document.getElementById("alert");
 
        button.addEventListener("click", function () {
            alert(this.getAttribute("rel"));
        });
    

 

Use what we've learned to add p nodes with a rel attribute. Then use the addEventListener to handle clicks on the p tags. Alert the rel attributes for each p that is clicked on.

    
        //loop our movie array and create one li for each movie,
        //with the title as the text
        movieObjs = [
            {title: "Star Wars"},
            {title: "Inception"},
            {title: "The Matrix"}
        ];
        for (var i = 0; i < movieObjs.length; i++) {
            var movie = movieObjs[i];
            var a = document.createElement("p");
            a.textContent = movie.title;
            a.setAttribute("rel", movie.title);
            a.setAttribute("style", "color:red;");
            a.addEventListener("click", function () {
                alert(this.getAttribute("rel"));
            });
 
        document.body.appendChild(a);
        }
    

 

The above modification will add a rel attribute to our p nodes that will track the movie title, and the new event listener will listen for click events and run the specified callback which will alert the rel attribute.

There are many more event types you can have element's listen for, and many that are used specifically with forms. We'll talk about those next...

Working with forms

Forms in HTML are a perfect way to collect information from someone interacting with your webpage. Until now, we've used prompts as a way of collecting data, but prompts are clunky which makes a form a much more attractive alternative. Form usages vary widely based on the type of information you're collecting, and which form elements you decide to work with.

Start with a simple text input that will allow us to input a movie title.

    
        <form name="newMovieForm" id="newMovieForm">
            <input type="text" name="movieTitle" id="movieTitle" />
            <input type="submit" value="Add Movie" />
        </form>
    

 

Notice, we've added id's to our form and our input. This is going to make it easy to work the form fields in JavaScript.

Also, notice that our form tag lacks an action or method attribute you may be familiar with. This is because we aren't actually going to be submitting this form in a traditional way. We'll be using JavaScript to work with the form, meaning there won't be a traditional submit needed.

The Submit Event

So, just like we added a click event to our tags in the previous exercise, there are other events we can listen for and react to with JavaScript. One of these is the submit event of an HTML form.

This works like you would probably expect. We get a reference to our form, add a submit event listener, then write a callback function to handle processing our form.

To start with, our goal will be to alert the movie title entered in the form when we click the submit button. To do this, we need to know how to get the value from a form field. We use the value property for this.

    
        document.getElementById("movieTitle").value;
    

Enter a value in the field and then run the above code in the console. The result should be the value you entered in the field.

Now that we know how to get the value of a form field, let's add an event handler that will alert the value of the movie title field when the form is submitted.

    
        var form = document.getElementById("newMovieForm");
 
        form.addEventListener("submit", function () {
            var movie = document.getElementById("movieTitle").value;
            alert(movie);
        });
    

 

Now, enter a value in your form field, and click submit. What happens? What result did you get? What happened after you dismissed the alert?

You should have seen your form was submitted. Well, that's not very useful, since as soon as the form is submitted, all the JavaScript we were executing will be refreshed, and everything starts over from scratch. Wouldn't it be great if we could somehow stop that page refresh from happening?

This is where the event object becomes really useful. The event listener callback that we've been working with actually receives one argument. We've not used it thus far, but when the callback is run, it's passed the event object as an argument.

The event object contains properties and functions related to the event that occurred, a submit event in this case.

It also contains functions that allow us to alter how the event continues after our callback function has run. One particularly useful is the evt.preventDefault() function.

The preventDefault() function does exactly what it says, it prevents the default behavior from occurring. That means is we are working with a submit event, the preventDefault function would prevent the submit from happening, making our callback function the only way to work with this form, as it will no longer submit. Let's try it!

    
        //notice the evt argument now being passed to the event listener callback
        var form = document.getElementById("newMovieForm");
 
        form.addEventListener("submit", function (evt) {
            var movie = document.getElementById("movieTitle").value;
            alert(movie);
            evt.preventDefault();
        });
    

So now we get our movie title alerted, but the form no longer submits. Success!

Working with radio / checkboxes

Radio buttons let you select one option from a group items. The name attribute on a group of radio buttons is always the same.

Add a "genre" radio group with a few options.

    
        <form name="newMovieForm" id="newMovieForm">
          <input type="text" name="movieTitle" id="movieTitle" />
          <div id="genre">
            <input type="radio" name="genre" value="comedy" /> comedy<br />
            <input type="radio" name="genre" value="drama" /> drama<br />
            <input type="radio" name="genre" value="horror" /> horror
          </div>
          <input type="submit" value="Add Movie" />
        </form>
    

We can't use getElementById to get our radio inputs, but the DOM does give us some other methods we can use to work with them.

document.getElementsByName(...) can be used in order to select an element by its name attribute, which is perfect for radio buttons, since they always have the same name.

    
        var genreInputs = document.getElementsByName("genre");
        console.log(genreInputs);
    

 

What does genreInputs look like in the console? An array! Does it have a length? Yes! We can loop it!

In order to find out which option from a radio group was selected, we need to look at the checked property of each radio.

Try it: Loop the genre inputs and find which element is checked by looking for the checked property on each element.

    
        var genre;
 
        for (var i = 0; i < genreInputs.length; i++) {
          var genreInput = genreInputs[i];
          if (genreInput.checked) {
            genre = genreInput.value;
          }
        }
 
        console.log(genre);
    

 

The loop above will interrogate each radio element and see if it's checked. If it is, it sets the genre variable equal to the current radio elements value.

One important thing to remember is that radio elements are only meant to return one value.

 

 

 


Assignment

  1. Continue work on final project. Now we can start adding event handlers to the ToDo application.
    1. When the submit button is clicked on your ToDo form, get the user input and add it to an array
    2. Create a function that will clear out the list and loop over the array to print out all of the ToDo items.
    3. Each ToDo item should have a button to delete the item and a checkbox to mark the item as finished by using strikethrough on the text like this.

                                                               i.      Hint: there are ways to have events for many items be handled by a single function instead of writing an event handler for each and every tag. We will cover this next week.