alwaysLearning
alwaysLearning

Reputation: 131

Event listener not displaying line-through when ticking checkbox of list item

I’ve created a function named checkedItems. I want the function to cross an item out each time the check box attached to it is ticked. However, nothing happens when I do so. If someone could point out where I’ve gone wrong in my code and fix it, that would be great.

var elUlList = document.getElementById("ulList");
var btn = document.getElementById("btn");
const elInput = document.getElementById("input");
const footer = document.querySelector("footer");
const message = document.getElementById("message");
const elCounter = document.getElementById("counter");

function createListItems() {
  var elements = document.getElementsByTagName('li');
  
  console.log(elements)
  
  var inputValue = elInput.value;
  var newLi = document.createElement("li");
  var input = document.createElement("input")
  
  input.type = "checkbox"
  
  var newText = document.createTextNode(inputValue);
  
  newLi.appendChild(input);
  newLi.appendChild(newText);
  elUlList.appendChild(newLi)
}

btn.addEventListener("click", createListItems, false);
elInput.addEventListener("keyup", function(e) {
  if (e.keyCode === 13) {
    e.preventDefault();
    btn.click()
  }
})
elInput.addEventListener("mouseover", emptyField, false)

function emptyField() {
  this.value = "";
}

elUlList.addEventListener("change", checkedItems, false)

function checkedItems() {
  var checkboxes = document.querySelectorAll("input[type=checkbox]")
  var checkboxesArray = Array.from(checkboxes);
  
  console.log(checkboxes.length);
  
  if (checkboxes.length > 1) {
    for (var i = 0; i < checkboxes.length; i++) {
      checkboxes[i].checked
        ? checkboxes[i].classList.toggle("lineThrough")
        : null;
    }
  }
}
<!DOCTYPE html>
<html lang="en" dir="ltr">

<head>
  <meta charset="utf-8">
  <title></title>
  <link rel="stylesheet" href="index.css">
</head>

<body>
  <div id="message" class=""></div>
  <ul id="ulList"></ul>
  <button id="btn" type="button" name="button">click here to add items</button>
  <input id="input" type="text" name="" value="">
  <div id="counter" class=""></div>
  <footer></footer>
  <script src="index.js" type="text/javascript"></script>
</body>

</html>

Upvotes: 0

Views: 74

Answers (2)

Sebastian Simon
Sebastian Simon

Reputation: 19545

Converting comments to an answer: you’re applying the lineThrough class to the checkbox, not its parent element, the <li>. The <li> contains the text.

The function referenced in elUlList.addEventListener("change", checkedItems, false) can be shortened:

const checkedItems = ({target}) => {
  if(target.matches("input[type=checkbox]")){
    target.closest("li").classList.toggle("lineThrough", target.checked);
  }
}

target.closest("li") will always find the <li> that contains target (and is the closest parent node in the DOM tree).

toggle accepts a second argument that will set or unset the class "lineThrough" based on the boolean target.checked.

No need to loop, because a change event will only be triggered when you change one specific checkbox, and you want to strike out the text in only this list item, so it’s sufficient to only target that one.

And your conditional operator was wrong: why do you toggle only when the checkbox is checked?

Another thing: checkedItems isn’t a good name for this function, as this name implies that the function returns a list of checked items or something similar, but it doesn’t. strikeOutCheckedItem or toggleCheckedItem is better; there’s also no plural, because this function only deals with one list item at a time.

Finally, make sure you actually have the CSS class defined:

.lineThrough {
  text-decoration: line-through;
}

Upvotes: 2

Manas Khandelwal
Manas Khandelwal

Reputation: 3931

I think this is a better approach

const elUlList = document.getElementById("ulList");
const btn = document.getElementById("btn");
const elInput = document.getElementById("input");

function addItem() {
  if (elInput.value !== "") {
    const listItem = `<li>
  <input type="checkbox">
  <span>${elInput.value}</span>
</li>`;

    elUlList.insertAdjacentHTML("afterbegin", listItem);

    elInput.value = "";
  }
}

btn.addEventListener("click", addItem);
elInput.addEventListener("keyup", (e) => {
  if (e.key === "Enter") {
    addItem();
  }
});

function isCompleted() {
  const checkboxs = document.querySelectorAll("li input");
  const tasks = document.querySelectorAll("li span");

  for (let i = 0; i < checkboxs.length; i++) {
    if (checkboxs[i].checked) {
      tasks[i].classList.toggle("lineThrough");
    }
  }
}

elUlList.addEventListener("change", isCompleted);
.lineThrough {
  text-decoration: line-through;
}
<ul id="ulList"></ul>
<button id="btn" type="button" name="button">
      click here to add items
    </button>
<input id="input" type="text" />

...

Upvotes: -1

Related Questions