/**
 * skinnablecontrols.js
 * 
 * Add support for entirely customizable and accessible versions of standard form controls, and some new controls 
 * 
 * @version 1.0
 * @copyright 2008
 * @author Mickael Marchal http://www.lesitedemika.org
 *
 */

/**
 * skinnable text field with watermarking
 */
function SkinnableWatermarkedField(fieldId) {
	
    this.fieldId = fieldId;	
	this.watermark = "";
	
	/**
	 * Initialize the skinnableCheckbox element
	 */
	this.create = function () {
		
		var instance = this;
		
		this.watermark = $("#"+this.fieldId).val();
		
		$("#"+this.fieldId).focus(function() {
			if($(this).val() == instance.watermark) {
				$(this).val("");
			}
		});
		
		$("#"+this.fieldId).blur(function() {
			if($(this).val() == "") {
				$(this).val(instance.watermark);
			}
		});
	};
}

/**
 * skinnable replacement for checkboxes
 */
function SkinnableCheckbox(checkboxId) {
	
    this.checkboxId = checkboxId;
	this.skinnableCheckboxId = 'skcb_'+this.checkboxId;
	
	this.imagePath = "/img/";
	this.imageChecked = "skinnablecheckbox_checked.gif";
	this.imageUnchecked = "skinnablecheckbox_unchecked.gif";
	
	/**
	 * Refresh the skinnableCheckbox with the original checkbox value
	 */
	this.refresh = function() {
		if ($("#"+this.checkboxId).attr("checked")) {
			$("#"+this.skinnableCheckboxId).removeClass("unchecked");
			$("#"+this.skinnableCheckboxId).addClass("checked");
			$("#"+this.skinnableCheckboxId).attr("src", this.imagePath+this.imageChecked);
		} else {
			$("#"+this.skinnableCheckboxId).removeClass("checked");
			$("#"+this.skinnableCheckboxId).addClass("unchecked");
			$("#"+this.skinnableCheckboxId).attr("src", this.imagePath+this.imageUnchecked);
		}
	};
	
	
	/**
	 * Initialize the skinnableCheckbox element
	 */
	this.create = function () {
		
		var instance = this;
		$("#"+this.checkboxId).after('<img id="'+this.skinnableCheckboxId+'" class="skinnableCheckbox" src="'+this.imagePath+this.imageChecked+'" />');
		$("#"+this.checkboxId).bind("click", function () {
			instance.refresh();
		});
		
		$("#"+this.skinnableCheckboxId).click(function () {
			
			$("#"+instance.checkboxId).attr("checked", ! $("#"+instance.checkboxId).attr("checked"));	    
			instance.refresh();
			$("#"+instance.checkboxId).change();
			
		});
		
		this.refresh();
		
        $("#"+this.checkboxId).hide();
	};
}

/**
 * skinnable replacement for radio buttons
 */
