
/**
 * Classe de gestion de selects personnalisés.
 *
 * @author Lapoz - pierre.guillaume@e-lixir.fr
 * @link http://www.e-lixir.fr
 * @copyright Copyright e-Lixir (c)
 *
 * - Le champ sera remplacé visuellement par un SPAN.selectField contenant un SPAN.selectValue et un SPAN.selectOptions.
 * - Appelé sans argument, le constructeur modifiera tous les éléments SELECT de classe "customSelect" de la page.
 *   Il peut également prendre en argument l'id d'un champ ou directement l'élément Prototype correspondant pour l'appliquer ponctuellement à un champ particulier.
 * - Le deuxième argument peut être un tableau d'options :
 *   - className: Classe CSS utilisée pour repérer les SELECT customisés (par défaut "customSelect")
 *   - effect(On|Off)Name: Nom de l'effet d'apparition ou de disparition de la liste. Par défaut aucun.
 *   - effect(On|Off|[])Options: Tableau d'options qui s'appliquera à l'effet d'apparition, de disparition, ou des deux
 */
var CustomSelect = Class.create({
	initialize : function(e, opts) {
		if(typeof customSelectInstances == "undefined")
			customSelectInstances = new Array();
		if(typeof e == "undefined" || !e)
			$$("SELECT."+(opts && opts.className ? opts.className : "customSelect")).each(function(e) { new CustomSelect(e, opts || {}); });
		else this.create(e, opts);
	},
	create: function(e, opts) {
		$(e).identify();
		this.select = $(e);
		if(!this.select) return;
		this.opts = Object.extend({
			className : "customSelect",
			effectOnName : null,
			effectOffName : null,
			effectOnOptions: {},
			effectOffOptions: {}
		}, opts || {});
		if(this.opts.effectOptions)
			this.opts.effectOnOptions = this.opts.effectOffOptions = this.opts.effectOptions;
		this.field = new Element("span", { "class": "selectField" });
		$w(this.select.className).each(function(e) {
			if(e != this.opts.className)
				this.field.addClassName(e);
		}.bind(this));
		this.value = new Element("span", { "class": "selectValue" }).observe("click", this.toggleOptions.bind(this));
		var middleSpan = new Element("span");
		this.options = new Element("span", { "class": "selectOptions", style:"display:none;z-index:"+(customSelectInstances.length+1) });
		if(this.select.select("option")[this.select.selectedIndex])
			this.value.className += (this.select.select("option")[this.select.selectedIndex].className ? " "+this.select.select("option")[this.select.selectedIndex].className : "");
		this.select.select("option").each(function(e) {
			var opt = new Element("span", { datafld: e.value });
			$w(e.className).each(function(e) {
				this.addClassName(e);
			}.bind(opt));
			if(!this.value.innerHTML || e.selected) {
				this.selected = opt;
				this.value.update(e.innerHTML)
			}
			if(e.selected) {
				this.selected = opt;
				opt.addClassName("selected");
			}
			opt.observe("mouseover", function(e) { this.addClassName("active"); });
			opt.observe("mouseout", function(e) { this.removeClassName("active"); });
			opt.observe("click", this.selectOption.bindAsEventListener(this));
			this.options.insert(opt.update(e.innerHTML));
		}.bind(this));
		middleSpan.insert(this.options);
		this.field.insert(this.value).insert(middleSpan);
		this.select.hide().insert({ after: this.field });
		customSelectInstances.push(this);
		Event.observe(document, "click", this.hideOptions.bindAsEventListener(this));
	},
	toggleOptions: function() {
		customSelectInstances.each(function(e) {
			if(e.select.id != this.select.id)
				e.hide();
		}.bind(this));
		if(!this.options.visible())
			this.show();
		else this.hide();
	},
	hideOptions: function(e) {
		if(!e.element().descendantOf(this.field))
			this.hide();
	},
	show: function() {
		this.value.addClassName("activeValue");
		if(this.opts.effectOnName)
			eval("new Effect."+this.opts.effectOnName+"(this.options, this.opts.effectOnOptions);");
		else this.options.show();
	},
	hide: function() {
		this.value.removeClassName("activeValue");
		if(this.opts.effectOffName)
			eval("new Effect."+this.opts.effectOffName+"(this.options, this.opts.effectOffOptions);");
		else this.options.hide();
	},
	selectOption: function(e) {
		e = e.element();
		this.selected.removeClassName("selected");
		this.selected = e.addClassName("selected");
		this.select.setValue(e.readAttribute("datafld"));
		this.select.simulate("change");
		this.value.update(e.innerHTML);
		this.value.className = "selectValue"+(e.className ? " "+e.className.gsub(/\s*(active|selected)\s*/, "") : "");
		this.toggleOptions();
	}
});

