/**
 * @author jan
 */

( function($){
  
/*
 * 
 * Vb: $("select").amaiSelect();
 * parameters: 
 * 		transitionTime (Tijd voor openschuiven) - optioneel - standaard 500 ms
 * 		maxHeight (maximum hoogte van de select)
 * 		selectClass (De klasse die gebruikt wordt voor de custom select boxes / handig als je twee verschillende stijlen selects wil op een site) - optioneel - standaard "select"
 * css:
 * .select: container
 * 		-> wanneer opengeklapt krijgt hij klasse .selectOpen
 * .selectBox: container voor tekstveld en pijltje
 * .selectArrow: pijltje
 * .selectInput: tekstveld
 * 		-> hierin zit ook nog een span voor extra fancy stuff, en evt overflow problemen
 * .select ul: lijst
 * 
 * Dependencies:
 * 		jQuery.timer http://plugins.jquery.com/files/jquery.timer.js_0.txt
 * 
 */

var globalList;

$.fn.amaiSelect = function(transitionTime, maxHeight, selectClass, wrapList){
	if(selectClass == undefined){
		selectClass = "select";
	}
	
	if(maxHeight == undefined){
		maxHeight = 0;
	}
	
	if(transitionTime == undefined){
		transitionTime = 500;
	}
	
	this.each(function(){
		/* SETTING SELECT ELEMENT TO WORK WITH */
		var select = $(this);
		select.hide();
		
		/* MAKING HTML REPLACEMENT */
		var container = $("<div></div>").addClass(selectClass);
		var box = $("<div></div>").addClass("selectBox");
		var input = $("<div></div>").addClass("selectInput").html("<span></span>");
		var arrow = $("<div style=\"cursor:pointer;\"></div>").addClass("selectArrow");
		box.append(input);
		box.append(arrow);
		var list = $("<ul></ul>").css({"overflow":"hidden"});
		if(maxHeight != 0){
			list.css({"max-height": maxHeight + "px"});
		}
		container.append(box);
		container.append(list);
		
		/* SOME FUNCTIONS */
		var closeList = function(){
			list.slideUp(transitionTime);
			box.removeClass("selectOpen");
		}
		
		var openList = function(){
			list.children(":first").css("margin-top", "0px");
			list.slideDown(transitionTime, function(){
				var elemHeight = 0;
				list.children().each(function(){
					elemHeight += $(this).outerHeight();
				});
				if(elemHeight > maxHeight){
					needsTweening = true;
				} else {
					needsTweening = false;
				}
			});
			box.addClass("selectOpen");
		}
		
		var changedItem = function(e){
			e.stopPropagation();
			select.val($(this).attr("rel"));
			closeList();
			updateList();
			select.trigger("change");
		}
		
		var tmr;
		var goTop = true;
		var first = true;
		var needsTweening = false;
		
		var moveList = function(){
			if (goTop) {
				var calc = (parseInt(list.children(":first").css("margin-top").replace("px", "")) + 2);
				if(calc > 0){
					calc = 0
				}
				list.children(":first").css("margin-top", calc + "px");
			} else {
				var elemHeight = 0;
				list.children().each(function(){
					elemHeight += $(this).outerHeight();
				});
				elemHeight -= maxHeight;
				var calc = (parseInt(list.children(":first").css("margin-top").replace("px", "")) - 2);
				if(calc < -elemHeight){
					calc = -elemHeight;
				}
				list.children(":first").css("margin-top", calc + "px");
			}
		}
		
		var mouseMoved = function(e){
			
			if(needsTweening){
				if(e.pageY - list.offset().top < 40){
					if(goTop != true || first == true){
						first = false;
						if(tmr != undefined){
							tmr.stop();
						}
						goTop = true;
						tmr = $.timer(10, function(timer){moveList()});
					}
				} else if (e.pageY - list.offset().top > maxHeight + parseInt(list.css("padding-top").replace()) + parseInt(list.css("padding-bottom").replace()) - 40){
					if(goTop != false || first == true){
						first = false;
						if(tmr != undefined){
							tmr.stop();
						}
						goTop = false;
						tmr = $.timer(10, function(timer){moveList()});
					}
				} else {
					if(tmr != undefined){
						tmr.stop();
						first = true;
					}
				}
			}
		}
		
		var mouseOut = function(e){
			if(tmr != undefined){
				tmr.stop();
				first = true;
			}
		}
		
		/* UPDATES THE LIST OF THE DDL REPLACEMENT */
		var updateList = function(){
			list.find("li li").unbind();
			list.find("li").unbind();
			list.html("");
			var isGrouped = false;
			select.children().each(function(){
				if($(this).is("option")){
					var selected = "";
					if($(this).val() == select.val()){
						selected = " selected";
						input.children("span").html($(this).text());
					}
					var extraClasses = "";
					if($(this).attr("class") != ""){
						extraClasses += " " + $(this).attr("class");
					}
					if($(this).attr("disabled")){
						extraClasses += " " + "disabled";
					}
					list.append("<li class=\"option"+selected+extraClasses+"\" rel=\""+$(this).val()+"\" style=\"cursor:pointer;\">"+$(this).text()+"</li>");
					
				} else {
					var html = "<li class=\"optgroup\" style=\"cursor:default;position:relative;\"><span>" + $(this).attr("label") + "</span><ul>";
					$(this).children().each(function(){
						var selected = "";
						if($(this).val() == select.val()){
							selected = " selected";
							input.children("span").html($(this).text());
						}
						var extraClasses = "";
						if($(this).attr("class") != ""){
							extraClasses += " " + $(this).attr("class");
						}
						if($(this).attr("disabled")){
							extraClasses += " " + "disabled";
						}
						html += "<li class=\"option"+selected+extraClasses+"\" rel=\""+$(this).val()+"\" style=\"cursor:pointer;\">"+$(this).text()+"</li>";
					});
					html += "</ul></li>";
					list.append(html);
					isGrouped = true;
				}
			});
			if(!isGrouped){
				list.find("li").each(function(){
					if(!$(this).hasClass("disabled")){
						$(this).bind("click", changedItem);
					} else {
						$(this).css("cursor", "default");
					}
				})
			} else {
				list.find("li li").each(function(){
					if(!$(this).hasClass("disabled")){
						$(this).bind("click", changedItem);
					} else {
						$(this).css("cursor", "default");
					}
				})
			}
			
		}
		
		/* EVENT CALLBACKS */
		select.change(function(){
			updateList();
		});
		
		select.bind("optionsChanged", function(){
			updateList();
		});
		
		box.click(function(e){
			$(document).click();
			e.stopPropagation();
			if(!list.is(":hidden")){
				closeList();
			} else {
				openList();
			}
		});
		
		if(maxHeight>0){
			list.bind("mousemove", mouseMoved);
			list.hover(function(){}, mouseOut);
		}
		
		$(document).click(function(){
			if(!list.is(":hidden")){
				closeList();
			}
		});
		
		var hasItem = false;
		$(document).keyup(function(e){
			hasItem = false;
			if(!list.is(":hidden")){
				if(e.keyCode < 91 && e.keyCode > 64){
					list.find("li").each(function(){
						if($(this).text().substring(0, 1).toLowerCase() == String.fromCharCode(e.keyCode).toLowerCase()){
							if(!hasItem){
								list.children(":first").css("margin-top", "-" + ($(this).position().top - parseInt(list.children(":first").css("margin-top").replace("px", ""))) + "px");
								hasItem = true;
							}
						}
					});
				}
			}
		});
		
		$("." + selectClass + " .selectBox").live("click", function(){
			if(!list.is(":hidden")){
				closeList();
			}
		});
		
		/* INIT */
		updateList();
		
		list.hide();
		
		if(select.next().hasClass(selectClass)){
			select.next().remove();
		}
		
		select.after(container);
		
		return this;
	});
}

	


/*
 * 
 * Vb. $("input[type=radio]").amaiRadio();
 * parameters
 * 		radioClass (Klasse die gebruikt wordt voor de radio button) - optioneel - standaard "radio"
 * css:
 * 		.radio (klasse voor de radiobutton)
 * 		.radioChecked (klasse voor de radiobutton wanneer gechecked)
 * 
 */


$.fn.amaiRadio = function(radioClass, useClassAsId){
	if(radioClass == undefined){
		radioClass = "radio";
	}
	
	if(useClassAsId == undefined){
		useClassAsId = false;
	}
	
	this.each(function(){
	
		var radio = $(this);
		
		var customRadio = $("<a href=\"#\"></a>");
		
		if(!useClassAsId){
			customRadio.addClass(radioClass);
		} else {
			customRadio.attr("id", radioClass);
		}
		
		var updateCustomRadio = function(){
			$("input[name='" + radio.attr("name") + "']").next().removeClass("radioChecked");
			if($(this).is(":checked")){
				$(this).next().addClass("radioChecked");
			} else {
				$(this).next().removeClass("radioChecked");
			}
		}
		
		var updateRadio = function(){
			//radio.attr("checked", "checked");
			$("input[name='" + radio.attr("name") + "']").next().removeClass("radioChecked");
			radio.click();
			customRadio.addClass("radioChecked");
			radio.trigger("change");
			return false;
		}
	
		$("input[name='" + radio.attr("name") + "']").change(updateCustomRadio);
		customRadio.click(updateRadio);
		
		if(radio.is(":checked")){
			customRadio.addClass("radioChecked");
		}
		
		radio.hide();
		
		if(radio.next().hasClass(radioClass) || radio.next().attr("id") == radioClass){
			radio.next().remove();
		}
		
		radio.after(customRadio);
		
		return this;
	});
}

/*
 * 
 * Vb. $("input[type=checkbox]").amaiCheck();
 * parameters
 * 		checkClass (Klasse die gebruikt wordt voor de checkbox button) - optioneel - standaard "check"
 * css:
 * 		.check (klasse voor de checkbox)
 * 		.checkChecked (klasse voor de checkbox wanneer gechecked)
 * 
 */

$.fn.amaiCheck = function(checkClass){
	if(checkClass == undefined){
		checkClass = "check";
	}
	
	this.each(function(){
	
		var check = $(this);
		
		var customCheck = $("<a href=\"#\"></a>").addClass(checkClass);
		
		var updateCustomCheck = function(){
			if($(check).is(":checked")){
				$(check).next().addClass("checkChecked");
			} else {
				$(check).next().removeClass("checkChecked");
			}
		}
		
		var updateCheck = function(){
			check.click();
			updateCustomCheck();
			check.trigger("change");
			return false;
		}
	
		$(check).change(updateCustomCheck);
		customCheck.click(updateCheck);
		
		if(check.is(":checked")){
			customCheck.addClass("checkChecked");
		}
		
		check.hide();
		
		if(check.next().hasClass(checkClass)){
			check.next().remove();
		}
		
		check.after(customCheck);
	
		return this;
	});
}

/*
*
* usage: $().amaiFile();
*
* creates a div for the button and a div for the input field
* The original <input type="file"> tag is placed inside the button div with an opacity of 0
* this makes the file dialog open when the button is clicked.
* 
* When a file is selected, filename is shown in the input div 
*
* Firefox and Opera don't support to change the css cursor property
* 
* tested in:
* - Firefox 3.6
* - Chrome 7.0
* - Opera 10
* - Safari 5.0
* - IE 8.0
* 
* Most browsers don't support to trigger the click event using javascript on an <input type="file"> element
* 
*
* css:
*     .file: wrapper
*     .fileButton: button element
*     .fileInput: input element
*
*/

$.fn.amaiFile = function() {
    
    if ( ! this.hasClass('amaiFile'))
    {
      var file = this.addClass('amaiFile');
      var label = $('label[for='+file.attr('id')+']');
      var container = $('<div></div>').addClass('file');
      var button = $('<div></div>').addClass('fileButton').css( { position: 'relative',
                                                                  cursor: 'pointer' } );
      var input = $('<div></div>').addClass('fileInput');
      
      file.after(container);    
      container.append(button).append(input);
      button.append(file);
      
      file.css( { position: 'absolute',
                  top: 0,
                  left: 0,
                  opacity: 0,
                  width: '100%',
                  height: '100%',
                  border: 0,
                  margin: 0,
                  padding: 0,
                  cursor: 'pointer' } );
      
      if (label.length!=0)
      {
        input.text( label.text() );
      }
      
      file.change( function() {
        var filename = $(this).val();
        var filenameA = filename.split('\\');
        
        if (filenameA.length==1)
        {      
          input.text( filename );
        }
        else
        {
          input.text( filenameA[filenameA.length-1] );
        }
      } );
    }
    return this;
  }

} )( jQuery );
