/***************************************************************
* STATIC LINKS
*
* Acts like abstract-class (no inheritance whatsoever) so 
* every script can access it
*
***************************************************************/

StaticLink = new Object();
StaticLink.repository = new Hash();
StaticLink.initialize = function(){
	$$('.staticLink').each(function(elem){
		elem.observe('click',StaticLink.eventHandler);
	});
	$$('a').each(function(elemObj){
		if(!elemObj.hasClassName('staticLink')){
			elemObj.observe('click', function(eventObject){
				if(this.readAttribute('href')){
					StaticLink.redirectDirect(this.readAttribute('href'),this.readAttribute('target'));
				}
				eventObject.stop();
				return false;
			});
		}
	});
}
StaticLink.setLink = function(linkRef,targetUrl) {
	StaticLink.repository.set(linkRef,targetUrl);
}
StaticLink.getLink = function(linkRef) {
	StaticLink.repository.get(linkRef);
}
StaticLink.eventHandler = function(e) {
	var reqLink = e.target.getAttribute('linkRef');
	StaticLink.redirect(reqLink);
}
StaticLink.redirect = function(linkRef) {
	// TODO : improve script with external window feature
	if(!StaticLink.repository.get(linkRef)) return false;
	var reposResult = StaticLink.repository.get(linkRef);
	StaticLink.redirectDirect(reposResult);
}

StaticLink.redirectDirect = function(URLPath,target) {
	if(URLPath.charAt(0) == '#') {
		document.location.hash = URLPath.substr(1);
	} else {
		var baseURL = '';
		$$('base').each(function(element) {
			baseURL = element.readAttribute('href');
		},this);
		if(!URLPath.match(/\:\/\/|mailto\:/)) {
			URLPath=baseURL+URLPath;
		}
		target ? window.open(URLPath,target) : (document.location.href = URLPath);
	}
}


// E-MAIL HANDLING

var emptyString = /^\s*$/ ;
var proceed = 2;

function evalForm(formId,validationScript) {
	if ((validationScript == "") || eval(validationScript)) {
		document.getElementById(formId).submit();
	}
}

function commonCheck(valfield, required) {
	if (!document.getElementById)  return true; 
	if (emptyString.test(valfield.value)) {
		if (required) {
			setfocus(valfield);
			return false;
		}
		else {
			return true;  
		}
	}
	return proceed;
}

function validatePresent(valfield) {
  var stat = commonCheck(valfield, true);
  if (stat != proceed) return false;
  return true;
}
function validateEmail  (valfield, required) {
	var tfld = trim(valfield.value); 
	var email = /^[^@]+@[^@.]+\.[^@]*\w\w$/  ;
	if (!email.test(tfld)) {
		setfocus(valfield);
		return false;
	}
	var email2 = /^[A-Za-z][\w.-]+@\w[\w.-]+\.[\w.-]*[A-Za-z][A-Za-z]$/  ;
	return true;
}
function validateTelnr  (valfield, required) {
	var tfld = trim(valfield.value);  
	var telnr = /^\+?[0-9 ()-]+[0-9]$/  ;
	if (!telnr.test(tfld)) {
		setfocus(valfield);
		return false;
	}
	var numdigits = 0;
	for (var j=0; j<tfld.length; j++)
	if (tfld.charAt(j)>='0' && tfld.charAt(j)<='9') numdigits++;
	if (numdigits<6) {
		setfocus(valfield);
		return false;
	}
	return true;
}

function trim(str) { return str.replace(/^\s+|\s+$/g, ''); }

function setFocusDelayed() { global_valfield.focus(); }
function setfocus(valfield) {
	global_valfield = valfield;
	setTimeout('setFocusDelayed()',100);
}

/* ---------------------------------------------------------------- //
// CONFIRM                                                          //
// ---------------------------------------------------------------- */

function initiate_confirm(e){
	var elem = e.target;
	var confirmMessage = elem.getAttribute("confirmMessage").replace(/\\n/,"\n");
	if(!confirmMessage) return false;
	if(!confirm(confirmMessage)) {
		window.event? event.returnValue = false : e.preventDefault();
		return false;
	}
}

/***************************************************************
* DOM EVENT LISTNERS
***************************************************************/
document.observe('dom:loaded', function(event){
	StaticLink.initialize();
	$$('.confirmBox').each(function(elem){elem.observe('click',initiate_confirm)});
});

/* slideshow */

var SlideShow = Class.create({
	timeout: 850,
	slideshow: null,
	slides: [],
	current: 0,
	initialize: function(slideshow,timeout){
		this.slideshow = $(slideshow);
		if(!this.slideshow) return false;
		this.slides = this.slideshow.select('img');
		this.current = this.slides.length-1;
		this.timeout = timeout;
		setTimeout((function(){this.next();}).bind(this), this.timeout);
	},
	next: function() {
		for (var i = 0; i < this.slides.length; i++) {
			var slide = this.slides[(this.current + i) % this.slides.length];
			slide.style.zIndex = this.slides.length - i;
		}
		Effect.Fade(this.slides[this.current], {
			afterFinish: function(effect) {
				effect.element.style.zIndex = 0;
				Element.show(effect.element);
				Element.setOpacity(effect.element, 1);
			}
		});
		this.current = (this.current + 1) % this.slides.length;
		setTimeout((function(){this.next();}).bind(this), this.timeout + 850);
	}
});


document.observe('dom:loaded', function(eventObject) {
	$$('.slideshow').each(function(elem){new SlideShow(elem, 9000)});	
});

/* Fotoalbum */

var images = {

	settings: {
		extraWidth: 2,
		extraHeight: 2
	},
	
	initialize: function(){
		console.log('initializing images');
		$$('a.imageContainerController').invoke('observe','click',images.click_controller);		
		$$('a.selectImg').invoke('observe','click',images.click_image);
		$$('.imageContainer.horizontal .imageContainerSlider').each(function(imageContainerSlider){
			imageContainerSlider.setStyle({
				width: (imageContainerSlider.select('a').length * (parseInt(imageContainerSlider.select('a')[0].getDimensions().width) + images.settings.extraWidth)) + 'px'
			});
		});
		$$('.imageContainer.vertical .imageContainerSlider').each(function(imageContainerSlider){
			imageContainerSlider.setStyle({
				height: (imageContainerSlider.select('a').length * parseInt(imageContainerSlider.select('a')[0].getDimensions().height)) + 'px'
			});
		});
		// verbergen van de controller knoppen / elementen als ze niet nodig zijn
		$$('.imageContainer').each(function(elem){
			if(elem.hasClassName('horizontal')){
				if(elem.select('.imageContainerSlider')[0].getDimensions().width <= elem.getDimensions().width){
					$$('.imageContainerController[imageContainer=' + elem.readAttribute('id') + ']').invoke('hide');
				}
			} else if(elem.hasClassName('vertical')) {
				if(elem.select('.imageContainerSlider')[0].getDimensions().height <= elem.getDimensions().height){
					$$('.imageContainerController[imageContainer=' + elem.readAttribute('id') + ']').invoke('hide');
				}
			}
		});
	},
	click_controller: function(eventObject){
		var imageContainer = $(this.readAttribute('imageContainer'));

		if(!imageContainer) {
			return false;
		};
		var action = this.readAttribute('action');
		var imageContainerSlider = imageContainer.select('.imageContainerSlider')[0];
		var imageDimension, moveByChanging, sliderDimension, containerDimension;
		if(imageContainer.hasClassName('horizontal')){
			imageDimension = parseInt(imageContainerSlider.select('a')[0].getDimensions().width) + 2;
			sliderDimension = imageContainerSlider.getDimensions().width;
			containerDimension = imageContainer.getDimensions().width;
			moveByChanging = 'left';
		} else {
			imageDimension = parseInt(imageContainerSlider.select('a')[0].getDimensions().height);
			sliderDimension = imageContainerSlider.getDimensions().height;
			containerDimension = imageContainer.getDimensions().height;
			moveByChanging = 'top';
		}
		console.log(imageContainerSlider,imageDimension,sliderDimension,containerDimension,moveByChanging);
		if(!(imageDimension && moveByChanging)) {
			console.log('Could not determine imageheight or width. Does the imageContainer have a class horizontal or vertical?');
			return false;
		}
		if(action == 'first'){
			new Effect.Morph(imageContainerSlider, {
				style: moveByChanging + ':0px;',
				duration: 0.5 
			});
		};
		if(action == 'previous'){
			
			var currentPosition = parseInt(imageContainerSlider.getStyle(moveByChanging).replace(/[^\d\-]/g,''));
			var targetPosition = ((currentPosition + imageDimension) <= 0) ? (currentPosition+imageDimension) : 0;
			new Effect.Morph(imageContainerSlider, {
				style: moveByChanging + ':' + targetPosition + 'px;',
				duration: 0.5 
			});
		};
		if(action == 'next'){
			var currentPosition = parseInt(imageContainerSlider.getStyle(moveByChanging).replace(/[^\d\-]/g,''));
			var minDimension = (-sliderDimension + containerDimension);
			var targetPosition = ((currentPosition - imageDimension) >= minDimension) ? (currentPosition-imageDimension) : minDimension;
			new Effect.Morph(imageContainerSlider, {
				style: moveByChanging + ':' + targetPosition + 'px;',
				duration: 0.5 
			});
		};
		if(action == 'last'){
			new Effect.Morph(imageContainerSlider, {
				style: moveByChanging + ':' + (-sliderDimension + containerDimension) + 'px;',
				duration: 0.5 
			});
		};

	},
	click_image: function(eventObject){
		var targetImg = $(this.readAttribute('targetImg'));
		if(targetImg) {
			targetImg.setAttribute('src',this.readAttribute('bigImg'));
		}
	}
}
	
