I tried to color the text I clicked on by gave them a class and besides the text I click on the original color is back again, but when I click on the text twice the class can't be removed. I use toggle class for this issue but doesn't work.
.red {
color: red;
}
<ul>
<li class="txt">Lorem ipsum dolor.</li>
<li class="txt">Lorem ipsum dolor.</li>
<li class="txt">Lorem ipsum dolor.</li>
</ul>
const txts = document.querySelectorAll('.txt');
const txtColor =(txt)=> {
txt.addEventListener('click', e => {
if(e.target.classList.contains('txt')) {
txts.forEach(txt => txt.classList.remove('red'));
e.target.classList.toggle('red');
}
});
}
txtColor(document.querySelector('ul'));
CodePudding user response:
Cache the main list element, and the list items, and then attach one listener to the list element so you can use Event delegation to catch item click events as they "bubble up" the DOM.
When an item is clicked remove the red
class from all the items and , depending on the conditional parameter you pass to toggle
, (does the classList
contain a red
class) toggle
the red
class.
// Cache the elements
const ul = document.querySelector('ul');
const lis = document.querySelectorAll('.txt');
// Add a listener to the list
ul.addEventListener('click', handleClick, false);
function handleClick(e) {
// Destructure the nodeName and classList from the
// the element we clicked on
const { nodeName, classList } = e.target;
// Check if it's a list item
if (nodeName === 'LI') {
// Does the list item contain a red class?
const isRed = classList.contains('red');
// Remove all the red classes from all the items
lis.forEach(li => li.classList.remove('red'));
// And depending on the answer to `isRed`
// toggle the class on or off
classList.toggle('red', !isRed);
}
}
.red { color: red; }
.txt:hover { cursor: pointer; }
<ul>
<li class="txt">Lorem ipsum dolor.</li>
<li class="txt">Lorem ipsum dolor.</li>
<li class="txt">Lorem ipsum dolor.</li>
</ul>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
Additional documentation
CodePudding user response:
Using jQuery, I could make this work.
$('ul li').on('click', function(){
$(this).toggleClass('text')
});
.text {
color:red
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li class="txt">Lorem ipsum dolor.</li>
<li class="txt">Lorem ipsum dolor.</li>
<li class="txt">Lorem ipsum dolor.</li>
</ul>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
Here's my answer. Please see the comments in each section.
const txts = document.querySelectorAll('.txt');
const txtColor = (txt) => {
// click on li item
txt.addEventListener('click', e => {
// if target contains class txt, which in case, it's hard coded
// this will always return true
if (e.target.classList.contains('txt')) {
// remove red class for each list item with class txt
// in this line, it removes every 'red' class on each list item
txts.forEach(txt => txt.classList.remove('red'));
// Then toggle 'red' class if it's not present on the target
// Toggle does as it say, if its not present, it adds the token
// if it's present, it removes it.
// since the statement above ALWAYS removes the red class,
// Toggle will only always add the 'red' class
}
e.target.classList.toggle('red');
});
}
txtColor(document.querySelector('ul'));
If I'm right, I think this is what you're trying to do.
document.querySelector('ul').addEventListener("click", (e) => {
// if target doesn't contain red class, then remove all red class from the list
if(!e.target.classList.contains("red")) {
document.querySelectorAll("li").forEach(e => e.classList.remove("red"))
}
// toggle red class to the target
e.target.classList.toggle("red")
})