var HSB = {
	methods: {domready: [], load: [], unload: []},
	
	initCore: function() {
		DOMAssistant.DOMReady(HSB.onDOMReadyCore);
		var window = $(window);
		window.addEvent("load", HSB.onLoadCore);
		window.addEvent("unload", HSB.onUnloadCore);
		
		this.addPlugin(this);
	},
	
	onDOMReadyCore: function() {
		HSB.runPluginMethods("domready");
	},
	
	onLoadCore: function() {
		HSB.runPluginMethods("load");
	},

	onUnloadCore: function() {
		HSB.runPluginMethods("unload");
	},

	addPlugin: function(plugin) {
		if (plugin.init) {
			plugin.init();
		}
		this.addMethod(plugin, "domready", plugin.onDOMReady);
		this.addMethod(plugin, "load", plugin.onLoad);
		this.addMethod(plugin, "unload", plugin.onUnload);
	},
	
	addMethod: function(plugin, methodName, method) {
		if (method) {
			this.methods[methodName].push({el: plugin, fn: method});
		}
	},
	
	runPluginMethods: function(methodName) {
		var methodsToRun = this.methods[methodName];
		if (methodsToRun) {
			for (var i = 0, il = methodsToRun.length; i < il; i++) {
				methodsToRun[i].fn.call(methodsToRun[i].el);
			}
		}
	},
	
	init: function() {
		/*@cc_on
		@if (@_jscript_version < 5.7)
			try {
				document.execCommand("BackgroundImageCache", false, true);
			} catch (err) {}
		@end @*/
	},
	
	onDOMReady: function() {},
	
	onLoad: function() {},

	onUnload: function() {},
	
	getClassNameValue: function(el, prefix) {
		var ret = new RegExp(".*" + prefix + "-(.*?)(?:\\s|$).*").exec(el.className);
		if (ret) {
			return ret[1];
		}
		return null;
	},
	
	getAnchoredElement: function(anchor) {
		return $$(anchor.href.replace(/.*\#(.*)/, "$1"));
	},

	getActualWidth: function(elem) {
		elem = $(elem);
		var margin = HSB.stripPx(elem.getStyle("margin-left")) + HSB.stripPx(elem.getStyle("margin-right"));
		return elem.offsetWidth + margin;
	},

	getActualHeight: function(elem) {
		elem = $(elem);
		var margin = HSB.stripPx(elem.getStyle("margin-bottom")) + HSB.stripPx(elem.getStyle("margin-top"));	
		return elem.offsetHeight + margin;
	},
	
	stripPx: function(str) {
		var value = parseInt(str.substring(0, str.length - 2));
		if (isNaN(value)) {
			return 0;
		}
		return value;
	},

	strip : function(str) {
		// Strips all whitespace
		return str.replace(/ /gi, "");
	},
	
	numericStrip : function(str) {
		// Strips all whitespace and acceptable chars within a "numeric" (phonenr, zip etc) string
		return str.replace(/ |-|\/|\.|\+/gi, "");
	},
		
	addParameter: function(url, name, value) {
		return url + (url.indexOf("?") < 0 ? "?" : "&") + name + "=" + value;
	},
	
	getFirstNode: function(node) {
		return node.firstChild.nodeType == 3 ? node.childNodes[1] : node.firstChild;
	}
};
HSB.initCore();


/**
 * Event delegation
 */
HSB.eventDelegator = {
	events: [],
	
	init: function() {
		$(document).addEvent("click", function(e) {
				if ((e.which && e.which != 1) || (e.button && e.button !== 0)) {
					return true;
				}
				var target = e.eventTarget;
				if (target.onclick) {
					return false;
				}
				for (var i = HSB.eventDelegator.events.length - 1; i >= 0; i--) {
					var match = HSB.eventDelegator.getMatch(target, HSB.eventDelegator.events[i].selector);
					if (match !== null) {
						var callbackValue = HSB.eventDelegator.events[i].fn.call(match, e);
						if (typeof callbackValue === "undefined") {
							callbackValue = false;
						}
						if (!callbackValue) {
							DOMAssistant.preventDefault(e);
							return false;
						}
					}
				}
				return true;
			}
		);	
	},
	
	registerClick: function(selector, fn) {
		this.events.push({selector: this.compileSelector(selector), fn: fn});
	},
	
	getMatch: function(el, selector) {
		var matchingEl = null;
		var noOfElms = selector.length - 1;
		var matchedSelector = false;
		for (var j = noOfElms; j >= 0; j--) {
			matchedSelector = false;
			while (!matchedSelector && el.parentNode) {
				var match = true;
				if (selector[j].tag && selector[j].tag != el.tagName) {
					match = false;
				} else if (selector[j].id && selector[j].id != el.id) {
					match = false;
				} else if (selector[j].className && el.className.indexOf(selector[j].className) < 0) {
					match = false;
				}
				if (matchingEl === null && match) {
					matchingEl = el;
				}
				matchedSelector = match;
				el = el.parentNode;
			}
		}
		if (!matchedSelector) {
			matchingEl = null;
		}
		return matchingEl;
	},
	
	compileSelector: function(selector) {
		var compiled = [];
		var part = [];
		var key = "tag";
		var value = "";
		var ch;
		for (var i = 0, il = selector.length; i < il; i++) {
			ch = selector.charAt(i);
			if (i == selector.length - 1) {
				value += ch;
				ch = " ";
			}
			if (ch == " ") {
				part[key] = value;
				if (part.tag) {
					part.tag = part.tag.toUpperCase();
				}
				compiled.push(part);
				part = [];
				key = "tag";
				value = "";
			} else if (ch == "#") {
				part[key] = value;
				key = "id";
				value = "";
			} else if (ch == ".") {
				part[key] = value;
				key = "className";
				value = "";
			} else {
				value += ch;
			}
		}
		return compiled;
	}
};
HSB.addPlugin(HSB.eventDelegator);


/**
 * Global clicks
 */
HSB.eventDelegator.registerClick(".print A", function() { print(); });



/**
 * POPUP LINKS
 */
HSB.popupLinks = {
	init: function() {
		HSB.eventDelegator.registerClick("A.popup", function() {
			window.open(this.href, "_blank");
		});
	}
};
HSB.addPlugin(HSB.popupLinks);


/**
 * CONDITIONAL DISPLAY OF ELEMENTS IN FORMS
 */
HSB.conditionalDisplay = {
	onDOMReady: function() {
		$(".conditional-display").each(function() {
			var showList = HSB.getClassNameValue(this, "showon");
			var show = new Array();
			if (showList != null) {
				show = showList.split("|");
			}
			var hideList = HSB.getClassNameValue(this, "hideon");
			var hide = new Array();
			if (hideList != null) {
				hide = hideList.split("|");
			}
			var focus = $$(HSB.getClassNameValue(this, "focuson"));
			var elem = this;
			for (var i=0, l = show.length; i < l; i++) {
				if($$(show[i]).checked) {
					elem.style.display = "block";
					focus.addClass("required");
				}
				HSB.eventDelegator.registerClick("#" + show[i], function() {
					if(this.checked) {
						elem.style.display = "block";
						focus.focus();
						focus.addClass("required");
					} else {
						elem.style.display = "none";
						focus.removeClass("required");
					}
					return true;
				});
			}
			for (var i=0, l = hide.length; i < l; i++) {
				HSB.eventDelegator.registerClick("#" + hide[i], function() {
					elem.style.display = "none";
					focus.removeClass("required");
					return true;
				});
			}
		});
	}
};
HSB.addPlugin(HSB.conditionalDisplay);


/**
 * Form functions
 */
HSB.formHandler = {
	filterData: [],
	
	onDOMReady: function() {
		// Handling of filtering selects
		$("SELECT.filter").each(function() {
				var targetId = HSB.getClassNameValue(this, "filter");
				var target = $$(targetId);
				var filterName = HSB.getClassNameValue(this, "namespace");
				if (target.options.selectedIndex > 0) {
					target.selectedValue = target.options[target.options.selectedIndex].value;				
				}
				if (target && HSB.formHandler.filterData[filterName] == null) {
					var data = [];
					data["__original"] = [];
					for (var i = 0, il = target.options.length; i < il; i++) {
						var key = target.options[i].className;
						if (!key) {
							key = "__all";
						}
						if (!data[key]) {
							data[key] = [];
						}
						var literal = {text: target.options[i].text, value: target.options[i].value, hide: false, key: key};
						data[key].push(literal);
						data["__original"].push(literal);
					}
					HSB.formHandler.filterData[filterName] = data;
				}
				
				$(this).addEvent("change", function() {
						HSB.formHandler.filter(this, targetId);
					}
				);
				if (this.options[this.selectedIndex].className) {
					HSB.formHandler.filter(this, targetId);
				}
			}
		);
		
		// Handling of submits on value changes
		$("select.submit-onchange").each(function() {
				var form = this.form;
				if (!this.form.isAJAXForm) {
					form = new HSB.AJAXForm(this.form);
					form.setResponseHandler(function(data) {
							$$(HSB.getClassNameValue(this, "show-in")).innerHTML = data;
						}
					);
				}
				$(this).addEvent("change", function() {
						HSB.AJAXForm.sendForm.call(form);
					}
				);
			}
		);

		// Handling ajax forms
		$("form.ajax-form").each(function() {
				var form = new HSB.AJAXForm($(this));
				var focusEl = null;
				form.elmsByClass("focus").each(function() {
						focusEl = this;
						try {
							this.focus();							
						} catch (e) {}
					}
				);
				if (form.hasClass("sliding")) {
					var sliderEl = form;
					for (var e = this; e.parentNode !== null; e = $(e.parentNode)) {
						if (e.hasClass("slider-box")) {
							sliderEl = e;
							break;
						}
					}
					if (!sliderEl.id) {
						sliderEl.id = "form-slider-" + (new Date()).getTime();
					}
					var slider = new HSB.slider(sliderEl);
					var toggleLinkId = HSB.getClassNameValue(form, "toggle-link");
					if (toggleLinkId) {
						HSB.eventDelegator.registerClick("#" + toggleLinkId, function() {
								slider.toggle(false, function() { if (focusEl && slider.isVisible) { focusEl.focus(); } });
							}
						);
					}
					HSB.eventDelegator.registerClick("#" + sliderEl.id + " .cancel", function() {
							slider.close();
						}
					);
					form.setResponseHandler(function(data) {
							slider.close();
							HSB.alertBox.show(data, sliderEl.parentNode);							
						}
					);
				} else {
					form.setResponseHandler(function(data) {
							HSB.alertBox.show(data, form);								
						}
					);					
				}
			}
		);
	},
	
	filter: function(select, targetId) {
		var target = $$(targetId);
		if (target) {
			var className = select.options[select.selectedIndex].className;
			var filterName = HSB.getClassNameValue(select, "namespace");
			var optionData = HSB.formHandler.filterData[filterName];
			var data = [];
			if (!className) {
				data = optionData["__original"];
			} else {
				var allData = optionData["__all"];
				if (allData) {
					data = data.concat(allData);
				}
				var classData = optionData[className];
				if (classData) {
					data = data.concat(classData);
				}
			}
			target.innerHTML = "";
			for (var i = 0, il = data.length; i < il; i++) {
				if (!data[i].hide) {
					var s = target.create("option", {value: data[i].value}, true, data[i].text);
					if (target.selectedValue && target.selectedValue == data[i].value) {
						s.selected = true;
						target.selectedValue = null;
					}
				}
			}
		}
	},
	
	addToFilter: function(namespace, option) {
		var literal = {text: option.text, value: option.value, hide: false, key: option.className, selected: false};
		HSB.formHandler.filterData[namespace][option.className].push(literal);
		HSB.formHandler.filterData[namespace]["__original"].push(literal);
		HSB.formHandler.sortFilter(namespace, option.className);
	},
	
	sortFilter: function(namespace, filterGroup) {
		HSB.formHandler.filterData[namespace]["__original"].sort(function(a, b) {
			return a.text > b.text;
		});
		HSB.formHandler.filterData[namespace][filterGroup].sort(function(a, b) {
			return a.text > b.text;
		});
	}
};
HSB.addPlugin(HSB.formHandler);


/**
 * Option picker class
 */
HSB.optionPicker = function(targetSelect, sourceSelect, sourceFilter, sourceFilterSelect) {
	this.sourceSelect = sourceSelect;
	this.targetSelect = targetSelect;
	this.sourceFilter = sourceFilter || null;
	this.sourceFilterSelect = sourceFilterSelect || null;
	this.pickedData = this.getPickedData();
	$(this.targetSelect.form).addEvent("submit", function() {
		for(i = 0, l = targetSelect.options.length; i < l; i++) {
			targetSelect.options[i].selected = true;
		}
	})
}
HSB.optionPicker.prototype.pick = function(){
	var selectedOptions = [];
	while (this.sourceSelect.selectedIndex != -1) {
		var optionIndex = this.sourceSelect.selectedIndex;
		var option = this.sourceSelect.options[optionIndex];

		if (option.className != "__all") {
			selectedOptions.push(option);
			if (this.sourceFilter != null) {
				var allOptionsList = HSB.formHandler.filterData[this.sourceFilter]["__original"];
				for (var i = 0, il = allOptionsList.length; i < il; i++) {
					if (allOptionsList[i].value == option.value) {
						allOptionsList[i].hide = true;
					}
				}
			}
			option.selected = false;
			this.sourceSelect.removeChild(option);
		} else {
			option.selected = false;
		}
	}
	this.pickedData = this.pickedData.concat(selectedOptions);
	this.populateTargetSelect();
}
HSB.optionPicker.prototype.unpick = function() {
	this.pickedData = [];

	for (var i = 0, il = this.targetSelect.options.length; i < il; i++) {
		var option = this.targetSelect.options[i];
		if (!option.selected) {
			this.pickedData.push(option);
		} else {
			if (this.sourceFilter != null) {
				// set option to "show" in filter
				var allOptionsList = HSB.formHandler.filterData[this.sourceFilter]["__original"];
				var exists = false;
				for (var a = 0, al = allOptionsList.length; a < al; a++) {
					if (allOptionsList[a].value == option.value) {
						allOptionsList[a].hide = false;
						exists = true;
					}
				}
				if (!exists) {
					/* HERE WE GO */
					newOption = this.sourceSelect.create("option", {value: option.value, className: option.className}, true, option.text);
					HSB.formHandler.addToFilter(this.sourceFilter, newOption);
				}
			} else {
				this.sourceSelect.create("option", {value: option.value, className: option.className}, true, option.text);
			}
			this.targetSelect.removeChild(this.targetSelect.options[i]);
			i--;
			il--;
		}
	}
	if (this.sourceFilterSelect != null) {
		HSB.formHandler.filter(this.sourceFilterSelect, this.sourceSelect.id);
	}
}
HSB.optionPicker.prototype.populateTargetSelect = function() {
	this.targetSelect.innerHTML = "";
	for (var i = 0, il = this.pickedData.length; i < il; i++) {
		var s = this.targetSelect.create("option", {value: this.pickedData[i].value, className: this.pickedData[i].className}, true, this.pickedData[i].text);
	}	
}
HSB.optionPicker.prototype.getPickedData = function() {
	var pickedData = [];
	for (var i = 0, il = this.targetSelect.options.length; i < il; i++) {
		pickedData.push(this.targetSelect.options[i]);
	}
	return pickedData;
}


/**
 * Option picker for form on "Mina sidor"
 */
HSB.myPagesOptionPicker = {
	onDOMReady: function() {
		if ($$("pickedmunicipality")) {
			var myMunicipalities = new HSB.optionPicker($$("pickedmunicipality"), $$("municipality"), "municipality", $$("county"));
			$$("add").addEvent("click", function(e) {
				DOMAssistant.preventDefault(e);
				myMunicipalities.pick();
			});
			$$("remove").addEvent("click", function(e) {
				DOMAssistant.preventDefault(e);
				myMunicipalities.unpick();
			});
		}
	}
}
HSB.addPlugin(HSB.myPagesOptionPicker);


/**
 * Slideshow
 */
HSB.slideshow = {
	onDOMReady: function() {
		this.hasSlideshow = $$("slideshow") !== null;
		if (this.hasSlideshow) {
			HSB.eventDelegator.registerClick("#slideshow A", function(e) {
					if ($(this.parentNode).hasClass("do-show-all")) {
						$$("slideshow").addClass("show-all");
						HSB.slideshow.showSiblings(this.parentNode);
					} else {
						if (!$(this.parentNode).hasClass("selected")) {
							var holder = $$("slideshow-contents");
							var selected = $(this.parentNode.parentNode.parentNode).elmsByClass("selected");
							if (selected && selected.length > 0) {
								$(selected[0]).removeClass("selected");
							}
							$(this.parentNode).addClass("selected");
							if ($(this).hasClass("map")) {
								var newEl = $$(HSB.map.mapId);
								holder.appendChild(newEl);
								newEl.style.display = "block";
								HSB.slideshow.show(holder, newEl, 350, 1, true);
							} else {
								var thumbImg = $(this).elmsByTag("img");
								var imgAlt = "";
								if (thumbImg.length > 0) {
									imgAlt = thumbImg[0].alt
								}
								var duration = 500;
								if (HSB.slideshow.previousWasMap) {
									duration = 1;
								}
								var image = holder.create("img", {id: "slideshow-current", alt: imgAlt});
								var text = this.title;
								image.addEvent("load", function() {
									HSB.slideshow.show(holder, image, this.height, duration, false, text);
								});
								image.src = this.href;
							}
						}
					}
				}
			);
			var slideshow = $$("slideshow");
			var firstSlide = null;
			for (var i = 0, il = slideshow.childNodes.length; i < il; i++) {
				if (slideshow.childNodes[i].nodeType == 1) {
					if (slideshow.childNodes[i].tagName != "UL") {
						firstSlide = slideshow.childNodes[i];					
					}
					break;
				}
			}
			var holder = slideshow.create("div", {id: "slideshow-contents"});
			if (firstSlide !== null) {
				var p = $($(firstSlide).next());
				if (firstSlide.tagName == "IMG") {
					if (firstSlide.complete) {
						var img = new Image();
						img.src = firstSlide.src;
					} else {
						$(firstSlide).addEvent("load", function() {
							holder.style.height = HSB.getActualHeight(holder) + "px";
						});
					}
				} else if (firstSlide.tagName == "DIV") {
					this.previousWasMap = (firstSlide.id == HSB.map.mapId);
				}
				if (!this.previousWasMap) {
					firstSlide.id = "slideshow-current";
				}
				holder.appendChild(firstSlide);
				if (p.tagName == "P") {
					holder.appendChild(p);
				}
			}
			slideshow.insertBefore(holder, slideshow.firstChild);
			holder.style.height = HSB.getActualHeight(holder) + "px";
		}
	},
	
	show: function(holder, slide, height, duration, isMap, text) {
		var image = null;
		var p = null;
		this.previousWasMap = isMap;
		if (!isMap) {
			image = slide;
			slide = holder.create("div", {className: "next"}, true, image);
			if (text != null && text.length > 0) {
				p = slide.create("p", null, true, text);
				height = HSB.getActualHeight(slide);
			}
		}
		holder.animate({height: height}, {duration: 500});
		slide.show({duration: duration, callback: function() {
			if (isMap) {
				$$("slideshow-current").remove();
			} else {
				while ((prev = $(slide.prev())) != null) {
					if (prev.id == HSB.map.mapId) {
						prev.style.opacity = "0";
						prev.style.display = "none";
						document.body.appendChild(prev);
					} else {
						prev.remove();
					}
				}
				holder.insertBefore(image, slide);
				if (p != null) {
					holder.insertBefore(p, slide);
				}
				slide.remove();
			}
		}});
	},
	
	showSiblings: function(nextEl) {
		if (nextEl !== null) {
			$(nextEl).show({duration: 10, callback: function() {
				HSB.slideshow.showSiblings(nextEl.next());
			}});
		}
	}
};
HSB.addPlugin(HSB.slideshow);


/**
 * Inline navigation
 */
HSB.navigation = {
	init: function() {
		HSB.eventDelegator.registerClick(".inline-navigation a", function(e) {
				var nav = $(this);
				while (!nav.hasClass("inline-navigation")) {
					nav = $(nav.parentNode);
				}
				var href = HSB.addParameter(this.href, "mode", "ajax");
				var target = $$(HSB.getClassNameValue(nav, "show-in"));
				if (target) {
					if(!target.live) {
						target.live = "polite";
						target.setAttribute("live", "polite");
					}
					target.hide({duration: 200, callback: function() {				
						target.ajax({url: href, callback: function(data) {
								this.innerHTML = data;
								target.show({duration: 200});
							}
						});
					}});
				}
			}
		);
	}
};
HSB.addPlugin(HSB.navigation);


/**
 * Region select
 */
HSB.regionSelect = {
	responseBox: null,
	onDOMReady : function() {
		var toggleRegionSelect = $$("toggle-region-select");
		if (toggleRegionSelect !== null) {
			toggleRegionSelect.setAttribute("role", "button");
			var regionSelectBox = new HSB.slider($$("region-select"));
			toggleRegionSelect.addEvent("click", function() {
					regionSelectBox.toggle();
				}
			);
		}
		var zip = $$("region-select-zip");
		if (zip !== null) {
			this.responseBox = new HSB.slider($$("region-select-form-response"));
			var form = new HSB.AJAXForm(zip.form);
			form.setResponseHandler(HSB.regionSelect.showRegionBox);
			zip.addEvent("keyup", function() {
					if (HSB.numericStrip(this.value).length == 5) {
						HSB.AJAXForm.sendForm.call(form);
					}
				}
			);
			$$("region-select-municipality").addEvent("change", function() {
					HSB.AJAXForm.sendForm.call(form);
				}
			);
		}
		var toggleList = $$("region-select-toggle-region-list");
		if (toggleList !== null) {
			var listBox = new HSB.slider($$("region-select-region-list"));
			toggleList.addEvent("click", function() {
					listBox.toggle();
				}
			);
		}
	},
	showRegionBox: function(content) {
		if (HSB.regionSelect.responseBox.isVisible) {
			HSB.regionSelect.responseBox.close(false, function() {HSB.regionSelect.showRegionBox(content); });			
		} else {
			$$("region-select-form-response").innerHTML = content;
			HSB.regionSelect.responseBox.open();			
		}
	}
};
HSB.addPlugin(HSB.regionSelect);

/**
 * Searchbox focus
 */
HSB.searchBoxFocus = {
	onDOMReady : function() {
		$("input.focus").each(function () {
			$(this).focus();
		});
	}
};
HSB.addPlugin(HSB.searchBoxFocus);


/**
 * Tab handling
 */
HSB.tabs = {
	tabHashPrefix: "flik_",
	init: function() {
		document.getElementById("tabbed") ? document.getElementById("tabbed").setAttribute("aria-live", "polite") : null;
		HSB.eventDelegator.registerClick("#tabbed .tabs a", function(e) {
				window.location.hash = HSB.tabs.tabHashPrefix + HSB.tabs.getHash(this);
				var parent = $(this.parentNode);
				if (!parent.hasClass("selected")) {
					var active = $(parent.parentNode).elmsByClass("selected")[0];
					if (active !== null) {
						active.removeClass("selected");
						HSB.getAnchoredElement($(active).elmsByTag("A")[0]).style.display = "none";
					}
					parent.addClass("selected");
					HSB.getAnchoredElement(this).style.display = "block";
				}
			}
		);
	},
	
	onDOMReady: function() {
		 $("#tabbed").each(function() {
		 		var tabAnchors = $($(this).elmsByClass("tabs")[0]).elmsByTag("A");
				if (tabAnchors !== null) {
					var selectedAnchor = null;
					var tabHash = location.hash.replace(HSB.tabs.tabHashPrefix, "");
					for (var i = 0, il = tabAnchors.length; i < il; i++) {
						var parent = $(tabAnchors[i].parentNode);
						var isSelected = parent.hasClass("selected");
						var isUrlSelected = tabHash.length > 0 && tabAnchors[i].href.indexOf(tabHash) >= 0;
						if (i === 0 || isSelected || isUrlSelected) {
							selectedAnchor = tabAnchors[i];
							if (isUrlSelected) {
								break;
							}
						}
					}
					for (var i = 0, il = tabAnchors.length; i < il; i++) {
						if (tabAnchors[i] != selectedAnchor) {
							$(tabAnchors[i].parentNode).removeClass("selected");
							HSB.getAnchoredElement(tabAnchors[i]).style.display = "none";						
						}
					}
					$(selectedAnchor.parentNode).addClass("selected");
					HSB.getAnchoredElement(selectedAnchor).style.display = "block";
				}
			}
		);
	},
	
	getHash: function(anchor) {
		return anchor.href.replace(/.*\#(.*)/, "$1");
	}
};
HSB.addPlugin(HSB.tabs);


/**
 * Google Maps Plugin
 */
HSB.map = {
	mapId: "map",
	
	init: function() {
		var mapEl = $$(this.mapId);
		if (mapEl) {
			var mapAnchors = mapEl.elmsByTag("A");
			try {
				google.load("maps", "2", {"locale" : "sv"});
				google.setOnLoadCallback(function() {
						var gx = new GGeoXml(mapAnchors[0].href + "&output=kml", function() {
								try {
									var map = new google.maps.Map2(mapEl);
									var bounds = gx.getDefaultBounds();
									map.setCenter(bounds.getCenter(),map.getBoundsZoomLevel(bounds));
									map.addOverlay(gx);
									map.addControl(new GSmallMapControl());
									map.addControl(new GMapTypeControl());							
								} catch (e) { 
									mapEl.style.display = "none";
								}
							}
						);
					}
				);
			} catch (e) { /* Google api isn't loaded, so just quit... */ }
		}
	},
	
	onUnload: function() {
		try {
			if (google && google.maps) {
				google.maps.Unload();
			}
		} catch (e) { /* Google api isn't loaded */ }
	}
};
HSB.addPlugin(HSB.map);


/**
 * Form Validator
 */
HSB.formValidator = {
	onDOMReady : function() {
		$(".validate").each(function() {
				var form = $(this);
				if (form.hasClass("ajax-form")) {
					form.setBeforeSubmissionHandler(HSB.formValidator.validate);
				} else {
					form.addEvent("submit", HSB.formValidator.validate);
				}
			}
		);
	},
	validate : function() {
		
		var form = $(this);
		var requiredFields = form.elmsByClass("required");
		var acceptConditionFields = form.elmsByClass("accept-conditions");
		var emailFields = form.elmsByClass("e-mail");
		var numericFields = form.elmsByClass("numeric");
		var personnummerFields = form.elmsByClass("personnummer");
		var errors = false;
		var missing = false;
		var hasAcceptedConditions = true;
		var radioFields = form.elmsByClass("required-radio");
		var selectFields = form.elmsByClass("required-select");
		var requiredPasswordFields = form.elmsByClass("required-pwd");
		var username = form.elmsByClass("username");
		var minLength2Fields = form.elmsByClass("minlength-2");		
		var hasDependenceOnPNrIfJa = form.elmsByClass("require-pnr-if-ja");
		
		var errorText = "<h2>Oj, vänta lite...</h2><ul>";

		function hasUpperCaseCharacter(password)
		{
		    return password.match("\[A-Z\]") != null;
		}
		function hasLowerCaseCharacter(password)
		{
		  return password.match("\[a-z\]") != null;
		}
		function hasNumericCharacter(password)
		{
		  return password.match("\[0-9\]") != null;
		}
		for (var i = 0, il = requiredPasswordFields.length; i < il; i++) {
			
			if (username[0].value == requiredPasswordFields[0].value) {
				HSB.formValidator.setError(requiredPasswordFields[0]);
				errors = true;
				errorText += "<li>Lösenordet får inte vara det samma som användarnamnet.</li>";
				break;
			}
			
			if (HSB.strip(requiredPasswordFields[i].value).length === 0) {
				HSB.formValidator.setError(requiredPasswordFields[i]);
				missing = true;
				errorText += "<li>Du har inte fyllt i " + $(requiredPasswordFields[i]).title + "</li>";
			}

			if (requiredPasswordFields[0].value != requiredPasswordFields[1].value) {
				HSB.formValidator.setError(requiredPasswordFields[i]);
				errors = true;
				errorText += "<li>Felaktig bekräftelse av lösenord.</li>";
				break;
			}
			
		}

		for (var i = 0, il = requiredPasswordFields.length; i < il; i++) {
			var valid = requiredPasswordFields[i].value.length >= 6 &&
            	hasUpperCaseCharacter(requiredPasswordFields[i].value) &&
            	hasLowerCaseCharacter(requiredPasswordFields[i].value) &&
            	hasNumericCharacter(requiredPasswordFields[i].value);

			if (!valid)
			{
				HSB.formValidator.setError(requiredPasswordFields[i]);
				errors = true;
				errorText+="<li>Lösenordet måste bestå av minst 6 tecken, innehålla både versaler och gemener, samt minst en siffra.</li>";
			    break;
			}
		}	
		
		for (var i = 0, il = requiredFields.length; i < il; i++) {
			if (HSB.strip(requiredFields[i].value).length === 0) {
				HSB.formValidator.setError(requiredFields[i]);
				missing = true;
				errorText += "<li>Du har inte fyllt i " + $(requiredFields[i]).title + "</li>";
			}
		}
		for (var i = 0, il = emailFields.length; i < il; i++) {
			if (HSB.strip(emailFields[i].value).length !== 0) {
				if (emailFields[i].value.search(/(\w|\.|\-)+\@(\w|\.|\-)+\.[a-z]{2,6}$/)) {
					HSB.formValidator.setError(emailFields[i]);
					errors = true;
					errorText += "<li><span>" + emailFields[i].value + "</span> är inte en korrekt e-postadress" + "</li>";
				}
			}
		}
		for (var i = 0, il = personnummerFields.length; i < il; i++) {
			if (HSB.strip(personnummerFields[i].value).length !== 0) {
				var val = HSB.numericStrip(personnummerFields[i].value);
				if((/\D/).test(val) || val.length > 12 || val.length < 10 || (val.length == 12 && (val.substr(0,2) != "19" && val.substr(0,2) != "20" && val.substr(0,2) != "18"))) {
					HSB.formValidator.setError(personnummerFields[i]);
					errors = true;
					errorText += "<li><span>" + personnummerFields[i].value + "</span> är inte ett giltigt " + personnummerFields[i].title + "</li>";
				} else {
					if (val.length < 12) {
						year = (new Date()).getFullYear() + "";
						if(year.substr(0,2) == "20") {
							if (val.substr(0,2) > year.substr(2,2)) {
								val = "19" + val;
							} else {
								val = "20" + val;
							}
						} else {
							val = "19" + val;
						}
					}
					personnummerFields[i].value = val;
				}
			}
			
		}
		for (var i = 0, il = numericFields.length; i < il; i++) {
			if((/\D/).test(HSB.numericStrip(numericFields[i].value))) {
				HSB.formValidator.setError(numericFields[i]);
				errors = true;
				errorText += "<li><span>" + numericFields[i].value + "</span> är inte ett giltigt " + numericFields[i].title + "</li>";
			}
			
		}
		for (var i = 0, il = hasDependenceOnPNrIfJa.length; i < il; i++) {
			if (hasDependenceOnPNrIfJa[i].value == "ja" && personnummerFields[0].value.length < 10) {
				errors = true;
				errorText += "<li>Du måste fylla i "+ personnummerFields[0].title + " när du väljer '" + hasDependenceOnPNrIfJa[i].title + "'.</li>";
			}
		}
		for (var i = 0, il = acceptConditionFields.length; i < il; i++) {
			if (acceptConditionFields[i].checked === false) {
				hasAcceptedConditions = false;
				errorText += "<li>Du måste godkänna villkoren för att kunna skicka in formuläret.</li>";
			}
		}
		if(radioFields.length > 0){
			for (var i = 0, il = radioFields.length; i < il; i++) {
				var validRadio = false;
				
				if (radioFields[i].checked == true) {
					validRadio = true;
					break;
				} 
	
			}
			if(!validRadio){
				missing = true;
				errorText += "<li>Du har inte fyllt i om " + radioFields[0].title + " finns </li>";	
			}
		}
		if(selectFields.length > 0){
			for (var i = 0, il = selectFields.length; i < il; i++) {
				var validSelect = false;
				
				if (selectFields[i].value !== "-1" && selectFields[i].value !== "") {
					validSelect = true;
					break;
				} 
	
			}
			if(!validSelect){
				missing = true;
				errorText += "<li>Du har inte valt " + selectFields[0].title + "</li>";	
			}
		}
		if(minLength2Fields.length > 0){
			for (var i = 0, il = minLength2Fields.length; i < il; i++) {
				var validLength = false;				
				if (minLength2Fields[i].value.length >= 2) {
					validLength = true;
					break;
				} 	
			}
			if(!validLength){
				missing = true;
				errorText += "<li>" + minLength2Fields[0].title + " måste bestå av minst 2 tecken</li>";	
			}
		}
		
		errorText += "</ul>";

		if (errors || missing || !hasAcceptedConditions) {
			form.elmsByClass("alert-box").each(function() { this.parentNode.removeChild(this); });

			if($(this).hasClass("alert-on-top")) {
				target = HSB.getFirstNode(this);
			} else {
				var submitButtons = $(this).elmsByClass("submit");
				if (submitButtons.length > 0) {
					target = submitButtons[0];
				}
				
			}
			if (target) {
				HSB.alertBox.show(errorText, target);
			}
		} 

		return !(errors || missing || !hasAcceptedConditions);
	},
	setError : function(elem) {
		elem = $(elem);
		elem.addClass("error");
		elem.addEvent("keyup", HSB.formValidator.clearError);
		elem.focus();
	},
	clearError : function() {
		if (this.value.length !== 0) {
			$(this).removeClass("error");
		}
	}
};
HSB.addPlugin(HSB.formValidator);


/**
 * Tool Tips
 */
HSB.toolTip = {
	containerId : "inline-tooltip",
	toggleLink : "A.toggle-tooltip",
	closeLink : "#inline-tooltip A.cancel",

	init: function() {
		HSB.eventDelegator.registerClick(this.toggleLink, function() { 
				HSB.toolTip.getInstance().toggle();
			}
		);
		HSB.eventDelegator.registerClick(this.closeLink, function() {
				HSB.toolTip.getInstance().close();
			}
		);	
	},
	
	getInstance: function() {
		if (!HSB.toolTip.slider) {
			HSB.toolTip.slider = new HSB.slider($$(this.containerId));
		}
		return HSB.toolTip.slider;
	}
};
HSB.addPlugin(HSB.toolTip);


/**
 * Scroller
 */
HSB.scroller = {
	scrollerId: "scroller",
	scrollerNo: 0,
	duration: 500,
	
	onDOMReady: function() {
		$(".scroller").each(function() {
				var scrollerId = HSB.scroller.scrollerId + HSB.scroller.scrollerNo++;
				var wrapper = HSB.getFirstNode($(this));
				wrapper.id = scrollerId;
				var items = this.elmsByClass("scroll-item");
				wrapper.noOfItems = items.length;
				wrapper.itemNo = 0;
				wrapper.width = HSB.stripPx(this.getStyle("width"));
				$(wrapper).setStyle("width", this.width * this.noOfItems + "px");
				HSB.eventDelegator.registerClick("#" + this.id + " .previous", function() { 				
						HSB.scroller.scrollLeft(scrollerId);
						this.blur();
					}
				);
				HSB.eventDelegator.registerClick("#" + this.id + " .next", function() { 				
						HSB.scroller.scrollRight(scrollerId);
						this.blur();
					}
				);
			}
		);
	},

	switchElements: function(list, forward, width) {
		var el = $(forward ? list.firstChild : list.lastChild);
		if (el.nodeType == 3) {
			el.remove();
			el = $(forward ? list.firstChild : list.lastChild);
		}
		el.remove();
		list.setStyle("margin-left", forward ? 0 : -width + "px");
		if (forward) {
			list.appendChild(el);
		} else {
			list.insertBefore(el, list.firstChild);		
		}
	},

	scroll: function(id, forward) {
		var el = $$(id);
		if (!forward) {
			el.itemNo = el.itemNo - 1 < 0 ? el.noOfItems - 1 : el.itemNo - 1;
			HSB.scroller.switchElements(el, false, el.width);
		} else {
			el.itemNo = el.itemNo + 1 == el.noOfItems ? 0 : el.itemNo + 1;			
		}
		el.animate({"margin-left": forward ? -el.width : 0}, {duration: HSB.scroller.duration, easing: HSB.slider.easing, callback: function() {
			if (forward) {
				HSB.scroller.switchElements(el, true, el.width);
			}
		}});
	},
	
	scrollLeft: function(id) {
		HSB.scroller.scroll(id, false);
	},
	
	scrollRight: function(id) {
		HSB.scroller.scroll(id, true);
	}

};
HSB.addPlugin(HSB.scroller);


/**
 * Alert Box
 */
HSB.alertBox = {
	noOfAlertBoxes: 0,
	show: function(content, sibling) {
		var alertBox;
		if (sibling.alertBoxId) {
			alertBox = $$(sibling.alertBoxId);
		} 
		if (!alertBox) {			
			sibling.alertBoxId = "alert-box-" + this.noOfAlertBoxes;
			alertBox = document.createElement("div");
			sibling.parentNode.insertBefore(alertBox, sibling);
			alertBox.id = sibling.alertBoxId;
			this.noOfAlertBoxes++;
		}
		alertBox.setAttribute("role", "alert");
		alertBox.innerHTML = content + "<a href=\"#\" onclick=\"HSB.alertBox.close('" + sibling.alertBoxId + "'); return false;\" class=\"cancel\">Stäng</a>";
		alertBox.className = "alert-box";
		alertBox.style.display = "block";
		alertBox.style.opacity = "0";
		$(alertBox).show();	
	},
	close: function(elemId) {
		$$(elemId).remove();
	}
};


/**
 * Slider class
 * @param {Object} elem
 */
HSB.slider = function(elem) {
	this.elem = $(elem);
	this.wrapper = $(document.createElement("div"));
	this.wrapper.setAttribute("aria-live", "polite");
	this.wrapper.style.position = "relative";
	this.wrapper.style.overflow = "hidden";
	this.wrapper.style.height = "0";
	this.elem.style.display = "block";
	this.elemWidth = HSB.getActualWidth(this.elem);
	this.elemHeight = HSB.getActualHeight(this.elem);
	this.elem.parentNode.insertBefore(this.wrapper, this.elem);
	this.wrapper.appendChild(this.elem);
	this.elem.style.position = "absolute";
	this.elem.style.left = "0px";
	this.elem.style.bottom = "0px";
	this.elemWidthPadding = HSB.stripPx(elem.getStyle("padding-left")) + HSB.stripPx(elem.getStyle("padding-right"));
	this.isVisible = this.elem.hasClass("display");
	this.wrapper.style.width = (this.elemWidth) + "px";
	this.wrapper.style.height = (this.isVisible ? this.elemHeight : 0) + "px";
	this.elem.style.width = (this.elemWidth - this.elemWidthPadding) + "px";
	this.fullWidth = "auto";
	/*@cc_on
		this.fullWidth = (this.elemWidth - this.elemWidthPadding) + "px";
	@*/
};
HSB.slider.prototype.open = function(force, callback) {
	if (!this.isInTransition || force) {
		this.isInTransition = true;
		this.elemWidth = HSB.getActualWidth(this.elem);
		this.elemHeight = HSB.getActualHeight(this.elem);
		var slider = this;
		this.wrapper.animate({ height: this.elemHeight }, { duration: this.duration, easing: HSB.slider.easing, callback: function() { slider.isVisible = true; slider.isInTransition = false; slider.elem.style.position = "relative"; slider.elem.style.width = slider.fullWidth; this.style.height = "100%"; this.style.width = "100%"; if (callback) { callback(); } } });
	}
};
HSB.slider.prototype.close = function(force, callback) {
	if (!this.isInTransition || force) {
		this.isInTransition = true;
		this.elemWidth = HSB.getActualWidth(this.elem);
		this.elemHeight = HSB.getActualHeight(this.elem);
		this.elem.style.position = "absolute";
		this.wrapper.style.width = this.elemWidth + "px";
		this.wrapper.style.height = HSB.getActualHeight(this.elem) + "px";
		this.elem.style.width = (this.elemWidth - this.elemWidthPadding) + "px";
		var slider = this;
		this.wrapper.animate({ height: 0 }, { duration: this.duration, easing: HSB.slider.easing, callback: function() { slider.isVisible = false; slider.isInTransition = false; if (callback) { callback(); } } });
	}
};
HSB.slider.prototype.toggle = function(force, callback) {
	if (this.isVisible) {
		this.close(force, callback);
	} else {
		this.open(force, callback);
	}
};
HSB.slider.easing = function(timediff, base, change, duration) {
	return (timediff==duration) ? base+change : change * (-Math.pow(2, -10 * timediff/duration) + 1) + base;
};


HSB.toggleFieldset = {
	prefix : "toggle-fieldset",
	init: function() {
		var prefix = this.prefix;
		HSB.eventDelegator.registerClick("." + prefix, function() {
				state = !this.checked;
				fieldsetId = HSB.getClassNameValue(this, prefix);
				$("#" + fieldsetId + " input, #" + fieldsetId + " select").each(function() {
					this.disabled = state;
				});
				return true;
			}
		);
	}
}
HSB.addPlugin(HSB.toggleFieldset);

HSB.selectAll = {
	prefix : "select-all",
	init: function() {
		var prefix = this.prefix;
		HSB.eventDelegator.registerClick("." + prefix, function() {
				selectId = HSB.getClassNameValue(this, prefix);
				noOfUnselected = 0;
				$("#" + selectId + " option").each(function() {
					if (!this.selected) {
						noOfUnselected++;
						this.selected = true;
					}
				});
				if (noOfUnselected == 0) {
					$("#" + selectId + " option").each(function() {
						this.selected = false;
					});
				}
				
				return true;
			}
		);
	}
}
HSB.addPlugin(HSB.selectAll);

HSB.resetForm = {
	prefix : "reset-form",
	init: function() {
		var prefix = this.prefix;
		HSB.eventDelegator.registerClick("." + prefix, function() {
				formId = HSB.getClassNameValue(this, prefix);
				$$(formId).reset();
				return false;
			}
		);
	}
}
HSB.addPlugin(HSB.resetForm);

/**
 * AJAX Form Class
 * @param {Object} form
 */
HSB.AJAXForm = function(form) {
	form = $(form);
	form.isAJAXForm = true;
	form.beforeSubmissionHandler = function () { return true; };
	form.addEvent("submit", HSB.AJAXForm.sendForm);
	form.setBeforeSubmissionHandler = function(funcRef) {
		this.beforeSubmissionHandler = funcRef;
	};
	form.setResponseHandler = function(funcRef) {
		this.responseHandler = funcRef;
	};
	return form;
};
HSB.AJAXForm.sendForm = function() {
	if (this.beforeSubmissionHandler.call(this) !== false) {
		var fields = this.elements;
		var parameters = "";
		for (var i=0, il=fields.length, field, type, isSelect; i<il; i++) {
			field = fields[i];
			type = field.getAttribute("type");
			isSelect = /select/i.test(field.nodeName);
			if (field.getAttribute("name") && (/text|hidden|password|submit|image/i.test(type) || isSelect || (/radio|checkbox/i.test(type) && field.checked) || /textarea/i.test(field.nodeName))) {
				parameters += field.getAttribute("name") + "=" + escape(((isSelect)? field.options[field.selectedIndex].value : field.value)) + "&";
			}
		}
		parameters += "mode=ajax";
		this.ajax({
			url : this.getAttribute("action"),
			method: "POST",
			params : parameters.replace(/&*$/g, ""),
			callback : this.responseHandler,
			headers : this.headers || {}
		});
	}
	return false;
};


function debug(str) {
	if (!$$("debug")) {
		$(document.body).create("div", {
				id: "debug", 
				style: "position: absolute; right: 0; top: 0; font: 11px verdana; background: white; padding: 10px; background: white; opacity: .5; z-index: 9999;"
			},
			true
		);
	}
	if (typeof(str) === "string") {
		str = str.replace(">", "&gt;");
		str = str.replace("<", "&lt;");		
	}
	$$("debug").innerHTML += str + "<br/>";
}
