Включить / отключить все входы и флажки с любым отмеченным флажком

У меня есть форма со многими текстовыми полями ввода и флажками. Всякий раз, когда флажок установлен, все поля ввода текста и все другие флажки (кроме того, который был отмечен) должны быть отключены. После снятия этого флажка все отключенные поля должны снова стать активными. Это работает со следующим кодом (показаны только первые 3 строки):

<form id="myForm">

    Checkbox 1: <input type="checkbox" name="checkbox1" id="checkboxOne" onclick="enableDisableAll();" />
    <input type="text" id="id1" name="name1" /><br>

    Checkbox 2: <input type="checkbox" name="checkbox2" id="checkboxTwo" onclick="enableDisableAll();" />
    <input type="text" id="id2" name="name2" /><br>

    Checkbox 3: <input type="checkbox" name="checkbox3" id="checkboxThree" onclick="enableDisableAll();" />
    <input type="text" id="id3" name="name3" /><br>

</form>


function enableDisableAll() {

    cb1 = document.getElementById('checkboxOne').checked;
    cb2 = document.getElementById('checkboxTwo').checked;
    cb3 = document.getElementById('checkboxThree').checked;


    document.getElementById('checkboxOne').disabled = (cb2 || cb3);
    document.getElementById('id1').disabled = (cb1 || cb2 || cb3);

    document.getElementById('checkboxTwo').disabled = (cb1 || cb3);
    document.getElementById('id2').disabled = (cb1 || cb2 || cb3);

    document.getElementById('checkboxThree').disabled = (cb1 || cb2);
    document.getElementById('id3').disabled = (cb1 || cb2 || cb3);

}

Поскольку код становится запутанным из-за множества флажков (cb1 || cb2 || cb3 || ....... cb(n)), мне интересно, есть ли более элегантная возможность сделать это, например:

функция enableDisableAll() {

cb1 = document.getElementById('checkboxOne').checked;
cb2 = document.getElementById('checkboxTwo').checked;
cb3 = document.getElementById('checkboxThree').checked;

var cb_array = [];

cb_array.push("cb1");
cb_array.push("cb2");

var cb_array_imploded = cb_array.join(" || ");

document.getElementById('id1').disabled = (cb_array_imploded);

К сожалению, это не работает.

У кого-нибудь есть простое решение моей проблемы?


person Columbus    schedule 10.06.2017    source источник


Ответы (3)


выберите все элементы формы, выполните цикл и проверьте идентификатор, такой же, как id элемента, по которому щелкнули, поэтому не отключайте его.

function enableDisableAll(e) {
        var own = e;
        var form = document.getElementById("myForm");
        var elements = form.elements;

    for (var i = 0 ; i < elements.length ; i++) {
          if(own !== elements[i] ){
          
            if(own.checked == true){
              
              elements[i].disabled = true;  
             
            }else{
            
              elements[i].disabled = false;  
            }
          
           }

     }
    
}

function clearAll(){
 document.getElementById("myForm").reset();
}
<form id="myForm">

    Checkbox 1: <input type="checkbox" name="checkbox1" id="checkboxOne" onclick="enableDisableAll(this);" />
    <input type="text" id="id1" name="name1" /><br>

    Checkbox 2: <input type="checkbox" name="checkbox2" id="checkboxTwo" onclick="enableDisableAll(this);" />
    <input type="text" id="id2" name="name2" /><br>

    Checkbox 3: <input type="checkbox" name="checkbox3" id="checkboxThree" onclick="enableDisableAll(this);" />
    <input type="text" id="id3" name="name3" /><br>
 
   

</form>

<input class="field button2" type="button" value="Clear form" size="10" onclick="clearAll(this);">

Обновление: Чтобы очистить все поля формы

document.getElementById("myForm").reset();
person Dinesh undefined    schedule 10.06.2017
comment
Динеш, отключение работает отлично, но нет включения, когда соответствующий флажок снова снят - person Columbus; 10.06.2017
comment
@Dinesh, ваше решение не сработало бы, если бы у элементов не было атрибута ID - person Freeman Lambda; 10.06.2017
comment
@Dinesh Поскольку ваш ответ принят, пожалуйста, обновите его, чтобы он не зависел от идентификаторов. Вы можете напрямую сравнивать ссылки на элементы: own !== elemets[i] - person Freeman Lambda; 10.06.2017
comment
Динеш, последний вопрос: с вашим кодом также должна быть возможность очистить все элементы формы. Я попробовал это с помощью document.myForm.elements[i].value = ; вместо elements[i].disabled = true; но это не сработало. - person Columbus; 10.06.2017
comment
@Columbus обновил мой ответ для вас. Проверь сейчас. это ты хотел? - person Dinesh undefined; 10.06.2017
comment
Прости, Динеш, за то, что не очень хорошо выразился! Я хотел бы очистить все поля (входы, флажки и параметры выбора) нажатием кнопки очистки НЕЗАВИСИМО от функции включения/отключения, но с использованием аналогичного цикла. - person Columbus; 10.06.2017
comment
проверить ответ сейчас. используйте reset в своей форме. нет необходимости зацикливаться - person Dinesh undefined; 10.06.2017
comment
Спасибо, так как я использую php для сохранения значений после отправки в полях (например, ‹?php if(isset($_POST['name'])) echo checked='checked'; ?›) Я думаю, что не могу использовать reset, могу я? Как я могу просто изменить ваш цикл, чтобы получить четкую функцию для всей формы? - person Columbus; 10.06.2017
comment
Давайте продолжим обсуждение в чате. - person Dinesh undefined; 10.06.2017

Один из возможных подходов заключается в следующем; хотя обратите внимание, что я изменил ваш HTML, обернув элементы <input type="checkbox"> в родительский элемент <label> и удалив ненужные элементы <br /> вместе с навязчивыми встроенными обработчиками событий в HTML:

// a named function bound to an element via
// via JavaScript; the 'event' argument
// is passed automatically from the
// EventTarget.addEventListener() method:
function disableIfChecked(event) {

  // the event.target node is the node upon which
  // the listened-for event was originally triggered:
  let target = event.target;

  // 'this' is also passed from the
  // EventTarget.addEventListener() method; here
  // retrieved all <input> elements within the
  // <form> (the 'this'), convert that NodeList
  // explicitly to an Array and then filter that
  // Array using an Arrow function:
  Array.from(this.querySelectorAll('input')).filter(

    // we retain only those elements ('el') in the Array
    // which are not equal to, and therefore are not, the
    // changed element:
    el => el !== target

    // iterating over the filtered collection:
  ).forEach(

    // each <input> element remaining in the collection
    // will be disabled if the changed element is clicked,
    // or enabled if the changed element is no longer clicked:
    el => el.disabled = target.checked
  );
}

document.querySelector('#myForm').addEventListener('change', disableIfChecked);
/* Selecting the <label> element that follows
   an <input> element: */

input+label::before {
  /* Adding a line-feed character using the CSS
     'content' property of the pseudo-element
     to force each <label> to a new-line: */
  content: '\A';
  display: block;
}
<form id="myForm">

  <!-- the label element associates the text with the enclosed
       input, so clicking the text focuses that input element: -->
  <label>Checkbox 1: <input type="checkbox" name="checkbox1" id="checkboxOne" /></label>
  <input type="text" id="id1" name="name1" />

  <label>Checkbox 2: <input type="checkbox" name="checkbox2" id="checkboxTwo" /></label>
  <input type="text" id="id2" name="name3" />

  <label>Checkbox 3: <input type="checkbox" name="checkbox3" id="checkboxThree" /></label>
  <input type="text" id="id3" name="name3" />

</form>

JS Fiddles: с комментариями, раскомментировано

Для поддержки браузеров без поддержки ES6 следующий альтернативный подход делает то же самое:

// a named function bound to an element via
// via JavaScript; the 'event' argument
// is passed automatically from the
// EventTarget.addEventListener() method:
function disableIfChecked(event) {

  // the event.target node is the node upon which
  // the listened-for event was originally triggered:
  let target = event.target;

  // 'this' is also passed from the
  // EventTarget.addEventListener() method; here
  // retrieved all <input> elements within the
  // <form> (the 'this'), convert that NodeList
  // explicitly to an Array by treating the NodeList
  // as an Array, using Function.prototype.call(),
  // and Array.prototype.slice():
  Array.prototype.slice.call(
    this.querySelectorAll('input')
  ).filter(function(el) {

    // we retain only those elements ('el') in the Array
    // which are not equal to, and therefore are not, the
    // changed element:
    return el !== target;

    // iterating over the filtered collection:
  }).forEach(function(el) {

    // each <input> element remaining in the collection
    // will be disabled if the changed element is clicked,
    // or enabled if the changed element is no longer clicked:
    el.disabled = target.checked;
  });
}

document.querySelector('#myForm').addEventListener('change', disableIfChecked);
/* Selecting the <label> element that follows
   an <input> element: */

input+label::before {
  /* Adding a line-feed character using the CSS
     'content' property of the pseudo-element
     to force each <label> to a new-line: */
  content: '\A';
  display: block;
}
<form id="myForm">

  <!-- the label element associates the text with the enclosed
       input, so clicking the text focuses that input element: -->
  <label>Checkbox 1: <input type="checkbox" name="checkbox1" id="checkboxOne" /></label>
  <input type="text" id="id1" name="name1" />

  <label>Checkbox 2: <input type="checkbox" name="checkbox2" id="checkboxTwo" /></label>
  <input type="text" id="id2" name="name3" />

  <label>Checkbox 3: <input type="checkbox" name="checkbox3" id="checkboxThree" /></label>
  <input type="text" id="id3" name="name3" />

</form>

JS Fiddles.

Использованная литература:

person David says reinstate Monica    schedule 10.06.2017
comment
Спасибо, Дэвид Томас, за ваше предложение, но, к сожалению, это не работает. - person Columbus; 10.06.2017
comment
Для меня это работает в Chrome, Opera, Firefox и Edge, как в опубликованном фрагменте, так и во внешних демонстрациях JS Fiddle; в вашем собственном использовании, что происходит вместо этого? Есть ошибки? - person David says reinstate Monica; 10.06.2017
comment
Когда я запускаю фрагмент кода, я получаю следующую ошибку: Ошибка: {сообщение: Syntaxfehler, имя файла: stacksnippets.net/js, строка: 56, строка: 9 } - person Columbus; 10.06.2017
comment
Какой браузер вы используете Columbus, похоже, он не поддерживает ES6 - person Freeman Lambda; 10.06.2017
comment
Вы случайно не пользуетесь Internet Explorer? Я только что попробовал это с IE, и, как и ожидалось, это не удалось; Я опубликую обновленную версию с обратной совместимостью на мгновение. - person David says reinstate Monica; 10.06.2017

Обычно лучше использовать событие onchange вместо onclick для входных данных, таких как флажки, радиокнопки или выборки.

Чтобы сделать общее решение для стольких входных данных, сколько вам нужно, лучше всего использовать document.querySelectorAll для получения всех входных данных в форме. Затем вы можете перебрать все входные данные и установить для их свойства disabled значение checked целевого checkbox.

Фрагмент решения ниже:

function enableDisableAll(event) {
  var allInputs = document.querySelectorAll('#myForm input');

  allInputs.forEach(function(input) {
    if (input !== event.target) {
      input.disabled = event.target.checked;
    }
  });
}
<form id="myForm">

  Checkbox 1: <input type="checkbox" name="checkbox1" id="checkboxOne" onchange="enableDisableAll(event);" />
  <input type="text" id="id1" name="name1" /><br> Checkbox 2: <input type="checkbox" name="checkbox2" id="checkboxTwo" onchange="enableDisableAll(event);" />
  <input type="text" id="id2" name="name2" /><br> Checkbox 3: <input type="checkbox" name="checkbox3" id="checkboxThree" onchange="enableDisableAll(event);" />
  <input type="text" id="id3" name="name3" /><br>

</form>

Важной деталью здесь является то, что если вы хотите назначить типичную функцию обработчика событий непосредственно атрибуту HTML, функция должна иметь один параметр с явным именем event. Однако рекомендуется назначать обработчики событий в javascript, а не в HTML. Синтаксис для этого будет myCheckbox.addEventListener('change', enableDisableAll); Вы можете добавить слушателей к каждому флажку, перебирая селектор всех флажков.

person Freeman Lambda    schedule 10.06.2017