Very basic task, don't worry about the coding style itself. I'm sure there are way more efficent and prettier ways of coding. The question is why the code doesn't work the way it is supposed to: It should add class "a" and remove class "b" and vice versa (depending on the class that is currently attached). It only works one way though, the class "closed" can be attached, but then "open" would not work anymore. Why is that?
HTML
<ul id="tasks">
<li class="open">AAAAA</li>
<li class="open">BBBBB</li>
<li class="open">CCCCC</li>
</ul>
CSS
.open {text-decoration: underline;}
.closed {text-decoration: line-through;}
JS
function doTask(event) {
event.target.classList.remove("open");
event.target.classList.add("closed");
}
function undoTask(event) {
event.target.classList.remove("closed");
event.target.classList.add("open");
}
function setup () {
document.querySelectorAll("li.open")[0].addEventListener("click", doTask);
document.querySelectorAll("li.open")[1].addEventListener("click", doTask);
document.querySelectorAll("li.open")[2].addEventListener("click", doTask);
document.querySelectorAll("li.closed")[0].addEventListener("click", undoTask);
document.querySelectorAll("li.closed")[1].addEventListener("click", undoTask);
document.querySelectorAll("li.closed")[2].addEventListener("click", undoTask);}
window.addEventListener("load", setup);
In this part of code
document.querySelectorAll("li.closed")[0].addEventListener("click", undoTask);
document.querySelectorAll("li.closed")[1].addEventListener("click", undoTask);
document.querySelectorAll("li.closed")[2].addEventListener("click", undoTask);
you are trying to add click
function to li.closed
, but there isn't any li.closed
until you clicked it. You can create another function ( doSomething
in the example below) for checking the target class, then doTask
or undoTask
depends on the contained class, like this
function doTask(event) { event.target.classList.remove("open"); event.target.classList.add("closed"); } function undoTask(event) { event.target.classList.remove("closed"); event.target.classList.add("open"); } function doSomething(event){ if (event.target.classList.contains('open')){ doTask(event); } else { undoTask(event); } } function setup () { document.querySelectorAll("li")[0].addEventListener("click", doSomething); document.querySelectorAll("li")[1].addEventListener("click", doSomething); document.querySelectorAll("li")[2].addEventListener("click", doSomething); } window.addEventListener("load", setup);
.open {text-decoration: underline;} .closed {text-decoration: line-through;}
<ul id="tasks"> <li class="open">AAAAA</li> <li class="open">BBBBB</li> <li class="open">CCCCC</li> </ul>
That is because for lines like this document.querySelectorAll("li.closed")[0].addEventListener("click", undoTask);
. It is trying to add event to elements which does not exist at all.
Infact you may not need a separate function to remove the class.
Use classList.toggle method to toggle the class
function doTask(event) { event.target.classList.toggle("closed"); } function setup() { document.querySelectorAll("li")[0].addEventListener("click", doTask); document.querySelectorAll("li")[1].addEventListener("click", doTask); document.querySelectorAll("li")[2].addEventListener("click", doTask); } window.addEventListener("load", setup);
.open { text-decoration: underline; } .closed { text-decoration: line-through; }
<ul id="tasks"> <li class="open">AAAAA</li> <li class="open">BBBBB</li> <li class="open">CCCCC</li> </ul>
The problem is that you are adding event listeners to these elements in your setup()
function:
document.querySelectorAll("li.closed")[0]
document.querySelectorAll("li.closed")[1]
document.querySelectorAll("li.closed")[2]
Those elements do not exist yet when you execute setup()
. That's why when clicking on a <li>
element with class="closed"
, it won't work.
The solution is to check the class of that specific element after clicking it. Like so:
function onLiClick(event) { if (event.target.className === 'open') event.target.className = 'closed'; else event.target.className = 'open'; } function setup() { for (var li of document.querySelectorAll('li')) li.addEventListener('click', onLiClick); } setup();
.open::after { content: "open"; } .closed::after { content: "closed"; }
<ul> <li class="open"></li> <li class="open"></li> <li class="open"></li> </ul>
Try like this
function setup () {
document.querySelectorAll("li.open")[0].addEventListener("click", doTask);
document.querySelectorAll("li.open")[1].addEventListener("click", doTask);
document.querySelectorAll("li.open")[2].addEventListener("click", doTask);
}
function doTask(event) {
if (!event.target.classList.contains("open")) {
undoTask(event);
} else {
event.target.classList.remove("open");
event.target.classList.add("closed");
}
}
function undoTask(event) {
event.target.classList.remove("closed");
event.target.classList.add("open");
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.