JSFiddle - React, Tailwind, and code Playground

by radu

HTML

<table id="foo">
    <colgroup>
        <col class="check">
        <col class="name">
    </colgroup>
    <thead>
        <tr>
            <th><input type="checkbox" id="all"></th>
            <th>Name</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><input type="checkbox"></td>
            <td>Example</td>
        </tr>
        <tr>
            <td><input type="checkbox"></td>
            <td>Example</td>
        </tr>
        <tr>
            <td><input type="checkbox"></td>
            <td>Sequence</td>
        </tr>
        <tr>
            <td><input type="checkbox"></td>
            <td>Example</td>
        </tr>
        <tr>
            <td><input type="checkbox"></td>
            <td>Example</td>
        </tr>
        <tr>
            <td><input type="checkbox"></td>
            <td>Example</td>
        </tr>
        <tr>
            <td><input type="checkbox"></td>
            <td>Example</td>
        </tr>
        <tr>
            <td><input type="checkbox"></td>
            <td>Example</td>
        </tr>
        <tr>
            <td><input type="checkbox"></td>
            <td>Example</td>
        </tr>
        <tr>
            <td><input type="checkbox"></td>
            <td>Test</td>
        </tr>
        <tr>
            <td><input type="checkbox"></td>
            <td>Example 2</td>
        </tr>
        <tr>
            <td><input type="checkbox"></td>
            <td>Example 2</td>
        </tr>
        <tr>
            <td><input type="checkbox"></td>
            <td>Example 2</td>
        </tr>
    </tbody>
</table>

CSS

#foo {
    border-collapse:collapse;
    clear:both;
    margin-bottom:10px;
    -webkit-user-select:none;
    user-select:none;
    width:100%;
}
thead {
    border-bottom:2px solid gray;
    color:gray;
}
th {
    cursor:pointer;
    text-align:center;
}
tbody {
    color:black;
}
tr {
    border-bottom:1px solid lightgray;
    height:22px;
}
.selected {
    background:#FFE433!important;
}
tr:nth-child(odd).selected {
    background:#FFFC4D!important;
}
input[type="checkbox"] {
    display:inline;
    float:left;
    margin-left:30px;
}

JavaScript

App = {};
App.select = 0;            // used for keypress events
App.$selected = null;      // stores previously selected element
App.checkClick = false;    // used to separate clicks on checkboxes from clicks on tr elements. 
                           // Can't stop event propagation since they must be bound with delegate() or live()

$('body').keydown(function(e) {
    var code = (e.keyCode ? e.keyCode : e.which);
    // CTRL = 17, SHIFT = 16
    if (code === 17) App.select = 'multi';
    else if (code === 16) App.select = 'range';
    else App.select = 0;
}).keyup(function() {
    App.select = 0;
});
    
$('tbody').delegate('tr input:checkbox', 'change', function(e) {
    if (e.target.id == 'all') return;
    
    var $tr = $(this).parents('tr');
    
    if (App.select === 'range') {
        selectRowRange($tr);
    } else {
        App.checkClick = true;
        $tr.toggleClass('selected');
        App.$selected = $tr;
    }
});
    
$('tbody').delegate('tr', 'click', function() {
    var $self = $(this);

    $('#all')[0].checked = false;
    
    if (!App.checkClick) {                
        if (App.select === 'range') {
            selectRowRange($self);
        } else {
            // deselect all rows unless CTRL key is held down
            if (App.select === 0) rowSelectChange($('.selected'), false);
            rowSelectChange($self, !$self.hasClass('selected'));
            App.$selected = $self;
        }
    }
    App.checkClick = false;
});
    
$('#all').click(function() {
    rowSelectChange($('tr'), $(this)[0].checked);
});


function rowSelectChange($obj, select) {
    $obj.toggleClass('selected', select)
        .find('input:checkbox')
        .each(function(){$(this).prop('checked', select)});
}

function selectRowRange($self) {
    var group,
        lastSelected = App.$selected;
    // conditional below is true when the dom element is after lastSelected
    // when using add(), jQuery keeps elements in DOM order
    // also, select from...