简体   繁体   中英

in JavaScript - select all elements with same class - except clicked one

in JavaScript - select all elements with same class - except clicked one

currently i am getting a result that works fine, but checking for a smart and simple solution

there are similar answers available using jquery not

 let color = document.querySelectorAll('.color'); let length = color.length; // for (let i = 0; i < length; i++) { // color[i].onclick = () => { // color[i].classList.toggle('gold'); // } // } // if gold exists on clicked element then remove it // if gold not exists on clicked element then remove from all element and add only on clicked element for (let i = 0; i < length; i++) { color[i].onclick = () => { if (color[i].classList.contains('gold')) { color[i].classList.toggle('gold'); // remove / toggle } else { for (let x = 0; x < length; x++) { color[x].classList.remove('gold'); } color[i].classList.toggle('gold'); // add / toggle } } } 
 .main { display: flex; justify-content: center; } .color { margin: 5px; width: 100px; height: 100px; border: 1px solid #ddd; } .gold { background-color: gold; } 
 <div class="main"> <div class="color"></div> <div class="color"></div> <div class="color"></div> <div class="color"></div> <div class="color"></div> </div> 

demo


 let color = document.querySelectorAll('.color') let gold = 'gold' color.forEach( (c) => c.onclick = (e) => { color.forEach( (c) => c.classList[e.target==c?'toggle':'remove'](gold) ) } ) 
 .main { display: flex; justify-content: center; } .color { margin: 5px; width: 100px; height: 100px; border: 1px solid #ddd; } .gold { background-color: gold; } 
 <div class="main"> <div class="color"></div> <div class="color"></div> <div class="color"></div> <div class="color"></div> <div class="color"></div> </div> 

You could just click if i is x in the loop

color[i].onclick = () => {
  for (let x = 0; x < length; x++) {
    if (i===x) continue
    color[x].classList.remove('gold');
  }
  color[i].classList.toggle('gold');
}

or you could just use one click handler and check to see if what you clicked is what is selected

 let color = document.querySelector('.main'); color.addEventListener('click', e => { if (e.target.classList.contains("main")) return var selected = color.querySelector(".gold") if (selected && selected!==e.target) selected.classList.remove('gold') e.target.classList.toggle('gold') }) 
 .main { display: flex; justify-content: center; } .color { margin: 5px; width: 100px; height: 100px; border: 1px solid #ddd; } .gold { background-color: gold; } 
 <div class="main"> <div class="color"></div> <div class="color"></div> <div class="color"></div> <div class="color"></div> <div class="color"></div> </div> 

Or no JavaScript at all

 .main { display: flex; justify-content: center; } .color { margin: 5px; width: 100px; height: 100px; border: 1px solid #ddd; } input[name="a"] { display:none } input[name="a"]:checked + label { background-color: gold; } 
 <div class="main"> <input type="radio" name="a" id="rb1"/><label class="color" for="rb1"></label> <input type="radio" name="a" id="rb2"/><label class="color" for="rb2"></label> <input type="radio" name="a" id="rb3"/><label class="color" for="rb3"></label> <input type="radio" name="a" id="rb4"/><label class="color" for="rb4"></label> <input type="radio" name="a" id="rb5"/><label class="color" for="rb5"></label> </div> 

let color = document.querySelectorAll('.color');
let length = color.length;
for (let i = 0; i < length; i++) {
    color[i].onclick = () => {
        for (let x = 0; x < length; x++) {
            if (i===x) continue
            color[x].classList.remove('gold');
        }
        color[i].classList.toggle('gold');
    }
}

It's more efficient to attach the click event to the parent div than each of the children so I've gone about the solution a little differently to everyone else.

 document.querySelector(".main").onclick = (event) => { let element = event.target; if (element.classList.contains("color")) { document.querySelector(".main") let isGold = false; if (element.classList.contains("gold")) { isGold = true; } document.querySelectorAll(".gold").forEach((color) => color.classList.remove("gold")); if (!isGold) { element.classList.add("gold"); } } }; 
 .main { display: flex; justify-content: center; } .color { margin: 5px; width: 100px; height: 100px; border: 1px solid #ddd; } .gold { background-color: gold; } 
 <div class="main"> <div class="color"></div> <div class="color"></div> <div class="color"></div> <div class="color"></div> <div class="color"></div> </div> 

Here's my attempt:

document.body.addEventListener("click", function(event){
    console.log(Array.prototype.slice.call(document.querySelectorAll(".color")).filter(function(element) {
        return element !== event.target;
    })); // This should print all elements with the class "color" except the clicked one
});

Edit: After taking another look at the question, is this more of what you are trying to do?

document.body.addEventListener("click", function(event){
    event.target.classList.add("gold");
    Array.prototype.slice.call(document.querySelectorAll("color")).forEach(function(element) {
        if (element !== event.target)
            element.classList.remove("gold"); // Don't need to exist to remove apparently
    });
});

Final edit (hopefully): Now it works exactly like your demo.

document.querySelector(".main").addEventListener("click", (event) => {
    event.target.classList.toggle("gold");
    Array.prototype.slice.call(document.querySelectorAll(".color")).forEach((element) => {
        if (element !== event.target)
            element.classList.remove("gold");
    });
});

One more way to do it..

 let colors = document.querySelectorAll('.color'); let length = colors.length; colors.forEach(function (color, index) { color.onclick = () => { colors.forEach(function(c, i) { c.classList[index === i ? "toggle" : "remove"]('gold'); }); }; }); 
 .main { display: flex; justify-content: center; } .color { margin: 5px; width: 100px; height: 100px; border: 1px solid #ddd; } .gold { background-color: gold; } 
 <div class="main"> <div class="color"></div> <div class="color"></div> <div class="color"></div> <div class="color"></div> <div class="color"></div> </div> 

With radio buttons:

 let colors = document.querySelectorAll('[name="color"]'); var checked = -1; colors.forEach(function(color, index) { color.onclick = () => { if (checked === index) { color.checked = false; checked = -1; } else checked = index; }; }); 
 .main { display: flex; justify-content: center; } label { margin: 5px; width: 100px; height: 100px; border: 1px solid #ddd; background-color: white; } .gold { background-color: gold; } input[type="radio"] { display: none; } input:checked+label { background-color: gold; } 
 <div class="main"> <input type="radio" id="radio1" name="color"> <label for="radio1"></label> <input type="radio" id="radio2" name="color"> <label for="radio2"></label> <input type="radio" id="radio3" name="color"> <label for="radio3"></label> <input type="radio" id="radio4" name="color"> <label for="radio4"></label> <input type="radio" id="radio5" name="color"> <label for="radio5"></label> </div> 

I fetched multiple list-item with the same class name. Need to show/hide list details by clicked list item. Below code may help someone -

function getDetailMsg(clicked){
    var len = document.getElementsByClassName("msg-accordion").length;
    var acc = document.getElementsByClassName("msg-accordion");

    acc[clicked].classList.toggle("active");
    var panel = acc[clicked].nextElementSibling;
    if (panel.style.maxHeight){
        panel.style.maxHeight = null;
    } else {
        for (let x = 0; x < len; x++) {
            var oldpanel = acc[x].nextElementSibling;
            if (clicked!=x) { 
                oldpanel.style.maxHeight = null;
                acc[x].classList.remove('active'); 
            }
        }
        panel.style.maxHeight = panel.scrollHeight + "px";
    } 
}

 <div class="list-group"> <div class="list-group-item justify-content-between msg-accordion" onclick="getDetailMsg('0');">Subject 1</div> <div class="panel bg-warning text-white">Body 1</div> <div class="list-group-item justify-content-between msg-accordion" onclick="getDetailMsg('1');">Subject 2</div> <div class="panel bg-warning text-white">Body 2</div></div> 

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM