correct synchronisation between toggling the 'select all' checkbox and the cloned checkbox in the sticky header.

Correct shift-click behavior

If the select all checkbox (both in the sticky header and the regular header) gets checked automatically if all checkboxes are selected, either manually and/or via shift click. Possibly mixed in with disabled checkboxes.

This is similar to the old code, but a possible improvement would be only updating the selectAll if it doesn't have the state it should have. Could be done by simply keeping track of the selectAll state in the object.

Going to fix the @todo and add the comment in #10 somewhere today. Also going to see if I can make the initial creation and state of the tableselect more robust (ie for the edgecase where all checkboxes are already checked at pageload).

By the way: I realize that it looks like there are over 4 times as much lines added than removed; after minification this will change to a little less than 2x the number of characters (1500 old minified file vs ~2900 characters new minified file). I'd call the code increase due to having a bit more explicite coding style, more comments, ability to handle multiple tableselects on the same page, and a detach event.

+ if ($selectAll.length) {+ if ($table.find('td input:checkbox').length !== 0) {+ if ($stickyTable.length === 1) {
Is there a convention how to check for existence of jQuery elements? I'm using if($foo.length) and if($foo.length !== 0), what should be used?

if ($foo.length) { }if (!$foo.length) { }
suffices for me, but I don't think there's an agreed-on standard right now, perhaps we should look into creating one.
jQuery uses this internally when checking for the presence of an array value, which is essentially what we're doing, and it is a pretty widely used standard within the JavaScript/jQuery community.

Where the use of a ternary can easily lead to confusion, a full if statement with curly braces is recommended.
In the case where you're storing exactly the value of your condition I would be fine with doing it directly, but with braces around the condition, like: a = (b === c);
Constructs like the following seem overly verbose to me, but again, there's no standard set in stone or anything and they might help readability for some people.

Probably has to be changed to TableSelect.tables.splice(i, 1);, and has to be moved outside the loop: removing an item like this forces the array to be reindexed, which makes the i parameter unreliable at best. The only way I see it (while still supporting IE8, which does not support indexOf or filter):

var indexes = [];
for (var i = 0, il = tables.length; i < il; i++) {
...
indexes.push(i);
...
}
// The removed entries need to be removed from cache as
// well, but because .splice() re-indexes an array the only
// way to do this safely is by going through the indexes in
// descending order.
indexes.sort(function (a,b) {return b-a});
for (var i = 0, il = indexes.length; i < il; i++) {
TableSelect.tables.splice(indexes[i], 1);
}

I added some basic *created/*removed events in this patch. I think it would be incredibly helpful if these events had extra parameters containing the index of the instance and a reference to the instance. The second parameter is easy to add, the first might take some thinking if it is _really_ necessary.

Testbot came back green, setting back to needs work for #29/#30 and the above comment.

While fixing #36, I thought of an obscure bug: tableselect and tableheader are applied: no biggie, it works. tableselect gets detached and attached while tableheader is left alone: stickyTableCreated will not fire. Plus, the checkbox from the cloned header is removed.

Tried to fix it, but it took more lines than I'm comfortable with :/. Any thoughts/ideas how to fix this more elegantly are more than welcome.

Sorry for being a bit unclear, by "not having sizzle-specific selectors", I meant changing :checkbox to [type=checkbox], which speeds up things on qSA-capable browsers (which is all we support anyway) (perf case -> http://jsperf.com/sizzle-vs-qsa ). The loop-check you changed it too seems a bit awkward and error-prone (it bails as soon as it detects an input that isn't a checkbox?)

On the issue raised in #42: I would say lowercase, as they are custom event names and don't really reference the constructor instances.

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)