Как выбрать только одну строку в таблице с помощью флажка

#javascript #jquery

Вопрос:

У меня есть таблица с x номерами строк и 4 столбцами, один столбец-флажок, а три других-только для чтения. Я хочу, чтобы пользователь выбрал только 1 строку для редактирования, установив флажок в первом столбце, затем, если он установит другой флажок в другой строке, флажок, который он ранее установил, будет снят, и строка снова будет доступна только для чтения.

Поэтому я хочу, чтобы пользователь выбирал только 1 строку для редактирования, а остальные-только для чтения. вот мой код, но он не работает.

 $(document).ready(function(){
  $('.col1, .col2, .col3').attr('disabled', true)
   selectRow();
    $('.tbl').on('change', '.selectRow', selectRow);
    function selectRow() {
     $('.tbl tbody tr').each(function () {
     $(this).find('.selectRow').each(function () {
      var checkedRow = $(this).closest('tr').find('input:checkbox:checked'),
        col1 = $(this).closest('tr').find('.col1'),
        col2 = $(this).closest('tr').find('.col2'),
        col3 = $(this).closest('tr').find('col3');
        if (checkedRow){
        $('.col1, .col2, .col3').removeAttr('disabled')
    checkedRow.siblings().prop('checked', false);
    }else{
        $('.col1, .col2, .col3').attr('disabled', true)
    checkedRow.siblings().prop('checked', false);
    }
 });
});
}
}); 
 <table class="tbl">
<tr>
  <td><input type="checkbox" name="check1" class = "selectRow" />amp;nbsp;</td>
  <td>
   <select class="col1">
       <option id="col1o1">A</option>
       <option id="col1o2">B</option>
       <option id="col1o3">C</option>
       <option id="col1o4">E</option>
   </select>
  </td>
    <td>
   <select class="col2">
       <option id="col2o1">A</option>
       <option id="col2o2">B</option>
       <option id="col2o3">C</option>
       <option id="col2o4">E</option>
   </select>
  </td>
    <td>
   <select class="col3">
       <option id="col3o1">A</option>
       <option id="col3o2">B</option>
       <option id="col3o3">C</option>
       <option id="col3o4">E</option>
   </select>
  </td>
</tr>
<br>
<tr>
  <td><input type="checkbox" name="check1" />amp;nbsp;</td>
  <td>
   <select class="s1">
       <option id="s1o1">A</option>
       <option id="o2">B</option>
       <option id="o3">C</option>
       <option id="o4">E</option>
   </select>
  </td>
    <td>
   <select class="s2">
       <option id="s2o1">A</option>
       <option id="s2o2">B</option>
       <option id="s2o3">C</option>
       <option id="s2o4">E</option>
   </select>
  </td>
    <td>
   <select class="s3">
       <option id="s3o1">A</option>
       <option id="s3o2">B</option>
       <option id="s3o3">C</option>
       <option id="s3o4">E</option>
   </select>
  </td>
</tr>
<br>
<tr>
  <td><input type="checkbox" name="check1" />amp;nbsp;</td>
  <td>
   <select class="s1">
       <option id="s1o1">A</option>
       <option id="o2">B</option>
       <option id="o3">C</option>
       <option id="o4">E</option>
   </select>
  </td>
    <td>
   <select class="s2">
       <option id="s2o1">A</option>
       <option id="s2o2">B</option>
       <option id="s2o3">C</option>
       <option id="s2o4">E</option>
   </select>
  </td>
    <td>
   <select class="s3">
       <option id="s3o1">A</option>
       <option id="s3o2">B</option>
       <option id="s3o3">C</option>
       <option id="s3o4">E</option>
   </select>
  </td>
</tr>
</table> 

это мой код:

Ответ №1:

Без jQuery и использования делегирования событий все может быть несколько проще:

 document.addEventListener(`click`, handle);

// disable all selectors initially
document.querySelectorAll(`td select`)
  .forEach(s => s.setAttribute(`disabled`, true));

function handle(evt) {
  // only do something if a checkbox was clicked
  if (evt.target.type === `checkbox`) {
    const isChecked = evt.target.checked;
    const selectedRow = evt.target.closest(`tr`);
    // reset checkboxes, row coloring and disabled state
    document.querySelectorAll(`input[type='checkbox']`)
      .forEach(cb => {
        cb.checked = cb !== evt.target ? false : isChecked;
        const row = cb.closest(`tr`);
        row.classList[isChecked amp;amp; row === selectedRow ?
          `add` : `remove`](`selected`);
        [...row.querySelectorAll(`select`)].filter(r => r !== selectedRow)
          .forEach(s => s.setAttribute(`disabled`, true));
        selectedRow.querySelectorAll(`select`)
          .forEach(s => s[isChecked ? 
              `removeAttribute` : `setAttribute`](`disabled`, true));
      });
  }
} 
 body {
  margin: 2rem;
}

