Как выбрать только элемент в последней строке таблицы с помощью селекторов CSS

#javascript #html #jquery #css

Вопрос:

У меня есть таблица со многими расширяемыми/складываемыми строками, которые скрыты метками до щелчка (показано ниже). Входные данные в правом столбце таблицы предназначены для редактирования и суммирования, поэтому у меня есть функция, чтобы настроить каждую ячейку .contentEditable и вычислить общую сумму введенных пользователем чисел. Однако, поскольку я не хочу, чтобы сама сумма (в последней строке таблицы) редактировалась, у меня есть следующее ограничение на обработчик событий в jQuery:

 document.querySelectorAll("table tr:not(:last-child) td ~ td");
 

В то время :not(:last-child) как часть избавляется от проблемы редактируемой последней строки, она создает еще одну проблему: теперь последние строки каждого расширяемого раздела (строки «Джилл» и «Джим» в приведенном ниже примере) также невозможно редактировать. Есть ли способ исправить это, не делая абсолютную последнюю строку таблицы («Всего») редактируемой в процессе?

Чтобы лучше визуализировать проблему, я приложил пример таблицы, демонстрирующей проблему.

 $(document).ready(function() {
  $('.hide').hide();
  $('[data-toggle="toggle"]').change(function() {
    $("label[for='"   this.id   "'] span").toggle();
    $(this).parents().next('.hide').toggle();
  });
});

function editcell() {
  let cellnum = document.querySelectorAll("table tr:not(:last-child) td ~ td");
  cellnum.forEach(td => {
    td.setAttribute("contentEditable", true);
    td.addEventListener("change", getsum());
  });
}

function getsum() {
  let sum = 0;
  let cellnum = document.querySelectorAll("table tr td ~ td");
  let count = cellnum.length - 1;
  for (i = 0; i < count; i  ) {
    sum  = parseInt(cellnum[i].innerHTML) || 0;
  }
  cellnum[count].innerHTML = sum;
}

editcell(); 
 table {
  width: 100%;
}

table,
tr,
th,
td {
  border: 1px solid black;
  border-collapse: collapse;
  font-family: Arial;
}

[data-toggle="toggle"] {
  display: none;
}

label {
  display: block;
} 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="table">
  <thead>
    <tr>
      <th>Name</th>
      <th>Number</th>
    </tr>
  </thead>

  <tbody class="section">
    <tr>
      <td colspan="2">
        <label class="label" for="class1">
            <b>Class 1</b>
            <span>(Click this!)</span>
          </label>
        <input type="checkbox" name="class1" id="class1" data-toggle="toggle">
      </td>
    </tr>
  </tbody>

  <tbody class="hide">
    <tr>
      <td>Jack</td>
      <td id="jack" oninput="editcell()">
        <span>0</span>
      </td>
    </tr>

    <tr>
      <td>John</td>
      <td id="john" oninput="editcell()">
        <span>0</span>
      </td>
    </tr>

    <tr>
      <td>Jill</td>
      <td id="jill" oninput="editcell()">
        <span>0</span>
      </td>
    </tr>
  </tbody>

  <tbody class="section">
    <tr>
      <td colspan="2">
        <label class="label" for="class2">
            <b>Class 2</b>
            <span>(Click this!)</span>
          </label>
        <input type="checkbox" name="class2" id="class2" data-toggle="toggle">
      </td>
    </tr>
  </tbody>

  <tbody class="hide">
    <tr>
      <td>Joe</td>
      <td id="joe" oninput="editcell()">
        <span>0</span>
      </td>
    </tr>

    <tr>
      <td>Jane</td>
      <td id="jane" oninput="editcell()">
        <span>0</span>
      </td>
    </tr>

    <tr>
      <td>Jim</td>
      <td id="jim" oninput="editcell()">
        <span>0</span>
      </td>
    </tr>
  </tbody>
  <tr>
    <td style="font-weight:bold; text-align: center">Total</td>
    <td id="total"></td>
  </tr>
</table> 

Ответ №1:

Вы можете выбрать (игнорировать) общую ячейку, так как она имеет уникальный идентификатор:

   let cellnum = document.querySelectorAll("table tr td ~ td:not(#total)");
 
 $(document).ready(function() {
  $('.hide').hide();
  $('[data-toggle="toggle"]').change(function() {
    $("label[for='"   this.id   "'] span").toggle();
    $(this).parents().next('.hide').toggle();
  });
});

function editcell() {
  let cellnum = document.querySelectorAll("table tr td ~ td:not(#total)");
  cellnum.forEach(td => {
    td.setAttribute("contentEditable", true);
    td.addEventListener("change", getsum());
  });
}

function getsum() {
  let sum = 0;
  let cellnum = document.querySelectorAll("table tr td ~ td");
  let count = cellnum.length - 1;
  for (i = 0; i < count; i  ) {
    sum  = parseInt(cellnum[i].innerHTML) || 0;
  }
  cellnum[count].innerHTML = sum;
}

editcell(); 
 table {
  width: 100%;
}

table,
tr,
th,
td {
  border: 1px solid black;
  border-collapse: collapse;
  font-family: Arial;
}

[data-toggle="toggle"] {
  display: none;
}

label {
  display: block;
} 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="table">
  <thead>
    <tr>
      <th>Name</th>
      <th>Number</th>
    </tr>
  </thead>

  <tbody class="section">
    <tr>
      <td colspan="2">
        <label class="label" for="class1">
            <b>Class 1</b>
            <span>(Click this!)</span>
          </label>
        <input type="checkbox" name="class1" id="class1" data-toggle="toggle">
      </td>
    </tr>
  </tbody>

  <tbody class="hide">
    <tr>
      <td>Jack</td>
      <td id="jack" oninput="editcell()">
        <span>0</span>
      </td>
    </tr>

    <tr>
      <td>John</td>
      <td id="john" oninput="editcell()">
        <span>0</span>
      </td>
    </tr>

    <tr>
      <td>Jill</td>
      <td id="jill" oninput="editcell()">
        <span>0</span>
      </td>
    </tr>
  </tbody>

  <tbody class="section">
    <tr>
      <td colspan="2">
        <label class="label" for="class2">
            <b>Class 2</b>
            <span>(Click this!)</span>
          </label>
        <input type="checkbox" name="class2" id="class2" data-toggle="toggle">
      </td>
    </tr>
  </tbody>

  <tbody class="hide">
    <tr>
      <td>Joe</td>
      <td id="joe" oninput="editcell()">
        <span>0</span>
      </td>
    </tr>

    <tr>
      <td>Jane</td>
      <td id="jane" oninput="editcell()">
        <span>0</span>
      </td>
    </tr>

    <tr>
      <td>Jim</td>
      <td id="jim" oninput="editcell()">
        <span>0</span>
      </td>
    </tr>
  </tbody>
  <tr>
    <td style="font-weight:bold; text-align: center">Total</td>
    <td id="total"></td>
  </tr>
</table>