/**
 * Styled Select
 *
 * @author		Chris Willerton <chris@chriswillerton.com>
 * @copyright	Chris Willerton 2011
 * @version		1.2.1
 *
 * @changelog
 *		1.1.0 	-	Added callbacks, added the option to pass false to the dropdownIcon option to get nothing, bugfixes
 *		1.1.1 	-	If an option is selected then make that the default option
 *		1.1.2 	-	Added in a fix for IE7 z-index issues
 *		1.1.3	-	Bugfixes
 *		1.2.0	-	Large refactor, better consistency and logic, effiency improvements - including removal of some unnecessary features
  *		1.2.1	-	Changed the values object to be an array - stems from problems with enumeration order, plus it makes more sense. Cheers Luke.
 *
 * Requires		jQuery 1.4.3 or later
 * 
 * ToDo
 * 1. Make the styles applied to the original select apply to the new markup
 */
;(function($){
	
	var plugin = "styledSelect";
	
	$[plugin] = {};
	
	// Default options
	$[plugin].defaults = {
		defaultOption	: 'Select',
		dropdownIcon	: null,
		containerClass	: 'styled_select_container',
		containerZIndex	: 100,
		callback		: {
			onStart			: null,
			onComplete		: null, // When the new DOM elements have been inserted
			onChange		: null
		},
		disableClearfix	: false
	};
	
	$.fn[plugin] = function(opts)
	{	
		var options = $.extend(true, {}, $[plugin].defaults, opts),
			zIndex = options.containerZIndex;
	
		return this.each(function(){
			
			var $this = $(this),
				values = [],
				newOptions = '',
				styledSelectContent = '',
				dropdownIcon = '',
				defaultOption = '',
				selectedOption = $this.find('option:selected').text();
			
			// Run the onStart callback if required
			(options.callback.onStart || null);
			
			
			// Loop through each option and save the value into the values array
			$this.find('option').each(function(index) {
				values.push({
					'text'	: $(this).text(),
					'val'	: $(this).val()
				});
			});	
			
			// Create the new options markup based on the values array
			$.each(values, function(index, obj){
				newOptions += '<span data-value="' + obj.val + '">' + obj.text + '</span>';
			});
			
			// Create the new markup to be inserted
			styledSelectContent += '<div class="' + options.containerClass + ' clearfix">';
			
			// Change the dropdown icon if something is specified
			if (options.dropdownIcon)
				dropdownIcon = options.dropdownIcon;
			else if (options.dropdownIcon == false)
				dropdownIcon = '';
			else
				dropdownIcon = '<span class="styled_select_arrow"></span>';
			
			// Set the default option as the selected option (if there is one)
			if (selectedOption)
				defaultOption = selectedOption;
			else if (options.defaultOption)
				defaultOption = options.defaultOption;
			
			// Add in the rest of the markup
			styledSelectContent += '<a href="#" class="styled_select"><span class="selection_holder">' + defaultOption + '</span>' + dropdownIcon + '</a><div class="options_container">' + newOptions + '</div></div>';
			
			// Insert the new markup and hide the original select box
			$this.after(styledSelectContent).hide();
			
			// Run the onComplete callback if required
			(options.callback.onComplete || null);
			
			// Remove the clearfix class if required
			if (options.disableClearfix == true)
				$('.' + options.containerClass).removeClass('clearfix');
				
				
			// When clicking a Styled Select box, show its options
			$this.next('.' + options.containerClass).find('.styled_select').click(function(){
				var $optionsContainer = $(this).siblings('.options_container');
				
				// Fade out all other optionsContainers except this one
				$('.options_container').not($optionsContainer).fadeOut('fast');
				
				($optionsContainer.is(':visible'))
					? $optionsContainer.hide()
					: $optionsContainer.slideDown(100);
					
				return false;
			// Fix the age old z-index issue with IE7 where the containing element needs a higher z-index
			}).end().css('z-index', zIndex--);
			
			/*
			When a Styled Option is clicked, change the original select box's value... 
			...then change this parents text to be the value of the clicked Styled Option and hide the options container
			*/
			$this.next('div').find('.options_container span').click(function(){
				var	$thisOption = $(this), 
					filterValue = $thisOption.data('value'),
					tidyFilterValue = $thisOption.text();
				
				$this.val(filterValue);
				
				$thisOption
					.closest('.options_container')
					.fadeOut('fast')
					.siblings('.styled_select')
					.find('span:not(.styled_select_arrow)')
					.text(tidyFilterValue);
				
				// Run any change events already bound to the select
				$this.change();
				
				// Run the onChange callback if required
				(options.callback.onChange || null);		
					
			});
			
			// Clicking anywhere will hide any options containers
			$('body').click(function() {
				$('.options_container:visible').fadeOut('fast');
			});
			
		});
	}
	
	function debug(value)
	{
		if (window.console && window.console.log)
			console.log(value);
	}

})(jQuery);
