/**
 * @author Ludovic Tarit
 * 
 * Options disponibles:
 * - hideonchoose: boolean (true)		dès qu'un item est sélectionné, la liste déroulante disparaît
 * - toggleElement: boolean (true) 		change la visibilité de la liste si l'on clique sur l'élément déclencheur
 * - enableKeyboard: boolean (true)		la liste déroulante est navigable au clavier:
 * - onEvent (click)					Evénement déclenchant l'ouverture de la liste
 * 		-> flèches bas, haut: sélectionne l'élément suivant et précédent de la liste de manière cyclique, et déclenche
 * 		   l'événement onselect
 * 		-> flèches droite, entrée: chosit l'item et déclenche l'évènement onchoose
 * - onchoose: function					fonction appellée lorsqu'un item est choisi (this fait référence à l'item chosi)
 * - onselect: function					fonction appellée lorsqu'un item est sélectionné (this fait référence à l'item sélectionné)
 * @return DropDownList
 */
(function($) {
	$.fn.DropDownList = function(settings) {
		var config = {};
		settings = $.extend(true,config,settings);
		
		var plugin = new DropDownList(this,settings);
		plugin.init();
		return plugin;
	};
	
	$.DropDownList = function(elem,settings) {
		return $(elem).DropDownList(settings);
	};
	
	DropDownList = function(e,settings)
	{
		settings.hideonchoose 	= settings.hideonchoose == undefined ? true : settings.hideonchoose;
		settings.toggleElement 	= settings.toggleElement == undefined ? true : settings.toggleElement;
		settings.enableKeyboard	= settings.enableKeyboard == undefined ? true : settings.enableKeyboard;
		settings.onselect 		= settings.onselect || {};
		settings.onchoose 		= settings.onchoose || {};
		settings.position		= settings.position || 'left';
		settings.offset			= settings.offset || { top: 0, left: 0 };
		settings.openOnEvent	= settings.openOnEvent || 'click';
		settings.closeOnEvent	= settings.closeOnEvent || 'click';
		
		this.settings = settings;
		
		this.e 				= e;
		this.list 			= settings.list;
		this.items 			= this.list.children("li");
		this.currentItem 	= null;
		this.closed 		= true;
	};
	
	DropDownList.prototype.init = function()
	{
		this.close();
		this.bindEvents();
	};
	
	DropDownList.prototype.bindMouseEvents = function()
	{
		var that = this;
		(this.e).bind( this.settings.openOnEvent, function(e) {
			if( that.settings.toggleElement == true ) {
				that.toggleList();
			} else {
				that.openList();
			}
		} );
		
		this.items.mouseover( function(e) {
			that.selectItem(this,e);
			e.stopPropagation();
		} );
		
		this.items.click( function(e) {
			that.chooseItem(this,e);
		} );
		
		$(document).bind( this.settings.closeOnEvent, function(e) {
			if( $(e.target).attr('id') != (that.e.attr('id')) 
					
			) {
				that.close();
			}
		} );
	};
	
	DropDownList.prototype.bindKeyboardEvents = function()
	{
		var that = this;
		$(document).keydown( function(e) {
			if( !that.isClosed() ) {
				switch( e.which ) {
				case 40:
					e.preventDefault();
					var item = that.getNextItem();
					that.selectItem(item,e);
					break;
				case 38:
					e.preventDefault();
					var item = that.getPrevItem();
					that.selectItem(item,e);
					break;
				case 39:
				case 13:
					if( that.currentItem != 0 ) {
						var item = that.getCurrentItem();
						that.chooseItem(item,e);
					}
					break;
				}
			}
		} );
	};
	
	DropDownList.prototype.bindEvents = function()
	{
		this.bindMouseEvents();
		
		if( this.settings.enableKeyboard == true ) {
			this.bindKeyboardEvents();
		}
	};
	
	DropDownList.prototype.openList = function()
	{
		if( this.getNbItems() > 0 ) {
			this.settings.list.show();
			this.closed = false;
		}
	};
	
	DropDownList.prototype.toggleList = function()
	{
		if( this.getNbItems() > 0 ) {
			this.settings.list.toggle();
			this.closed = !this.closed;
		}
	};
	
	DropDownList.prototype.hideList = function()
	{
		this.list.hide();
		this.list.children("li").removeClass('selected');
	};
	
	DropDownList.prototype.getNbItems = function()
	{
		return this.items.length;
	};
	
	DropDownList.prototype.getPrevItem = function()
	{
		return (this.currentItem-1 <= 0 ? this.items[this.getNbItems()-1] : this.items[this.currentItem-2]);
	};
	
	DropDownList.prototype.getCurrentItem = function()
	{
		return this.items[this.currentItem-1];
	};
	
	DropDownList.prototype.getNextItem = function()
	{
		return this.items[this.currentItem % (this.getNbItems())];
	};
	
	
	DropDownList.prototype.selectItem = function(item,event)
	{
		this.currentItem = $(item).prevAll().length + 1;
		this.list.children("li").removeClass('selected');
		$(item).addClass('selected');
		
		var f = this.settings.onselect;
		if( $.isFunction(f) ) {
			f.apply(item,[{curentItem: this.currentItem,event:event}]);
		}
	};
	
	DropDownList.prototype.chooseItem = function(item,event)
	{
		var f = this.settings.onchoose;
		if( $.isFunction(f) ) {
			f.apply(item,[{curentItem: this.currentItem,event:event}]);
		}
		
		if( this.settings.hideonchoose == false ) {
			event.stopPropagation();
		} else {
			this.close();
		}
	};
	
	DropDownList.prototype.isClosed = function()
	{
		return this.closed;
	};
	
	DropDownList.prototype.close = function()
	{
		this.hideList();
		this.currentItem = 0;
		this.closed = true;
	};
	
	DropDownList.prototype.update = function()
	{
		this.items = this.list.children("li");
		this.currentItem = 0;
		this.bindMouseEvents();
		this.openList();
	};
	
} )(jQuery);






















