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...