/*
 * $Id: multiSelectBox.js 4241 2008-02-18 14:05:58Z jons $
 * 
 * MultiSelectBox creates an unobtrusive multiselect box.
 * 
 * Requires the id of or a reference to a DIV element containing the one SELECT with multiple set to multiple. 
 * 
 * TODO: Options:
 * 
 *  [int] max -> A maximum of selected options. Defaults to 0 meaning no maximum.
 *  [string] maxMessage -> Message to display when a selection exceeds the maximum of selected options.
 * 
 * 	Snap je niks van de syntax?:
 * 	http://www.prototypejs.org/api
 */

var MultiSelect = Class.create();

MultiSelect.prototype = {
	// Constructor
	initialize: function( elementOrId , options ) {
		
		// De container DIV
		this.element = $( elementOrId );
		
		// De originele select box
		this.selector = this.element.getElementsBySelector("SELECT")[0];
		
		
		// Opbouwen extra HTML elementen
		
		// de box met geselecteerde opties
		this.selection = document.createElement("SELECT");
		Element.addClassName(this.selection, "multiple");
		this.selection.addClassName("selection");
		this.selection.setAttribute("multiple","multiple");
		this.selection.name = this.selector.name;
		this.selection.setStyle({'float': 'left'});
		
		// De button om plaatsten toe te voegen
		this.addButton = document.createElement("DIV");
		Element.addClassName(this.addButton, "multiselect_button");
		this.addButton.addClassName("add");
		this.addButton.innerHTML = "<span><img src='/public/icons/silk/arrow_right.png' alt='toevoegen' /></span>";
		
		// De button om plaatsten te verwijderen
		this.removeButton = document.createElement("DIV");
		Element.addClassName(this.removeButton, "multiselect_button");
		this.removeButton.addClassName("remove");
		this.removeButton.innerHTML = "<span><img src='/public/icons/silk/arrow_left.png' alt='verwijderen' /></span>";
		
		// De container div voor de buttons
		this.buttons =  document.createElement("DIV");
		Element.addClassName(this.buttons, "multiselect_buttons");
		this.buttons.appendChild(this.addButton);
		this.buttons.appendChild(this.removeButton);
		this.buttons.setStyle({'float': 'left'});
		
		
		this.element.appendChild(this.buttons);
		this.element.appendChild(this.selection);
		
		// Reset de naam van de originele selectbox
		this.selector.name="";
		this.selector.setStyle({'float': 'left'});
		
		// Zoek het formulier element op om onsubmit behaviour toe te passen.
		this.form;
		var ancestors = this.element.ancestors();
		ancestors.each(function(a){
			if(a.tagName == 'FORM') {
				this.form = a;
			}
		}.bind(this));
		
		// default options
		this.options = {
			max: 0,
			maxMessage: 'U kun maximaal $max opties selecteren.'
		};
		
		// overwrite default options
		Object.extend(this.options, options || {});
		
		// add behaviour
		this.selector.observe("dblclick" , this.select.bind(this));
		this.selection.observe("dblclick" , this.deselect.bind(this));
		this.removeButton.observe("click" , this.deselect.bind(this));
		this.addButton.observe("click" , this.select.bind(this));
		this.form.observe("submit" , this.onSubmit.bind(this));
		
		// Nadat ik geinitialisserd ben stop ik alle opties met selected="selected" 
		// in de box voor geselecteerde opties
		this.select();
		
	},
	select: function() {
		var isSelected = false;
		
		// voor elke geselecteerde optie een controle of deze al geselecteerd was.
		// zo niet voeg dan toe.
		$A(this.selector.options).each(function(c){
			if(c.selected && c.value != '') {
				$A(this.selection.options).each(function(cc){
					if(c.value == cc.value) {
						isSelected = true;
					}
				});
				if(! isSelected ) {
					this.selection.options[this.selection.options.length] = new Option(c.text , c.value );
				} else {
					isSelected = false;
				}
			}
		}.bind(this));
		this.clearSelector();
	}, 
	deselect: function() {
		var c = [];
		// Maak een nieuwe array aan met opties die niet verwijderd moeten worden.
		// Omdat: als je in een loop een optie weggooit klopt je iterator niet meer.
		$A(this.selection.options).each(function(cc){
			if(!cc.selected) {
				c.push(cc);
			}
		});	
		
		// Verwijder alle opties
		this.selection.options.length=0;
		
		// Plaats alle opties die uit array met niet geselecteerde opties terug
		c.each(function(ccc){
			this.selection.options[this.selection.options.length] = ccc;
		}.bind(this));
	},
	onSubmit: function() {
		// Zorg dat alle gekozen opties geselecteerd worden als het formulier wordt verstuurd.
		$A(this.selection.options).each(function(o){o.selected = 'selected'});
	},
	clearSelector: function(){
		$A(this.selector.options).each(function(o){o.selected='';});
	}
}