
jQuery.fn.customSelect = function(settings) {

	settings = jQuery.extend({
		speed: 'normal'
	}, settings);

	return this.each(function() {
		$this = jQuery(this);

		if($this.context.nodeName == 'SELECT') {
			customizeSelect( $this );
		}
		else {
			jQuery('select', $this).each(function() {
				customizeSelect( jQuery(this) );
			});
		}
	});
	
	
	function changeTo($el) {
		var v = $el.html();
		var $holder = $el.closest('.cs-holder');
		
		jQuery('.cs-val', $holder).html(v);
		
		jQuery('.cs-selected', $holder).removeClass('cs-selected');
		jQuery(':selected', $holder).removeAttr('selected');
		
		$el.addClass('cs-selected');
		jQuery('option[value="'+v+'"]', $holder).attr('selected', 'selected');
	}
	
	
	function hideSelect(selector) {
		jQuery(selector).unbind('keypress').hide(settings.speed);
	}


	function customizeSelect($sel) {
		// ----------  CREATION  ----------
		var name = $sel.attr('name');
		
		var csId = 'cs-'+$sel.attr('id');
		
		var selected = jQuery(':selected', $sel).attr("value");
		var cVal = '<div class="cs-val" id="'+csId+'-val" tabindex="0">'+selected+'</div>';

		var listOpts = '';
		$sel.children('option').each(function(){
			var v = jQuery(this).attr("value");
			var selectedClass = (v == selected) ? ' cs-selected' : '';
			listOpts += '<p id="'+csId+'-option'+v+'" class="cs-option'+selectedClass+'">'+v+'</p>';
		});
		
		var cOpts = '<div class="cs-options" id="'+csId+'-options">'+listOpts+'</div>';
		$sel.after('<div id="'+csId+'" class="cs-holder">'+cVal+cOpts+'</div>');
		$sel.css('display', 'none');
		
		
		// ----------  HOVER  ----------
		jQuery('#'+csId+'-val').hover(
			function() { jQuery(this).addClass('cs-hover'); },
			function() { jQuery(this).removeClass('cs-hover'); }
		);
		
		
		// ----------  ANIMATION  ----------
		var $cs = jQuery('#'+csId);
		$cs.click(function() {
			var selector = '#'+csId+'-options';
			jQuery(selector).toggle(settings.speed);
			hideSelect('.cs-options:not('+selector+')');
		});
		
		jQuery('.cs-option', $cs).hover(
			function() { jQuery(this).addClass('cs-opt-hover'); },
			function() { jQuery(this).removeClass('cs-opt-hover'); }
		).click(function() {
			changeTo(jQuery(this));
		});
		
		
		// ----------  KEYBOARD ----------
		$cs.keydown(function(e) {
			var key = e.charCode ? e.charCode : e.keyCode ? e.keyCode : 0;
			switch(key){
				case 32: jQuery('#'+csId+'-options').toggle(settings.speed);
					break;
				case 38: changeTo(jQuery('.cs-selected', this).prev());
					break;
				case 40: changeTo(jQuery('.cs-selected', this).next());
					break;
				case 13: jQuery('.cs-selected', this).click();
					break;
				case 9: jQuery('.cs-options', this).hide(settings.speed);
					return true;
					break;
				case 116: return true;
					break;
				default: break;
			}
			return false;
		});

		
		// ----------  OUTSIDE CLICK DETECTION  ----------
		$cs.hover(
			function() {
				jQuery(document).unbind('click');
			},
			function() {
				jQuery(document).bind('click', function(e){
					hideSelect('.cs-options');
				});
			}
		);
	}

};
