/* === gelriaselect.js === */


(function($) {
	$.extend( {
		
		config: (function() {
			// Put config settings in configObj (private):
			var confObj = {
				printLabel:			"Print",
				siteSearchEmpty:	"U heeft geen zoekterm opgegeven.\nVul een of meerdere zoektermen in en klik op \"zoeken\", of druk op Enter.",
				jsLinks:			{	// actual [link text] between square brackets
										back:		"Ga [terug].",
										close:		"[Sluit venster]"
									},
				searchForm:			{
										checkAll:	true,
										label:		"Alles selecteren",
										infoIcon:	"images/ico_info.png"
									},
				reqPassword:		{
										forgotLink:	"Wachtwoord vergeten?",
										backLink:	"Terug naar inloggen"
									},
				nlMonths:			[ "januari", "februari", "maart", "april", "mei", "juni", "juli", "augustus", "september", "oktober", "november", "december" ],
				tabMapSearch: {
					label: "Zoek op kaart",
					id: "kaart",
					qsParams: {tabaan: "kaart"},
					afterId: "tab_naam"
				},
				mapSearch: {
					wrapperId: "mapSearch",
					hash: {
						map: "#map_search",
						searched: "#map_searched"
					},
					zoom: 9,
					bounds: {
						north: 52.2561055478495,
						east: 6.279287563842786,
						south: 51.73286439778115,
						west: 4.963674770874036
					},
					infoWindow: {
						contentClassName: "infoContent",
						lists: [	// order + list headers
							{"vacatures": "Vacatures"},
							{"stages": "Stageplaatsen"},
							{"vrijwilligers": "Vrijwilligersvacatures"}
						]
					},
					dev: false // development
				}
			};
			
			// Private methods:
			var extend = function(conf, callbacks) {
				if (!conf || typeof conf !== "object") { return; }
				var proceed;
				for (var key in conf) {
					proceed = true;
					if (callbacks) {
						// Call appropriate callback function, if specified:
						if (confObj[key] && callbacks.onAlter) { proceed = callbacks.onAlter(key, conf[key], confObj[key]); }
						else if (!confObj[key] && callbacks.onAdd) { proceed = callbacks.onAdd(key, conf[key]); }
					}
					// Set value, unless callback function returned false:
					if (proceed || proceed == null) { confObj[key] = conf[key]; }
				}
			};
			var get = function(key) {
				return key ? confObj[key] : confObj;
			};
			
			// Interface:
			return {extend: extend, get: get};
		})(),
		
		addMapSearchTab: function($tabs) {
			var mapSearchTab = $.config.get("tabMapSearch"),
				$prevTab,
				location = window.location,
				qs = "",
				page,
				pattern = /[\?&]+(p|alias|tabaan)\=([^&]*)/g,
				params = mapSearchTab.qsParams || {},
				selected = "",
				href = "",
				tab;
				
			if (mapSearchTab && mapSearchTab.id /*&& $("#link_" + mapSearchTab.id).length > 0*/) {
				$prevTab = mapSearchTab.afterId ? $("#" + mapSearchTab.afterId) : $tabs.find("li:last-child");
				$prevTab = $prevTab.length ? $prevTab : $tabs.find("li:last-child");
				
				qs = location.search;
				while ((page = pattern.exec(qs)) != null) {
					if (page[1] == "p" || page[1] == "alias") {
						params[page[1]] = page[2];
					} else if (page[1] == "tabaan" && page[2] == "kaart") {
						selected = ' class="selected"';
					}
				}
				href = location.pathname + "?" + $.param(params);
				tab = document.createDocumentFragment().innerHTML = '<li id="tab_' + mapSearchTab.id + '"' + selected + '><a href="' + href + '">' + mapSearchTab.label + '</a></li>';
				
				if ($prevTab.length) {
					$prevTab.after(tab);
				} else {
					$tabs.append(tab);
				}
			}
		},
		
		maps: {},
		infoWinOpen: {},
		
		initSearchMap: function() {
			var mapConf = $.config.get("mapSearch"),
				gm = window.google && window.google.maps,
				mapOptions = {},
				map,
				bounds,
				wrapper,
				devLog,
				$form;
			
			// is configuration available and is the map not yet initiated?
			if (gm && mapConf && mapConf.wrapperId && $.maps && !$.maps[mapConf.wrapperId]) {
				wrapper = document.getElementById(mapConf.wrapperId);
				bounds = mapConf.bounds;
				bounds.sw = new gm.LatLng(bounds.south, bounds.west);
				bounds.ne = new gm.LatLng(bounds.north, bounds.east);
				bounds.box = new gm.LatLngBounds(bounds.sw, bounds.ne);
				if (wrapper && bounds.box) {
					mapOptions.zoom = mapConf.zoom || 1;
					mapOptions.center = bounds.box.getCenter();
					mapOptions.mapTypeId = google.maps.MapTypeId.ROADMAP;
					
					map = new gm.Map(wrapper, mapOptions);
					$.maps[mapConf.wrapperId] = {map: map, center: mapOptions.center};
					
					/* --- for development only --- */
					if (mapConf.dev && (/\.sebastian\.nl/i).test(window.location.hostname)) {
						devLog = (function() {
							return (typeof console != "undefined" && console.log) ? console.log : alert;
						}());
						
						gm.event.addListener(map, "click", function(pos) {
							devLog("latLng: " + pos.latLng.toString());
						});
						
						gm.event.addListener(map, "zoom_changed", function() {
							devLog("zoom: " + map.getZoom());
						});
					}
					
					$form = $(wrapper).closest("form");
					$.initMarkerUpdate(map, $form);
					$.initMapFinalState(mapConf, $form);
				}
			}
		},
		
		initMarkerUpdate: function(map, $form) {
			var mapConf = $.config.get("mapSearch"),
				hashConf = mapConf.hash,
				infoConf = mapConf.infoWindow,
				gm = google.maps,
				markers = [],
				//$.infoWinOpen = {},
				xhr,
				xhrOptions = {
					dataType: "json",
					type: $form.attr("method"),
					url: $form.attr("action"),
					success: function(data, status, xhr) {
						updateMarkers(data);
						window.location.hash = hashConf.searched;
					},
					beforeSend: function(ajaxObj) {
						if (xhr) {
							xhr.abort();
						}
						xhr = ajaxObj;
					}
				},
				hash = window.location.hash;
				
			function removeMarkers() {
				if ($.infoWinOpen.win) {
					$.infoWinOpen.win.close();
				}
				for (var i = 0, length = markers.length; i < length; i += 1) {
					markers[i].setMap(null);
				}
				markers = [];
			}
			
			function createMarker(loc) {
				var marker = new gm.Marker({
					position: new gm.LatLng(parseFloat(loc.lat), parseFloat(loc.lng)),
					map: map,
					title: loc.naam || loc.naam_fallback
				});
				markers.push(marker);
				return marker;
			}
			
			function createInfoWindow(loc, marker, locId) {
				var contentHTML = "",
					addressHTML = "",
					descrHTML = "",
					linkHTML = "",
					lists = infoConf.lists,
					infoWindow;
					
				function createLists() {
					var list,
						listName,
						listOrder = [],
						listHeaders = {},
						listsLength,
						showHeaders,
						itemsHTML = "",
						listItem,
						listsHTML = "";
						
					for (var i = 0, length = lists.length; i < length; i += 1) {
						//list = lists[i];
						for (listName in lists[i]) {
							if (loc[listName]) {
								listOrder.push(listName);
								listHeaders = $.extend(listHeaders, lists[i]);
							}
						}
					}
					
					listsLength = listOrder.length;
					showHeaders = listsLength > 1 ? true : false;
					for (var i = 0; i < listsLength; i += 1) {
						listName = listOrder[i],
						list = loc[listName];
						if (typeof list === "object") {
							for (var lnk in list) {
								listItem = list[lnk];
								itemsHTML += '<li><a href="' + listItem.url + '">' + listItem.titel + '</a></li>';
							}
							if (itemsHTML) {
								listsHTML += '<p>&nbsp;</p>';
								if (showHeaders) {
									listsHTML += '<h4>' + listHeaders[listName] + '</h4>';
								}
								listsHTML += '<ul>' + itemsHTML + '</ul>';
								itemsHTML = "";
							}
						} else {
							itemsHTML += '<li>' + listHeaders[listName] + ': ' + list + '</li>';
						}
					}
					if (!listsHTML && itemsHTML) {
						listsHTML += '<br /><ul class="totals">' + itemsHTML + '</ul>';
					}
					
					return listsHTML;
				}
				
				if (loc.adres) {
					addressHTML = loc.adres;
					if (addressHTML && (loc.postcode || loc.plaats)) {
						addressHTML += '<br />' + loc.postcode;
						if (loc.postcode && loc.plaats) {
							addressHTML += '&nbsp; ';
						}
					}
				}
				addressHTML += loc.plaats;
				
				if (loc.omschrijving) {
					descrHTML = '<br /><p>' + loc.omschrijving + '</p>';
				}
				
				if (loc.url) {
					linkHTML = '<br /><p><a href="' + loc.url + '">Meer informatie</a></p>';
				}
				
				contentHTML += '<div class="' + infoConf.contentClassName + '">' +
						'<h3>' + marker.getTitle() + '</h3>' +
						'<p>' + addressHTML + '</p>' +
						descrHTML +
						createLists() +
						linkHTML +
					'</div>';
				
				// create infoWindow
				infoWindow = new gm.InfoWindow({
					content: contentHTML
				});
				
				function openInfoWindow() {
					if ($.infoWinOpen.win) {
						$.infoWinOpen.win.close();
					}
					infoWindow.open(map, marker);
					$.infoWinOpen = {
						win: infoWindow,
						loc: locId
					};
				}
				
				// connect infoWindow to marker
				gm.event.addListener(marker, "click", openInfoWindow);
				
				// reset $.infoWinOpen when infoWindow is closed
				gm.event.addListener(infoWindow, "closeclick", function() {
					$.infoWinOpen = {};
				});
				
				// open previously selected infoWindow
				if (loc.prevSelected && hash == hashConf.searched) {
					openInfoWindow();
				}
				
				// fix content height infoWindows
				/*gm.event.addListener(infoWindow, "domready", function() {
					setTimeout(function() {
						$("#" + mapConf.wrapperId + " div." + infoConf.contentClassName).parent().css("overflow", "");
					}, 0);
				});*/
				
				return infoWindow;
			}
				
			function updateMarkers(data) {
				var marker,
					infoWindow;
				
				// remove previous markers
				removeMarkers();
				
				if (!(data instanceof Array)) {
					// add new markers
					for (var loc in data) {
						marker = createMarker(data[loc]);
						infoWindow = createInfoWindow(data[loc], marker, loc);
					}
				}
			}
			
			function getData(settings) {
				settings.data = $form.serialize();
				$.ajax(settings);
			}
			
			function getLastSearch(settings) {
				var url = settings.url,
					options = $.extend({}, settings, {
						url: url + (/\?/.test(url) ? "&" : "?") + "getPrevReq=1",
						success: function(data, status, xhr) {
							if (data && data.length) {
								var expr = "input:checkbox[name='" + data.join("'], input:checkbox[name='") + "']";
								$form
									.find("input:checkbox")//.removeAttr("checked")
									.filter(expr).attr("checked","checked");
							}
						},
						complete: function() {
							getData(xhrOptions);
						}
					});
				$.ajax(options);
			}
				
			$form.find("input:checkbox").click(function() {
				setTimeout(function() {
					getData(xhrOptions);
				}, 0);
			});
			
			if (hash == hashConf.searched) {
				getLastSearch(xhrOptions);
			} else {
				getData(xhrOptions);
			}
		},
		
		initMapFinalState: function(mapConf, $form) {
			var url = $form.attr("action"),
				xhrSettings = {
					dataType: "json",
					type: "get",
					asynch: false
				};
			
			// save location id server side + update hash
			$("div." + mapConf.infoWindow.contentClassName + " a").live("click", function() {
				if ($.infoWinOpen.loc) {
					xhrSettings.data = { loc: $.infoWinOpen.loc };
					xhrSettings.url = url;	// reset url
					$.ajax(xhrSettings);
				}
				window.location.hash = mapConf.hash.searched;
			});
		},
		
		initSiteSearch: function() {
			// simple validation:
			$("#siteSearch")
				.submit(function(e){
					var jSearchBox = $("#zkr_words");
					if (!jSearchBox.val()) {
						e.preventDefault();
						var msg = $.config.get().siteSearchEmpty;
						alert(msg);
						jSearchBox.focus();
					}
				});
		},
		
		addJSLinks: function() {
			$.initPrintPage();
			$.returnLinks("#cvOK", "back", 2);
			if ($.config.get("isPopup")) {
				$.returnLinks("#sendPageDone", "close");
			}
		},
		
		initPrintPage: function() {
			if (window.print) {
				$("#pageTools ul.nav").prepend('<li id="printPage"><a href="#">' + $.config.get().printLabel + '</a></li>');
				$("#printPage").click( function(e) {
					e.preventDefault();
					window.print();
				});
			}
		},
		
		returnLinks: function(parentSelector, type, steps) {
			if (!parentSelector) { return; }
			if (!type) { type = "back" }
			
			var returnLink = $.config.get("jsLinks")[type].replace(/(.*)\[(.*)\](.*)/, '<p class="' + type + '">$1<a href="#">$2</a>$3</p>');
			$(parentSelector).append(returnLink);
			
			// go back:
			$("p.back a").click(function(e) {
				e.preventDefault();
				window.history.go(-1 * (steps || 1));
			});
			
			// close window:
			$("p.close a").click(function(e) {
				e.preventDefault();
				window.close();
			});
		},
		
		popImages: function() {
			var links = $.config.get("popImages");	// gets defined in template
			for (lnk in links) {
				$("#" + lnk).popLink({width:links[lnk][0], height:links[lnk][1]})
			}
		},
		
		searchForms: function(expr) {
			var sfConfig = $.config.get("searchForm");
			if (!sfConfig || sfConfig.checkAll === false) { return; }
			
			var formDiv = $(expr);
			
			function checkAll(collection, check) {
				var checkBoxes = collection.find("input:checkbox");
				check ? checkBoxes.attr("checked", "checked") : checkBoxes.removeAttr("checked");
			}
			
			formDiv
				.each(function() {
					var jThis = $(this);
					var total = jThis.find("input:checkbox");
					var checked = total.filter("input:checked");
					var id = jThis.attr("id").substring(3).toLowerCase();
					var allID = "option_all." + id;
					var allName = "option_all[" + id + "]";
					var checkedAttr = total.length == checked.length ? ' checked="checked"' : "";
					var checkAllBox = '<li><label for="' + allID + '"><input type="checkbox" id="' + allID + '" name="' + allName + checkedAttr + '" />' + sfConfig.label + '</label></li>';
					jThis
						.data("total", total.length)
						.data("checked", checked.length)
						.prepend(checkAllBox);
				})
				.click(function(e) {
					var target = $(e.target);
					if (target.is("label")) { target = target.find("input:checkbox"); }
					var jThis = $(this);
					var checkAllID = "option_all." + jThis.attr("id").substring(3).toLowerCase();
					var checked = !!target.attr("checked");	// convert to boolean
					if (target.attr("id") == checkAllID) {
						checkAll(jThis, checked);
					} else {
						checkAllID = checkAllID.replace(/\./, "\\\.");
						var others = jThis.find("input:checkbox:not(#" + checkAllID + ")");
						others = checked ? others.not(":checked") : others.filter(":checked");
						if (others.length == 0) {
							checkAll(jThis, checked);
						} else {
							$("#" + checkAllID).removeAttr("checked");
						}
					}
				});
				
			var infoIcon = sfConfig.infoIcon;
			if (infoIcon) {
				formDiv
					.addClass("jsInfo")
					.find("div.infoLayer")
					.prepend('<a href="#"><img src="' + infoIcon + '" alt="info" /></a>')
					.hover(
						function(e) {
							var jThis = $(this);
							jThis.addClass("jsHover");
							jThis.closest("li").addClass("jsHover");
						},
						function(e) {
							var jThis = $(this);
							jThis.removeClass("jsHover");
							jThis.closest("li").removeClass("jsHover");
						});
			}
		},
		
		requestPassword: function() {
			var emailServiceForm = $("#emailService #searchForm");
			var reqPassword = emailServiceForm.find("#requestPassword");
			var login = emailServiceForm.find("#login");
			if (!login || login.length == 0 || !reqPassword || reqPassword.length == 0) { return; }
			
			emailServiceForm.addClass("jsSwap");
			var links = $.config.get("reqPassword");
			login.append('<p class="swapLink"><a href="#">' + links.forgotLink + '</a></p>');
			reqPassword.append('<p class="swapLink"><a href="#">' + links.backLink + '</a></p>');
			emailServiceForm
				.find("p.swapLink a")
				.click(function(e) {
					e.preventDefault();
					emailServiceForm.toggleClass("jsRequest");
				})
		},
		
		initOpleidingen: function() {
			var institutes = $("#oplInstitutes");
			var oplLists = institutes.find("div.opl");
			if (oplLists.length === 0) { return; }
			
			oplLists.prev().find("a")
				.addClass("toggleOplList")
				.append("<span></span>");
			
			institutes
				.addClass("jsExpandable")
				.click(function(e) {
					var jTarget = $(e.target);
					if (jTarget.is("a.toggleOplList")) {
						e.preventDefault();
						jTarget.closest("li").toggleClass("jsExpand");
					}
				});
			
		},
		
		emailDays: function() {
			var days = $("#searchForm.emailServiceProfile #dagen, #searchForm.cvProfile #dagen");
			days
				.keyup(function() {
					// validate value:
					var jThis = $(this);
					var val = jThis.val();
					var absIntVal = Math.abs(parseInt(val), 10);
					if (val != absIntVal && val != "") {
						val = absIntVal;
					}
					if (isNaN(val)) {
						val = 0;
					}
					if (val > 99) {
						val = 99;
					}
					jThis.val(val);
					
					calcDate(val);
				})
				.blur(function() {
					// validate value:
					var jThis = $(this);
					var val = jThis.val();
					if (val == "") {
						jThis.val("0");
					}
					calcDate(jThis.val());
				});
				
			function calcDate(period) {
				if (period >= 0) {
					var today = new Date();
					var futureDate = new Date(today.getTime() + 86400000 * period);	// 24 * 60 *60 * 1000 = 86400000 milliseconds in a day
					var dateTxt = futureDate.getDate() + " " + $.config.get("nlMonths")[futureDate.getMonth()] + " " + futureDate.getFullYear();
					var endDate = $("#verloopdatum");
					var finalDate = $("#finalDate");
					if (finalDate.length == 0) {
						endDate.before(', tot <span id="finalDate">' + dateTxt + '</span>');
						finalDate = $("#finalDate");
					}
					finalDate.text(futureDate.toLocaleDateString());
					endDate.val(dateTxt);
				}
			}
			
			function leadingZero(num) {
				return num < 10 ? "0" + num : num;
			}
			
			calcDate(days.val());
		}
	} );
	
	$.fn.extend( {
		validateForm: function(checkObj) {
			/* optional checkObj keys:
				{
					required: Boolean (default: true),
					pattern: RegExp, or one of the keys in config.patterns (e.g. "email"),
					label: String (name used in error message),
					error: String (additional error message)
				} 	*/
			var config = {
				defProps:	{
								required: true
							},
				errorMsg:	"De volgende velden zijn niet (juist) ingevuld:",
				patterns:	{
								email: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i
							}
			}
			for (field in checkObj) {
				var fieldObj = checkObj[field];
				for (prop in config.defProps) {
					if (fieldObj[prop] == null) {
						fieldObj[prop] = config.defProps[prop];
					}
				}
				if (fieldObj.pattern && config.patterns[fieldObj.pattern]) {
					fieldObj.pattern = config.patterns[fieldObj.pattern];
				}
				if (!fieldObj.label) {
					fieldObj.label = field;
				}
			}
			
			var jThis = $(this);
			var fields = jThis.is("form :input") ? jThis : jThis.find(":input");
			fields.each(function() {
				var jThis = $(this);
				jThis.data("valObj", checkObj[jThis.attr("name")]);
			});
			var jForm = $($.unique(fields.closest("form")));
			jForm.submit(function(e) {
				var jThis = $(this);
				var errorStr = "";
				var firstItem;
				jThis.find(":input")
					.each(function() {
						var jThis = $(this);
						var value = jThis.val();
						var valObj = jThis.data("valObj");
						if (valObj) {
							if ((valObj.required && !value) || (value && valObj.pattern && !value.match(new RegExp(valObj.pattern)))) {
								errorStr += "\n- " + valObj.label;
								if (valObj.error) {
									errorStr += " (" + valObj.error + ")";
								}
								if (!firstItem) {
									firstItem = jThis;
								}
							}
						}
					});
				if (errorStr != "") {
					e.preventDefault();
					alert(config.errorMsg + errorStr);
					firstItem.focus();
				}
			});
		}
	} );
} )(jQuery);

jQuery( function( $ ) {
	
	// extend $.config with window.config (if any):
	$.config.extend(window.config);
	
	// init searchForms:
	$.searchForms("#searchForm fieldset.checkboxField ul.overview, #mapForm fieldset.checkboxField ul.overview");
	
	// map search:
	var $tabs = $("#sectionNav.tabs ul");
	if ($tabs.hasClass("mapSearch")) {
		$.addMapSearchTab($tabs);
		$.initSearchMap();
	}

	// init #siteSearch (overLabel + button image [onfocus]):
	$.initSiteSearch();
	
	// overLabel:
	$("#emailService label, #cvBank label").overLabel();
	
	// requestPassword swap:
	$.requestPassword();
	
	// expand/collapse opleidingen:
	$.initOpleidingen();
	
	// add JavaScript links (print, back, zoek op kaart):
	$.addJSLinks();
	
	// select box navigation:
	$("#mainContent div.resultsNav select").selectNav();
	
	// popLinks:
	$.popImages();
	$("#sendPage a, #mainContent p.reportToUs a").popLink({ width: 540, height: 600, props: ["resizable", "scrollbars"] });
	
	// make entire block elements clickable:
	$("#results li, #rndInstelling div.item:has(img)").clickable();
	
	// validate forms:
	$("#searchForm.emailServiceProfile").validateForm({
		"voornaam": { label: "Voornaam" },
		"achternaam": { label: "Achternaam" },
		"straat": { label: "Straat" },
		"huisnummer": { label: "Huisnummer + toevoegsel" },
		"postcode": { label: "Postcode" },
		"plaats": { label: "Woonplaats" },
		"email": { label: "E-mailadres", pattern: "email", error: "vul een geldig e-mailadres in" }
	});
	$("#wrapper div.sendPage #email_form").validateForm({
		"fields[uwnaam]": { label: "Uw naam" },
		"fields[email]": { label: "E-mailadres van de ontvanger", pattern: "email", error: "vul een geldig e-mailadres in" },
		"fields[onderwerp]": { label: "Onderwerp" }
	});
	$("#wrapper div.wrongVac #email_form").validateForm({
		"fields[uwnaam]": { label: "Uw naam" },
		"fields[uwemail]": { label: "Uw e-mailadres", pattern: "email", error: "vul een geldig e-mailadres in" }
	});
	
	// set final date email service/CV bank:
	$.emailDays();
} );
