I am working on project and my goal is to toggle each individual li element by clicking toggle button. I managed to do this so far but it's working only on first li element. Can you help me with this code?
<li id="liEl">Target This element</li>
<button id="Btn">toggle</button>
<li id="liEl" >Target This element</li>
<button id="Btn">toggle</button>
<li id="liEl" >Target This element</li>
<button id="Btn">toggle</button>
.done {
text-decoration: line-through;
text-decoration-thickness: 0.2rem;
text-decoration-color:red;
}
Btn= document.getElementById("Btn");
liEl= document.getElementById("liEl");
const toggleDoneClass = () => {
liEl.classList.toggle('done');
};
Btn.addEventListener('click', toggleDoneClass);
CodePudding user response:
id attribute must be unique. you can use class instead of that.
HTML
<li >Target This element</li>
<button >toggle</button>
<li >Target This element</li>
<button >toggle</button>
<li >Target This element</li>
<button >toggle</button>
You must select all buttons and then add Event Listener to each one by a loop.
Javascript
var btns = document.getElementsByClassName("btn");
for (let i = 0; i < btns.length; i ) {
btns[i].addEventListener("click", () => {
// Previous is li because li is before button
btns[i].previousElementSibling.classList.toggle("done");
});
}
Now this is Working.
CodePudding user response:
You are giving the same ids to all the buttons and li instead of id use class names
btns= document.getElementsByClassName("btn");
it will select all the classes which contain buttons
for(let index = 0;index < btns.length; index ){
btns[index].onclick = (evt) =>{
evt.target.previousElementSibling.classList.toggle("done")
}
}
looping all the classes on which you will click it will take that element and then get their previous child which is li and toggle class on that
btns= document.getElementsByClassName("btn");
for(let index = 0;index < btns.length; index ){
btns[index].onclick = (evt) =>{
evt.target.previousElementSibling.classList.toggle("done")
}
}
.done {
text-decoration: line-through;
text-decoration-thickness: 0.2rem;
text-decoration-color:red;
}
<li id="" >Target This element</li>
<button >toggle</button>
<li id="" >Target This element</li>
<button >toggle</button>
<li id="lEl" >Target This element</li>
<button >toggle</button>
CodePudding user response:
IDs should be unique in a page so maybe switch those to classes.
If you want the buttons you should add them within the list item elements.
You can attach one listener to the <ul>
element and have that catch events from its children as they "bubble up" the DOM. (This is known as event delegation.)
When a click event is fired you can retrieve the specific element that was clicked with event.target, check that it's a button element, find the closest
list item element to that button, and then toggle its class.
const list = document.querySelector('ul');
list.addEventListener('click', toggleDoneClass);
function toggleDoneClass(e) {
if (e.target.matches('button')) {
e.target.closest('li').classList.toggle('done');
}
}
.done { text-decoration: line-through; text-decoration-thickness: 0.2rem; text-decoration-color:red; }
li button { margin-left: 0.5em; }
<ul>
<li >
Target This element
<button type="button">Toggle</button>
</li>
<li >
Target This element
<button type="button">Toggle</button>
</li>
<li >
Target This element
<button type="button">Toggle</button>
</li>
</ul>
But, ultimately, you don't really need the buttons.
const list = document.querySelector('ul');
list.addEventListener('click', toggleDoneClass);
function toggleDoneClass(e) {
if (e.target.matches('li')) {
e.target.classList.toggle('done');
}
}
.done { text-decoration: line-through; text-decoration-thickness: 0.2rem; text-decoration-color:red; }
li:hover { cursor: pointer; }
<ul>
<li >Target This element</li>
<li >Target This element</li>
<li >Target This element</li>
</ul>