SuperDuper Checkboxes
by Bruno G.
HTML
<form method="post">
<div class="checkbox-column" data-group="column1">
<label><input type="checkbox" name="col1[]" value="apple"> Apple</label>
<label><input type="checkbox" name="col1[]" value="banana"> Banana</label>
<label><input type="checkbox" name="col1[]" value="cherry"> Cherry</label>
<label><input type="checkbox" name="col1[]" value="date"> Date</label>
<label><input type="checkbox" name="col1[]" value="elderberry"> Elderberry</label>
<label><input type="checkbox" name="col1[]" value="fig"> Fig</label>
<label><input type="checkbox" name="col1[]" value="grape"> Grape</label>
<label><input type="checkbox" name="col1[]" value="honeydew"> Honeydew</label>
<label><input type="checkbox" name="col1[]" value="kiwi"> Kiwi</label>
<label><input type="checkbox" name="col1[]" value="lemon"> Lemon</label>
</div>
<div class="checkbox-column" data-group="column2">
<label><input type="checkbox" name="col2[]" value="dog"> Dog</label>
<label><input type="checkbox" name="col2[]" value="cat"> Cat</label>
<label><input type="checkbox" name="col2[]" value="mouse"> Mouse</label>
<label><input type="checkbox" name="col2[]" value="rabbit"> Rabbit</label>
<label><input type="checkbox" name="col2[]" value="parrot"> Parrot</label>
<label><input type="checkbox" name="col2[]" value="hamster"> Hamster</label>
<label><input type="checkbox" name="col2[]" value="ferret"> Ferret</label>
<label><input type="checkbox" name="col2[]" value="goldfish"> Goldfish</label>
<label><input type="checkbox" name="col2[]" value="turtle"> Turtle</label>
<label><input type="checkbox" name="col2[]" value="snake"> Snake</label>
</div>
<div class="checkbox-column" data-group="column3">
<label><input type="checkbox" name="col3[]" value="red"> Red</label>
<label><input type="checkbox" name="col3[]" value="blue">...
CSS
.checkbox-column {
display: inline-block;
margin-right: 20px;
vertical-align: top;
}
label {
display: block;
cursor: pointer;
user-select: none; /* Prevents text selection */
}
input[type="checkbox"]:focus {
outline: 2px solid blue; /* Ensures consistent focus outline */
}
JavaScript
(function ($) {
$.fn.multiSelectCheckboxes = function () {
return this.each(function () {
const $group = $(this);
let lastChecked = null;
let lastCheckedState = null;
function toggleRange($start, $end, checkState) {
const $columns = $group.find('.checkbox-column');
const $startCol = $start.closest('.checkbox-column');
const $endCol = $end.closest('.checkbox-column');
const startColIndex = $columns.index($startCol);
const endColIndex = $columns.index($endCol);
const [minCol, maxCol] = [startColIndex, endColIndex].sort((a, b) => a - b);
const checkboxesInColumns = $columns.slice(minCol, maxCol + 1).map((_, col) => $(col).find('input[type=checkbox]')).get();
const startIndex = $startCol.find('input[type=checkbox]').index($start);
const endIndex = $endCol.find('input[type=checkbox]').index($end);
const [minIndex, maxIndex] = [startIndex, endIndex].sort((a, b) => a - b);
checkboxesInColumns.forEach($colCheckboxes => {
$colCheckboxes.slice(minIndex, maxIndex + 1).prop('checked', checkState);
});
}
$group.find('.checkbox-column').on('click', 'input[type=checkbox]', function (e) {
if (e.shiftKey && lastChecked) {
toggleRange($(lastChecked), $(this), lastCheckedState);
}
lastChecked = this;
lastCheckedState = this.checked;
});
$group.find('.checkbox-column').on('keydown', 'input[type=checkbox]', function (e) {
const $checkboxes = $(this).closest('.checkbox-column').find('input[type=checkbox]');
const currentIndex = $checkboxes.index(this);
if (currentIndex ===...