tr.selected {
  background-color: lightgreen;
} 
 <table class="tbl">
  <tr>
    <td><input type="checkbox" name="check1" class="selectRow" />amp;nbsp;</td>
    <td>
      <select class="col1">
        <option id="col1o1">A</option>
        <option id="col1o2">B</option>
        <option id="col1o3">C</option>
        <option id="col1o4">E</option>
      </select>
    </td>
    <td>
      <select class="col2">
        <option id="col2o1">A</option>
        <option id="col2o2">B</option>
        <option id="col2o3">C</option>
        <option id="col2o4">E</option>
      </select>
    </td>
    <td>
      <select class="col3">
        <option id="col3o1">A</option>
        <option id="col3o2">B</option>
        <option id="col3o3">C</option>
        <option id="col3o4">E</option>
      </select>
    </td>
  </tr>
  <br>
  <tr>
    <td><input type="checkbox" name="check1" />amp;nbsp;</td>
    <td>
      <select class="s1">
        <option id="s1o1">A</option>
        <option id="o2">B</option>
        <option id="o3">C</option>
        <option id="o4">E</option>
      </select>
    </td>
    <td>
      <select class="s2">
        <option id="s2o1">A</option>
        <option id="s2o2">B</option>
        <option id="s2o3">C</option>
        <option id="s2o4">E</option>
      </select>
    </td>
    <td>
      <select class="s3">
        <option id="s3o1">A</option>
        <option id="s3o2">B</option>
        <option id="s3o3">C</option>
        <option id="s3o4">E</option>
      </select>
    </td>
  </tr>
  <br>
  <tr>
    <td><input type="checkbox" name="check1" />amp;nbsp;</td>
    <td>
      <select class="s1">
        <option id="s1o1">A</option>
        <option id="o2">B</option>
        <option id="o3">C</option>
        <option id="o4">E</option>
      </select>
    </td>
    <td>
      <select class="s2">
        <option id="s2o1">A</option>
        <option id="s2o2">B</option>
        <option id="s2o3">C</option>
        <option id="s2o4">E</option>
      </select>
    </td>
    <td>
      <select class="s3">
        <option id="s3o1">A</option>
        <option id="s3o2">B</option>
        <option id="s3o3">C</option>
        <option id="s3o4">E</option>
      </select>
    </td>
  </tr>
</table> 

Вот еще более упрощенная версия, действующая на строки таблицы

 document.addEventListener(`click`, handle);

// create the table dynamically to keep demo lean
createTable();

function handle(evt) {
  if (evt.target.type === `checkbox`) {
    const selectedRow = evt.target.closest(`tr`);
    document.querySelectorAll(`tr`)
      .forEach( row => {
        // not selected
        if (row !== selectedRow) {
          row.querySelector(`[type=checkbox]`).checked = false;
          row.classList.remove(`selected`);
          return row.querySelectorAll(`select`)
            .forEach(s => s.setAttribute(`disabled`, true));
        }
        // selected
        row.classList[[`remove`, `add`][ evt.target.checked]](`selected`);
        row.querySelectorAll(`select`).forEach(s => 
          s[`${[`set`,`remove`][ evt.target.checked]}Attribute`](`disabled`, true));
      });
  }
}

function createTable() {
  const table = document.createElement(`table`);
  const repeat = (str, n) => Array(n   1).join(str);
  const select = `<td><select>
      <option>A</option>
      <option>B</option>
      <option>C</option>
      <option>E</option></select></td>`;
  const row = `<tr>
    <td><input type="checkbox" /></td>
    ${repeat(select, 3)}</tr>`;
    
  table.insertAdjacentHTML(`beforeend`, repeat(row, 3));
  
  document.body.appendChild(table);
  // disable all selectors initially
  document.querySelectorAll(`td select`)
    .forEach(s => s.setAttribute(`disabled`, true));
} 
 body {
  margin: 2rem;
}

tr.selected {
  background-color: lightgreen;
}

tr td:nth-child(1) {
  padding-right: 6px;
} 

Комментарии:

1. Спасибо, это отлично работает.

2. Привет @M. Хорошо, рад, что смог помочь. К ответу добавлен еще один пример, который, имхо, немного проще.

Ответ №2:

Проблема в том, что checkedRow содержит объект jQuery. Когда вы используете это в if состоянии, оно всегда будет равносильно true . Вместо этого вам нужно получить checked свойство из этого элемента и вместо этого использовать его в условии.

