(function($) {
	$.fn.selectmore = function() {
		var index = -1;
		
		$(this).each(function() {
			index++;
			var theName = index;
			
			/* CREATE HIDDEN FORM ELEMENT FOR TABBING AND SERVER PASSING */
			$(this).before('<input type="text" class="'+theName+'-tab cs-tab" style="position: absolute; left: -9999px;" />');
			$('.'+theName+'-tab').attr("autocomplete","off");
			
			/* CREATE CUSTOM SELECT */
			$(this).after('<ul class="'+theName+'-select cs-select"><li class="current"></li><ol></ol></ul>');
			
			/* POPULATE OPTIONS */
			var opPopIndex = 0;
			$(this).children().each(function() {
				/* GENERATE SELECTED OPTION */
				if($(this).attr("selected")) {
					$('.' + theName + '-select ol').append('<li class="' + theName + '-option cs-option cs-selected cs-highlight cs-o' + opPopIndex + '" cs-value="' + $(this).val() + '"><div>' + $(this).text() + '</div></li>');
					$('.' + theName + '-select ol').scrollTop($('.' + theName + '-select ol .cs-selected').position().top + $('.' + theName + '-select ol').scrollTop());
				}
				/* GENERATE OTHER OPTIONS */
				else 
					$('.' + theName + '-select ol').append('<li class="' + theName + '-option cs-option cs-o' + opPopIndex + '" cs-value="' + $(this).val() + '"><div class="cs-option-content">' + $(this).text() + '</div></li>');
				opPopIndex++;
			});
			
			/* FUNCTIONAL SELECT LIST STYLES */
			$('.'+theName+'-select ol').css("opacity","0");
			
			//$('.'+theName+'-select ol').css("margin-top",$('.'+theName+'-select .current').outerHeight()*-1+"px");
			//if($.browser.safari && ($(this).parents("li").css("float") == "left" || $(this).parents("li").css("float") == "right"))
				//$('.'+theName+'-select ol').css("margin-top",$('.'+theName+'-select .current').outerHeight()+"px");
			//$('.'+theName+'-select ol').css("left",$('.'+theName+'-select .current').position().left+"px");
			//$('.'+theName+'-select ol').css("left","0");
			
			/* IF OPTIONS DO NOT EXCEED LIST HEIGHT, SHORTEN LIST HEIGHT */
			var opHeight = 0;
			$.each($('.'+theName+'-select ol li'), function() {
				opHeight+=$(this).outerHeight();
			});
			
			
			if($('.'+theName+'-select ol').height() > opHeight) {
				$('.'+theName+'-select ol').height(opHeight);
				$('.'+theName+'-select ol').css("overflow","hidden");
			} else {
				$('.'+theName+'-select ol').width($('.'+theName+'-select ol').width()+15);
			}

			/* DISPLAY SELECT LIST AT SELECTED ITEM */
			//console.log($('.'+theName+'-select ol .cs-highlight').position().top);
			//$('.'+theName+'-select ol').scrollTop($('.'+theName+'-select ol .cs-highlight').position().top);
			//$('.'+theName+'-select ol').scrollLeft($('.'+theName+'-select ol .cs-highlight').position().left);
			
			/* DISPLAY DEFAULT SELECTED ITEM */
			$('.'+theName+'-select .current').text($('.'+theName+'-select ol li.cs-selected').text());
			
			/* OPTION-LIST-DISPLAY-RELATED CLICK EVENTS */
			$(this).siblings('.'+theName+'-tab').focus(function() {
				toggleCS($('.'+theName+'-select'), true);
			});
			$(this).focus(function() {
				if(!shift) {
					$(':input').eq($(':input').index(this)+1).focus();
				}
			});
			$('.'+theName+'-select').click(function(e) {
				
				if(!$(e.target).is('.cs-option-content') && !$(this).hasClass("cs-open")) {
					
					// need function to hide item values on rollover
					
					toggleCS('.cs-open');
					$('.' + theName + '-tab').focus();
					
					hideSelectStack(e);
					
				}
			});
			$('.'+theName+'-select .current').click(function(e) {
				if($(this).parent().hasClass("cs-open")) {
					var opa = parseFloat($('.cs-open ol').css("opacity")) ? "0" : "1";
					var top = opa == "1" ? $(this).parent().children('.current').height() + "px" : "-9999px";
					$('.cs-open ol').css("opacity",opa);
					$('.cs-open ol').css("top",top);
					
					if (opa == 1) {
						hideSelectStack(e);
					} else {
						showSelectStack();
					}
					
				}
			});
			
			/* OPTION ITEMS MOUSE EVENTS */
			$(this).siblings('.'+theName+'-select').children('ol').children('li').click(function() {
				selectCS(this);
				var opa = parseFloat($('.cs-open ol').css("opacity")) ? "0" : "1";
				var top = opa == "1" ? $(this).parent().siblings('.current').height() + "px" : "-9999px";
				$('.cs-open ol').css("opacity",opa);
				$('.cs-open ol').css("top",top);
			});
			$(this).siblings('.'+theName+'-select').children('ol').children('li').mouseover(function() {
				if (!held) {
					$('li.cs-highlight').removeClass("cs-highlight");
					$(this).addClass("cs-highlight");
				}
			});
			$('.'+theName+'-select ol').css("display","none");
			
			// HIDE ORIGINAL SELECT
			$(this).css("position","absolute");
			$(this).css("left","-9999px");
		});
		
		/* KEYBOARD CONTROLS */
		var numbers = new Array();
		var letters = new Array();
		numbers[48] = "0";
		numbers[49] = "1";
		numbers[50] = "2";
		numbers[51] = "3";
		numbers[52] = "4";
		numbers[53] = "5";
		numbers[54] = "6";
		numbers[55] = "7";
		numbers[56] = "8";
		numbers[57] = "9";
		letters[65] = "a";
		letters[66] = "b";
		letters[67] = "c";
		letters[68] = "d";
		letters[69] = "e";
		letters[70] = "f";
		letters[71] = "g";
		letters[72] = "h";
		letters[73] = "i";
		letters[74] = "j";
		letters[75] = "k";
		letters[76] = "l";
		letters[77] = "m";
		letters[78] = "n";
		letters[79] = "o";
		letters[80] = "p";
		letters[81] = "q";
		letters[82] = "r";
		letters[83] = "s";
		letters[84] = "t";
		letters[85] = "u";
		letters[86] = "v";
		letters[87] = "w";
		letters[88] = "x";
		letters[89] = "y";
		letters[90] = "z";

		var keybinder = $.browser.msie ? document : window;
		var held = false;
		var shift;

		$(keybinder).keydown(function(e) {
			shift = e.shiftKey;
			
			if(!e.ctrlKey && !e.altKey && !e.metaKey) {
				switch(e.keyCode) {
					case 37: //LEFT
						if(!held) {
							$('.cs-open ol').css("opacity",1);
							$('.cs-open ol').css("top",$('.cs-open li.current').height()+"px");
							held = setInterval(function() { scrollCS('.cs-open',true) }, 50);
						}
						break;
					case 38: //UP
						if(!held) {
							$('.cs-open ol').css("opacity",1);
							$('.cs-open ol').css("top",$('.cs-open li.current').height()+"px");
							held = setInterval(function() { scrollCS('.cs-open',true) }, 50);
						}
						break;
					case 39: //RIGHT
						if(!held) {
							$('.cs-open ol').css("opacity",1);
							$('.cs-open ol').css("top",$('.cs-open li.current').height()+"px");
							held = setInterval(function() { scrollCS('.cs-open',false) }, 50);
						}
						break;
					case 40: //DOWN
						if(!held) {
							$('.cs-open ol').css("opacity",1);
							$('.cs-open ol').css("top",$('.cs-open li.current').height()+"px");
							held = setInterval(function() { scrollCS('.cs-open',false) }, 50);
						}
						break;
					case 9: //TAB
						if($('.cs-open').length > 0) {
							selectCS($('.cs-open ol .cs-highlight'));
							toggleCS('.cs-open');
						}
						break;
					case 13: //ENTER
						if($('.cs-open').length > 0) {
							var opa = parseFloat($('.cs-open ol').css("opacity")) ? "0" : "1";
							var top = opa == "1" ? $('.cs-open li.current').height() + "px" : "-9999px";
							if(opa == "0") {
								selectCS($('.cs-open ol .cs-highlight'));
								$('.cs-open ol').css("opacity",opa);
								$('.cs-open ol').css("top",top);
							}
							else 
								$('.cs-open').parents('form').submit();
						}
						break;
					case 32: //SPACEBAR
						if($('.cs-open').length > 0) {
							var opa = parseFloat($('.cs-open ol').css("opacity")) ? "0" : "1";
							var top = opa == "1" ? $('.cs-open li.current').height() + "px" : "-9999px";
							if(opa == "0")
								selectCS($('.cs-open ol .cs-highlight'));
							$('.cs-open ol').css("opacity",opa);
							$('.cs-open ol').css("top",top);
						}
						break;
					case 27: //ESC
						if($('.cs-open').length > 0) {
							toggleCS('.cs-open');
						}
						break;
					default:
						break;
				}
				
				if((e.keyCode >= 65 && e.keyCode <= 90 || e.keyCode >= 48 && e.keyCode <= 57) && $('.cs-open').length > 0) {
					$('.cs-open .cs-option').each(function() {
						if($(this).text()[0] == letters[e.keyCode] || $(this).text()[0] == letters[e.keyCode].toUpperCase()) {
							$(this).addClass("cs-match");
						}
					});
					
					if($('.cs-match.cs-highlight').length == 0) {
						$('.cs-open .cs-highlight').removeClass("cs-highlight");
						$('.cs-match:first').addClass('cs-highlight');
						selectCS($('.cs-open ol .cs-highlight'));
						$('.cs-open ol').scrollTop(0);
						$('.cs-open ol').scrollLeft(0);
						$('.cs-open ol').scrollTop($('.cs-open ol .cs-highlight').position().top);
						$('.cs-open ol').scrollLeft($('.cs-open ol .cs-highlight').position().left);
					} else if($('.cs-match:last').hasClass('cs-highlight') && $('.cs-match').length - 1 != 0) {
						$('.cs-open .cs-highlight').removeClass('cs-highlight');
						$('.cs-match:first').addClass("cs-highlight");
						selectCS($('.cs-open ol .cs-highlight'));
						$('.cs-open ol').scrollTop(0);
						$('.cs-open ol').scrollLeft(0);
						$('.cs-open ol').scrollTop($('.cs-open ol .cs-highlight').position().top);
						$('.cs-open ol').scrollLeft($('.cs-open ol .cs-highlight').position().left);
					} else {
						$('.cs-match.cs-highlight').next().addClass('cs-highlight');
						$('.cs-match.cs-highlight:first').removeClass('cs-highlight');
						selectCS($('.cs-open ol .cs-highlight'));
						//$('.cs-open ol').scrollTop(0);
						//$('.cs-open ol').scrollLeft(0);
						//$('.cs-open ol').scrollTop($('.cs-open ol .cs-highlight').position().top);
						//$('.cs-open ol').scrollLeft($('.cs-open ol .cs-highlight').position().left);
					}
					$('.cs-match').removeClass('cs-match');
				}
			}
		});
		$(keybinder).keyup(function(e) {
			clearInterval(held);
			held = false;
		});
		$(keybinder).keydown(function(e) {
			if($('.cs-open').length > 0 && (!e.ctrlKey && !e.altKey && !e.metaKey)) {
				return false;
			}
		});
		$(keybinder).keypress(function(e) {
			if($('.cs-open').length > 0 && (!e.ctrlKey && !e.altKey && !e.metaKey)) {
				return false;
			}
		});
		
		$(document).click(function(e) {
			if($('.cs-open').length > 0) {
				var target = $(e.target);
				if(!target.is('.cs-select') && !target.is('.current') && !target.is('.cs-open') && !target.is('.cs-option-content')) {
					if($('.cs-open ol').css("opacity") == "0")
						toggleCS('.cs-open');
					else {
						$('.cs-open ol').css("opacity","0");
						$('.cs-open ol').css("top","-9999px");
						$('.cs-open ol .cs-highlight').removeClass('cs-highlight');
						$('.cs-open ol .cs-selected').addClass('cs-highlight');
						$('.cs-open li.current').text($('.cs-open ol .cs-selected').text());
						$('.cs-open ol').scrollTop($('.cs-open ol .cs-selected').position().top + $('.cs-open ol').scrollTop());
						
						showSelectStack ();
						
					}
				}
			}
		});

		
		/* EVENT : OPEN / CLOSE CUSTOM SELECT OPTION LIST */
		function toggleCS(obj, picked) {
			/* MAIN TOGGLE ACTIONS */
			var theSelect = $(obj);
			var theOptions = theSelect.children('ol');
			if(!theSelect.hasClass("cs-open") || picked) {
				theSelect.addClass("cs-open");
				theOptions.css("top",theSelect.children('.current').height() + "px");
				theOptions.css("display","block").animate({
					//marginTop: theSelect.children('.current').outerHeight() + "px",
					opacity: "1"
				}, 'fast');
				
			} else {
				theSelect.removeClass("cs-open");
				theOptions.children('.cs-highlight').removeClass('cs-highlight');
				theOptions.children('.cs-selected').addClass('cs-highlight');
				theOptions.css("display","none");
				
				showSelectStack ();
				
				/* We've changed the functionality, only fade in once.
				 * theOptions.animate({
					//marginTop: theSelect.children('.current').outerHeight()*-1 + "px",
					opacity: "0"
				}, 'fast', function() {
					theSelect.removeClass("cs-open");
					theOptions.children('.cs-highlight').removeClass('cs-highlight');
					theOptions.children('.cs-selected').addClass('cs-highlight');
					theOptions.css("display","none");
				});*/
			}
		}
		/* EVENT : SCROLL THROUGH OPTIONS */
		var btnDown = false;
		function scrollCS(obj, up) {
			var curHighlight = $(obj).children('ol').children('.cs-highlight');
			var opIndex = $(obj).children('ol').children().length - $(obj).children('ol').children('.cs-highlight').nextAll().length - 1;
			if(up && opIndex > 0 && !btnDown) {
				btnDown = true;
				setTimeout(function() {
					curHighlight.removeClass('cs-highlight');
					curHighlight.prev().addClass("cs-highlight");
					$(obj).children('ol').scrollTop($(obj).find('.cs-highlight').position().top + $(obj).children('ol').scrollTop());
					$(obj).children('li.current').text($('.cs-open ol .cs-highlight').text());
					btnDown = false;
				}, 50);
			} else if(!up && opIndex < $(obj).children('ol').children().length-1 && !btnDown) {
				btnDown = true;
				setTimeout(function() {
					curHighlight.removeClass('cs-highlight');
					curHighlight.next().addClass("cs-highlight");
					$(obj).children('ol').scrollTop($(obj).find('.cs-highlight').position().top + $(obj).children('ol').scrollTop());
					$(obj).children('li.current').text($('.cs-open ol .cs-highlight').text());
					btnDown = false;
				}, 50);
			}
		}
		/* EVENT : SELECT AN OPTION */
		function selectCS(obj) {
			if($(obj).parents('ul.cs-open').length == 1) {
				$(obj).parents('ul.cs-open').children('.current').text($(obj).text());
				$(obj).parents('ul.cs-open').children('.current').attr("style",$(obj).attr("style"));
				$('.cs-open .cs-selected').removeClass("cs-selected");
				$('.cs-open .cs-highlight').removeClass("cs-highlight");
				$(obj).addClass("cs-selected cs-highlight");
				var opIndex = ($(obj).parent().children().length - $(obj).nextAll().length) - 1;
				$(obj).parent().parent().siblings('select').val($(obj).attr("cs-value"));
				$(obj).parent().parent().siblings('select').children('option').eq(opIndex).attr("selected","selected");
				$(obj).parent().parent().siblings('select').change();
				
				showSelectStack ();
			}
		}
		
		function hideSelectStack (e) {
			// HIDE ALL other selects in stack of selects w a higher index
			// get all divs in the collection with an index higher then THIS one
			var index = $("div.selectMore_stack").index($(e.target).closest("div.selectMore_stack"));					
			var selectDivs_toHide = $("div.selectMore_stack:gt("+index+")");
			// hide them
			selectDivs_toHide.hide();
		}
		
		function showSelectStack () {
			$("div.selectMore_stack").show();
		}
	}
})(jQuery);