0

I am starting out with studying JS and in my online course there is an exercise that is really confusing me.

We have a simple list, to which we can add items and now our job is to make it so that when a list element is clicked, it adds a class, basically "crossing out" the item.

So, my problem is, i am caching my <li> elements in a var in my script.js. When i use the .addEventListener to this var, to listen for the mouse clicks, my console spits out an error. I know why this is happening, basically because the <li> items in my var are stored inside of an array. So i really don't understand how to make this work - How do i use the .addEventListener("click", classList.add("done")) ? How do i make it so that the <li> items are targeted individually, on mouse click? Thank you very much for any help! *Vanilla JS only please ;) Here's the code so far:

var button = document.getElementById("enter");
var input = document.getElementById("userinput");
var ul = document.querySelector("ul");
var li = document.getElementsByTagName("li");


//Make sure input field is not empty
function inputLength() {
    return input.value.length;
}

//Add a list element from the user's input
function createListElement() {
    var li = document.createElement("li");
        li.appendChild(document.createTextNode(input.value));
        ul.appendChild(li);
        input.value = "";
}

//Add it through clicking
function addListAfterClick() {
    if (inputLength() > 0) {
        var li = document.createElement("li");
        createListElement();
        } 
}

//Add it through pressing Enter
function addListAfterKeyPress(event) {
    if (inputLength() > 0 && event.keyCode === 13) {
        createListElement();
    } 
}

button.addEventListener("click", addListAfterClick);

input.addEventListener("keypress", addListAfterKeyPress);

//* THIS IS THE PROBLEM *
li.addEventListener("click", classList.add("done"));
.done {
  text-decoration: line-through;
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel="stylesheet" href="style.css">
    <title>JavaScript + DOM</title>
</head>

<body>
    <h1>Shopping List</h1>
    <p id="first">Get it done today</p>
    <input id="userinput" type="text" placeholder="Enter Items">
    <button id="enter">Enter</button>

    <ul>
        <li>Notebook</li>
        <li>Jello</li>
        <li>Spinach</li>
        <li>Rice</li>
        <li>Birthday Cake</li>
        <li>Candles</li>
    </ul>
    

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

2 Answers 2

1

use this. e.target get the item you clicked within the ul with target and because you wanted to catch it when you hit li, you used the e.target.tagName feature of the element you clicked.

ul.addEventListener("click", function(e) {
    if(e.target.tagName === "LI") {
        e.target.classList.add("done");  
    }
});
Sign up to request clarification or add additional context in comments.

4 Comments

Thank you very much! It worked! Just a question: Why does "LI" in if(e.target.tagName === "LI") have to be in capital letters? I tried changing to small caps and the code didn't work..
@PauloSchinzel because, the older versions of HTML back when JavaScript was first created used all caps for tag names by convention instead of today's lowercase. To stay backwards-compatible with older code tagName() still returns all uppercase and has been stuck that way. check this: programming.enthuses.me/tag-node-case.php?doc=x
@PauloSchinzel if you want to use small, you can use such a e.target.tagName.toLowerCase() === "li"
Thank you very much for the explanation! Seems really archaic that they just left it like that though :P I feel it's these kinds of idiosyncrasies that sometimes discourage people from learning coding hehe But i'll push through this time! With you guys' help of course. Thanks again!
0

You need to loop over the array. Use li.forEach(function (item) { ... });

You also need to put the li.addEventListener(...) line in the function where you create those items.

3 Comments

Thank you very much for the reply! I don't understand the concept with the loop, sorry :( Could you maybe explain it to me? Thanks!
A loop is a programming construct in which you have some code that you want to repeat a number of times. In this case, you have an array (or list) of items, and you have some actions that you want to perform on each element of that list. You put those actions in a function that takes a variable, then use a forEach loop on the array with that function. This means the function will be executed as many times as there are elements, with each element of the array in turn as its argument. So list.forEach(foo) is the same as foo(list[0]); foo(list[1]); foo(list[2]); ...
Thank you very much for the explanation!

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.