1

Im trying to do homework assignment and confused why I'm getting error message(undefined is not an object (evaluating 'buttons[i].style')) any help appreciated Ive been trying to loop through the buttons array and add an Event Listener to each item in the list

var buttons = document.getElementsByClassName("quality");
for(var i = 0; i < buttons.length; i += 1){
buttons[i].addEventListener('click', function (i) {
    buttons[i].style.background = "red";
});
}



<!doctype html>

<html>
<head>
 <title>L.A. Hiking</title>
 <link rel="stylesheet" href="css/hiking.css">
 </head>

<ul id = "navbar">
    <li><a href="index.html" class= "selected">Home</a></li>
    <li><a href="contact.html">Contact</a></li>
    <li><a href="about.html">About</a></li>
</ul>
<body>

<div>
    <div class="blocks" id="selections">
        <ul id= "attr1">
            <li class="Instruction">Pick one:</li>
            <li class ="quality">Hard</li>
            <li class ="quality">Medium</li>
            <li class ="quality">Easy</li>
        </ul>

        <ul id = "attr2">
            <li class="Instruction">Pick one:</li>
            <li class ="quality">Hard</li>
            <li class ="quality">Medium</li>
            <li class ="quality">Easy</li>
        </ul>

        <ul id = "attr3">
            <li class="Instruction">Pick one:</li>
            <li class ="quality">Hard</li>
            <li class ="quality">Medium</li>
            <li class ="quality">Easy</li>
        </ul>
    </div>  
    <div class="blocks" id="results">
        <ul id = "choices">
            <li class="choice">Pick one:</li>
            <li class ="choice">Hard</li>
            <li class ="choice">Medium</li>
        </ul>
    </div>
</div>
<div id="button-container">
    <button>Go!</button>
</div>

<script src="javascript/hiking.js"></script>
</body>
</html>
0

3 Answers 3

1

The callback for addEventListener doesn't give you the index of the button clicked but an event object. You can then access the button using event.target:

for(var i = 0; i < buttons.length; i += 1){
    buttons[i].addEventListener('click', function (e) {
        e.target.style.background = "red";
    });
}

As per @Sgnl:

since you are binding to the event to the object itself you could also use context aka this so e.target.style.background = "red"; becomes this.style.background = "red";

for(var i = 0; i < buttons.length; i += 1){
    buttons[i].addEventListener('click', function () {
        this.style.background = "red";
    });
}
Sign up to request clarification or add additional context in comments.

2 Comments

Also, since you are binding to the event to the object itself you could also use context aka this so e.target.style.background = "red"; becomes this.style.background = "red";
This PhD guy nailed it, he saved my bus seater array
0
  1. document.getElementsByClassName("quality"); returns the collection of all the elements matching the class name quality in a NodeList object. From the code you posted, it seems that you are having the listitem and not the button element for the quality class name.

  2. More importantly, the addEventListener callback would pass in the event information in the parameter to the callback. The property event.target returns the element on which the event was registered, which in this case is the listItem[i]. So, you need to use the e.target as e.target.style.background = "red";

var listItems = document.getElementsByClassName("quality");
for(var i = 0; i < listItems.length; i += 1){
listItems[i].addEventListener('click', function (e) {
    e.target.style.background = "red";
});
}
<html>
<head>
 <title>L.A. Hiking</title>
 <link rel="stylesheet" href="css/hiking.css">
 </head>

<ul id = "navbar">
    <li><a href="index.html" class= "selected">Home</a></li>
    <li><a href="contact.html">Contact</a></li>
    <li><a href="about.html">About</a></li>
</ul>
<body>

<div>
    <div class="blocks" id="selections">
        <ul id= "attr1">
            <li class="Instruction">Pick one:</li>
            <li class ="quality">Hard</li>
            <li class ="quality">Medium</li>
            <li class ="quality">Easy</li>
        </ul>

        <ul id = "attr2">
            <li class="Instruction">Pick one:</li>
            <li class ="quality">Hard</li>
            <li class ="quality">Medium</li>
            <li class ="quality">Easy</li>
        </ul>

        <ul id = "attr3">
            <li class="Instruction">Pick one:</li>
            <li class ="quality">Hard</li>
            <li class ="quality">Medium</li>
            <li class ="quality">Easy</li>
        </ul>
    </div>  
    <div class="blocks" id="results">
        <ul id = "choices">
            <li class="choice">Pick one:</li>
            <li class ="choice">Hard</li>
            <li class ="choice">Medium</li>
        </ul>
    </div>
</div>
<div id="button-container">
    <button>Go!</button>
</div>

<script src="javascript/hiking.js"></script>
</body>
</html>

1 Comment

Also, since you are binding to the event to the object itself you could also use context aka this so e.target.style.background = "red"; becomes this.style.background = "red";
0

In addition to everyone suggesting attaching an event to each li.quality element, you could also consider this pattern.

You can attach one event to the parent element (instead of having an event listener for each li.quality element) by taking advantage of Event Bubbling (see SO post here).

let selectionsElement = document.querySelector('#selections');

selectionsElement.addEventListener('click', function(event) {
  // stop event from bubbling further up the DOM tree
  event.stopPropagation();
  
  /*
    the `this` keyword will refer to the #selections element
    so we can't use it with this approach so we'll have to use `event`
  */
  
  // check if the element which triggered the event is li.quality
  if (event.target.classList.contains('quality')) {
    event.target.style.backgroundColor = 'red';
  }
});
<html>
<head>
 <title>L.A. Hiking</title>
 <link rel="stylesheet" href="css/hiking.css">
 </head>

<ul id = "navbar">
    <li><a href="index.html" class= "selected">Home</a></li>
    <li><a href="contact.html">Contact</a></li>
    <li><a href="about.html">About</a></li>
</ul>
<body>

<div>
    <div class="blocks" id="selections">
        <ul id= "attr1">
            <li class="Instruction">Pick one:</li>
            <li class ="quality">Hard</li>
            <li class ="quality">Medium</li>
            <li class ="quality">Easy</li>
        </ul>

        <ul id = "attr2">
            <li class="Instruction">Pick one:</li>
            <li class ="quality">Hard</li>
            <li class ="quality">Medium</li>
            <li class ="quality">Easy</li>
        </ul>

        <ul id = "attr3">
            <li class="Instruction">Pick one:</li>
            <li class ="quality">Hard</li>
            <li class ="quality">Medium</li>
            <li class ="quality">Easy</li>
        </ul>
    </div>  
    <div class="blocks" id="results">
        <ul id = "choices">
            <li class="choice">Pick one:</li>
            <li class ="choice">Hard</li>
            <li class ="choice">Medium</li>
        </ul>
    </div>
</div>
<div id="button-container">
    <button>Go!</button>
</div>

<script src="javascript/hiking.js"></script>
</body>
</html>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.