/* page.js|global */
// page object
var Page = new function(){

	// Utility functions object (all functions declared in utilities)
	this.Util = new Object();
	// Page element Objects array
	this.Objects = new Array();

	// defining Page.HOST, Page.GFX based on hosts page.js inclusion path
	this.SRC = document.getElementById("page.js") ? document.getElementById("page.js").src : false;
	if(this.SRC){
		this.HOST = this.SRC.replace("/page.js", "");
		this.GFX = this.HOST+"/img";
	}else{
		alert("Fejl i inkluderingen af page.js");
	}

}
/* util_basics.js|global */
/* START browser definition utilities */
Page.Util.explorer = function(){
	if(document.all){
		return true;
	}
	return false;
}
Page.Util.safari = function(){
	if(navigator.appVersion.indexOf("Safari") >= 0){
		return true;
	}
	return false;
}
Page.Util.firefox = function(){
	if(navigator.userAgent.indexOf("Firefox") >= 0){
		return true;
	}
	return false;
}
/* END browser definition utilities */

// kills click (to prevent click from bubbling)
Page.Util.nonClick = function(event){
	event = event ? event : window.event;
	if(event.preventDefault){event.preventDefault();}
	if(event.stopPropagation){event.stopPropagation();}
	event.returnValue = false;
	event.cancelBubble = true;
}

// add event handler ...
Page.Util.addEventHandler = function(element, eventType, action){
	if(Page.Util.explorer()){
		element.attachEvent("on" + eventType, action);
	}else{
		element.addEventListener(eventType, action, false);
	}
}
// remove event handler 
Page.Util.removeEventHandler = function(element, eventType, action){
	if(Page.Util.explorer()){
		element.detachEvent("on" + eventType, action);
	}else{
		element.removeEventListener(eventType, action, false);
	}
}

// extracting variable from location search
Page.Util.getVar = function(string){
	var startIndex = (location.search.indexOf("&" + string + "=") > -1) ? location.search.indexOf("&" + string + "=") + string.length + 2 : ((location.search.indexOf("?" + string + "=") > -1) ? location.search.indexOf("?" + string + "=") + string.length + 2 : false);
	var endIndex = (location.search.substring(startIndex).indexOf("&") > -1) ? location.search.substring(startIndex).indexOf("&")+startIndex : false;
	var returnString = (startIndex) ? location.search.substring(startIndex,((endIndex) ? endIndex : location.search.length)): "";
	return returnString;
}

// compiles mailto link based on name and domain
Page.Util.otliam = function(name, domain){
	document.write('<a href="mailto:'+name+'@'+domain+'">'+name+"@"+domain+'</a>');
}

// post function
Page.Util.post = function(url, array, target) {

	// create post form
	post_form = document.createElement('form');
	post_form.id = "postform";
	post_form.method = "post";
	post_form.action = url;
	post_form.target = target ? target : "";
	document.body.appendChild(post_form);

	// find selected documents
	for(x in array){
		if(typeof(array[x]) != "function") {
			inputfield = document.createElement('input');
			inputfield.name = x;
			inputfield.value = array[x];
			post_form.appendChild(inputfield);
		}
	}
	// submit form
	post_form.submit();
	// remove form
	document.body.removeChild(post_form);

}
/* util_interface.js|global */
// parses document and enables buttons and more
Page.Util.awakeInterface = function(){

	if(document.getElementById("mdTm")){
		Page.Util.unSelectify(document.getElementById("mdTm"));
	}
	if(document.getElementById("mdHm")){
		Page.Util.unSelectify(document.getElementById("mdHm"));
	}
	if(document.getElementById("mdLm")){
		Page.Util.unSelectify(document.getElementById("mdLm"));
	}
	if(typeof(Page.Util.initButtons) == "function"){
		Page.Util.initButtons();
	}
	if(typeof(Page.Util.initInputs) == "function"){
		Page.Util.initInputs();
	}
	if(typeof(Page.Util.initComponents) == "function"){
		Page.Util.initComponents(document.getElementById("mdBody"));
	}
	if(typeof(Page.Util.localAwakening) == "function"){
		Page.Util.localAwakening();
	}
}

// make elements unselectable
Page.Util.unSelectify = function(element){
	if(Page.Util.explorer()){
		element.onselectstart = function(){return false;}
	}else{
		element.onmousedown = function(){return false;}
	}
}

// fake submits form on key "Enter", calls function "action"
Page.Util.submitOnEnter = function(event, action){
	event = event ? event : window.event;
	if(event.keyCode == 13){
		if(event.preventDefault){event.preventDefault();}
		if(event.stopPropagation){event.stopPropagation();}
		event.returnValue = false;
		event.cancelBubble = true;
		action();
	}
}

/* util_dom.js|global */
// returns the first parent tag (which)
Page.Util.getParentTag = function(which, element){
	 if(element.nodeName != which && element.nodeName != "BODY"){
		  element = Page.Util.getParentTag(which,element.parentNode);
	 } 
	 return element;
}

// check for type definition of element. Defined by identifier:type
Page.Util.getTypeDefinitionByClassName = function(identifier, element){
	var regexp = new RegExp(identifier+":[?=\\w/\\#~:.?+=?&%@!\\-]*");
	if(element.className.match(regexp)){
		return element.className.match(regexp)[0].replace(identifier+":", "");
	}else{
		return false;
	}
}

// get elements in optional content with classname (default content is mdBodyContent)
Page.Util.getElementsByClassName = function(classname, content){
	var element, i, elements;
	var returnArray = new Array();
	elements = content ? (typeof(content) == "string" ? document.getElementById(content).getElementsByTagName("*") : content.getElementsByTagName("*")) : document.getElementById("mdBodyContent").getElementsByTagName("*");
	// IE < 6 needs a bit of help getting elements
	elements = (elements.length ? elements : (Page.Util.explorer() ? document.all : elements));
	var regexp = new RegExp("(^|\\s)" + classname + "(\\s|$|\:)");
	for(i = 0;(element = elements[i]); i++){
		if(regexp.test(element.className)){
			returnArray[returnArray.length] = element;
		}
	}
	return returnArray;
}

// get elements in optional content with attribute (default content is mdBodyContent)
Page.Util.getElementsByAttribute = function(attribute, content){
	var element, i, elements;
	var returnArray = new Array(); 
	elements = content ? (typeof(content) == "string" ? document.getElementById(content).getElementsByTagName("*") : content.getElementsByTagName("*")) : document.getElementById("mdBodyContent").getElementsByTagName("*");
	// IE < 6 needs a bit of help getting elements
	elements = (elements.length ? elements : (Page.Util.explorer() ? document.all : elements));
	for(i = 0;(element = elements[i]); i++){
		if(element.getAttribute(attribute)){
			returnArray[returnArray.length] = element;
		}
	}
	return returnArray;
}

// returns previous sibling, not counting text nodes as siblings (also ignoring optional exclude=classname or exclude=nodeName)
Page.Util.previousRealSibling = function(element, exclude){
	var regexp, previous;
	exclude = typeof(exclude) != "undefined" ? exclude : false;
	regexp = new RegExp("(^|\\s)" + exclude + "(\\s|$)");
	previous = element.previousSibling;
	if(exclude){
		while(previous && (previous.nodeType == 3 || previous.className.match(regexp) || previous.nodeName == exclude)){
			previous = previous.previousSibling;
		}
	}else{
		while(previous && previous.nodeType == 3){
			previous = previous.previousSibling;
		}
	}
	return previous;
}

// returns next sibling, not counting text nodes as siblings (also ignoring exclude=classname or exclude=nodeName)
Page.Util.nextRealSibling = function(element, exclude){
	var regexp, next;
	exclude = typeof(exclude) != "undefined" ? exclude : false;
	regexp = new RegExp("(^|\\s)" + exclude + "(\\s|$)");
	next = element.nextSibling;
	if(exclude){
		while(next && (next.nodeType == 3 || next.className.match(regexp) || next.nodeName == exclude)){
			next = next.nextSibling;
		}
	}else{
		while(next && next.nodeType == 3){
			next = next.nextSibling;
		}
	}
	return next;
}

