Если вы сталкивались с Javascript, работали с jQuery, то обработка событий браузера (таких как onclick
, onsubmit
и др.) не вызывает у вас вопросов. Представьте, что у вас есть HTML таблица с записями, для которой нужно реализовать обработку действий в пакете, например, удалить выделенные записи или переместить все выделенные статьи в категорию. Первым шагом для этого будет добавление в таблицу чекбоксов. Как реализовать подобный функционал выделения записей мы и поговорим в данной статье.
Для примера возьмем довольно простую HTML разметку:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Обработка кликов на чекбоксах</title>
</head>
<body>
<table border="1" cellspacing="2" cellpadding="10">
<thead>
<tr>
<th><input type="checkbox" id="select-all" class="chkbox" value="1" title="Выделить все" /></th>
<th>Title</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="checkbox" id="id_chk1" class="chkbox" value="1" /></td>
<td>Check 1</td>
</tr>
<tr>
<td><input type="checkbox" id="id_chk2" class="chkbox" value="2" /></td>
<td>Check 2</td>
</tr>
<tr>
<td><input type="checkbox" id="id_chk3" class="chkbox" value="3" /></td>
<td>Check 3</td>
</tr>
<tr>
<td><input type="checkbox" id="id_chk4" class="chkbox" value="4" /></td>
<td>Check 4</td>
</tr>
<tr>
<td><input type="checkbox" id="id_chk5" class="chkbox" value="5" /></td>
<td>Check 5</td>
</tr>
<tr>
<td><input type="checkbox" id="id_chk6" class="chkbox" value="6" /></td>
<td>Check 6</td>
</tr>
<tr>
<td><input type="checkbox" id="id_chk7" class="chkbox" value="7" /></td>
<td>Check 7</td>
</tr>
</tbody>
</table>
<!-- scripts -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script>
<!-- здесь будем добавлять jQuery код -->
</script>
</body>
</html>
Обычно в таких случая мы хотим иметь возможность выделять все записи одним кликом. Для этого в хедер таблицы добавлен чекбокс "Выделить все". Напишем простой обработчик кликов для него:
$('#select-all').on('click', function () {
// находим все чекбоксы
var $checkboxes = $('.chkbox');
// устанавливаем им свойство checked, такое же, как и чекбокса #select-all
$checkboxes.prop('checked', $(this).prop('checked'));
});
Теперь неплохо бы, чтоб после выделения всех чекбоксов и снятия выделения с одного, чекбокс #select-all
также отображался без выделения. И в обратном случае: если все чекбоксы выделяются один за одним, то после выделения всех, чекбокс #select-all
также выделялся. На словах сложно, на практике все просто:
$('.chkbox').on('click', function () {
var $selectAll = $('#select-all');
// находим все чекбоксы
var $checkboxes = $('.chkbox');
// находим все выделенные чекбоксы
var $allChecked = $checkboxes.filter(':checked');
// сравниваем количество всех и выбранных чекбоксов
// если равно - выделяем чекбокс #select-all
// если нет - снимаем выделение с чекбокса #select-all
$selectAll.prop('checked', $checkboxes.length === $allChecked.length);
});
Теперь представьте, что у вас на странице десятки записей (да-да, обычно их меньше благодаря разбиению страницы), а выделить нужно всего 5 или 10, но не все. Выделять поштучно не слишком-то и удобно. И снимать выделение также не удобно. Неплохо бы, чтоб при нажатии Shift мы могли выделять несколько чекбоксов, указывая только начальный и конечный в интервале. Не забываем также, что при выделении через Shift всех чекбоксов, у нас должен выделяться чекбокс #select-all
+var lastChecked = null;
-$('.chkbox').on('click', function () {
+$('.chkbox').on('click', function (e) {
var $selectAll = $('#select-all');
// находим все чекбоксы
var $checkboxes = $('.chkbox');
+
+ // если это первый выделенный чекбокс, сохраняем его как последий выделенный
+ if (!lastChecked) {
+ lastChecked = this;
+ }
+
+ // проверяем, что клавиша Shift нажата
+ if (e.shiftKey) {
+ // находим начало и конец интервала
+ var start = $checkboxes.index(this);
+ var end = $checkboxes.index(lastChecked);
+
+ // фильтруем все чекбоксы по интервалу выделения
+ $checkboxes.slice(
+ Math.min(start, end),
+ Math.max(start, end) + 1
+ )
+ // выделяем или снимаем выделение с интервала в зависимости
+ // от первого чекбокса в выделении
+ .prop('checked', lastChecked.checked)
+ }
+
+ // сохраняем последний выделенный чекбокс
+ lastChecked = this;
// находим все выделенные чексбоксы
var $allChecked = $checkboxes.filter(':checked');
// сравниваем количество всех и выбранных чекбоксов
// если равно - выделяем чекбокс #select-all
// если нет - снимаем выделение с чекбокса #select-all
$selectAll.prop('checked', $checkboxes.length === $allChecked.length);
});
Полный код обработчиков событий браузера:
<script>
$('#select-all').on('click', function () {
// находим все чекбоксы
var $checkboxes = $('.chkbox');
// устанавливаем им свойство checked, такое же, как и элемента #select-all
$checkboxes.prop('checked', $(this).prop('checked'));
});
var lastChecked = null;
$('.chkbox').on('click', function (e) {
var $selectAll = $('#select-all');
// находим все чексбоксы
var $checkboxes = $('.chkbox');
// если это первый выделенный чекбокс, сохраняем его как последий выделенный
if (!lastChecked) {
lastChecked = this;
}
// находим начало и конец интервала
var start = $checkboxes.index(this);
var end = $checkboxes.index(lastChecked);
// фильтруем все чекбоксы по интервалу выделения
$checkboxes.slice(
Math.min(start, end),
Math.max(start, end) + 1
)
// выделяем или снимаем выделение с интервала в зависимости
// от первого чекбокса в выделении
.prop('checked', lastChecked.checked);
// сохраняем последний выделенный чекбокс
lastChecked = this;
// находим все выделенные чексбоксы
var $allChecked = $checkboxes.filter(':checked');
// сравниваем количество всех и выбранных чекбоксов
// если равно - выделяем чекбокс #select-all
// если нет - снимаем выделение с чекбокса #select-all
$selectAll.prop('checked', $checkboxes.length === $allChecked.length);
});
</script>
Надеюсь, статья будет вам полезной. Если есть какие-то вопросы, пишите их в комментариях, не стесняйтесь ;)