mooSelect – convert a select list into a sliding checkbox list
EDITED: [2009-11-12]
Well, I have taken the plunge…. I have finally my first mootools class 🙂
Despite all the tutorials claiming that it is easy, I must admit to have found it rather complicated. I am the first to admit that I have problems with classes so this is not a reflection on mootools, rather on my limited abilities.
The final result is probably not very good as far as classes go but it works and I’m happy with it 🙂
See Demo
The background:
For a client site I needed to convert a multiple select list into a dropdown list of checkboxes. As usual I scanned google and all the usual places where mootools scripts are posted but to no avail. The only one that came close to what I needed was Custom Form Elements (link no longer working). Whilst this certainly looks good, for my needs it was far too complicated and I must admit (yet again) that I couldn’t even get it working as a test. I finally gave up on my search and resolved to have a go myself.
The result is my mooSelect class.
The idea was to take a standard select multiple select list and convert it to a dropdown list of checkboxes. This solution gains over the original as the multiple elements can be selected just by using the mouse as compared to the default method of a combination of keyboard and mouse clicks. It also takes up less room on the page (the main reason why this alternative solution was needed by the client).
So, how does it work?
- The mootools code retrieves all the options from the defined select list.
- It creates a list of checkboxes using the same field name, values, text and even retains the “selected” value if the item has been previously selected.
- A “summary” box is added that serves to show the number of options selected (dynamically updating as items are removed or added) and also as the handle to toggle the checkbox list.
- A “close” button is also placed at the bottom of the list.
- The list will close itself automatically after X number of seconds (where X can be defined as an option)
- The new list is placed where the original select list is.
- The original select list element is removed.
Of course, if the user has javascript turned off, the standard multiple select list is shown as normal.
So, here is the code. Go easy with me, it is my first attempt at writing a class….
The html:
Option:<select id="my_list" multiple name="my_list" style="width:200px;"> <option value="">- select -</option> <option value="1" >Car</option> <option value="2" >Lorry</option> <option value="3" >Motorbike</option> <option value="4" >Bus</option> <option value="5" >Train</option> <option value="6" >Airplane</option> </select>
The CSS:
.pseudo_select{ background:#DDD url(images/arrows_blue.png) no-repeat right; width:200px; z-index:20; padding:4px; border:1px solid #CCC; } .select_list{ position:absolute; border-left:1px solid #DDD; border-right:1px solid #DDD; border-bottom:1px solid #DDD; width:200px; background:#F6FFD0; z-index:20; padding:4px; font-size:0.8em; } .select_close{ position:absolute; bottom:2px; right:2px; cursor:pointer; border:1px solid #CCC; padding:0px 4px 2px 4px; background:#006699; color:#FFFFFF; line-height:1.0em; font-size:0.8em; width:6px; text-align:center; }
The Javascript (mootools)
var mooSelect = new Class({ Implements: [Options, Events], options: { //start_txt:'- select options -', inititalText:'- select -', // the initial default text (will be overwridden if the select list has it's own) txt: 'options selected', // text for counter auto_close:true, // to close or not to close the checklist auto_close_time:5000 // time to close the list }, initialize: function(element,options){ this.setOptions(options); var counter = 0; var state = false; var select_box = $(element); var select_options = select_box.getElements('option'); var field_name = select_box.getProperty('name'); var selected_items = select_box.getSelected(); var auto_close = this.options.auto_close; var auto_close_time = this.options.auto_close_time; var initial_txt = this.options.inititalText; //create checklist from select list options var chk_items = ''; var chk=''; var initial_number=''; select_options.each(function(option) { // define select option value and text value opt_val=option.get('value'); opt_txt=option.get('text'); // define default initial text (if it is set) if(opt_val=='')initial_txt = opt_txt; // check if item is selected checked=''; if(option.get('selected')){ checked='checked="checked"'; counter=counter+1; // add 1 to counter } // define number and text if if(counter>0) { initial_txt = options.txt; initial_number = counter; } // add checkbox if value isn't empty if(opt_val!='')chk_items += '<label><input type="checkbox" class="sel_checkbox" name="'+field_name+'[]" '+checked+' value="'+opt_val+'">'+opt_txt+'</label><br>'; }); chk_items +='<div class="select_close" title="close">x</div>'; // create new div to hold selected items counter and acts as toggle for checkbox list var pseudo_select=new Element('div',{ 'class':'pseudo_select', 'html':'<span class="counter">'+initial_number+'</span> <span class="text">'+initial_txt+'</span>', events: { click: function(e) { //alert(auto_close_time); state = !state; if(auto_close){ if(state) sel_list.wink(auto_close_time); }else{ if(state) sel_list.reveal(); else sel_list.dissolve(); } } } }).setStyle('cursor','pointer').inject(select_box,'after'); //create select list var sel_list = new Element('div',{ 'class': 'select_list', 'html':chk_items }).inject(pseudo_select,'after'); // delete original select box select_box.dispose(); // hide new select list sel_list.dissolve(); // close button sel_list.getElement('.select_close').addEvent('click',function(){ sel_list.dissolve(); }); // click options on select list var sel_checkboxes=sel_list.getElements('.sel_checkbox'); sel_checkboxes.addEvent('click',function(){ // count checked checkboxes chk=0; for(var i=0;i<sel_checkboxes.length;i++){ sel_checkboxes[i].checked? chk++:null; } if(chk==0) { pseudo_select.getElement('.text').set('html',''+initial_txt+''); pseudo_select.getElement('.counter').set('html',''); }else{ pseudo_select.getElement('.text').set('html',''+options.txt+''); pseudo_select.getElement('.counter').set('html',chk); } }); } });
As always, any pointers as to how it can be improved would be greatly appreciated.
EDIT: [2009-11-12]
I have added a couple of new features to this class:
- On load it now uses the first option (if it has no value) as the default text for the box.
- Auto close can be turned off/on as an option
There are 8 comments in this article: