/*
 * HTML Parser By John Resig (ejohn.org)
 * Original code by Erik Arvidsson, Mozilla Public License
 * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js
 *
 * // Use like so:
 * HTMLParser(htmlString, {
 *     start: function(tag, attrs, unary) {},
 *     end: function(tag) {},
 *     chars: function(text) {},
 *     comment: function(text) {}
 * });
 *
 * // or to get an XML string:
 * HTMLtoXML(htmlString);
 *
 * // or to get an XML DOM Document
 * HTMLtoDOM(htmlString);
 *
 * // or to inject into an existing document/DOM node
 * HTMLtoDOM(htmlString, document);
 * HTMLtoDOM(htmlString, document.body);
 *
 */

(function(){

	// Regular Expressions for parsing tags and attributes
	var startTag = /^<(\w+)((?:\s+\w+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/,
		endTag = /^<\/(\w+)[^>]*>/,
		attr = /(\w+)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|([^>\s]+)))?/g;
		
	// Empty Elements - HTML 4.01
	var empty = makeMap("area,base,basefont,br,col,frame,hr,img,input,isindex,link,meta,param,embed");

	// Block Elements - HTML 4.01
	var block = makeMap("address,applet,blockquote,button,center,dd,del,dir,div,dl,dt,fieldset,form,frameset,hr,iframe,ins,isindex,li,map,menu,noframes,noscript,object,ol,p,pre,script,table,tbody,td,tfoot,th,thead,tr,ul");

	// Inline Elements - HTML 4.01
	var inline = makeMap("a,abbr,acronym,applet,b,basefont,bdo,big,br,button,cite,code,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,object,q,s,samp,script,select,small,span,strike,strong,sub,sup,textarea,tt,u,var");

	// Elements that you can, intentionally, leave open
	// (and which close themselves)
	var closeSelf = makeMap("colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr");

	// Attributes that have their values filled in disabled="disabled"
	var fillAttrs = makeMap("checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected");

	// Special Elements (can contain anything)
	var special = makeMap("script,style");

	var HTMLParser = this.HTMLParser = function( html, handler ) {
		var index, chars, match, stack = [], last = html;
		stack.last = function(){
			return this[ this.length - 1 ];
		};

		while ( html ) {
			chars = true;

			// Make sure we're not in a script or style element
			if ( !stack.last() || !special[ stack.last() ] ) {

				// Comment
				if ( html.indexOf("<!--") == 0 ) {
					index = html.indexOf("-->");
	
					if ( index >= 0 ) {
						if ( handler.comment )
							handler.comment( html.substring( 4, index ) );
						html = html.substring( index + 3 );
						chars = false;
					}
	
				// end tag
				} else if ( html.indexOf("</") == 0 ) {
					match = html.match( endTag );
	
					if ( match ) {
						html = html.substring( match[0].length );
						match[0].replace( endTag, parseEndTag );
						chars = false;
					}
	
				// start tag
				} else if ( html.indexOf("<") == 0 ) {
					match = html.match( startTag );
	
					if ( match ) {
						html = html.substring( match[0].length );
						match[0].replace( startTag, parseStartTag );
						chars = false;
					}
				}

				if ( chars ) {
					index = html.indexOf("<");
					
					var text = index < 0 ? html : html.substring( 0, index );
					html = index < 0 ? "" : html.substring( index );
					
					if ( handler.chars )
						handler.chars( text );
				}

			} else {
				html = html.replace(new RegExp("(.*)<\/" + stack.last() + "[^>]*>"), function(all, text){
					text = text.replace(/<!--(.*?)-->/g, "$1")
						.replace(/<!\[CDATA\[(.*?)]]>/g, "$1");

					if ( handler.chars )
						handler.chars( text );

					return "";
				});

				parseEndTag( "", stack.last() );
			}

			if ( html == last )
				throw "Parse Error: " + html;
			last = html;
		}
		
		// Clean up any remaining tags
		parseEndTag();

		function parseStartTag( tag, tagName, rest, unary ) {
			if ( block[ tagName ] ) {
				while ( stack.last() && inline[ stack.last() ] ) {
					parseEndTag( "", stack.last() );
				}
			}

			if ( closeSelf[ tagName ] && stack.last() == tagName ) {
				parseEndTag( "", tagName );
			}

			unary = empty[ tagName ] || !!unary;

			if ( !unary )
				stack.push( tagName );
			
			if ( handler.start ) {
				var attrs = [];
	
				rest.replace(attr, function(match, name) {
					var value = arguments[2] ? arguments[2] :
						arguments[3] ? arguments[3] :
						arguments[4] ? arguments[4] :
						fillAttrs[name] ? name : "";
					
					attrs.push({
						name: name,
						value: value,
						escaped: value.replace(/(^|[^\\])"/g, '$1\\\"') //"
					});
				});
	
				if ( handler.start )
					handler.start( tagName, attrs, unary );
			}
		}

		function parseEndTag( tag, tagName ) {
			// If no tag name is provided, clean shop
			if ( !tagName )
				var pos = 0;
				
			// Find the closest opened tag of the same type
			else
				for ( var pos = stack.length - 1; pos >= 0; pos-- )
					if ( stack[ pos ] == tagName )
						break;
			
			if ( pos >= 0 ) {
				// Close all the open elements, up the stack
				for ( var i = stack.length - 1; i >= pos; i-- )
					if ( handler.end )
						handler.end( stack[ i ] );
				
				// Remove the open elements from the stack
				stack.length = pos;
			}
		}
	};
	
	this.HTMLtoXML = function( html ) {
		var results = "";
		
		HTMLParser(html, {
			start: function( tag, attrs, unary ) {
				results += "<" + tag;
		
				for ( var i = 0; i < attrs.length; i++ )
					results += " " + attrs[i].name + '="' + attrs[i].escaped + '"';
		
				results += (unary ? "/" : "") + ">";
			},
			end: function( tag ) {
				results += "</" + tag + ">";
			},
			chars: function( text ) {
				results += text;
			},
			comment: function( text ) {
				results += "<!--" + text + "-->";
			}
		});
		
		return results;
	};
	
	this.HTMLtoDOM = function( html, doc ) {
		// There can be only one of these elements
		var one = makeMap("html,head,body,title");
		
		// Enforce a structure for the document
		var structure = {
			link: "head",
			base: "head"
		};
	
		if ( !doc ) {
			if ( typeof DOMDocument != "undefined" )
				doc = new DOMDocument();
			else if ( typeof document != "undefined" && document.implementation && document.implementation.createDocument )
				doc = document.implementation.createDocument("", "", null);
			else if ( typeof ActiveX != "undefined" )
				doc = new ActiveXObject("Msxml.DOMDocument");
			
		} else
			doc = doc.ownerDocument ||
				doc.getOwnerDocument && doc.getOwnerDocument() ||
				doc;
		
		var elems = [],
			documentElement = doc.documentElement ||
				doc.getDocumentElement && doc.getDocumentElement();
				
		// If we're dealing with an empty document then we
		// need to pre-populate it with the HTML document structure
		if ( !documentElement && doc.createElement ) (function(){
			var html = doc.createElement("html");
			var head = doc.createElement("head");
			head.appendChild( doc.createElement("title") );
			html.appendChild( head );
			html.appendChild( doc.createElement("body") );
			doc.appendChild( html );
		})();
		
		// Find all the unique elements
		if ( doc.getElementsByTagName )
			for ( var i in one )
				one[ i ] = doc.getElementsByTagName( i )[0];
		
		// If we're working with a document, inject contents into
		// the body element
		var curParentNode = doc.createDocumentFragment();
		var result = curParentNode;
		
		HTMLParser( html, {
			start: function( tagName, attrs, unary ) {
				// If it's a pre-built element, then we can ignore
				// its construction
				if ( one[ tagName ] ) {
					curParentNode = one[ tagName ];
					return;
				}
			
				var elem = doc.createElement( tagName );
				
				for ( var attr in attrs ) {
					if (attrs[attr].name == 'style') {
						setStyle(elem, attrs[attr].value);
					} else {
						elem.setAttribute( attrs[ attr ].name, attrs[ attr ].value.decode() );
					}
				}
				
				if ( structure[ tagName ] && typeof one[ structure[ tagName ] ] != "boolean" )
					one[ structure[ tagName ] ].appendChild( elem );
				
				else if ( curParentNode && curParentNode.appendChild )
					curParentNode.appendChild( elem );
					
				if ( !unary ) {
					elems.push( elem );
					curParentNode = elem;
				}
			},
			end: function( tag ) {
				elems.length -= 1;
				
				// Init the new parentNode
				curParentNode = elems[ elems.length - 1 ];
			},
			chars: function( text ) {
				if (!text.match(/^\s+$/))
					curParentNode.appendChild( doc.createTextNode( text.decode() ) );
			},
			comment: function( text ) {
				// create comment node
			}
		});
		
		return result;
	};

	function makeMap(str){
		var obj = {}, items = str.split(",");
		for ( var i = 0; i < items.length; i++ )
			obj[ items[i] ] = true;
		return obj;
	}

	var camelCase = (function(){
		var reg = /\-([a-z])/g;
		function f(a, l) {
			return l.toUpperCase();
		}
		return function(s) {
			if (s == 'float')
				s = 'cssFloat';
			else
				s = s.replace(reg, f);
			return s;
		};
	})();

	function setStyle(elm, style) {
		style = style.split(/\s*;\s*/);
		var reg = /^([^\s:]+)\s*:\s*(.*)$/, s;
		for (var i = 0; i < style.length; i++) {
			s = style[i].match(reg);
			if (s) {
				elm.style[camelCase(s[1])] = s[2];
			}
		}
	}
})();
/**
 * End of HTML Parser
 */



(function() {
	if (typeof XMLHttpRequest === 'undefined') {
		window.XMLHttpRequest = function() {
			var t = [
				'Msxml2.XMLHTTP.6.0',
				'Msxml2.XMLHTTP.3.0',
				'Msxml2.XMLHTTP',
				'Microsoft.XMLHTTP'
			];
			var result = null;
			for (var i = 0; i < t.length && !result; i++) {
				try {
					result = new ActiveXObject(t[i]);
				} catch (e) {}
			}
			if (!result) {
				throw new Error('XMLHttpRequest not supported');
			}
			return result;
		};
	}
})(); 

window.Ajax = (function(){
	function makeRequest(type, url) {
		var request = new XMLHttpRequest();
		request.open(type, url, true);
		if (type == 'POST') {
			request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
		}
		return request;
	};
	function preparePostData(data) {
        if (data && typeof data === 'object') {
            var list = [];
            for (var i in data) {
                list.push(encodeURIComponent(i)+'='+encodeURIComponent(data[i]));
            }
            data = list.join('&');
        } else {
            data = null;
        }
		return data;
	};
	var specialTags = /^\s*<(li|tr|td|tbody|thead|tfoot|th|caption|colgroup|col|dd|dt)(?:\s|>)/i;
	var specialTops = {
		li: 'ul',
		tr: 'tbody',
		tbody: 'table',
		thead: 'table',
		tfoot: 'table',
		th: 'tr',
		td: 'tr',
		caption: 'table',
		colgroup: 'table',
		col: 'colgroup',
		dd: 'dl',
		dt: 'dl'
	};
	function createFragment(content) {
		/*
		var absoluteTop;
		var tags = [];
		var top;
		var fragment = document.createDocumentFragment();
		var tag = content.match(specialTags);
		if (tag) {
			tag = tag[1].toLowerCase();
			tag = specialTops[tag];
			while (specialTops[tag]) {
				tags.push(tag);
				tag = specialTops[tag];
			}
			top = absoluteTop = document.createElement(tag);
			for (var i = tags.length -1; i >= 0; i--) {
				top = top.appendChild(document.createElement(tags[i]));
			}
		} else {
			top = document.createElement('div');
		}*/
		return HTMLtoDOM(content.trim(), document);
		// return fragment;
	};
	var insertType = /^(before|after|append|insert[0-9]*|replace)\s+([^\s]+)(?:\s+remove\s*(.*))?$/;
	/**
	 * before id
	 *   Indsætter indholdet før elementet med det id.
	 * after id
	 *   Indsætter indholdet efter elementet med det id.
	 * append id
	 *   Indsætter indholdet inde i elementet som det sidste
	 * insert[tal] id
	 *   Indsætter indholdet på [tal]'s position, eller først i elementet
	 * replace id
	 *   Erstatter hele elementet med indholdet
	 * Efter strengen kan der skrives "remove id".
	 * Hvis id undlades fjernes linket som aktiverede ajax, ellers fjernes elementet med det id.
	 */
	function handleResult(id, html, sender) {
		var type = id.match(insertType);
		var index, remove = null;
		if (type) {
			id = type[2];
			if (typeof type[3] == 'string')
				remove = type[3] == '' ? sender : document.getElementById(type[3]);
			type = type[1];
			index = type.match(/^insert([0-9]*)/);
			if (index) {
				index = index[1];
				if (!index)
					index = 0;
				type = 'insert';
			}
		}
		id = document.getElementById(id);
		if (id) {
			html = createFragment(html);
			switch (type) {
				case 'before':
					id.parentNode.insertBefore(html, id);
					break;
				case 'after':
					id.parentNode.insertBefore(html, id.nextSibling);
					break;
				case 'append':
					id.appendChild(html);
					break;
				case 'insert':
					index = id.childNodes[index];
					if (!index)
						index = null;
					id.insertBefore(html, index);
					break;
				case 'replace':
					id.parentNode.replaceChild(html, id);
					break;
				default:
					while (id.firstChild)
						id.removeChild(id.firstChild);
					id.appendChild(html);
					break;
			}
		}
		if (remove) {
			remove.parentNode.removeChild(remove);
		}
	};
	function setCallback(request, id, sender) {
		request.onreadystatechange = function() {
			if (request.readyState == 4) {
				switch (request.status) {
					case 200:
						handleResult(id, request.responseText, sender);
						break;
					case 500:
						alert('Der skete en fejl. Der er sendt en e-mail til udviklerne med problemet.');
						break;
					default:
						alert('Noget gik ikke som det skulle...');
						break;
				}
			}
		};
	};
	return {
		/**
		 * Accepted parameters:
		 * url: Url to request
		 * id: Puts the response of the request into the element with this id
		 */
		get: function(object) {
			if (typeof object.url === 'string') {
				var request = makeRequest('GET', object.url);
				if (object.id) {
					setCallback(request, object.id, object.sender);
				}
				request.send(null);
			}
		},
		/**
		 * Accepted parameters:
		 * url: Url to request
		 * id: Puts the response of the request into the element with this id,
		 * data: Object with attributes (ex. {search: 'string', type: 15})
		 */
		post: function(object) {
			if (typeof object.url === 'string') {
				var request = makeRequest('POST', object.url);
				if (object.id) {
					setCallback(request, object.id);
				}
				request.send(preparePostData(object.data));
			}
		}
	}
})();

document.onclick = function(event) {
	event = event || window.event;
	var elm, result;
	if (elm = (event.target || event.srcElement)) {
		while (elm && elm.tagName != 'A') {
			elm = elm.parentNode;
		}
		if (elm && elm.className.match(/(?:^|\s+)ajax(?:\s+|$)/)) {
			var object = {
				url: elm.getAttribute('href'),
				id: elm.getAttribute('rel'),
				sender: elm
			};
			if (object.id && object.url) {
				if (event.preventDefault)
					event.preventDefault();
				result = false;
				Ajax.get(object);
			}
		}
	}
	return result;
};

window.goas = {
	openDeltager: function(event, anchor) {
		event = event || window.event;
		var tr = anchor.parentNode.parentNode;
		if (event.preventDefault)
			event.preventDefault();
		if (event.stopPropagation)
			event.stopPropagation();
		if (anchor.className == 'open') {
			anchor.className = 'closed';
			anchor.firstChild.src = '/images/green/menu_elementer/plus.gif';
			var next = tr.nextSibling;
			while (next && next.nodeType != 1)
				next = next.nextSibling;
			if (next && next.id == '') {
				tr.parentNode.removeChild(next);
			}
		} else {
			anchor.className = 'open';
			anchor.firstChild.src = '/images/green/menu_elementer/minus.gif';
			Ajax.get({
				url: anchor.href,
				id: 'after '+tr.id
			});
		}
		return false;
	}
};

String.prototype.trim = function() {
	return this.replace(/^\s+|\s+$/g, "");
};

String.prototype.decode = (function () {
	var entities = {
		AElig: "\xC6",
		Oslash: "\xD8",
		Aring: "\xC5",
		aelig: "\xE6",
		oslash: "\xF8",
		aring: "\xE5",
		eacute: "\xE9",
		Eacute: "C9",
		amp: "&",
		quot: '"',
		apos: "'",
		lt: "<",
		gt: ">",
		nbsp: "\xA0"
	},
	reg = /&((\w|#)+);/g,
	func = function (a, entity) {
		var result;
		if (entities[entity]) {
			result = entities[entity];
		} else {
			if (result = entity.match(/#([0-9]+)/)) {
				result = String.fromCharCode(parseInt(result[1]))
			} else {
				result = entity;
			}
		}
		return result;
	};
	return function () {
		return this.replace(reg, func);
	}
})();