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

Copyright (c) 2009 Scott Darby

Requires: jQuery 1.3

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

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

	//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
	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();
						}
					},
		resetSS: function(){
						jQuerythis = jQuery(this);
						jQuerythis.next().remove();
						//unbind all events and redraw
						jQuerythis.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),
				jQueryinput = jQuery(this),
				jQuerycontainerDivText = jQuery('<div class="selectedTxt"></div>'),
				jQuerycontainerDiv = jQuery('<div class="newListSelected" tabindex="0"></div>'),
				jQuerynewUl = jQuery('<ul class="newList"></ul>'),
				itemIndex = -1,
				currentIndex = -1,
				keys = [],
				prevKey = false,
				newListItems = '',
				prevented = false;
				
			//build new list
			jQuerycontainerDiv.insertAfter(jQueryinput);
			jQuerycontainerDivText.prependTo(jQuerycontainerDiv);
			jQuerynewUl.appendTo(jQuerycontainerDiv);
			jQueryinput.hide();
		
			//test for optgroup
			if (jQueryinput.children('optgroup').length == 0){
				jQueryinput.children().each(function(i){
					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 = i;
					}
					newListItems += '<li>'+option+'</li>';
				});
				//add new list items to ul
				jQuerynewUl.html(newListItems);
				newListItems = '';
				//cache list items object
				var jQuerynewLi = jQuerynewUl.children();
								
			} else { //optgroup
				jQueryinput.children('optgroup').each(function(i){
				
					var optionTitle = jQuery(this).attr('label'),
						jQueryoptGroup = jQuery('<li class="newListOptionTitle">'+optionTitle+'</li>');
						
					jQueryoptGroup.appendTo(jQuerynewUl);

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

					jQueryoptGroupList.appendTo(jQueryoptGroup);

					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
					jQueryoptGroupList.html(newListItems);
					newListItems = '';
				});
				//cache list items object
				var jQuerynewLi = jQuerynewUl.find('ul li');
			
			}
			
			//get heights of new elements for use later
			var newUlHeight = jQuerynewUl.height()+3,
				containerHeight = jQuerycontainerDiv.height()+3,
				newLiLength = jQuerynewLi.length;
		
			//check if a value is selected
			if (currentIndex != -1){
				navigateList(currentIndex, true);
			} else {
				//set placeholder text
				jQuerycontainerDivText.text(opts.defaultText);
			}

			//decide if to place the new list above or below the drop-down
			function newUlPos(){
				var containerPosY = jQuerycontainerDiv.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){
					jQuerynewUl.css({top: '-'+newUlHeight+'px', height: newUlHeight});
					jQueryinput.onTop = true;
				} else {
					jQuerynewUl.css({top: containerHeight+'px', height: newUlHeight});
					jQuerynewUl.css({width: '190px'});
					jQueryinput.onTop = false;
				}
				
				
					Принудительное вываливание меню только вниз
				*/
				jQuerynewUl.css({top: containerHeight+'px', height: '250px' /*newUlHeight*/, width: '188px'});
				jQueryinput.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(){
				jQuerycontainerDiv.css('position','relative');
			}

			function positionHideFix(){
				jQuerycontainerDiv.css('position','static');
			}
			
			jQuerycontainerDivText.click(function(){
			
				if (jQuerynewUl.is(':visible')){
					jQuerynewUl.hide();
					positionHideFix()
					return false;
				}

				jQuerycontainerDiv.focus();

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

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

			jQuerynewLi.click(function(e){
				var jQueryclickedLi = jQuery(e.target);
				//update counter
				currentIndex = jQuerynewLi.index(jQueryclickedLi);
				//remove all hilites, then add hilite to selected item
				prevented = true;
				navigateList(currentIndex);
				jQuerynewUl.hide();
				jQuerycontainerDiv.css('position','static');//ie
			});

			function navigateList(currentIndex, init){

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

			};

			jQueryinput.change(function(event){
					jQuerytargetInput = jQuery(event.target);
					//stop change function from firing 
					if (prevented == true){
						prevented = false;
						return false;
					}
					jQuerycurrentOpt = jQuerytargetInput.find(':selected');
					currentIndex = jQuerytargetInput.find('option').index(jQuerycurrentOpt);
					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:
						jQuerynewUl.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);
			}

			jQuerycontainerDiv.click(function(){
				keyPress(this);
			});

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

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

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

})(jQuery);
