Niceform = Class.create();
Niceform.prototype = {
	initialize: function() {
		// inputs (password, text)
		var inputs = document.getElementsByTagName('input'), i=0;
		while (input = inputs[i++]) {
			if (input.type == 'password' || input.type == 'text') {
				if (input.id == '') 
					input.id = 'input-' + input.type + '-' + i;
				if (input.className.indexOf('textfield') == -1) 
					new Textfield(input.id);
			}
		}
        // textareas
		var textareas = document.getElementsByTagName('textarea'), i=0;
		while (textarea = textareas[i++]) {
			if (textarea.id == '') 
				textarea.id = 'textarea-' + i;
			if (textarea.className.indexOf('textfield') == -1 && textarea.className.indexOf('richtext') == -1)
				new Textfield(textarea.id);
		}
        // checkboxes, radios
		var labels = document.getElementsByTagName('label'), i = 0;
		while (label = labels[i++]) {
			element = $(label.htmlFor);
			if (element.type == 'checkbox') 
				new Checkbox(element, label);
			else if (element.type == 'radio') 
				new Radiobutton(element, label);
		}
        // selectboxes
		Selectbox.replaceAll();
		
		/*
		var datepickers = document.getElementsByClassName('datepicker'), i = 0;
		while (datepicker = datepickers[i++]) 
			new DatePicker(datepicker.id, DATEFORMAT);
		*/
	}
}

/**
 * Checkbox
 */
Checkbox = Class.create();
Checkbox.instances = [];
Checkbox.prototype = {
	initialize: function(element, label) {
		for (var i=0; i<Checkbox.instances.length; i++) {
			if (Checkbox.instances[i] == element.id) 
				return;
		}
		Checkbox.instances[Checkbox.instances.length] = element.id;
		this.element = element;
		this.element.label = label;
		this.element.className = 'hide';

		var css = 'checkbox' + (this.element.checked ? 'On' : 'Off');
		if (this.element.disabled) 
			css += 'Disabled';
		else 
			Event.observe(this.element.label, 'click', this.onClick.bindAsEventListener(this));
		this.element.label.className = css;
	},
    onClick: function() {
        check = this.element.label.className == 'checkboxOff';
        this.element.label.className = check ? 'checkboxOn' : 'checkboxOff';
        if (Prototype.Browser.IE) this.element.checked = check;
    }
}


/**
 * Radiobutton
 */
Radiobutton = Class.create();
Radiobutton.instances = [];
Radiobutton.prototype = {
	initialize: function(element, label) {
		for (var i=0; i<Radiobutton.instances.length; i++) {
			if (Radiobutton.instances[i] == element.id) 
				return;
		}
		Radiobutton.instances[Radiobutton.instances.length] = element.id;
		this.element = element;
		this.element.label = label;
		this.element.className = 'hide';
		var css = 'radio' + (this.element.checked ? 'On' : 'Off');
		if (this.element.disabled) 
			css += 'Disabled';
		else 
			Event.observe(this.element.label, 'click', this.onClick.bindAsEventListener(this));
		this.element.label.className = css;
	},
    onClick: function(event) {
        var radios = document.getElementsByName(this.element.name);
        var selectedIndex = 0;
        for (var i=0; i<radios.length; i++) {
            radios[i].checked = false;
            this.changeLabelClass(radios[i].id, 'radioOff');
            if (radios[i].value == this.element.value) selectedIndex = i;
        }
        radios[selectedIndex].checked = true;
        this.changeLabelClass(radios[selectedIndex].id, 'radioOn');
    },
    changeLabelClass: function (id, css) {
        var labels = document.getElementsByTagName('label');
        for (var i=0; i<labels.length; i++) {
            if (labels[i].htmlFor == id) {
                labels[i].className = css;
                return true;
            }
        }
    }
}

/**
 * Textfield
 */
Textfield = Class.create();
Textfield.instances = [];
Textfield.prototype = {
	initialize: function(id) {
		Textfield.instances[Textfield.instances.length] = id;
		this.element = $(id);
		var css = this.element.className;
		if (css.length) css += ' ';
		css += this.element.disabled ? 'textfield_disabled' : 'textfield';
		this.element.className = css;
		Event.observe(this.element, 'focus', this.onFocus.bindAsEventListener(this));
		Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this));
	},
	onFocus: function() {
		this.element.className = this.element.className.replace('textfield', 'textfield_focus');
	},
	onBlur: function() {
		this.element.className = this.element.className.replace('textfield_focus', 'textfield');
	}
}

/**
 * Selectbox
 */
