Friday, February 5, 2010

GMail Style Multiple Checkbox Shift Selection

A while ago I ran into a situation where there were a list of check boxes in a ASP.NET GridView control and I wanted to be able to Shift+Click the check boxes like GMail or make a selection in Windows Explorer.

Here is the mocked up code that I came up with using jQuery. I make extensive use of is the predicate selector '$='. Which a very useful trick to get around injecting the ASP.NET client id into JavaScript.
var selectedCheckRow = 2;
function itemToggleSelect(cb, e) {
    var checkAll = $("input[id$='CheckAll']"),
        chkVal = cb.checked,
        idVal = cb.id;
    if (!chkVal && checkAll.attr('checked')) {
        $(".selectAllMsg").hide();
        selectAllPages('false');
        checkAll.attr('checked', false);
    }
    // -- Shift-Click Select on Item Grid -- //
    if (!e) e = event;
    CurrentCheckRow = $("#" + idVal)[0].parentNode.parentNode.rowIndex;
    if (e.shiftKey) {
        ((CurrentCheckRow > selectedCheckRow) ?
            $("input[id$='chkAction']").slice(selectedCheckRow - 2, CurrentCheckRow - 2)    // Selecting down
            : $("input[id$='chkAction']").slice(CurrentCheckRow - 2, selectedCheckRow - 2)  // Selecting up
        ).attr('checked', chkVal)
    }
    // Save checkbox row
    selectedCheckRow = $("#" + idVal)[0].parentNode.parentNode.rowIndex;
}
//Expects: 'true' if all pages should be selected
//         'false' if select only viewable items/page.
function selectAllPages(allPages) {
    $(".selectAllPages").val(allPages);
    var selectAll = $(".selectAllMsg > td");
    selectAll.html((allPages == "true") ?
        "All items on all pages have been selected.  <a  href='#' onclick='ToggleAll(false);return false;'>Clear Selection.</a>" :
        "All items on this page are selected.  <a href='#' onclick='selectAllPages(true);return false;'>Select All Items on All Pages.</a>");
}
function ToggleAll(cb) {
    var msg = $(".selectAllMsg"), selectAll,
        chkVal = cb.checked,
        idVal = cb.id;
    if (chkVal) {
        selectAll = $(".selectAllMsg > td");
        selectAll.html("All items on this page are selected.  <a href='#' onclick='selectAllPages(true);return false;'>Select All Items on All Pages.</a>");
        msg.slideDown(0);
    }
    else
    {
        msg.hide();
        selectAllPages('false');
    }
    $("input[id$='chkAction'],input[id$='CheckAll']").attr('checked', chkVal);
}

Demo
The demo code (view the source to see) is setup to mimic an GridView control. To make this demo function you can click a check box, perhaps '3' and then shift+click another check box, perhaps '7'. Not overly complicated, but could definitely save time over developing from scratch.





Select All




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17