Также обратите внимание, что логику можно сделать гораздо более сжатой и расширяемой за счет использования общих селекторов вместо инкрементных. Кроме того, вам следует попытаться добавить disabled атрибут непосредственно в HTML. Добавление его через JS означает, что появится видимая вспышка, в которой элемент будет загружен как включенный, а затем, когда DOM загрузится, он будет отключен, что не подходит для вашего UX.

 jQuery($ => {
  selectRow();
  $('.tbl').on('change', '.selectRow', selectRow);

  function selectRow() {
    $('.tbl tbody tr').each(function() {
      let $row = $(this);
      let $checkbox = $row.find('.selectRow');
      $row.find('select').prop('disabled', !$checkbox.prop('checked'));
    });
  }
}); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table class="tbl">
  <tr>
    <td><input type="checkbox" name="check1" class="selectRow" />amp;nbsp;</td>
    <td>
      <select class="col1" disabled="disabled">
        <option id="col1o1">A</option>
        <option id="col1o2">B</option>
        <option id="col1o3">C</option>
        <option id="col1o4">E</option>
      </select>
    </td>
    <td>
      <select class="col2" disabled="disabled">
        <option id="col2o1">A</option>
        <option id="col2o2">B</option>
        <option id="col2o3">C</option>
        <option id="col2o4">E</option>
      </select>
    </td>
    <td>
      <select class="col3" disabled="disabled">
        <option id="col3o1">A</option>
        <option id="col3o2">B</option>
        <option id="col3o3">C</option>
        <option id="col3o4">E</option>
      </select>
    </td>
  </tr>
  <br>
  <tr>
    <td><input type="checkbox" name="check1" class="selectRow"  />amp;nbsp;</td>
    <td>
      <select class="s1">
        <option id="s1o1">A</option>
        <option id="o2">B</option>
        <option id="o3">C</option>
        <option id="o4">E</option>
      </select>
    </td>
    <td>
      <select class="s2">
        <option id="s2o1">A</option>
        <option id="s2o2">B</option>
        <option id="s2o3">C</option>
        <option id="s2o4">E</option>
      </select>
    </td>
    <td>
      <select class="s3">
        <option id="s3o1">A</option>
        <option id="s3o2">B</option>
        <option id="s3o3">C</option>
        <option id="s3o4">E</option>
      </select>
    </td>
  </tr>
  <br>
  <tr>
    <td><input type="checkbox" name="check1" class="selectRow"  />amp;nbsp;</td>
    <td>
      <select class="s1">
        <option id="s1o1">A</option>
        <option id="o2">B</option>
        <option id="o3">C</option>
        <option id="o4">E</option>
      </select>
    </td>
    <td>
      <select class="s2">
        <option id="s2o1">A</option>
        <option id="s2o2">B</option>
        <option id="s2o3">C</option>
        <option id="s2o4">E</option>
      </select>
    </td>
    <td>
      <select class="s3">
        <option id="s3o1">A</option>
        <option id="s3o2">B</option>
        <option id="s3o3">C</option>
        <option id="s3o4">E</option>
      </select>
    </td>
  </tr>
</table> 

Ответ №3:

Это отлично работает! снимите все флажки, кроме того, у которого есть текущий фокус '.tbl [type="checkbox"]:not(:focus)' , затем манипулируйте полями выбора

 $(document).ready(function(){
  $('.tbl [type="checkbox"]').on('click', function() {
    $('.tbl [type="checkbox"]:not(:focus)').prop('checked', false);
    $('.tbl select').attr('disabled', true);
    $(this).parent().parent().find('select').attr('disabled', !$(this).prop('checked'));
  });
}); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table class="tbl">
<tr>
  <td><input type="checkbox" name="check1" class = "selectRow" />amp;nbsp;</td>
  <td>
   <select class="col1" disabled>
       <option id="col1o1">A</option>
       <option id="col1o2">B</option>
       <option id="col1o3">C</option>
       <option id="col1o4">E</option>
   </select>
  </td>
    <td>
   <select class="col2" disabled>
       <option id="col2o1">A</option>
       <option id="col2o2">B</option>
       <option id="col2o3">C</option>
       <option id="col2o4">E</option>
   </select>
  </td>
    <td>
   <select class="col3" disabled>
       <option id="col3o1">A</option>
       <option id="col3o2">B</option>
       <option id="col3o3">C</option>
       <option id="col3o4">E</option>
   </select>
  </td>
</tr>
<br>
<tr>
  <td><input type="checkbox" name="check1" />amp;nbsp;</td>
  <td>
   <select class="s1" disabled>
       <option id="s1o1">A</option>
       <option id="o2">B</option>
       <option id="o3">C</option>
       <option id="o4">E</option>
   </select>
  </td>
    <td>
   <select class="s2" disabled>
       <option id="s2o1">A</option>
       <option id="s2o2">B</option>
       <option id="s2o3">C</option>
       <option id="s2o4">E</option>
   </select>
  </td>
    <td>
   <select class="s3" disabled>
       <option id="s3o1">A</option>
       <option id="s3o2">B</option>
       <option id="s3o3">C</option>
       <option id="s3o4">E</option>
   </select>
  </td>
</tr>
<br>
<tr>
  <td><input type="checkbox" name="check1" />amp;nbsp;</td>
  <td>
   <select class="s1" disabled>
       <option id="s1o1">A</option>
       <option id="o2">B</option>
       <option id="o3">C</option>
       <option id="o4">E</option>
   </select>
  </td>
    <td>
   <select class="s2" disabled>
       <option id="s2o1">A</option>
       <option id="s2o2">B</option>
       <option id="s2o3">C</option>
       <option id="s2o4">E</option>
   </select>
  </td>
    <td>
   <select class="s3" disabled>
       <option id="s3o1">A</option>
       <option id="s3o2">B</option>
       <option id="s3o3">C</option>
       <option id="s3o4">E</option>
   </select>
  </td>
</tr>
</table> 

Комментарии:

1. Спасибо, это отлично работает.