javascript - 如何根据匹配的 classList 从元素中删除类

标签 javascript html css class html-table

我有一个 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: &emsp;</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 &emsp;</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 three td.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: &emsp;</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: &emsp;</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:&emsp;</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:&emsp;</label>
    <output id="remaining">0</output><br><br>
  </form>
  <script></script>
</body>

</html>

关于javascript - 如何根据匹配的 classList 从元素中删除类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56159531/

相关文章:

javascript - 如何调用父变量i++

javascript - 用 document.URL 替换当前 url

javascript - 禁止同时在多个浏览器/选项卡中登录网站

html - 将文本从图像的一侧移动到图像下方

html - 使用HTML播放实时视频

CSS Sprite 不适用于 Chrome 移动版

javascript - 在javascript中获取复选框值

javascript - 使用 jQuery 删除动态生成的 html

css - 使用 Font Awesome 自定义 li-element - 有点复杂的情况

iframe 上的 CSS float 属性,得到广泛支持?