/*
Stylish Select 0.4.1 - $ plugin to replace a select drop down box with a stylable unordered list
http://github.com/sko77sun/Stylish-Select

Requires: jQuery 1.3 or newer

Contributions from Justin Beasley: http://www.harvest.org/ & Anatoly Ressin: http://www.artazor.lv/

Dual licensed under the MIT and GPL licenses.

 */
(function($) {
	// add class to html tag
	$('html').addClass('stylish-select');

	// create cross-browser indexOf
	Array.prototype.indexOf = function(obj, start) {
		for ( var i = (start || 0); i < this.length; i++) {
			if (this[i] == obj) {
				return i;
			}
		}
	}

	// utility methods
	$.fn.extend( {
		getSetSSValue : function(value) {
			if (value) {
				// set value and trigger change event
		$(this).val(value).change();
		return this;
	} else {
		return $(this).find(':selected').val();
	}
},
// added by Justin Beasley
		resetSS : function() {
			var oldOpts = $(this).data('ssOpts');
			$this = $(this);
			$this.next().remove();
			// unbind all events and redraw
			$this.unbind('.sSelect').sSelect(oldOpts);
		}
	});

	$.fn.sSelect = function(options) {

		return this.each(function() {

			var defaults = {
				defaultText : 'Please select',
				animationSpeed : 0, // set speed of dropdown
				ddMaxHeight : '', // set css max-height value of dropdown
				containerClass : '' // additional classes for container div
			};

			// initial variables
				var opts = $.extend(defaults, options), $input = $(this), $containerDivText = $('<div class="selectedTxt"></div>'), $containerDiv = $('<div class="newListSelected ' + opts.containerClass + '"></div>'), $newUl = $('<ul class="newList" style="visibility:hidden;"></ul>'), itemIndex = -1, currentIndex = -1, keys = [], prevKey = false, prevented = false, $newLi;

				// added by Justin Beasley
				$(this).data('ssOpts', options);

				// build new list
				$containerDiv.insertAfter($input);
				$containerDiv.attr("tabindex", $input.attr("tabindex") || "0");
				$containerDivText.prependTo($containerDiv);
				$newUl.appendTo($containerDiv);
				$input.hide();

				// added by Justin Beasley (used for lists initialized while
				// hidden)
				$containerDivText.data('ssReRender', !$containerDivText
						.is(':visible'));

				// test for optgroup
				if ($input.children('optgroup').length == 0) {
					$input
							.children()
							.each(function(i) {
								var option = $(this).html();
								var key = $(this).val();

								// add first letter of each word to array
									keys.push(option.charAt(0).toLowerCase());
									if ($(this).attr('selected') == true) {
										opts.defaultText = option;
										currentIndex = i;
									}
									$newUl
											.append($(
													'<li><a href="JavaScript:void(0);">' + option + '</a></li>')
													.data('key', key));

								});
					// cache list items object
					$newLi = $newUl.children().children();

				} else { // optgroup
					$input
							.children('optgroup')
							.each(
									function() {

										var optionTitle = $(this).attr('label'), $optGroup = $('<li class="newListOptionTitle">' + optionTitle + '</li>');

										$optGroup.appendTo($newUl);

										var $optGroupList = $('<ul></ul>');

										$optGroupList.appendTo($optGroup);

										$(this)
												.children()
												.each(
														function() {
															++itemIndex;
															var option = $(this)
																	.html();
															var key = $(this)
																	.val();
															// add first letter
															// of each word to
															// array
															keys
																	.push(option
																			.charAt(
																					0)
																			.toLowerCase());
															if ($(this).attr(
																	'selected') == true) {
																opts.defaultText = option;
																currentIndex = itemIndex;
															}
															$optGroupList
																	.append($(
																			'<li><a href="JavaScript:void(0);">' + option + '</a></li>')
																			.data(
																					'key',
																					key));
														})
									});
					// cache list items object
					$newLi = $newUl.find('ul li a');
				}

				// get heights of new elements for use later
				var newUlHeight = $newUl.height(), containerHeight = $containerDiv
						.height(), newLiLength = $newLi.length;

				// check if a value is selected
				if (currentIndex != -1) {
					navigateList(currentIndex, true);
				} else {
					// set placeholder text
					$containerDivText.text(opts.defaultText);
				}

				// decide if to place the new list above or below the drop-down
				function newUlPos() {
					var containerPosY = $containerDiv.offset().top, docHeight = jQuery(
							window).height(), scrollTop = jQuery(window)
							.scrollTop();

					// if height of list is greater then max height, set list
					// height to max height value
					if (newUlHeight > parseInt(opts.ddMaxHeight)) {
						newUlHeight = parseInt(opts.ddMaxHeight);
					}

					containerPosY = containerPosY - scrollTop;
					if (containerPosY + newUlHeight >= docHeight) {
						$newUl.css( {
							top : '-' + newUlHeight + 'px',
							height : newUlHeight
						});
						$input.onTop = true;
					} else {
						$newUl.css( {
							top : containerHeight + 'px',
							height : newUlHeight
						});
						$input.onTop = false;
					}
				}

				// run function on page load
				newUlPos();

				// run function on browser window resize
				$(window).bind('resize.sSelect scroll.sSelect', newUlPos);

				// positioning
				function positionFix() {
					$containerDiv.css('position', 'relative');
				}

				function positionHideFix() {
					$containerDiv.css('position', 'static');
				}

				$containerDivText.bind('click.sSelect', function(event) {
					event.stopPropagation();

					// added by Justin Beasley
						if ($(this).data('ssReRender')) {
							newUlHeight = $newUl.height('').height();
							containerHeight = $containerDiv.height();
							$(this).data('ssReRender', false);
							newUlPos();
						}

						// hide all menus apart from this one
						$('.newList').not($(this).next()).hide().parent().css(
								'position', 'static').removeClass(
								'newListSelFocus');

						// show/hide this menu
						$newUl.toggle();
						positionFix();
						// scroll list to selected item
						$newLi.eq(currentIndex).focus();

					});

				$newLi.bind('click.sSelect', function(e) {
					var $clickedLi = $(e.target);

					// update counter
						currentIndex = $newLi.index($clickedLi);

						// remove all hilites, then add hilite to selected item
						prevented = true;
						navigateList(currentIndex);
						$newUl.hide();
						$containerDiv.css('position', 'static');// ie

					});

				$newLi.bind('mouseenter.sSelect', function(e) {
					var $hoveredLi = $(e.target);
					$hoveredLi.addClass('newListHover');
				}).bind('mouseleave.sSelect', function(e) {
					var $hoveredLi = $(e.target);
					$hoveredLi.removeClass('newListHover');
				});

				function navigateList(currentIndex, init) {
					$newLi.removeClass('hiLite').eq(currentIndex).addClass(
							'hiLite');

					if ($newUl.is(':visible')) {
						$newLi.eq(currentIndex).focus();
					}

					var text = $newLi.eq(currentIndex).html();
					var val = $newLi.eq(currentIndex).parent().data('key');

					// page load
					if (init == true) {
						$input.val(val);
						$containerDivText.text(text);
						return false;
					}

					try {
						$input.val(val)
					} catch (ex) {
						// handle ie6 exception
						$input[0].selectedIndex = currentIndex;
					}

					$input.change();
					$containerDivText.text(text);
				}

				$input.bind('change.sSelect', function(event) {
					$targetInput = $(event.target);
					// stop change function from firing
						if (prevented == true) {
							prevented = false;
							return false;
						}
						$currentOpt = $targetInput.find(':selected');

						// currentIndex =
						// $targetInput.find('option').index($currentOpt);
						currentIndex = $targetInput.find('option').index(
								$currentOpt);

						navigateList(currentIndex, true);
					});

				// handle up and down keys
				function keyPress(element) {
					// when keys are pressed
					$(element).unbind('keydown.sSelect').bind(
							'keydown.sSelect', function(e) {
								var keycode = e.which;

								// prevent change function from firing
							prevented = true;

							switch (keycode) {
							case 40: // down
							case 39: // right
								incrementList();
								return false;
								break;
							case 38: // up
							case 37: // left
								decrementList();
								return false;
								break;
							case 33: // page up
							case 36: // home
								gotoFirst();
								return false;
								break;
							case 34: // page down
							case 35: // end
								gotoLast();
								return false;
								break;
							case 13:
							case 27:
								$newUl.hide();
								positionHideFix();
								return false;
								break;
							}

							// check for keyboard shortcuts
							keyPressed = String.fromCharCode(keycode)
									.toLowerCase();

							var currentKeyIndex = keys.indexOf(keyPressed);

							if (typeof currentKeyIndex != 'undefined') { // if
																			// key
																			// code
																			// found
																			// in
																			// array
								++currentIndex;
								currentIndex = keys.indexOf(keyPressed,
										currentIndex); // search array from
														// current index
								if (currentIndex == -1 || currentIndex == null
										|| prevKey != keyPressed)
									currentIndex = keys.indexOf(keyPressed); // if
																				// no
																				// entry
																				// was
																				// found
																				// or
																				// new
																				// key
																				// pressed
																				// search
																				// from
																				// start
																				// of
																				// array

								navigateList(currentIndex);
								// store last key pressed
								prevKey = keyPressed;
								return false;
							}
						});
				}

				function incrementList() {
					if (currentIndex < (newLiLength - 1)) {
						++currentIndex;
						navigateList(currentIndex);
					}
				}

				function decrementList() {
					if (currentIndex > 0) {
						--currentIndex;
						navigateList(currentIndex);
					}
				}

				function gotoFirst() {
					currentIndex = 0;
					navigateList(currentIndex);
				}

				function gotoLast() {
					currentIndex = newLiLength - 1;
					navigateList(currentIndex);
				}

				$containerDiv.bind('click.sSelect', function(e) {
					e.stopPropagation();
					keyPress(this);
				});

				$containerDiv.bind('focus.sSelect', function() {
					$(this).addClass('newListSelFocus');
					keyPress(this);
				});

				$containerDiv.bind('blur.sSelect', function() {
					$(this).removeClass('newListSelFocus');
				});

				// hide list on blur
				$(document).bind('click.sSelect', function() {
					$containerDiv.removeClass('newListSelFocus');
					$newUl.hide();
					positionHideFix();
				});

				// add classes on hover
				$containerDivText.bind('mouseenter.sSelect', function(e) {
					var $hoveredTxt = $(e.target);
					$hoveredTxt.parent().addClass('newListSelHover');
				}).bind('mouseleave.sSelect', function(e) {
					var $hoveredTxt = $(e.target);
					$hoveredTxt.parent().removeClass('newListSelHover');
				});

				// reset left property and hide
				$newUl.css( {
					left : '0',
					display : 'none',
					visibility : 'visible',
                                        zIndex: 1000
				});

			});

	};

})(jQuery);
