#javascript #html #jquery
При выборе главного checkbox'а выбираются все остальные, привязанные к нему, и наоборот, при выборе всех привязанных выбирается и главный. Реализовать необходимо так, чтобы можно было использовать несколько групп на странице в пределах одной формы. Поэтому сейчас реализовано так: у главного checkbox'а есть id, который совпадает с классами зависимых checkbox'ов. Классы могут быть любые - главное что они совпадают с id главного checkbox'а. Рабочий код можно посмотреть ниже, но он слишком массивный. Есть ли более элегантные решения, желательно легко модифицируемые? $(document).on("change", "input[type=checkbox]", function() { // По изменению checkbox'а if ($(this).attr('class')) { var CBgroupID = $(this).attr('class'); } if (($(this).attr('id')) && ($('input[type="checkbox"].' + $(this).attr('id')).length)) { var CBgroupID = $(this).attr('id'); if (this.checked) { $('input[type="checkbox"].' + CBgroupID).attr('checked', 'checked'); $('input[type="button"][class*="' + CBgroupID + '"]').removeAttr('disabled'); } else { $('input[type="checkbox"].' + CBgroupID).removeAttr('checked'); $('input[type="button"][class*="' + CBgroupID+'"]').attr('disabled', 'disabled'); } } if (!CBgroupID) { return; } if ($('input[type="checkbox"].' + CBgroupID + ':not(:checked)').length) { $('input[type="checkbox"]#' + CBgroupID).removeAttr('checked'); } else { $('input[type="checkbox"]#' + CBgroupID).attr('checked', 'checked'); } if ($('input[type="checkbox"].' + CBgroupID+':checked').length) { $('input[type="button"][class*="' + CBgroupID + '"]').removeAttr('disabled'); } else { $('input[type="button"][class*="' + CBgroupID + '"]').attr('disabled', 'disabled'); } if ($('input[type="checkbox"].' + CBgroupID + ':checked').length === 1) { $('.jToEdit').removeAttr('disabled'); } else { $('.jToEdit').attr('disabled', 'disabled'); } delete CBgroupID; });Группа 1
Общий
Группа 2
Общий
Пример в fiddle.
Ответы
Ответ 1
$(document).on('change', 'input[type=checkbox]', function () { var $this = $(this), $chks = $(document.getElementsByName(this.name)), $all = $chks.filter(".chk-all"); if ($this.hasClass('chk-all')) { $chks.prop('checked', $this.prop('checked')); } else switch ($chks.filter(":checked").length) { case +$all.prop('checked'): $all.prop('checked', false).prop('indeterminate', false); break; case $chks.length - !!$this.prop('checked'): $all.prop('checked', true).prop('indeterminate', false); break; default: $all.prop('indeterminate', true); } });
Ответ 2
Можно: checkbox'ам в рамках одной группы присвоить уникальное значение data-атрибута (например, data-id). checkbox'ам, выбирающим все, дать один класс (например, .all), а остальным - другой (например, one). Тогда код может выглядеть следующим образом: JS: $(document).ready(function() { $(".all").on("change", function() { var groupId = $(this).data('id'); $('.one[data-id="' + groupId + '"]').prop("checked", this.checked); }); $(".one").on("change", function() { var groupId = $(this).data('id'); var allChecked = $('.one[data-id="' + groupId + '"]:not(:checked)').length == 0; $('.all[data-id="' + groupId + '"]').prop("checked", allChecked); }); }); HTML:Группа 1
Общий
Группа 2
Общий
Полный пример в fiddle.Ответ 3
Разбавлю ка я счастливый мирный уголок любителей jQuery суровым и прямолинейным vanilla JavaScript. Реализовывать будем так: засовываем группу checkbox'ов в обертку; на каждой обертке слушаем событие onchange; на каждое событие меняем количество отмеченных checkbox'ов, в зависимости от этого мы можем убрать/поставить "главный" checkbox если же нажали на "главный" checkbox, то выделяем или снимаем выделение со всех checkbox в обертке. Прилагаю свой пример, полная версия на jsFiddle: var count = item.getElementsByClassName('js-checkbox').length; var currentCount = 0; item.addEventListener('change', function(evt) { if (evt.target.classList.contains('js-checkbox-main')) { if (evt.target.checked) { setAllCheckboxes(item, true); currentCount = count; } else { setAllCheckboxes(item, false); currentCount = 0; } } else { evt.target.checked ? ++currentCount : --currentCount; console.log(currentCount) if (currentCount == count) { setAllCheckboxes(item, true); } else if (currentCount == count - 1){ if (!evt.target.checked) { item.getElementsByClassName('js-checkbox-main')[0].checked = false; } } } }, false); Операция getElementsByClassName(), особенно не от корня, очень быстрая, так что если количество checkbox будет динамически изменяться, их количество легко и незаметно для глаза можно пересчитывать на каждое сгенерированное событие. Код полностью независим от каких-либо библиотек. Уверен jQuery делает это примерно также (могу обманывать в этом утверждении, но как сделать это по другому просто не приходит в голову). Интересно было бы протестировать скорость работы обоих вариантов, но почему-то мне кажется, что разница может быть заметна только на очень большом количестве элементов, которые в пользовательском интерфейсе будут глупо достаточно выглядеть. Поэтому данный ответ имеет смысл только в том случае, когда в вашем проекте практически нет jQuery и Вы хотите от него уйти или никто его не знает в команде jQuery (странновато звучит), или в чисто академических целях.)
Комментариев нет:
Отправить комментарий