// Unobtrusive formhandling
// Voor ROC Midden Nederland
// peer&dedigitalesupermarkt (c) 2007

var ROCForm = 
{
	Validate: 
	{
		Debug: false,
		initLiveValidation: function ()
		{
			$$('form.validate .live').each(function(field){
				switch (field.type)
				{
					case 'checkbox':
					case 'radio':
						field.addEvent('change', this.liveValidateField.bindWithEvent(this));
						field.addEvent('click', this.liveValidateField.bindWithEvent(this));
					break;
					default:
						field.addEvent('blur', this.liveValidateField.bindWithEvent(this));
				}
			}.bind(this));
			$$('form.validate').each(function(form){
				form.onsubmit = this.validateForm;
			}.bind(this));
		},
		validateForm: function()
		{
			validate = ROCForm.Validate; // Deze moet verwijzen naar het huidige object.
			validate.errorFound = false;
			validate.didntIgnore = true;
			
			//Lanceer validators die betrekking hebben op het hele formulier. 
			//Deze moeten zelf eventuele error handling doen, ze worden hier enkel aangeroepen!!
			if (validate.FormValidators) 
				validate.FormValidators.each(function(func){func.bind(this)();}.bind(validate));
			
			$A($(this).getElementsByClassName('validate')).each(function(obj){
				if (!this.validateField(obj, false)) 
				{
					if (this.Debug) alert(obj.id + '-' + obj.name + '-' + obj.nodeName);
					this.errorFound = true;
					this.didntIgnore = false;
				}
			}.bind(validate));
			
			if (validate.errorFound) 
			{
				alert(validate.Errors.errors);
				//Lanceer errorhandlers die post check problemen oplossen
				//Deze moeten zelf eventuele error handling doen, ze worden hier enkel aangeroepen!!
				// Voornamelijk voor vervelende verdwijnend veld ding
				if (validate.ErrorHandlers) 
					validate.ErrorHandlers.each(function(func){func.bind(this)();}.bind(validate));
				return false;
			}
			validate.clearForm.bind(validate)();
			return true;
		},
		validateField: function(obj, live)
		{
			this.removeWarnings(obj);
			if (obj.disabled || !obj.hasClass('validate')) return true;
			required = (obj.hasClass('required'));
			confirm_ = (!required && obj.hasClass('confirm'));
			error = false;
			
			if (obj.type == 'radio')
			{
				if (!error && (required || confirm_)) error = !this.Validators.radio.bind(this)(obj);
			}
			else if (obj.type == 'checkbox')
			{
				if (!error && (required || confirm_)) error = !this.Validators.check.bind(this)(obj);
			}
			else
			{
				validities = obj.className.split('validate')[1].trim().split(' ');
				validities.each(function(check){
					if (this.Validators[check] && !this.Validators[check].bind(this)(obj)) error = true; 
				}.bind(this));
			}
			
			if (error)
			{
				if (required || obj.get('value') != '') this.showWarnings(obj);
				if (!live)
				{
					if (required) return false;
					else if (confirm_)  
					{
						if (this.didntIgnore)
						{
							this.didntIgnore = confirm(this.Errors.confirmQuestion(obj.name));
						}
						if (this.didntIgnore) this.ClearList[obj.name] = obj;
						return this.didntIgnore;
					}
					else
					{
						if (obj.get('value') != '') return false;
					}	
				}
			}
			return true;
		},
		liveValidateField: function(e)
		{
			var e = new Event(e);
			return this.validateField(e.target, true);
		},
		removeWarnings: function(obj)
		{
			if (this.noWarnings) return;
			$ES('.errorMessage', obj.parentNode).dispose();
		},
		showWarnings: function(obj)
		{
			if (this.noWarnings) return;
			if (!this.WarningList[obj.name]) return;
			error = document.createElement('UL');
			error.className = 'errorMessage';
			warnings = this.WarningList[obj.name].values().each(function(warning){
				li = document.createElement('LI');
				li.innerHTML = warning;
				error.appendChild(li);
			});
			obj.parentNode.appendChild(error);
		},
		setWarning: function(obj, cat, warning)
		{
			if (!this.WarningList[obj.name]) this.WarningList[obj.name] = $H();
			this.WarningList[obj.name][cat] = this.Errors[warning];
		},
		clearForm : function()
		{
			this.ClearList.values().each(function(field){
				$(field).clear();
			})
		},
		Validators: 
		{
			required: function(obj)
			{
				if (obj.getValue() != "") return true;
				else
				{
					this.setWarning(obj, 'required', 'required');
					return false;
				}
			},
			confirm: function(obj)
			{
				if (this.Validators.required.bind(this)(obj)) return true;
				else 
				{
					this.setWarning(obj,'required','confirm')
					return false;
				}
			},
			phone: function(obj)
			{
				var phone = obj.value.replace(/[^0-9]/g, '');
				correct = /^0([0-9]{9})$/.test(phone);
				if (!correct) this.setWarning(obj, 'phone', 'phone');
				else obj.value = phone;
				return correct;
			},
			postcode: function(obj)
			{
				var postcode = /^([0-9]{4})[ ]?([a-z]{2})$/i;
				currentValue = obj.value.trim();
				correct = postcode.test(currentValue);
				if (!correct) this.setWarning(obj, 'postcode', 'postcode');
				else obj.value = postcode.exec(currentValue)[1] + postcode.exec(currentValue)[2].toUpperCase();
				return correct;
			},
			number: function(obj)
			{
				correct = /^[0-9]+$/.test(obj.value.trim());
				if (!correct) this.setWarning(obj, 'number', 'number');
				return correct;
			},
			email: function(obj)
			{
				correct = /^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/.test(obj.value.trim());
				if (!correct) this.setWarning(obj, 'email', 'email');
				return correct;
			},
			check: function(obj)
			{
				if (!obj.checked) this.setWarning(obj,'required', 'check')
				return obj.checked;
			},
			'case': function(obj)
			{
				var value = obj.get('value').split(' ');
				for (i = 0; i < value.length; i++)
				{
					value[i] = value[i].substr(0, 1).toUpperCase() + value[i].substr(1, value[i].length + 1);
				}
				obj.set('value', value.join(' '));
				return true;
			},
			initials: function(obj)
			{
				var tekst = obj.get('value');
				var arTekst = tekst.split(' ');
				maxI = arTekst.length;
				if (maxI == 1) 
				{
					var arTekst = tekst.split('.');
					var maxI = arTekst.length;
				}
				for (i = 0; i < maxI; i++)
				{
					if (arTekst[i] == "")
					{
						arTekst.splice(i, 1);
						i--;
						maxI--;
					}
					else
					{
						if (arTekst[i].substring(arTekst[i].length - 1) != '.') arTekst[i] += '.';
							arTekst[i] = arTekst[i].substring(0,1).toUpperCase() + arTekst[i].substring(1).toLowerCase()
					}
				}
				obj.set('value',arTekst.join(' '));
				return true;
			},
			radio: function(obj)
			{
				checked = false;
				$A(document.getElementsByName(obj.name)).each(function(radio){
					if (!checked && radio.checked) 
					{
						checked = true;
					}
				});
				if (!checked) this.setWarning(obj, 'required', 'radio');
				return checked;
			},
			bsn: function (obj)
			{
				sofi = obj.value;
				sofi *= 1;
				// laatste getal van het geheel aftrekken
				tempsofi = -1 * (sofi % 10);
				sofi += tempsofi;
				sofi /= 10;
				for (i = 2; i < 10; i++)
				{
					if (i == 9 && (sofi % 10) == 0) 
					{
						tempsofi = -1;
						break;
					}; //als laatste/eerste cijfer een 0, geen 9 cijfers
					// ieder volgend nummer vermenigvuldigen met zijn omgekeerde positie en van het sofi aftrekken en bij het totaal optellen
					tempsofi += i * (sofi % 10); 
					sofi -= (sofi % 10);
					sofi /= 10;
				}
				checked = ((tempsofi % 11) == 0);// return true als het totaal veelvoud van 11 is.
				if (!checked) this.setWarning(obj, 'bsn', 'bsn');
				return checked;
			}
		},
		Errors: 
		{
			bsn: 'Dit is geen geldig BSN.',
			radio: 'Er is geen enkele radiobutton geselecteerd.',
			check: 'Deze checkbox staat niet aan.',
			required: 'Dit veld is verplicht.',
			confirm: 'Dit veld is niet verplicht, maar wel belangrijk.',
			number: 'Dit veld hoort een nummer te bevatten.',
			phone: 'Dit veld hoort een telefoonnummer te bevatten.',
			postcode: 'Dit veld hoort een postcode te bevatten.',
			email: 'Dit veld hoort een e-mailadres te bevatten.',
			errors: "Er zijn fouten gevonden in het formulier.\nCorrigeer de fouten en probeer het opnieuw.",
			confirmQuestion: function (name) {return "Het veld " + name + " is niet (correct) ingevuld.\nHoewel dit veld invullen niet vereist is, zou het toch op prijs gesteld worden als u het deed.\n\nDit veld negeren en leeg opsturen?";}
		},
		didntIgnore: true,
		noWarnings: false,
		ClearList: $H(),
		WarningList: $H()
	},
	Intelligence:
	{
		initIntelligentForms: function()
		{
			//$$('accessability')
			this.Rules.each(function(n, key, value){
				value.values().each(function(selectors){
					this.disableForCSSSelectors(selectors);
				}.bind(this))
				$$(document.getElementsByName(key)).each(function(field){
					switch (field.type)
					{
						case 'checkbox':
						case 'radio':
							field.addEvent('click', this.updateForm.bindWithEvent(this));
						break;
						default:
							field.addEvent('change', this.updateForm.bindWithEvent(this));
					}
					this.updateForm(field);
				}.bind(this));
			}.bind(this))
		},
		disableForCSSSelectors: function(array)
		{
			array.each(function(selector){
				$$(selector).each(function(container){
					container.setStyle('display','none');
					if (container.nodeName == 'INPUT' || container.nodeName == 'SELECT' || container.nodeName == 'TEXTAREA')
					{
						container.set("disabled", true);
					}
					else
					{
						$ES('input, select, textarea', container).set('disabled', true);
					}
				}.bind(this));
			}.bind(this));
		},
		enableForCSSSelectors: function(array)
		{
			array.each(function(selector){
				$$(selector).each(function(container){
					if (container.nodeName == 'INPUT' || container.nodeName == 'SELECT' || container.nodeName == 'TEXTAREA')
					{
						container.set('disabled', false);
						this.updateForm(container);
					}
					else
					{
						is = $ES('input, select', container).set('disabled', false);
						$ES('textarea', container).set('disabled', false);
						is.each(function(field){this.updateForm(field)}.bind(this));
					}
					container.setStyle('display', '');
				}.bind(this));
			}.bind(this));
		},
		updateForm: function(e, currentValue)
		{
			if (!e.nodeName) {
				var e = new Event(e);
				obj = e.target;
			}
			else obj = e;
			
			if (!this.Rules.has(obj.name)) return;
			if (obj.type == 'radio' && !obj.checked)
			{
				checked = false;
				$A(document.getElementsByName(obj.name)).each(function(radio){
					if (!checked && radio.checked) 
					{
						checked = true;
					}
				});
				if (!checked) currentValue = '_empty';
				else return;
			}
			//checkboxes worden behandeld als individuele toggles
			if (obj.type == 'checkbox') 
			{
				value = obj.value;
				altValue = value;
				if (obj.checked) altValue = '__' + value;
				else value = '__' + value;
				rules = this.Rules.get(obj.name);
				if (rules.has(altValue)) this.disableForCSSSelectors(rules[altValue]);
				if (rules.has(value)) this.enableForCSSSelectors(rules[value]);
				return;
			}
			if (currentValue == null) currentValue = $(obj).get('value');
			if (obj.nodeName == 'SELECT' && currentValue == '') currentValue = '_empty';
			show = [];
			this.Rules.get(obj.name).each(function(value, key){
				if (key == '__forall' && currentValue != '_empty') {
					show = value;
					return;
				}
				if (key.substring(0,2) == '__')
				{
					if (key.substring(2) != currentValue && currentValue != '_empty') show = value;
					else this.disableForCSSSelectors(value);
				}
				else
				{
					if (key == currentValue) show = value;
					else this.disableForCSSSelectors(value);
				}
			}.bind(this));
			this.enableForCSSSelectors(show);
		},
		Rules: $H()
	},
	Helpers:
	{
		initHelpers: function()
		{
			this.Validate = ROCForm.Validate; // Deze moet verwijzen naar het huidige object.
			this.Links.each(function(links, link_name){
				if (document.getElementsByName(link_name)[0]) obj = $(document.getElementsByName(link_name)[0]);
				else return;
				links.each(function(actions, action_class){
					actions.each(function(helper){				
						obj.addEvent(action_class,this.Functions[helper].bindWithEvent(this));
						this.Functions[helper].bind(this)(obj);
					}.bind(this));
				}.bind(this));
			}.bind(this));
		},
		Functions:
		{
			postcodeAjax: function(e)
			{
				if (e.nodeName) obj = e;
				else {
					var e = new Event(e);
					obj = e.target;
				}
				if (obj.disabled) return;
				prefix = '__def';
				if (obj.name.indexOf('_') != -1) prefix = obj.name.substr(0,obj.name.indexOf('_'));
				if (!this.postcodeStore.has(prefix)) this.postcodeStore.set(prefix, $H());
				this.Validate.noWarnings = true;
				if (!this.Validate.validateField.bind(this.Validate)(obj,false)) 
				{
					$ES('.adres', obj.parentNode).set('text','');
					this.Validate.noWarnings = false;
					return;
				}
				this.Validate.noWarnings = false;
				update = false;
				if (obj.hasClass('postcode') && /^([0-9]{4})([A-Z]{2})$/.test(obj.get('value')) && this.postcodeStore[prefix].get('postcode') != obj.get('value')) 
				{
					update = true;
					this.postcodeStore[prefix].set('postcode', obj.get('value'));
				}
				if (obj.hasClass('huisnummer') && /^([0-9]+)$/.test(obj.get('value')) && this.postcodeStore[prefix].get('nummer') != obj.get('value')) 
				{
					update = true;
					this.postcodeStore[prefix].set('nummer', obj.get('value'));
				}
				if (!update || !this.postcodeStore[prefix].has('postcode') || !this.postcodeStore[prefix].has('nummer')) return;
				postcode = this.postcodeStore[prefix].postcode;
				huisnummer = this.postcodeStore[prefix].nummer;
				var nummers = postcode.substr(0,4);
				var letters = postcode.substr(4,2);
				var rand = Math.round(Math.random()*899) + 100;
			  	if (location.host.match('rocmn.nl') == null || (location.host == 'aanmeldenvavo.rocmn.nl')) var a = "http://" + location.host + "/postcode.php?l=" + letters + "&n=" + nummers + "&h=" + huisnummer;
				else var a = "http://" + location.host + "/smartsite.dws?id=35865&l=" + letters + "&n=" + nummers + "&r=" + rand + "&h=" + huisnummer + "&o=" + (huisnummer % 2 == 0 ? 1 : 0);
				var req = new Request({url: a}); 
				req.addEvent('onSuccess', function(t){
					//$ES('.adres', this.parentNode).dispose();					
					cnt = t.substr(9);
					prefix = '';
					if (this.name.indexOf('_') != -1) prefix = this.name.substr(0,this.name.indexOf('_')) + '_';
					adres = $(prefix + 'adresVeld')
					sep = cnt.indexOf('|x|');
					straatnaam = cnt.substr(0, sep).trim();
					woonplaats = cnt.substr(sep + 3).trim();
					adres.set('html',straatnaam + '<br />' + woonplaats);
					new Element('input', {'type':'hidden', 'name': prefix + 'straatnaam', 'value': straatnaam}).inject(adres);
					new Element('input', {'type':'hidden', 'name': prefix + 'woonplaats', 'value': woonplaats, 'class':(this.hasClass('required') ? 'validate required' : '')}).inject(adres);
					//adres.inject(this.parentNode);
				}.bind(obj));
				//$ES('.adres', obj.parentNode).dispose();
				if (!$((prefix == '__def' ? '' : prefix + '_') + 'adresVeld')) adres = new Element('div', {'html': 'Bezig met opzoeken postcode', 'class': 'adres', 'id':'adresVeld'}).inject(obj.parentNode);
				else adres = $((prefix == '__def' ? '' : prefix + '_') + 'adresVeld').set('text','Bezig met opzoeken postcode');
				
				new Element('input', {'type':'hidden', 'name': (prefix == '__def' ? '' : prefix + '_') + 'woonplaats', 
					'value': '', 'class':(obj.hasClass('required') ? 'validate required' : '')}).inject(adres);
				//adres.inject(obj.parentNode);
				req.send('');
			}
		},
		Links: $H({
			postcode: $H({
				blur: ['postcodeAjax']
			}),
			huisnummer: $H({
				blur: ['postcodeAjax']
			})
		}),
		postcodeStore:$H()
	},
	Layout: {
		valueHide: {
			init: function()
			{
				$$('#pagecontent form.valuelabel input').each(this.procElement, this);
				$$('#pagecontent form.valuelabel textarea').each(this.procElement, this);
				if (!ROCForm.Validate.FormValidators)
					ROCForm.Validate.FormValidators = $H();
				if (!ROCForm.Validate.ErrorHandlers)
					ROCForm.Validate.ErrorHandlers = $H();
				ROCForm.Validate.FormValidators.valueHide = this.preSubmit;
				ROCForm.Validate.ErrorHandlers.valueHide = this.postSubmit;
			},
			procElement: function(el){
				if (el.type == 'hidden' || el.type == 'submit' || el.type == 'reset' || el.type == 'button') return;
				if (!el._emptyValue && el.parentNode.nodeName == 'LABEL')
				{
					el._emptyValue = $(el.parentNode).get('text');
					$A(el.parentNode.childNodes).each(function(node) {
						if ($type(node) == 'textnode') node.parentNode.removeChild(node);
					});
					if (el.get('value') == '')
						el.set('value', el._emptyValue);
				}
				if (!el._emptyValue) el._emptyValue = el.get('value');
				el._filledIn = (el._emptyValue != el.get('value'));
				el.addEvent('focus', function(){
					if (!this._filledIn)
					{
						this.value = '';
					}
				}, el);
				el.addEvent('blur', function(){
					if (this.getValue() == '')
					{
						this.value = this._emptyValue;
						this._filledIn = false;
					}
					else
					{
						this._filledIn = true;
					}
				}, el);
			},
			postSubmit: function() {
				$$('#pagecontent form.valuelabel input').each(ROCForm.Layout.valueHide.fillElement, this);
				$$('#pagecontent form.valuelabel textarea').each(ROCForm.Layout.valueHide.fillElement, this);
			},
			preSubmit: function () {
				$$('#pagecontent form.valuelabel input').each(ROCForm.Layout.valueHide.clearElement, this);
				$$('#pagecontent form.valuelabel textarea').each(ROCForm.Layout.valueHide.clearElement, this);
			},
			clearElement: function (el) {
				if (el._emptyValue && !el._filledIn) el.set('value', '');
			},
			fillElement: function (el) {
				if (el._emptyValue && !el._filledIn) el.set('value', el._emptyValue);
			}
		}
	}
};

$(window).addEvent('domready', function () {
	ROCForm.Validate.initLiveValidation();
	ROCForm.Intelligence.initIntelligentForms();
	ROCForm.Helpers.initHelpers();
	ROCForm.Layout.valueHide.init();
});
