/**
 * Permet de transformer un select en comboBox
 * @author JB
 * @version 1.5
 */
var ComboBox = function(el, config){
	var select = $(el);
	var _largeurScroll = 0;
    if (select.attr('tagName').toLowerCase() != 'select') 
        return;
    
    var selectedIndex = select.attr('selectedIndex'),
		selectId = select.attr('id')+Math.random(10).toString().replace('.',''),
		_newSelect = '<input type="hidden" class="'+select.attr('class')+' comboBoxHidden" id="' +select.attr('id') +'" name="' + select.attr('name') + '" value="' + select[0][selectedIndex].value + '" />' +
    '<span class="comboBox" id="'+selectId+'"><input type="text" readonly="readonly" value="'+ select[0][selectedIndex].text +'"/><span class="comboBoxSelect">&nbsp;</span></span>' +
    '<ul class="comboBoxList" style="position:absolute;padding:0;margin:0;">';
    var x = 0,
		vals = {},
		currentSelected=0,
		_class='',
		maxItems = select.children().length - 1;
    select.children().each(function(i, child){
        if (child.tagName.toLowerCase() == 'optgroup') {
            _newSelect += '<li><span class="comboBoxParent">' + child.label + '</span>';
            _newSelect += '<ul>';
            $(child).children().each(function(_i, _child){
				_class='';
				if(x == selectedIndex){
					_class = 'current';
					currentSelected = x;
				}
                _newSelect += '<li id="'+selectId+'-'+x+'" class="comboBoxChild ' + _class + ((x % 2) == 1 ? ' alt' : '') + '"><a href="#' + _child.value + '">' + _child.text + '</a></li>';
               	vals[x] = _child.text;
			    x++;
            })
            _newSelect += '</ul></li>';
        }
        else {
			_class='';
			if(x == selectedIndex){
				_class = 'current';
				currentSelected = x;
			}
            _newSelect += '<li id="'+selectId+'-'+x+'" class="comboBoxChild ' + _class  + ((x % 2) == 1 ? ' alt' : '') + '"><a href="#' + child.value + '">' + child.text + '</a></li>';
			vals[x] = child.text;
            x++;
        }
    })
    
    _newSelect += '</ul>';
    
    $(_newSelect).insertAfter(select);
    select.remove();
	
    var newSelect = $('#' + selectId),
		newSelectInput = $($(newSelect).children()[0]),
		list = newSelect.next(),
   	 	inputHidden = newSelect.prev();
		
	list.hide();
	
    newSelect.click(function(e){
		e.preventDefault();
		if (!list.hasClass('visible')) {
			setTimeout(function(){
				newSelect.addClass('comboBoxOpened');
				list.toggleClass('visible');
				list.show();
				var newSelectBottom = parseInt(newSelect.position().top + newSelect.height() +
						parseInt(newSelect.css('padding-top'), 10) +
						parseInt(newSelect.css('padding-bottom'), 10) +
						parseInt(newSelect.css('border-top-width'), 10),10) ,
					
					newSelectTop = parseInt(newSelect.position().top,10) + parseInt(newSelect.css('margin-top'), 10) ,
					newSelectLeft = parseInt(newSelect.position().left,10),
				
					listWidth = newSelect.width(), //Largeur du select + 28px pour la scrollbar 
					
					windowTop = parseInt($(document).scrollTop(),10),
					windowBottom = parseInt($(window).height() + windowTop,10),

					//On calcule la distance entre le select et le bas de la fenêtre
					hauteurInf = windowBottom - newSelectBottom,
					//On calcule la distance entre le select et le haut de la fenêtre
					hauteurSup = parseInt(newSelectTop - windowTop),
					
					affDessous = true;
					
				//On reinitialise la hauteur de la ComboboxList pour voir si sa hauteur réelle la ferait dépasser de la fenêtre
				list.css('height', 'auto');
				list.css('margin-left', newSelect.css('margin-left'));
				list.css('width', listWidth+'px'); //largeur de la liste
				
				
				if((parseInt(list.height(),10) + newSelectBottom) > windowBottom){
					
					if(hauteurSup > hauteurInf){ //On l'affiche au dessus
						affDessous = false;
					}
				}
				var left = newSelectLeft+'px';
				var listHeight = list.height();
				if (affDessous) {//dessous 
					listHeight = hauteurInf > listHeight? listHeight : hauteurInf - 10;
					list.css({
						'left':left,
						'top': (newSelectTop + newSelect.height()+2) + 'px',
						'height': listHeight+'px',
						'overflow': 'auto',
						'border-bottom': '1px solid',
						'border-top': 'none',
						'margin-top': '-'+newSelect.css('margin-bottom')
					});
					
					if($.browser.msie && parseInt($.browser.version) < 8){
						list.css('top',(newSelectTop + 30)+'px');
					}
				}
				else {//dessus
					listHeight = hauteurSup > listHeight? listHeight : hauteurSup - 10;
					list.css({
						'left':left,
						'top': (newSelectTop - listHeight) + 'px',
						'height': listHeight + 'px',
						'overflow': 'auto',
						'border-top': '1px solid',
						'border-bottom': 'none',
						'margin-bottom':'0'
					});
					if($.browser.msie && parseInt($.browser.version) < 8){
						list.css('top',(newSelectTop - listHeight)+'px');
					}
				}
				
				if(newSelectLeft != parseInt(list.position().left,10)){
					list.css('left','auto');
				}
				
				if($.browser.msie && parseInt($.browser.version) < 8){
					list.css('left',newSelectLeft+'px');
				}
			}, 1);
		}
    });
	
	var selectMe = function(li){
		var li = $(li);
		currentSelected = parseInt(li.attr('id').split('-')[1],10);
		list.find('.current').removeClass('current');
		var a = $(li.children()[0]);
        li.addClass('current');
        inputHidden.val(a.attr('href').split('#')[1]);
        newSelectInput.val(a.html().replace('&nbsp;',' '));
        list.hide();
		inputHidden.trigger("change");
		list.toggleClass('visible');
	}
    
	var word='',
		timeout1,
		timeout2;
		
    newSelect.keydown(function(e){
		var _char = e.keyCode || e.charCode;
		if (_char != 9) { //tab
			e.preventDefault();
		}
		if(_char == 38 && currentSelected == 0 || _char == 40 && currentSelected == maxItems){
			return ;
		}
		if(_char == 40){
			selectMe('#'+selectId+'-'+(currentSelected+1));
			return;
		}
		if(_char == 38){
			selectMe('#'+selectId+'-'+(currentSelected-1));
			return;
		}
		
		clearTimeout(timeout1);
		clearTimeout(timeout2);
		word+=String.fromCharCode(_char);
		timeout1 = setTimeout(function(){
			for(var i in vals){
				var v = vals[i];
				if (v.substr(0,word.length).toLowerCase() == word.toLowerCase()) {
					selectMe('#'+selectId+'-'+i);
					clearTimeout(timeout1);
					break;
	            }
			}
		},300);
		timeout2 = setTimeout(function(){
			word='';
		},1000);
		
    });
	
	
    list.find('li').click(function(e){
        e.preventDefault();
		e.stopPropagation();
        selectMe(this);
    });
	
	
    list.find('.comboBoxChild').hover(function(e){
        $(this).addClass('comboBoxChildHover');
    },function(){
		$(this).removeClass('comboBoxChildHover');
	});
    
    $(document).click(function(){
        list.hide();
		list.removeClass('visible');
		newSelect.removeClass('comboBoxOpened');
    });
}

jQuery.fn.extend({
    comboBox: function(){
		this.each(function(i,el){
			ComboBox(el);
		})
		return this;
    },
    
    comboBoxVal: function(){
		if(this.hasClass('comboBox'))
        	return this.prev().val();
    },
    
    comboBoxHtml: function(){
		if(this.hasClass('comboBox'))
      		return this.val();
    }
    
});
