HTML Checkbox enhancement: iCheck and Shift-Click

Capture

iCheck plug-in

When other HTML form elements can be formatting so easily, checkboxes and radio buttons need some javascript to be more beautiful. iCheck is a jQuery plug-in that:

Highly customizable checkboxes and radio buttons for jQuery and Zepto.
Damir Sultanov – iCheck author

You can see how checkboxes and radio buttons are formatted by iCheck in the image below

Checkboex and radio buttons when formatted with iChekc plug in

Checkboxes and radio buttons when formatted with iChekc plug in

Selecting multiples checkboxes in a range with Shift-Click

When the number of checkboxes increases, the time it consumes to check or uncheck these checkboxes grows. Users will feel unhappy if he must click 10 times just to check 10 consecutive checkboxes. In many desktop applications, this task is not a problem because users can Shift-Click and just touch the first checkboxes and the last one. In the end of this post, you will know how I implement this behavior in Web screens. The final result will something looks like this JS Bin:

Working with javascript

You can choose with tab to view in the previous demo frame by click the corresponding buttons in the top of the frame

Init the iCheck plugin

First, include iCheck javascript and CSS files after loading jQuery.

<head>
    <link rel="stylesheet" href="https://www.hieule.info/source/iCheck-1.0.2/skins/minimal/_all.css" />
    <script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
    <script src="https://www.hieule.info/source/iCheck-1.0.2/icheck.min.js" type="text/javascript"></script>
</head>

And call this init code to format all of your checkboxes

$(document).ready(function(){
  // Init checkboxes with iCheck
  $('input').iCheck({
    checkboxClass: 'icheckbox_minimal-blue',
    radioClass: 'iradio_minimal'
  });
  // Next step code here
});

After this step, you must see all of your checkboxes appear in a different style than the default one.

Handle the click  event

Instead of handling this event on the input element itself, we binding your handler on the outter div that created by iCheck

/* This code is inside the $(document).ready() */
  // Binding `click` event into iCheck inputs
  $('#checkboxes .iCheck-helper').click(function(evt) {
    var $this = $(this);
    var element = $this.prev('input[type="checkbox"]');
    var parent = $this.parents('.control');
    if (element.length)
    {
      // Next step code here
    }
  });

I create variables to hold the reference to two objects: the real input element the the container element that repeated in the form (in this examples, you can see the div.control element is the container of each input). Moreover, when handling the click event, javascript allow us to know whether the Shift key is press at the same time with the click by supporting the shiftKey property.

Manipulate the click event

Now, my code works as follows:

  1. Detect whether this is a normal click or a Shift-Click
  2. If this is a normal click, record the current zero-based index of the clicked checkboxes in the checkboxes array
  3. If this is a Shift-Click, find the previous clicked checkboxes by the saved index. If nothing found, treat this event as normal. Otherwise, copy the state of the previous clicked one to all checkboxes between this current target and the previous one (including these both)
if (evt.shiftKey)
{
  if (lastCheckedCheckboxIndex >= 0)
  {
    var isChecked = $('#checkboxes input[type="checkbox"]:nth(' + lastCheckedCheckboxIndex + ')')[0].checked ? 'check' : 'uncheck';
    $('#checkboxes input[type="checkbox"]').each(function(i, e) {
      if ((i - pIndex) * (i - lastCheckedCheckboxIndex) <= 0)
      {
        // this checkbox is in the range
        $(e).iCheck(isChecked);
      }
    });
  }
}
else
{
  lastCheckedCheckboxIndex = pIndex;
}

 In the end…

If you are not using the iCheck plug-in, the click handler can be registered directly on the input element it self. It’s rumored that iCheck author will support this event on the 2.0 release. I think I will refactor this code when this happens. You can preview the code of this tutorial by the frame at the second section or go to this lik: https://jsbin.com/lobowe/6/edit

 

One comment

  1. Sergio on

    Hello Hieu Le Trung
    Thanks for the code. It was a good start for my own code.

    Please use this instead, it’s more accurate

    $('tbody .iCheck-helper').click(function (evt) {
    		
    		var $this = $(this);
    		var element = $this.prev('input[type="checkbox"]');
    		var parent = $this.closest('tr');
    		
    		if (element.length) {
    			
    			var pIndex = parent.index();
    			
    			if (evt.shiftKey) {
    				
    				if (Saes.last >= 0) {
    					
    					var isChecked,
    						//last_checked = $('tbody input[type="checkbox"]:nth(' + Saes.last + ')').prop('checked'),
    						current_checked = ! $('tbody input[type="checkbox"]:nth(' + pIndex + ')').prop('checked');
    						// here, current checkbox has already been clicked, that's why we use the opposite
    					
    					//console.log(last_checked, current_checked);
    					isChecked = current_checked ? 'uncheck' : 'check';
    					
    					$('tbody input[type="checkbox"]').each(function(i, e) {
    						
    						if ((i - pIndex) * (i - Saes.last) <= 0) {
    							// this checkbox is in the range
    							$(e).iCheck(isChecked);
    						}
    					});
    				}
    				
    			} else {
    				//Saes.last = pIndex;
    			}
    			
    			Saes.last = pIndex;
    			
    		}
    	});
    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *