SuperDuper Checkboxes With Table

by Bruno G.

HTML

<table class="checkbox-grid">
    <thead>
        <tr>
            <th class="row-header"><button type="button" class="btnAll">All</button></th>
            <th class="col-header">Option 1</th>
            <th class="col-header">Option 2</th>
            <th class="col-header">Option 3</th>
            <th class="col-header">Option 4</th>
            <th class="col-header">Option 5</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td class="row-header">Label 1</td>
            <td><label for="r1c1"><input type="checkbox" id="r1c1"></label></td>
            <td><label for="r1c2"><input type="checkbox" id="r1c2"></label></td>
            <td><label for="r1c3"><input type="checkbox" id="r1c3"></label></td>
            <td><label for="r1c4"><input type="checkbox" id="r1c4"></label></td>
            <td><label for="r1c5"><input type="checkbox" id="r1c5"></label></td>
        </tr>
        <tr>
            <td class="row-header">Label 2</td>
            <td><label for="r2c1"><input type="checkbox" id="r2c1"></label></td>
            <td><label for="r2c2"><input type="checkbox" id="r2c2"></label></td>
            <td><label for="r2c3"><input type="checkbox" id="r2c3"></label></td>
            <td><label for="r2c4"><input type="checkbox" id="r2c4"></label></td>
            <td><label for="r2c5"><input type="checkbox" id="r2c5"></label></td>
        </tr>
        <tr>
            <td class="row-header">Label 3</td>
            <td><label for="r3c1"><input type="checkbox" id="r3c1"></label></td>
            <td><label for="r3c2"><input type="checkbox" id="r3c2"></label></td>
            <td><label for="r3c3"><input type="checkbox" id="r3c3"></label></td>
            <td><label for="r3c4"><input type="checkbox" id="r3c4"></label></td>
            <td><label for="r3c5"><input type="checkbox" id="r3c5"></label></td>
        </tr>
    </tbody>
</table>

<table class="checkbox-grid">
    <thead>
        <tr>
            <th class="row-header"></th>
         ...

CSS

.checkbox-grid .checked {
    background-color: #007bff;
    color: white;
}

JavaScript

(function ($) {
    $.fn.checkboxGrid = function () {
        return this.each(function () {
            const $table = $(this);
            let lastChecked = null;

            // Handle checkbox click with Shift key for range selection
            $table.on('click', 'input[type=checkbox]', function (event) {
                const $checkboxes = $table.find('tbody input[type=checkbox]');
                if (lastChecked && event.shiftKey) {
                    const start = $checkboxes.index(lastChecked);
                    const end = $checkboxes.index(this);
                    const min = Math.min(start, end);
                    const max = Math.max(start, end);
                    const checkState = lastChecked.checked;
                    $checkboxes.slice(min, max + 1).prop('checked', checkState);
                }
                lastChecked = this;
            });

            // Handle row toggle
            $table.on('click', 'tbody th.row-header', function () {
                const $row = $(this).closest('tr');
                const $rowCheckboxes = $row.find('input[type=checkbox]');
                const checkState = $rowCheckboxes.first().prop('checked');
                $rowCheckboxes.prop('checked', !checkState);
            });

            // Handle column toggle
            $table.on('click', 'thead th.col-header', function () {
                const colIndex = $(this).index();
                const $colCheckboxes = $table.find(`tbody tr td:nth-child(${colIndex + 1}) input[type=checkbox]`);
                const checkState = $colCheckboxes.first().prop('checked');
                $colCheckboxes.prop('checked', !checkState);
            });

            // Handle Ctrl-A to toggle all checkboxes
            $(document).on('keydown', function (event) {
                if (event.ctrlKey && event.key.toLowerCase() === 'a') {
                    event.preventDefault();
                    const $upperLeftCheckbox = $table.find('tbody tr:nth-child(2)...