function SkinnableRadio(radioIds) {
	
    this.radioIds = radioIds;
	this.skinnableRadioIds = new Array();
	
	for(var i=0; i < this.radioIds.length; i++) {
	    this.skinnableRadioIds[i] = 'skr_'+this.radioIds[i];
    }
	
	this.imagePath = "/img/";
	this.imageChecked = "skinnableradio_checked.gif";
	this.imageUnchecked = "skinnableradio_unchecked.gif";
	
	/**
	 * Refresh the skinnableRadios with the original checkbox value
	 */
	this.refresh = function() {
		
		for(var i=0; i < this.radioIds.length; i++) {
		    
			if($("#"+this.radioIds[i])) {
		  	    
				if($("#"+this.radioIds[i]).attr("checked")) {
					
					$("#"+this.skinnableRadioIds[i]).removeClass("unchecked");
					$("#"+this.skinnableRadioIds[i]).addClass("checked");
					$("#"+this.skinnableRadioIds[i]).attr("src", this.imagePath+this.imageChecked); 	    
					
			    } else {
					
					$("#"+this.skinnableRadioIds[i]).removeClass("checked");
					$("#"+this.skinnableRadioIds[i]).addClass("unchecked");
					$("#"+this.skinnableRadioIds[i]).attr("src", this.imagePath+this.imageUnchecked);
			
			    }
		    }	
		}
	};
	
	
	/**
	 * Initialize the skinnableCheckbox element
	 */
	this.create = function (containerId) {
		
		var instance = this;
		
		for(var i=0; i < this.radioIds.length; i++) {
			
			$("#"+this.radioIds[i]).after('<img id="'+this.skinnableRadioIds[i]+'" class="skinnableRadio" src="'+this.imagePath+this.imageChecked+'" />');
			$("#"+this.radioIds[i]).bind("click", function () {
				instance.refresh();
			});
			
			$("#"+this.skinnableRadioIds[i]).click(function () {
				
				var skRadioId = $(this).attr("id");
				var radioId = skRadioId.substring(4);
				$("#"+radioId).attr("checked", true);
				$("#"+radioId).change();	    
				instance.refresh();
			});
			$("#"+this.radioIds[i]).hide();
		}
		this.refresh();
		
	};
}

/**
 * skinnable replacement for select fields
 */
function SkinnableSelect(selectId) {
	
	this.selectItems = new Array();
	this.hasReToggled = false;
	
    this.selectId = selectId;
	this.skinnableSelectId = 'sks_'+this.selectId;
	this.buildList = null;
	
	/**
	 * Open / close associated option list 
	 */
    this.toggleOptionList = function () {
		$("#"+this.skinnableSelectId+" > div").toggle();
        if(! this.hasReToggled && jQuery.browser.msie) {
			skMgr.toToggle = this;
			setTimeout('IEreToggle()', 10);
		}
		this.opened = ! this.opened;
	};
	
	/**
	 * Close associated option list
	 */
    this.closeOptionList = function () {
	    $("#"+this.skinnableSelectId+" > div").hide();
		this.opened = false;
    };

    /**
     * Open associated option list
     */
    this.openOptionList = function () {
        $("#"+this.skinnableSelectId+" > div").show();
		if(! this.hasReToggled && jQuery.browser.msie) {
            skMgr.toToggle = this;
            setTimeout('IEreToggle()', 10);
        }
		this.opened = true;
    };
	
	/**
	 * Build the list of items in the select element
	 * 
	 * structure : [{name:group1, items:[{value:val1.1, label:label1.1}, {value:val1.2, label:label1.2}]},
	 * 				{name:group2, items:[{value:val2.1, label:label2.1}, {value:val2.2, label:label2.2}]},
	 * 				{name:NULL,   items:[{value:val1, label:label1}, {value:val2, label:label2}]}
	 * 			   ]
	 */
	this.buildItemsList = function () {
	    
		var instance = this;

		//traite les options seules
		var group = {name : null, items: []};
		$("#"+this.selectId + " > option").each( function() {
			group.items.push({name: $(this).val(), value: $(this).text()});
		});
		instance.selectItems.push(group);
		
		//traite les optgroups
		$("#"+this.selectId + " optgroup").each( function() {
			var group = {name: $(this).attr("label"), items: []};
			$(this).find("option").each( function () {
				group.items.push({name: $(this).val(), value: $(this).text()});
			});
			instance.selectItems.push(group);
		});
	};
	
	/**
	 * Refresh the item list according to the original select list
	 */
	this.refresh = function() {
		this.closeOptionList();
		$("#"+this.skinnableSelectId).remove();
        this.selectItems = new Array();
		this.create();
	};
	
	/**
	 * Initialize the newSelect element
	 */
	this.create = function () {
		
		var instance = this;
			
		this.buildItemsList();
		$("#"+this.selectId).after('<div class="skinnableSelect" id="'+this.skinnableSelectId+'"><a href="#" class="sks_link">'+$("#"+this.selectId+" option:selected").text()+' </a><div></div></div>');

		$("#"+this.skinnableSelectId +" > div").hide();
		$("#"+this.selectId).hide();
		
		$("#"+this.skinnableSelectId +" > a").click(function() {
	        instance.clickFlag = true;
	        instance.toggleOptionList();
			return false;
	    });
		$("#"+this.skinnableSelectId +" > a").bind('click', function(e) {skMgr.manageSelectsClosing(e);});
		
		//build item list
		if(null !== this.buildList) {
			var html = this.buildList();
		} else {
			var html = '<ul>';
			for(group in this.selectItems) {
				if(null !== this.selectItems[group].name) {
					html += '<li>'+this.selectItems[group].name+'<ul>';
				}
				for(var item = 0; item < this.selectItems[group].items.length; item ++) {
					html += '<li><a href="#" name="'+this.selectItems[group].items[item].name+'" class="sks_element">'+this.selectItems[group].items[item].value+'</a></li>';
				}
				if(null !== this.selectItems[group].name) {
					html += '</ul></li>';
				}
			}
			html += '</ul>';
		}
		$("#"+this.skinnableSelectId +" > div").html(html);
		
		//register events
		$("#"+this.skinnableSelectId +" > div a").each(function() {
			$(this).click(function() {
				$("#"+instance.selectId).val($(this).attr("name"));
				$("#"+instance.skinnableSelectId+" > a").text($(this).text());
				$("#"+instance.selectId).change();
				instance.closeOptionList();
				return false;
			});
		});
		
		$("#"+this.selectId).change(function() {
				
				var text = document.getElementById(instance.selectId)[document.getElementById(instance.selectId).selectedIndex].firstChild.nodeValue;
				$("#"+instance.skinnableSelectId+" > a").text(text);
		});
	};
}
 