Event.observe(window,'load',images.initialize);

/* formulieren */

var formValidation = {
	errorClass: 'error'
};




























// Deze client-sided validator treft integratie met de serversided validator
// en is verantwoordelijk voor het tegenhouden van foutief intevulde formulieren.
//
// deze javascript validator wordt gevoed door de php validator.
// Zodoende zie je hier geen inhoudelijke toepassingen / expressies etc.
//
// dit script wordt automatisch gebruikt door bouwpakket en is dus
// verplicht mee te draaien.

var validator = Class.create({
	
	_pathUpToErrorElem: 'div, tr, table',
	_errorClass: 'JS_checkInput',
	_errorClassForm: 'JS_formValidatedFalse',
	_validationTypes: {},
	_validationFields: {},
	_observers: [],
	_formName: '',
	__form: '',
	__formElements: [],
	
	consoleMessages: {
		info: {
			matchFailed: 'field did not pass validation',
			preventedSubmit: 'prevented the field from submitting',
			attachedObserver: 'attached an extra observer'
		},
		warning: {
			illegalValidationMethod: 'could not validate field due to unknown validationmethod',
			invalidPattern: 'Pattern was not a proper regular expression',
			unknownCallback: 'Callbackfunction not found'
		},
		error: {
			noFormName: 'validation called without formname, aborting',
			formNotFound: 'The form could not be found, aborting validation'
		}
	},
	
	// deze functie verwacht een formuliernaam (welke ook daadwerkelijk in de HTML zo moet staan)
	initialize: function(formName){
		this._formName = formName;
		if(!this._formName) {
			console.error(this.consoleMessages.error.noFormName);
			return false;
		};
		document.observe('dom:loaded',this.__attachElements.bind(this));
	},
	
	__attachElements: function(eventObject){
		// sla het formulier in de lokale scope van het object op
		this.__form = $$('form[name=' + this._formName + ']')[0];
		if(!this.__form){
			console.error(this.consoleMessages.error.formNotFound, this._formName);
			return;
		}
		// sla de onderliggende elementen in de lokale scope van het object op
		this.__formElements = this.__form.select('input','textarea','select','button');
		
		// indien er eventuele observers voor formulier-elementen zijn willen we deze graag attachen
		this.__formElements.each(this.__attachPossibleObservers,this);
		
		// indien het formulier verzonden word willen we inhaken om te kijken of het wel voldoet
		// aan de voorwaarden om verzonden te mogen worden
		this.__form.select('input[type=submit]','input[type=button]','submit','button','input[type=image]')
					.invoke('observe','click',this.__attemptSubmit.bind(this));
		
		// vuur een event op alle elementen zodat we zeker weten dat de beginsituatie
		// nooit verschilt van de interactieve situatie
		this.__formElements.invoke('fire','validation:initialized');
	},
	
	// attach mogelijke observers 
	__attachPossibleObservers: function(formElem){
		var elemName = formElem.readAttribute('name');
		if(elemName){
			this._observers.each(function(observer){
				if(observer.field == elemName) {
					var callback = eval(observer.callback);
					if(!callback) {
						console.warn(this.consoleMessages.warning.unknownCallback);
					}
					else {
						// attach op de elementen de callback, en een extra event welke zal
						// worden getriggered na de load van het hele formulier ( op
						// die manier weten we zeker dat begin situatie ook klopt)
						formElem.observe(observer.event, bekendVan);
						formElem.observe('validation:initialized', bekendVan);
					}
				}
			});
		}
	},
	
	__attemptSubmit: function(eventObject){
		var preventSubmit = false;
		// doorloop ieder formelement voor eventuele problemen
		var formElements = this.__formElements;
		
		// groepeer waar nodig elementen (zoals bij checkboxes en datumvelden (Y,m,d,H,i)
		var combinedElements = {};
		formElements.each(function(formElem){
				var originalName = formElem.readAttribute('name');
				if(originalName){
					var name = originalName.replace(/\[[Y|m|d|H|i]{0,1}\]/g,'');
					if(combinedElements[name]) {
						if(Object.isArray(combinedElements[name])) {
							combinedElements[name].push(formElem);
						} else {
							combinedElements[name] = [combinedElements[name],formElem];
						}
					} else {
						combinedElements[name] = formElem;
					}
				}
			});

		$H(combinedElements).each(function(elem){
				var name = elem.key;
				var formElem = elem.value;
				
				//console.log(this._validationFields,name,this._validationFields.get(name));
				if(this._validationFields.get(name)){
					
					// bepaal de waarde van het veld. Indien het een checkbox is (en dus meerdere waarden
					// in arrayvorm kan teruggeven) willen we de waarden concateneren zodat we er alsnog
					// een reguliere expressie op los kunnen laten
					if(Object.isArray(formElem)){
						var fieldValue = formElem.invoke('getValue').compact().join(',');
					} else {
						var fieldValue = formElem.getValue();						
					}
					
					// valideer het veld tegen de bekende valideermethode
					if(this._validationTypes[this._validationFields.get(name)]){
						// maak van de regexp (nu nog een string) een echte regexp
						var matchAgainst = this._validationTypes[this._validationFields.get(name)];
					}
					// er is wel verteld dat er gevalideerd moet worden maar de methode was niet bekend
					// valideer hem als zijnde 'goed' (we willen immers niet dat het formulier hier op blijft hangen)
					else {
						console.warn(
							this.consoleMessages.warning.illegalValidationMethod,
							': ' + name
						);
						return;
					}
					
					// indien de formwaarde opgebouwd is door meerdere elementen willen we de error genereren
					// vanaf het eerste element
					var queryElem = Object.isArray(formElem) ? formElem[0] : formElem;
					switch(matchAgainst.type){
						// standaardvalidatie van 1 veld tegen 1 regex
						case 'match':
							// controleer of het een goed patroon is
							var pattern = eval(matchAgainst.pattern);
							if(!pattern) {
								console.warn(this.consoleMessages.warning.invalidPattern, matchAgainst.pattern);
								return;
							}
							
							// indien het veld goed door de validatie heenkomt
							if(fieldValue && fieldValue.match(pattern)){
								queryElem.up(this._pathUpToErrorElem).removeClassName(this._errorClass);
							}
							// indien het veld niet goed door de validatie heenkomt
							else {
								console.info(this.consoleMessages.info.matchFailed, fieldValue, formElem, matchAgainst);
								queryElem.up(this._pathUpToErrorElem).addClassName(this._errorClass);
								preventSubmit = true;
							}
							break;
						// validatie van een veld tegen een regex en vervolgens een vergelijking tussen waarden van 1 veld tov een ander veld
						case 'matchAndEqual':
							// controleer of het een goed patroon is
							var pattern = eval(matchAgainst.pattern);
							if(!pattern) {
								console.warn(this.consoleMessages.warning.invalidPattern, matchAgainst.pattern);
								return;
							}
							// controleer of veld 1 voldoet aan de regex
							if(fieldValue && fieldValue.match(pattern)){
								combinedElements[name].up(this._pathUpToErrorElem).removeClassName(this._errorClass);
							}
							else {
								console.info(this.consoleMessages.info.matchFailed, fieldValue, formElem, matchAgainst);
								queryElem.up(this._pathUpToErrorElem).addClassName(this._errorClass);
								preventSubmit = true;
							}
							// controleer of veld 2 (naam 1 + suffix) voldoet aan veld 1
							if(combinedElements[name].getValue() == combinedElements[name+matchAgainst.suffix].getValue()){
								combinedElements[name+matchAgainst.suffix].up(this._pathUpToErrorElem).removeClassName(this._errorClass);
							}
							else {
								console.info(this.consoleMessages.info.matchFailed, fieldValue, formElem, matchAgainst);
								combinedElements[name+matchAgainst.suffix].up(this._pathUpToErrorElem).addClassName(this._errorClass);
								preventSubmit = true;
							}
							break;
						case 'date':
							// lees uit welke datum het momenteel is
							var currentlySelected = {
								year: formElem.find(function(elem){ return elem.readAttribute('name').match(/\[Y\]/); }).getValue(),
								month: formElem.find(function(elem){ return elem.readAttribute('name').match(/\[m\]/); }).getValue(),
								day: formElem.find(function(elem){ return elem.readAttribute('name').match(/\[d\]/); }).getValue()
							};
							
							// bepaal de laatste dag binnen deze maand van het jaar
							var dd = new Date(currentlySelected.year, currentlySelected.month, 0);
							var lastDayOfMonth = dd.getDate();
							
							// nu kijken we of de huidige dag binnen de datum een geldige dag is
							if(currentlySelected.day > lastDayOfMonth) {
								console.info(this.consoleMessages.info.matchFailed, fieldValue, formElem, currentlySelected);
								formElem[0].up(this._pathUpToErrorElem).addClassName(this._errorClass);
								preventSubmit = true;
								break;
							}
							else {
								formElem[0].up(this._pathUpToErrorElem).removeClassName(this._errorClass);
							}
							
							// indien alle velden minimaal ingevuld moeten zijn
							if(matchAgainst.required){
								if(!currentlySelected.year || !currentlySelected.month || !currentlySelected.day){
									console.info(this.consoleMessages.info.matchFailed, fieldValue, formElem, currentlySelected);
									formElem[0].up(this._pathUpToErrorElem).addClassName(this._errorClass);
									preventSubmit = true;
									break;
								}
								else {
									formElem[0].up(this._pathUpToErrorElem).removeClassName(this._errorClass);
								}
							}
							break;
						case 'callback':
							var callbackFunction = eval(matchAgainst.callback);
							if (callbackFunction) {
								// hier binden we de scope van de validator aan
								// de externe callbackfunctie
								callbackFunction = callbackFunction.bind(this);
								var callbackResult = callbackFunction(name, formElem);
								if (!callbackResult) {
									// Callback functies zijn uit zichzelf complex en dragen de
									// verantwoordelijkheid om zelf de highlighting van de elementen
									// te regelen
									console.info(
										this.consoleMessages.info.matchFailed,
										formElem,
										matchAgainst,
										callbackFunction,
										callbackResult
									);
									preventSubmit = true;
								}
							}
							else {
								preventSubmit = true;
							}
							break;
					}
				}
			},this);
		// voorkom dat het formulier verzonden word indien een veld niet aan de voorwaarden heeft voldaan
		if(preventSubmit) {
			// indien de validatie niet is geslaagd geven we het formulier een extra class mee
			// zodat mogelijke errormessages kunnen worden weergegeven
			this.__form.addClassName(this._errorClassForm);
			console.info(this.consoleMessages.info.preventedSubmit);
			eventObject.stop();
			return false;
		} else {
			// we halen de errorclass van het formulier af, dit doen we omdat mogelijke foutmeldingen
			// niet moeten blijven staan gedurende de tijd dat de pagina aan het submitten is.
			this.__form.removeClassName(this._errorClassForm);
		}
		return true;
	},
	
	// nieuwe validatietypen aanmelden
	loadValidationTypes: function(validationTypes) {
		this._validationTypes = validationTypes;
	},
	
	// nieuwe velden om te valideren aanmelden
	loadValidationFields: function(validationFields) {
		console.log('attaching observers',validationFields);
		this._validationFields = $H(validationFields);
	},
	
	// stelt ons in staat extra observaties op waarden van elementen te doen
	attachObservers:  function(observers){
		this._observers = observers;
	}
	
});

