//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;
		}
	}
}

jQuery.fn.sSelect = function(options) {
	
  return this.each(function(){
	  
	var defaults = {
		defaultText: '(Seleziona)',
		objWidth: 0,
		fixPos: false
	};
	

	//initial variables
	var opts = jQuery.extend(defaults, options),
		$oldSelectBox = jQuery(this),
		$newSelectBox = jQuery('<input type="text" autocomplete="off" readonly="readonly" class="newSelectBox" id="newSelectBox_'+$oldSelectBox.attr("id")+'" name="newSelectBox_'+$oldSelectBox.attr("id")+'" />'),
		$containerSelectBox = jQuery('<div class="containerSelectBox" tabindex="0" ></div>'),
		$newUl = jQuery('<ul></ul>'),
		
		itemIndex = -1,
		currentIndex = -1,
		keys = [],
		prevKey = false,
		newListItems = ''		

	//build new list
	$containerSelectBox.insertAfter($oldSelectBox);
	$newSelectBox.insertAfter($oldSelectBox);				
	$newUl.appendTo($containerSelectBox);
	$oldSelectBox.hide();
   
	//test for optgroup
	if ($oldSelectBox.children('optgroup').length == 0){
		$oldSelectBox.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
		$newUl.html(newListItems);
		//cache list items object
		var $newLi = $newUl.children();
	} else { //optgroup
		$oldSelectBox.children('optgroup').each(function(i){
		
			var optionTitle = jQuery(this).attr('label'),
				$optGroup = jQuery('<li><span class="newListOptionTitle">'+optionTitle+'</span></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');
	}

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

	var newLiLength = $newLi.length;

	//******************************************FIX WIDTH*****************************************
	if (defaults.objWidth>0){
		$containerSelectBox.css('width', defaults.objWidth+'px');
	}
	plr=parseInt($newSelectBox.css("padding-left"))+parseInt($newSelectBox.css("padding-right"));
	wTot=$containerSelectBox.width();
	$newSelectBox.css('width', (wTot-plr)+'px');
	$containerSelectBox.css('width', wTot+'px');
	//*******************************************************************************************

	
	//positioning
	function positionFix(){
		//****************FIX POSITION*****************
		var position = $newSelectBox.position();									
		$containerSelectBox.css('left' , position.left + "px" );		
		
		ptb=$newSelectBox.outerHeight();	
		$containerSelectBox.css('top' , (position.top +ptb)+ "px");	
		//altrimenti se presente jquery dimension		
		//$containerSelectBox.css('top' , (position.top + ptb*2)+ "px");	
		//*********************************************
		
	}

	
	//decide if to place the new list above or below the drop-down
	function newUlPos(){
		positionFix();
		if (defaults.fixPos){
			var containerSelectBoxPosY = parseInt($containerSelectBox.css('top')),
				containerSelectBoxHeight = $containerSelectBox.height()+parseInt($containerSelectBox.css("padding-top"))+parseInt($containerSelectBox.css("padding-bottom")),
				newSelectBoxHeight= $newSelectBox.height()+parseInt($newSelectBox.css("padding-top"))+parseInt($newSelectBox.css("padding-bottom")),
				scrollTop = jQuery(window).scrollTop(),
				docHeight = jQuery(window).height(),			
				containerSelectBoxPosY = containerSelectBoxPosY-scrollTop,
				newContainerSelectBoxPosY = containerSelectBoxPosY-containerSelectBoxHeight-newSelectBoxHeight
				
				
			if (containerSelectBoxPosY+containerSelectBoxHeight >= docHeight){		
				$containerSelectBox.css('top', newContainerSelectBoxPosY+'px');
			}
		}
	}

	//run function on page load
	newUlPos();
	
	//run function on browser window resize
	jQuery(window).resize(function(e){
		newUlPos(e);
	});
	
	jQuery(window).scroll(function(e){
		newUlPos(e);
	});
	
    $newSelectBox.click(function(){	
		if ($containerSelectBox.is(':visible')){
			$containerSelectBox.hide();
			return false;
		}
		positionFix();
		$containerSelectBox.show();
		$containerSelectBox.focus();	
		keyPress(this);
	});
	
	$containerSelectBox.focus(function(){
        keyPress(this);
    });
	
	//hide list on blur
    $containerSelectBox.blur(function(){
       $containerSelectBox.hide();
    });

    $newSelectBox.hover(function(e) {
		var $hoveredTxt = jQuery(e.target);
        $hoveredTxt.addClass('newSelectBoxHover');
      }, 
      function (e) {
		var $hoveredTxt = jQuery(e.target);
        $hoveredTxt.removeClass('newSelectBoxHover');
      }
    );

    $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),
			text = $clickedLi.text();
		
        //update counter
        currentIndex = $newLi.index($clickedLi);
        //remove all hilites, then add hilite to selected item
        $newLi.removeClass('selectedItem');
        $clickedLi.addClass('selectedItem');
        
		setSelectText(text);
        $containerSelectBox.hide();		
    });

	function setSelectText(text){
		//set text of select box
        $oldSelectBox.val(text).change();
        $newSelectBox.val(text);
	}

    //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;
            }

            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: //return
				$containerSelectBox.hide();
				return false;
				break;
			case 27:
				$containerSelectBox.hide();
				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
				e.preventDefault();
				++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;
			}
        }
    }

	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(e){
		currentIndex = newLiLength-1;
		navigateList(currentIndex);
	}
	
	function navigateList(currentIndex){
		$newLi.removeClass('selectedItem')
			.eq(currentIndex).addClass('selectedItem');
        var text = $newLi.eq(currentIndex).text();
		setSelectText(text);
	}
	
   
  });
};

