Moron Test Part 3 – Adding an EventListener to your Icons

Which icon did I click, which one, which one!

Tutorial

You’ve been introduced to the process of attaching an event listener to a selected list of elements using a for loop. For example below, we select all of <li> elements and then listen for three different events: mouseover, mouseout, and click.

var toDos = document.querySelectorAll("li")

for (var i = 0; i < toDos.length; i++) {
    toDos[i].addEventListener("mouseover", function () {
        this.classList.add("hover")
    })
    toDos[i].addEventListener("mouseout", function () {
        this.classList.remove("hover")
    })
    toDos[i].addEventListener("click", function () {
        this.classList.toggle("complete")
    })
}

This was very effective way to have every element call the exact same functions for each event. But in our game the moron test, this isn’t going to work. We could select all the <i> elements we added to the DOM and attach an event listener with a for loop, but we would not be able to track which <i> element was clicked. And that’s a problem. We need to be able to set different icons to be clicked in a particular order. And the events for each click could differ. For example in scene 8:

The first correctly clicked <i> element causes the instructions to be removed, the second causes the icons to be rearranged, and any incorrectly clicked icon causes the fail screen to be displayed. So how do we do that?

The answer is arrays and array index values. We were introduced to “node lists” which are array-like objects created when we select a number of elements. What if we could change that node list into an array? And then we could take advantage of index values which are assigned to each selected element! Enter the Array.prototype and the call method. We can create a new empty array with Array.prototype, then “call” the selected node list object into that array. The array uses our forEach method giving us access to each element in the new array and it’s index value. Let’s see what that looks like:

var icons = document.querySelectorAll("i")

Array.prototype.forEach.call(icons, function (iconEl, iconIndx) {
    iconEl.addEventListener("click", function () {
         //do something
         console.log(iconEl, iconIndx)
    })
})

So now we can specify actions for specific icons clicked based on their index value. This is the key to creating the unique testing logic for each scene!

Problem Set

Create a function iconListener() that will add event listeners to all your <i> elements. The event is a “click” and the callback should hide (add the .hidden class) the clicked icon, as well as console.log the icon element and its index value.

***Bonus****

Create a function start(iconArr) that calls the three functions in sequence:

  • clearIcons()
  • mapIcons(iconsArr)
  • iconListener()

Blogging Questions

Why do we need to call the iconListener function after we’ve cleared the iconSpace and mapped our new icon <i> elements to that space? Why do we need to follow this three step process: clear <i> elements, add new <i> elements, add event listeners to <i> elements?

Leave a comment

Your email address will not be published. Required fields are marked *