/* $Id: customselect.jquery.js,v 1.1.2.3 2008/08/22 00:14:24 gburns Exp $

Unobtrusive Accessible jQuery 1.2.1 drop downs.

Overview:
	jQuery.fn.customselect()

Parameters:
	prepend: (String) Text to be prepended to classes on nodes.
		Default: 'customselect_'

Usage:
	HTML:
	<select name="selector" id="selector">
		<option name="something" value="something_value">Something Display</option>
	</select"

	JavaScript:
	$('#selector').customselect();

Author:
	gburns

TODO:

*/

(function($) {
$.fn.customselect = function(arguments) {
	var settings = $.extend({
		prepend: 'customselect_',
		submit: false // submit the form when input is clicked
	}, arguments || {});

	return this.each(function() {
		var $this = $(this);

		var $select_node = $('<span/>')
			.addClass(settings.prepend + 'main')
			.bind('click', function(e) {
				if ( $options_node.is(':visible') ) {
					$options_node.hide();
				} else {
					$options_node.show();
				}
				e.stopPropagation();
				return false;
			});

		var $options = $('option', $this);

		var current_html = $options.filter(':selected').html().replace(/^\s\s*/, '').replace(/\s\s*$/, '');
		if ( !current_html ) current_html = '&nbsp;';

		var header_selector = 'h3 a';
		var $header_node = $('<h3/>')
			.append(
				$('<a href="javascript:;"/>')
					.html(current_html)
					.css({display: 'block'})
					.bind('keypress', function(e) {
						//37, 38 up
						//39, 40 down
						var c = (e.which) ? e.which : e.keyCode;
						if ( c == 37 || c == 38 ) {
							var index = $options.index($selected_node);
							if ( index - 1 >= 0 ) {
								set_selection($($options.get(index - 1)));
							} else {
								set_selection($($options.get($options.length - 1)));
							}
							return false;
						} else if ( c == 39 || c == 40 ) {
							var index = $options.index($selected_node);
							if ( index + 1 < $options.length ) {
								set_selection($($options.get(index + 1)));
							} else {
								set_selection($($options.get(0)));
							}
							return false;
						}
					})
			)
			.appendTo($select_node);

		var options_selector = 'ul';
		var $options_node = $('<div/>')
			.addClass(settings.prepend + 'options')
			.append($('<ul/>'))
			.appendTo($select_node);

		var option_selector = 'li';

		/*var $hidden_input = $('<input type="hidden"/>')
			.attr({name: $this.attr('name')})
			.attr({value: $this.attr('value')})
			.addClass(settings.prepend + 'hidden')
			.appendTo($select_node);*/

		$this
			.hide()
			//.css({height: 100, width: 100, padding: 0, margin: -1, border: 0})
			//.attr({tabIndex: -1})
			.after($select_node);

		var $selected_node;
		var set_selection = function($option) {
			var value = $option.attr('value');
			$($(option_selector, $select_node).get($options.index($selected_node))).removeClass(settings.prepend + 'selected');
			$selected_node = $option;
			var display = $option.html().replace(/^\s\s*/, '').replace(/\s\s*$/, '');
			if ( !display ) display = '&nbsp;';

			//$hidden_input.attr({value: value});
			$(header_selector, $select_node)
				.html(display);
			$option
				.attr({selected: 'selected'});

			$($(option_selector, $select_node).get($options.index($option))).addClass(settings.prepend + 'selected');
		}

		$options.each(function() {
			var $option = $(this);
			var display = $option.html().replace(/^\s\s*/, '').replace(/\s\s*$/, '');
			if ( !display ) display = '&nbsp;';
			var $option_node = $('<li/>')
				.addClass(settings.prepend + 'option')
				.bind('click', function(e) {
					set_selection($option);
					$options_node
						.hide();
					e.stopPropagation();
				})
				.html(display)
				.appendTo($(options_selector, $select_node));

			if ( $option.is(':selected') ) {
				$selected_node = $option;
			}

			if ( settings.submit ) {
				$option_node.bind('click', function() {
					$select_node.parents('form').get(0).submit();
				});
			}
		});

		$($(option_selector, $select_node).get($options.index($selected_node))).addClass(settings.prepend + 'selected');

		$(document).bind('click', function() {
			$options_node.hide();
		});

		var $h = $(header_selector, $select_node);
		var header_extra = parseInt($h.css('paddingLeft')) + parseInt($h.css('paddingRight')) + parseInt($h.css('borderLeftWidth')) + parseInt($h.css('borderRightWidth'));
		var header_inner_width = $h.outerWidth() - header_extra;
		$h.css({width: header_inner_width});

		var $s = $(option_selector, $select_node);
		var option_extra = parseInt($s.css('paddingLeft')) + parseInt($s.css('paddingRight')) + parseInt($s.css('borderLeftWidth')) + parseInt($s.css('borderRightWidth'));
		var option_inner_width = $s.outerWidth() - option_extra;

		if ( header_inner_width > option_inner_width ) {
			$s.css({width: option_inner_width + (header_inner_width - option_inner_width)});
		} else if ( header_inner_width < option_inner_width ) {
			$h.css({width: header_inner_width + (option_inner_width - header_inner_width)});
		}

		header_inner_width = $h.outerWidth() - header_extra;
		option_inner_width = $s.outerWidth() - option_extra;

		var select_outer_width = $select_node.outerWidth();
		var options_outer_width = $options_node.outerWidth();

		if ( select_outer_width > options_outer_width ) {
			$s.css({width: option_inner_width + (select_outer_width - options_outer_width)});
		} else if ( select_outer_width < options_outer_width ) {
			$h.css({width: header_inner_width + (options_outer_width - select_outer_width)});
		}

		$(options_selector, $options_node).css({overflowY: 'auto', overflowX: 'hidden'});

		/*var extra_padding = h_padding - s_padding;
		$s.css({width: $s.outerWidth() + extra_padding});

		var header_outer_width = $select_node.outerWidth();
		var options_outer_width = $options_node.outerWidth();

		if ( options_outer_width > header_outer_width ) {
			$h.css({width: $h.outerWidth() - h_padding + (options_outer_width - header_outer_width)});
		} else if ( options_outer_width < header_outer_width ) {
			//$(options_selector, $select_node).css({width: $(options_selector, $select_node).innerWidth() + (header_outer_width - options_outer_width)});
		}*/

		$options_node.hide();
	});
}
})(jQuery);