如何基于匹配的classList从元素中删除类

时间:2019-05-16 01:15:27

标签: 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无关,以提高灵活性。

  <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>

2 个答案:

答案 0 :(得分:1)

有很多变化,但是与实际问题有关的变化

  

“ ...显示15个元素中只有1个元素属于'.selected'类的一部分。”

是要从所有.selected中删除<td>,然后将.selected添加到单击的<td>中。使用<td>属性可以轻松确定点击的Event.target

  for (let cell of cells) {
    cell.classList.remove('selected');
  }
  target.classList.add('selected');

修改

在OP中存在一些冲突的信息:

  

“ ...,因此每列只能有1个单元格可以成为'.selected'类的一部分。”

不是三个td.selected而是一个td.selected -每列一个。

演示1 具有以下行为:

  

只有一个td.selected

演示2 具有以下行为:

  

每列一个td.selected,共三个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>

答案 1 :(得分:0)

在测试条件下使用i.classList.value == this.classList.value而不是将整个对象与==运算符进行比较。

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 .selected class to the clicked cell
      this.classList.add("selected");
      var clickedCellClasslist = this.classList.value;
      
      for (var i of document.getElementsByTagName('td')) {
        if (i.classList.value == clickedCellClasslist) {
          i.classList.remove("selected");
        }
      }

      this.classList.add("selected");
      deduct = deduct + Number(this.innerText);
      document.getElementById("dollars_left_id").innerHTML = dollars_remaining - deduct;
    }
  }
}

window.onload = mainFunction();
<!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>


</body>

</html>