我有一个 HTML 表格,其中每一列都是它自己的类的一部分。单击列中的单元格时,应将新类添加到该单元格 (.selected)。同一列中的其他单元格应删除“.selected”类,这样每列只有 1 个单元格可以属于“.selected”类。 为此,我将表中所有元素的 classList 与被单击的单元格“this”进行比较,当列表匹配时删除该类,然后重新添加到被单击的单元格。 这失败了,最终所有单元格都属于这两个类。
日志显示对于单击的单元格,classList 正确更新(添加、删除、然后重新添加)。对于其他单元格,它们不会被“if”条件改变。 这是完整的 HTML 文档:
<!DOCTYPE html>
<html>
<head>
<title>test</title>
</head>
<body>
<style>
table {
font-family: google-sans, sans-serif;
border-collapse: collapse;
width: 100%;
}
td,
th {
border: 2px solid #48236F;
text-align: center;
padding: 8px;
width: 30%;
}
th {
background-color: grey;
color: white;
border: 2px solid #ffffff;
width: 10%;
}
.option {
color: #48236F;
font-weight: bold;
}
.selected {
background-color: #b7dc90;
}
</style>
<div>Choose your coverage situation</div>
<select id="coverage" onchange="mainFunction()">
<option value="">--Choose below--</option>
<option value="1102">Single</option>
<option value="1610">Couple</option>
<option value="2118">Family</option>
</select><br><br>
<span>Dollars Allocated:  </span>
<span id="dollars_id">0 $</span><br><br>
<table id="display-table">
<tr>
<th></th>
<th>Col 1</th>
<th>Col 2</th>
<th>Col 3</th>
</tr>
<tr>
<th>Option 1</th>
<td class="col_1" value="10">101</td>
<td class="col_2" value="20">201</td>
<td class="col_3" value="30">301</td>
<tr>
<tr>
<th>Option 2</th>
<td class="col_1">102</td>
<td class="col_2">202</td>
<td class="col_3">302</td>
<tr>
<tr>
<th>Option 3</th>
<td class="col_1">103</td>
<td class="col_2">203</td>
<td class="col_3">303</td>
<tr>
<tr>
<th>Option 4</th>
<td class="col_1">104</td>
<td class="col_2">204</td>
<td class="col_3">304</td>
<tr>
<tr>
<th>Option 5</th>
<td class="col_1">105</td>
<td class="col_2">205</td>
<td class="col_3">305</td>
<tr>
</table>
<br>
<span>Remaining Dollars  </span>
<span id="dollars_left_id">0 $</span><br><br>
<script>
function currencyFormat(num) {
return num.toFixed(2).replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,') + ' $';
}
var dollars_allocated = 0;
var deduct = 0;
var test = 0;
function mainFunction() {
dollars_allocated = Number(document.getElementById("coverage").value);
document.getElementById("dollars_id").innerHTML = dollars_allocated;
var table = document.getElementById('display-table');
var cells = table.getElementsByTagName('td');
for(let cell of cells){
cell.onclick = function() {
var dollars_remaining = dollars_allocated;
// Add the clicked cell to the .selected class
console.log(this.classList);
this.classList.add("selected");
console.log(this.classList);
for (var i of document.getElementsByTagName('td')){
if (i.classList == this.classList){
i.classList.remove("selected");
}
console.log(i.classList);
}
console.log(this.classList);
this.classList.add("selected");
console.log(this.classList);
deduct = deduct + Number(this.innerText);
document.getElementById("dollars_left_id").innerHTML = dollars_remaining - deduct;
}
}
}
window.onload = mainFunction();
</script>
</body>
</html>
我希望控制台日志仅显示 15 个元素中的 1 个元素属于“.selected”类。 所选类显示绿色背景,因此很容易看到错误。
感谢您的帮助。
编辑
基于 zer00ne 的优秀回答,这里是经过一些调整的最终函数:
1- 确保只有 <td>
元素可以被点击
2-“剩余”将“选定”类的所有元素相加,而不仅仅是目标的
3- 为每个元素添加了一个“值”属性,以允许返回一个值,而不管单元格的 innerText,以获得更大的灵 active 。
<script>
const form = document.forms.healthcare;
const table = document.getElementById('display');
const cells = document.getElementsByTagName('td');
form.onchange = dollars;
table.onclick = dollars;
function dollars(e) {
const target = e.target;
const type = e.type;
const fields = form.elements;
const col1 = Array.from(table.querySelectorAll('.col1'));
const col2 = Array.from(table.querySelectorAll('.col2'));
const col3 = Array.from(table.querySelectorAll('.col3'));
if (type === 'change') {
if (target.matches('#coverage')) {
fields.allocated.value = currency(parseFloat(target.value));
}
} else if (type === 'click') {
if (target.matches('.col1')) {
for (let cel1 of col1) {
cel1.classList.remove('selected');
}
} else if (target.matches('.col2')) {
for (let cel2 of col2) {
cel2.classList.remove('selected');
}
} else {
for (let cel3 of col3) {
cel3.classList.remove('selected');
}
}
// Add selected class to clicked cell
if (target.tagName == 'TD'){
target.classList.add('selected');
}
// Add total of selected cells
var totalPremium = 0;
for (let cell of cells){
if (cell.classList.contains('selected')){
totalPremium = totalPremium + parseFloat(cell.getAttribute('value'));
}
}
// Substract totalPremium from the allocated dollars
fields.remaining.value = currency(parseFloat(fields.coverage.value) - parseFloat(totalPremium));
} else {
return false;
}
}
function currency(number, country = 'en-US') {
return (number).toLocaleString(country, {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
style: "currency",
currency: "USD"
});
}
</script>
最佳答案
有很多变化,但变化与实际问题有关:
"...show only 1 element out of the 15 to be part of the '.selected' class."
是删除.selected
来自所有<td>
, 然后添加 .selected
点击<td>
.点击的 <td>
可以通过使用 Event.target
轻松确定属性(property)。
for (let cell of cells) {
cell.classList.remove('selected');
}
target.classList.add('selected');
编辑
在 OP 中有一些相互矛盾的信息:
"...so that only 1 cell per column can be part of the '.selected' class."
而不是一个td.selected
有可能三个td.selected
-- 每列一个。
Demo 1 具有以下行为:
Only one
td.selected
Demo 2 具有以下行为:
One
td.selected
per column for a total of threetd.selected
演示 1
const form = document.forms.healthcare;
const table = document.getElementById('display');
form.onchange = dollars;
table.onclick = dollars;
function dollars(e) {
const target = e.target;
const type = e.type;
const fields = form.elements;
const cells = table.querySelectorAll('td');
if (type === 'change') {
if (target.matches('#coverage')) {
fields.allocated.value = currency(parseFloat(target.value));
}
} else if (type === 'click') {
if (target.matches('td')) {
for (let cell of cells) {
cell.classList.remove('selected');
}
target.classList.add('selected');
let deduct = parseFloat(target.textContent);
fields.remaining.value = currency(parseFloat(fields.coverage.value) - deduct);
}
} else {
return false;
}
}
function currency(number, country = 'en-US') {
return (number).toLocaleString(country, {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
style: "currency",
currency: "USD"
});
}
:root {
font: 400 small-caps 14px/1.2 Arial
}
table {
border-collapse: collapse;
table-layout: fixed;
width: 100%;
}
td,
th {
border: 2px solid #48236F;
text-align: center;
padding: 8px;
width: 25%;
}
th {
background-color: grey;
color: white;
border: 2px solid #ffffff;
}
td,
output {
font-family: Consolas
}
select {
font: inherit
}
.option {
color: #48236F;
font-weight: bold;
}
.selected {
background-color: #b7dc90;
}
<!DOCTYPE html>
<html>
<head>
<title>test</title>
<style></style>
</head>
<body>
<form id='healthcare'>
<label for='coverage'>Choose Your Coverage</label><br>
<select id="coverage">
<option value="">--Coverage--</option>
<option value="1102">Single</option>
<option value="1610">Married</option>
<option value="2118">Dependents</option>
<option value="3728">Married with Dependents</option>
</select><br><br>
<label for='allocated'>Allocated:  </label>
<output id="allocated">0</output><br><br>
<table id="display">
<tr>
<th></th>
<th>Col 1</th>
<th>Col 2</th>
<th>Col 3</th>
</tr>
<tr>
<th>Option 1</th>
<td>101</td>
<td>201</td>
<td>301</td>
</tr>
<tr>
<th>Option 2</th>
<td>102</td>
<td>202</td>
<td>302</td>
</tr>
<tr>
<th>Option 3</th>
<td>103</td>
<td>203</td>
<td>303</td>
</tr>
<tr>
<th>Option 4</th>
<td>104</td>
<td>204</td>
<td>304</td>
</tr>
<tr>
<th>Option 5</th>
<td>105</td>
<td>205</td>
<td>305</td>
</tr>
</table>
<br>
<label for='remaining'>Remaining:  </label>
<output id="remaining">0</output><br><br>
</form>
<script></script>
</body>
</html>
演示2
const form = document.forms.healthcare;
const table = document.getElementById('display');
form.onchange = dollars;
table.onclick = dollars;
function dollars(e) {
const target = e.target;
const type = e.type;
const fields = form.elements;
const col1 = Array.from(table.querySelectorAll('.col1'));
const col2 = Array.from(table.querySelectorAll('.col2'));
const col3 = Array.from(table.querySelectorAll('.col3'));
if (type === 'change') {
if (target.matches('#coverage')) {
fields.allocated.value = currency(parseFloat(target.value));
}
} else if (type === 'click') {
if (target.matches('.col1')) {
for (let cel1 of col1) {
cel1.classList.remove('selected');
}
} else if (target.matches('.col2')) {
for (let cel2 of col2) {
cel2.classList.remove('selected');
}
} else {
for (let cel3 of col3) {
cel3.classList.remove('selected');
}
}
target.classList.add('selected');
fields.remaining.value = currency(parseFloat(fields.coverage.value) - parseFloat(target.textContent));
} else {
return false;
}
}
function currency(number, country = 'en-US') {
return (number).toLocaleString(country, {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
style: "currency",
currency: "USD"
});
}
:root {
font: 400 small-caps 14px/1.2 Arial
}
table {
border-collapse: collapse;
table-layout: fixed;
width: 100%;
}
td,
th {
border: 2px solid #48236F;
text-align: center;
padding: 8px;
width: 25%;
}
th {
background-color: grey;
color: white;
border: 2px solid #ffffff;
}
td,
output {
font-family: Consolas;
font-size: 1.1rem;
}
select {
font: inherit
}
.option {
color: #48236F;
font-weight: bold;
}
.selected {
background-color: #b7dc90;
}
<!DOCTYPE html>
<html>
<head>
<title>Healthcare</title>
<style></style>
</head>
<body>
<form id='healthcare'>
<label for='coverage'>Choose Your Coverage</label><br>
<select id="coverage">
<option value="">--Coverage--</option>
<option value="1102">Single</option>
<option value="1610">Married</option>
<option value="2118">Dependents</option>
<option value="3728">Married with Dependents</option>
</select><br><br>
<label for='allocated'>Allocated: </label>
<output id="allocated">0</output><br><br>
<table id="display">
<thead>
<tr>
<th></th>
<th>Col 1</th>
<th>Col 2</th>
<th>Col 3</th>
</tr>
</thead>
<tbody>
<tr>
<th>Option 1</th>
<td class='col1'>101</td>
<td class='col2'>201</td>
<td class='col3'>301</td>
</tr>
<tr>
<th>Option 2</th>
<td class='col1'>102</td>
<td class='col2'>202</td>
<td class='col3'>302</td>
</tr>
<tr>
<th>Option 3</th>
<td class='col1'>103</td>
<td class='col2'>203</td>
<td class='col3'>303</td>
</tr>
<tr>
<th>Option 4</th>
<td class='col1'>104</td>
<td class='col2'>204</td>
<td class='col3'>304</td>
</tr>
<tr>
<th>Option 5</th>
<td class='col1'>105</td>
<td class='col2'>205</td>
<td class='col3'>305</td>
</tr>
</tbody>
</table>
<br>
<label for='remaining'>Remaining: </label>
<output id="remaining">0</output><br><br>
</form>
<script></script>
</body>
</html>
关于javascript - 如何根据匹配的 classList 从元素中删除类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56159531/