/**
 * skinnable field with AJAX autocomplete
 */
function SkinnableAutocompleteField(fieldId) {
	
    this.fieldId = fieldId;
	this.resultsId = "skar_"+fieldId;
	this.oldValue = "";
	this.watermark = "";
	this.popupIFrame = null;
	
	this.xhrUrl = ""; 	//Change this property to set the url where the results wil be fetched
	
	//override this method to change the value sent to the xhrUrl
	this.prepareParams = function () {
		return {'kw':this.oldValue};
	};
	
	/**
	 * Initialize the skinnableCheckbox element
	 */
	this.create = function () {
		
		var instance = this;
		
		this.oldValue = $("#"+this.fieldId).val();
		this.watermark = $("#"+this.fieldId).val();
		
		//IE only
		if(jQuery.browser.msie) {
			var str = '<br />';
		} else {
			var str = '';
		}
		
		$("#"+this.fieldId).after(str+'<div class="skinnableAutocompleteResults" id="'+this.resultsId+'"></div>');
		$("#"+this.resultsId).hide();
		
		$("#"+this.fieldId).focus(function() {
			if($(this).val() == instance.watermark) {
				$(this).val("");
			}
			skMgr.closeAllLists();
		});
		
		$("#"+this.fieldId).blur(function() {
			if($(this).val() == "") {
				$(this).val(instance.watermark);
			}
		});
		skMgr.lookForValueChange(this.fieldId);
	};
	
	/**
	 * Loop checking if the field value has changed during the last 200ms
	 */
	
	/**
	 * Fetch autcomplete items
	 */
	this.getAutocompleteResults = function() {
		var instance = this;
		$("#"+this.resultsId).show();
		$("#"+this.resultsId).css('z-index',2);
        $("#"+this.resultsId).html("<ul><li>Loading...</li></ul>");
		$("#"+this.resultsId).load(this.xhrUrl, this.prepareParams(), function() {
			instance.updateKeywordLinks();
		});
	};
	
	this.updateKeywordLinks = function() {
    	var instance = this;
		
		//IE6 fix
		/*if (jQuery.browser.msie && jQuery.browser.version <= "6.0")
        {
            var divPopup = document.getElementById(this.resultsId);
			
            //Increase default zIndex of div by 1, so that DIV appears before IFrame
            divPopup.style.zIndex=divPopup.style.zIndex+1;

            var iFrame = document.createElement("IFRAME");
		    iFrame.setAttribute("src", "");
		
		    //Match IFrame position with divPopup
		    iFrame.style.position="absolute";
		    iFrame.style.left =divPopup.offsetLeft + 'px';
		    iFrame.style.top =divPopup.offsetTop + 'px';
		    iFrame.style.width =divPopup.offsetWidth + 'px';
		    iFrame.style.height =divPopup.offsetHeight + 'px';
		
		    document.body.appendChild(iFrame);
		
		    //Store iFrame in global variable, so it can get removed when divPopup is hidden g_PopupIFrame=iFrame;
		    this.popupIFrame=iFrame;
			divPopup.style.visibility ="visible";

        }*/
		
		
		$("#"+this.resultsId+" a").bind('click', function () {
									 								 
			$("#"+instance.fieldId).val($(this).text());
			instance.closeOptionList();
			instance.oldValue = $("#"+instance.fieldId).val();
			return false;
		});
		
		if(document.getElementById('mode')) {
		    $("#skar_cities .kw_element").bind('click', function() {
                $("#mode").val(1);
            });
            $("#skar_countries .kw_element").bind('click', function() {
                $("#mode").val(2);
            });
		}
	};
	
	/**
	 * Close associated option list
	 */
    this.closeOptionList = function () {
	    $("#"+this.resultsId).empty();
		$("#"+this.resultsId).hide();
		if(this.popupIFrame) {
		  document.body.removeChild(this.popupIFrame);
          this.popupIFrame=null;
		}
    };
}
 
