/* jquery selectbox (version 1.0.7) a cosmetic, styleable replacement for select elements. homepage: http://abeautifulsite.net/blog/2011/01/jquery-selectbox-plugin/ demo page: http://labs.abeautifulsite.net/projects/js/jquery/selectbox/ copyright 2011 cory laviska for a beautiful site, llc. features: - supports optgroups - supports standard dropdown controls - supports multi-select controls (i.e. multiple="multiple") - supports inline controls (i.e. size="5") - fully accessible via keyboard - shift + click (or shift + enter) to select a range of options in multi-select controls - type to search when the control has focus - auto-height based on the size attribute (to use, omit the height property in your css!) - tested in ie7-ie9, firefox 3-4, recent webkit browsers, and opera license: licensed under both the mit license and the gnu gplv2 (same as jquery: http://jquery.org/license) usage: link to the js file: add the css file (or append contents to your own stylesheet): to create: $("select").selectbox([settings]); settings: to specify settings, use this syntax: $("select").selectbox('settings', { settingname: value, ... }); menutransition: ['default', 'slide', 'fade'] - the show/hide transition for dropdown menus menuspeed: [integer, 'slow', 'normal', 'fast'] - the show/hide transition speed methods: to call a method use this syntax: $("select").selectbox('methodname', [options]); create - creates the control (default method) destroy - destroys the selectbox control and reverts back to the original form control disable - disables the control (i.e. disabled="disabled") enable - enables the control value - if passed with a value, sets the control to that value; otherwise returns the current value options - pass in either a string of html or a json object to replace the existing options control - returns the selectbox control element (an anchor tag) for working with directly events: events are fired on the original select element. you can bind events like this: $("select").selectbox().change( function() { alert( $(this).val() ); } ); focus - fired when the control gains focus blur - fired when the control loses focus change - fired when the value of a control changes change log: v1.0.0 (2011-04-03) - complete rewrite with added support for inline and multi-select controls v1.0.1 (2011-04-04) - fixed options method so it doesn't destroy/recreate the control when called. - added a check for ios devices (their native controls are much better for touch-based devices; you can still use selectbox api methods for theme) - fixed issue where ie window would lose focus on xp - fixed premature selection issue in webkit browsers v1.0.2 (2011-04-13) - fixed auto-height for inline controls when control is invisible on load - removed auto-width for dropdown and inline controls; now relies 100% on css for setting the width - added 'control' method for working directly with the selectbox control v1.0.3 (2011-04-22) - fixed bug in value method that errored if the control didn't exist v1.0.4 (2011-04-22) - fixed bug where controls without any options would render with incorrect heights v1.0.5 (2011-04-22) - removed 'tick' image in lieu of background colors to indicate selection - clicking no longer toggles selected/unselected in multi-selects; use ctrl/cmd and shift like in normal browser controls - fixed bug where inline controls would not receive focus unless tabbed into v1.0.6 (2011-04-29) - fixed bug where inline controls could be "dragged" when selecting an empty area v1.0.7 (2011-05-18) - expanded ios check to include android devices as well - added autowidth option; set to false on init to use css widths for dropdown menus known issues: - the blur and focus callbacks are not very reliable in ie7. the change callback works fine. */ if(jquery) (function($) { $.extend($.fn, { selectbox: function(method, data) { var typetimer, typesearch = ''; // // private methods // var init = function(select, data) { // disable for ios devices (their native controls are more suitable for a touch device) if( navigator.useragent.match(/ipad|iphone|android/i) ) return false; // element must be a select control if( select.tagname.tolowercase() !== 'select' ) return false; select = $(select); if( select.data('selectbox-control') ) return false; var control = $(''), inline = select.attr('multiple') || parseint(select.attr('size')) > 1; var settings = data || {}; if( settings.autowidth === undefined ) settings.autowidth = true; // inherit class names, style, and title attributes control .addclass(select.attr('class')) .attr('style', select.attr('style') || '') .attr('title', select.attr('title') || '') .attr('tabindex', parseint(select.attr('tabindex'))) .css('display', 'inline-block') .bind('focus.selectbox', function() { if( this !== document.activeelement ) $(document.activeelement).blur(); if( control.hasclass('selectbox-active') ) return; control.addclass('selectbox-active'); select.trigger('focus'); }) .bind('blur.selectbox', function() { if( !control.hasclass('selectbox-active') ) return; control.removeclass('selectbox-active'); select.trigger('blur'); }); if( select.attr('disabled') ) control.addclass('selectbox-disabled'); // generate control if( inline ) { // // inline controls // var options = getoptions(select, 'inline'); control .append(options) .data('selectbox-options', options) .addclass('selectbox-inline') .addclass('selectbox-menushowing') .bind('keydown.selectbox', function(event) { handlekeydown(select, event); }) .bind('keypress.selectbox', function(event) { handlekeypress(select, event); }) .bind('mousedown.selectbox', function(event) { if( $(event.target).is('a.selectbox-inline') ) event.preventdefault(); if( !control.hasclass('selectbox-focus') ) control.focus(); }) .insertafter(select); // auto-height based on size attribute if( !select[0].style.height ) { var size = select.attr('size') ? parseint(select.attr('size')) : 5; // draw a dummy control off-screen, measure, and remove it var tmp = control .clone() .removeattr('id') .css({ position: 'absolute', top: '-9999em' }) .show() .appendto('body'); tmp.find('.selectbox-options').html('
  • \u00a0
  • '); optionheight = parseint(tmp.find('.selectbox-options a:first').html(' ').outerheight()); tmp.remove(); control.height(optionheight * size); } disableselection(control); } else { // // dropdown controls // var label = $(''), arrow = $(''); label.text( $(select).find('option:selected').text() || '\u00a0' ); var options = getoptions(select, 'dropdown'); options.appendto('body'); control .data('selectbox-options', options) .addclass('selectbox-dropdown') .append(label) .append(arrow) .bind('mousedown.selectbox', function(event) { if( control.hasclass('selectbox-menushowing') ) { hidemenus(); } else { event.stoppropagation(); // webkit fix to prevent premature selection of options options.data('selectbox-down-at-x', event.screenx).data('selectbox-down-at-y', event.screeny); showmenu(select); } }) .bind('keydown.selectbox', function(event) { handlekeydown(select, event); }) .bind('keypress.selectbox', function(event) { handlekeypress(select, event); }) .insertafter(select); disableselection(control); } // store data for later use and show the control select .addclass('selectbox') .data('selectbox-control', control) .data('selectbox-settings', settings) .hide(); }; var getoptions = function(select, type) { var options; switch( type ) { case 'inline': options = $('