/*
Object.extend(Event, {
    wheel:function (event){
        var delta = 0;
        if (!event) event = window.event;
        if (event.wheelDelta) {
            delta = event.wheelDelta/120;
            if (window.opera) delta = -delta;
        } else if (event.detail) { delta = -event.detail/3;     }
        return Math.round(delta); //Safari Round
    }
});
*/

Selectbox = Class.create();
Selectbox.instances = [];
Selectbox.open = 0;
Selectbox.hideAll = function() {
	for (var i = 0; i < Selectbox.instances.length; i++) {
		Selectbox.instances[i] == Selectbox.open ? Selectbox.open = 0 : $('selectbox_options_' + Selectbox.instances[i]).hide();
	}
}
Selectbox.replaceAll = function() {
	var selects = document.getElementsByTagName('select'), i=0;
	
	while (select = selects[i++]) {
		if (select.id == '') 
			select.id = 'selectbox_' + i;
		if (select.className.indexOf('noselect') == -1) {
			var found = false;
			for (var j=0; j<Selectbox.instances.length; j++) {
				if (Selectbox.instances[j] == select.id) 
					found = true;
			}
			if (!found) select.multiple ? new MultiSelectbox(select.id) : new Selectbox(select.id);
		}
	}
}

Selectbox.prototype = {
	initialize: function(id) {
		Selectbox.instances[Selectbox.instances.length] = id;
		this.id = id;
		this.element = $(id);
		this.disabled = this.element.disabled;
		this.active = false;
		this.scroll = true;
		this.textvalue = '';
		this.render();
	},
	render: function() {
		// create selectbox		
		var div;
		// container
		this.container = document.createElement('div');
		this.container.id = 'selectbox_' + this.id;
		this.container.style.width = (parseInt(this.element.style.width)-10) + 'px';
		// hide selectbox
		this.element.style.visibility = 'hidden';	
		// this.input
		this.input = document.createElement('input');
		this.input.type = 'text';
		this.input.style.width = (parseInt(this.container.style.width)-12) + 'px';
		this.input.setAttribute('autocomplete', 'off');	
		this.input.className = '';
		div = document.createElement('div');
		div.appendChild(this.input);
		this.container.appendChild(div);
		// create list
		this.a = []
		this.options = document.createElement('ul');
		this.options.id = 'selectbox_options_' + this.id;
		this.options.className = 'selectbox_options';
		this.update();
		this.options.style.display = 'none';
		// observe events
		Event.observe(this.container, 'click', this.onClick.bindAsEventListener(this));
		Event.observe(this.input, 'keypress', this.onKeyPress.bindAsEventListener(this));
		Event.observe(this.input, 'keyup', this.onKeyUp.bindAsEventListener(this));
		Event.observe(this.input, 'mousewheel', this.onMouseWheel.bindAsEventListener(this));
		Event.observe(this.input, 'DOMMouseScroll', this.onMouseWheel.bindAsEventListener(this)); // Firefox
		// add to document
		this.element.parentNode.insertBefore(this.container, this.element);
		this.element.parentNode.insertBefore(this.options, this.element);
	},
    update: function() {
        this.selectedIndex = null;
        this.optionsCount = this.element.options.length;
        this.disabled = this.element.disabled ? true : (this.optionsCount > 0 ? false : true);
        this.input.disabled = this.disabled;
        this.container.className = this.disabled ? 'selectbox_disabled' : 'selectbox';
        this.options.innerHTML = '';

        var li, a, img;
        for (var i = 0; i < this.optionsCount; i++) {
            li = document.createElement('li');
            this.a[i] = document.createElement('a');
            this.a[i].id = 'selectbox_options_' + this.id + '_' + i;
            this.a[i].setAttribute('href', 'javascript:void(0)');
            if (this.element.options[i].selected) this.selectedIndex = i;
            this.a[i].innerHTML = this.element.options[i].text;
            if (this.a[i].innerHTML == '') this.a[i].innerHTML = '&nbsp;';
            Event.observe(this.a[i], 'click', this.onSelect.bindAsEventListener(this, i));
            li.appendChild(this.a[i]);
            this.options.appendChild(li);
        }
        if (this.selectedIndex != null) {
            this.select(this.selectedIndex);
        } else {
            this.input.value = '';
        }
        var width = parseInt(this.container.style.width) - 4;
        if (i > 10) { 
            this.options.style.overflow = 'auto';
            this.options.style.height = '201px';
            this.options.style.width = (width + 17) + 'px';
            this.scroll = true;
        } else this.options.style.width = width + 'px';
    },
	showOptions: function() {
		if (this.disabled) return;
		this.active = true;
		$('selectbox_options_' + this.id).show();
		if (this.scroll) {
			var scroll_top = 0;
			if (this.selectedIndex > 9) scroll_top = 20 * this.selectedIndex - 9 * 20;
			$('selectbox_options_' + this.id).scrollTop = scroll_top;
		}
	},
	hideOptions: function() {
		this.active = false;
		$('selectbox_options_' + this.id).hide();
	},
	select: function(selectedIndex) {
		this.element.options[this.selectedIndex].selected = false;
		Element.removeClassName(this.a[this.selectedIndex], 'selected');
			
		this.selectedIndex = selectedIndex;
		this.input.value = this.element.options[this.selectedIndex].text;
		this.textvalue = this.input.value;
		if (this.a[this.selectedIndex].style.backgroundImage) 
			this.input.style.backgroundImage = this.a[this.selectedIndex].style.backgroundImage;
		this.element.options[this.selectedIndex].selected = true;
		Element.addClassName(this.a[this.selectedIndex], 'selected');
	},
	selectNext: function() {
		var next = this.selectedIndex + 1;
		if (next < this.optionsCount) {
			for (var i=next; i<this.optionsCount; i++) {
				if (this.a[i].style.display != 'none') {
					this.select(i);
					return;
				}
			}
		}
	},
	selectPrevious: function() {
		var previous = this.selectedIndex - 1;
		if (previous >= 0) {
			for (var i=previous; i>=0; i--) {
				if (this.a[i].style.display != 'none') {
					this.select(i);
					return;
				}
			}
		}
	},
	onClick: function() {
		if (this.input.disabled) return;
		if (this.options.style.display == 'none') {
			Selectbox.open = this.id;
			this.showOptions();
			this.input.focus();
		} else {
			Selectbox.open = 0;
			this.hideOptions();
		}
	},
	onSelect: function(e) {
		this.select(arguments[1]);
	},
	onKeyPress: function(event) {
		if (this.disabled) return;
		switch(event.keyCode) {
			case Event.KEY_TAB: if (this.active) this.hideOptions(); return;
			case Event.KEY_RETURN:
			case Event.KEY_ESC: this.hideOptions(); this.active = false; this.input.blur(); Event.stop(event); return;
			case Event.KEY_LEFT:
			case Event.KEY_UP: this.selectPrevious(); Event.stop(event); return;
			case Event.KEY_RIGHT:
			case Event.KEY_DOWN: this.selectNext(); Event.stop(event); return;
		}
	},
	onKeyUp: function(event) {
		if (this.disabled) return;
		if (this.textvalue != this.input.value) {
			var s = this.input.value.toLowerCase();
			var l = s.length;
			for (var i=0; i<this.optionsCount; i++) 
				this.a[i].innerHTML.substring(0, l).toLowerCase() == s ? this.a[i].show() : this.a[i].hide();			
		}
	},
	onMouseWheel: function(event) {
		if (this.disabled) return;
		Event.wheel(event) == 1 ? this.selectPrevious() : this.selectNext();
	}
}