/**
 * Global handler for skinnable components
 * Use it to add skinnable components in a page
 */
function SkinnableControlsManager() {
	
	this.components = new Array();
	this.componentsIds = new Array();
	this.selectComponents = new Array();
	this.autocompleteComponents = new Array();
	this.autocompleteIds = new Array();
	this.registeredFields = new Array();
	this.registeredFieldsProperties = new Array();
	
	this.toToggle = null; //bug scrollabars IE : pour le re-togglage au bout de qq milisecondes
	
	/**
	 * Add a registered field to be converted in a skinnable field
	 */
	this.add = function (componentId, properties) {
		
		if(typeof componentId == "object") {
			var component = new SkinnableRadio(componentId);
		} else {

	        if(!document.getElementById(componentId)) {
	            return null;
	        }
					
			var tag = document.getElementById(componentId).tagName;
			
			if(tag.toUpperCase() == "SELECT") {
				if(jQuery.browser.msie == true && jQuery.browser.version == '6.0')
				    return null;
				
				var component = new SkinnableSelect(componentId, properties);
				this.selectComponents.push(this.components.length);
			}
			else if(tag.toUpperCase()  == "INPUT") {
				
				var type = $("#"+componentId).attr("type");
				
				if(type.toUpperCase() == "CHECKBOX") {
					var component = new SkinnableCheckbox(componentId);
				}	
				else if((type.toUpperCase() == "TEXT" || type.toUpperCase() == "PASSWORD") && $("#"+componentId).hasClass("watermarkedField")  ) {
					var component = new SkinnableWatermarkedField(componentId);
				} 
				else if(type.toUpperCase() == "TEXT" && $("#"+componentId).hasClass("autocompleteField")  ) {
					var component = new SkinnableAutocompleteField(componentId);
					this.autocompleteComponents.push(this.components.length);
					this.autocompleteIds.push(componentId);
				}				
			}
		}
		
		if(component) {
			if(properties) {
				if(properties.prepareParams) { component.prepareParams = properties.prepareParams; }
				if(properties.xhrUrl) { component.xhrUrl = properties.xhrUrl; }
				if(properties.imagePath) { component.imagePath = properties.imagePath; }
				if(properties.imageChecked) { component.imageChecked = properties.imageChecked; }
				if(properties.imageUnchecked) { component.imageUnchecked = properties.imageUnchecked; }
				if(properties.buildList) { component.buildList = properties.buildList; }
			}
			this.components.push(component);
			this.componentsIds.push(componentId);
			return component;
		} else {
			return null;	
		}		
	};
	
	/**
	 * Register a field to be added as a skinnable field 
	 */
	this.register = function (fieldId, properties) {
		this.registeredFields.push(fieldId);
		if(properties) { this.registeredFieldsProperties.push(properties); } else { this.registeredFieldsProperties.push({}); }
	};
	
	/**
	 * Register all skinnable elements in a form
	 * Also works with other tags (div etc)
	 * They MUST have an id attribute to be registered
	 * NOTE : groups of radio buttons must have the same root for their ids (ex : radio_gender_1, radio_gender_2)
	 * the root is the part of the id before the last underscore
	 */ 
	this.registerForm = function (formId) {
		
		var instance = this;
		
		var radioIds = new Array();
		var radioGroups = new Array();
		
		//radio buttons : try to detect groups of buttons (they must have the same root in their ids)
		$('#'+formId+" :radio").each( function () {
			
			if($(this).attr('id')) {
			    radioIds.push($(this).attr('id'));
			}
		});
		for(var i=0; i<radioIds.length; i++) {
			var pos = radioIds[i].lastIndexOf('_');
			var rootstr = radioIds[i].substring(0, pos);
			
			var found = false;
			for(var j=0; j < radioGroups.length; j++) {
				if(rootstr == radioGroups[j].root) {
					radioGroups[j].radios.push(radioIds[i]);
					found = true;
					break;
				}
			}
			if(! found) {
               radioGroups.push({root:rootstr, radios:[radioIds[i]]});
            }
		}
		
		for(var i=0; i < radioGroups.length; i++) {
			this.register(radioGroups[i].radios);
		}
		
		$("#"+formId+" select, #"+formId+" input, #"+formId+" textarea").each(function () {
			
			if($(this).attr('id')) {
				instance.register($(this).attr('id'));
			}
		});
	};
	
	/**
	 * Initialize all registered fields
	 */
	this.init = function() {
		
		for(var i=0; i < this.registeredFields.length; i++) {
			this.add(this.registeredFields[i], this.registeredFieldsProperties[i]);
		}
		for(var i=0; i < this.components.length; i++) {
			this.components[i].create();
		}
		$(document).bind('click', function(e) {skMgr.manageSelectsClosing(e);});
	};
	
	/**
	 * Get a skinnable component by its Id
	 */
	this.getById = function(id) {
		for(var i=0; i< this.componentsIds.length; i++) {
			if( this.componentsIds[i] == id) {
				return this.components[i];	
			}
		}
		return null;
	};
	
	
	/**
	 * Manage selects and autocomplete lists closing
	 */
	this.manageSelectsClosing = function(e) {
		
		var targ;
		if (!e) {
		  var e=window.event;
		}
		if (e.target) {
		  targ=e.target;
		}
		else if (e.srcElement) { 
		   targ=e.srcElement;
		}
		if (targ.nodeType==3) { // defeat Safari bug
		   targ = targ.parentNode;
		}
		
		if(targ.className == "sks_element" || targ.className == "sks_link") {
			
			//Gets the id of the clicked listbox
			if(targ.className == "sks_element") {
				var parent = targ.parentNode.parentNode.parentNode;
			} else {
				var parent = targ.parentNode;
			}
			
			//Close other boxes
			for(var i=0; i<this.selectComponents.length; i++) {
				if(this.components[this.selectComponents[i]].skinnableSelectId != parent.id) {
					this.components[this.selectComponents[i]].closeOptionList();
				}
			}
		} else {
			//No box was clicked : close all boxes
			for(var i=0; i<this.selectComponents.length; i++) {
				this.components[this.selectComponents[i]].closeOptionList();
			}
		}

		if(targ.className == "skar_link") {
			
			//Gets the id of the clicked listbox
			var parent = targ.parentNode.parentNode.parentNode;
			
			//Close other boxes
			for(var i=0; i<this.autocompleteComponents.length; i++) {
				if(this.components[this.autocompleteComponents[i]].resultsId != parent.id) {
					this.components[this.autocompleteComponents[i]].closeOptionList();
				}
			}
		} else {
			//No box was clicked : close all boxes
			for(var i=0; i<this.autocompleteComponents.length; i++) {
				this.components[this.autocompleteComponents[i]].closeOptionList();
			}
		}
	};
	
	/**
	 * Close all lists
	 */
	this.closeAllLists = function () {
        for(var i=0; i<this.selectComponents.length; i++) {
            this.components[this.selectComponents[i]].closeOptionList();
        }
        for(var i=0; i<this.autocompleteComponents.length; i++) {
            this.components[this.autocompleteComponents[i]].closeOptionList();
        }
	};
	
	
	/**
	 * Utility functions to handle autocomplete fields
	 */
	this.lookForValueChange = function(fieldId) {
		
		var autocomplete = null;
		//search for the component requested
		for(var i=0; i < this.autocompleteIds.length; i++) {
			if(this.autocompleteIds[i] == fieldId) {
				var autocomplete = this.components[this.autocompleteComponents[i]];
				break;
			}
		}
		
		if(autocomplete) {
			
			if($("#"+fieldId).val() != autocomplete.oldValue) {
				//si le contenu de la boite a chang�,  on attend encore 200ms.
				//si au bout de ce temps la boite n'a pas chang�, on lance la requete 
				autocomplete.oldValue = $("#"+fieldId).val();
				
				//special pour le menu du haut
				if(document.getElementById('mode')) {
					$("#mode").val(3);
				}
				
				setTimeout('skMgr.lookForNoValueChange("'+fieldId+'")', 400);
			} else {
				autocomplete.oldValue = $("#"+fieldId).val();
				setTimeout('skMgr.lookForValueChange("'+fieldId+'")', 400);	
			}
		}
	};

	/**
	 * Check if the field has not been modified during the last 200ms
	 * If this is the case, start autocomplete results fetching
	 */
	this.lookForNoValueChange = function (fieldId) {
		
		var autocomplete = null;
		//search for the component requested
		for(var i=0; i < this.autocompleteIds.length; i++) {
			if(this.autocompleteIds[i] == fieldId) {
				var autocomplete = this.components[this.autocompleteComponents[i]];	
			}
		}
		
		if(autocomplete) {
			
			
			if(! (autocomplete.oldValue.length > 1 && autocomplete.oldValue != autocomplete.watermark)) {
				$("#"+autocomplete.resultsFieldId).hide();
				  
				autocomplete.oldValue = $("#"+fieldId).val();
				skMgr.lookForValueChange(fieldId);
			}
			else if($("#"+fieldId).val() == autocomplete.oldValue && autocomplete.oldValue.length > 1 && autocomplete.oldValue != autocomplete.watermark) {
				
				//le mot n'a pas chang�. On lance la requete
				//autocomplete.oldValue = $("#"+fieldId).val();
				setTimeout('skMgr.lookForValueChange("'+fieldId+'")', 400);
				autocomplete.getAutocompleteResults();
			} else {
				
				//$("#searchkwres").hide();
				
				autocomplete.oldValue = $("#"+fieldId).val();
				setTimeout('skMgr.lookForNoValueChange("'+fieldId+'")', 400);	
			}
		}
	};
}

function IEreToggle() {
	if(skMgr.toToggle) {
    	var obj = skMgr.toToggle;
	   $("#"+obj.skinnableSelectId+" ul").toggle();
        $("#"+obj.skinnableSelectId+" ul").toggle();
        obj.hasReToggled = true;
	   skMgr.toToggle = null;    
    }
}

skMgr = new SkinnableControlsManager(); //do not change this variable name
$(document).ready(function () { skMgr.init(); });

