问题
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
回答1:
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>
回答2:
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>
回答3:
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');
}
}
回答4:
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>
回答5:
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");
});
});
回答6:
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>
回答7:
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>
来源:https://stackoverflow.com/questions/45166546/in-javascript-select-all-elements-with-same-class-except-clicked-one