MultiSelectbox = Class.create();
MultiSelectbox.prototype = {
	initialize: function(id) {
		Selectbox.instances[Selectbox.instances.length] = id;
		this.id = id;
		this.element = $(id);
		this.disabled = this.element.disabled;
		this.active = false;
		this.scroll = true;
		this.scroll_top = 0;
		this.textvalue = '';
		this.render();
	},
	render: function() {
		// create selectbox		
		var div;
		// container
		this.container = document.createElement('div');
		this.container.id = 'selectbox_' + this.id;
		this.container.style.width = (parseInt(this.element.style.width)-10) + 'px';
		// hide selectbox
		this.element.size = 1;
		this.element.style.visibility = 'hidden';	
		// this.input
		this.input = document.createElement('input');
		this.input.type = 'text';
		this.input.style.width = (parseInt(this.container.style.width)-12) + 'px';
		this.input.setAttribute('autocomplete', 'off');	
		this.input.className = '';
		div = document.createElement('div');
		div.appendChild(this.input);
		this.container.appendChild(div);
		// create list
		this.options = document.createElement('ul');
		this.options.id = 'selectbox_options_' + this.id;
		this.options.className = 'selectbox_options';
		this.update();
		this.options.style.display = 'none';
		// observe events
		Event.observe(this.container, 'click', this.onClick.bindAsEventListener(this));
		Event.observe(this.input, 'keypress', this.onKeyPress.bindAsEventListener(this));
		// add to document
		this.element.parentNode.insertBefore(this.container, this.element);
		this.element.parentNode.insertBefore(this.options, this.element);
	},
	update: function() {
		this.checkbox = [];
		this.a = []
		
		this.selectedIndex = [];
		this.optionsCount = this.element.options.length;
		this.disabled = this.optionsCount > 0 ? false : true;
		this.input.disabled = this.disabled;
		this.container.className = this.disabled ? 'selectbox_disabled' : 'selectbox';
		this.options.innerHTML = '';
		
		var li, label, a;
		
		// select all
		li = document.createElement('li');
		this.select_all_link = document.createElement('a');
		this.select_all_link.setAttribute('href', 'javascript:void(0)');
		this.select_all_link.className = 'multiple_on selectall';
		Event.observe(this.select_all_link, 'click', this.selectAll.bindAsEventListener(this));
		li.appendChild(this.select_all_link);
		this.options.appendChild(li);
		
		this.selected = 0;
		for (var i = 0; i < this.optionsCount; i++) {
			li = document.createElement('li');
			this.a[i] = document.createElement('a');
			this.a[i].id = 'selectbox_options_' + this.id + '_' + i;
			this.a[i].setAttribute('href', 'javascript:void(0)');
			if (this.element.options[i].selected) {
				this.a[i].className = 'multiple_on';
				this.selectedIndex[this.selectedIndex.length] = i;
				this.selected++;
			} else {
				this.a[i].className = 'multiple_off';
			}						
			this.a[i].innerHTML = this.element.options[i].text;
			if (this.a[i].innerHTML == '') this.a[i].innerHTML = '&nbsp;';
			Event.observe(this.a[i], 'click', this.onSelect.bindAsEventListener(this, i));
			
			li.appendChild(this.a[i]);
			this.options.appendChild(li);
		}
		
		this.select_all_link.innerHTML = this.optionsCount == this.selected ? 'Unselect all' : 'Select all';
		var width = parseInt(this.container.style.width) - 4;
		if (i > 10) { 
			this.options.style.overflow = 'auto';
			this.options.style.height = '201px';
			this.options.style.width = (width + 17) + 'px';
			this.scroll = true;
		} else this.options.style.width = width + 'px';
		
		this.showText();
	},
	showOptions: function() {
		if (this.disabled) return;
		this.active = true;
		$('selectbox_options_' + this.id).show();
		$('selectbox_options_' + this.id).scrollTop = this.scroll_top;
	},
	hideOptions: function() {
		this.active = false;
		$('selectbox_options_' + this.id).hide();
	},
	select: function(selectedIndex) {
		if (this.a[selectedIndex].className == 'multiple_on') {
			this.a[selectedIndex].className = 'multiple_off';
			this.element.options[selectedIndex].selected = false;
		} else {
			this.a[selectedIndex].className = 'multiple_on';
			this.element.options[selectedIndex].selected = true;
		}
		Selectbox.open = this.id;
		this.showText();
	},
	selectAll: function() {
		var select = this.optionsCount != this.selected;
		this.selected = 0;
		for (var i=0; i<this.optionsCount; i++) {
			if (select) {
				this.a[i].className = 'multiple_on';
				this.element.options[i].selected = true;
				this.selected++;
			} else {
				this.a[i].className = 'multiple_off';
				this.element.options[i].selected = false;
			}
		}
		if (this.optionsCount == this.selected) {
			this.select_all_link.innerHTML = 'Unselect all';
			this.select_all_link.className = 'multiple_off selectall';
		} else {
			this.select_all_link.innerHTML = 'Select all';
			this.select_all_link.className = 'multiple_on selectall';
		}
		
		Selectbox.open = this.id;
		this.showText();
	},
	onClick: function() {
		if (this.options.style.display == 'none') {
			Selectbox.open = this.id;
			this.showOptions();
			this.input.focus();
		} else {
			Selectbox.open = 0;
			this.hideOptions();
		}
	},
	onSelect: function(e) {
		this.select(arguments[1]);
	},
	onKeyPress: function(event) {
		if (this.disabled) return;
		switch(event.keyCode) {
			case Event.KEY_TAB: if (this.active) this.hideOptions(); return;
			case Event.KEY_RETURN:
			case Event.KEY_ESC: this.hideOptions(); this.active = false; this.input.blur(); Event.stop(event); return;
		}
	},
	showText: function() {
		this.selected = 0;
		var i = 0;
		var text = '';
		while (option = this.element.options[i++]) {
			if (option.selected) {
				text += option.text + ', ';
				this.selected++;
			}
		}
		if (text.length) {
			text = text.substring(0, text.length-2);
			text = this.selected + '/' + (i-1) + ': ' + text;
		}
		text = text.replace(/<[^>]+>[^<]+<\/[^>]+>/gi, '');
		text = text.replace(' ,', ',');
		this.input.value = this.textvalue = text;
	}
}

// close open select when click outside
Event.observe(document, 'click', Selectbox.hideAll);