0

I made a simple unordered list with checkboxes and want a class with strikethrough text to be applied to the li that the checkbox belongs to. The methods I've tried either only work on the first element or get applied to all of them at once.

The HTML:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="style.css">
  <title>Document</title>
</head>
<body>
  <h1>Todo List</h1>
  <ul>
    <li>
      <input type="checkbox">
      List Item 1
    </li>
    <li>
      <input type="checkbox">
      List Item 2
    </li>
    <li>
      <input type="checkbox">
      List Item 3
    </li>
  </ul>
</body>
</html>

The Javascript (only selects the first one):

document.querySelector("input").addEventListener("click", addStrike);

function addStrike() {
  document.querySelector("li").classList.toggle("completed");
}

(selects all at once, when using this code I had the jquery CDN in my html)

$("li").on("click", addStrike);

function addStrike() {
  $("li").toggleClass("completed")
}
  • 3
    Um, look up what `querySelector` does. It selects one element. You need to code your code to look for the parent li of the input that was clicked. You also need to loop over each element and set the event listener. – epascarello Feb 19 '20 at 18:35
  • Also, you say it only selects 1 in one case, but all in another. But the first case is vanilla javascript, and the second is jQuery. That's not comparing apples to apples. – Taplar Feb 19 '20 at 18:37
  • Does this answer your question? [querySelector and querySelectorAll vs getElementsByClassName and getElementById in JavaScript](https://stackoverflow.com/questions/14377590/queryselector-and-queryselectorall-vs-getelementsbyclassname-and-getelementbyid) – freedomn-m Feb 19 '20 at 19:20
  • So what's your question? You call a method that selects one element and it selects one element, then you call a method selects all of type and it ... selects all of type. Thanks for letting us know? – freedomn-m Feb 19 '20 at 19:27

3 Answers3

1

You need to select all the checkboxes, loop over them, and attach the event.

function cbClicked (event) {
  // reference the checkbox
  var cb = event.target
  // find it was checked
  var isChecked = cb.checked
  cb.closest("li")  // find the parent li
    .classList.toggle("done", isChecked) // toggle the class
}


// Select all the checkboxes
var checkboxes = document.querySelectorAll('ul input[type="checkbox"]')

// loop over all the checkboxes
checkboxes.forEach( function (cb) {
  // attach the event listener to each one
  cb.addEventListener("change", cbClicked)
})
.done {
  text-decoration: line-through;
}
<ul>
    <li>
      <input type="checkbox">
      List Item 1
    </li>
    <li>
      <input type="checkbox">
      List Item 2
    </li>
    <li>
      <input type="checkbox">
      List Item 3
    </li>
  </ul>

If you want to use jQuery it is similar, jQuery just does the looping for you

function cbClicked (event) {
  // reference the checkbox
  var cb = this
  var isChecked = this.checked
  $(cb).closest("li")  // find the parent li
    .toggleClass("done", isChecked) // toggle the class
}


// Select all the checkboxes
var checkboxes = $('ul input[type="checkbox"]').on("change", cbClicked)
.done {
  text-decoration: line-through;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
    <li>
      <input type="checkbox">
      List Item 1
    </li>
    <li>
      <input type="checkbox">
      List Item 2
    </li>
    <li>
      <input type="checkbox">
      List Item 3
    </li>
  </ul>

And it can be done with Just CSS

input:checked + label {
  text-decoration: line-through;
}
<ul>
    <li>
      <input type="checkbox" id="cb1">
      <label for="cb1">List Item 1</label>
    </li>
    <li>
      <input type="checkbox" id="c2">
      <label for="cb2">List Item 2</label>
    </li>
    <li>
      <input type="checkbox" id="cb3">
      <label for="cb3">List Item 3</label>
    </li>
  </ul>
epascarello
  • 204,599
  • 20
  • 195
  • 236
0

If you would rather apply the class 'completed' (and for that the style) when the check box is checked, I would recommend doing this, with jQuery:

$(".strikeCheckbox").change(function() {
    if(this.checked) {
        $(this).parent().addClass("completed")
    } else {
        $(this).parent().removeClass("completed")
    }
});

You can change the parent function for a specific prev(...) if you want.

Thiago
  • 193
  • 3
  • 9
  • I'm glad it did! If this answered your question, would you please sign it as it does, so your question is resolved? – Thiago Feb 20 '20 at 02:08
0

Add an Id to the UL and then use the below javascript

document.getElementById('ele').addEventListener('click',function(e){
    event.target.parentElement.classList.toggle('completed');
});

document.querySelector always returns the first element that matches the given selector

Akash
  • 377
  • 6
  • 17