// get elements computed style value for css attribute
Page.Util.getStyleValue = function(element, attribute){

	// Correct W3C method (Mozilla)
	if (document.defaultView && document.defaultView.getComputedStyle) {
		return document.defaultView.getComputedStyle(element, null).getPropertyValue(attribute);

	// Internet Explorer only
	}else if(document.body.currentStyle) {
		attribute = attribute.replace(/(-\w)/g, function(word){return word.replace(/-/, "").toUpperCase()});
		return element.currentStyle[attribute];
	}else{
		return false;
	}
}
/* util_components.js|global */
// initialize components
Page.Util.initComponents = function(container){
	var i, element, elements, definition;
	// additional initializations based on class name
	elements = Page.Util.getElementsByClassName("init([:a-z])+", container);
	for(i = 0; element = elements[i]; i++){
		// get init definition
		definition = Page.Util.getTypeDefinitionByClassName("init", element);
		// if object exists, init element
		if(definition && typeof(Page.Objects[definition]) == "object"){
			Page.Objects[definition].init(element);
		}
	}
}
/* util_buttons.js|global */
Page.Util.initButtons = function(){
	var buttons, button, i;
	buttons = document.getElementsByTagName('button');
	for(i = 0; button = buttons[i]; i++){
		// change focus and blur of all button elements
		Page.Util.addEventHandler(button, "mouseover", Page.Util.buttonOver);
		Page.Util.addEventHandler(button, "mouseout", Page.Util.buttonOut);
		Page.Util.addEventHandler(button, "mousedown", Page.Util.buttonDown);
	}
}
// button activity
Page.Util.buttonOver = function(){
	var element = (window.event ? window.event.srcElement : this);
	element.className += (element.className) ? ' over' : 'over';
}
Page.Util.buttonDown = function(){
	var element = (window.event ? window.event.srcElement : this);
	element.className += (element.className) ? ' down' : 'down';
}
Page.Util.buttonOut = function(){
	var element = (window.event ? window.event.srcElement : this);
	element.className = element.className.replace(/ over| down|over|down/g,"");
}
/* obj_datagrid.js|global */
Page.Objects["datagrid"] = new function(){

	this.init = function(datagrid){
		var header, body, element, i;

		// Some specialchars do not have an alphabetically correct charCode
		datagrid.correctCharOrder = function(value) {

			// In array below you can define a new charCode for misplaced chars (used only for sorting)
			var misplacedChars = new Array();
			misplacedChars["\xE5"] = 250;

			var regexp = "";
			for(x in misplacedChars) {
				if(typeof(misplacedChars[x]) == "number") {
					regexp += (regexp ? "|" : "") + x;
				}
			}
			regexp = new RegExp(regexp, "g");
			value = value.replace(regexp, function(c){return String.fromCharCode(misplacedChars[c])});
			return value;
		}
		// compare function for sort
		datagrid.compare = function(a, b) {
			if (a.value == b.value) {
				return 0;
			}
			else if (a.value < b.value) {
				return -1;
			}
			else {
				return 1;
			}
		}

		// select row
		datagrid.select = function(element_index){
			var element = this.elements[element_index];
			if(!element.className.match(/unselectable/g) && !element.className.match(/head/g) && element.getElementsByTagName("input").length) {
				element.className += element.className ? " selected" : "selected";
				element.className = element.className.replace(/ over|over/g,"");
				element.getElementsByTagName("input")[0].checked = true;
				this.updateToolbar();
			}
		}

		// deselect row
		datagrid.deselect = function(element_index){
			var element = this.elements[element_index];
			if(!element.className.match(/unselectable/g) && !element.className.match(/head/g) && element.getElementsByTagName("input").length) {
				element.className = element.className.replace(/ selected|selected/g,"");
				element.getElementsByTagName("input")[0].checked = false;
				this.updateToolbar();
			}
		}

		// select/deselect all rows
		datagrid.selectall = function(){
			var check, i;
			// should we check or uncheck
			check = (this.countSelected() < this.countRows()) ? true : false; // elements.length - 1, don't count header row
			for(i = 1; i < this.elements.length; i++){
				if(check){
					this.select(i);
				}else{
					this.deselect(i);
				}
			}
		}

		// count number of actual rows (excluding subheaders)
		datagrid.countRows = function(){
			var count, element, i;
			count = 0;
			for(i = 1; element = this.elements[i]; i++){
				if(!element.className.match(/unselectable/g) && !element.className.match(/head/g) && element.getElementsByTagName("input").length){
					count++;
				}
			}
			return count;
		}

		// count number of selected rows
		datagrid.countSelected = function(){
			var count, element, i;
			count = 0;
			for(i = 1; element = this.elements[i]; i++){
				if(element.className.match(/selected/g)){
					count++;
				}
			}
			return count;
		}

		// get array of selected rows
		datagrid.getSelected = function(){
			var element, elements, i;
			elements = new Array();
			for(i = 1; element = this.elements[i]; i++){
				if(element.className.match(/selected/g)){
					elements[elements.length] = element;
				}
			}
			return elements;
		}

		// find child text node with content (besides space)
		datagrid.getRowValue = function(row) {
			var i, node, value_type;
			node = Page.Util.getElementsByClassName("row:value", row)[0];

			value_type = Page.Util.getTypeDefinitionByClassName("row:value", node);
			value_type = value_type ? value_type : "text";

			if(value_type == "text") {
				return this.findTextNode(node);
			}
			else {
				return node.getAttribute(value_type);
			}
		}

		// find child text node with content (besides space)
		datagrid.getRowTitle = function(row) {
			var i, node, value_type;
			node = Page.Util.getElementsByClassName("row:title", row)[0];

			value_type = Page.Util.getTypeDefinitionByClassName("row:title", node);
			value_type = value_type ? value_type : "text";

			if(value_type == "text") {
				return this.findTextNode(node);
			}
			else {
				return node.getAttribute(value_type);
			}
		}

		// find child text node with content (besides space)
		datagrid.findTextNode = function(element) {
			var i, node;
			for(i = 0; node = element.childNodes[i]; i++) {
				if(node.nodeType == 3 && node.nodeValue && node.nodeValue.trim()) {
					return node.nodeValue;
				}
				else if(node.childNodes.length) {
					return this.findTextNode(node);
				}
			}
			return "";
		}

		// sort by column
		datagrid.sortBy = function(column_header) {
			var time1 = new Date().getTime();

			var header, direction, ascii, sorting, i, u, o, element;

			if(!this.indexed) {
				for(i = 0; header = this.headers[i]; i++) {
					if(header.type == "sortable"){
						// is sorttype defined?
						if(header.sort == "numeric") {
							header.ascii = false;
						}
						else if(header.sort == "ascii") {
							header.ascii = true;
						}
						// else guess ...
						else {
							if(Page.Util.getTypeDefinitionByClassName("sortby", this.elements[1].cells[header.column])) {
								header.ascii = isNaN(Page.Util.getTypeDefinitionByClassName("sortby", this.elements[1].cells[header.column]));
							}
							else {
								header.ascii = isNaN(this.findTextNode(this.elements[1].cells[header.column]));
							}
						}

						// index
						for(u = 1, o = 0; element = this.elements[u]; u++, o++) {

							header.sortInfo[o] = new Object();
							header.sortInfo[o].row = element;

							// do we have sortby definition
							if(Page.Util.getTypeDefinitionByClassName("sortby", element.cells[i])) {
								header.sortInfo[o].value = Page.Util.getTypeDefinitionByClassName("sortby", element.cells[i]).toLowerCase();
							}
							// otherwise find textnode
							else {
								header.sortInfo[o].value = this.findTextNode(element.cells[i]).toLowerCase();
							}
							if (header.ascii) {
								header.sortInfo[o].value = this.correctCharOrder(header.sortInfo[o].value);
							}
							else {
								header.sortInfo[o].value = parseFloat(header.sortInfo[o].value);
								if (isNaN(header.sortInfo[o].value)) {
									header.sortInfo[o].value = Number.NEGATIVE_INFINITY;
								}
							}
						}
					}
				}
				this.indexed = true;
			}

			// check for direction
			direction = column_header.className ? (column_header.className.match(/sortup/g) ? "sortdown" : "sortup") : "sortup";
			// reset direction indicators
			for(i = 0; header = this.headers[i]; i++) {
				header.className = header.className.replace(/ sortup|sortup | sortdown|sortdown |sortup|sortdown/g, "");
			}
			column_header.className += column_header.className ? " "+direction : direction;

			// sort
			this.headers[column_header.column].sortInfo.sort(this.compare);

			// reappend
			if(direction == "sortdown") {
				for(i = this.headers[column_header.column].sortInfo.length-1; element = this.headers[column_header.column].sortInfo[i]; i--) {
					this.body.appendChild(element.row);
				}
			}
			else {
				for(i = 0; element = this.headers[column_header.column].sortInfo[i]; i++) {
					this.body.appendChild(element.row);
				}
			}

			this.resetRowColor();
		}

		// reset row coloring
		datagrid.resetRowColor = function(){
			var row_color_options, element, i;
			row_color_options = new Array("even", "odd");
			for(i = 1;  element = this.elements[i]; i++){
				element.className = element.className.replace(/odd|even/g, row_color_options[i%2]);
			}
		}

		// update toolbar buttons according to selected rows
		datagrid.updateToolbar = function(){
			if(this.toolbar){
				this.toolbar.update();
			}
		}

		// get body
		datagrid.body = datagrid.getElementsByTagName("tbody")[0];

		// get headers
		datagrid.headers = datagrid.getElementsByTagName("th");
		// initiate all elements in header
		for(i = 0; header = datagrid.headers[i]; i++){
			// un-select text on datagrid buttons
			Page.Util.unSelectify(header);

			header.datagrid = datagrid;
			header.type = Page.Util.getTypeDefinitionByClassName("datagrid", header);
			header.sort = Page.Util.getTypeDefinitionByClassName("sort", header);
			header.sortInfo = new Array();

			if(header.type == "sortable" || header.type == "selectall" || header.onclick){
				header.className += header.className ? " clickable" : "clickable";

				// if js sortable
				if(header.type == "sortable"){
					header.column = i;
					datagrid.indexed = false;
					header.onclick = function(){
						this.datagrid.sortBy(this);
					}
				}
				// set onclick on select all element
				else if(header.type == "selectall"){
					header.onclick = function(){
						this.datagrid.selectall();
					}
				}
				// set mouseover
				header.onmouseover = function(){
					this.className += this.className ? " over" : "over";
				}
				// set mouseout
				header.onmouseout = function(){
					this.className = this.className.replace(/ over|over/g,"");
				}
			}
		}

		// get list entries
		datagrid.elements = datagrid.getElementsByTagName("tr");
		// initiate all row elements in grid
		for(i = 1; element = datagrid.elements[i]; i++){
			element.datagrid = datagrid;
			element.index = i;

			// only initiate mouseover/mouseout/click if rows contain checkbox
			if(element.getElementsByTagName("input").length > 0){

				element.className += element.className ? " clickable" : "clickable";
				// if element is selected
				if(element.getElementsByTagName("input")[0].checked){
					element.className += element.className ? " selected" : "selected";
				}

				// set mouseover
				element.onmouseover = function() {
					this.className += this.className ? " over" : "over";
				}
				// set mouseout
				element.onmouseout = function() {
					this.className = this.className.replace(/ over|over/g,"");
				}
				// set onclick
				element.onclick = function() {
					if(this.className.match(/selected/g)){
						this.datagrid.deselect(this.index);
					}else{
						this.datagrid.select(this.index);
					}
				}
			}
		}

		// update toolbar (only has effect if datagrid is associated with toolbar)
		datagrid.updateToolbar();
	}

}

