/*
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('