Я пытаюсь написать базовую функцию на чистом JS, которая просто проверяет количество отмеченных флажков, и если это число превышает определенное количество, отключает остальные. Я легко могу добиться этого в jQuery, но пытаюсь заставить его работать на чистом JS. У меня есть CodePen, настроенный здесь, и я включаю свой рабочий JS ниже. Спасибо за понимание здесь.
(function() {
var checkboxes = document.querySelectorAll('input[id^ = "mktoCheckbox"]');
var active = document.querySelectorAll('input[id^ = "mktoCheckbox"]:checked');
var numActive = active.length;
console.info(numActive);
if (numActive > 1) {
for(var i = 0; i < checkboxes.length; i++){
if (checkboxes[i].checked == true) {
return;
} else {
checkboxes[i].disabled == true;
}
}
}
})();
Я подозреваю, что вас сбил с толку тот факт, что при использовании jQuery часто можно использовать $.each, который принимает функцию в качестве аргумента. В этом случае возврат из функции просто прервет текущую итерацию. for не использует обратный вызов функции, а скорее является самостоятельным выражением, поэтому возврат завершит весь цикл.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


В вашем коде есть две проблемы:
if, которое приводит к завершению цикла.true атрибуту disabled, вместо этого вы сравниваете с ==.Измените связанный фрагмент на следующий, чтобы он работал:
if (numActive > 1) {
for (var i = 0; i < checkboxes.length; i++) {
if (checkboxes[i].checked != true) {
checkboxes[i].disabled = true;
}
}
}
Вы можете найти рабочую вилку своего пера здесь. Ниже приведен рабочий фрагмент SO:
(function() {
var checkboxes = document.querySelectorAll('input[id^ = "mktoCheckbox"]');
var active = document.querySelectorAll('input[id^ = "mktoCheckbox"]:checked');
var numActive = active.length;
console.info(numActive);
if (numActive > 1) {
for (var i = 0; i < checkboxes.length; i++) {
if (checkboxes[i].checked != true) {
checkboxes[i].disabled = true;
}
}
}
})();<fieldset>
<legend>Choose some monster features</legend>
<div>
<input type = "checkbox" id = "mktoCheckbox_1" name = "feature" value = "scales" checked />
<label for = "scales">Scales</label>
</div>
<div>
<input type = "checkbox" id = "mktoCheckbox_2" name = "feature" value = "horns" />
<label for = "horns">Horns</label>
</div>
<div>
<input type = "checkbox" id = "mktoCheckbox_3" name = "feature" value = "claws" />
<label for = "claws">Claws</label>
</div>
<div>
<input type = "checkbox" id = "mktoCheckbox_4" name = "feature" value = "tails" checked />
<label for = "tails">Tails</label>
</div>
</fieldset>Вот рабочая ручка.
Прежде всего, imo, вы должны использовать getAttribute и setAttribute на элементах DOM. HTMLInputElement.checked afaik отражает только атрибут checked (и преобразует его в boolean) для удобства.
Имея это в виду, теперь вам нужно протестировать строки с помощью оператора строгого сравнения ===. Например.
if (checkbox.getAttribute('checked') === 'true') {...}
поскольку использование == будет оцениваться как ложное
true == 'true' // false
Кроме того, вместо цикла для вы можете использовать цикл для-из для коллекций DOM. Т.е. это работает:
const checkboxes = document.querySelectorAll('...');
for(const checkbox of checkboxes) {
...
}
Имейте в виду, что для управления петлей вы используете continue и break, а не return.
Хотя getAttribute и setAttribute жизненно важно знать в чистом js, .checked все еще работает в этом случае (и может быть быстрее)
Из любопытства - я вижу, что этот ответ был отклонен; для моего собственного назидания, есть ли причина, по которой это менее желательный / эффективный подход, чем выбранный ответ выше?
Боюсь, я проголосовал против, потому что на самом деле он не отвечал на вопрос и на самом деле немного вводил в заблуждение, например в этом случае вы можете полностью использовать атрибут .checked. Также я не совсем уверен, что имелось в виду под комментарием о преобразовании типов, но похоже, что они предполагают, что true == 'true' разрешится как false, что неверно. В противном случае true == 'true' разрешает как истину, а true === 'true' разрешает как ложь (как правило, вы всегда должны использовать строгое равенство === для более надежного кода).
@ChrisM Я только что проверил это в консоли в Chrome, и true == 'true' оценивается как false. Не понимаю, почему вы думаете иначе. Спорный вопрос, использовать ли свойство getAttribute/setAttribute или checked. Но они эквивалентны при правильном тесте, и вы можете утверждать, что атрибут является более стандартным, поскольку свойство checked вычисляется из атрибута. Кроме того, я на самом деле отвечаю на вопрос, предоставляя рабочий код?
@ FK82 Верно, мой плохой true == 'true' - фальшивка. Думаю, я, должно быть, думал о случае с числами (developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…), но в данном случае это немного спорный вопрос, потому что таков и true === 'true'. Это правда, что нужно иметь привычку использовать ===, но ваш комментарий сбивает с толку в этом контексте. Хотя вы ссылались на рабочий пример, он не был адекватно объяснен в основном тексте вашего ответа. Само по себе это не является основанием для голосования против, но это сбивает с толку тело. Простите. Я ценю, что вы пытаетесь помочь :)
Я сейчас почесываю голову, потому что почти уверен, что где-то есть язык, где, к сожалению, true == 'true' верен, но я не уверен, какой именно. Я всегда использую '===' с JS, поэтому мое предположение никогда не проверялось. Возможно, PHP? Хм исчезает в дыре Google
@ChrisM Я обновил свой ответ, чтобы прояснить моменты, которые, по вашему мнению, сбивают с толку. Кстати, я почти уверен, что можно забыть любой язык, где true == 'true'. Когда-то можно / нужно терпеть столько гибкости шрифтов. ; )
@ FK82 Я снял голос против. Возможно, мне следовало бы скорее попросить разъяснений, чем просто проголосовать против. Кстати, это было PHP, но только потому, что все непустые строки считаются истинными в этом безумном мире. крики
У вас есть оператор
return;в вашем цикле. Это приведет к выходу из цикла, когда он встретит первый установленный флажок. В вашем примере это первый, поэтому ничего не происходит. Кроме того, вы используете оператор равенства в другом предложении блокаif:checkboxes[i].disabled == true;Это должно бытьcheckboxes[i].disabled = true;, если вы хотите установить для свойства значениеtrue.