/*
Stylish Select 0.3 -  plugin to replace a select drop down box with a stylable unordered list
http://scottdarby.com/

Copyright (c) 2009 Scott Darby

Requires:  1.3

Licensed under the GPL license:
http://www.gnu.org/licenses/gpl.html
*/
(function(){

	//add class of js to html tag
	jQuery('html').addClass('js');

	//utility methods
	jQuery.fn.extend({
		getSetSSValue: function(value){
						if (value){
							//set value and trigger change event
							jQuery(this).val(value).change();
							return this;
						} else {
							return selText = jQuery(this).find(':selected').text();
						}
					},
		getSetSSId: function(value){if (value){
							//set value and trigger change event
							jQuery(this).val(value).change();
							return this;
						} else {
							return selText = document.getElementById('currency-dropdown').value;
						}
					},
		resetSS: function(){
						thisis = jQuery(this);
						thisis.next().remove();
						//unbind all events and redraw
						thisis.unbind().sSelect();
					}
	});

	jQuery.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
			};

			//initial variables
			var opts = jQuery.extend(defaults, options),
				input = jQuery(this),
				containerDivText = jQuery('<div class="selectedTxt"></div>'),
				containerDiv = jQuery('<div class="newListSelected" tabindex="0"></div>'),
				newUl = jQuery('<ul class="newList"></ul>'),
				itemIndex = -1,
				currentIndex = -1,
				keys = [],
				prevKey = false,
				newListItems = '',
				prevented = false;
				
			//build new list
			containerDiv.insertAfter(input);
			containerDivText.prependTo(containerDiv);
			newUl.appendTo(containerDiv);
			input.hide();
		
			//test for optgroup
			if (input.children('optgroup').length == 0){
				input.children().each(function(i){
					var option = jQuery(this).text();
					var optionVal = (jQuery(this).val());
					//add first letter of each word to array
					keys.push(option.charAt(0).toLowerCase());
					if (jQuery(this).attr('selected') == true){
						opts.defaultText = option;
						currentIndex = i;
					}
					newListItems += '<li class="icon-'+ optionVal +'">'+option+'</li>';
				});
				//add new list items to ul
				newUl.html(newListItems);
				newListItems = '';
				//cache list items object
				var newLi = newUl.children();
								
			} else { //optgroup
				input.children('optgroup').each(function(i){
				
					var optionTitle = jQuery(this).attr('label'),
						optGroup = jQuery('<li class="newListOptionTitle">'+optionTitle+'</li>');
						
					optGroup.appendTo(newUl);

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

					optGroupList.appendTo(optGroup);

					jQuery(this).children().each(function(){
						++itemIndex;
						var option = jQuery(this).text();
						//add first letter of each word to array
						keys.push(option.charAt(0).toLowerCase());
						if (jQuery(this).attr('selected') == true){
							opts.defaultText = option;
							currentIndex = itemIndex;
						}
						newListItems += '<li>'+option+'</li>';
					})
					//add new list items to ul
					optGroupList.html(newListItems);
					newListItems = '';
				});
				//cache list items object
				var newLi = newUl.find('ul li');
			
			}
			
			//get heights of new elements for use later
			var newUlHeight = newUl.height()+3,
				containerHeight = containerDiv.height()+3,
				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
			jQuery(window).resize(function(){
				newUlPos();
			});
			
			jQuery(window).scroll(function(){
				newUlPos();
			});

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

			function positionHideFix(){
				containerDiv.css('position','static');
			}
			
			containerDivText.click(function(){
			
				if (newUl.is(':visible')){
					newUl.hide();
					positionHideFix()
					return false;
				}

				containerDiv.focus();

				//show list
				newUl.slideDown(opts.animationSpeed);
				positionFix();
				//scroll list to selected item
				newUl.scrollTop(input.liOffsetTop);

			});
			
			newLi.hover(
			  function (e) {
				var hoveredLi = jQuery(e.target);
				hoveredLi.addClass('newListHover');
			  },
			  function (e) {
				var hoveredLi = jQuery(e.target);
				hoveredLi.removeClass('newListHover');
			  }
			);

			newLi.click(function(e){
				var clickedLi = jQuery(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
				containerDivText.addClass('icon-'+input.val());
			});

			function navigateList(currentIndex, init){
				//get offsets
				var containerOffsetTop = containerDiv.offset().top,
					liOffsetTop = newLi.eq(currentIndex).offset().top,
					ulScrollTop = newUl.scrollTop();
				
				//get distance of current li from top of list				
				if (input.onTop == true){
					//if list is above select box, add max height value
					input.liOffsetTop = (((liOffsetTop-containerOffsetTop)-containerHeight)+ulScrollTop)+parseInt(opts.ddMaxHeight);
				} else {
					input.liOffsetTop = ((liOffsetTop-containerOffsetTop)-containerHeight)+ulScrollTop;
				}
				
				//scroll list to focus on current item
				newUl.scrollTop(input.liOffsetTop);
				newLi.removeClass('hiLite')
					.eq(currentIndex)
					.addClass('hiLite');
				var text = newLi.eq(currentIndex).text();
				var textVal = input.val();
				//page load
				if (init == true){
					input.val(text);
					containerDivText.text(text);
					containerDivText.addClass('icon-'+textVal);
					return false;
				}
				input.val(text).change();
				containerDivText.text(text);
			};

			input.change(function(event){
					targetInput = jQuery(event.target);
					//stop change function from firing 
					if (prevented == true){
						prevented = false;
						return false;
					}
					currentOpt = targetInput.find(':selected');
					currentIndex = targetInput.find('option').index(currentOpt);
					navigateList(currentIndex, true);
				}
			);
			
			//handle up and down keys
			function keyPress(element) {
				//when keys are pressed
				element.onkeydown = function(e){
					if (e == null) { //ie
						var keycode = event.keyCode;
					} else { //everything else
						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.click(function(){
				keyPress(this);
			});

			containerDiv.focus(function(){
				jQuery(this).addClass('newListSelFocus');
				keyPress(this);
			});
			
			//hide list on blur
			containerDiv.blur(function(){
			   jQuery(this).removeClass('newListSelFocus');
			   newUl.hide();
			   positionHideFix();
			});

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

			//reset left property and hide
			newUl.css('left','0').hide();
			
		});
	  
	};

})(jQuery);
