﻿/* 
jquery plugin for creating nice selectors for usage in forms 

Use this plugin on a <select> element in your form and it will be
replaced by a style dropdown using an unordered list for the <option> elements.

The plugin can be configured to show only a certain amout of list entries using the numberOfVisibleEntries option. 
If there are more option elements, a scrollbar will be used.

There are two modes for the plugin: "text" and "submit"
 - "text" (default) 
 	- will just show the selected option next to the dropdown button (like a normal select box)
	- a click on the selected option will open the dropdown
 - "submit"
 	- in this mode, the selected option next to the dropdown will be a submit button
	- the dropdwon can only be opened using the arrow button
	
A callback function for the selection can be provided:

selectCallback:callbackFunction
The callback will be provided with the following arguments:
 - an array holding the selected values e.g. {text:"Vorarlberg", value:"ApaSearch"}
 - a reference to the selection ul
 
In submit mode a callback function for the submit event can be provided
 
submitCallback:callbackFunction

*/

// create closure
(function($) {
	// plugin definition
	jQuery.fn.mcomSelector = function(options) {
	  // standard settings
	  settings = jQuery.extend({
		containerClass: "Selector",				//css class of the outer container
   
		selectionClass: "Selection",				//css class applied to the upper element showing the active selection
		selectionButtonClass: "SelectionButton",	//css class applied to the upper element showing the active selection in submit mode
		selectionClassActive: "SelectionActive",	//css class applied to the upper element showing the active selection when dropdwon is open
   
		buttonClass: "Button",						//css class applied to the upper dropdown button (e.g. showing an arrow)
		buttonClassActive: "ButtonActive",			//css class applied to the upper dropdown button when dropdown is open
   
		optionListClass: "OptionList",				//css class applied to the <ul> showing the list of options
		optionSelectedClass: "Selected",			//css class applied to a selected/active option element (<li>)
		optionFirstClass: "First",					//css class applied only to the first option element (<li>)
		optionLastClass: "Last",					//css class applied only to the last option element (<li>)
   
		numberOfVisibleEntries: 0,	 				//the number of visible entries - if there are more, a scrollbar will appear. 0=unlimited
		listElementHeight: 31,                      //as we are unable to determine the real width of the hidden li elements we have to set it manually
		listElementWidth: 141,			            //as we are unable to determine the real width of the hidden li elements we have to set it manually
   
		mode: "text",								//mode of the plugin (see desciption above)
		selectCallback: null,                        //optional callback function when selecting an element							
		submitCallback: null                        //optional callback function when using the submit button
	  }, options);
   


	  return this.each(function(){
 		var oldSelector = $(this);						//reference to the original <select> element
		var container = document.createElement("DIV");	//container <div> element
		var optionList = document.createElement("UL");	//<ul> element
		var option = null;								//<li> elements will be created
		var input = document.createElement("INPUT");	//input elements for the upper part of the dropdown
		var input2 = document.createElement("INPUT");
   
		//apply classes to the container and the option list
		$(container).addClass(settings.containerClass);	
		$(optionList).addClass(settings.optionListClass);	
   
		//hide the original <select> element
		oldSelector.hide();
   
		//set input type to submit or text, depending on the mode
		if (settings.mode == "text") {
			$(input).attr("type","text");
			$(input).attr("readonly","readonly");
			$(input).addClass(settings.selectionClass );
		}
		else {
			$(input).attr("type","submit");
			$(input).addClass(settings.selectionButtonClass );
			//attach optional submit event
			if (settings.submitCallback != null)
			    //$(input).click(settings.submitCallback);
			    $("#ActiveSearch").submit(function(){
			        return settings.submitCallback()
                });
		}
   		
		//set id and selected value
		$(input).attr("id","selection"+oldSelector.attr("id"));
		$(input).val(oldSelector[0].options[oldSelector[0].selectedIndex].text);
   
   		//set attributes for the dropdown button
   		$(input2).attr("type","button");	
		$(input2).addClass(settings.buttonClass);
		$(input2).attr("id","button"+oldSelector.attr("id"));
   		
		//append both input elements to the container
		$(container).append(input);
		$(container).append(input2);
   
   
		//create the option list
		for(var i=0;i<oldSelector[0].options.length;i++){
			option = document.createElement("LI");
			$(option).attr("rel",oldSelector[0].options[i].value);
			$(option).html(oldSelector[0].options[i].text);
			if(i==0)
				$(option).addClass(settings.optionFirstClass);		//apply class for first option element
			if(i==oldSelector[0].options.length-1)
				$(option).addClass(settings.optionLastClass);		//apply class for last option element
			if($(option).attr("rel")==oldSelector.val())
				$(option).addClass(settings.optionSelectedClass);	//apply class for selected option element
			optionList.appendChild(option);
		}
   
   		//append list to container, append container after the original select element
		$(container).append(optionList);	
		$(oldSelector).after(container);
		//insert a hidden input with the same name as the original <select> so the parameter will be passed on submit
		$(container).after("<input type=\"hidden\" class=\"Hidden\" id=\"hidden"+oldSelector[0].id+"\" name=\""+oldSelector[0].name+"\" value=\""+oldSelector.val()+"\" />");
   
  
   		//set click behaviour for option elements
		$("li", optionList).click(function(){
			var $this = $(this);
			
			$this.parent().slideToggle("fast", function(){ //toggle slide in/out
			    $("#button"+oldSelector.attr("id")).toggleClass(settings.buttonClassActive);		//toggle class for active/passive upper dropdown element1
			    $("#selection"+oldSelector.attr("id")).toggleClass(settings.selectionClassActive);	//toggle class for active/passive upper dropdown element2
			});		
			
			$("#selection"+oldSelector.attr("id")).val($this.html());	//set selected value in the upper dropdown element
			$("#hidden"+oldSelector[0].id).val($this.attr("rel"));	//set selected value in hidden input field
			
			$this.siblings("li").removeClass(settings.optionSelectedClass);	//remove selected class for all other option elements
			$this.addClass(settings.optionSelectedClass);	//toggle class for selected option element
            
            if(options.selectCallback!=null){
                var arguments = [{text: $this.html(), value: $this.attr("rel")},$this.parent()];
                options.selectCallback.apply(this, arguments);
            }
            
			return false;
		});
   
		//click behaviour for first selection element (textmode only)
		if (settings.mode == "text") {
			$("#selection"+oldSelector.attr("id")).click(function(){  		
				var $this = $(this);
							
				return buttonClick($("#button"+oldSelector.attr("id")), $this);
			});
		}
   
		//click behaviour for second selection element(all modes)
		$("#button"+oldSelector.attr("id")).click(function(){
			var $this = $(this);
			
			return buttonClick($this, $("#selection"+oldSelector.attr("id")));
		});
		
		
     	
		//if there are more list elements than configured to be visible:
		//	- add some pixels to the widht, so there is space for a scrollbar
		//	- set the height of the <ul> to a fixed value
		//	- set overflow to auto		
		if(settings.numberOfVisibleEntries > 0 && settings.numberOfVisibleEntries < $(optionList).children("li").length) {
			$(optionList).width(settings.listElementWidth + 20);
			$(optionList).height(settings.listElementHeight * settings.numberOfVisibleEntries);
			$(optionList).css("overflow", "auto");
		}
		
		//remove the original <select> element
		oldSelector.remove();	
	  }); 
	}
	
	//private method for the button click events
	function buttonClick(button, selection) {
		
		if (button.nextAll("ul").is(':hidden')) {
		    //set both buttons active
	        button.toggleClass(settings.buttonClassActive);
	        selection.toggleClass(settings.selectionClassActive);
	        
		    //show the list
		    button.nextAll("ul").slideToggle("fast");			
		    
		}
		else {
		    //hide the list
		    button.nextAll("ul").slideToggle("fast", function() {
		        //set both buttons passive
	            button.toggleClass(settings.buttonClassActive);
	            selection.toggleClass(settings.selectionClassActive);
		    });			
		}
		return false;
	}

// end of closure
})(jQuery);




