JSFiddle - React, Tailwind, and code Playground

by doug65536

HTML

<table class='journal'>
    <thead>
        <tr class='header'>
            <th class='title' colspan="5">120625-Scorpan</th>
            <th class='checkbox'>
                <input type="checkbox" />
            </th>
            <th class='notes'>
                <textarea cols="20" rows="3"></textarea>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td class='name'>Alex Scorpan</td>
            <td>(email)</td>
            <td>2013-10-15</td>
            <td>1</td>
            <td>no</td>
            <td class='checkbox'>
                <input type="checkbox" />
            </td>
            <td></td>
        </tr>
        <tr>
            <td class='name'>Joseph Crawford</td>
            <td>(email)</td>
            <td>2013-10-15</td>
            <td class="over-limit">2</td>
            <td>yes</td>
            <td class='checkbox'>
                <input type="checkbox" />
            </td>
            <td></td>
        </tr>
    </tbody>
</table>

<table class='journal'>
    <thead>
        <tr class='header'>
            <th class='title' colspan="5">120625-Scorpan</th>
            <th class='checkbox'>
                <input type="checkbox" />
            </th>
            <th class='notes'>
                <textarea cols="20" rows="3"></textarea>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td class='name'>Alex Scorpan</td>
            <td>(email)</td>
            <td>2013-10-15</td>
            <td>1</td>
            <td>no</td>
            <td class='checkbox'>
                <input type="checkbox" />
            </td>
            <td></td>
        </tr>
        <tr>
            <td class='name'>Joseph Crawford</td>
            <td>(email)</td>
            <td>2013-10-15</td>
            <td class="over-limit">2</td>
            <td>yes</td>
            <td class='checkbox'>
                <input type="checkbox" />
            </td>
            <td></td>
        </tr>
   ...

CSS

.journal {
        width: 60%;
        min-width: 800px;
        padding-left: 20px;
        padding-right: 20px;
        padding-top: 5px;
        border-top: 2px solid #929292;
    }
    .journal th, .journal td {
        vertical-align: top;
        text-align: left;
    }
    .journal td {
        width: 15%;
        white-space: nowrap;
    }
    .journal .header .title {
        font-style: italic;
        font-size: 1.4em;
        text-align: left;
    }
    .journal .notes {
        font-style: normal;
        font-size: 1em;
    }
    .journal .checkbox {
        text-align: center;
    }
    .journal .header {
        padding-bottom: 1em;
    }
    .journal .name {
        padding-left: 5em;
        text-align: left;
        padding-right: 5em;
    }
    .journal .over-limit {
        color: #b6001a;
        font-weight: bold;
    }

JavaScript

$(function() {
    // Set one event handler per table - only get change events for checkboxes
    $('table.journal').on('change', 'input[type=checkbox]', function() {
        // element = what they changed
        var element = $(this);
        
        // Search through the parents and find the closest table element
        var table = element.closest('table');
        
        // Make an array of everything between what they checked and the table element
        var parents = element.parentsUntil(table);
        
        // If they checked something under thead
        if (parents.filter('thead').length > 0) {
            // Set all the checkboxes in tbody to match the thead
            $('tbody input[type=checkbox]', table).prop('checked', element.is(':checked'));
        } else {
            // Count the checked checkboxes and all the checkboxes
            var checkboxes = $('tbody input[type=checkbox]', table);
            var checked = $('tbody input[type=checkbox]:checked', table);
            var headcheck = $('thead input[type=checkbox]', table);
            // Set checked if all checked, not checked if not all checked
            headcheck.prop('checked', checked.length == checkboxes.length);
            // Set indeterminate if some checked
            headcheck.prop('indeterminate', checked.length != 0 && checked.length != checkboxes.length);
        }
    });
});