/*
	$Id: forms.js 70 2009-05-16 11:46:14Z root $ [load:0]
	$HeadURL: file:///usr/home/svn/cms/scripts/forms.js $
	(C) Copyright 2006-2009 Fellownet / Third Floor Design.
	All rights reserved.
*/

Element.addMethods(['input', 'select', 'textarea', 'button', 'a'], {
	my_disable: function(el_) {
		var el = $(el_);
		try {
			el.addClassName('disabled');
			el.setAttribute('disabled', 'disabled');
		} catch(e_) {}
		return el;
	},
	my_enable: function(el_) {
		var el = $(el_);
		try {
			el.removeClassName('disabled');
			el.removeAttribute('disabled');
		} catch(e_) {}
		return el;
	},
	my_hide: function(el_) {
		var el = $(el_);
		el.addClassName('offscreen');
	},
	my_show: function(el_) {
		var el = $(el_);
		el.removeClassName('offscreen');
	}
} );

Element.addMethods(['div'], {
	my_disable: function(el_) {
		var el = $(el_);
		el.select('button').each( function(el_) {
			if (typeof(el_.my_disable) != 'undefined') el_.my_disable();
		} );
		return el;
	},
	my_enable: function(el_) {
		var el = $(el_);
		el.select('button').each( function(el_) {
			if (typeof(el_.my_enable) != 'undefined') el_.my_enable();
		} );
		return el;
	}
} );

Element.addMethods('select', {
	my_add_option:function(el_, value_, text_) {
		var el = $(el_);
		var option = new Element('option', { value:value_ } ).update(text_);
		el.insert( { bottom:option } );
		if (el.extended) {
			var li = new Array(7);
			li[0] = '<li text="';
			li[1] = text_;
			li[2] = '" value="';
			li[3] = value_;
			li[4] = '">';
			li[5] = text_;
			li[6] = '</li>';
			el.next('ul').insert( { bottom:li.join('') } );
		}
		return el;
	},
	my_remove_option:function(el_, value_) {
		var el = $(el_);

		var option = el.down('option[value="' + value_ + '"]');
		if (option) option.remove();
		var li = el.next('ul').down('li[value="' + value_ + '"]');
		if (li) li.remove();

		return el;
	},
	my_update_option:function(el_, value_, text_) {
		var el = $(el_);

		var option = el.down('option[value="' + value_ + '"]');
		if (option) {
			option.setAttribute('text', text_);
			option.update(text_);
		}
		var li = el.next('ul').down('li[value="' + value_ + '"]');
		if (li) {
			li.setAttribute('text', text_);
			li.update(text_);
		}

		return el;
	},
	my_select_option:function(el_, value_) {
		var el = $(el_);
		el.setValue(value_);
		if (el.extended) {
			var li = el.next('ul').down('li[value="' + value_ + '"]');
			if (li) {
				if (el.next('ul').selected_li) el.next('ul').selected_li.removeClassName('selected');
				el.next('ul').selected_li = li;
				el.next('input').setValue(li.readAttribute('text'));
			}
		}
		return el;
	}
} );

Element.addMethods('form', {
	my_serialize: function(el_, hash_) {
		var el = $(el_);
		el.select('input').concat(el.select('textarea')).each( function(input_) {
			input_.setAttribute('oldvalue', input_.value);
			if (
				typeof(input_.getAttribute('title')) == 'string' &&
				input_.getAttribute('title') == $F(input_)
			) input_.setValue('');
		} );
		var result = el.serialize(hash_);
		el.select('input').concat(el.select('textarea')).each( function(input_) {
			if (typeof(input_.getAttribute('oldvalue')) == 'string') {
				input_.value = input_.getAttribute('oldvalue');
			}
		} );
		return result;
	},

	my_prepare_extend: function(el_) {
		var el = $(el_);
		el.options = $H( {
			checkboxes:true,
			selects:true
		} ).update($H(el.options));

		if (el.options.get('selects')) el.select('select').each( function(select_) {
			var html = new Array(16 + (select_.options.length * 10));
			html[0] = '<input readonly="readonly" class="select ';
			html[1] = select_.className;
			html[2] = '" value="';
			html[3] = select_.selectedIndex >= 0 ? select_.options[select_.selectedIndex].text : '';
			html[4] = '"><ul class="select" style="display:none;">';

			for (var i = 0; i < select_.options.length; i++) {
				html[5 + (i * 10)] = '<li text="';
				html[6 + (i * 10)] = select_.options[i].text;
				html[7 + (i * 10)] = '" value="';
				html[8 + (i * 10)] = select_.options[i].value;
				html[9 + (i * 10)] = '" class="'
				html[10 + (i * 10)] = select_.options[i].value == '---' ? 'divider' : (select_.options[i].value == '***' ? 'group' : '');
				html[11 + (i * 10)] = i == select_.selectedIndex && ! /^\s*$/i.test(select_.options[i].value) ? ' selected'  : '';
				html[12 + (i * 10)] = '">';
				html[13 + (i * 10)] = select_.options[i].text;
				html[14 + (i * 10)] = '</li>';
			}
			html[15 + (i * 10)] = '</ul>';
			select_.insert( { after:html.join('') } ).my_hide();
		} );

		if (el.options.get('checkboxes')) el.select('input[type="radio"],input[type="checkbox"]').each( function(input_) {
			var span = new Element('span', { 'class':input_.className } );
			span.addClassName('my_' + input_.getAttribute('type'));
			span.setAttribute('x_offset', input_.getAttribute('type') == 'radio' ? '-15px' : '0px');
			span.setAttribute('checked', input_.checked ? 'yes' : 'no');
			span.style.backgroundPosition = span.getAttribute('x_offset') + ' ' + (input_.checked ? '-17px' : '0px');
			input_.insert( { after:span } ).my_hide();
		} );

		el.select('input[title][type="text"],textarea[title]').each( function(input_) {
			var title = input_.getAttribute('title');
			if (! /^\s*$/i.test(title)) {
				if (/^\s*$/i.test($F(input_))) {
					if (input_.tagName.toLowerCase() == 'textarea') {
						input_.innerHTML = title;
					} else input_.setAttribute('value', title);
				}
				if ($F(input_) == title) input_.addClassName('default');
			}			
		} );

		el.select('input[type="password"]').each( function(password_) {
			password_.setAttribute('password', $F(password_));
			var title = password_.getAttribute('title');
			var input = new Element('input', { 'type':'text', 'class':password_.className, 'value':title } );
			input.addClassName('default');
			password_.insert( { after:input } );
			if (/^\s*$/i.test($F(password_))) {
				password_.my_hide();
			} else input.my_hide();
		} );

		el.setAttribute('prepared', 'true');
	},

	my_extend: function(el_, options_) {
		var el = $(el_);
		el.options = $H( {
			modal:true,
			button:false,
			buttons:'Close',
			default_button:'Close',
			action:'untitled.html',
			checkboxes:true,
			selects:true
		} ).update($H(options_));

		if (typeof(el.getAttribute('prepared')) != 'string') el.my_prepare_extend();

		if (typeof(window.events) == 'undefined') {
			window.events = new Hash();
			window.events.set('select-input-focus', function(event_) {
				var el = event_.element();
				el.blur();
				var ul = el.next();
				var offset = el.positionedOffset();

				ul.setStyle( {
					left:'-999px',
					top:'-999px'
				} ).show();

				if (! ul.selected_li) ul.selected_li = ul.down('li.selected');
				if (ul.selected_li) {
					ul.selected_li.addClassName('selected');
					ul.scrollTop = Math.max(0, ul.selected_li.positionedOffset().top - (ul.getHeight() / 2) + (ul.selected_li.getHeight() / 2));
				}

				if (! ul.my_width) {
					ul.my_width = el.getWidth() - 20;
					ul.select('li').each( function(li_) {
						ul.my_width = Math.max(li_.getWidth(), ul.my_width);
					} ).each( function(li_) {
						li_.style.width = (ul.my_width - 8) + 'px';
					} );
				}

				ul.setStyle( {
					left:offset.left + 'px',
					top:(offset.top + el.getHeight()) + 'px'
				} );

				Event.observe(ul, 'click', window.events.get('select-ul-click'));
				Event.observe(document, 'mousedown', ul.event_mousedown = window.events.get('select-input-mousedown').bind(ul));
			} );
			window.events.set('select-input-mousedown', function(event_) {
				var el = event_.element();
				if (
					el != this &&
					el.parentNode != this
				) {
					this.hide();
					Event.stopObserving(this);
					Event.stopObserving(document, 'mousedown', this.event_mousedown);
				}
			} );
			window.events.set('select-ul-click', function(event_) {
				var el = event_.element();
				if (
					el.tagName.toLowerCase() != 'li' ||
					el.getAttribute('value') == '---' ||
					el.getAttribute('value') == '***'
				) return;
				el.parentNode.hide();
				if (el != el.parentNode.selected_li) {
					if (el.parentNode.selected_li) el.parentNode.selected_li.removeClassName('selected');
					el.parentNode.selected_li = el;
					el.parentNode.previous('input').setValue(el.getAttribute('text'));
					el.parentNode.previous('select').setValue(el.getAttribute('value'));
					el.parentNode.previous('input').blur();
					
					var form = el.up('form');
					form.dirty = true;
					if (typeof(form.options.get('onChange')) == 'function') form.options.get('onChange')(form);
				}
				Event.stopObserving(el.parentNode);
				Event.stopObserving(document, 'mousedown', this.event_mousedown);
			} );
			window.events.set('radio-change', function(event_) {
				var el = event_.element();
				var form = el.up('form');
				if (el.tagName.toLowerCase() == 'span') {
					var input = el.previous('input');
					if (input.disabled) return;
					input.checked = input.getAttribute('type') == 'radio' ? true : input.checked = ! input.checked;
					el.style.backgroundPosition = el.getAttribute('x_offset') + ' ' + (el.previous('input').checked ? '-17px' : '0px');
				}
			} );
			window.events.set('radio-observe', function(pe_) {
				try {
					var changed = false;
					this.select('span[x_offset]').each( function(span_) {
						span_.style.backgroundPosition = span_.getAttribute('x_offset') + ' ' + (span_.previous('input').checked ? '-17px' : '0px');
						if (span_.previous('input').checked != (span_.getAttribute('checked') == 'yes')) {
							changed = true;
							span_.setAttribute('checked', span_.previous('input').checked ? 'yes' : 'no');
						}
					}.bind(this));
					if (changed) {
						this.dirty = true;
						if (typeof(this.options.get('onChange')) == 'function') this.options.get('onChange')(this);
					}
				} catch(e_) { pe_.stop(); }
			} );

			window.events.set('input-focus', function(event_) {
				var el = event_.element();
				el.removeClassName('default');
				if (el.getAttribute('title') == $F(el)) el.setValue('');
			} );
			window.events.set('input-blur', function(event_) {
				var el = event_.element();
				if ($F(el) == '') {
					el.setValue(el.getAttribute('title'));
					el.addClassName('default');
				} else el.removeClassName('default');
			} );
			window.events.set('password-input-focus', function(event_) {
				var el = event_.element();
				if (el.readAttribute('type').toLowerCase() == 'password') el = el.next('input');
				el.my_hide();
				el.setAttribute('tabindex', '-1');
				var password = el.previous('input');
				password.my_show();
				password.activate();
			} );
			window.events.set('password-blur', function(event_) {
				var el = event_.element();
				if (/^\s*$/i.test($F(el))) {
					el.my_hide();
					el.next('input').my_show();
				}
			} );
			window.events.set('input-key-down', function(event_) {
				var el = event_.element();
				el.old_value = el.getValue();
			} );
			window.events.set('input-key-up', function(event_) {
				var el = event_.element();
				var form = el.up('form');
				if (
					typeof(el.old_value) == 'string' &&
					el.old_value != $F(el)
				) {
					form.dirty = true;
					form.options.get('onChange')(form);
				}
			} );
			window.events.set('submit', function(event_) {
				var el = event_.element();
				if (typeof(el.options.get('onSubmit')) == 'function') {
					event_.stop();
					el.options.get('onSubmit')(el);
				}
			} );
		}

		if (el.options.get('selects')) el.select('select').each( function(select_) {
			Event.stopObserving(select_.next(), 'focus', window.events.get('select-input-focus'));
			Event.observe(select_.next(), 'focus', window.events.get('select-input-focus'));
			select_.extended = true;
		} );
		if (el.options.get('checkboxes')) el.select('input[type="radio"],input[type="checkbox"]').each( function(input_) {
			var span = input_.next('span');
			Event.stopObserving(span, 'click', window.events.get('radio-change'));
			Event.observe(span, 'click', window.events.get('radio-change'));
		} );
		if (el.options.get('checkboxes')) {
			if (el.radio_observer) el.radio_observer.stop();		
			el.radio_observer = new PeriodicalExecuter(window.events.get('radio-observe').bind(el), 0.25);
		}
		el.select('input[title][type="text"],textarea[title]').each( function(input_) {
			Event.stopObserving(input_, 'focus', window.events.get('input-focus'));
			Event.stopObserving(input_, 'blur', window.events.get('input-blur'));
			Event.observe(input_, 'focus', window.events.get('input-focus'));
			Event.observe(input_, 'blur', window.events.get('input-blur'));
		} );
		el.select('input[type="password"]').each( function(password_) {
			password_.setValue(password_.getAttribute('password'));
			var input = password_.next('input');
			Event.stopObserving(password_, 'blur', window.events.get('password-blur'));
			Event.stopObserving(input, 'focus', window.events.get('password-input-focus'));
			Event.stopObserving(password_, 'focus', window.events.get('password-input-focus'));
			Event.observe(password_, 'blur', window.events.get('password-blur'));
			Event.observe(input, 'focus', window.events.get('password-input-focus'));
			Event.observe(password_, 'focus', window.events.get('password-input-focus'));
		} );
		if (typeof(el.options.get('onChange')) == 'function') el.select('input,textarea').each( function(input_) {
			Event.stopObserving(input_, 'keydown', window.events.get('input-key-down'));
			Event.stopObserving(input_, 'keyup', window.events.get('input-key-up'));
			Event.observe(input_, 'keydown', window.events.get('input-key-down'));
			Event.observe(input_, 'keyup', window.events.get('input-key-up'));
		} );
		el.select('textarea').each( function(textarea_) {
			textarea_.setAttribute('spellcheck', 'false');
		} );
		Event.stopObserving(el, 'submit', window.events.get('submit'));
		Event.observe(el, 'submit', window.events.get('submit'));

		if (window.console) window.console.log('[Form] form with id ' + el.identify() + ' extended');
	},

	my_dirty:function(el_, set_) {
		var el = $(el_);
		if (
			typeof(set_) == 'boolean' &&
			set_
		) {
			el.dirty = true;
			if (typeof(el.options.get('onChange')) == 'function') el.options.get('onChange')(el);
		}
		return (typeof(el.dirty) == 'boolean' ? el.dirty : false);
	},

	my_clean:function(el_) {
		var el = $(el_);
		el.dirty = false;
	},

	my_reset:function(el_) {
		var el = $(el_);
		el.reset();
	},

	my_submit:function(el_, options_) {
		var el = $(el_);
		if (typeof(el.options) == 'undefined') {
			el.options = $H( {
				modal:true,
				button:false,
				evalJS:'force',
				evalJSON:'force',
				buttons:'Close',
				default_button:'Close',
				action:'untitled.html'
			} );
		}
		el.options.update(options_);

		if (typeof(el.options.get('button')) !== 'boolean') {
			if (typeof(el.options.get('button')) == 'string') {
				el.options.set('button', $A(el.options.get('button').split(',')));
			} else {
				var buttons = new Array(el.options.get('button'));
				el.options.set('button', $A(buttons));
			}
			el.options.get('button').each( function(button_) {
				$(button_).my_disable();
			} );
		}

		el.select('.field_error').each( function(field_) {
			field_.removeClassName('field_error');
		} );

		var marker = el.appendChild(new Element('input', {
			'type':'hidden',
			'name':'__ajaxcall',
			'value':'1'
		} ));

		var action = el.options.get('action');
		if (el.options.get('parameters')) action += '?' + el.options.get('parameters');

		new Ajax.Request(
			action, {
				method:'post',
				evalJS:el.options.get('evalJS'),
				evalJSON:el.options.get('evalJSON'),
				parameters:el.my_serialize(),
				onComplete:function(req_) {
					el.removeChild(marker);

					var results = $H(req_.responseText.toQueryParams());
					if (typeof(results.get('result')) != 'string') {
						alert(req_.responseText);
						if (typeof(el.options.get('button')) !== 'boolean') {
							$(el.options.get('button')).each( function(button_) {
								$(button_).my_enable();
							} );
						}
						if (typeof(el.options.get('onFailure')) == 'function') el.options.get('onFailure')(results);
					} else {
						switch(results.get('result')) {
							case 'OK':
								if (typeof(el.options.get('onSuccess')) == 'function') el.options.get('onSuccess')(results);
								break;
							default:
								var errors;
								try {
									(errors = $A(results.get('fields').split(';'))).each( function(field_) {
										if (typeof(el[field_]) != 'undefined') {
											Element.addClassName(el[field_], 'field_error');
										}
									} );
								} catch(e_) {}
								Dialog.open( {
									content:'<p>' + results.get('content') + '</p>',
									title:results.get('title'),
									subtitle:el.options.get('subtitle'),
									buttons:el.options.get('buttons'),
									default_button:el.options.get('default_button'),
									width:400,
									padding:10,
									modal:true,
									onClick:function(action_, dialog_) {
										if (typeof(el.options.get('button')) != 'boolean') {
											$(el.options.get('button')).each( function(button_) {
												$(button_).my_enable();
											} );
										}
										if (typeof(el.options.get('onError')) == 'function') el.options.get('onError')(action_, results);
										dialog_.close();
									},
									onOpen: function(dialog_) {
										if (typeof(el.options.get('onOpen')) == 'function') el.options.get('onOpen')(dialog_);
									}
								} );
								break;
						}	
					}
				}
			}
		);
		return el;
	}
} );
