A lot of good answers to a very old question, however none of them take into consideration that most people click on the checkbox label when selecting an option, not the checkbox itself. Below are a couple of listeners that allow you to click on a checkbox or its accompanying label to select a range.
The only assumption made about the HTML is that the checkbox has an ID and that the ID starts with the string "checkbox" (thus the accompanying label for
tag value starts with checkbox
).
$(document).ready(function() {
// Disable the text selection that would otherwise happen on shift+click
$("input[type='checkbox'], label[for^='checkbox']").on("mousedown", function (e) {
if(e.shiftKey) {
window.getSelection().removeAllRanges();
}
});
$("input[type='checkbox'], label[for^='checkbox']").on("click", function (e) {
// We're not actually interested in the label clicks themselves
if($(this).attr("for")){
// Because if a label is clicked, the checkbox will be clicked too
return;
}
// Get all the checkboxes
var checkboxes = $(`input[name='${$(this).attr("name")}']`);
// If there are no checked checkboxes, check this first one
if(!checkboxes.filter(function() {
return $(this).data('last-checked');
}).length){
$(this).data("last-checked", true);
return;
}
// If the shift key is held down, select the range
if(e.shiftKey){
var start = checkboxes.index($(this));
var end = checkboxes.index(checkboxes.filter(function() {
return $(this).data('last-checked');
}));
checkboxes.slice(Math.min(start,end), Math.max(start,end)+ 1).prop('checked', $(this).prop("checked"));
}
// Deselect everything and only mark the last checked
for (const box of checkboxes) {
$(box).data("last-checked", false);
}
$(this).data("last-checked", true);
});
});