/**
 * jQuery custom selectboxes
 * 
 * Copyright (c) 2008 Krzysztof Suszyński (suszynski.org)
 * Licensed under the MIT License:
 * http://www.opensource.org/licenses/mit-license.php
 * Modified by Aaron Heckmann allowing clicking anywhere on 
 * select box to open and adding keyboard accessablity.
 *
 * @version 0.6.2
 * @category visual
 * @package jquery
 * @subpakage ui.selectbox
 * @author Krzysztof Suszyński <k.suszynski@wit.edu.pl>
**/
var GLOBAL_JQUERY_SELECTBOX_COUNT = 0;
jQuery.fn.selectbox = function(options){
	/* Default settings */
	var settings = {
		className: 'jquery-selectbox',
		animationSpeed: "normal",
		listboxMinSize: 1,
		listboxMaxSize: 10,
		replaceInvisible: false,
		clearAfter: false
	};
	var commonClass = 'jquery-custom-selectboxes-replaced';
	var listOpen = false;
	var showList = function(listObj) {
		var selectbox = listObj.parents('.' + settings.className + '');
		
		listObj.slideDown(settings.animationSpeed, function(){
			listOpen = true;
		});
		//listObj[0].scrollTop=0;
		selectbox.addClass('selecthover');
		jQuery(document).bind('keydown', onSelectBoxKeyDown);
		jQuery(document).bind('click', onBlurList);
		//listObj.focus();
		return listObj;
	}
	var hideList = function(listObj) {
		var selectbox = listObj.parents('.' + settings.className + '');
		jQuery(document).unbind('keydown', onSelectBoxKeyDown);
		listObj.slideUp(settings.animationSpeed, function(){
			listOpen = false;
			jQuery(this).parents('.' + settings.className + '').removeClass('selecthover');
		});
		jQuery(document).unbind('click', onBlurList);
		return listObj;
	}
	var onBlurList = function(e) {
		var trgt = e.target;
		var currentListElements = jQuery('.' + settings.className + '-list:visible').parent().find('*').andSelf();
		if(jQuery.inArray(trgt, currentListElements)<0 && listOpen) {
			hideList( jQuery('.' + commonClass + '-list') );
		}
		return false;
	}
	var onSelectBoxClick = function () {
		var thisMoreButton = jQuery(this).parent().find('.' + settings.className + '-moreButton');
		var otherLists = jQuery('.' + settings.className + '-list')
			.not(thisMoreButton.siblings('.' + settings.className + '-list'));
		hideList( otherLists );
		var thisList = thisMoreButton.siblings('.' + settings.className + '-list');
		if(thisList.filter(":visible").length > 0) {
			hideList( thisList );
		}else{
			showList( thisList );
		}
	}
	var onSelectBoxKeyDown = function (e) {
		// up:38, down:40, enter: 13
		if (e.which == 40 || e.which == 38 || e.which == 13) {
			// e.target is body in Safari Win
			var list = jQuery('.jquery-selectbox.selecthover').find('.' + settings.className + '-list');
			if (list.filter(":visible").length > 0) {
				var option = list.find('.listelementhover');
				option = option.length > 0 ? option : list.find('.' + settings.className + '-item:first');
				
				switch (e.which) {
					case 40:
						if (option.next().length > 0) {
							option.prev();
							option.trigger('mouseleave').next().trigger('mouseenter');			
							var l = option.offset().top - list.offset().top;
							if (list.height() < l + option.height() ) {
								list[0].scrollTop = l;
							}			
						}
						return false;					
						break;
					case 38:
						if (option.prev().length > 0) {
							option.next();
							option.trigger('mouseleave').prev().trigger('mouseenter');					
							var l = option.offset().top - list.offset().top;
				
							l = l < option.height() ? 0 : l;

							if (option.offset().top - option.height() < list.offset().top) {
								list[0].scrollTop = l;
							}
						}
						
						return false;
						break;
					case 13:
						option.trigger('click');
						break;
				}		
			}
		}
	}
	
	/* Processing settings */
	settings = jQuery.extend(settings, options || {});
	/* Wrapping all passed elements */
	return this.each(function() {
		GLOBAL_JQUERY_SELECTBOX_COUNT++;
		var _this = jQuery(this);
		if(_this.filter(':visible').length == 0 && !settings.replaceInvisible)
			return;
		
		var replacement = jQuery(
			'<div class="' + settings.className + ' ' + commonClass + '">' +
				'<a href="#" onclick="return false;" class="' + settings.className + '-currentItem" />' +
				'<div class="' + settings.className + '-moreButton" />' +
				'<div class="' + settings.className + '-list ' + commonClass + '-list" />' +
			'</div>')
			.find('.' + settings.className + '-currentItem')
				.attr('tabindex', _this.attr('tabindex') || '')
				.click(onSelectBoxClick)
				.end();
				
		jQuery('option', _this).each(function(k,v){
			var v = jQuery(v);
			var listElement =  jQuery('<span class="' + settings.className + '-item value-'+v.val()+' item-'+k+' '+v.get(0).className+'">' + v.text() + '</span>');	
			listElement.bind('click',function(){
				var thisListElement = jQuery(this);
				var thisReplacment = thisListElement.parents('.'+settings.className);
				var thisIndex = thisListElement[0].className.split(' ');
				for( k1 in thisIndex ) {
					if(/^item-[0-9]+$/.test(thisIndex[k1])) {
						thisIndex = parseInt(thisIndex[k1].replace('item-',''), 10);
						break;
					}
				};
				var thisValue = thisListElement[0].className.split(' ');
				for( k1 in thisValue ) {
					if(/^value-.+$/.test(thisValue[k1])) {
						thisValue = thisValue[k1].replace('value-','');
						break;
					}
				};
				thisReplacment
					.find('.' + settings.className + '-currentItem')
					.text(thisListElement.text());
				thisReplacment
					.find('select')
					.val(thisValue)
					.triggerHandler('change');
				var thisSublist = thisReplacment.find('.' + settings.className + '-list');
				if(thisSublist.filter(":visible").length > 0) {
					hideList( thisSublist );
				}else{
					showList( thisSublist );
				}
			}).bind('mouseenter',function(){
				jQuery(this).addClass('listelementhover');
			}).bind('mouseleave',function(){
				jQuery(this).removeClass('listelementhover');
			});
			jQuery('.' + settings.className + '-list', replacement).append(listElement);
			if(v.filter(':selected').length > 0) {
				jQuery('.'+settings.className + '-currentItem', replacement).text(v.text());
			}
		});
		replacement.find('.' + settings.className + '-moreButton')
		.click(onSelectBoxClick)
		.bind('mouseenter',function(){
			jQuery(this).addClass('morebuttonhover');
		}).bind('mouseleave',function(){
			jQuery(this).removeClass('morebuttonhover');
		});
		var clrAfter = '';
		if( settings.clearAfter ){
			clrAfter = '<br style="clear:both;" />';
		}
		_this.after(clrAfter).hide().replaceWith(replacement).appendTo(replacement);
		var thisListBox = replacement.find('.' + settings.className + '-list');
		var thisListBoxSize = thisListBox.find('.' + settings.className + '-item').length;
		if(thisListBoxSize > settings.listboxMaxSize)
			thisListBoxSize = settings.listboxMaxSize;
		if(thisListBoxSize < settings.listboxMinSize)
			thisListBoxSize = settings.listboxMinSize;
		if(thisListBoxSize == 0)
			thisListBoxSize = 1;
		var thisListBoxWidth = Math.round(_this.width()-8);
		if(jQuery.browser.safari)
			thisListBoxWidth = thisListBoxWidth * 0.99; //originally 0.94, but caused Safari width problems.
		replacement.css({
			'width': (thisListBoxWidth+35) + 'px',
			'zIndex': (500-GLOBAL_JQUERY_SELECTBOX_COUNT)
		});
		thisListBox.css({
			width: Math.round(thisListBoxWidth+30) + 'px',
			height: thisListBoxSize + 'em',
			'zIndex': (800-GLOBAL_JQUERY_SELECTBOX_COUNT)
		});
	});
}
jQuery.fn.unselectbox = function(){
	var commonClass = 'jquery-custom-selectboxes-replaced';
	return this.each(function() {
		var selectToRemove = jQuery(this).filter('.' + commonClass);
		selectToRemove.replaceWith(selectToRemove.find('select').show());		
	});
}