Reg Exp
Web Design
Notes Client
SHIFT+CLICK to Select Multiple Checkboxes
I'm working on a web project where the users will interact with multiple documents in a view. The user shouldn't open the documents - all the information they need is shown in the view. But they are going to select several documents and click on an action button to process those documents. Normally I would have "Select All" and "Deselect All" buttons for them to click to select all the documents. But, in this case, they aren't going to select everything. Instead, they are going to select many documents (some people it may be 5 or 6, but others it might be 30 or more). I wanted to implement a way for them to select the first document, then hold down SHIFT and select the last document, and everything between would be selected.

This can be done pretty easily with JQuery, but I'm not using JQuery for anything else in this project, so I didn't want to bring in all those libraries just for this. As it turns out, it was surprisingly easy to do in standard JavaScript.

First, in the view I needed to make it so the document couldn't be clicked and there would instead be a checkbox that appeared. In the first column of the view (the one that would normally be the link), I used this column formula:

"[</a><input type=\"checkbox\" id=\"checkbox\" class=\"checkbox\" value=\"" + @Text(@DocumentUniqueID) + "\" />]"

Notice that I added a class of "checkbox" to all the check boxes. This is how the JavaScript code will find them all later.

In my JavaScript code, I defined two global variables:

var lastChecked = null;
var allCheckboxes = [];

Next, I added code to the onLoad event of the view template:

function doOnLoad() {
     // Run through all the checkboxes and add an "onClick" event to them to handle SHIFT-CLICK
     var checkboxes = document.getElementsByClassName("checkbox");
     for (var i=0; i<checkboxes.length; i++) {
           checkboxes[i].onclick = function(e) {
                 if (!lastChecked) {
                       lastChecked = this;
                 if (e.shiftKey) {
                       var startTemp = allCheckboxes.indexOf(this);
                       var endTemp = allCheckboxes.indexOf(lastChecked);
                       var start = Math.min(startTemp, endTemp);
                       var end = Math.max(startTemp, endTemp);
                       for (var i=start; i<=end; i++) {
                             allCheckboxes[i].checked = lastChecked.checked;
                 lastChecked = this;
           }; // end the custom "onclick" function for this check box
     } // run through all the check boxes on the page
} // "doOnLoad()"

(Note that this function is called from the view template's "onload" event).

First, get all the check boxes (every element with a class name of "checkbox"). For each check box, put it into the global array called "allCheckboxes". Then add an "onclick" function to each checkbox. In the function, if this is the first check box clicked in the view, set the "lastChecked" global object and exit. If this is the second, third, etc. check box clicked, then see if the SHIFT key was held down when the click happened. If so, figure out the starting and ending array elements using the "indexOf" function built in to the Array object in JavaScript. Make sure "start" is the lower of the two indexes and "end" is the greater of the two indexes. Then either check or uncheck every check box between the two positions (including the start and end). Use the status of "lastChecked" (checked or unchecked) and set everything to that same state. Finally, at the end (whether or not SHIFT was held down), reset the global variable "lastChecked".

It's actually pretty easy to implement this functionality and now users can select a whole bunch of consecutive documents in just a few clicks and then click on the action button to perform their task on those documents.