
/*FILEHEAD(/in/jpf.js)SIZE(53971)TIME(1213483123975)*/
/** 
* @projectDescription 	Javeline Platform
*
* @author	Ruben Daniels ruben@javeline.nl
* @version	1.0
* http://java.sun.com/j2se/javadoc/writingdoccomments/
* http://www.scriptdoc.org/specification.htm
*/

VERSION 			= 0x000982;

DOC_NODE       = 100;
NOGUI_NODE     = 101;
GUI_NODE       = 102;
KERNEL_MODULE  = 103;
MF_NODE        = 104;

//CGI VARS
var HTTP_GET_VARS={}, vars = location.href.split(/[\?\&\=]/);
for(var k=1;k<vars.length;k+=2) HTTP_GET_VARS[vars[k]] = vars[k+1] || "";

Array.prototype.dataType = "array";
Number.prototype.dataType = "number";
Date.prototype.dataType = "date";
Boolean.prototype.dataType = "boolean";
String.prototype.dataType = "string";
RegExp.prototype.dataType = "regexp";
Function.prototype.dataType = "function";

//Start of the Javeline PlatForm namespace
jpf = {
	AppData : null,
	IncludeStack : [],
	isInitialized : false,
	autoLoadSkin : true,
	
	debug : true,
	debugType : "Memory",
	debugFilter : "!teleport",
	
	browserDetect : function(){
		//Browser Detection
		this.isOpera = navigator.userAgent.toLowerCase().indexOf("opera") != -1;
		
		this.isKonqueror = navigator.userAgent.toLowerCase().indexOf("konqueror") != -1;
		this.isSafari = !this.isOpera && ((navigator.vendor && navigator.vendor.match(/Apple/) ? true : false) || navigator.userAgent.toLowerCase().indexOf("safari") != -1 || this.isKonqueror);
		this.isSafariOld = false;
		if(this.isSafari){
			var matches = navigator.userAgent.match(/AppleWebKit\/(\d+)/);
			if(matches) this.isSafariOld = parseInt(matches[1]) < 420;
		}
		
		this.isGecko = !this.isOpera && !this.isSafari && navigator.userAgent.toLowerCase().indexOf("gecko") != -1;
		this.isGecko3 = this.isGecko && navigator.userAgent.toLowerCase().indexOf("firefox/3") != -1;
		this.isIE = document.all && !this.isOpera && !this.isSafari ? true : false;
		this.isIE50 = this.isIE && navigator.userAgent.toLowerCase().indexOf("5.0") != -1;
		this.isIE55 = this.isIE && navigator.userAgent.toLowerCase().indexOf("5.5") != -1;
		this.isIE6 = this.isIE && navigator.userAgent.toLowerCase().indexOf("6.") != -1;
		this.isIE7 = this.isIE && navigator.userAgent.toLowerCase().indexOf("7.") != -1;
		
		if(this.onbrowsercheck) this.onbrowsercheck();
	},
	
	setCompatFlags : function(){
		//Set Compatibility
		this.TAGNAME = jpf.isIE ? "baseName" : "localName";
		this.hasContentEditable = jpf.isIE || jpf.isSafari;
		this.styleSheetRules = jpf.isIE ? "rules" : "cssRules";
		this.brokenHttpAbort = jpf.isIE6;
		this.canUseHtmlAsXml = jpf.isIE;
		this.supportNamespaces = !jpf.isIE;
		this.cannotSizeIframe = jpf.isIE;
		this.supportOverflowComponent = jpf.isIE;
		this.hasDocumentFragment = !jpf.isIE55;
		this.hasEventSrcElement = jpf.isIE;
		this.canHaveHtmlOverSelects = !jpf.isIE6 && !jpf.isIE5;
		this.hasInnerText = jpf.isIE;
		this.hasMsRangeObject = jpf.isIE;
		this.hasContentEditable = jpf.isIE || jpf.isOpera;
		this.descPropJs = jpf.isIE;
		this.hasClickFastBug = jpf.isIE;
		this.hasExecScript = window.execScript ? true : false;
		this.canDisableKeyCodes = jpf.isIE;
		this.hasTextNodeWhiteSpaceBug = jpf.isIE;
		this.canUseInnerHtmlWithTables = !jpf.isIE;
		this.hasSingleResizeEvent = !jpf.isIE;
		this.hasStyleFilters = jpf.isIE;
		this.cantParseXmlDefinition = jpf.isIE50;
		this.hasDynamicItemList = !jpf.isIE || jpf.isIE7;
		this.canImportNode = jpf.isIE;
		this.hasSingleRszEvent = !jpf.isIE;
		this.hasXPathHtmlSupport = !jpf.isIE;
		this.hasReadyStateBug = jpf.isIE50;
		this.dateSeparator = jpf.isIE ? "-" : "/";
		this.canInsertGlobalCode = !jpf.isSafari && !jpf.isGecko;
		this.canCreateStyleNode = !jpf.isIE;
		this.supportFixedPosition = !jpf.isIE || jpf.isIE7;
		
		//Other settings
		this.maxHttpRetries = this.isOpera ? 0 : 3;
	},
	
	start : function(){
		//Set Variables
		this.host = location.href.split("?")[0].replace(/(\/\/[^\/]*)\/.*$/, "$1");
		this.hostPath = location.href.split("?")[0].replace(/\/[^\/]*$/, "") + "/";
		this.CWD = location.href.split("?")[0].replace(/^(.*\/)[^\/]*$/, "$1") + "/";
		
		jpf.status("Starting Javeline PlatForm Application...");
		
		//mozilla root detection
		//try{ISROOT = !window.opener || !window.opener.jpf}catch(e){ISROOT = true}
		
		//Browser Specific Stuff
		this.browserDetect();
		this.setCompatFlags();
		
		if(this.isIE){
			try{this.hasDeskRun = window.external && window.external.shell && window.external.shell.version && window.external.shell.runtime == 2;}catch(e){this.hasDeskRun = false;}
			try{this.hasWebRun  = !this.hasDeskRun && jdshell.runtime==1;}catch(e){this.hasWebRun = false;}	
		}
				
		//Load Browser Specific Code
		if(this.isIE) this.importClass(runIE, true, self);
		if(this.isSafari) this.importClass(runSafari, true, self);
		if(this.isOpera) this.importClass(runOpera, true, self);
		if(this.isGecko || !this.isIE && !this.isSafari && !this.isOpera) this.importClass(runGecko, true, self);
		runGecko = runOpera = runSafari = runIE = runXpath = runNonIe = runXslt = undefined;
		
		// Start HTTP object
		this.oHttp = new this.http();
		
		// Load user defined includes
		this.Init.addConditional(this.loadIncludes, null, ['BODY', 'HTTP', 'XMLDatabase', 'TelePort']);
		
		//IE fix
		try{if(jpf.isIE) document.execCommand("BackgroundImageCache", false, true);}catch(e){};
		
		//try{jpf.root = !window.opener || !window.opener.jpf;}
		//catch(e){jpf.root = false}
		this.root = true;
		
		jpf.debugwin.init();
	},
	
	startDependencies : function(){
		jpf.status("Loading Dependencies...");
		
		// Load Kernel Modules
		for(var i=0;i<this.KernelModules.length;i++)
			jpf.include("Library/Core/" + this.KernelModules[i], true);
		
		// Load TelePort Modules
		for(var i=0;i<this.TelePortModules.length;i++)
			jpf.include("Library/TelePort/" + this.TelePortModules[i], true);
		
		// Load Components
		for(var i=0;i<this.Components.length;i++)
			jpf.include("Library/Components/" + this.Components[i] + ".js", true);
		
		jpf.Init.interval = setInterval("if(jpf.checkLoadedDeps()){clearInterval(jpf.Init.interval);jpf.start()}", 100);
	},

	ns : {
		jpf : "http://www.javeline.com/2005/PlatForm",
		xsd : "http://www.w3.org/2001/XMLSchema",
		xhtml : "http://www.w3.org/1999/xhtml",
		xslt : "http://www.w3.org/1999/XSL/Transform",
		xforms : "http://www.w3.org/2002/xforms",
		ev : "http://www.w3.org/2001/xml-events"
	},
	
	findPrefix : function(xmlNode, xmlns){
		if(xmlNode.nodeType == 9){
			if(!xmlNode.documentElement) return false;
			if(xmlNode.documentElement.namespaceURI == xmlns) return xmlNode.prefix || xmlNode.scopeName;
			var docEl = xmlNode.documentElement;
		}
		else{
			if(xmlNode.namespaceURI == xmlns) return xmlNode.prefix || xmlNode.scopeName;
			var docEl = xmlNode.ownerDocument.documentElement;
			if(docEl && docEl.namespaceURI == xmlns)
				return xmlNode.prefix || xmlNode.scopeName;
			
			while(xmlNode.parentNode){
				xmlNode = xmlNode.parentNode;
				if(xmlNode.namespaceURI == xmlns)
					return xmlNode.prefix || xmlNode.scopeName;
			}
		}
		
		if(docEl){
			for(var i=0;i<docEl.attributes.length;i++){
				if(docEl.attributes[i].nodeValue == xmlns) return docEl.attributes[i][jpf.TAGNAME]
			}
		}
		
		return false;
	},

	getWindowWidth : function(){
		return (jpf.isIE ? document.documentElement.offsetWidth : window.innerWidth);
	},
	getWindowHeight : function(){
		return (jpf.isIE ? document.documentElement.offsetHeight : window.innerHeight);
	},
	
	/**
	* This method returns a string representation of the object
	* @return {String}	Returns a string representing the object.
	* @method
	*/
	toString : function(){
		return "[Javeline (jpf)]";
	},
	
	emptyf : function(){},
	
	all : [],
	
	getElement : function(parent, nr){
		var nodes = parent.childNodes;
		for(var j=0,i=0;i<nodes.length;i++){
			if(nodes[i].nodeType != 1) continue;
			if(j++ == nr) return nodes[i];
		}
	},
	
	/**
	* This method inherit all properties and methods to this object from another class
	* @param {Function}	classRef	Required Class reference 
	* @method
	*/
	inherit : function(classRef){classRef.call(this);},
	
	/**
	* This method transforms an object into a Javeline Class
	* @param {Object}	oBlank Required Object to be transformed into a Javeline Class
	* @method
	*/
	makeClass : function(oBlank){if(oBlank.inherit) return; oBlank.inherit = this.inherit;oBlank.inherit(jpf.Class);},
	
	/* ******** BROWSER FEATURES ***********
		Compatibility Methods and functions
	**************************************/
	root : true,
	named : {},

	cancelBubble : function(e, o){
		e.cancelBubble = true;
		if(o.focussable && !o.disabled) jpf.window.__focus(o);
	},

	/**
	* This method sets a single CSS rule 
	* @param {String}	name Required CSS name of the rule (i.e. '.cls' or '#id')
	* @param {String}	type Required CSS property to change
	* @param {String}	value Required CSS value of the property
	* @param {String}	stylesheet Optional Name of the stylesheet to change 
	* @method
	*/	
	setStyleRule : function(name, type, value, stylesheet){
		var rules = document.styleSheets[stylesheet || 0][jpf.styleSheetRules] ;
		for(var i=0;i<rules.length;i++){
			if(rules.item(i).selectorText == name){
				rules.item(i).style[type] = value;
				return;
			}
		}
	},
	
	setStyleClass : function(oEl, className, exclusion, special){
		if(!oEl || this.disabled) return;
		if(!exclusion) exclusion = new Array();
		exclusion.push(className);

		//Remove defined classes
		var re = new RegExp("(?:(^| +)" + exclusion.join("|") + "($| +))", "gi");

		if(special){
			//Create animation between two classes
			//For now just a hack
			if(oEl.firstChild.style.display == "none"){
				oEl.firstChild.style.display = "block";
				new jpf.GuiAnimation(oEl.firstChild, 'fade', 0, 1, 0, 10, 10);
			}
			else{
				new jpf.GuiAnimation(oEl.firstChild, 'fade', 1, 0, 0, 10, 10, function(){
					oEl.firstChild.style.display = "none";
				});
			}
		}
		else{
			//Set new class
			oEl.className != null ?
				(oEl.className = oEl.className.replace(re, " ") + " " + className) :
				oEl.setAttribute("class", (oEl.getAttribute("class") || "").replace(re, " ") + " " + className);
		}

		return oEl;
	},

	/**
	* This method imports a stylesheet defined in a multidimensional array 
	* @param {Array}	def Required Multidimensional array specifying 
	* @param {Object}	win Optional Reference to a window
	* @method
	* @deprecated
	*/	
	importStylesheet : function(def, win){
		//if(jpf.isOpera) return; //maybe version check here 9.21 it works, below might not
		for(var i=0;i<def.length;i++){
			if(def[i][1]){
				if(jpf.isIE)
					(win || window).document.styleSheets[0].addRule(def[i][0], def[i][1]);
				else
					(win || window).document.styleSheets[0].insertRule(def[i][0] + " {" + def[i][1] + "}", 0);
			}
		}
	},

	/**
	* This method imports a CSS stylesheet from a string 
	* @param {Object}	doc Required Reference to the document where the CSS is applied on
	* @param {String}	cssString Required String containing the CSS definition 
	* @param {String}	media Optional The media to which this CSS applies (i.e. 'print' or 'screen')
	* @method
	*/
	importCssString : function(doc, cssString, media){
		var htmlNode = doc.getElementsByTagName("head")[0];//doc.documentElement.getElementsByTagName("head")[0]

		if(jpf.canCreateStyleNode){
			var head = document.getElementsByTagName("head")[0];
			var style = document.createElement("style");
			style.appendChild(document.createTextNode(cssString));
			head.appendChild(style);
		}
		else{
			htmlNode.insertAdjacentHTML("beforeend",".<style media='" +(media || "all")+ "'>" + cssString + "</style>");
			
			/*if(document.body){
				document.body.style.height = "100%";
				setTimeout('document.body.style.height = "auto"');
			}*/
		}
	},

	/**
	* This method loads a stylesheet from a url
	* @param {String}	filename Required The url to load the stylesheet from
	* @param {String}	title Optional Title of the stylesheet to load
	* @method
	*/
	loadStylesheet : function(filename, title){
		with(o = document.getElementsByTagName("head")[0].appendChild(document.createElement("LINK"))){
			rel = "stylesheet";
			type = "text/css";
			href = filename;
			title = title;
		}

		return o;
	},

	/**
	* This method retrieves the current value of a property on a HTML element
	* @param {HTMLElement}	el Required The element to read the property from
	* @param {String}	prop Required The property to read 
	* @method
	*/
	getStyle : function(el, prop) {
		if(typeof document.defaultView != "undefined"
		   && typeof document.defaultView.getComputedStyle != "undefined")
			return document.defaultView.getComputedStyle(el,'').getPropertyValue(prop);
		return el.currentStyle[prop];
	},
	
	addEventListener : function(oHtml, eventName, method){
		if(oHtml.addEventListener)
			oHtml.addEventListener(eventName, method, false);
		else
			oHtml["on" + eventName] = method;
	},
	
	removeNode : function (element) {
		if(!element) return;
		
		if(!jpf.isIE){
			if(element.parentNode) element.parentNode.removeChild(element);
			return;
		}
		
		var garbageBin = document.getElementById('IELeakGarbageBin');
		if (!garbageBin) {
			garbageBin = document.createElement('DIV');
			garbageBin.id = 'IELeakGarbageBin';
			garbageBin.style.display = 'none';
			document.body.appendChild(garbageBin);
		}
	
		// move the element to the garbage bin
		garbageBin.appendChild(element);
		garbageBin.innerHTML = '';
	},
	
	uniqueHtmlIds : 0,
	setUniqueHtmlId : function(oHtml){
		oHtml.setAttribute("id", "q" + this.uniqueHtmlIds++)
	},
	
	getUniqueId : function(oHtml){return this.uniqueHtmlIds++;},

	/* ******** NODE METHODS ***********
		Methods to help Javeline Nodes
	**********************************/

	local : [],
	locals : {},

	getRoot : function(){
		return this.root ? this : window.opener.jpf;
	},

	getActiveWindow : function(){
		return this.getRoot().activeWindow;
	},

	getPath : function(path){
		return (path.match(/http\:\/\/|file\:\/\//) ? path : jpf.hostPath + path);
	},

	register : function(o, tagName, nodeType){
		o.tagName = tagName;
		o.nodeType = nodeType || NOGUI_NODE;
		//o.kernel = this;
		o.uniqueId = this.all.push(o)-1;
		
		this.makeClass(o);

		if(o.nodeType == MF_NODE) DeskRun.register(o);

		if(!this.root){
			this.local.push(o);
			this.locals[o.uniqueId] = true;
		}
	},
	
	lookup : function(uniqueId){
		return this.all[uniqueId];
	},

	localLookup : function(uniqueId){
		if(this.locals.length && !this.locals[uniqueId]) return;
		return this.all[uniqueId];
	},

	findHost : function(o){
		var node = o;
		while(o && !o.host && o.parentNode) o = o.parentNode;
		return o && o.host && typeof o.host != "string" ? o.host : false;
	},

	sleep : function(ms){
		if(!window.showModalDialog) return;
		window.showModalDialog('javascript:document.writeln("<script>window.setTimeout(function () { window.close(); }, ' + ms + ');</script>")');
	},
	
	availHTTP : [],
	
	releaseHTTP : function(http){
		if(jpf.brokenHttpAbort) return;
		if(self.XMLHttpRequestUnSafe && http.constructor == XMLHttpRequestUnSafe) return;
		
		http.onreadystatechange = this.emptyf;
		http.abort();
		this.availHTTP.push(http);
	},

	/* ******** SETREFERENCE ***********
		Set Reference to an object by name
	
		INTERFACE:
		this.setReference(name, o, global);
	****************************/
	setReference : function(name, o, global){
		if(self[name] && self[name].hasFeature) return;
		return (self[name] = o);
	},
	
	getRules : function(node){
		var rules = {};
		
		for(var w = node.firstChild;w;w=w.nextSibling){
			if(w.nodeType != 1) continue;
			else{
				if(!rules[w[jpf.TAGNAME]]) rules[w[jpf.TAGNAME]] = [];
				rules[w[jpf.TAGNAME]].push(w);
			}
		}
		
		return rules;
	},

	/* ******** NODE METHODS ***********
		Debug functions
	**********************************/

	status : function(str){
		if(!jpf.debug) return;
		
		if(false && jpf.isOpera) status = str;
		//else if(jpf.hasDeskRun || jpf.hasWebRun)	lp.Write("STATUS",str);
		else if(jpf){
			var dt = new Date();
			var date = dt.getHours() + ":" + dt.getMinutes() + ":" + dt.getSeconds() + ":" + dt.getMilliseconds();	
			jpf.debugMsg("[" + date + "] " + str.replace(/\n/g, "<br />").replace(/\t/g,"&nbsp;&nbsp;&nbsp;") + "<br />", "status");
		}
		else document.title = str;
	},
	
	issueWarning : function(nr, msg){
		if(!self.jpf.debug) return;
		
		//needs implementation
		if(jpf.warnings[msg]) return;
	
		//var seeAgain = confirm("Javelin Notification\nA warning has been issued\n\nNumber: " + nr + "\nWarning: " + msg + "\n\nPress OK to see this warning again.");
		//if(!seeAgain) jpf.warnings[msg] = true;

		jpf.status("[WARNING]:" + msg.replace(/\n/g, "<br />"));
		jpf.warnings[msg] = true;
	},

	warnings : {},
	debugInfo : "",

	debugMsg : function(msg, type, forceWin){
		if(!jpf.debug) return;

		if(jpf.debugFilter.match(new RegExp("!" + type + "(\||$)", "i"))) return;
		if(jpf.debugType.toLowerCase() == "window" || this.win && !this.win.closed || forceWin){
			this.win = window.open("", "debug");
			if(!this.win){
				if(!this.haspopupkiller) alert("Could not open debug window, please check your popupkiller");
				this.haspopupkiller = true;
			}
			else this.win.document.write(msg);
		}
		
		this.debugInfo += msg;

		if(this.ondebug) this.ondebug(msg);
	},

	showDebug : function(){
		this.win = window.open("", "debug");
		this.win.document.write(this.debugInfo);
	},
	
	formErrorString : function(number, control, process, message, jmlContext, outputname, output){
		var str = ["---- Javeline Error ----"];
		if(jmlContext){
			if(jmlContext.nodeType == 9) jmlContext = jmlContext.documentElement;
			var c = jmlContext.ownerDocument.outerHTML || (jmlContext.ownerDocument.xml || jmlContext.ownerDocument.serialize()) || "";
			var jmlStr = (jmlContext.outerHTML || jmlContext.xml || jmlContext.serialize()).replace(/\<\?xml\:namespace prefix = j ns = "http\:\/\/www.javeline.net\/j" \/\>/g, "").replace(/xmlns:j="[^"]*"\s*/g, "");
			var linenr = c.substr(0, c.indexOf(jmlStr)).split("\n").length;
			str.push("jml file: [line: " + linenr + "] " + jpf.removePathContext(jpf.hostPath, jmlContext.ownerDocument.documentElement.getAttribute("filename")));
		}
		if(control) str.push("Control: '" + (control.name||(control.jml?control.jml.getAttribute("id"):null)||"{Anonymous}") + "' [" + control.tagName + "]");
		if(process) str.push("Process: " + process);
		if(message) str.push("Message: [" + number + "] " + message);
		if(outputname) str.push(outputname+ ": " + output);
		if(jmlContext) str.push("\n===\n" + jmlStr);

		return str.join("\n");
	},
	
	//throw new Error(1101, jpf.formErrorString(1101, this, null, "A dropdown with a bind='' attribute needs a smartbinding='' attribute or have <j:Item /> children.", "JML", this.jml.outerHTML));
	

	/* ******** DRAGMODE ***********
		Drag Mode - Handles Drag&Drop Methods on Body
	*******************************/
	DragMode : {
		modes : {},

		removeMode : function(mode){
			this.modes[mode] = null;
		},
		
		defineMode : function(mode, struct){
			this.modes[mode] = struct;
		},

		setMode : function(mode){
			for(prop in this.modes[mode])
				if(prop.match(/^on/))
					document.body[prop] = this.modes[mode][prop];

			this.mode = mode;
		},

		clear : function(){
			for(prop in this.modes[this.mode])
				if(prop.match(/^on/))
					document.body[prop] = null;
					
			this.mode = null;
		}
	},

	Plane : {
		init : function(){
			if(!this.plane){
				this.plane = document.createElement("DIV");
				this.plane.style.background = "url(spacer.gif)";
				this.plane.style.position = "absolute";
				this.plane.style.zIndex = 99999;
				this.plane.style.left = 0;
				this.plane.style.top = 0;
			}
		},

		show : function(o){
			this.init();
			
			this.current = o;
			this.lastZ = this.current.style.zIndex;
			this.current.style.zIndex = 100000;

			o.parentNode.appendChild(this.plane);
			var p = document.body == this.plane.parentNode ? document.documentElement : this.plane.parentNode;

			this.plane.style.display = "block";
			this.plane.style.left = p.scrollLeft;
			this.plane.style.top = p.scrollTop;
			
			var diff = jpf.compat.getDiff(p);
			this.plane.style.width = p.offsetWidth - diff[0];
			this.plane.style.height = p.offsetHeight - diff[1];
			
			return this.plane;
		},

		hide : function(){
			this.plane.style.display = "none";
			this.current.style.zIndex = this.lastZ;
			
			return this.plane;
		}
	},
	
	Popup : {
		cache : {},
		setContent : function(cacheId, content, style, width, height){
			if(!this.popup) this.init();

			this.cache[cacheId] = {
				content : content,
				style : style,
				width : width,
				height : height
			};
			content.style.position = "absolute";
			//if(content.parentNode) content.parentNode.removeChild(content);
			//if(style) jpf.importCssString(this.popup.document, style);
			
			return content.ownerDocument;
		},
		removeContent : function(cacheId){
			this.cache[cacheId] = null;
			delete this.cache[cacheId];
		},
		init : function(){
			//consider using iframe
			this.popup = {};
		},
		show : function(cacheId, x, y, animate, ref, width, height, callback){
			if(!this.popup) this.init();
			if(this.last != cacheId) this.hide();
			
			var o = this.cache[cacheId];
			//if(this.last != cacheId) 
			//this.popup.document.body.innerHTML = o.content.outerHTML;

			var popup = o.content;
			o.content.onmousedown = function(e){(e||event).cancelBubble = true;}
			o.content.style.zIndex = 10000000;
			//o.content.style.display = "block";
			
			var pos = jpf.compat.getAbsolutePosition(ref);//[ref.offsetLeft+2,ref.offsetTop+4];//
			var top = y+pos[1];
			var p = jpf.compat.getOverflowParent(o.content); 
			var moveUp = (top + height + y) > p.offsetHeight + p.scrollTop;
			
			popup.style.top = top + "px";
			popup.style.left = (x+pos[0]) + "px";
			popup.style.width = ((width || o.width)-3) + "px";

			if(animate){
				var iVal, steps = 7, i = 0;
				
				iVal = setInterval(function(){
					var value = ++i*((height || o.height)/steps);
					popup.style.height = value + "px";
					if(moveUp) popup.style.top = (top - value - y) + "px"
					else popup.scrollTop = -1*(i-steps-1)*((height || o.height)/steps);
					popup.style.display = "block";
					if(i > steps){
						clearInterval(iVal)
						callback(popup);
					}
				}, 10);
			}
			else{
				popup.style.height = (height || o.height) + "px"
			}

			this.last = cacheId;
		},
		hide : function(){
			if(this.cache[this.last])
				this.cache[this.last].content.style.display = "none";
			//if(this.popup) this.popup.hide();
		},
		forceHide : function(){
			if(this.last){
				var o = jpf.lookup(this.last);
				if(!o) this.last = null;
				else o.dispatchEvent("onpopuphide");
			}
		},
		destroy : function(){
			if(!this.popup) return;
			//this.popup.document.body.c = null;
			//this.popup.document.body.onmouseover = null;
		}
	},
	
	/* Init */
	
	include : function(sourceFile, doBase){
		jpf.status("including js file: " + sourceFile);
		
		//Safari Special Case
		/*if(jpf.isSafari){
			document.write("<script src='" + (doBase ? BASEPATH + sourceFile : sourceFile) + "' defer='true'></script>");
		}
		//Other browsers
		else{*/
			var head = document.getElementsByTagName("head")[0];
			var elScript = document.createElement("script");
			elScript.defer = true;
			elScript.src = doBase ? (jpf.basePath || "") + sourceFile : sourceFile;
			head.appendChild(elScript);
		//}
	},
	
	Init : {
		queue : [],
		cond : {
			combined : []	
		},
		done : {},
		
		add : function(func, o){
			if(this.inited) func.call(o);
			else if(func) this.queue.push([func, o]);
		},
		
		addConditional : function(func, o, strObj){
			if(typeof strObj != "string"){
				if(this.checkCombined(strObj)) return func.call(o);
				this.cond.combined.push([func, o, strObj]);
			}
			else if(self[strObj]) func.call(o);
			else{
				if(!this.cond[strObj]) this.cond[strObj] = [];
				this.cond[strObj].push([func, o]);
				
				this.checkAllCombined();
			}
		},
		
		checkAllCombined : function(){
			for(var i=0;i<this.cond.combined.length;i++){
				if(!this.cond.combined[i]) continue;
				
				if(this.checkCombined(this.cond.combined[i][2])){
					this.cond.combined[i][0].call(this.cond.combined[i][1])
					this.cond.combined[i] = null;
				}
			}
		},
		
		checkCombined : function(arr){
			for(var i=0;i<arr.length;i++){
				if(!this.done[arr[i]]) return false;
			}
	
			return true;
		},
		
		run : function(strObj){
			this.inited = true;
			this.done[strObj] = true;
			
			this.checkAllCombined();
			
			var data = strObj ? this.cond[strObj] : this.queue;
			if(!data) return;
			for(var i=0;i<data.length;i++) data[i][0].call(data[i][1]);
		}
	},
	
	//case sensitivity... is this too much??
	getJmlDocFromString : function(xmlString){
		//replace(/&\w+;/, ""). replace this by something else
		var str = xmlString.replace(/\<\!DOCTYPE[^>]*>/, "").replace(/&nbsp;/g, " ").replace(/^[\r\n\s]*/, "").replace(/<\s*\/?\s*\w+:\s*[\w-]*[\s>\/]/g, function(m){return m.toLowerCase()});
		if(!this.supportNamespaces) str = str.replace(/xmlns\=\"[^"]*\"/g, "")
		
		var xmlNode = jpf.getObject("XMLDOM", str);
		if(jpf.xmlParseError) jpf.xmlParseError(xmlNode);
		//xmlNode.setProperty("SelectionNamespaces", "xmlns:j='http://www.javeline.com/2001/PlatForm'");
		
		// Case insensitive support
		var nodes = xmlNode.selectNodes("//@*[not(contains(local-name(), '.')) and not(translate(local-name(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz') = local-name())]");
		for(var i=0;i<nodes.length;i++){
			(nodes[i].ownerElement || nodes[i].selectSingleNode("..")).setAttribute(nodes[i].nodeName.toLowerCase(), nodes[i].nodeValue);
		}
			
		return xmlNode;
	},
 
	loadIncludes : function(docElement){
		//Subwindow
		if(false && window.opener && window.opener.jpf.JMLParser){
			if(document.all) document.body.innerHTML = window.opener.jpf.JMLParser.xml.outerHTML;
			LoadData["interface"] = [window.opener.jpf.JMLParser.xmlClass, document.all ? document.getElementsByTagName("jpf.JMLParser")[0] : window.opener.jpf.JMLParser.xml];
			
			/*if(LoadData[1].getElementsByTagName("LoadScreen").length){
				if(!document.all) document.body.innerHTML = "";
				jpf.loadScreen = jpf.XMLDatabase.htmlImport(jpf.getElement(LoadData[1].getElementsByTagName("LoadScreen")[0], 0), document.body);
			}*/
	
			document.body.style.display = "block";
			return;
		}
	
		//Load current HTML document as 'second DOM'
		
		
		if((!jpf.canUseHtmlAsXml || document.body.getAttribute("mode") != "html") && !docElement){
			return new jpf.http().getString((document.body.getAttribute("xmlurl") || location.href).split(/#/)[0], function(xmlString, status, extra){
				if(status != __HTTP_SUCCESS__){
					if(state == __HTTP_TIMEOUT__ && extra.retries < jpf.maxHttpRetries) return extra.tpModule.retry(extra.id);
					else{
						var commError = new Error(0, jpf.formErrorString(0, null, "Loading XML application data", "Could not load XML from remote source: " + extra.message));
						if(jpf.document.dispatchEvent("onerror", jpf.extend({error : commError, state : status}, extra)) !== false)
							throw commError;
						return;
					}
				}
				
				var xmlNode = jpf.getJmlDocFromString(xmlString);
				
				
				//Clear Body
				if(jpf.isIE) document.body.innerHTML ="";
				else{
					var nodes = document.body.childNodes;
					for(var i=nodes.length-1;i>=0;i--) nodes[i].parentNode.removeChild(nodes[i]);
				}
				
				
				return jpf.loadIncludes(xmlNode);
			}, true);
		}
		else if(!docElement) docElement = document;
		
		//Parse the second DOM (add includes)
		
		
		var prefix = jpf.findPrefix(docElement, jpf.ns.jpf); if(prefix) prefix += ":";
		
		if(!prefix) throw new Error(0, jpf.formErrorString(0, null, "Parsing document", "Unable to find Javeline PlatForm namespace definition. (i.e. xmlns:j=\"" + jpf.ns.jpf + "\")", docElement));
		jpf.AppData = jpf.supportNamespaces ? docElement.createElementNS(jpf.ns.jpf, prefix + "application") : docElement.createElement(prefix + "application");
		
		//Head support
		var head = $xmlns(docElement, "head", jpf.ns.xhtml)[0];
		if(head){
			var nodes = head.childNodes;
			for(var i=nodes.length-1;i>=0;i--) 
				if(nodes[i].namespaceURI && nodes[i].namespaceURI != jpf.ns.xhtml) 
					jpf.AppData.insertBefore(nodes[i], jpf.AppData.firstChild);
		}
		
		//Body support
		var body = (docElement.body ? docElement.body : $xmlns(docElement, "body", jpf.ns.xhtml)[0]);
		for(var i=0;i<body.attributes.length;i++) jpf.AppData.setAttribute(body.attributes[i].nodeName, body.attributes[i].nodeValue);

		var nodes = body.childNodes;
		for(var i=nodes.length-1;i>=0;i--) jpf.AppData.insertBefore(nodes[i], jpf.AppData.firstChild);
		docElement.documentElement.appendChild(jpf.AppData); //Firefox fix for selectNode insertion need...
		
	
		jpf.loadJMLIncludes(jpf.AppData);
		
		
		if($xmlns(jpf.AppData, "loader", jpf.ns.jpf).length){
			jpf.loadScreen = {
				show : function(){
					this.oExt.style.display = "block";
					//this.oExt.style.height = document.body.scrollHeight + "px";
				},
				hide : function(){
					this.oExt.style.display = "none";
				}
			}
			
			if(jpf.isGecko || jpf.isSafari) document.body.innerHTML = "";
			if(jpf.isSafariOld){
				var q = jpf.getElement($xmlns(jpf.AppData, "loader", jpf.ns.jpf)[0], 0).serialize();
				document.body.insertAdjacentHTML("beforeend", q);
				jpf.loadScreen.oExt = document.body.lastChild;
			}
			else{
				var htmlNode = jpf.getElement($xmlns(jpf.AppData, "loader", jpf.ns.jpf)[0], 0);
				
				//if(jpf.isSafari) jpf.loadScreen = document.body.appendChild(document.importNode(htmlNode, true));
				if(htmlNode.ownerDocument == document) jpf.loadScreen.oExt = document.body.appendChild(htmlNode.cloneNode(true));
				else{
					document.body.insertAdjacentHTML("beforeend", htmlNode.xml || htmlNode.serialize());
					jpf.loadScreen.oExt = document.body.lastChild;
				}
			}
		}
		
		document.body.style.display = "block";
		
		
		if(!self.ERROR_HAS_OCCURRED)
			jpf.Init.interval = setInterval('if(jpf.checkLoaded()) jpf.initialize()', 20);
	},
	
	loadJMLIncludes : function(xmlNode, doSync){
		
		if(xmlNode.ownerDocument.documentElement[jpf.TAGNAME] == "application"){
			var nodes = xmlNode.ownerDocument.documentElement.attributes;
			for(var found=false,i=0;i<nodes.length;i++){
				if(nodes[i].nodeValue == jpf.ns.jpf){
					found = true;
					break;
				}
			}
	
			if (!found){
				//throw new Error(0, jpf.formErrorString(0, null, "Loading includes", (found ? "Invalid namespace found '" + found + "'" : "No namespace definition found") + ". Expecting " + jpf.ns.jpf + "\nFile : " + (xmlNode.ownerDocument.documentElement.getAttribute("filename") || location.href), xmlNode.ownerDocument.documentElement));
				jpf.issueWarning(0, "The Javeline PlatForm xml namespace was not found.");
			}
		}
		
		var nodes = $xmlns(xmlNode, "include", jpf.ns.jpf);
		if(nodes.length){
			xmlNode.setAttribute("loading", "loading");
		
			for(var i=nodes.length-1;i>=0;i--){
				if(!nodes[i].getAttribute("src")) 
					throw new Error(0, jpf.formErrorString(0, null, "Loading includes", "Could not load Include file " + nodes[i].xml + ":\nCould not find the src attribute."))
				
				jpf.loadJMLInclude(nodes[i], doSync);
			}
		}
		else xmlNode.setAttribute("loading", "done");
		
		var nodes = $xmlns(xmlNode, "skin", jpf.ns.jpf);
		for(var i=0;i<nodes.length;i++){
			if(!nodes[i].getAttribute("src") && !nodes[i].getAttribute("name") || nodes[i].childNodes.length) continue;

			var path = nodes[i].getAttribute("src") ? 
				jpf.getAbsolutePath(jpf.hostPath, nodes[i].getAttribute("src")) : 
				jpf.getAbsolutePath(jpf.hostPath, nodes[i].getAttribute("name")) + "/index.xml";
			
			jpf.loadJMLInclude(nodes[i], doSync, path, true);
		}
		
		//XForms and lazy programmers support
		if(!jpf.PresentationServer.skins["default"] && jpf.autoLoadSkin){
			jpf.issueWarning(0, "No skin file found, trying to autoload it named as skins.xml");
			jpf.loadJMLInclude(null, doSync, "skins.xml", true);
		}
		
		return true;
	},

	loadJMLInclude : function(node, doSync, path, isSkin){
		jpf.status("Loading include file: " + (path || jpf.getAbsolutePath(jpf.hostPath, node.getAttribute("src"))));
		
		this.oHttp.getString(path || jpf.getAbsolutePath(jpf.hostPath, node.getAttribute("src")), function(xmlString, state, extra){
			if(state != __HTTP_SUCCESS__){
				if(state == __HTTP_TIMEOUT__ && extra.retries < jpf.maxHttpRetries) return extra.tpModule.retry(extra.id);
				else{
					var commError = new Error(1007, jpf.formErrorString(1007, null, "Loading Includes", "Could not load Include file '" + (path || extra.userdata[0].getAttribute("src")) + "'\nReason: " + extra.message, node));
					if(!jpf.document || jpf.document.dispatchEvent("onerror", jpf.extend({error : commError, state : state}, extra)) !== false)
						throw commError;
					return;
				}
			}

			if(!isSkin){
				var xmlNode = jpf.getJmlDocFromString(xmlString).documentElement;
				if(xmlNode[jpf.TAGNAME].toLowerCase() == "skin") isSkin = true;
				else if(xmlNode[jpf.TAGNAME] != "application"){
					throw new Error(0, jpf.formErrorString(0, null, "Loading Includes", "Could not find handler to parse include file for '" + xmlNode[jpf.TAGNAME] + "' expected 'skin' or 'application'", node));
				}
			}
			
			if(isSkin){
				var xmlNode = jpf.XMLDatabase.getXml(xmlString);
				jpf.PresentationServer.Init(xmlNode, node, path);
				jpf.IncludeStack[extra.userdata[1]] = true;
				
				if(jpf.isOpera && extra.userdata[0] && extra.userdata[0].parentNode) //for opera...
					extra.userdata[0].parentNode.removeChild(extra.userdata[0]);
			}
			else{
				jpf.IncludeStack[extra.userdata[1]] = xmlNode;//extra.userdata[0].parentNode.appendChild(xmlNode, extra.userdata[0]);
				extra.userdata[0].setAttribute("iid", extra.userdata[1]);
				xmlNode.setAttribute("filename", extra.url);
			}
			
			jpf.status("Loading of " + xmlNode[jpf.TAGNAME].toLowerCase() + " include done from file: " + extra.url);
			
			jpf.loadJMLIncludes(xmlNode); //check for includes in the include (NOT recursive save)
			
		}, !doSync, [node, jpf.IncludeStack.push(false) - 1]);
		
	},

	checkLoaded : function(){
		for(var i=0;i<jpf.IncludeStack.length;i++){
			if(!jpf.IncludeStack[i]){
				jpf.status("Waiting for: [" + i + "] " + jpf.IncludeStack[i]);
				return false;
			}
		}
		
		if(!document.body) return false;
		
		jpf.status("Dependencies loaded");
		
		return true;
	},
	
	checkLoadedDeps : function(){
		jpf.status("Loading...");

		for(var i=0;i<this.Modules.length;i++){
			if(!jpf[this.Modules[i]]){
				jpf.status("Waiting for module " + this.Modules[i]);
				return false;
			}
		}
		
		for(var i=0;i<this.TelePortModules.length;i++){
			var mod = this.TelePortModules[i].replace(/(^.*\/|^)([^\/]*)\.js$/, "$2").toLowerCase();
			if(!jpf[mod]){
				jpf.status("Waiting for TelePort module " + mod);
				return false;
			}
		}
	
		for(var i=0;i<this.Components.length;i++){
			if(this.Components[i].match(/^_base/) || this.Components[i] == "HtmlWrapper") continue;
			if(!jpf[this.Components[i].toLowerCase()]){
				jpf.status("Waiting for component " + this.Components[i]);
				return false;
			}
		}
		
		if(!document.body) return false;
		
		jpf.status("Dependencies loaded");
		
		return true;
	},

	initialize : function(){
		if(jpf.isInitialized) return;
		jpf.isInitialized = true;
		
		jpf.status("Initializing...");
		clearInterval(jpf.Init.interval);
		
		// Run Init
		jpf.Init.run(); //Process load dependencies
	
		// Start application
		if(jpf.JMLParser && jpf.AppData) jpf.JMLParser.parse(jpf.AppData);
	
		if(jpf.loadScreen && jpf.appsettings.autoHideLoading) jpf.loadScreen.hide();
	},
	
	/* Process Instructions */
	
	
	//PROCINSTR
	
	/** 
	 * Execute a process instruction
	 * @todo combine:
	 * + jpf.Teleport.callMethodFromNode (except submitform)
	 * + ActionTracker.doResponse
	 * + MultiSelect.add
	 * + rewrite jpf.Model.parse to support load/submission -> rename to loadJML
	 * + fix .doUpdate in Tree
	 * + fix .extend in Model
	 * + add Model.loadFrom(instruction);
	 * + add Model.insertFrom(instruction, xmlContext, parentXMLNode, jmlNode);
	 * + remove url attribute in insertJML function
	 * @see jpf.Teleport#processArguments
	 *
	 * <j:Bar rpc="" jml="<get_data>" />
	 * <j:bindings>
	 * 	<j:load select="." get="<get_data>" />
	 * 	<j:insert select="." get="<get_data>" />
	 * </j:bindings>
	 * <j:actions>
	 * 	<j:rename set="<save_data>" />
	 * 	<j:add get="<same_as_model>" set="<save_data>" />
	 * </j:actions>
	 * 
	 * <j:list model="<model_get_data>" />
	 * 
	 * <j:model load="<get_data>" submission="<save_data>" />
	 * <j:smartbinding model="<model_get_data>" />
	 */	
	
	/**
	 * save_data : as specified above -> saves data and returns value, optionally in callback
	 * @syntax
	 * - set="url:http://www.bla.nl?blah=10&zep=xpath:/ee&blo=eval:10+5&"
	 * - set="url.post:http://www.bla.nl?blah=10&zep=xpath:/ee&blo=eval:10+5&"
	 * - set="rpc:comm.submit('abc', xpath:/ee)"
	 * - set="call:submit('abc', xpath:/ee)"
	 * - set="eval:blah=5"
	 * - set="cookie:name.subname(xpath:.)"
	 */
	saveData : function(instruction, xmlContext, callback, multicall, userdata, arg, isGetRequest){
		if(!instruction) return false;

		var data = instruction.split(":");
		var instrType = data.shift();

		switch(instrType){
			case "url":
			case "url.post":
			case "url.eval":
				var oPost = instrType == "url.post" ? new jpf.post() : new jpf.get();

				//Need checks here
				var xmlNode = xmlContext;
				var x = instrType == "url.eval" ? eval(data.join(":")).split("?") : data.join(":").split("?");
				var url = x.shift();
				
				var cgiData = x.join("?").replace(/\=(xpath|eval)\:([^\&]*)\&/g, function(m, type, content){
					if(type == "xpath"){
						var retvalue, o = xmlNode.selectSingleNode(RegExp.$1);
						if(!o) retvalue = "";
						else if(o.nodeType >= 2 && o.nodeType <= 4) retvalue = o.nodeValue;
						else retvalue = o.serialize ? o.serialize() : o.xml;
					}
					else if(type == "eval"){
						try{
							var retvalue = eval(content);
						}
						catch(e){
							throw new Error(0, jpf.formErrorString(0, null, "Saving/Loading data", "Could not execute javascript code in process instruction '" + content + "' with error " + e.message));
						}
					}
					
					return "=" + retvalue + "&";
				});

				if(arg && arg.length){
					var arg = arg[0];
					var pdata = arg.nodeType ? arg.xml || arg.serialize() : jpf.serialize(arg);
					url += "?" + cgiData;
				}
				else{
					//Get CGI vars
					var pdata = cgiData
				}
				
				//Add method and call it
				oPost.urls["saveData"] = url;
				oPost.addMethod("saveData", callback, null, true);
				oPost.callWithString("saveData", pdata, callback)
			break;
			case "rpc":
				var parsed = this.parseInstructionPart(data.join(":"), xmlContext, arg);
				arg = parsed.arguments;
				
				var q = parsed.name.split(".");
				var obj = eval(q[0]);
				var method = q[1];
				
				if(!obj) throw new Error(0, jpf.formErrorString(0, null, "Saving/Loading data", "Could not find RPC object by name '" + q[0] + "' in process instruction '" + instruction + "'"));
		
				//force multicall if needed;
				if(multicall) obj.force_multicall = true;
				
				//Set information later neeed
				if(!obj[method]) throw new Error(0, jpf.formErrorString(0, null, "Saving/Loading data", "Could not find RPC function by name '" + method + "' in process instruction '" + instruction + "'"));
				
				if(userdata) obj[method].userdata = userdata;
				if(!obj.multicall) obj.callbacks[method] = callback; //&& obj[method].async
				
				//Call method
				var retvalue = obj.call(method, arg ? obj.fArgs(arg, obj.names[method], (obj.vartype != "cgi" && obj.vexport == "cgi")) : null);//obj.named ? obj.names[method] : []));
		
				if(obj.multicall) return obj.purge(callback, "&@^%!@");
				else if(multicall){
					obj.force_multicall = false;
					return obj;
				}
	
				//Call callback for sync calls
				if(!obj.multicall && !obj[method].async && callback)
					return callback(retvalue);
			break;
			case "call":
				var parsed = this.parseInstructionPart(data.join(":"), xmlContext, arg);
				
				if(!self[parsed.name]) throw new Error(0, jpf.formErrorString(0, null, "Saving/Loading data", "Could not find Method '" + q[0] + "' in process instruction '" + instruction + "'"));
				
				//Call method
				var retvalue = self[parsed.name].apply(null, parsed.arguments);
				
				//Call callback
				if(callback) callback(retvalue, __HTTP_SUCCESS__, {userdata:userdata});
			break;
			case "eval":
				try{
					var retvalue = eval(data[1]);
				}
				catch(e){
					throw new Error(0, jpf.formErrorString(0, null, "Saving data", "Could not execute javascript code in process instruction '" + instruction + "' with error " + e.message));
				}
				
				if(callback) callback(retvalue, __HTTP_SUCCESS__, {userdata:userdata});
			break;
			case "cookie":
				var parsed = this.parseInstructionPart(data.join(":"), xmlContext, arg);
				
				var q = parsed.name.split(".");
				var cur_value = jpf.getcookie(q[0]);
				cur_value = cur_value ? jpf.unserialize(cur_value) || {} : {};
				if(!isGetRequest) cur_value[q[1]] = parsed.arguments[0];

				jpf.setcookie(q[0], jpf.serialize(cur_value));
				if(callback) callback(cur_value ? cur_value[q[1]] : null, __HTTP_SUCCESS__, {userdata:userdata});
			break;
			default:
				//Warning?
				return false;
			break;
		}
	},
	
	/**
	 * get_data : same as above + #name:select:xpath en name:xpath -> returns data via a callback
	 * @syntax
	 * - get="id"
	 * - get="id:xpath"
	 * - get="#component"
	 * - get="#component:select"
	 * - get="#component:select:xpath"
	 * - get="#component"
	 * - get="#component:choose"
	 * - get="#component:choose:xpath"
	 * - get="#component::xpath"
	 * ? - get="::xpath"
	 * - get="url:http://www.bla.nl?blah=10&zep=xpath:/ee&blo=eval:10+5&|ee/blah:1"
	 * - get="rpc:comm.submit('abc', xpath:/ee)|ee/blah:1"
	 * - get="call:submit('abc', xpath:/ee)|ee/blah:1"
	 * - get="eval:10+5"
	 */
	getData : function(instruction, xmlContext, callback, multicall, arg){
		var instrParts = instruction.match(/^([^\|]*)(?:\|([^|]*)){0,1}$/);
		var operators = (instrParts[2]||"").split(":");
		var get_callback = function(data, state, extra){
			if(state != __HTTP_SUCCESS__) return callback(data, state, extra);
			
			operators[2] = data;
			if(operators[0] && data){
				if(typeof data == "string") data = jpf.XMLDatabase.getXml(data);
				data = data.selectSingleNode(operators[0]);
				
				//Change this to warning?
				if(!data)
					throw new Error(0, jpf.formErrorString(0, null, "Loading new data", "Could not load data by doing selection on it using xPath: '" + operators[0] + "'."));	
			}
			
			extra.userdata = operators;
			return callback(data, state, extra);
		}
		
		//Get data operates exactly the same as saveData...
		if(this.saveData(instrParts[1], xmlContext, get_callback, multicall, operators, arg, true) !== false) return;
		
		//...and then some
		var data = instruction.split(":");
		var instrType = data.shift();
		
		if(instrType.substr(0,1) == "#"){
			instrType = instrType.substr(1);
			var retvalue, oJmlNode = self[instrType];
			
			if(!oJmlNode) throw new Error(0, jpf.formErrorString(0, null, "Loading data", "Could not find object '" + instrType + "' referenced in process instruction '" + instruction + "' with error " + e.message));
			
			if(!oJmlNode.value) retvalue = null;
			else{
				if(data[2]) retvalue = oJmlNode.value.selectSingleNode(data[2]);
				else retvalue = oJmlNode.value;
			}
		}
		else{
			var model = jpf.NameServer.get("model", instrType);
			
			if(!model)
				throw new Error(1068, jpf.formErrorString(1068, jmlNode, "Loading data", "Could not find model by name: " + instrType, x));
			
			if(!model.data) retvalue = null;
			else{
				if(data[1]) retvalue = model.data.selectSingleNode(data[1]);
				else retvalue = model.data;
			}
		}
		
		if(callback) get_callback(retvalue, __HTTP_SUCCESS__, {userdata:operators});
		else{
			jpf.issueWarning(0, "Returning data directly in jpf.getData(). This means that all callback communication ends in void!");
			return retvalue;
		}
	},
	
	/**
	 * model_get_data : creates a model object (model will use get_data to process instruction) -> returns model + xpath
	 * @todo
	 * + rename jpf.JMLParser.selectModel to jpf.setModel
	 * + change jpf.SmartBinding.loadJML to use jpf.setModel
	 * + change function modelHandler to use jpf.setModel
	 */
	setModel : function(instruction, jmlNode, isSelection){
		if(!instruction) return;

		var data = instruction.split(":");
		var instrType = data[0];
		
		if(instrType.match(/^(?:url|url.post|rpc|call|eval|cookie|gears)$/)){
			jmlNode.setModel(new jpf.Model().loadFrom(instruction));
			//x.setAttribute((isSelection ? "select-" : "") + "model", "#" + jmlNode.name + (data.length ? ":" + data.join(":") : ""));
		}
		else if(instrType.substr(0,1) == "#"){
			instrType = instrType.substr(1);
			
			if(isSelection){
				var sb2 = jmlNode.getSelectionSmartBinding() || jpf.JMLParser.getFromSbStack(jmlNode.uniqueId, 1);
				if(sb2) sb2.model = new jpf.Model().loadFrom(instruction);
			}
			else if(!self[instrType] || !jpf.JMLParser.inited){
				jpf.JMLParser.addToModelStack(jmlNode, data)
			}
			else{
				var oConnect = eval(instrType);
				if(oConnect.connect) oConnect.connect(jmlNode, null, data[2], data[1] || "select");
				else jmlNode.setModel(new jpf.Model().loadFrom(instruction));
			}
			
			jmlNode.connectId = instrType;
		}
		else{
			var instrType = data.shift();
			var model = instrType == "@default" ? jpf.JMLParser.globalModel : jpf.NameServer.get("model", instrType);
			
			if(!model)
				throw new Error(1068, jpf.formErrorString(1068, jmlNode, "Finding model", "Could not find model by name: " + instrType));
			
			if(isSelection){
				var sb2 = jmlNode.getSelectionSmartBinding() || jpf.JMLParser.getFromSbStack(jmlNode.uniqueId, 1);
				if(sb2){
					sb2.model = model;
					sb2.modelXpath[jmlNode.uniqueId] = data.join(":");
				}
			}
			else jmlNode.setModel(model, data.join(":"));
		}
	},
	
	parseInstructionPart : function(instrPart, xmlNode, arg){
		var parsed = {}, s = instrPart.split("(");
		parsed.name = s.shift();
		
		//Get arguments for call
		if(!arg){
			arg = s.join("(");
			
			if(arg.substr(arg.length-1) != ")") throw new Error(0, jpf.formErrorString(0, null, "Saving data", "Syntax error in instruction. Missing ) in " + instrPart));
			
			arg = arg.substr(0, arg.length-1);
			arg = arg ? arg.split(",") : []; //(?=\w+:) would help, but makes it more difficult
			
			for(var i=0;i<arg.length;i++){
				if(typeof arg[i] == "object") continue;
				
				if(typeof arg[i] == "string"){
					//this could be optimized if needed
					if(arg[i].match(/^xpath\:(.*)$/)){
						var o = xmlNode ? xmlNode.selectSingleNode(RegExp.$1) : null;
		
						if(!o) arg[i] = "";
						else if(o.nodeType >= 2 && o.nodeType <= 4) arg[i] = o.nodeValue;
						//else if(o.firstChild) arg[i] = o.firstChild.nodeValue;// && (o.firstChild.nodeType == 3 || o.firstChild.nodeType == 4)
						//else arg[i] = "";
						else arg[i] = o.xml || o.serialize();
					}
					else if(arg[i].match(/^call\:(.*)$/)){
						arg[i] = self[RegExp.$1](xmlNode, instrPart);
					}
					else if(arg[i].match(/^\((.*)\)$/)){
						arg[i] = this.processArguments(RegExp.$1.split(";"), xmlNode, instrPart);
					}
					//if(arg[i].match(/^eval\:(.*)$/)){
					else{
						arg[i] = eval(arg[i]);//RegExp.$1);
					}
				}
				else arg[i] = arg[i] || "";
			}
		}
		
		parsed.arguments = arg;
		
		return parsed;
	},
	
	
	/* Destroy */

	destroy : function(exclude){
		var models = jpf.NameServer.getAll("model");
		for(var i=0;i<models.length;i++) models[i].dispatchEvent("xforms-model-destruct");
		
		this.Popup.destroy();
		
		for(var i=0;i<this.all.length;i++)
			if(this.all[i] && this.all[i] != exclude && this.all[i].destroy)
				this.all[i].destroy();
		
		document.oncontextmenu = null;
		document.onmousedown = null;
		document.onselectstart = null;
		document.onkeyup = null;
		document.onkeydown = null;
		
		for(var i=0;i<this.availHTTP.length;i++){
			this.availHTTP[i] = null;
		}
		
		jpf.XMLDatabase.unbind(jpf.window);
	}
};

var $ = function(tag, doc, prefix, force){
	return (doc || document).getElementsByTagName((prefix && (force || jpf.isGecko || jpf.isOpera) ? prefix + ":" : "") + tag);
}

var $xmlns = function(xmlNode, tag, xmlns, prefix){
	if(!jpf.supportNamespaces){
		if(!prefix) prefix = jpf.findPrefix(xmlNode, xmlns);
		
		if(xmlNode.style)
			return xmlNode.getElementsByTagName(tag)
		else{
			if(prefix) (xmlNode.nodeType == 9 ? xmlNode : xmlNode.ownerDocument).setProperty("SelectionNamespaces", "xmlns:" + prefix + "='" + xmlns + "'");
			return xmlNode.selectNodes(".//" + (prefix ? prefix + ":" : "") + tag);
		}
	}
	else
		return xmlNode.getElementsByTagNameNS(xmlns, tag);
}

var $j = function(xmlNode, tag){
	return $xmlns(xmlNode, tag, jpf.ns.jpf);
}


/* ******** COOKIE METHODS *********
	Cookie Handling Methods
**********************************/

jpf.setcookie = function(name, value, expire, path, domain, secure){
	var ck = name + "=" + escape(value) + ";";
	if(expire) ck += "expires=" + new Date(expire + new Date().getTimezoneOffset()*60).toGMTString() + ";";
	if(path) ck += "path=" + path + ";";
	if(domain) ck += "domain=" + domain;
	if(secure) ck += "secure";

	document.cookie = ck;
	return true
}

jpf.getcookie = function (name){
  var aCookie = document.cookie.split("; ");
  for (var i=0; i < aCookie.length; i++){
	var aCrumb = aCookie[i].split("=");
	if (name == aCrumb[0])
	  return unescape(aCrumb[1]);
  }

  return "";
}

jpf.delcookie = function (name,domain){
  	document.cookie = name + "=blah; expires=Fri, 31 Dec 1999 23:59:59 GMT;"+domain?'domain='+domain:'';
}

/* ******** HELPER FUNCTIONS *********
**********************************/

jpf.getXmlValue = function (xmlNode, xpath){
	if(!xmlNode) return "";
	xmlNode = xmlNode.selectSingleNode(xpath);
	if(xmlNode && xmlNode.nodeType == 1) xmlNode = xmlNode.firstChild;
	return xmlNode ? xmlNode.nodeValue : "";
}

jpf.getXmlValues = function(xmlNode, xpath){
	var out = [];
	if(!xmlNode) return out;
	
	var nodes = xmlNode.selectNodes(xpath);
	if(!nodes.length) return out;
	
	for(var i=0;i<nodes.length;i++){
		var n = nodes[i];
		if(n.nodeType == 1) n = n.firstChild;
		out.push(n.nodeValue || "");
	}
	return out;
}


jpf.removeParts = function(str){
	q = str.replace(/^\s*function\s*\w*\s*\([^\)]*\)\s*\{/, "");
	q = q.replace(/\}\s*$/, "");
	return q;
}

jpf.importClass = function(ref, strip, win){
	if(!ref) throw new Error(1018, jpf.formErrorString(1018, null, "importing class", "Could not load reference. Reference is null"));

	if(!jpf.hasExecScript) return ref();//.call(self);

	if(!strip) return (win.execScript ? win.execScript(ref.toString()) : eval(ref.toString()));
	var q = jpf.removeParts(ref.toString());

	//var q = ref.toString().split("\n");q.shift();q.pop();
	//if(!win.execScript) q.shift();q.pop();

	return win.execScript ? win.execScript(q) : eval(q);
}

jpf.Init.run('jpf');
/*FILEHEAD(/in/Components/Bar.js)SIZE(1389)TIME(1203730484247)*/

/**
 * Component displaying a skinnable rectangle which can contain other JML components.
 *
 * @classDescription		This class creates a new bar
 * @return {Bar} Returns a new bar
 * @type {Bar}
 * @constructor
 * @allowchild {components}, {anyjml}
 * @addnode components:bar
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.4
 */
jpf.bar = function(pHtmlNode){
	jpf.register(this, "bar", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	/* ***********************
	  		Inheritance
	************************/
	this.inherit(jpf.Presentation); /** @inherits jpf.Presentation */
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/
	
	/* *********
		INIT
	**********/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.draw = function(){
		//Build Main Skin
		this.oExt = this.__getExternal();
	}
		
	this.__loadJML = function(x){
		var oInt = this.__getLayoutNode("Main", "container", this.oExt);
	
		this.oInt = this.oInt ? 
			jpf.JMLParser.replaceNode(oInt, this.oInt) : 
			jpf.JMLParser.parseChildren(x, oInt, this);
	}
}
/*FILEHEAD(/in/Components/Browser.js)SIZE(3393)TIME(1203730484247)*/

/**
 * Component displaying the rendered contents of an URL.
 *
 * @classDescription		This class creates a new browser
 * @return {Browser} Returns a new browser
 * @type {Browser}
 * @constructor
 * @addnode components:browser
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.4
 */
jpf.browser = function(pHtmlNode){
	jpf.register(this, "browser", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	/* ********************************************************************
										PROPERTIES
	*********************************************************************/
	
	//Options
	//this.focussable = true; // This object can get the focus
	this.inherit(jpf.Validation); /** @inherits jpf.Validation */
	this.inherit(jpf.XForms); /** @inherits jpf.XForms */
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/
	
	this.loadURL = function(src){
		try{
			this.oInt.src = src;
		}catch(e){
			this.oInt.src = "about:blank";
		}
	}
	
	this.getURL = function(){
		return this.oInt.src;
	}
	
	this.back = function(){
		this.oInt.contentWindow.history.back();
	}
	
	this.forward = function(){
		this.oInt.contentWindow.history.forward();
	}
	
	this.reload = function(){
		this.oInt.src = this.oInt.src;	
	}
	
	this.print = function(){
		this.oInt.contentWindow.print();
	}
	
	this.runCode = function(str, no_error){
		if(no_error) try{this.oInt.contentWindow.eval(str);}catch(e){}
		else this.oInt.contentWindow.eval(str);
	}
	
	/* ***********************
	  Other Inheritance
	************************/
	this.inherit(jpf.DataBinding); /** @inherits jpf.DataBinding */
	
	/* ***************
		DATABINDING
	****************/
	this.mainBind = "source";
	
	
	this.__supportedProperties = ["value", "src"];
	this.__handlePropSet = function(prop, value){
		switch(prop){
			case "src":
			case "value":
				this.loadURL(value);
			break;
		}
	}
	
	/* *********
		INIT
	**********/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.draw = function(parentNode){
		if(!parentNode) parentNode = this.pHtmlNode;
		
		//Build Main Skin
		if(jpf.cannotSizeIframe){
			this.oExt = parentNode.appendChild(document.createElement("DIV")).appendChild(document.createElement("iframe")).parentNode;//parentNode.appendChild(document.createElement("iframe"));//
			this.oExt.style.width = "100px";
			this.oExt.style.height = "100px";
			this.oInt = this.oExt.firstChild;
			//this.oInt = this.oExt;
			this.oInt.style.width = "100%";
			this.oInt.style.height = "100%";
		}
		else{
			this.oExt = parentNode.appendChild(document.createElement("iframe"));
			this.oExt.style.width = "100px";
			this.oExt.style.height = "100px";
			this.oInt = this.oExt;
			//this.oExt.style.border = "2px inset white";
		}
		
		//this.oInt = this.oExt.contentWindow.document.body;
		this.oExt.host = this;
		//this.oInt.host = this;
	}
	
	this.__loadJML = function(x){
	}
}
/*FILEHEAD(/in/Components/Button.js)SIZE(7916)TIME(1203730484247)*/

/**
 * Component displaying a clickable rectangle that visually confirms the 
 * user interaction and executes a command when clicked.
 *
 * @classDescription		This class creates a new button
 * @return {Button} Returns a new button
 * @type {Button}
 * @constructor
 * @addnode components:button, components:trigger, components:submit
 * @alias submit
 * @alias trigger
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.4
 */
jpf.submit = 
jpf.trigger = 
jpf.button = function(pHtmlNode, tagName){
	jpf.register(this, tagName || "button", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	/* ***********************
	  		Inheritance
	************************/
	this.inherit(jpf.Presentation); /** @inherits jpf.Presentation */
	
	this.editableParts = {"Main" : [["caption","text()"]]};
	
	/* ********************************************************************
										PROPERTIES
	*********************************************************************/
	
	//Options
	this.focussable = true; // This object can get the focus
	this.value = null;
	
	/* ********************************************************************
										PRIVATE METHODS
	*********************************************************************/

	this.setActive = 
	this.__enable = function(){
		this.__doBgSwitch(1);
	}
	
	this.setInactive = 
	this.__disable = function(){
		this.__doBgSwitch(4);
		this.__setStyleClass(this.oExt, "", [this.baseCSSname + "Over", this.baseCSSname + "Down"]);
	}
	
	this.__doBgSwitch = function(nr){
		if(this.bgswitch && (this.bgoptions[1] >= nr || nr == 4)){
			if(nr == 4) nr = this.bgoptions[1] + 1;
			
			var strBG = this.bgoptions[0] == "vertical" ? 
				"0 -" + (parseInt(this.bgoptions[2])*(nr-1)) + "px": 
				"-" + (parseInt(this.bgoptions[2])*(nr-1)) + "px 0";

			this.__getLayoutNode("Main", "background", this.oExt).style.backgroundPosition = strBG;
		}
	}
	
	this.__setStateBehaviour = function(value){
		this.value = value || false;
		this.isBoolean = true;
		this.__setStyleClass(this.oExt, this.baseCSSname + "Bool");
		
		if(this.value){
			this.__setStyleClass(this.oExt, this.baseCSSname + "Down");
			this.__doBgSwitch(this.states["Down"]);
		}
	}
	
	this.__setNormalBehaviour = function(){
		this.value = null;
		this.isBoolean = false;
		this.__setStyleClass(this.oExt, "", [this.baseCSSname + "Bool"]);
	}
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/
	
	/**
	 * @copy   Widget#setValue
	 */
	this.setValue = function(value){
		if(value === undefined) value = !this.value;
		this.value = value;
		
		if(this.value) this.__setStyleClass(this.oExt, this.baseCSSname + "Down", [this.baseCSSname + "Over"]);
		else this.__setStyleClass(this.oExt, "", [this.baseCSSname + "Down"]);
		
		this.dispatchEvent("onclick");
	}
	
	/**
	 * Sets the text displayed as caption of this component.
	 *
	 * @param  {String}  value  required  The string to display. 
	 * @see    Validation
	 */
	this.setCaption = function(value){
		if(this.oCaption) this.oCaption.nodeValue = value;
	}
	
	/**
	 * Sets the URL of the icon displayed on this component.
	 *
	 * @param  {String}  value  required  The URL to the location of the icon. 
	 * @see    Button
	 * @see    ModalWindow
	 */
	this.setIcon = function(url){
		if(this.oIcon.tagName == "img") this.oIcon.setAttribute("src", this.iconPath + url);
		else this.oIcon.style.backgroundImage = "url(" + this.iconPath + url + ")";
	}
	
	/* ********************************************************************
										PRIVATE METHODS
	*********************************************************************/
	
	/* ***************
		Init
	****************/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	this.inherit(jpf.BaseButton); /** @inherits jpf.BaseButton */
	
	this.__setState = function(state, e, strEvent){
		if(this.disabled) return;

		this.__doBgSwitch(this.states[state]);
		this.__setStyleClass(this.oExt, (state != "Out" ? this.baseCSSname + state : ""), [(this.value ? "" : this.baseCSSname + "Down"), this.baseCSSname + "Over"]);
		this.dispatchEvent(strEvent, e);
		
		if(state != "Down") e.cancelBubble = true;
	}
	
	this.draw = function(clear, parentNode, Node, transform){
		//Build Main Skin
		this.oExt = this.__getExternal(); 
		this.oIcon = this.__getLayoutNode("Main", "icon", this.oExt);
		this.oCaption = this.__getLayoutNode("Main", "caption", this.oExt);
	
		this.__setupEvents();	
	}
	
	this.__clickHandler = function(){
		// This handles the actual OnClick action. Return true to redraw the button.
		if(this.isBoolean){	
			this.value = !this.value;
			return true;
		}
	}
	
	this.__supportedProperties = ["icon", "value", "tooltip", "state", "color", "caption", "action", "target"];
	this.__handlePropSet = function(prop, value){
		if(prop == "icon") this.setIcon(value);
		else if(prop == "value") this.sValue = value;
		else if(prop == "tooltip") this.oExt.setAttribute("title", value);
		else if(prop == "state") this.__setStateBehaviour(value == 1);
		else if(prop == "color") this.oCaption.parentNode.style.color = value;
		else if(prop == "caption") this.setCaption(value);
	}
	
	this.__loadJML = function(x){
		this.setCaption(x.firstChild ? x.firstChild.nodeValue : "");
		
			this.__makeEditable("Main", this.oExt, this.jml);
		
		
		this.bgswitch = x.getAttribute("bgswitch") ? true : false;
		if(this.bgswitch){
			this.__getLayoutNode("Main", "background", this.oExt).style.backgroundImage = "url(" + this.mediaPath + x.getAttribute("bgswitch") + ")";
			this.__getLayoutNode("Main", "background", this.oExt).style.backgroundRepeat = "no-repeat";

			this.bgoptions = x.getAttribute("bgoptions") ? x.getAttribute("bgoptions").split("\|") : ["vertical", 2, 16];
		}
		
		//this.__focus();
		
		
		//XForms support
		if(this.tagName == "trigger"){
			this.addEventListener("onclick", function(e){
				this.dispatchXFormsEvent("DOMActivate", e);
			});
		}
		
		//XForms support
		this.action = this.tagName == "submit" ? "submit" : x.getAttribute("action");
		this.target = x.getAttribute("target");
		if(this.action == "submit") this.submission = x.getAttribute("submission");
		
		this.addEventListener("onclick", function(e){
			if(!this.action) return;
			var target;
			
			if(this.submission){
				var submission = self[this.submission];
				if(!submission) throw new Error(0, jpf.formErrorString(0, this, "Submission", "Could not find submission to execute action on '" + this.submission + "'", this.jml));
				
				submission.dispatchXFormsEvent("xforms-submit");
				
				return;
			}
			else if(this.target){
				if(!self[this.target]) throw new Error(0, jpf.formErrorString(0, this, "Clicking on Button", "Could not find target to execute action on '" + this.target + "' with action '" + this.action + "'", this.jml));
				
				target = self[this.target]
			}
			else{
				var p = this;
				while(p.parentNode){
					if(p[this.action]){
						target = p;
						break;
					}
					p = p.parentNode;
				};
				
				if(!target){
					target = this.getModel();
					if(!target) throw new Error(0, jpf.formErrorString(0, this, "Clicking on Button", "Could not find target to for action '" + this.action + "'", this.jml));
				}
			}
			
			if(!target[this.action]) throw new Error(0, jpf.formErrorString(0, this, "Clicking on Button", "Could not find action on target.", this.jml));
			
			target[this.action]();
		});
		
		//if(x.getAttribute("condition")) this.condition = x.getAttribute("condition");
		//this.form.registerButton(this.action, this);
		
		jpf.JMLParser.parseChildren(this.jml, null, this);
		// this.doOptimize(false);
	}
}
/*FILEHEAD(/in/Components/Checkbox.js)SIZE(5564)TIME(1203730484247)*/

/**
 * Component displaying a clickable rectangle having two states which
 * can be toggled by user interaction.
 *
 * @classDescription		This class creates a new checkbox
 * @return {Checkbox} Returns a new checkbox
 * @type {Checkbox}
 * @constructor
 * @addnode components:checkbox
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.4
 */
jpf.checkbox = function(pHtmlNode){
	jpf.register(this, "checkbox", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	/* ***********************
	  		Inheritance
	************************/
	this.inherit(jpf.Presentation); /** @inherits jpf.Presentation */
	this.inherit(jpf.BaseButton); /** @inherits jpf.BaseButton */
	
	this.editableParts = {"Main" : [["label","text()"]]};
	
	this.inherit(jpf.DataBinding); /** @inherits jpf.DataBinding */
	
	/* ********************************************************************
										PROPERTIES
	*********************************************************************/
	
	//Options
	this.focussable = true; // This object can get the focus
	this.checked = false;
	this.inherit(jpf.Validation); /** @inherits jpf.Validation */
	this.inherit(jpf.XForms); /** @inherits jpf.XForms */
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/

	this.setValue = function(value){
		if(!this.values) return;
		this.setProperty("value", value);
	}
	
	this.getValue = function(){
		return this.XMLRoot ? this.values[this.checked ? 0 : 1] : this.value;
	}
	
	this.check = function(){
		this.setProperty("value", true);
	}
	
	this.uncheck = function(){
		this.setProperty("value", false);
	}
	
	this.setError = function(value){
		this.__setStyleClass(this.oExt, this.baseCSSname + "Error");
	}
	
	this.clearError = function(value){
		this.__setStyleClass(this.oExt, "", [this.baseCSSname + "Error"]);
	}
	
	this.__enable = function(){
		if(this.oInt) this.oInt.disabled = false;
		this.__doBgSwitch(1);
	}
	
	this.__disable = function(){
		if(this.oInt) this.oInt.disabled = true;
		this.__doBgSwitch(4);
	}
	
	this.__doBgSwitch = function(nr){
		if(this.bgswitch && (this.bgoptions[1] >= nr || nr == 4)){
			if(nr == 4) nr = this.bgoptions[1] + 1;
			
			var strBG = this.bgoptions[0] == "vertical" ? 
				"0 -" + (parseInt(this.bgoptions[2])*(nr-1)) + "px": 
				"-" + (parseInt(this.bgoptions[2])*(nr-1)) + "px 0";

			this.__getLayoutNode("Main", "background", this.oExt).style.backgroundPosition = strBG;
		}
	}
	
	/* ********************************************************************
										PRIVATE METHODS
	*********************************************************************/

	this.__supportedProperties = ["value"];
	this.__handlePropSet = function(prop, value){
		switch(prop){
			case "value":
				this.value = value = (typeof value == "string" ? value.trim() : value);
				this.checked = value !== undefined && value.toString() == this.values[0].toString();
				if(!jpf.isNull(value) && value.toString() == this.values[0].toString()) 
					this.__setStyleClass(this.oExt, this.baseCSSname + "Checked");
				else this.__setStyleClass(this.oExt, "", [this.baseCSSname + "Checked"]);
			break;
		}
	}

	/* *********
		INIT
	**********/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.__setState = function(state, e, strEvent){
		if(this.disabled) return;

		this.__doBgSwitch(this.states[state]);
		this.__setStyleClass(this.oExt, (state != "Out" ? this.baseCSSname + state : ""), [this.baseCSSname + "Down", this.baseCSSname + "Over"]);
		this.state = state; // Store the current state so we can check on it coming here again.
		
		this.dispatchEvent(strEvent, e);
		
		if(state == "Down") jpf.cancelBubble(e, this);
		else e.cancelBubble = true;
	}
	
	this.__clickHandler = function(){
		this.checked = !this.checked;
		this.change(this.values[(this.checked) ? 0 : 1]);
		if(this.validate) this.validate();
		return true;		
	}
	
	this.draw = function(){
		//Build Main Skin
		this.oExt = this.__getExternal();
		this.oInt = this.__getLayoutNode("Main", "input", this.oExt);
		
		this.__setupEvents();
	}
	
	this.__loadJML = function(x){
		//this.value = x.getAttribute("value");
		if(x.getAttribute("checked") == "true") this.check();
		if(x.firstChild){
			jpf.XMLDatabase.setNodeValue(this.__getLayoutNode("Main", "label", this.oExt), x.firstChild.nodeValue);
		}
		
			this.__makeEditable("Main", this.oExt, this.jml);
		
		this.bgswitch = x.getAttribute("bgswitch") ? true : false;
		if(this.bgswitch){
			this.__getLayoutNode("Main", "background", this.oExt).style.backgroundImage = "url(" + this.mediaPath + x.getAttribute("bgswitch") + ")";
			this.__getLayoutNode("Main", "background", this.oExt).style.backgroundRepeat = "no-repeat";

			this.bgoptions = x.getAttribute("bgoptions") ? x.getAttribute("bgoptions").split("\|") : ["vertical", 2, 16];
		}
		
		this.values = x.getAttribute("values") ? x.getAttribute("values").split("\|") : [1, 0];
	}
}

/*FILEHEAD(/in/Components/Collection.js)SIZE(1226)TIME(1203730484247)*/

/**
 * Virtual component acting as a parent for a set of child components 
 * but only draws it's children. It doesn't have any representation itself.
 *
 * @classDescription		This class creates a new collection
 * @return {Collection} Returns a new collection
 * @type {Collection}
 * @constructor
 * @allowchild {components}, {anyjml}
 * @addnode components:collection
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.4
 */
jpf.collection = function(pHtmlNode){
	jpf.register(this, "collection", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	/* ***********************
	  		Inheritance
	************************/
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/
	
	/* *********
		INIT
	**********/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.draw = function(){
		this.oExt = pHtmlNode;
		this.oInt = pHtmlNode;
		jpf.JMLParser.parseChildren(this.jml, this.oInt, this);
	}
	
	this.__loadJML = function(x){}
}

/*FILEHEAD(/in/Components/Colorpicker.js)SIZE(10483)TIME(1203730484247)*/

/**
 * Component giving the user a visual choice of several colors presented in a grid.
 *
 * @classDescription		This class creates a new colorpicker
 * @return {Colorpicker} Returns a new colorpicker
 * @type {Colorpicker}
 * @constructor
 * @addnode components:colorpicker
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.4
 */
jpf.colorpicker = function(pHtmlNode){
	jpf.register(this, "colorpicker", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	/* ***********************
	  		Inheritance
	************************/
	this.inherit(jpf.Presentation); /** @inherits jpf.Presentation */
	
	this.inherit(jpf.DataBinding); /** @inherits jpf.DataBinding */
	
	/* ********************************************************************
										PROPERTIES
	*********************************************************************/
	
	//Options
	this.focussable = true; // This object can get the focus
	this.inherit(jpf.Validation); /** @inherits jpf.Validation */
	this.inherit(jpf.XForms); /** @inherits jpf.XForms */
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/
	
	this.setValue = function(value, type){
		//this.value = value;

		if(!type) type = "RGBHEX";
		switch(type){
			case "HSL":
				this.fill(value[0], value[1], value[2]);
			break;
			case "RGB":
				var a = this.RGBtoHLS(value[0], value[1], value[2]);
				this.fill(a[0], a[1], a[2]);
			break;
			case "RGBHEX":
				var RGB = arguments[0].match(/(..)(..)(..)/);
				var a = this.RGBtoHLS(Math.hexToDec(RGB[0]), Math.hexToDec(RGB[1]), Math.hexToDec(RGB[2]));
				this.fill(a[0], a[1], a[2]);
			break;
		}
	}
	
	this.getValue = function(type){
		return this.HSLRangeToRGB(this.cH, this.cS, this.cL);
	}
	
	/* ********************************************************************
										PRIVATE METHODS
	*********************************************************************/
	
	this.cL = 120;
	this.cS = 239;
	this.cH = 0;
	this.cHex = "#FF0000";
	this.HSLRange = 240;
	
	this.HSLRangeToRGB = function(H, S, L){
	  return this.HSLtoRGB (H / (this.HSLRange-1), S / this.HSLRange, Math.min(L / this.HSLRange, 1))
	}
	
	this.RGBtoHLS = function(R,G,B){
		var RGBMAX = 255;
		var HLSMAX = this.HSLRange;
		var UNDEF = (HLSMAX*2/3);
	
	   /* calculate lightness */ 
	   cMax = Math.max(Math.max(R,G), B);
	   cMin = Math.min(Math.min(R,G), B);
	   L = (((cMax+cMin)*HLSMAX) + RGBMAX )/(2*RGBMAX);
	
	   if(cMax == cMin) {           /* r=g=b --> achromatic case */ 
	      S = 0;                     /* saturation */ 
	      H = UNDEF;             		/* hue */ 
	   }
	   else{                        /* chromatic case */ 
	      /* saturation */ 
	      if(L <= (HLSMAX/2)) S = ( ((cMax-cMin)*HLSMAX) + ((cMax+cMin)/2) ) / (cMax+cMin);
	      else S = (((cMax-cMin)*HLSMAX) + ((2*RGBMAX-cMax-cMin)/2)) / (2*RGBMAX-cMax-cMin);
	
	      /* hue */ 
		   Rdelta = ( ((cMax-R)*(HLSMAX/6)) + ((cMax-cMin)/2) ) / (cMax-cMin);
		   Gdelta = ( ((cMax-G)*(HLSMAX/6)) + ((cMax-cMin)/2) ) / (cMax-cMin);
		   Bdelta = ( ((cMax-B)*(HLSMAX/6)) + ((cMax-cMin)/2) ) / (cMax-cMin);
	
	      if(R == cMax) H = Bdelta - Gdelta;
	      else if(G == cMax) H = (HLSMAX/3) + Rdelta - Bdelta;
	      else H = ((2*HLSMAX)/3) + Gdelta - Rdelta;
	
	      if(H < 0) H += HLSMAX;
	      if(H > HLSMAX) H -= HLSMAX;
	   }

	   return [H,S,L];
	}
	
	this.HueToColorValue = function(Hue){
		var V;
	  
		if(Hue < 0) Hue = Hue + 1
		else if(Hue > 1) Hue = Hue - 1;
		
		if(6 * Hue < 1) V = M1 + (M2 - M1) * Hue * 6
		else if(2 * Hue < 1) V = M2
		else if(3 * Hue < 2) V = M1 + (M2 - M1) * (2/3 - Hue) * 6
		else V = M1;

		return Math.max(Math.floor(255 * V), 0);
	}
	
	this.HSLtoRGB = function(H, S, L){
		var R,  G,  B;
		
		if(S == 0) G = B = R = Math.round (255 * L);
		else{
			M2 = L <= 0.5 ? L * (1 + S) : L + S - L * S;
		
			M1 = 2 * L - M2;
			R = this.HueToColorValue(H + 1/3);
			G = this.HueToColorValue(H);
			B = this.HueToColorValue(H - 1/3);
		}

		return Math.decToHex(R) + "" + Math.decToHex(G) + "" + Math.decToHex(B);
	}
	
	this.fill = function(H, S, L){
		var Hex = this.HSLRangeToRGB(H,S,L);
		this.value = Hex;

		//RGB
		var RGB = Hex.match(/(..)(..)(..)/);
		this.tbRed.value = Math.hexToDec(RGB[1]);
		this.tbGreen.value = Math.hexToDec(RGB[2]);
		this.tbBlue.value = Math.hexToDec(RGB[3]);
		
		//HSL
		this.tbHue.value = Math.round(H);
		this.tbSatern.value = Math.round(S);
		this.tbLuminance.value = Math.round(L);
		
		//HexRGB
		this.tbHexColor.value = Hex;
		
		//Shower
		this.shower.style.backgroundColor = Hex;
	
		//Luminance
		var HSL120 = this.HSLRangeToRGB(H, S, 120);
		this.bar1.style.backgroundColor = HSL120;
		this.bgBar1.style.backgroundColor = this.HSLRangeToRGB(H, S, 240);
		this.bar2.style.backgroundColor = this.HSLRangeToRGB(H, S, 0);
		this.bgBar2.style.backgroundColor = HSL120;
	}		
	
	this.movePointer = function(){
		var cs = __ColorPicker;
		
		var ty = cs.pHolder.ty;
		if((event.clientY - ty >= 0) && (event.clientY - ty <= cs.pHolder.offsetHeight - cs.pointer.offsetHeight + 22))
			cs.pointer.style.top = event.clientY - ty;
		if(event.clientY - ty < 21) cs.pointer.style.top = 21;
		if(event.clientY - ty > cs.pHolder.offsetHeight - cs.pointer.offsetHeight + 19)
			cs.pointer.style.top = cs.pHolder.offsetHeight - cs.pointer.offsetHeight + 19;

		var y = cs.pointer.offsetTop - 22;
		cs.cL = (255-y) / 2.56 * 2.4;
		cs.fill(cs.cH, cs.cS, cs.cL);
		
		window.event.returnValue = false;
		window.event.cancelBubble = true;
	}
	
	this.setLogic = function(){
		this.pHolder.host = this;
		this.pHolder.style.zIndex = 10;
		this.pHolder.onmousedown = function(){
			__ColorPicker = this.host;
			
			this.ty = jpf.compat.getAbsolutePosition(this)[1] - 20;
			
			this.host.movePointer();
			document.onmousemove = this.host.movePointer
			document.onmouseup = function(){this.onmousemove = function(){}}
		}
		
		this.container.host = this;
		this.container.onmousedown = function(e){
			__ColorPicker = this.host;
			
			this.active = true;
			if(event.srcElement == this){
				if(event.offsetX >= 0 && event.offsetX <= 256 && event.offsetY >= 0 && event.offsetY <= 256){
					this.host.cS = (256-event.offsetY) / 2.56 * 2.4
					this.host.cH = event.offsetX / 2.56 * 2.39
				}
				this.host.fill(this.host.cH, this.host.cS, this.host.cL);
				this.host.shower.style.backgroundColor = this.host.currentColor;
			}
			this.host.point.style.display = "none";
			
			event.cancelBubble = true;
		}
		
		this.container.onmouseup = function(e){
			this.active = false;	
			this.host.point.style.top = event.offsetY - this.host.point.offsetHeight - 2;
			this.host.point.style.left = event.offsetX - this.host.point.offsetWidth - 2;
			this.host.point.style.display = "block";
			
			this.host.change(this.host.tbHexColor.value);
		}
		
		this.container.onmousemove = function(e){
			if(this.active){
				if(event.offsetX >= 0 && event.offsetX <= 256 && event.offsetY >= 0 && event.offsetY <= 256){
					this.host.cS = (256-event.offsetY) / 2.56 * 2.4
					this.host.cH = event.offsetX / 2.56 * 2.39
				}
				this.host.fill(this.host.cH, this.host.cS, this.host.cL);
				this.host.shower.style.backgroundColor = this.host.currentColor;
			}
		}
		
		/*this.tbHexColor.host = 
		this.tbRed.host = 
		this.tbGreen.host = 
		this.tbBlue.host = this;
		this.tbHexColor.onblur = function(){this.host.setValue("RGBHEX", this.value);}
		this.tbRed.onblur = function(){this.host.setValue("RGB", this.value, this.host.tbGreen.value, this.host.tbBlue.value);}
		this.tbGreen.onblur = function(){this.host.setValue("RGB", this.host.tbRed.value, this.value, this.host.tbBlue.value);}
		this.tbBlue.onblur = function(){this.host.setValue("RGB", this.host.tbRed.value, this.host.tbGreen.value, this.value);}
		*/
	}
	
	/* *********
		Databinding
	**********/
	this.mainBind = "color";
	
	/* *********
		INIT
	**********/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.draw = function(parentNode, clear){
		//Build Main Skin
		this.oExt = this.__getExternal(); 

		this.tbRed = this.__getLayoutNode("Main", "red", this.oExt);
		this.tbGreen = this.__getLayoutNode("Main", "green", this.oExt);
		this.tbBlue = this.__getLayoutNode("Main", "blue", this.oExt);
		
		this.tbHue = this.__getLayoutNode("Main", "hue", this.oExt);
		this.tbSatern = this.__getLayoutNode("Main", "satern", this.oExt);
		this.tbLuminance = this.__getLayoutNode("Main", "luminance", this.oExt);
		
		this.tbHexColor = this.__getLayoutNode("Main", "hex", this.oExt);
		this.tbHexColor.host = this;
		this.tbHexColor.onchange = function(){
			this.host.setValue(this.value, "RGBHEX");
		}
		
		this.shower = this.__getLayoutNode("Main", "shower", this.oExt);
		
		this.bar1 = this.__getLayoutNode("Main", "bar1", this.oExt);
		this.bgBar1 = this.__getLayoutNode("Main", "bgbar1", this.oExt);
		this.bar2 = this.__getLayoutNode("Main", "bar2", this.oExt);
		this.bgBar2 = this.__getLayoutNode("Main", "bgbar2", this.oExt);
		
		this.pHolder = this.__getLayoutNode("Main", "pholder", this.oExt);
		this.pointer = this.__getLayoutNode("Main", "pointer", this.oExt);
		this.container = this.__getLayoutNode("Main", "container", this.oExt);
		this.point = this.__getLayoutNode("Main", "point", this.oExt);

		var nodes = this.oExt.getElementsByTagName("input");
		for(var i=0;i<nodes.length;i++){
			nodes[i].onselectstart = function(e){if(!e) e = event;e.cancelBubble = true}
		}

		this.setLogic();
		
		this.setValue("ffffff");
		//this.fill(this.cH, this.cS, this.cL);
	}
	
	this.__loadJML = function(x){
		if(x.getAttribute("color")) this.setValue(x.getAttribute("color"));
	}
	
	this.__destroy = function(){
		this.container.host =
		this.tbRed.host = 
		this.tbGreen.host = 
		this.tbBlue.host = 
		this.tbHexColor.host = 
		this.pHolder.host = null;
	}
}
/*FILEHEAD(/in/Components/Container.js)SIZE(3314)TIME(1203730484247)*/

/**
 * Component containing other components that are hidden by default.
 *
 * @classDescription		This class creates a new container
 * @return {Container} Returns a new container
 * @type {Container}
 * @constructor
 * @allowchild {components}, {anyjml}
 * @addnode components:container
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.4
 */
jpf.container = function(pHtmlNode){
	jpf.register(this, "container", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	/* ***********************
	  		Inheritance
	************************/
	this.inherit(jpf.Presentation); /** @inherits jpf.Presentation */
	
	this.inherit(jpf.DelayedRender); /** @inherits jpf.DelayedRender */
	
	this.inherit(jpf.Validation); /** @inherits jpf.Validation */
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/
	
	this.setActive = function(){
		this.setProperty("active", true);
	}
	
	this.setInactive = function(){
		this.setProperty("active", false);
	}
	
	this.__supportedProperties = ["active"];
	this.__handlePropSet = function(prop, value){
		if(prop == "active"){
			if(jpf.isTrue(value)){
				this.render();
				
				this.__setStyleClass(this.oExt, this.baseCSSname + "Active", [this.baseCSSname + "Inactive"]);
				this.dispatchEvent("onactivate");
			}
			else{
				this.__setStyleClass(this.oExt, this.baseCSSname + "Inactive", [this.baseCSSname + "Active"]);
				this.dispatchEvent("oninactivate");
			}	
		}
	}
	
	/* *********
		INIT
	**********/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.draw = function(){
		//Build Main Skin
		this.oExt = this.__getExternal(); 
		
		this.setInactive();
	}
	
	this.__loadJML = function(x){
		//Set Form
		var y = x;
		do{
			y = y.parentNode;
		}while(!y.tagName.match(/submitform|xforms$/) && y.parentNode && y.parentNode.nodeType != 9);
		
		if(y.tagName.match(/submitform|xforms$/)){
			//if(!y.tagName.match(/submitform|xforms$/)) throw new Error(1004, jpf.formErrorString(1004, this, "Loading JML", "Could not find Form element whilst trying to bind to it's Data."));
			if(!y.getAttribute("id")) throw new Error(1005, jpf.formErrorString(1005, this, "Loading JML", "Found Form element but the id attribute is empty or missing."));
			
			this.form = eval(y.getAttribute("id"));
			this.condition = x.getAttribute("condition") || x.getAttribute("jscondition");
			this.onlyWhenActive = x.getAttribute("activeonly") == "show";
		}
		
		//parse children
		var oInt = this.__getLayoutNode("Main", "container", this.oExt) || this.oExt;
		this.oInt = this.oInt ? 
			jpf.JMLParser.replaceNode(oInt, this.oInt) : 
			jpf.JMLParser.parseChildren(this.jml, oInt, this, true);
		
		if(this.condition) this.form.registerCondition(this, this.condition, x.getAttribute("jscondition") ? true : false);
	}
}
/*FILEHEAD(/in/Components/Datagrid.js)SIZE(49375)TIME(1213483123975)*/

/**
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.4
 */

/*
<Heading caption="Contact Naam" span="2" width="18" />
<Heading width="105" />
<Heading caption="E-mail Adres" width="159" />

<Column_0 type="icon" select="." default="icoUsers.gif" />
<Column_1 select="@name" />
<Column_2 select="@email" />

<Traverse select="Person" />
<Heading name="Subject" .. />
<Name select=".@icon" type="icon" .... />
<Name select="." type="icon" .... />
<Subject select=".@icon" type="icon" .... />
<Subject select=".@icon" type="j:Textbox" .... />

type="icon|color|text|mask"
widget="j:Textbox"

selecttype = "row|cell"
*/

jpf.DgSizeServer = {
	init : function(){
		jpf.DragMode.defineMode("dgdragsize", this);
	},
	
	start : function(host, heading){

		//EVENT - cancellable: ondragstart
		if(host.dispatchEvent("onsizeheadingstart") === false) 
			return false;//(this.host.tempsel ? select(this.host.tempsel) : false);

		host.oSplitter.className = host.oSplitterLeft.className = "dg_size_headers";
		host.oSplitter.style.display = "block";
		
		var pos = jpf.compat.getAbsolutePosition(heading);
		host.oSplitter.style.left = (pos[0] + heading.offsetWidth - 1) +  "px";//+ (onRight ? heading.offsetWidth : 0)
		host.oSplitter.style.top = (pos[1]) + "px";

		var s = jpf.compat.getBox(jpf.compat.getStyle(host.oExt, "borderWidth"));
		host.oSplitter.style.height = host.oExt.offsetHeight - (s[0] + s[2]);
		var intWidth = host.oInt.clientWidth; // host.oExt.offsetWidth - (s[1] + s[3]);

		jpf.Plane.show (host.oSplitter).style.cursor = "w-resize";

		if (!(heading === host.headings[0].html))
		{
			host.oSplitterLeft.style.left = (pos[0] - 1) +  "px";//+ (onRight ? heading.offsetWidth : 0)
			host.oSplitterLeft.style.top = (pos[1]) + "px";
			host.oSplitterLeft.style.display = "block";
			host.oSplitterLeft.style.height = host.oSplitter.style.height;
		}

		// Make sure we'll take the header's border and padding into account when sizing.		
		var padding = (parseInt(jpf.compat.getStyle(heading, "paddingLeft")) || 0) + (parseInt(jpf.compat.getStyle(heading, "paddingRight")) || 0);
		var border = (parseInt(jpf.compat.getStyle(heading, "borderLeftWidth")) || 0) + (parseInt(jpf.compat.getStyle(heading, "borderRightWidth")) || 0);
		
		// Figure out the heading index we're sizing.
		var curHeading;
		for (var i=0; i<host.headings.length; i++)
			if (heading === host.headings[i].html)
			{
				curHeading = i;
				jpf.DgSizeServer.sizeHeading = i;
				break;
			}
		
		// Make sure that we can't make the right columns disappear.
		var minRemaining = 0;	
		for (var i=curHeading+1; i<host.headings.length; i++)
			minRemaining += Math.max(parseInt(host.headings[i].xml.getAttribute("minwidth")) || 0, padding+border);

		// Store relative widths - we'll keep these ratios when sizing.	
		host.rightWidth = 0;
		for (var i=curHeading+1;i<host.headings.length;i++)
			host.rightWidth += host.headings[i].width;

		host.orgSizeWidths = new Array();
		for (var i=curHeading; i<host.headings.length; i++)
			host.orgSizeWidths[i] = host.headings[i].width;
	
		this.dragdata = {
			heading : heading, 
			indicator : host.oSplitter,
			indicatorLeft : host.oSplitterLeft,
			host : host,
			minWidth : Math.max(padding+border, parseInt(host.headings[curHeading].xml.getAttribute("minwidth"))||0),
			maxWidth : Math.min(intWidth - heading.offsetLeft - minRemaining, (parseInt(host.headings[curHeading].xml.getAttribute("maxwidth")) || 9999999))
		};
		
		jpf.DgSizeServer.isActive = true;

		jpf.DragMode.setMode("dgdragsize");
	},
	
	/* **********************
		Mouse Movements
	***********************/
	
	ontimerevent : function() {
		var dragdata = jpf.DgSizeServer .dragdata;
		dragdata.host.__updateColumnSizes(dragdata.heading.getAttribute('hid'));
		jpf.DgSizeServer.timerEvent = undefined;
	},

	onmousemove : function(e){
		if(!e) e = event;
		var dragdata = jpf.DgSizeServer .dragdata;

		// Calc the new size.
		var pos = jpf.compat.getAbsolutePosition(dragdata.heading);
		var newSize = (e.clientX+jpf.DgSizeServer.sizeOffset) - pos[0];
		if(dragdata.indicator) dragdata.indicator.style.left = 
			pos[0] + Math.min(Math.max(newSize, dragdata.minWidth), dragdata.maxWidth) - 1;

		dragdata.host.sizeColumn(dragdata.heading.getAttribute("hid"), newSize + dragdata.host.oInt.scrollLeft, true);

		if (jpf.DgSizeServer.timerEvent) 
		{
			clearTimeout(jpf.DgSizeServer.timerEvent);
			jpf.DgSizeServer.timerEvent = undefined;
		}

		if (!jpf.DgSizeServer.timerEvent) 
			jpf.DgSizeServer.timerEvent = setTimeout(jpf.DgSizeServer.ontimerevent, 100);
	},
	
	stop : function(reset) {
		if (jpf.DgSizeServer.timerEvent) clearTimeout(jpf.DgSizeServer.timerEvent);
		jpf.DgSizeServer.timerEvent = undefined;
		jpf.DgSizeServer.sizeOffset = undefined;

		jpf.DragMode.clear();
		jpf.Plane.hide ().style.cursor = "default";
		
		if(!jpf.DgSizeServer.dragdata) return;
		var dragdata = jpf.DgSizeServer .dragdata;
		dragdata.indicator.style.display = "none"; // Let's hide it again.
		dragdata.indicatorLeft.style.display = "none"; // Let's hide it again.
		
		// Clear the sizing-cursor. Although, one could argue that we'd have to check the mouse position 
		// to see whether it shouldn't again be the sizing cursor if the mouse is over a splitter.
		dragdata.heading.style.cursor = "default";
		if (jpf.DgSizeServer.sizeHeading < dragdata.host.headings.length-1)
			dragdata.host.headings[jpf.DgSizeServer.sizeHeading+1].html.style.cursor = "default";
		
		if (reset) 
		{
			for (var i=jpf.DgSizeServer.sizeHeading; i<dragdata.host.headings.length; i++)
				dragdata.host.headings[i].width = dragdata.host.orgSizeWidths[i];
			dragdata.host.__updateHeadingSizes(jpf.DgSizeServer.sizeHeading);
			dragdata.host.__updateColumnSizes(jpf.DgSizeServer.sizeHeading);
		}
		
		jpf.DgSizeServer.isActive = false;
	},
	
	onmouseup : function(e){
		if(!e) e = event;
		var dragdata = jpf.DgSizeServer .dragdata;
		var pos = jpf.compat.getAbsolutePosition(dragdata.heading);
		var newSize = (e.clientX+jpf.DgSizeServer.sizeOffset) - pos[0];
		
		jpf.DgSizeServer.stop();
		dragdata.host.sizeColumn(dragdata.heading.getAttribute("hid"), newSize + dragdata.host.oInt.scrollLeft);
		dragdata.host.__storeRelativeWidths();
	}
}
jpf.Init.add(jpf.DgSizeServer.init, jpf.DgSizeServer);

jpf.DgHeadServer = {
	init : function(){
		jpf.DragMode.defineMode("dgdraghead", this);
	},
	
	start : function(host, heading){
		this.dragdata = {
			heading : heading, 
			indicator : host.__showDragHeading(heading, this.coordinates),
			host : host
		};

		//EVENT - cancellable: ondragstart
		if(host.dispatchEvent("ondragheadingstart") === false) return false;//(this.host.tempsel ? select(this.host.tempsel) : false);
		host.dragging = 2;

		jpf.DragMode.setMode("dgdraghead");
	},
	
	stop : function(runEvent){
		//Reset Objects
		var dg = this.dragdata.host;

		dg.dragging = 0;
		dg.__hideDragHeading();
		dg.__setStyleClass(this.dragdata.heading, "", ["state_down"]);
		
		dg.oSplitter.style.display = "none";
		dg.oSplitterLeft.style.display = "none";
		
		jpf.DragMode.clear();
		this.dragdata = null;
	},
	
	/* **********************
		Mouse Movements
	***********************/
	
	onmousemove : function(e){
		if(!e) e = event;
		var dragdata = jpf.DgHeadServer .dragdata;
		
		//get Element at x, y
		if(dragdata.indicator) dragdata.indicator.style.top = "10000px";
		var el = document.elementFromPoint(e.clientX+document.documentElement.scrollLeft, e.clientY+document.documentElement.scrollTop);
		
		var o = el;
		while(o && !o.host && o.parentNode) o = o.parentNode;
		var host = o && o.host ? o.host : false;

		//Set Indicator
		dragdata.host.__moveDragHeading(e);
		
		//show highlighter..
		var dg = jpf.DgHeadServer.dragdata.host;
		if(host && host == jpf.DgHeadServer.dragdata.host && host.oExt != o){
			var oEl = dg.oSplitter;
			oEl.style.display = "block";
			
			var pos = jpf.compat.getAbsolutePosition(o);
			//var dgpos = jpf.compat.getAbsolutePosition(host.oExt);
			var toRight = (e.clientX+document.documentElement.scrollLeft - pos[0])/o.offsetWidth > 0.5
			oEl.style.left = pos[0] - 2 + (toRight ? o.offsetWidth : 0);
			oEl.style.top = pos[1] - 2;
		}
		else{
			var oEl = dg.oSplitter;
			oEl.style.display = "none";
		}
	},
	
	onmouseup : function(e){
		if(!e) e = event;
		var dragdata = jpf.DgHeadServer .dragdata;
		
		//get Element at x, y
		if(dragdata.indicator) dragdata.indicator.style.top = "10000px";
		var el = document.elementFromPoint(e.clientX+document.documentElement.scrollLeft, e.clientY+document.documentElement.scrollTop);
		
		var o = el;
		while(o && !o.host && o.parentNode) o = o.parentNode;
		var host = o && o.host ? o.host : false;

		//show highlighter..
		var dg = jpf.DgHeadServer.dragdata.host;
		if(host && host == jpf.DgHeadServer.dragdata.host && host.oExt != o){
			var pos = jpf.compat.getAbsolutePosition(o);
			
			var toRight = (e.clientX+document.documentElement.scrollLeft - pos[0])/o.offsetWidth > 0.5
			var hid = parseInt(o.getAttribute("hid")) + (toRight ? 1 : 0);
			dg.moveColumn(parseInt(dragdata.heading.getAttribute("hid")), hid);
		}
		
		//Run Events
		jpf.DgHeadServer.stop(true);
		
		//Clear Selection
		if(jpf.isNS){
			var selObj = window.getSelection();
			if(selObj) selObj.collapseToEnd();
		}
	}	
}
jpf.Init.add(jpf.DgHeadServer.init, jpf.DgHeadServer);

/**
 * Component providing a sortable, selectable grid containing scrollable information. 
 * Grid columns can be reordered and resized.
 *
 * @classDescription		This class creates a new datagrid
 * @return {Datagrid} Returns a new datagrid
 * @type {Datagrid}
 * @constructor
 * @addnode components:datagrid
 */
jpf.datagrid = function(pHtmlNode){
	jpf.register(this, "datagrid", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	/* ********************************************************************
										PROPERTIES
	*********************************************************************/

	this.focussable = true; // This object can get the focus
	this.multiselect = true; // Enable MultiSelect

	this.clearMessage = "There are no items"; // There is no spoon
	
	var colspan = 0;
	var totalWidth = 0;
	//this.htmlHeadings = [];
	this.headings = [];
	this.cssRules = [];
	
	this.dynCssClasses = [];

	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/

	this.Data = function(xmlNode, data, fieldnum){
		if(xmlNode) this.select(xmlNode);
	}
	
	/* ********************************************************************
										PRIVATE METHODS
	*********************************************************************/

	this.showSelection = function(){
		var Q = (this.current || this.selected);
		var o = this.__getLayoutNode("Main", "body", this.oExt);
		o.scrollTop = (Q.offsetTop)-21;
	}

	/* ***********************
		Keyboard Support
	************************/
	this.keyHandler = function(key, ctrlKey, shiftKey){
		/*if(!this.oContainer || this.dragging) return;

		if(!this.selected){
			if(o.firstChild.firstChild && o.firstChild.firstChild.firstChild)
				this.select(o.firstChild.firstChild.firstChild);
			else return;
			
			//this.selected.scrollIntoView(true);
		}
		else 
		*/	
		
		if(!this.selected || !this.value) return;	
		
		var Q = (this.current || this.selected);
		var o = this.__getLayoutNode("Main", "body", this.oExt);
		var st = o.scrollTop;
		var oh = o.offsetHeight;
		
		if(this.colSorting && sortObj && (key > 32 && key < 41)) return; //Hack
		
		if(key == 27 && jpf.DgSizeServer.isActive)
			jpf.DgSizeServer.stop(true);
		else if(key == 38){
			//UP
			//REWRITE if(shiftKey) else select(htmlNode)
			var node = this.getNextTraverseSelected(this.value, false);
			if(node) this.select(node, ctrlKey, shiftKey);
			
			if(Q.offsetTop < st+Q.offsetHeight+20 || Q.offsetTop > st + oh) o.scrollTop = (Q.offsetTop - Q.offsetHeight) - 20
				//Q.scrollIntoView(true);
		}
		else if(key == 40){
			//DOWN
			//REWRITE if(shiftKey) else select(htmlNode)
			var node = this.getNextTraverseSelected(this.value, true);
			if(node) this.select(node, ctrlKey, shiftKey);
			
			if(Q.offsetTop < st || Q.offsetTop+Q.offsetHeight >= st + oh-20) o.scrollTop = (Q.offsetTop + 2*Q.offsetHeight) - o.offsetHeight + 20;
				//Q.scrollIntoView(false);
		}
		else if(key == 33){
			//PGUP
			var p = Q, count = parseInt((oh-50) / Q.offsetHeight);
			
			for(var i=0;i<count;i++)
				if(p.previousSibling) p = p.previousSibling;
				
			this.select(p, ctrlKey, shiftKey);
			o.scrollTop = (p.offsetTop)-21;
			//Q.scrollIntoView(true);
		}
		else if(key == 34){
			//PGDN
			var p = Q, count = parseInt((oh-50) / (Q.offsetHeight));
			
			for(var i=0;i<count;i++)
				if(p.nextSibling) p = p.nextSibling;
				
			this.select(p, ctrlKey, shiftKey);
			o.scrollTop = (p.offsetTop + p.offsetHeight) - o.offsetHeight+20;
			//Q.scrollIntoView(false);
		}
		else if(key == 36){
			//HOME
			this.select(Q.parentNode.firstChild, ctrlKey, shiftKey);
			o.scrollTop = 0;
			//Q.scrollIntoView(true);
		}
		else if(key == 35){
			//END
			this.select(Q.parentNode.lastChild, ctrlKey, shiftKey);
			o.scrollTop = o.scrollHeight;
			//Q.scrollIntoView(true);
		}
		else if(key == 46){
			//DEL
			var ln = this.getSelectCount();
			var xmlNode = ln == 1 ? this.value : null;
			this.remove(xmlNode, true);
		}
		else if(ctrlKey && key == 65){
			this.selectAll();	
			return false;
		}
		else if(key == 13)
			this.dispatchEvent('onchoose');
		else return;

		return false;
	}
	
	/* ***********************
				SELECT
	************************/
	
	this.__calcSelectRange = function(xmlStartNode, xmlEndNode){
		var r = [];
		var nodes = this.getTraverseNodes();
		for(var f=false,i=0;i<nodes.length;i++){
			if(nodes[i] == xmlStartNode) f = true;
			if(f) r.push(nodes[i]);
			if(nodes[i] == xmlEndNode) f = false;
		}
		
		if(!r.length || f){
			r = [];
			for(var f=false,i=nodes.length-1;i>=0;i--){
				if(nodes[i] == xmlStartNode) f = true;
				if(f) r.push(nodes[i]);
				if(nodes[i] == xmlEndNode) f = false;
			}
		}
		
		return r;
	}
	
	this.inherit(jpf.MultiSelect); /** @inherits jpf.MultiSelect */
	this.inherit(jpf.Cache); /** @inherits jpf.Cache */
	
	/* ***********************
			SKIN
	************************/
	
	this.__deInitNode = function(xmlNode, htmlNode){
		//Remove htmlNodes from tree
		htmlNode.parentNode.removeChild(htmlNode);
	}
	
	this.__updateNode = function(xmlNode, htmlNode){
		var dataset = this.dataset.set[htmlNode.getAttribute(jpf.XMLDatabase.htmlIdTag)];
		//Update Identity (Look)
		//this.__getLayoutNode("Item", "icon", htmlNode).style.backgroundImage = "url(" + this.iconPath + this.applyRuleSetOnNode("icon", xmlNode) + ")";
		//this.__getLayoutNode("Item", "caption", htmlNode).nodeValue = this.applyRuleSetOnNode("caption", xmlNode);

		var nodes = [];
		for(var j=0;j<htmlNode.childNodes.length;j++){
			if(htmlNode.childNodes[j].nodeType == 1) nodes.push(htmlNode.childNodes[j]);
		}

		//Build the Cells
		for(var i=0;i<this.headings.length;i++){
			var value = this.applyRuleSetOnNode(this.headings[i].xml.getAttribute("name"), xmlNode);
			if(dataset) dataset[i] = value;

			this.__getNewContext("Cell");
			var txtNode = this.__getLayoutNode("Cell", "caption", nodes[i]) || nodes[i];

			if(this.headings[i].xml.getAttribute("type") == "icon"){
				nodes[i].getElementsByTagName("img")[0].setAttribute("src", value ? this.iconPath + value : this.mediaPath + "spacer.gif");
			}
			else if(!value) jpf.XMLDatabase.setNodeValue(txtNode, " ");
			else jpf.XMLDatabase.setNodeValue(txtNode, value);
		}
		
		var cssClass = this.applyRuleSetOnNode("css", xmlNode);
		if(cssClass || this.dynCssClasses.length){
			this.__setStyleClass(htmlNode, cssClass, this.dynCssClasses);
			if(cssClass && !this.dynCssClasses.contains(cssClass)) this.dynCssClasses.push(cssClass);
		}
	}
	
	this.__moveNode = function(xmlNode, htmlNode){
		if(!htmlNode) return;
		var oPHtmlNode = htmlNode.parentNode;
		var beforeNode = xmlNode.nextSibling ? jpf.XMLDatabase.findHTMLNode(this.getNextTraverse(xmlNode), this) : null;

		oPHtmlNode.insertBefore(htmlNode, beforeNode);
		
		//if(this.emptyMessage && !oPHtmlNode.childNodes.length) this.setEmpty(oPHtmlNode);
	}
	
	this.__setLoading = function(htmlNode, container){
		//xmlNode.setAttribute("_loaded", "potential");
		//jpf.XMLDatabase.htmlImport(this.__getLayoutNode("Loading"), container);
	}
	
	this.__removeLoading = function(htmlNode){
		//this.__getLayoutNode("Item", "container", htmlNode).innerHTML = "";
	}
	
	/* ***********************
			DATABINDING
	************************/
	
	this.__selectDefault = function(XMLRoot){
		this.select(XMLRoot.selectSingleNode(this.ruleTraverse));
	}
	
	this.__addHeadings = function(xmlHeadings, headParent){
		// Calculate the control's inner width.
		var s = jpf.compat.getBox(jpf.compat.getStyle(this.oExt, "borderWidth"));
		var innerWidth = this.oExt.offsetWidth - (s[1] + s[3]);	// Now everything needs to fit in 'innerWidth' pixels.

		// Calc/retrieve heading sizes.
		var colWidths = new Array();
		var pixelsLeft = innerWidth;
		var colsLeft = xmlHeadings.length;
		for (var iHeading=0; iHeading<xmlHeadings.length; iHeading++)
		{
			var xmlHeading = xmlHeadings[iHeading];
			var xmlWidth = xmlHeading.getAttribute("width");
			if (typeof(xmlWidth) == "string" && xmlWidth.indexOf("%") != -1)
				xmlWidth = Math.round ((parseInt(xmlWidth) * innerWidth) / 100);
			else if (typeof(xmlWidth) == "string")				
				xmlWidth = parseInt(xmlWidth) || "*";

			if (typeof(xmlWidth) == "number")
			{
				// The width is beknownst to us. Do some min/max clampery, if applicable. 
				// Except for border/padding, because we don't know of those yet.
				xmlWidth = Math.min(xmlWidth, parseInt(xmlHeading.getAttribute("maxwidth"))||99999999);
				xmlWidth = Math.max(xmlWidth, parseInt(xmlHeading.getAttribute("minwidth"))||0);
				colWidths[iHeading] = xmlWidth;
				pixelsLeft -= xmlWidth;
				colsLeft--;
			}
		}
		
		var pixelsPerColumn = Math.round(pixelsLeft/colsLeft);
		for (var iHeading=0; iHeading<xmlHeadings.length; iHeading++)
		{
			if (!colWidths[iHeading])
			{
				colsLeft--;
				colWidths[iHeading] = colsLeft?pixelsPerColumn:pixelsLeft;
				pixelsLeft-=colWidths[iHeading];
			}
		}

		// Create the HTML components, calculate the desired widths, but don't size them yet.
		for (var iHeading=0; iHeading<xmlHeadings.length; iHeading++)
		{
			var xmlHeading = xmlHeadings[iHeading];
			//Check Colspan settings
			if(--this.colspan > 0){
				this.headings.push({
					xml : xmlHeading
				});
				continue;
			}
			colspan = xmlHeading.getAttribute("span") || 1;
			xmlHeading.setAttribute("name", xmlHeading.getAttribute("name").toLowerCase());

			//Set CSS
			var cssClass = "col" + this.uniqueId + iHeading;
			var cssRule = "width:" + (colWidths[iHeading] - this.cellBorderPadding) + "px;" + (xmlHeading.getAttribute("align") ? "text-align:" + xmlHeading.getAttribute("align") : "");
			this.cssRules.push(["." + cssClass, cssRule]);
			
			//Get Width (possibly over colspan)
			var wt = colWidths[iHeading];
			for(var q=xmlHeading,i=1;i<colspan;i++){
				if((q = q.nextSibling).nodeType != 1 && i--) continue; //for Mozilla
				wt += parseInt(q.getAttribute("width"));
			}
	
			totalWidth += wt;
			
			//Add to htmlRoot
			this.__getNewContext("HeadItem");
			var Head = this.__getLayoutNode("HeadItem");
			Head.setAttribute("class", cssClass);
	
			if(colspan) Head.setAttribute("style", "width:" + (wt) + "px;" + (xmlHeading.getAttribute("align") ? "text-align:" + xmlHeading.getAttribute("align") : ""));//hack
			var hCaption = this.__getLayoutNode("HeadItem", "caption");
	
			if(xmlHeading.getAttribute("icon")){
				hCaption.nodeValue = "";
				hCaption.parentNode.appendChild(hCaption.parentNode.ownerDocument.createElement("img")).setAttribute("src", this.iconPath + xmlHeading.getAttribute("icon"));
			}
			else{
				if(!xmlHeading.getAttribute("caption")){
					throw new Error(0, jpf.formErrorString(0, this, "rendering data for datagrid", "Missing caption attribute in heading", xmlHeading));	
				}
			
				hCaption.nodeValue = xmlHeading.getAttribute("caption");
			}
	
			//Import Head XML -> HTML
			var Head = jpf.XMLDatabase.htmlImport(Head, headParent);
	
			// Query the padding and border so the css rule actually produces the correct width.
			var padding = (parseInt(jpf.compat.getStyle(Head, "paddingLeft")) || 0) + (parseInt(jpf.compat.getStyle(Head, "paddingRight")) || 0);
			var border = (parseInt(jpf.compat.getStyle(Head, "borderLeftWidth")) || 0) + (parseInt(jpf.compat.getStyle(Head, "borderRightWidth")) || 0);
			Head.style.width = Math.max(0,wt-(padding+border)) + "px";
			
			//Add to this.headings
			var hid = this.headings.push({
				xml : xmlHeading,
				html : Head,
				width : Math.max(wt,padding+border),
				colspan : colspan,
				cssClass : cssClass
			}) - 1;

			Head.host = this;
			Head.setAttribute("hid", hid);
			
			/* Moving a column */
			Head.onmousedown = function(e){
				if(!e) e = event;
				e.cancelBubble = true;
				
				if(!jpf.isIE && !jpf.DgHeadServer.coordinates) return; //firefox quick fix
				
				// Sizing
				if(this.host.colSizing){
					var xpos = e.layerX ? e.layerX - jpf.DgHeadServer.coordinates.srcElement.offsetLeft : e.offsetX;
					var onRight = this.offsetWidth - xpos < 6;
					var onLeft = xpos < 3;
					if(onLeft || onRight){
						jpf.DgSizeServer.sizeOffset = (onRight ? this.offsetWidth-xpos : -xpos)-3; // Fixme: where the hell does this 3 come from?
						var sizeCol = onRight ? this : this.previousSibling;
						if (sizeCol) // Make sure the user is not sizing column -1.


						{
							var xmlHead = sizeCol.host.headings[sizeCol.hid].xml;
							if ((parseInt (xmlHead.getAttribute("minwidth")) || 0) != (parseInt (xmlHead.getAttribute("maxwidth")) || 9999999))
							{
								jpf.DgSizeServer.start(this.host, sizeCol);
							}
						}
						return;
					}

				}
				
				if(this.host.colSorting) 
					this.host.__setStyleClass(this, "state_down");
				
				//Dragging
				if(this.host.colMoving){
					this.host.dragging = 1;
					this.host.oSplitter.className = "dg_move_headers";
					jpf.DgHeadServer.coordinates = {
						srcElement : this, 
						offsetX : e.layerX ? e.layerX - this.offsetLeft : e.offsetX, 
						offsetY : e.layerY ? e.layerY - this.offsetTop : e.offsetY,
						clientX : e.clientX, 
						clientY : e.clientY
					};
				}
			}

			Head.__isSizingColumn = function(xpos) {
				var onRight = this.offsetWidth - xpos < 6;
				var onLeft = xpos < 3;
				if(onLeft || onRight)
				{
					col = onRight ? this : this.previousSibling;
					return col || -1;
				}
			}
		
			Head.__isSizeableColumn = function(sizeCol) {
				var xmlHead = sizeCol.host.headings[sizeCol.hid].xml;
				if ((parseInt (xmlHead.getAttribute("minwidth")) || 0) != (parseInt (xmlHead.getAttribute("maxwidth")) || 9999999))
					return true;
			}

			Head.onmousemove = function(e){
				if(!jpf.isIE && !jpf.DgHeadServer.coordinates) return;
				if(!e) var e = event;
				
				//Sizing
				if(!this.host.colSizing) return;
				
				var xpos = e.layerX ? e.layerX - jpf.DgHeadServer.coordinates.srcElement.offsetLeft : e.offsetX;
				var sizeCol = this.__isSizingColumn(xpos)	
				if (sizeCol && sizeCol != -1) // Make sure the user is not sizing column -1.
				{
					var xmlHead = sizeCol.host.headings[sizeCol.hid].xml;
					if ((parseInt (xmlHead.getAttribute("minwidth")) || 0) != (parseInt (xmlHead.getAttribute("maxwidth")) || 9999999))
						this.style.cursor = "w-resize";
				}
				else
					this.style.cursor = "default";
					
				if (!sizeCol)
				{
					//Dragging
					if(this.host.dragging != 1) return;//e.button != 1 || 
					if(Math.abs(jpf.DgHeadServer.coordinates.offsetX - (e.layerX ? e.layerX - jpf.DgHeadServer.coordinates.srcElement.offsetLeft : e.offsetX)) < 6 && Math.abs(jpf.DgHeadServer.coordinates.offsetY - (e.layerX ? e.layerY - jpf.DgHeadServer.coordinates.srcElement.offsetTop : e.offsetY)) < 6)
						return;
		
					jpf.DgHeadServer.start(this.host, this);
				}
			}
			
			Head.onmouseup = function(){
				this.host.dragging = 0;
				this.host.oSplitter.style.display = "none";
				this.host.__setStyleClass(this, "", ["state_down"]);
			}
			
			Head.ondragmove = 
			Head.ondragstart = function(){return false}
			
			/* Sorting a column */
			Head.onclick = function(){
				this.host.sortColumn(this.getAttribute("hid"));
			}
			
			Head.ondblclick = function(e)
			{
				if(!this.host.colSizing) return;
				
				// Autosize
				if(!e) var e = event;
				var xpos = e.layerX ? e.layerX - jpf.DgHeadServer.coordinates.srcElement.offsetLeft : e.offsetX;
				var sizeCol = this.__isSizingColumn(xpos)	
				if (sizeCol && sizeCol != -1 && this.__isSizeableColumn(sizeCol)) // Make sure the user is not sizing column -1.
				{
					// Autosize the heading
// 				sizeCol.style.width = "auto"; 
					var minWidth = 0;// sizeCol.offsetWidth;
					jpf.setStyleRule("." + this.host.headings[sizeCol.hid].cssClass, "width", "auto");
					
					// Iterate over all the cells. This ain't not no quick.
					var nodes = this.host.oExt.lastChild.childNodes;
					for(var i=0; i<nodes.length; i++)
						minWidth = Math.max(minWidth, nodes[i].childNodes[sizeCol.hid].offsetWidth);
					this.host.sizeColumn (sizeCol.hid, minWidth);
					this.host.__storeRelativeWidths();
				}
			}
			
		} // for(iHeading)

		// Store the relative sizes for later use.
		this.__storeRelativeWidths();
	}

	this.__loaddatabinding = function(){
		var nSibl = this.oExt.nextSibling;
		document.body.appendChild(this.oExt);
		
		var headParent = this.__getLayoutNode("Main", "head", this.oExt);
		
		this.__initDragHeading();

		// Measure Cell
		this.__getNewContext("Cell");
		var newCell = jpf.XMLDatabase.htmlImport(this.__getLayoutNode("Cell"), this.oInt);
		newCell.style.display = "block";
		//newCell.style.width = "1px";
		//newCell.style.height = "1px";
		var diff = jpf.compat.getDiff(newCell);
		newCell.parentNode.removeChild(newCell);
		this.cellBorderPadding = diff[0];
		
		//Set Up Headings
		this.__addHeadings(this.bindingRules.heading, headParent);
		this.cssRules.push([".row" + this.uniqueId, "width:" + (totalWidth) + "px"]);

		//Add extra header for empty space....
		this.__getNewContext("HeadItem");
		this.__getLayoutNode("HeadItem", "caption").nodeValue = "";
		//this.__getLayoutNode("HeadItem").setAttribute("style", "width:" + (this.jml.getAttribute("width")-totalWidth) + "px");
		this.__getLayoutNode("HeadItem").setAttribute("class", "lastHead");
		if(jpf.isIE6) this.__getLayoutNode("HeadItem").setAttribute("style", "display:none");
		jpf.XMLDatabase.htmlImport(this.__getLayoutNode("HeadItem"), headParent);

		//Activate CSS Rules
		jpf.importStylesheet(this.cssRules, window);
		this.__getLayoutNode("Main", "body", this.oExt).onscroll = new Function('var o = jpf.lookup(' + this.uniqueId + '); var head = o.__getLayoutNode("Main", "scrollhead", o.oExt);head.scrollLeft = this.scrollLeft;');
		
		pHtmlNode.insertBefore(this.oExt, nSibl);
	}
	
	this.__unloaddatabinding = function(){
		var headParent = this.__getLayoutNode("Main", "head", this.oExt);
		for(var i=0;i<headParent.childNodes.length;i++){
			headParent.childNodes[i].host = null;
			headParent.childNodes[i].onmousedown = null;
			headParent.childNodes[i].__isSizingColumn = null;
			headParent.childNodes[i].__isSizeableColumn = null;
			headParent.childNodes[i].onmousemove = null;
			headParent.childNodes[i].onmouseup = null;
			headParent.childNodes[i].ondragmove = null;
			headParent.childNodes[i].ondragstart = null;
			headParent.childNodes[i].onclick = null;
			headParent.childNodes[i].ondblclick = null;
		}
		
		this.__getLayoutNode("Main", "body", this.oExt).onscroll = null;
		
		jpf.removeNode(this.oDragHeading);
		this.oDragHeading = null;
		jpf.removeNode(this.oSplitter);
		this.oSplitter = null;
		jpf.removeNode(this.oSplitterLeft);
		this.oSplitterLeft = null;
		
		headParent.innerHTML = "";
		totalWidth = 0;
		this.headings = [];
	}

	this.nodes = [];
	this.dataset = {set:{},seq:[]};
	//<CSS select="@new='true'" default="classname" />
	this.__add = function(xmlNode, Lid, xmlParentNode, htmlParentNode, beforeNode){
		var dataset = [];
		
		//Build Row
		this.__getNewContext("Row");
		var Row = this.__getLayoutNode("Row");
		Row.setAttribute("id", Lid);
		Row.setAttribute("class", "row" + this.uniqueId);//"width:" + (totalWidth+40) + "px");
		Row.setAttribute("ondblclick", 'jpf.lookup(' + this.uniqueId + ').choose()');
		Row.setAttribute("onmousedown", 'var o = jpf.lookup(' + this.uniqueId + ');o.select(this, event.ctrlKey, event.shiftKey);');//, true;o.dragging=1;
		//Row.setAttribute("onmouseup", 'var o = jpf.lookup(' + this.uniqueId + ');o.select(this, event.ctrlKey, event.shiftKey);o.dragging=false;');
		
		//Build the Cells
		for(var i=0;i<this.headings.length;i++){
			this.__getNewContext("Cell");
			var value = this.applyRuleSetOnNode(this.headings[i].xml.getAttribute("name"), xmlNode);
			
			//(i == this.colCount-1 ? "width=100%" : "" )
			var Cell = this.__setStyleClass(this.__getLayoutNode("Cell"), "col" + this.uniqueId + i);
			var txtNode = this.__getLayoutNode("Cell", "caption");

			if(this.headings[i].xml.getAttribute("type") == "icon"){
				txtNode.nodeValue = "";
				txtNode.parentNode.appendChild(txtNode.parentNode.ownerDocument.createElement("img")).setAttribute("src", value ? this.iconPath + value : this.mediaPath + "spacer.gif");
			}
			else if(!value) jpf.XMLDatabase.setNodeValue(txtNode, " ");
			else jpf.XMLDatabase.setNodeValue(txtNode, value);

			Row.appendChild(Cell);
			dataset.push(value);
		}
		
		var cssClass = this.applyRuleSetOnNode("css", xmlNode);
		if(cssClass){
			this.__setStyleClass(Row, cssClass);
			if(cssClass) this.dynCssClasses.push(cssClass);
		}

		//return jpf.XMLDatabase.htmlImport(Row, htmlParentNode || this.oInt, beforeNode);
		if(htmlParentNode) jpf.XMLDatabase.htmlImport(Row, htmlParentNode, beforeNode);
		else this.nodes.push(Row);
		
		dataset.id = Lid;
		this.dataset.set[Lid] = dataset;
		dataset.index = this.dataset.seq.push(dataset);
	}
	
	this.__fill = function(nodes){
		jpf.XMLDatabase.htmlImport(this.nodes, this.oInt);
		this.nodes.length = 0;
	}

	/* ***********************
			DRAGDROP
	************************/
	
	this.__showDragIndicator = function(sel, e){
		var x = e.offsetX;
		var y = e.offsetY;

		this.oDrag.startX = x;
		this.oDrag.startY = y;

		document.body.appendChild(this.oDrag);
		//this.__updateNode(this.value, this.oDrag); // Solution should be found to have this on conditionally
		
		return this.oDrag;
	}
	
	this.__hideDragIndicator = function(){
		this.oDrag.style.display = "none";
	}
	
	this.__moveDragIndicator = function(e){
		this.oDrag.style.left = (e.clientX) + "px";// - this.oDrag.startX
		this.oDrag.style.top = (e.clientY+15) + "px";// - this.oDrag.startY
	}
	
	this.__initDragDrop = function(){
		if(!this.__hasLayoutNode("DragIndicator")) return;
		this.oDrag = jpf.XMLDatabase.htmlImport(this.__getLayoutNode("DragIndicator"), document.body);
		
		this.oDrag.style.zIndex = 1000000;
		this.oDrag.style.position = "absolute";
		this.oDrag.style.cursor = "default";
		this.oDrag.style.display = "none";
	}
	
	this.__dragout = 
	this.__dragover = 
	this.__dragdrop = function(){}
	
	this.inherit(jpf.DragDrop); /** @inherits jpf.DragDrop */
	
	/* ***********************
			DRAGDROP
			headings
	************************/
	
	this.__showDragHeading = function(heading, e){
		var x = e.offsetX;
		var y = e.offsetY;

		this.oDragHeading.startX = x;
		this.oDragHeading.startY = y;
		this.oDragHeading.style.left = e.clientX;
		this.oDragHeading.style.top = e.clientY;

		
		document.body.appendChild(this.oDragHeading);
		//this.oDragHeading.getElementsByTagName("DIV")[0].innerHTML = this.selected.innerHTML;
		//this.oDragHeading.getElementsByTagName("IMG")[0].src = this.selected.parentNode.parentNode.childNodes[1].firstChild.src;
		this.oDragHeading.innerHTML = heading.innerHTML;
		
		var diff = jpf.compat.getDiff(heading);
		this.oDragHeading.style.width = jpf.compat.getStyle(heading, "width");
		this.oDragHeading.style.height = jpf.compat.getStyle(heading, "height");;
		this.oDragHeading.style.padding = jpf.compat.getStyle(heading, "padding");;
		
		return this.oDragHeading;
	}
	
	this.__hideDragHeading = function(){
		this.oDragHeading.style.display = "none";
	}
	
	this.__moveDragHeading = function(e){
		this.oDragHeading.style.left = (e.clientX - this.oDragHeading.startX) + "px";
		this.oDragHeading.style.top = (e.clientY - this.oDragHeading.startY) + "px";
	}
	
	this.__initDragHeading = function(){
		if(!this.__hasLayoutNode("DragHeading") || this.oDragHeading) return;
		this.oDragHeading = jpf.XMLDatabase.htmlImport(this.__getLayoutNode("DragHeading"), document.body);
		this.oSplitter = jpf.XMLDatabase.htmlImport(this.__getLayoutNode("Splitter"), document.body);
		this.oSplitterLeft = this.oSplitter.parentNode.appendChild(this.oSplitter.cloneNode(true));
		
		this.oDragHeading.style.zIndex = 1000000;
		this.oDragHeading.style.position = "absolute";
		this.oDragHeading.style.cursor = "default";
		this.oDragHeading.style.display = "none";
	}
	
	this.__dragout = 
	this.__dragover = 
	this.__dragdrop = function(){}
	
	this.hideColumn = function(nr){
		jpf.setStyleRule(".col" + this.uniqueId + nr, "visibility", "hidden");
	}
	
	this.showColumn = function(){
		
	}
	
	this.moveColumn = function(from, to){
		if(from == to-1 || from == to) return;
		
		var pHeadings = this.__getLayoutNode("Main", "head", this.oExt);
		pHeadings.insertBefore(this.headings[from].html, this.headings[to] ? this.headings[to].html : pHeadings.lastChild);
		
		var min = Math.min(from, to), max = Math.max(from, to), htmlHeading = [];
		for(var i=0;i<min;i++) htmlHeading.push(this.headings[i]);

		if(min != from) this.headings[from].html.setAttribute("hid", htmlHeading.push(this.headings[from])-1);
		for(var i=min==from?min+1:min;i<max;i++)
			this.headings[i].html.setAttribute("hid", htmlHeading.push(this.headings[i])-1);
		if(min == from) this.headings[from].html.setAttribute("hid", htmlHeading.push(this.headings[from])-1);

		for(var i=max==from?max+1:max;i<this.headings.length;i++)
			this.headings[i].html.setAttribute("hid", htmlHeading.push(this.headings[i])-1);
		
		//if(this.htmlHeadings.length != htmlHeading.length) debugger;
		this.headings = htmlHeading;
		
		var nodes = this.__getLayoutNode("Main", "body", this.oExt).childNodes;
		for(var i=0;i<nodes.length;i++){
			nodes[i].insertBefore(nodes[i].childNodes[from], nodes[i].childNodes[to] || null);
		}
	}

	var sortObj = new jpf.Sort();
	this.sortAscending = true;
	this.currentSortColumn = null;
	this.sortColumn = function(nr){
		if(!this.colSorting) return;
		
		//Profiler.start(true);
		var sel = this.getSelection();
		for(var ids=[],i=0;i<sel.length;i++) ids.push(sel[i].getAttribute(jpf.XMLDatabase.xmlIdTag) + "|" + this.uniqueId);
		sel = null;
		//this.clearSelection();
		
		this.sortAscending = this.currentSortColumn == nr ? !this.sortAscending : true;
		sortObj.set({
			//method : sortCompare,
			getValue : function(item){return item[nr];},
			isAscending : this.sortAscending,
			type : "alpha"
		});
		this.dataset.seq = sortObj.apply(this.dataset.seq);

		var strHtml = this.oInt.innerHTML;
		var htmlNodes = strHtml.split("\n");
		var resultNodes = [];
		for(var i=0;i<htmlNodes.length;i++){
			htmlNodes[i].match(/id\=(\d+\|\d+\|\d+)/);
			resultNodes[RegExp.$1] = htmlNodes[i] + "\n";
		}

		//if(this.sortAscending) this.dataset.seq.invert();

		
		for(var sortNodes=[],i=0;i<this.dataset.seq.length;i++){
			if(this.dataset.seq[i])
				sortNodes.push(resultNodes[this.dataset.seq[i].id]);
		}

		this.oInt.innerHTML = sortNodes.join("");
		
		for(var i=0;i<ids.length;i++) 
			this.select(ids[i], true, null, true, true, true); 
		
		//Profiler.end();
		//alert(Profiler.totalTime);
		
		this.currentSortColumn = nr;
	}
	
	this.updateWindowSize = function(force)
	{
		// Size the header
		var fNode = jpf.compat.getFirstElement(this.oExt);
		
		var oldWidth = fNode.offsetWidth; // Old size.
		if (oldWidth != this.oInt.clientWidth || force) 
		{
			var innerWidth = this.oInt.clientWidth; // IE only?
			fNode.style.width = innerWidth + "px";
			
			if (this.headings && this.headings.length)
			{
				// Pass 1: Calculate the minimum/maximum usage for all following columns based on border, padding and min-width attribute.
				var minWidths = new Array();
				var maxWidths = new Array();
				var minUsage = 0, maxUsage = 0, curUsage = 0;
				for (var i=0; i<this.headings.length; i++)
				{
					// User defined minimum width.
					var minWidth = parseInt(this.headings[i].xml.getAttribute("minwidth"))||0;
					
					// Take the header's border and padding.
					var diff = jpf.compat.getWidthDiff(this.headings[i].html);

					minWidths[i] = Math.max(diff, minWidth);
					maxWidths[i] = parseInt(this.headings[i].xml.getAttribute("maxwidth"))||999999999;

					minUsage += minWidths[i];
					maxUsage += maxWidths[i];
					curUsage += this.headings[i].width;
				}

				// If there's blank space at the end, we'll just be sizing emptyness. Which is fairly easy.
				if ((curUsage < oldWidth && innerWidth > oldWidth) ||
						(curUsage < oldWidth && innerWidth < oldWidth && innerWidth >= curUsage))
				{
					jpf.setStyleRule(".row" + this.uniqueId, "width", (innerWidth) + "px");
					return; // Do jack.
				}

				// Clamp the size to min/border/padding and max widths.
				innerWidth = Math.min (Math.max (innerWidth, minUsage), maxUsage);

				// Store all relative widths and the total, so we can keep the ratios the same.
				var relativeTotal = 0, fixedTotal = 0;
				var oldRelativeTotal = 0;
				for (var i=0; i<this.headings.length; i++)
				{
					if (this.headings[i].relativeWidth)
					{
						oldRelativeTotal += this.headings[i].relativeWidth; // Before sizing.
						relativeTotal += this.headings[i].width;
					}
					else fixedTotal += this.headings[i].width;
				}

				// Crunch the relative columns first until they hit the minimum size. Then try the fixed columns.
				var newRelativeTotal = innerWidth - fixedTotal; // Space to divide over the relative columns.

				// Relative, first pass. We'll divide newRelativeTotal over all relative columns, with the exception of the ones that 
				// have complaints due to min or maximum widths. We'll remove these from the equasion.

				var usedWidth = 0;
				var relativeLeft = newRelativeTotal;
				var oldRelativeLeft = oldRelativeTotal;
				
				for (var i=0; i<this.headings.length; i++)
					this.headings[i].clamped = undefined;
					
				var nRelColsLeft = 0;
				for (var i=0; i<this.headings.length; i++)
					if (this.headings[i].relativeWidth) nRelColsLeft++;
					
				var nObjections;
				do
				{
					nObjections = 0;
					var passRelLeft = relativeLeft;
					var passOldRelLeft = oldRelativeLeft;
					for (var i=0; i<this.headings.length; i++)
					{
						if (this.headings[i].relativeWidth && !this.headings[i].clamped)
						{
							var freeSize = (nRelColsLeft == 1) ? (newRelativeTotal - usedWidth) : Math.round((this.headings[i].relativeWidth * passRelLeft) / passOldRelLeft);
							var clampedSize = Math.max(freeSize, minWidths[i]);
							clampedSize = Math.min(clampedSize, maxWidths[i]);
							if (freeSize != clampedSize)
							{
								// Objection, your honor!
								relativeLeft -= clampedSize;
								oldRelativeLeft -= this.headings[i].relativeWidth;
								this.headings[i].width = clampedSize;
								usedWidth += clampedSize;
								this.headings[i].clamped = true;
								nRelColsLeft--;
								nObjections++;
							}
						}
					}
				} while (nObjections);
				
				// Now process all the leftover relative columns that didn't have any objection.
				for (var i=0; i<this.headings.length; i++)
				{
					if (this.headings[i].relativeWidth && !this.headings[i].clamped)
					{
							var freeSize = (nRelColsLeft == 1) ? (newRelativeTotal - usedWidth) : Math.round((this.headings[i].relativeWidth * passRelLeft) / passOldRelLeft);
							this.headings[i].width = freeSize;
							usedWidth += freeSize;
							nRelColsLeft--;
					}
				}
				
				// Adjust fixed width columns.
				var pixelsShort = (usedWidth + fixedTotal) - innerWidth;
				if (pixelsShort > 0)
				{
					// We haven't the size. No, sir.
					for (var i=this.headings.length-1; i>=0; i--)
					{
						if (!this.headings[i].relativeWidth)
						{
							var newWidth = Math.max(this.headings[i].width-pixelsShort, minWidths[i]);
							pixelsShort -= (this.headings[i].width-newWidth);
							this.headings[i].width = newWidth;
							if (pixelsShort == 0)
								break; // Done.	
						}
					}
				}
					
				this.__updateHeadingSizes(0);
				this.innerWidth = innerWidth;
				this.__updateColumnSizes(0);
			}
		}
		
		this.dispatchEvent("onafterresize");
	}
	
	this.__updateHeadingSizes = function(nr)
	{
		for (var i=nr; i<this.headings.length; i++)
		{
			var diff = jpf.compat.getWidthDiff(this.headings[i].html);
			this.headings[i].html.style.width = Math.max (0,(this.headings[i].width-diff)) + "px";
		}
	}

	this.__storeRelativeWidths = function()
	{
		for (var i=0; i<this.headings.length; i++)
		{
			var xmlWidth = this.headings[i].xml.getAttribute("width");
			if (typeof(xmlWidth) == "string" && xmlWidth.indexOf("%") == -1)
				xmlWidth = parseInt(xmlWidth) || "*"; 
			if (typeof(xmlWidth) != "number") // Then it's relative.
				this.headings[i].relativeWidth = this.headings[i].width;
		}
	}

	this.__updateColumnSizes = function(nr)
	{
		// Pass 2: Apply the new sizes.
		for (var i=nr; i<this.headings.length; i++)
			jpf.setStyleRule("." + this.headings[i].cssClass, "width", (this.headings[i].width-(this.cellBorderPadding)) + "px");
		jpf.setStyleRule(".row" + this.uniqueId, "width", (this.innerWidth) + "px");
	}
	
	// This function updates all of the headings that need resizing.
	this.sizeColumn = function(nr, size, preview) 
	{
		// Calculate inner width of the datagrid control.
		var s = jpf.compat.getBox(jpf.compat.getStyle(this.oExt, "borderWidth"));
		this.innerWidth = this.oInt.clientWidth; //this.oExt.offsetWidth - (s[1] + s[3]);	// Now everything needs to fit in 'innerWidth' pixels.

		// Pass 1: Calculate the minimum usage for all following columns based on border, padding and min-width attribute.
		var minWidths = new Array();
		var minUsage = 0;
		for (var i=nr; i<this.headings.length; i++)
		{
			// User defined minimum width.
			var minWidth = parseInt(this.headings[i].xml.getAttribute("minwidth"))||0;
			
			// Take the header's border and padding.
			var diff = jpf.compat.getWidthDiff(this.headings[i].html);
			minWidths[i] = Math.max(diff, minWidth);
			if (i>nr) minUsage += minWidths[i];
		}

		// Clamp the size to min/border/padding and max widths.
		size = Math.max(minWidths[nr], size);
		size = Math.min(size, parseInt(this.headings[nr].xml.getAttribute("maxwidth"))||99999999);

		var leftWidth = 0, rightWidth = 0;
		for (var i=0;i<nr;i++)
			leftWidth += this.headings[i].width;
		for (var i=nr+1;i<this.headings.length;i++)
			rightWidth += this.headings[i].width;
		size = Math.min(size, this.innerWidth-(leftWidth+minUsage)); // Clamp to the right columns' minimum values as well.			
			
		if (size > this.headings[nr].width && leftWidth+size+rightWidth <= this.innerWidth)
			this.headings[nr].width = size; // Nothing fancy to do.
		else
		{
			// Store all relative widths and the total, so we can keep the ratios the same.
			var relativeRightTotal = 0;
			var oldRelativeRightTotal = 0;
			for (var i=nr+1; i<this.headings.length; i++)
			{
				if (this.headings[i].relativeWidth)
				{
					oldRelativeRightTotal += this.headings[i].relativeWidth; // Before sizing.
					relativeRightTotal += this.headings[i].width;
				}
			}
			
			if (size != this.headings[nr].width)
			{
				// Sizing right. Crunch the relative columns first until they hit the minimum size. Then try the fixed columns.
				var spaceAvailable = this.innerWidth - (leftWidth+size); // This is what we have divide the pixels over.
				if (size < this.headings[nr].width)
					spaceAvailable = rightWidth + (this.headings[nr].width-size);
					
				var fixedRightTotal = rightWidth - relativeRightTotal; // This is what we had for fixed columns.
				var newRelativeTotal = spaceAvailable - fixedRightTotal; // Space to divide over the relative columns.

				var relativeUsed = 0;
				for (var i=nr+1;i<this.headings.length;i++)
				{
					if (this.headings[i].relativeWidth)
					{
						// Fixme: this could overflow by one pixel due to roundoff errors.
						var colSize = Math.round((this.headings[i].relativeWidth * newRelativeTotal)/oldRelativeRightTotal);
						colSize = Math.max(colSize, minWidths[i]);
						colSize = Math.min(colSize, parseInt(this.headings[i].xml.getAttribute("maxwidth"))||99999999);
						relativeUsed += colSize;
						rightWidth += (colSize - this.headings[i].width); // Adjust rightWidth.
						this.headings[i].width = colSize;
					}
				}
				
				// Adjust fixed width columns.
				var pixelsShort = rightWidth-spaceAvailable;
				if (pixelsShort > 0)
				{
					for (var i=this.headings.length-1; i>nr; i--)
					{
						var newWidth = Math.max(this.headings[i].width-pixelsShort, minWidths[i]);
						pixelsShort -= (this.headings[i].width-newWidth);
						this.headings[i].width = newWidth;
						if (pixelsShort == 0)
							break; // Done.				
					}
				}
			}
			
			this.headings[nr].width = size; // Don't forget to set the sizing column.
		}

		// Pass 2: Apply the new sizes.
		this.__updateHeadingSizes(nr);
		if (!preview)
			this.__updateColumnSizes (nr);			
	}
	
	/* ***********************
	  Other Inheritance
	************************/
	
	this.inherit(jpf.Presentation); /** @inherits jpf.Presentation */
	this.inherit(jpf.DataBinding); /** @inherits jpf.DataBinding */
	
	/* ***********************
				INIT
	************************/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.draw = function(){
		//Build Main Skin
		this.oExt = this.__getExternal(); 
		this.oInt = this.__getLayoutNode("Main", "body", this.oExt);

		jpf.layoutServer.setRules(this.oInt, "dg" + this.uniqueId, "jpf.lookup(" + this.uniqueId + ").updateWindowSize();setTimeout(function(){jpf.lookup(" + this.uniqueId + ").updateWindowSize();});", true);

		var updScroll = this;
		updScroll.updateWindowSize(true);
		setTimeout(function(){updScroll.updateWindowSize(true);}); 
		this.addEventListener("onafterload", function(){
			// Once for scrollbar due to data changes. This gets processed when everything has been redrawn. Could move this to __fill or so.
			setTimeout(function(){updScroll.updateWindowSize(true);}); 	
		});
		this.oExt.onclick = function(){this.host.focus()}
		//this.oExt.onresize = function(){updScroll.updateWindowSize(true);}
		jpf.JMLParser.parseChildren(this.jml, null, this);
	}
	
	this.__loadJML = function(x){
		if(x.getAttribute("message")) this.clearMessage = x.getAttribute("message");
		this.colSizing = jpf.appsettings.colsizing && !jpf.isFalse(x.getAttribute("colsizing")) && jpf.isIE; //temp fix
		this.colMoving = jpf.appsettings.colmoving && !jpf.isFalse(x.getAttribute("colmoving")) && jpf.isIE;//temp fix
		this.colSorting = jpf.appsettings.colsorting && !jpf.isFalse(x.getAttribute("colsorting")) && jpf.isIE;//temp fix
	}
	
	this.__destroy = function(){
		jpf.removeNode(this.oDrag);
		this.oDrag = null;
		this.oExt.onclick = null;
		this.oInt.onresize = null;
		
		jpf.layoutServer.removeRule(this.oInt, "dg" + this.uniqueId);
		jpf.layoutServer.activateRules(this.oInt);
	}
	
	this.counter = 0;
}
/*FILEHEAD(/in/Components/Datastore.js)SIZE(1907)TIME(1203730484247)*/

/**
 * Non-visual component providing databinding functionality only.
 *
 * @classDescription		This class creates a new datastore
 * @return {Datastore} Returns a new datastore
 * @type {Datastore}
 * @constructor
 * @allowchild {smartbinding}
 * @addnode components:datastore
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.4
 */
jpf.datastore = function(){
	jpf.register(this, "datastore", NOGUI_NODE);/** @inherits jpf.Class */

	/* ***********************
			  Inheritance
	************************/
	this.inherit(jpf.DataBinding); /** @inherits jpf.DataBinding */
	this.smartBinding = true;

	/* ********************************************************************
			       PUBLIC METHODS
	*********************************************************************/
	
	this.select = function(xpath){
		var obj = typeof xpath == "string" ? this.XMLRoot.selectSingleNode(xpath) : xpath;
		this.setConnections(obj, "select");
		this.value = obj;
	}

	this.__load = function(){
		this.value = this.sXpath ? this.XMLRoot.selectSingleNode(this.sXpath) : this.XMLRoot;
		this.setConnections(this.value, "select");
	}

	this.__xmlUpdate= function(){
		
	}
	this.clear = function(){}
	
	/* *********
		INIT
	**********/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */

	this.draw = function(){}
	this.__loadJML = function(x){
		if(x.getAttribute("xpath")) this.sXpath = x.getAttribute("xpath");

		if(x.getAttribute("load")){
			var sNode = jpf.getObject("XMLDOM", "<SmartBinding><Data file='" + x.getAttribute("load") + "' /><Bindings /></SmartBinding>").documentElement;
			var dbnode = sNode.selectSingleNode("Bindings");

			jpf.JMLParser.addToSbStack(this.uniqueId, sNode);
		}
		
		jpf.JMLParser.parseChildren(x, null, this);
	}
}
/*FILEHEAD(/in/Components/Dropdown.js)SIZE(11673)TIME(1203730484247)*/

/**
 * Component allowing a user to select a value from a list 
 * which is only displayed on request by the user.
 *
 * @classDescription		This class creates a new dropdown
 * @return {Dropdown} Returns a new dropdown
 * @type {Dropdown}
 * @constructor
 * @allowchild item, {smartbinding}
 * @addnode components:dropdown
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.4
 */
jpf.dropdown = function(pHtmlNode){
	jpf.register(this, "dropdown", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	/* ********************************************************************
										PROPERTIES
	*********************************************************************/

	this.animType = 1;
	this.animSteps = 5;
	this.animSpeed = 20;
	this.itemSelectEvent = "onmouseup";
	
	this.dragdrop = false;
	this.reselectable = true;
	this.focussable = true;
	this.nonSizingHeight = true;

	/* ***********************
	  Other Inheritance
	************************/
	this.inherit(jpf.BaseList); /** @inherits jpf.BaseList */

	this.autoselect = false;
	this.multiselect = false;
	
	this.setLabel = function(value){
		this.oLabel.innerHTML = value || this.initialMsg || "";
		
		this.__setStyleClass(this.oExt, value ? "" : this.baseCSSname + "Initial", [!value ? "" : this.baseCSSname + "Initial"]);
	}

	this.addEventListener("onafterselect", function(e){
		if(!e) e = event;
		
		this.slideUp();
		if(!this.isOpen) this.__setStyleClass(this.oExt, "", [this.baseCSSname + "over"]);
		
		this.setLabel(this.applyRuleSetOnNode("caption", this.value))
		//return selBindClass.applyRuleSetOnNode(selBindClass.mainBind, selBindClass.XMLRoot, null, true);
		
		this.__updateOtherBindings();
		
		if(this.hasFeature(__VALIDATION__) && this.form){
			this.validate();
		}
	});
	
	this.addEventListener("onafterdeselect", function(){
		this.setLabel("");
	});
	
	function setMaxCount(){
		this.setMaxItems(this.getTraverseNodes().length);
		if(this.isOpen == 2) this.slideDown();
	}
	this.addEventListener("onafterload", setMaxCount);
	this.addEventListener("onxmlupdate", function(){
		setMaxCount.call(this);
		this.setLabel(this.applyRuleSetOnNode("caption", this.value));
	});
	
	/*this.addEventListener("oninitselbind", function(bindclass){
		var jmlNode = this;
		bindclass.addEventListener("onxmlupdate", function(){
			debugger;
			jmlNode.__showSelection();
		});
	});*/
	
	//For MultiBinding
	this.__showSelection = function(value){
		//Set value in Label
		var bc = this.getSelectionSmartBinding();

		//Only display caption when a value is set
		if(value === undefined){
			var sValue2, sValue = bc.applyRuleSetOnNode("value", bc.XMLRoot, null, true);
			if(sValue) sValue2 = bc.applyRuleSetOnNode("caption", bc.XMLRoot, null, true);

			if(!sValue2 && this.XMLRoot && sValue){
				var rule = this.getBindRule(this.mainBind).getAttribute("select");
				
				xpath = this.ruleTraverse + "[" + rule + "='" + sValue.replace(/'/g, "\\'") + "']";
				
				var xmlNode = this.XMLRoot.selectSingleNode(xpath);// + "/" + this.getBindRule("caption").getAttribute("select")
				value = this.applyRuleSetOnNode("caption", xmlNode);
			}
			else{
				value = sValue2 || sValue;
			}
		}
		this.setLabel(value || "");
	}
	
	//I might want to move this method to the MultiLevelBinding baseclass
	this.__updateOtherBindings = function(){
		if(!this.multiselect){
			// Set Caption bind
			var bc = this.getSelectionSmartBinding(), caption;
			if(bc && bc.XMLRoot && (caption = bc.bindingRules["caption"])){
				var xmlNode = jpf.XMLDatabase.createNodeFromXpath(bc.XMLRoot, bc.bindingRules["caption"][0].getAttribute("select"));
				if(!xmlNode) return;
	
				jpf.XMLDatabase.setNodeValue(xmlNode, this.applyRuleSetOnNode("caption", this.value));
			}
		}
	}
	
	/* ***********************
	  Private functions
	************************/
	
	this.__blur = function(){
		this.slideUp();
		//this.oExt.dispatchEvent("onmouseout")
		if(!this.isOpen) this.__setStyleClass(this.oExt, "", [this.baseCSSname + "over"])
		//if(this.oExt.onmouseout) this.oExt.onmouseout();
		
		this.__setStyleClass(this.oExt, "", [this.baseCSSname + "Focus"]);
	}
	
	this.keyHandler = function(key, ctrlKey, shiftKey, altKey){
		//this.__keyHandler(key, ctrlKey, shiftKey, altKey);
		if(!this.XMLRoot) return;
		
		switch(key){
			case 38:
			//UP
				if(!this.value && !this.indicator) return;
				var node = this.getNextTraverseSelected(this.indicator || this.value, false);
				if(node) this.select(node);
				
			break;
			case 40:
			//DOWN
				var node;
				
				if(!this.value && !this.indicator){
					node = this.getFirstTraverseNode();
					if(!node) return;
				}
				else node = this.getNextTraverseSelected(this.indicator || this.value, true);
				if(node) this.select(node);
				
			break;
			default:
				if(key == 9) return;	
			
				//if(key > 64 && key < 
				if(!this.lookup || new Date().getTime() - this.lookup.date.getTime() > 1000) this.lookup = {
					str : "",
					date : new Date()
				};

				this.lookup.str += String.fromCharCode(key);
				
				var nodes = this.getTraverseNodes();
				for(var i=0;i<nodes.length;i++){
					if(this.applyRuleSetOnNode("caption", nodes[i]).indexOf(this.lookup.str) > -1){
						this.select(nodes[i]);
						return;
					}
				}
			return;
		}

		return false;
	}
	
	/* *********
		INIT
	**********/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.__setClearMessage = function(msg){
		this.setLabel(msg);
	}
	
	this.__removeClearMessage = function(){
		this.setLabel("");
	}

	this.slideToggle = function(e){
		if(!e) e = event;
		
		if(this.isOpen) this.slideUp();
		else this.slideDown(e);
	}

	this.slideDown = function(e){
		if(this.dispatchEvent("onslidedown") === false) return false;
		
		this.isOpen = true;
		
		this.oSlider.style.display = "block";
		this.oSlider.style[jpf.supportOverflowComponent ? "overflowY" : "overflow"] = "hidden";
		
		this.oSlider.style.display = "";
		this.__setStyleClass(this.oExt, this.baseCSSname + "Down");
		
		/*var HT = this.sliderHeight;
		new jpf.GuiAnimation(this.oSlider, this.direction == "up" ? 'scrolltop' : 'scrollheight', 0, HT, this.animType, this.animSteps, this.animSpeed, 
			function(container){
				container.style[jpf.isIE ? "overflowY" : "overflow"] = "auto";
			});*/

		//var pos = jpf.compat.getAbsolutePosition(this.oExt);
		this.oSlider.style.height = (this.sliderHeight - 1) + "px";
		this.oSlider.style.width = (this.oExt.offsetWidth - 2) + "px";

		jpf.Popup.show(this.uniqueId, 0, this.oExt.offsetHeight, true, this.oExt, this.oExt.offsetWidth, this.containerHeight,
			function(container){
				container.style[jpf.supportOverflowComponent ? "overflowY" : "overflow"] = "auto";
			});
	}
	this.addEventListener("onslidedown", function(){
		//THIS SHOULD BE UPDATED TO NEW SMARTBINDINGS
		if(!this.form || !this.form.xmlActions || this.XMLRoot) return;
		var loadlist = this.form.xmlActions.selectSingleNode("LoadList[@element='" + this.name + "']");
		if(!loadlist) return;
		
		this.isOpen = 2;
		this.form.processLoadRule(loadlist, true, [loadlist]);
		
		return false;
	});
	
	this.slideUp = function(){
		if(this.isOpen == 2) return;
		if(this.dispatchEvent("onslideup") === false) return false;
		
		this.isOpen = false;
		if(this.value){
			var htmlNode = jpf.XMLDatabase.findHTMLNode(this.value, this);
			if(htmlNode) this.__setStyleClass(htmlNode, '', ["hover"]);
		}
		
		this.__setStyleClass(this.oExt, '', [this.baseCSSname + "Down"]);
		jpf.Popup.hide();
	}
	this.addEventListener("onpopuphide", this.slideUp);
	
	this.setMaxItems = function(count){
		this.sliderHeight = count ? (Math.min(this.maxItems, count) * this.itemHeight) : 10;
		this.containerHeight = count ? (Math.min(this.maxItems, count) * this.itemHeight) : 10;
		if(this.containerHeight > 20) this.containerHeight = Math.ceil(this.containerHeight*0.9);
	}
	
	this.draw = function(){
		this.animType = this.__getOption("Main", "animtype") || 1;
		this.clickOpen = this.__getOption("Main", "clickopen") || "button";

		//Build Main Skin
		this.oExt = this.__getExternal(null, null, function(oExt){
			oExt.setAttribute("onmouseover", 'var o = jpf.lookup(' + this.uniqueId + ');o.__setStyleClass(o.oExt, o.baseCSSname + "over");');
			oExt.setAttribute("onmouseout", 'var o = jpf.lookup(' + this.uniqueId + ');if(o.isOpen) return;o.__setStyleClass(o.oExt, "", [o.baseCSSname + "over"]);');
			
			//Button
			var oButton = this.__getLayoutNode("Main", "button", oExt);
			if(oButton){
				oButton.setAttribute("onmousedown", 'jpf.lookup(' + this.uniqueId + ').slideToggle(event);');
				//oButton.setAttribute("onmouseup", 'var o = jpf.lookup(" + this.uniqueId + ");o.__setStyleClass(o.oExt, '', [o.oExt.className.split(' ')[0] + 'down'])");
				//oButton.setAttribute("onmouseout", 'var o = jpf.lookup(" + this.uniqueId + ");o.__setStyleClass(o.oExt, '', [o.oExt.className.split(' ')[0] + 'down'])");
			}
			
			//Label
			var oLabel = this.__getLayoutNode("Main", "label", oExt);
			if(this.clickOpen == "both"){
				oLabel.parentNode.setAttribute("onmousedown", 'jpf.lookup(' + this.uniqueId + ').slideToggle(event);');
			}
		});
		this.oLabel = this.__getLayoutNode("Main", "label", this.oExt);
		
		if(this.oLabel.nodeType == 3) this.oLabel = this.oLabel.parentNode;
		
		this.oIcon = this.__getLayoutNode("Main", "icon", this.oExt);
		if(this.oButton) this.oButton = this.__getLayoutNode("Main", "button", this.oExt);
		
		//Slider
		/*var oSlider = this.__getLayoutNode("Container", null, oExt);
		oSlider.setAttribute("onmouseover", "event.cancelBubble = true");
		oSlider.setAttribute("onmouseout", "event.cancelBubble = true");*/
		this.oSlider = jpf.XMLDatabase.htmlImport(this.__getLayoutNode("Container"), document.body);
		this.oInt = this.__getLayoutNode("Container", "contents", this.oSlider);
		
		//Set up the popup
		this.pHtmlDoc = jpf.Popup.setContent(this.uniqueId, this.oSlider, jpf.PresentationServer.getTemplate(this.skinName).selectSingleNode("style").firstChild.nodeValue);
		
		//Get Options form skin
		this.listtype = parseInt(this.__getLayoutNode("Main", "type")) || 1; //Types: 1=One dimensional List, 2=Two dimensional List
		
		if(this.jml.childNodes.length) this.loadInlineData(this.jml);
		if(this.jml.getAttribute("fill")) this.loadFillData(this.jml.getAttribute("fill"));
	}
	
	this.__loadJML = function(x){
		this.name = x.getAttribute("id");
		this.maxItems = x.getAttribute("maxitems") || 5;
		this.disableremove = x.getAttribute("disableremove") != "false";
		
		this.setMaxItems();
		
		if(x.getAttribute("multibinding") == "true" && !x.getAttribute("ref"))
			this.inherit(jpf.MultiLevelBinding); /** @inherits jpf.MultiLevelBinding */
		
		this.initialMsg = x.getAttribute("initial");
		
		this.itemHeight = this.__getOption("Main", "item-height") || 18.5;
	}
	
	this.__destroy = function(){
		jpf.Popup.removeContent(this.uniqueId);
		jpf.removeNode(this.oSlider);
		this.oSlider = null;
	}
}
/*FILEHEAD(/in/Components/Errorbox.js)SIZE(2282)TIME(1203730484247)*/

/**
 * Component showing an error message when the attached component 
 * is in erroneous state and has the invalidmsg="" attribute specified.
 * In most cases the errorbox component is implicit and will be created 
 * automatically. 
 *
 * @classDescription		This class creates a new errorbox
 * @return {Errorbox} Returns a new errorbox
 * @type {Errorbox}
 * @constructor
 * @allowchild {anyxhtml}
 * @addnode components:errorbox
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.4
 */
jpf.errorbox = function(pHtmlNode){
	jpf.register(this, "errorbox", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	/* ***********************
	  		Inheritance
	************************/
	this.inherit(jpf.Presentation); /** @inherits jpf.Presentation */
	
	this.editableParts = {"Main" : [["container","@invalidmsg"]]};
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/
	
	this.setMessage = function(value){
		if(value.indexOf(";")>-1){
			value = value.split(";");
			value = "<strong>" + value[0] + "</strong>" + value[1];
		}
		this.oInt.innerHTML = value;
	}
	
	/* *********
		INIT
	**********/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	
	this.draw = function(){
		//Build Main Skin
		this.oExt = this.__getExternal(); 
		this.oInt = this.__getLayoutNode("Main", "container", this.oExt);
		
		this.hide();
	}
	
	this.__loadJML = function(x){
		if(x.firstChild) this.setMessage(x.firstChild.nodeValue);
		
	}
}
/*FILEHEAD(/in/Components/FastList.js)SIZE(4382)TIME(1203730484247)*/

/**
 * Component displaying a list of options which might be selected.
 * This component is optimized for large number of items (1000+) and
 * has been tested with more than 100,000 items.
 *
 * @classDescription		This class creates a new fastlist
 * @return {Fastlist} Returns a new fastlist
 * @type {Fastlist}
 * @constructor
 * @allowchild {smartbinding}
 * @addnode components:fastlist
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.4
 */
jpf.fastlist = function(pHtmlNode){
	jpf.register(this, "fastlist", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	/* ***********************
			  RENAME
	************************/
	
	this.__getCaptionElement = function(){
		var x = this.__getLayoutNode("Item", "caption", this.selected);
		if(!x) return false;
		return x.nodeType == 1 ? x : x.parentNode;
	}
	
	this.addEventListener("onafterselect",function(e){
		if(this.hasFeature(__VALIDATION__)) this.validate();
	});
	
	/* ***********************
	  Other Inheritance
	************************/
	this.inherit(jpf.BaseFastList); /** @inherits jpf.BaseFastList */
	
	this.keyHandler = this.__keyHandler;
	
	this.inherit(jpf.Rename); /** @inherits jpf.Rename */
	
	/* ***********************
			DRAGDROP
	************************/
	
	this.__showDragIndicator = function(sel, e){
		var x = e.offsetX;
		var y = e.offsetY;

		this.oDrag.startX = x;
		this.oDrag.startY = y;
		
		document.body.appendChild(this.oDrag);
		//this.oDrag.getElementsByTagName("DIV")[0].innerHTML = this.selected.innerHTML;
		//this.oDrag.getElementsByTagName("IMG")[0].src = this.selected.parentNode.parentNode.childNodes[1].firstChild.src;
		this.__updateNode(this.value, this.oDrag);
		
		return this.oDrag;
	}
	
	this.__hideDragIndicator = function(){
		this.oDrag.style.display = "none";
	}
	
	this.__moveDragIndicator = function(e){
		this.oDrag.style.left = (e.clientX - this.oDrag.startX) + "px";
		this.oDrag.style.top = (e.clientY - this.oDrag.startY) + "px";
	}
	
	this.__initDragDrop = function(){
		if(!this.__hasLayoutNode("DragIndicator")) return;
		this.oDrag = jpf.XMLDatabase.htmlImport(this.__getLayoutNode("DragIndicator"), document.body);
		
		this.oDrag.style.zIndex = 1000000;
		this.oDrag.style.position = "absolute";
		this.oDrag.style.cursor = "default";
		this.oDrag.style.display = "none";
	}
	
	this.__dragout = 
	this.__dragover = 
	this.__dragdrop = function(){}
	
	this.inherit(jpf.DragDrop); /** @inherits jpf.DragDrop */
	
	/* *********
		INIT
	**********/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.draw = function(){
		//Build Main Skin
		this.oExt = this.__getExternal(); 
		this.oInt = this.__getLayoutNode("Main", "container", this.oExt);

		/*this.oExt.onmousedown = function(e){
			if(!e) e = event;
			if(e.ctrlKey || e.shiftKey) return;
			
			var srcElement = jpf.isIE ? e.srcElement : e.target;
			debugger;
			if(this.host.allowDeselect && (srcElement == this || srcElement.getAttribute(jpf.XMLDatabase.htmlIdTag)))
				this.host.clearSelection(); //hacky
		}*/
		
		this.oExt.onclick = function(e){
			this.host.dispatchEvent("onclick", {htmlEvent : e || event});
		}
		
		this.sb = new jpf.Scrollbar(this.pHtmlNode);

		//Get Options form skin
		this.listtype = parseInt(this.__getLayoutNode("Main", "type")) || 1; //Types: 1=One dimensional List, 2=Two dimensional List
		this.behaviour = parseInt(this.__getLayoutNode("Main", "behaviour")) || 1; //Types: 1=Check on click, 2=Check independent
	}
	
	this.__loadJML = function(x){
		if(this.jml.childNodes.length) this.loadInlineData(this.jml);
		
		if(this.hasFeature(__MULTIBINDING__) && x.getAttribute("value")) this.setValue(x.getAttribute("value"));
		
		// this.doOptimize(true);
		
		if(x.getAttribute("multibinding") == "true" && !x.getAttribute("ref")) 
			this.inherit(jpf.MultiLevelBinding); /** @inherits jpf.MultiLevelBinding */
	}
	
	this.__destroy = function(){
		this.oExt.onclick = null;	
	}
}
/*FILEHEAD(/in/Components/FileUploadBox.js)SIZE(9579)TIME(1203730484247)*/

/**
 * Component allowing the user to upload a file to a server. Whilst
 * uploading this component shows a virtual progressbar. The component
 * also provides a visual representation of the uploaded file.
 *
 * @classDescription		This class creates a new fileuploadbox
 * @return {Fileuploadbox} Returns a new fileuploadbox
 * @type {Fileuploadbox}
 * @constructor
 * @alias upload
 * @addnode components:fileuploadbox, components:upload
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.4
 */
jpf.upload = 
jpf.fileuploadbox = function(pHtmlNode, tagName){
	jpf.register(this, tagName || "fileuploadbox", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	/* ********************************************************************
										PROPERTIES
	*********************************************************************/
	
	//Options
	this.focussable = true; // This object can get the focus
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/
	
	this.setIcon = function(url){
		if(this.oIcon.tagName == "img") this.oIcon.setAttribute("src", this.iconPath + url);
		else this.oIcon.style.backgroundImage = "url(" + this.iconPath + url + ")";
	}
	
	this.SetCaption = function(value){
		this.oCaption.nodeValue = value;
		//this.change(value, true);
	}
	
	/* ***************
		API
	****************/
	
	this.getValue = function(){
		return this.value;
	}
	
	this.setValue = function(value){
		if(!this.value) this.old_value = value;
		this.value = value;
		
		if(this.oInt.nodeType == 1) this.oInt.innerHTML = value;
		else this.oInt.nodeValue = value;
		//this.Change(value);
	}
	
	this.setCaption = function(value){
		if(!value) value = "";
		//this.oInt.innerHTML = value;
		//this.SetCaption(value);
		this.lastCaption = value;
		this.oCaption.nodeValue = value;
	}
	
	this.__enable = function(){
		enable(this.oBtn);
	}
	
	this.__disable = function(){
		disable(this.oBtn);
	}
	
	this.showBrowseWindow = function(){
		if(this.disabled) return;

		this.inpFile.click();
		//this.__startUpload();
	}
	
	this.__startUpload = function(){
		if(this.value == this.inpFile.value || !this.inpFile.value) return;
		
		this.old_value = this.value;
		this.value = this.inpFile.value;
		this.setValue(this.value);
		
		this.upload();
	}
	
	this.updateProgress = function(){
		this.oSlider.style.width = this.oSlider.offsetWidth + 1;
	}
	
	this.upload = function(){
		this.uploading = true;
		
		this.disableEvents();
		this.oCaption.nodeValue = "Uploading...";
		this.oSliderExt.style.display = "block";
		//this.oSlider.style.display = "block";
		this.oSlider.style.width = 1;
		this.timer = setInterval('jpf.lookup(' + this.uniqueId + ').updateProgress()', 800);
		this.timeout_timer = setTimeout('jpf.lookup(' + this.uniqueId + ').doTimeout()', this.timeout);
		this.form.submit();
	}
	
	this.done = function(value, caption){
		window.clearInterval(this.timer);
		window.clearInterval(this.timeout_timer);
		this.oSlider.style.width = "100%";
		window.setTimeout('jpf.lookup(' + this.uniqueId + ').clearProgress()', 300);

		if(value) this.setValue(value);
		this.old_value = null;
		
		//if(caption) 
		this.setCaption(this.lastCaption);

		this.dispatchEvent("onreceive", {returnValue : value});

		this.initForm();
		this.uploading = false;
		this.setEvents();
	}
	
	this.cancel = function(value, caption){
		window.clearInterval(this.timer);
		window.clearInterval(this.timeout_timer);
		this.clearProgress();

		this.setCaption(this.lastCaption);
		if(this.old_value) this.setValue(this.old_value);
		this.old_value = null;
		
		this.dispatchEvent("oncancel", {returnValue : value});

		this.initForm();
		this.uploading = false;
		this.setEvents();
	}
	
	this.doTimeout = function(){
		clearInterval(this.timer);
		
		this.setEvents();
		this.oCaption.nodeValue = this.jml.firstChild ? this.jml.firstChild.nodeValue : "";
		this.clearProgress();
		
		if(this.old_value) this.setValue(this.old_value);
		this.old_value = null;
		
		this.initForm();
		this.uploading = false;
		
		this.dispatchEvent("ontimeout");
	}
	
	this.clearProgress = function(){
		//this.oInt.style.display = "block";
		this.oSliderExt.style.display = "none";
	}
	
	/* ***************
		DATABINDING
	****************/
	
	this.inherit(jpf.DataBinding); /** @inherits jpf.DataBinding */
	
	/* ***********************
	  Other Inheritance
	************************/
	
	this.inherit(jpf.Presentation); /** @inherits jpf.Presentation */
	
	/* ***********************
	  		Events
	************************/
	
	this.disableEvents = function(){
		this.oBtn.onclick = this.oBtn.onmouseover = this.oBtn.onmouseout = this.oBtn.onmouseup = this.oBtn.onmousedown = null;
	}
	
	this.setEvents = function(){
		this.oBtn.onmousedown = function(e){
			this.host.__setStyleClass(this, this.host.baseCSSname + "down", [this.host.baseCSSname + "over"]);
			if(this.host.onmousedown) this.host.onmousedown();
			(e || event).cancelBubble = true;
		};
		this.oBtn.onmouseover = function(e){
			this.host.__setStyleClass(this, this.host.baseCSSname + "over", [this.host.baseCSSname + "down"]);
			if(this.host.bgswitch) this.host.__getLayoutNode("Main", "background", this.host.oBtn).style.backgroundPosition = "-" + jpf.getStyle(this.host.oBtn, "width") + " 0";
			if(this.host.onmouseover) this.host.onmouseover();
			(e || event).cancelBubble = true;
		};
		this.oBtn.onmouseout = function(e){
			this.host.__setStyleClass(this, "", [this.host.baseCSSname + "down", this.host.baseCSSname + "over"]);
			if(this.host.bgswitch) this.host.__getLayoutNode("Main", "background", this.host.oBtn).style.backgroundPosition = "0 0";
			if(this.host.onmouseout) this.host.onmouseout();
			(e || event).cancelBubble = true;
		};
		this.oBtn.onmouseup = function(e){
			this.host.__setStyleClass(this, this.host.baseCSSname + "over", [this.host.baseCSSname + "down"]);
			if(this.host.bgswitch) this.host.__getLayoutNode("Main", "background", this.host.oBtn).style.backgroundPosition = "-" + jpf.getStyle(this.host.oBtn, "width") + " 0";
			if(this.host.onmouseup)this.host.onmouseup();
			(e || event).cancelBubble = true;
		};
		this.oBtn.onclick = function(e){
			if(this.host.onclick) this.host.onclick();
			(e || event).cancelBubble = true;
			
			this.host.showBrowseWindow();
		}
	}
	
	/* *********
		INIT
	**********/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.setTarget = function(target){
		this.target = target;
		this.initForm();
	}
	
	this.initForm = function(){
		if(jpf.isIE){
			this.oFrame.contentWindow.document.write("<body></body>");
			this.form = jpf.XMLDatabase.htmlImport(this.__getLayoutNode("Form"), this.oFrame.contentWindow.document.body);
		}
		
		//this.form = this.__getLayoutNode("Main", "form", this.oExt);
		this.form.setAttribute("action", this.target);
		this.form.setAttribute("target", "upload" + this.uniqueId);
		this.__getLayoutNode("Form", "inp_uid", this.form).setAttribute("value", this.uniqueId);
		this.inpFile = this.__getLayoutNode("Form", "inp_file", this.form);
		
		var jmlNode = this;
		this.inpFile.onchange = function(){
			jmlNode.__startUpload();
		}
		
		if(jpf.isGecko){
			this.inpFile.onmouseover = function(e){
				if(jmlNode.oBtn.onmouseover)
					jmlNode.oBtn.onmouseover(e);
			}
			this.inpFile.onmouseout = function(e){
				if(jmlNode.oBtn.onmouseout)
					jmlNode.oBtn.onmouseout(e);
			}
		}

		if(jpf.debug == 2){
			this.oFrame.style.visibility = "visible";
			this.oFrame.style.width = "100px";
			this.oFrame.style.height = "100px";
		}
	}
	
	this.draw = function(){
		//Build Main Skin
		this.oExt = this.__getExternal("Main", null, function(oExt){
			oExt.appendChild(oExt.ownerDocument.createElement("iframe")).setAttribute("name", "upload" + this.uniqueId);
		});
		
		this.oInt = this.__getLayoutNode("Main", "value", this.oExt);
		this.oBtn = this.__getLayoutNode("Main", "button", this.oExt);
		this.oIcon = this.__getLayoutNode("Main", "icon", this.oExt);
		this.oCaption = this.__getLayoutNode("Main", "caption", this.oExt);
		this.oSliderExt = this.__getLayoutNode("Main", "slider", this.oExt);
		this.oSlider = this.__getLayoutNode("Main", "slidemove", this.oExt);
		
		this.oFrame = this.oExt.getElementsByTagName("iframe")[0];
		if(!jpf.isIE) this.form = jpf.XMLDatabase.htmlImport(this.__getLayoutNode("Form"), this.oExt);
		
		this.oBtn.host = this;
		
		this.setEvents();
	}
	
	this.__loadJML = function(x){
		this.target = x.getAttribute("target");
		if(x.getAttribute("value")) this.setValue(x.getAttribute("value"));
		
		this.setCaption(x.firstChild ? x.firstChild.nodeValue : "");
		if(x.getAttribute("icon")) this.setIcon(x.getAttribute("icon"));
		if(x.getAttribute("onclick")) this.onclick = x.getAttribute("onclick");
		this.timeout = x.getAttribute("timeout") || 100000;
		
		this.bgswitch = x.getAttribute("bgswitch") ? true : false;
		if(this.bgswitch){
			this.__getLayoutNode("Main", "background", this.oExt).style.backgroundImage = "url(" + this.mediaPath + x.getAttribute("bgswitch") + ")";
			this.__getLayoutNode("Main", "background", this.oExt).style.backgroundRepeat = "no-repeat";
		}
		
		this.initForm();
	}
	
	this.__destroy = function(){
		this.oBtn.host = null;
	}
}
/*FILEHEAD(/in/Components/Flash.js)SIZE(2582)TIME(1202849967875)*/

/**
 * Component displaying the contents of a .swf (adobe flash) file.
 *
 * @classDescription		This class creates a new flash
 * @return {Flash} Returns a new flash
 * @type {Flash}
 * @constructor
 * @allowchild {smartbinding}
 * @addnode components:flash
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.9
 */
jpf.flash = function(pHtmlNode){
	jpf.register(this, "flash", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	//this.editableParts = {"Main" : [["image","@src"]]};
	
	this.setValue = function(value){
		//this.setProperty("value", value);
	}
	
	this.getApi = function(){
		return this.oExt;
	}
	
	this.__supportedProperties = ["value"];
	this.__handlePropSet = function(prop, value){
		switch(prop){
			case "value":
				this.setSource(value);
			break;
		}
	}
	
	this.draw = function(){
		//Build Main Skin
		//this.oInt = this.oExt = this.__getExternal();
		//this.oExt.onclick = function(){this.host.dispatchEvent("onclick");}
		
		var src = this.jml.getAttribute("src") || "";
		document.body.insertAdjacentHTML("beforeend", '<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" width="1" height="1" align="middle"><param name="allowScriptAccess" value="sameDomain" /><param name="allowFullScreen" value="false" /><param name="movie" value="' + src + '" /><param name="play" value="false" /><param name="menu" value="false" /><param name="quality" value="high" /><param name="wmode" value="transparent" /><param name="bgcolor" value="#ffffff" />	<embed src="' + src + '" play="false" menu="false" quality="high" wmode="transparent" bgcolor="#ffffff" width="1" height="1" align="middle" allowScriptAccess="sameDomain" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" /></object>')
		this.oExt = document.body.lastChild;
		pHtmlNode.appendChild(this.oExt);
	}
	
	this.__loadJML = function(x){
			//this.__makeEditable("Main", this.oExt, this.jml);
		
		jpf.JMLParser.parseChildren(x, null, this);
	}
	
	this.inherit(jpf.BaseSimple); /** @inherits jpf.BaseSimple */
}

/*FILEHEAD(/in/Components/Frame.js)SIZE(1925)TIME(1203730484247)*/

/**
 * Component displaying a frame with a title containing other components.
 *
 * @classDescription		This class creates a new frame
 * @return {Frame} Returns a new frame
 * @type {Frame}
 * @constructor
 * @allowchild {components}, {anyjml}
 * @addnode components:frame
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.9
 */
jpf.frame = function(pHtmlNode){
	jpf.register(this, "frame", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;

	/* ***********************
	  		Inheritance
	************************/
	this.inherit(jpf.Presentation); /** @inherits jpf.Presentation */
	
	this.editableParts = {"Main" : [["caption","@caption"]]};
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/
	
	this.setCaption = function(value){
		this.oCaption.nodeValue = value;
	}
		
	/* *********
		INIT
	**********/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.draw = function(){
		//Build Main Skin
		this.oExt = this.__getExternal(); 
		this.oCaption = this.__getLayoutNode("Main", "caption", this.oExt);
		var oInt = this.__getLayoutNode("Main", "container", this.oExt);
		
			this.__makeEditable("Main", this.oExt, this.jml);
		
		this.oInt = this.oInt ? 
			jpf.JMLParser.replaceNode(oInt, this.oInt) : 
			jpf.JMLParser.parseChildren(this.jml, oInt, this);
	}
	
	this.__loadJML = function(x){
		if(x.getAttribute("caption")) this.setCaption(x.getAttribute("caption"));
	}
}
/*FILEHEAD(/in/Components/Hbox.js)SIZE(5461)TIME(1213483123975)*/

/**
 * @define vbox
 * @define hbox
 */
jpf.hbox = 
jpf.vbox = function(pHtmlNode, tagName){
 	jpf.register(this, tagName, GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	function checkSplitters(node){
		var lastNode = node.children[node.children.length-1];
		if(lastNode.splitter && node.parent){
			var p = node;
			p.splitter = lastNode.splitter;
			p.edgeMargin = Math.max(p.edgeMargin, p.splitter);
			lastNode.splitter = null;
			
			if(p.parent && p.stackId == p.parent.children.length-1){
				p.parent.splitter = p.splitter;
				p.parent.edgeMargin = Math.max(p.parent.edgeMargin, p.parent.splitter);
				p.splitter = null;
			}
		}
		var firstNode = node.children[0];
		if(firstNode && node.parent){
			if(node.vbox){
				node.fwidth = firstNode.fwidth;
				firstNode.fwidth = null;
			}
			else{
				node.fheight = firstNode.fheight;
				firstNode.fheight = null;
			}
			node.weight = firstNode.weight;
		}
		
		for(var i=0;i<node.children.length;i++){
			if(!node.children[i].node) 
				checkSplitters(node.children[i]);
		}
	}
	
	this.compileAlignment = function(){
		var n = this.aData.children;
		for(var f=false,i=0;i<n.length;i++){
			if(n[i].template == "bottom"){
				if(n[i].splitter){
					n[i-1].splitter = n[i].splitter;
					n[i-1].edgeMargin = Math.max(n[i-1].edgeMargin, n[i-1].splitter);
					n[i].splitter = null;
				}
			}
		}
		
		checkSplitters(this.aData);
		jpf.layoutServer.compile(pHtmlNode);
	}
	
	this.addAlignNode = function(jmlNode){
		var align = jmlNode.jml.getAttribute("align").split("-");
		var s = this.aData.children;
		var a = jmlNode.aData;
		if(align[1] == "splitter"){
			a.splitter = align[2] || 5;
			a.edgeMargin = Math.max(a.edgeMargin, a.splitter);
		}
		align = align[0];
		a.template = align;

		if(align == "top"){
			for(var p=s.length,i=0;i<s.length;i++){
				if(s[i].template != "top"){
					p = i;
					break;
				}
			}
			for(var i=s.length-1;i>p;i++){
				s[i+1] = s[i];
				s[i].stackId = i+1;
			}

			s[p] = a;
			s[p].stackId = p;
			a.parent = this.aData;
		}
		else if(align == "bottom"){
			a.stackId = s.push(a) - 1;
			a.parent = this.aData;
		}
		else{
			//find hbox
			var hbox = null;
			for(var p=0,i=0;i<s.length;i++){
				if(s[i].hbox){
					hbox = s[i];
					break;
				}
				else if(s[i].node && s[i].template == "top") p = i;
			}
			
			//create hbox
			if(!hbox){
				var hbox = new jpf.hbox(this.pHtmlNode, "hbox");
				hbox.loadJML(jpf.XMLDatabase.getXml("<hbox />"));
				hbox.parentNode = this;
				hbox.aData.jmlNode = hbox;
				hbox = hbox.aData;
				hbox.parent = this.aData;
				if(p){
					for(var i=s.length-1;i>p;i--){
						s[i+1] = s[i];
						s[i].stackId++;
					}
					s[p+1] = hbox;
					hbox.stackId = p+1;
				}
				else hbox.stackId = s.push(hbox) - 1;
			}
			
			//find col
			var col, n = hbox.children;
			for(var i=0;i<n.length;i++){
				if(n[i].template == align){
					col = n[i];
					break;
				}
			}
			
			//create col
			if(!col){
				var col = new jpf.vbox(this.pHtmlNode, "vbox");
				col.loadJML(jpf.XMLDatabase.getXml("<vbox />"));
				col.parentNode = hbox.jmlNode;
				col = col.aData;
				col.parent = hbox;
				col.template = align;
				
				if(align == "left"){
					n.unshift(col);
					for(var i=0;i<n.length;i++) n[i].stackId = i;
				}
				else if(align == "right") col.stackId = n.push(col) - 1;
				else if(align == "middle"){
					for(var f,i=0;i<n.length;i++) if(n[i].template == "right") f = i;
					var rcol = n[f];
					if(rcol){
						n[f] = col; col.stackId = f;
						rcol.stackId = n.push(rcol) - 1;
					}
					else{
						col.stackId = n.push(col) - 1;
					}
				}
			}
			
			a.stackId = col.children.push(a) - 1;
			a.parent = col;
		}
	}
	
	/* *********
		INIT
	**********/
	//inheriting might needs to be reconsidered
	//this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.loadJML = function(x, pJmlNode, ignoreBindclass, id){
		this.name = x.getAttribute("id");
		
		if(x){
			if(!this.parentNode) this.parentNode = pJmlNode;
			this.jml = x;
		}
		else x = this.jml;
		
		this.inherit(jpf.JmlDomAPI); /** @inherits jpf.JmlDomAPI */
		this.oInt = this.oExt = this.jml.parentNode.lastChild == this.jml.parentNode.firstChild ? pHtmlNode : pHtmlNode.appendChild(document.createElement("div"));
		if(this.jml.getAttribute("cssclass")) this.oExt.className = this.jml.getAttribute("cssclass");
			
		if(id) this.oExt.setAttribute("id", id);
			
		this.drawed = true;
		this.dispatchEvent("ondraw");
		
		var l = jpf.layoutServer.get(pHtmlNode, (x.getAttribute("margin") || "").split(/,\s*/));
		this.aData = jpf.layoutServer.parseXml(x, l, null, true);
		
		this.oInt = jpf.JMLParser.parseChildren(x, pHtmlNode, this);
		
		if(!this.parentNode) return;
		
		if(!this.parentNode.tagName || !this.parentNode.tagName.match(/^(?:vbox|hbox)$/)){
			l.root = this.aData;
			
			if(this.aData.children.length)
				jpf.layoutServer.compile(pHtmlNode);
			//if(jpf.JMLParser.loaded) 
			//jpf.layoutServer.activateRules(pHtmlNode);
		}
		else{
			this.aData.stackId = this.parentNode.aData.children.push(this.aData) - 1;
			this.aData.parent = this.parentNode.aData;
		}
	}
}

/*FILEHEAD(/in/Components/HtmlWrapper.js)SIZE(2095)TIME(1213483123975)*/

/**
 * @private
 * @constructor
 */
jpf.HtmlWrapper = function(pHtmlNode, htmlNode, namespace){
	this.uniqueId = jpf.all.push(this) - 1;
	this.inherit = jpf.inherit;
	this.oExt = htmlNode;
	this.pHtmlDoc = document;
	this.pHtmlNode = pHtmlNode;
	
	this.inherit(jpf.Anchoring); /** @inherits jpf.Anchoring */
	
	this.inherit(jpf.Alignment); /** @inherits jpf.Alignment */
	
	var copy = htmlNode.cloneNode();
	this.enableAlignment = function(purge){
		var l = jpf.layoutServer.get(this.pHtmlNode); // , (x.parentNode.getAttribute("margin") || "").split(/,\s*/)might be optimized by splitting only once

		if(!this.aData){
			if(x.getAttribute(namespace + ":align")) x.setAttribute("align", x.getAttribute(namespace + ":align"));
			if(x.getAttribute(namespace + ":lean")) x.setAttribute("lean", x.getAttribute(namespace + ":lean"));
			if(x.getAttribute(namespace + ":edge")) x.setAttribute("edge", x.getAttribute(namespace + ":edge"));
			if(x.getAttribute(namespace + ":weight")) x.setAttribute("weight", x.getAttribute(namespace + ":weight"));
			if(x.getAttribute(namespace + ":splitter")) x.setAttribute("splitter", x.getAttribute(namespace + ":splitter"));
			if(x.getAttribute(namespace + ":width")) x.setAttribute("width", x.getAttribute(namespace + ":width")); 
			if(x.getAttribute(namespace + ":height")) x.setAttribute("height", x.getAttribute(namespace + ":height")); 
			if(x.getAttribute(namespace + ":min-width")) x.setAttribute("min-width", x.getAttribute(namespace + ":min-width"));
			if(x.getAttribute(namespace + ":min-height")) x.setAttribute("min-height", x.getAttribute(namespace + ":min-height"));
			
			this.aData = jpf.layoutServer.parseXml(x, l, this);
			this.aData.stackId = this.parentNode.aData.children.push(this.aData) - 1;
			this.aData.parent = this.parentNode;
		}
		else{
			//put aData back here
		}
		
		if(purge) this.purgeAlignment();
	}
}

/*FILEHEAD(/in/Components/Insert.js)SIZE(3003)TIME(1203730484247)*/

/**
 * Databound component displaying it's textual content directly in the 
 * position it's placed without drawing any containing elements.
 *
 * @classDescription		This class creates a new insert
 * @return {Insert} Returns a new insert
 * @type {Insert}
 * @constructor
 * @alias jpf.output
 * @addnode components:output
 * @addnode components:insert
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.9
 */
jpf.output = 
jpf.insert = function(pHtmlNode, tagName){
	jpf.register(this, tagName || "insert", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	/* ***********************
	  		Inheritance
	************************/
	
	this.editableParts = {"Main" : [["caption","text()"]]};
	this.inherit(jpf.DataBinding); /** @inherits jpf.DataBinding */
	
	/* ********************************************************************
										PROPERTIES
	*********************************************************************/
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/
	
	this.getValue = function(){
		return this.value;
	}
	
	this.setValue = function(value){
		this.value = value;
		//pHtmlNode.innerHTML = value;
		this.oTxt.nodeValue = value;
	}
	
	this.__supportedProperties = ["value"];
	this.__handlePropSet = function(prop, value){
		switch(prop){
			case "value":
				this.oTxt.nodeValue = value;
			break;
		}
	}
	
	/* ***************
		DATABINDING
	****************/
	this.mainBind = "caption";
	
	this.__xmlUpdate = function(action, xmlNode, listenNode, UndoObj){
		//Action Tracker Support
		if(UndoObj) UndoObj.xmlNode = this.XMLRoot;
		
		//Refresh Properties
		this.setValue(this.applyRuleSetOnNode("caption", this.XMLRoot) || "");
	}
	
	this.__load = function(node){
		/*
			absolutely weird behaviour when bind="" is set. 
			This function is loaded twice. First with some xml, 
			dunno why it's selected or called
		*/
		
		//Add listener to XMLRoot Node
		jpf.XMLDatabase.addNodeListener(node, this);
	
		var value = this.applyRuleSetOnNode("caption", node);
		this.setValue(value || typeof value == "string" ? value : "");
	}
	
	/* *********
		INIT
	**********/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.draw = function(){
		//Build Main Skin
		this.oInt = this.oExt = pHtmlNode;
		this.oTxt = document.createTextNode("");
		pHtmlNode.appendChild(this.oTxt);
	}
	
	
	this.__loadJML = function(x){
		if(x.firstChild){
			if(x.childNodes.length > 1 || x.firstChild.nodeType == 1){
				this.setValue("");
				jpf.JMLParser.parseChildren(x, this.oExt, this);
			}
			else this.setValue(x.firstChild.nodeValue);
		}
		
		//this.__makeEditable("Main", this.oExt, this.jml);
	}
}

/*FILEHEAD(/in/Components/Jslt.js)SIZE(3261)TIME(1203730484247)*/

/**
 * Component displaying the contents of a JSLT transformation on
 * the bound dataset. This component can create a containing element
 * when none is provided.
 *
 * @classDescription		This class creates a new jslt renderer
 * @return {Jslt} Returns a new jslt renderer
 * @type {Jslt}
 * @constructor
 * @allowchild [cdata]
 * @addnode components:jslt
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.9
 */
jpf.jslt = function(pHtmlNode){
	jpf.register(this, "jslt", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;

	/* ***********************
	  		Inheritance
	************************/
	
	this.inherit(jpf.DataBinding); /** @inherits jpf.DataBinding */
	
	/* ********************************************************************
										PROPERTIES
	*********************************************************************/
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/
	
	
	/* ***************
		DATABINDING
	****************/
	this.mainBind = "contents";
	
	/* *********
		INIT
	**********/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.parse = function(code){
		this.setProperty("value", code);
	}

	this.__clear = function(a,b){
		//BUG: WTF? clear gets called before load AND if there is nothing to load but with different args
		//IF YOU CLEAR HERE A REDRAW WITH THE SAME CONTENT WILL FAIL 
		if(b==true){
			this.oInt.innerHTML = "";//alert(a+"-"+b);
			// WHY . if i dont do this the setProperty loses its update. 
			this.setProperty("value","");
		}
		//alert(this.uniqueId);
		//this.oInt.innerHTML = "";
	}
	
	this.__supportedProperties = ["value"];
	this.__handlePropSet = function(prop, code){
		switch(prop){
			case "value":
				if(this.createJml){
					if(typeof code == "string") code = jpf.XMLDatabase.getXml(code);
					// To really make it dynamic, the objects created should be 
					// deconstructed and the xml should be attached and detached
					// of the this.jml xml. 
					jpf.JMLParser.parseChildren(code, this.oInt, this);
					if(jpf.JMLParser.inited) jpf.JMLParser.parseLastPass();
				}
				else{
					this.oInt.innerHTML = code;
				}
			break;
		}
	}
	
	this.draw = function(){
		//Build Main Skin
		//alert("REDRAW");
		this.oInt = this.oExt = this.jml.parentNode.lastChild == this.jml.parentNode.firstChild ? pHtmlNode : pHtmlNode.appendChild(document.createElement("div"));
		if(this.jml.getAttribute("cssclass")) this.oExt.className = this.jml.getAttribute("cssclass");
	}
	
	this.__loadJML = function(x){
		this.createJml = jpf.isTrue(x.getAttribute("jml"));

		if(x.firstChild){
			var bind = x.getAttribute("ref") || "."; x.removeAttribute("ref");
			var strBind = "<smartbinding><bindings><contents select='" + bind + "'><![CDATA[" + x.firstChild.nodeValue + "]]></contents></bindings></smartbinding>";
			jpf.JMLParser.addToSbStack(this.uniqueId, new jpf.SmartBinding(null, jpf.XMLDatabase.getXml(strBind)));
		}
	}
}

/*FILEHEAD(/in/Components/Label.js)SIZE(3627)TIME(1203784122302)*/

/**
 * Component displaying rectangle containing text usually specifying 
 * a description of another component or user interface element.
 * Optionally when clicked it can set the focus on another JML component.
 *
 * @classDescription		This class creates a new label
 * @return {Label} Returns a new label
 * @type {Label}
 * @constructor
 * @allowchild {smartbinding}
 * @addnode components:label
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.9
 */
jpf.label = function(pHtmlNode){
	jpf.register(this, "label", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	this.editableParts = {"Main" : [["caption","text()"]]};
	
	this.setValue = function(value){
		this.value = value;
		this.oInt.innerHTML = value;
	}
	
	this.__supportedProperties = ["value"];
	this.__handlePropSet = function(prop, value){
		switch(prop){
			case "value":
				this.oInt.innerHTML = value;
			break;
		}
	}
	
	var forJmlNode;
	this.setFor = function(jmlNode){
		forJmlNode = jmlNode;
	}
	
	/* ***************
		DATABINDING
	****************/

	/* *********
		INIT
	**********/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.draw = function(){
		//Build Main Skin
		this.oExt = this.__getExternal(); 
		this.oInt = this.__getLayoutNode("Main", "caption", this.oExt);
		if(this.oInt.nodeType != 1) this.oInt = this.oInt.parentNode;
		
		this.oExt.onmousedown = function(){
			if(this.host.formEl && this.host.formEl.nodeType == GUI_NODE){
				//this.host.formEl.focus();
				jpf.window.__focus(this.host.formEl);
			}
		}
		
		if(!this.jml.getAttribute("height") && this.parentNode && this.parentNode.jml && this.parentNode.jml.getAttribute("grid"))
			this.jml.setAttribute("autosize", "true")
	}
	
	this.setFormEl = function(formEl){
		this.formEl = formEl;
	}
	
	this.__loadJML = function(x){
		if(x.firstChild){
			if(x.childNodes.length > 1 || x.firstChild.nodeType == 1){
				this.setValue("");
				jpf.JMLParser.parseChildren(x, this.oExt, this);
			}
			else this.setValue(x.firstChild.nodeValue);
		}
		
			this.__makeEditable("Main", this.oExt, this.jml);
		
		
		//Set Form
		var y = x;
		do{
			y = y.parentNode;
		}while(y.tagName && !y.tagName.match(/submitform|xforms$/) && y.parentNode && y.parentNode.nodeType != 9);
		
		if(y.tagName && y.tagName.match(/submitform|xforms$/)){
			if(!y.tagName.match(/submitform|xforms$/)) throw new Error(1004, jpf.formErrorString(1004, this, "Textbox", "Could not find Form element whilst trying to bind to it's Data."));
			if(!y.getAttribute("id")) throw new Error(1005, jpf.formErrorString(1005, this, "Textbox", "Found Form element but the id attribute is empty or missing."));
			
			this.form = eval(y.getAttribute("id"));
		}
		
		//Please make this working without the submitform
		//if(x.getAttribute("for") && this.form) this.form.addConnectQueue(this, this.setFormEl, x.getAttribute("for"));
		
	}
	
	this.inherit(jpf.BaseSimple); /** @inherits jpf.BaseSimple */
	
	this.___focus = this.__focus;
	this.__focus = function(){
		if(forJmlNode) forJmlNode.focus();
		this.__focus();
	}
}

/*FILEHEAD(/in/Components/Layoutbuilder.js)SIZE(13658)TIME(1213483123975)*/

/**
 * @private
 * @constructor
 */
jpf.layoutbuilder = function(pHtmlNode){
	jpf.register(this, "layoutbuilder", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	/* ********************************************************************
										PROPERTIES
	*********************************************************************/

	//Options
	this.focussable = true; // This object can get the focus
	this.multiselect = false; // Initially Disable MultiSelect
	this.structs = {};
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/

	/* ********************************************************************
										PRIVATE METHODS
	*********************************************************************/

	/* ***********************
				Skin
	************************/

	this.__deInitNode = function(xmlNode, htmlNode){
		if(!htmlNode) return;

		htmlNode.parentNode.removeChild(htmlNode);
	}
	
	this.checkPosition = function(m){
		
	}
	
	this.isValid = function(){
		for(var i=0;i<this.oInt.childNodes.length;i++){
			this.layout.align(this.oInt.childNodes[i], this.structs[this.oInt.childNodes[i].getAttribute("id")]);
		}
		
		//can be optimized
		var result = this.layout.check(true);
		this.layout.reset();
		
		return result;
	}
	
	this.alignElement = function(xmlNode, htmlNode, purge){
		var aData = {};
		if(xmlNode.getAttribute("align")) aData.template = xmlNode.getAttribute("align");
		if(xmlNode.getAttribute("align-lean")) aData.isBottom = xmlNode.getAttribute("align-lean").match(/bottom/);
		if(xmlNode.getAttribute("align-lean")) aData.isRight = xmlNode.getAttribute("align-lean").match(/right/);
		if(xmlNode.getAttribute("align-position")){
			xmlNode.getAttribute("align-position").match(/\((\d+),(\d+)\)/);
			aData.vpos = parseInt(RegExp.$1);
			aData.hpos = parseInt(RegExp.$2);
			aData.template = undefined;
		}
		
		if(xmlNode.getAttribute("align-margin")) aData.edgeMargin = xmlNode.getAttribute("align-margin");
		if(xmlNode.getAttribute("align-span")) aData.span = parseInt(xmlNode.getAttribute("align-span"));
		if(xmlNode.getAttribute("align-splitter") || xmlNode.getAttribute("align-edge") == "splitter") aData.splitter = xmlNode.getAttribute("align-splitter") || (xmlNode.getAttribute("align-edge") == "splitter" ? 3 : false);
		if(xmlNode.getAttribute("width")) aData.fwidth = xmlNode.getAttribute("width");
		if(xmlNode.getAttribute("height")) aData.fheight = xmlNode.getAttribute("height");
		if(xmlNode.getAttribute("minwidth")) aData.minwidth = xmlNode.getAttribute("minwidth");
		if(xmlNode.getAttribute("minheight")) aData.minheight = xmlNode.getAttribute("minheight");

		/*var id = htmlNode.getAttribute("id");
		if(this.structs[id]) this.layout.remove(this.structs[id]);*/
		
		//var struct = this.layout.align(htmlNode, aData);
		this.structs[xmlNode.getAttribute(jpf.XMLDatabase.xmlIdTag)] = aData;
		
		this.sort();
		
		if(false && !this.isValid() && !this.isInError){
			this.isInError = true;
			return this.__setStyleClass(htmlNode, "error");
		}
		
		if(purge) this.purge();
	}
	
	this.seq = {"top":0, "left":1, "middle":2, "right":3, "bottom":4};
	this.getPrevSibl = function(node){if(!node) return; return !node.previousSibling || node.previousSibling.nodeType == 1 ? node.previousSibling : node.previousSibling.previousSibling}
	this.getNextSibl = function(node){if(!node) return; return !node.nextSibling || node.nextSibling.nodeType == 1 ? node.nextSibling : node.nextSibling.nextSibling}
	this.sort = function(){
		var node = this.XMLRoot.childNodes[0], prevSib = this.getPrevSibl(node);
		do{
			while(prevSib && prevSib.nodeType == 1 && node.nodeType == 1 && this.seq[node.getAttribute("align")] < this.seq[prevSib.getAttribute("align")]){
				node.parentNode.insertBefore(node, prevSib);
				prevSib = this.getPrevSibl(node);
			}
			node = this.getNextSibl(node);
			prevSib = this.getPrevSibl(node);
		}while(node);
	}
	
	this.purge = function(){
		//if(!this.isValid()) return;
		this.isInError = false;
		
		/*this.layout = new jpf.Layout(this.oExt);
		var pMargin = this.XMLRoot.getAttribute("margin");
		if(pMargin) this.layout.setMargin(pMargin.split(/,\s* /));*/
		
		//Replace below with sorting of the jpf.layoutServer
		var nodes = this.XMLRoot.childNodes;//this.oInt.childNodes;//
		for(var i=0;i<nodes.length;i++){
			if(nodes[i].nodeType != 1) continue;
			//this.layout.align(jpf.XMLDatabase.findHTMLNode(nodes[i], this), this.structs[nodes[i].getAttribute("id")]);
			this.layout.align(jpf.XMLDatabase.findHTMLNode(nodes[i], this), this.structs[nodes[i].getAttribute(jpf.XMLDatabase.xmlIdTag)]);
			//this.__setStyleClass(this.oInt.childNodes[i], "", ["error"]);
		}
		
		var cResult = this.layout.compile();
		this.layout.reset();
		if(cResult){
			this.__setStyleClass(this.oExt, this.baseCSSname + "Error");
			alert(cResult);
		}
		else this.__setStyleClass(this.oExt, "", [this.baseCSSname + "Error"]);
	}
	
	this.__updateNode = function(xmlNode, htmlNode){
		var elCaption = this.__getLayoutNode("Item", "caption", htmlNode);
		if(elCaption)
			this.__getLayoutNode("Item", "caption", htmlNode).parentNode.innerHTML = this.applyRuleSetOnNode("caption", xmlNode);

		this.alignElement(xmlNode, htmlNode);
	}
	
	this.__moveNode = function(xmlNode, htmlNode){
		if(!htmlNode) return;
		var oPHtmlNode = htmlNode.parentNode;
		var beforeNode = xmlNode.nextSibling ? jpf.XMLDatabase.findHTMLNode(this.getNextTraverse(xmlNode), this) : null;

		oPHtmlNode.insertBefore(htmlNode, beforeNode);
		
		this.alignElement(xmlNode, htmlNode);
	}
	
	this.addEventListener("onxmlupdate", function(e){
		if(e.action == "remove") return;
		this.purge();
	});
	
	/* ***********************
		Keyboard Support
	************************/
	
	this.__keyHandler = function(key, ctrlKey, shiftKey, altKey, e){
		if(!this.selected) return;

		switch(key){
			case 13:
				this.choose(this.selected);
			break;
			case 32:
				this.select(this.indicator, true);
			break;
			case 46:
			//DELETE
				var ln = this.getSelectCount();
				var xmlNode = ln == 1 ? this.value : null;
				this.remove(xmlNode);
			break;
			case 37:
			//LEFT
				var margin = jpf.compat.getBox(jpf.getStyle(this.selected, "margin"));
			
				if(!this.value) return;
				var node = this.getNextTraverseSelected(this.indicator || this.value, false);
				if(node){
					if(ctrlKey) this.setIndicator(node);
					else this.select(node, null, shiftKey);
				}
				
				if(this.selected.offsetTop < this.oExt.scrollTop)
					this.oExt.scrollTop = this.selected.offsetTop - margin[0];
			break;
			case 38:
			//UP
				var margin = jpf.compat.getBox(jpf.getStyle(this.selected, "margin"));
				
				if(!this.value && !this.indicator) return;
				var hasScroll = this.oExt.scrollHeight > this.oExt.offsetHeight;
				var items = Math.floor((this.oExt.offsetWidth - (hasScroll ? 15 : 0)) / (this.selected.offsetWidth+margin[1]+margin[3]));
				var node = this.getNextTraverseSelected(this.indicator || this.value, false, items);
				if(node){
					if(ctrlKey) this.setIndicator(node);
					else this.select(node, null, shiftKey);
				}
				
				if(this.selected.offsetTop < this.oExt.scrollTop)
					this.oExt.scrollTop = this.selected.offsetTop - margin[0];
			break;
			case 39:
			//RIGHT
				var margin = jpf.compat.getBox(jpf.getStyle(this.selected, "margin"));
				
				if(!this.value) return;
				var node = this.getNextTraverseSelected(this.indicator || this.value, true);
				if(node){
					if(ctrlKey) this.setIndicator(node);
					else this.select(node, null, shiftKey);
				}
				
				if(this.selected.offsetTop + this.selected.offsetHeight > this.oExt.scrollTop + this.oExt.offsetHeight)
					this.oExt.scrollTop = this.selected.offsetTop - this.oExt.offsetHeight + this.selected.offsetHeight + margin[0];
					
			break;
			case 40:
			//DOWN
				var margin = jpf.compat.getBox(jpf.getStyle(this.selected, "margin"));
				
				if(!this.value && !this.indicator) return;
				var hasScroll = this.oExt.scrollHeight > this.oExt.offsetHeight;
				var items = Math.floor((this.oExt.offsetWidth - (hasScroll ? 15 : 0)) / (this.selected.offsetWidth+margin[1]+margin[3]));
				var node = this.getNextTraverseSelected(this.indicator || this.value, true, items);
				if(node){
					if(ctrlKey) this.setIndicator(node);
					else this.select(node, null, shiftKey);
				}
				
				if(this.selected.offsetTop + this.selected.offsetHeight > this.oExt.scrollTop + this.oExt.offsetHeight)
					this.oExt.scrollTop = this.selected.offsetTop - this.oExt.offsetHeight + this.selected.offsetHeight + 10;
				
			break;
			case 65:
				if(ctrlKey){
					this.selectAll();	
					return false;
				}
			break;
			default: 
			return;
		}
		
		return false;
	}
	
	/* ***********************
			DATABINDING
	************************/
	
	this.nodes = [];
	
	this.__add = function(xmlNode, Lid, xmlParentNode, htmlParentNode, beforeNode){
		//Build Item
		this.__getNewContext("Item");
		var Item = this.__getLayoutNode("Item");
		var elSelect = this.__getLayoutNode("Item", "select");
		var elCaption = this.__getLayoutNode("Item", "caption");
		
		Item.setAttribute("id", Lid);
		
		//elSelect.setAttribute("oncontextmenu", 'jpf.lookup(' + this.uniqueId + ').dispatchEvent("oncontextmenu", event);');
		elSelect.setAttribute("ondblclick", 'jpf.lookup(' + this.uniqueId + ').choose()');
		elSelect.setAttribute("onmousedown", 'jpf.lookup(' + this.uniqueId + ').select(this, event.ctrlKey, event.shiftKey)'); 
		elSelect.setAttribute("onmouseover", 'jpf.lookup(' + this.uniqueId + ').__setStyleClass(this, "hover");'); 
		elSelect.setAttribute("onmouseout", 'jpf.lookup(' + this.uniqueId + ').__setStyleClass(this, "", ["hover"]);'); 
		
		if(elCaption) elCaption.nodeValue = this.applyRuleSetOnNode("caption", xmlNode);

		if(htmlParentNode){
			jpf.XMLDatabase.htmlImport(Item, htmlParentNode, beforeNode);
			this.alignElement(xmlNode, Item);
		}
		else{
			this.nodes.push(Item);
			this.alignElement(xmlNode, Item);
		}
	}
	
	this.__fill = function(){
		jpf.XMLDatabase.htmlImport(this.nodes, this.oInt);
		
		var pMargin = this.XMLRoot.getAttribute("margin");
		if(pMargin) this.layout.setMargin(pMargin.split(/,\s*/));

		this.sort();
		this.purge();
		
		this.nodes.length = 0;
	}
	
	/* ***********************
				SELECT
	************************/
	
	this.__calcSelectRange = function(xmlStartNode, xmlEndNode){
		var r = [], loopNode = xmlStartNode;
		while(loopNode && loopNode != xmlEndNode.nextSibling){
			r.push(loopNode);
			loopNode = loopNode.nextSibling;
		}

		if(r[r.length-1] != xmlEndNode){
			var r = [], loopNode = xmlStartNode;
			while(loopNode && loopNode != xmlEndNode.previousSibling){
				r.push(loopNode);
				loopNode = loopNode.previousSibling;
			};
		}
		
		return r;
	}
	
	this.__selectDefault = function(XMLRoot){
		this.select(XMLRoot.selectSingleNode(this.ruleTraverse));
	}

	this.inherit(jpf.MultiSelect); /** @inherits jpf.MultiSelect */
	
	/* ***********************
			  CACHING
	************************/
	
	this.__getCurrentFragment = function(){
		//if(!this.value) return false;

		var fragment = jpf.hasDocumentFragment ? document.createDocumentFragment() : new DocumentFragment(); //IE55
		while(this.oInt.childNodes.length){
			fragment.appendChild(this.oInt.childNodes[0]);
		}

		return fragment;
	}
	
	this.__setCurrentFragment = function(fragment){
		jpf.hasDocumentFragment ? this.oExt.appendChild(fragment) : fragment.reinsert(this.oExt); //IE55
		
		//Select First Node....
		if(!jpf.window.isFocussed(this)) this.blur();
	}

	this.__findNode = function(cacheNode, id){
		if(!cacheNode) return document.getElementById(id);
		return cacheNode.getElementById(id);
	}
	
	this.__setClearMessage = function(msg){
		var oEmpty = jpf.XMLDatabase.htmlImport(this.__getLayoutNode("Empty"), this.oInt);
		var empty = this.__getLayoutNode("Empty", "caption", oEmpty);
		if(empty) jpf.XMLDatabase.setNodeValue(empty, msg || "");
		if(oEmpty) oEmpty.setAttribute("id", "empty" + this.uniqueId);
	}
	
	this.__removeClearMessage = function(){
		var oEmpty = document.getElementById("empty" + this.uniqueId);
		if(oEmpty) oEmpty.parentNode.removeChild(oEmpty);
		else this.oInt.innerHTML = ""; //clear if no empty message is supported
	}
	
	this.inherit(jpf.Cache); /** @inherits jpf.Cache */
	this.caching = false;

	/* ***********************
	  Other Inheritance
	************************/
	
	this.inherit(jpf.Presentation); /** @inherits jpf.Presentation */
	this.inherit(jpf.DataBinding); /** @inherits jpf.DataBinding */
	
	this.keyHandler = this.__keyHandler;

	/* *********
		INIT
	**********/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.draw = function(){
		//Build Main Skin
		this.oExt = this.__getExternal(); 
		this.oInt = this.__getLayoutNode("Main", "container", this.oExt);
		
		this.layout = new jpf.Layout(this.oExt);
	}
	
	this.__loadJML = function(x){
	}
}
/*FILEHEAD(/in/Components/Lineselect.js)SIZE(3529)TIME(1203730484247)*/

/*FILEHEAD(/in/Components/List.js)SIZE(6870)TIME(1203730484247)*/

/**
 * Component displaying a skinnable list of options which can be selected. 
 * Selection of multiple items can be allowed. Items can be renamed
 * individually and deleted individually or in groups.
 *
 * @classDescription		This class creates a new list
 * @return {List} Returns a new list
 * @type {List}
 * @constructor
 * @allowchild item,{smartbinding}
 * @addnode components:list, components:select, components:select1
 * @alias select
 * @alias select1
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.4
 */
jpf.select = 
jpf.select1 = 
jpf.list = function(pHtmlNode, tagName, jmlNode){
	jpf.register(this, tagName || "list", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	/* ***********************
			  RENAME
	************************/
	
	this.__getCaptionElement = function(){
		var x = this.__getLayoutNode("Item", "caption", this.selected);
		if(!x) return;
		return x.nodeType == 1 ? x : x.parentNode;
	}
	
	this.addEventListener("onafterselect",function(e){
		if(this.hasFeature(__VALIDATION__)) this.validate();
	});
	
	/* ***********************
	  Other Inheritance
	************************/
	this.inherit(jpf.BaseList); /** @inherits jpf.BaseList */
	
	this.keyHandler = this.__keyHandler;
	
	this.inherit(jpf.Rename); /** @inherits jpf.Rename */
	
	/* ***********************
			DRAGDROP
	************************/
	
	this.__showDragIndicator = function(sel, e){
		var x = e.offsetX;
		var y = e.offsetY;

		this.oDrag.startX = x;
		this.oDrag.startY = y;

		
		document.body.appendChild(this.oDrag);
		//this.oDrag.getElementsByTagName("DIV")[0].innerHTML = this.selected.innerHTML;
		//this.oDrag.getElementsByTagName("IMG")[0].src = this.selected.parentNode.parentNode.childNodes[1].firstChild.src;
		this.__updateNode(this.value, this.oDrag);
		
		return this.oDrag;
	}
	
	this.__hideDragIndicator = function(){
		this.oDrag.style.display = "none";
	}
	
	this.__moveDragIndicator = function(e){
		this.oDrag.style.left = (e.clientX - this.oDrag.startX) + "px";
		this.oDrag.style.top = (e.clientY - this.oDrag.startY) + "px";
	}
	
	this.__initDragDrop = function(){
		if(!this.__hasLayoutNode("DragIndicator")) return;
		this.oDrag = jpf.XMLDatabase.htmlImport(this.__getLayoutNode("DragIndicator"), document.body);
		
		this.oDrag.style.zIndex = 1000000;
		this.oDrag.style.position = "absolute";
		this.oDrag.style.cursor = "default";
		this.oDrag.style.display = "none";
	}
	
	this.__dragout = 
	this.__dragover = 
	this.__dragdrop = function(){}
	
	this.inherit(jpf.DragDrop); /** @inherits jpf.DragDrop */
	
	/* *********
		INIT
	**********/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.draw = function(){
		this.appearance = this.jml.getAttribute("appearance") || "compact";
		
		if(this.tagName == "select" && (this.appearance == "full" || this.appearance == "minimal")){
			this.mode = "check";
			if(!this.jml.getAttribute("skin")) this.loadSkin("default:CheckList");
		}
		else if(this.tagName == "select1" && this.appearance == "full"){
			this.mode = "radio";
			if(!this.jml.getAttribute("skin")) this.loadSkin("default:RadioList");
		}
		else if(this.tagName == "select1" && this.appearance == "compact") this.multiselect = false;
		
		//Build Main Skin
		this.oExt = this.__getExternal(); 
		this.oInt = this.__getLayoutNode("Main", "container", this.oExt);

		this.oExt.onmousedown = function(e){
			if(!e) e = event;
			if(e.ctrlKey || e.shiftKey) return;
			
			var srcElement = jpf.hasEventSrcElement ? e.srcElement : e.target;
			//debugger;
			if(this.host.allowDeselect && (srcElement == this || srcElement.getAttribute(jpf.XMLDatabase.htmlIdTag)))
				this.host.clearSelection(); //hacky
		}
		
		this.oExt.onclick = function(e){
			this.host.dispatchEvent("onclick", {htmlEvent : e || event});
		}

		//Get Options form skin
		this.listtype = parseInt(this.__getOption("Main", "type")) || 1; //Types: 1=One dimensional List, 2=Two dimensional List
		this.behaviour = parseInt(this.__getOption("Main", "behaviour")) || 1; //Types: 1=Check on click, 2=Check independent
		
		//Support for check mode
		this.mode = this.mode || this.jml.getAttribute("mode") || "normal";
		if(this.mode == "check" || this.mode == "radio"){
			this.allowDeselect = false;
			this.ctrlSelect = true;
			
			this.addEventListener("onafterrename", function(){
				var sb = this.getSelectionSmartBinding();
				if(!sb) return;
				
				//Make sure that the old value is removed and the new one is entered
				sb.__updateSelection();
				//this.reselect(this.value);
			});
			
			if(this.mode == "check") this.autoselect = false;
			if(this.mode == "radio") this.multiselect = false;
		}
		
		//Support for more mode - Rename is required
		this.more = this.jml.getAttribute("more") ? true : false;
		if(this.more){
			this.delayedSelect = false;
						
			this.addEventListener("onxmlupdate", function(e){
				if("insert|add|synchronize|move".indexOf(e.action) > -1)
					this.oInt.appendChild(this.moreItem);
			});
			
			this.addEventListener("onafterrename", function(){
				var caption = this.applyRuleSetOnNode("caption", this.indicator)
				var xmlNode = this.findXmlNodeByValue(caption);
				
				var curNode = this.indicator;
				if(xmlNode != curNode || !caption){
					if(xmlNode && !this.isSelected(xmlNode)) this.select(xmlNode);
					this.remove(curNode);
				}
				else if(!this.isSelected(curNode)) this.select(curNode);
			});
			
			this.addEventListener("onbeforeselect", function(){
				//This is a hack
				if(arguments[0] && this.isSelected(arguments[0]) && arguments[0].getAttribute('custom') == '1'){
					this.setIndicator(arguments[0]);
					this.value = arguments[0];
					var j = this;
					setTimeout(function(){j.startRename()});
					return false;
				}
			});
		}
	}
	
	this.__loadJML = function(x){
		if(this.jml.childNodes.length) this.loadInlineData(this.jml);
		
		if(this.hasFeature(__MULTIBINDING__) && x.getAttribute("value")) this.setValue(x.getAttribute("value"));
		
		// this.doOptimize(true);
		
		if(x.getAttribute("multibinding") == "true" && !x.getAttribute("ref")) 
			this.inherit(jpf.MultiLevelBinding); /** @inherits jpf.MultiLevelBinding */
	}
	
	this.__destroy = function(){
		this.oExt.onclick = null;
		jpf.removeNode(this.oDrag);
		this.oDrag = null;
	}
}
/*FILEHEAD(/in/Components/mediaflow/MFBrowser.js)SIZE(3512)TIME(1203730484247)*/

/**
 * @constructor
 */
jpf.MFBrowser = function(pHtmlNode){
	jpf.register(this, "MFBrowser", MF_NODE);
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	/* ********************************************************************
										PROPERTIES
	*********************************************************************/
	
	//Options
	//this.focussable = true; // This object can get the focus
	this.inherit(jpf.Validation); /** @inherits jpf.Validation */
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/
	
	this.loadURL = function(src){
		this.oInt.global.location.href = src;
	}
	
	this.getURL = function(){
		return this.oInt.global.location.href
	}
	
	this.back = function(){
		this.oInt.global.history.back();
	}
	
	this.forward = function(){
		this.oInt.global.history.forward();
	}
	
	this.reload = function(){
		this.oInt.global.location.reload()
	}
	
	this.print = function(){
		this.oInt.global.print();
	}
	
	this.runCode = function(str, no_error){
		if(no_error) try{this.oInt.contentWindow.eval(str);}catch(e){}
		else this.oInt.contentWindow.eval(str);
	}
	
	/* ***********************
	  Other Inheritance
	************************/
	this.inherit(jpf.DataBinding); /** @inherits jpf.DataBinding */
	
	/* ***************
		DATABINDING
	****************/
	this.mainBind = "Source";
	
	this.__xmlUpdate = function(action, xmlNode, listenNode, UndoObj){
		//Action Tracker Support
		if(UndoObj) UndoObj.xmlNode = this.XMLRoot;
		
		//Refresh Properties
		this.loadURL(this.applyRuleSetOnNode("Source", this.XMLRoot) || "about:blank");
	}
	
	this.__load = function(node){
		this.loadURL(this.applyRuleSetOnNode("Source", node));
	}
	
	
	/* *********
		INIT
	**********/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.draw = function(){
		var x = this.jml; 
		this.oExt = jdwin.CreateWidget( "window" );
		this.oExt.InitWindow( "child", x.getAttribute("url"), "", parseInt( x.getAttribute("left") ), parseInt( x.getAttribute("top") ),parseInt( x.getAttribute("width") ), parseInt( x.getAttribute("height") ));
		this.oExt.width = parseInt( x.getAttribute("width") );
		this.oExt.height= parseInt( x.getAttribute("height") );
		//this.oExt.top   = 40;//parseInt( x.getAttribute("top") );
		//this.oExt.left  = 0;//parseInt( x.getAttribute("left") );
		setTimeout('jpf.lookup(' + this.uniqueId + ').oExt.SetOrder("first");', 100);

		if(this.jml.getAttribute("size") == "true"){
			var myId = 'jpf.lookup(' + this.uniqueId + ')';
			LayoutServer.setRules(this.pHtmlNode, this.uniqueId + "h", myId + '.oExt.width = document.documentElement.offsetWidth - 4 - ' + this.jml.getAttribute("left"));
			LayoutServer.setRules(this.pHtmlNode, this.uniqueId + "v", myId + '.oExt.height = document.documentElement.offsetHeight - 4 - ' + this.jml.getAttribute("top"));
			//LayoutServer.activateRules(document.documentElement);
		}

		jdshell.Update();
		//this.oExt.Show();
		//this.oExt.SetOrder("first");
		
		this.oInt = logwin;
		
		//this.oInt = this.oExt.contentWindow.document.body;
		//this.oExt.host = this;
		//this.oInt.host = this;
	}
	
	this.__loadJML = function(x){
	}
}
/*FILEHEAD(/in/Components/mediaflow/MFButton.js)SIZE(3710)TIME(1203730484247)*/

/**
 * @constructor
 */
jpf.MFButton = function(pHtmlNode){
	jpf.register(this, "MFButton", MF_NODE);
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	/* ***********************
	  		Inheritance
	************************/
	this.inherit(jpf.DataBinding); /** @inherits jpf.DataBinding */
	
	/* ********************************************************************
										PROPERTIES
	*********************************************************************/
	
	//Options
	this.focussable = false; // This object can get the focus
	this.disabled = false; // Object is enabled
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/

	this.__enable = function(){
		this.disabled = false;
		this.oExt.disabled = false;
	}

	this.__disable = function(){
		this.disabled = true;
		this.oExt.disabled = true;
	}
	
	this.lock = function(){
		this.locked = false;
		this.oExt.locked = false;
	}

	this.unlock = function(){
		this.locked = false;
		this.oExt.locked = false;
	}
	
	this.setBool = function(){
		//this.SetMode(3);
	}
	
	this.setNormal = function(){
		//this.SetMode(0);
	}
		
	/*
		this.setCaption = function(value){
			this.oCaption.nodeValue = value;
		}
	
		this.setIcon = function(url){
			if(this.oIcon.tagName == "img") this.oIcon.setAttribute("src", this.iconPath + url);
			else this.oIcon.style.backgroundImage = "url(" + this.iconPath + url + ")";
		}
	*/
	
	/* ********************************************************************
										PRIVATE METHODS
	*********************************************************************/
	
	/* ***********************
				Focus
	************************/
	
	this.__focus = function(){
		
	}
	
	this.__blur = function(){
		
	}
	
	/* ***********************
		Keyboard Support
	************************/
	
	this.keyHandler = function(key, ctrlKey, shiftKey){
		
	}
	
	/* ***************
		Init
	****************/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.draw = function(){
		if(!this.oExt) this.oExt = jdwin.CreateWidget("button");
	}
	
	this.setCaption = function(caption){
		// state, fontname, size, weight, color, left, top, center
		
		this.oExt.caption = caption;
	}
	
	this.setColor = function(color){
		var clr = eval(color.replace(/#/, "0x"));
		this.oExt.SetFont(0,"Arial",11,1,clr,0,1,1);
		this.oExt.SetFont(1,"Arial",11,1,clr,0,1,1);
		this.oExt.SetFont(2,"Arial",11,1,clr,0,1,1);
	}
	
	this.__loadJML = function(x){
		if(!this.oExt) this.oExt = jdwin.CreateWidget("button");
		
		if(x.getAttribute("onclick")){
			this.onclick = x.getAttribute("onclick");
			if(typeof this.onclick == "string") this.onclick = new Function(this.onclick);
		}
		//jpf.isIE ?  : new Function(x.getAttribute("onclick"));
		
		this.bgswitch = x.getAttribute("bgswitch") ? true : false;
		if(this.bgswitch){
			this.bgoptions = x.getAttribute("bgoptions") ? x.getAttribute("bgoptions").split("\|") : ["vertical", 2];
			
			this.oExt.InitButton(0, 0, 0, this.bgoptions[1], this.mediaPath.replace(/jav\:\//, "") + x.getAttribute("bgswitch"), this.parentNode.offsetHeight ? 1 : 0);
			this.setCaption(x.firstChild ? x.firstChild.nodeValue : "");
			if(x.getAttribute("color")) this.setColor(x.getAttribute("color"));
		}
		
		this.disabled = x.getAttribute("disabled") || false;
		this.oExt.disabled = this.disabled;
		
		var jmlNode = this;
		this.oExt.onbuttonclick = function(){
			jmlNode.dispatchEvent("onclick");
		}
		
		this.__focus();
	}
	
	DeskRun.register(this);
}

/*FILEHEAD(/in/Components/mediaflow/MFCheckbox.js)SIZE(4796)TIME(1203730484247)*/

/**
 * @constructor
 */
jpf.MFCheckbox = function(pHtmlNode){
	jpf.register(this, "MFCheckbox", MF_NODE);
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	/* ***********************
	  		Inheritance
	************************/
	this.inherit(jpf.DataBinding); /** @inherits jpf.DataBinding */
	
	/* ********************************************************************
										PROPERTIES
	*********************************************************************/
	
	//Options
	this.focussable = false; // This object can get the focus
	this.disabled = false; // Object is enabled
	this.checked = false;
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/
	
	this.setValue = function(value){
		this.check_value = value;
	}
	
	this.getValue = function(){
		return this.checked ? this.check_value : null;
	}
	
	this.check = function(){
		this.oExt.clicked = true;
		this.checked = true;
	}
	
	this.uncheck = function(){
		this.oExt.clicked = false;
		this.checked = false;
	}
	
	this.setError = function(value){
	}
	
	this.clearError = function(value){
	}
	
	this.enable = function(){
		this.disabled = false;
		this.oExt.disabled = false;
	}
	
	this.disable = function(){
		this.disabled = true;
		this.oExt.disabled = true;
	}
	
	/* ***********************
				Actions
	************************/
	
	this.Change = function(value){
		var node = this.getNodeFromRule("Value", this.XMLRoot);
		if(!node){
			if(value == this.values[0]) this.check();
			else this.uncheck();
			
			return this.dispatchEvent("onchange");
		}

		var atAction = node.nodeType == 3 || node.nodeType == 4 ? "setTextNode" : "setAttribute";
		var args = node.nodeType == 3 || node.nodeType == 4 ? 
			[node.parentNode, value] : [node.selectSingleNode(".."), node.nodeName, value];

		//Use Action Tracker
		this.executeAction(atAction, args, "Change", this.XMLRoot);
	}
	
	/* ********************************************************************
										PRIVATE METHODS
	*********************************************************************/
	
	this.processClick = function(checked){
		this.Change(this.values[checked ? 0 : 1]);
	}
	
	/* ***********************
				Focus
	************************/
	
	this.__focus = function(){
		
	}
	
	this.__blur = function(){
		
	}
	
	/* ***********************
		Keyboard Support
	************************/
	
	this.keyHandler = function(key, ctrlKey, shiftKey){
		
	}
	
	/* ***********************
			DATABINDING
	************************/

	this.__xmlUpdate = function(action, xmlNode, listenNode, UndoObj){
		//Action Tracker Support
		if(UndoObj) UndoObj.xmlNode = this.XMLRoot;
		
		//Refresh Properties
		if(this.applyRuleSetOnNode("Value", this.XMLRoot) == this.values[0]) this.check();
		else this.uncheck();
	}
	
	this.__load = function(XMLRoot, id){
		//Add listener to XMLRoot Node
		XMLDatabase.addNodeListener(XMLRoot, this);
		
		if(this.applyRuleSetOnNode("Value", XMLRoot) == this.values[0]) this.check();
		else this.uncheck();
	}
	
	/* ***************
		Init
	****************/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.draw = function(){
		this.oExt = jdwin.CreateWidget("button");
	}
	
	this.__loadJML = function(x){
		this.name = x.getAttribute("id");
		this.value = x.getAttribute("value");
		if(x.getAttribute("checked") == "true") this.check();
		
		this.bgswitch = x.getAttribute("bgswitch") ? true : false;
		if(this.bgswitch){
			this.bgoptions = x.getAttribute("bgoptions") ? x.getAttribute("bgoptions").split("\|") : ["vertical", 2];

			this.oExt.InitButton(0, 0, 1, this.bgoptions[1], this.mediaPath.replace(/jav\:\//, "") + x.getAttribute("bgswitch"), this.parentNode.offsetHeight ? 1 : 0, "00110");
			// normal, mo, clicked, clickedover, disabled
		}
		
		this.disabled = x.getAttribute("disabled") || false;
		this.oExt.disabled = this.disabled;
	
		var jmlNode = this;
		this.oExt.onbuttonclick = function(e){
			jmlNode.processClick(e.clicked);
			jmlNode.dispatchEvent("onclick");
		}
		
		this.values = x.getAttribute("values") ? x.getAttribute("values").split("\|") : ["true","false"];
		
		//Set inline binding
		if(x.getAttribute("bind")){
			var sNode = jpf.getObject("XMLDOM", "<Type><DataBinding connect='" + (this.form ? y.getAttribute("id") : this.getInheritedConnectId(x)) + "' type='select'><Value select=\"" + x.getAttribute("bind").replace(/"/g, "\\\"") + "\"  /></DataBinding></Type>").documentElement;
			var dbnode = sNode.selectSingleNode("DataBinding");

			me.stackDB.push([this, sNode, dbnode]);
		}
		
		this.__focus();
	}
	
	DeskRun.register(this);
}

/*FILEHEAD(/in/Components/mediaflow/MFDisplay.js)SIZE(4528)TIME(1203730484247)*/

/**
 * @constructor
 */
jpf.MFDisplay = function(pHtmlNode){
	jpf.register(this, "MFDisplay", MF_NODE);
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;

	/* ***********************
	  		Inheritance
	************************/
	this.inherit(jpf.Presentation); /** @inherits jpf.Presentation */
	this.inherit(jpf.DataBinding); /** @inherits jpf.DataBinding */
	
	/* ********************************************************************
										PROPERTIES
	*********************************************************************/
	
	//Options
	this.focussable = true; // This object can get the focuse
	this.disabled = false; // Object is enabled
	this.inherit(jpf.Validation); /** @inherits jpf.Validation */
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/
	
	this.setValue = function(value){
		this.value = value;

		this.oGroup.SetFlowValue('value', parseFloat(value));
 		this.oExt.Redraw();
	}

	this.setNamedValue = function(name,value){
		this.oGroup.SetFlowValue(name, value);
 		this.oExt.Redraw();
	}
	
	this.getValue = function(){
		return this.value;
	}
	
	/* ***********************
				Actions
	************************/
	
	this.Change = function(value){
		var node = this.getNodeFromRule("Value", this.XMLRoot);
		if(!node){
			this.setValue(value);
			return;
		}

		if(!this.errBox && this.form) this.errBox = this.form.getErrorBox(this.name);
		if(this.errBox && this.errBox.isVisible() && this.isValid()){
			this.clearError();
			this.errBox.hide();
		}

		var atAction = node.nodeType == 1 || node.nodeType == 3 || node.nodeType == 4 ? "setTextNode" : "setAttribute";
		var args = node.nodeType == 1 ? [node, value] : (node.nodeType == 3 || node.nodeType == 4 ? [node.parentNode, value] : [node.selectSingleNode(".."), node.nodeName, value]);

		//Use Action Tracker
		this.executeAction(atAction, args, "Change", this.XMLRoot);
	}
	
	/* ***********************
		Keyboard Support
	************************/
	
	//Handler for a plane list
	this.keyHandler = function(key, ctrlKey, shiftKey, altKey){
		switch(key){
			case 37:
			//LEFT
			break;
			case 38:
			//UP
			break;
			case 39:
			//RIGHT
			break;
			case 40:
			//DOWN
			break;
			default: 
			return;
		}
		
		return false;
	}
	
	/* ***********************
			Databinding
	************************/
	
	this.__xmlUpdate = function(action, xmlNode, listenNode, UndoObj){
		//Action Tracker Support
		if(UndoObj) UndoObj.xmlNode = this.XMLRoot;
		
		//Refresh Properties
		//var value = this.applyRuleSetOnNode("Value", this.XMLRoot);
		//if(value != this.getValue()) this.setValue(value || "");
		
		var value = this.applyRuleSetOnNode("Value", this.XMLRoot);
		if((value || typeof value == "string")){
			if(value != this.getValue()) this.setValue(value);
		}
		else this.setValue("");
	}
	
	this.__load = function(XMLRoot, id){
		//Add listener to XMLRoot Node
		XMLDatabase.addNodeListener(XMLRoot, this);
		
		var value = (this.rules ? this.applyRuleSetOnNode("Value", XMLRoot) : (this.jml.firstChild ? this.jml.firstChild.nodeValue : false));
		if((value || typeof value == "string")){
			if(value != this.getValue()) this.setValue(value);
		}
		else this.setValue("");
	}
	
	/* ***********************
				INIT
	************************/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.changeSlider = function(value, userdata){
		this.Change(value);
	}
	
	this.draw = function(){
		this.oFlow = jdshell.CreateComponent("flow");
		this.oFlow.InitFlowRenderDevice("software",3);
		
		this.oExt = jdwin.CreateWidget("display");
		this.oGroup = this.oFlow.CreateFlowNode(this.__getLayoutNode("Main"), "dial");
		var x=this.jml;

		this.oExt.InitDisplay(	this.oFlow, 
														parseInt(x.getAttribute("left"))+2,
														parseInt(x.getAttribute("top"))+40+2,
														parseInt(x.getAttribute("width")),
														parseInt(x.getAttribute("height")), 
														"over", "", 100, 25 );
		this.oExt.flowdraw  = this.oGroup.GetFlowNode("final");
		this.oExt.flowmouse = this.oGroup.GetFlowNode("mouse");
		this.oExt.SetMaskImage(this.mediaPath.replace(/jav\:\//, "") + x.getAttribute("mask"));
	}
	
	this.__loadJML = function(x){
		if(x.getAttribute("value")) this.setValue(x.getAttribute("value"));
	}
	
	DeskRun.register(this);
}

/*FILEHEAD(/in/Components/mediaflow/MFDropdown.js)SIZE(10896)TIME(1203730484247)*/
/**
 * @constructor
 */
jpf.MFDropdown = function(pHtmlNode){
	jpf.register(this, "MFDropdown", MF_NODE);
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	/* ********************************************************************
										PROPERTIES
	*********************************************************************/

	this.animType = 1;
	this.animSteps = document.all ? 5 : 8;
	this.animSpeed = document.all ? 20 : 10;
	this.itemSelectEvent = "onmouseup";
	
	this.inherit(jpf.Validation); /** @inherits jpf.Validation */
	this.hasCheckbox = false;
	this.dragdrop = false;
	this.reselectable = true;
	this.focussable = true;

	/* ***********************
	  Other Inheritance
	************************/
	this.inherit(jpf.BaseList); /** @inherits jpf.BaseList */

	this.autoselect = false;
	this.multiselect = false;

	this.addEventListener("onafterselect", function(e){
		if(IS_IE) e = event;
		
		this.slideUp();
		//this.oExt.onmouseout(e);
		//this.oExt.onmouseout(e);
		this.oExt.caption = this.applyRuleSetOnNode("Caption", this.value);
		this.oExt.Redraw();
		//return selBindClass.applyRuleSetOnNode(selBindClass.mainBind, selBindClass.XMLRoot, null, true);
		
		this.__updateOtherBindings();
		
	});
	
	this.addEventListener("onafterdeselect", function(){
		//this.oLabel.nodeValue = "";
		this.oExt.caption = "";
		this.oExt.Redraw();
	});
	
	function setMaxCount(){
		if(!this.XMLRoot) return;
		this.setMaxItems(this.getTraverseNodes().length);
		if(this.isOpen == 2) this.slideDown();
	}
	this.addEventListener("onafterload", setMaxCount);
	this.addEventListener("onxmlupdate", setMaxCount);
	
	/*this.addEventListener("oninitselbind", function(bindclass){
		var jmlNode = this;
		bindclass.addEventListener("onxmlupdate", function(){
			debugger;
			jmlNode.__showSelection();
		});
	});*/
	
	//For MultiBinding
	this.__showSelection = function(value){
		//Set value in Label
		var bc = this.getSelectionBindClass();

		//Only display caption when a value is set
		if(value === undefined){
			var value = bc.applyRuleSetOnNode("Value", bc.XMLRoot, null, true);
			value = value ? bc.applyRuleSetOnNode("Caption", bc.XMLRoot, null, true) : "";
		}

		//this.oExt.caption = value || "";
		//this.oExt.Redraw();
	}
	
	//I might want to move this method to the MultiLevelBinding baseclass
	this.__updateOtherBindings = function(){
		if(!this.multiselect){
			// Set Caption bind
			var bc = this.getSelectionBindClass(), caption;
			if(bc && (caption = bc.bindingRules["Caption"])){
				var xmlNode = XMLDatabase.createNodeFromXpath(bc.XMLRoot, bc.bindingRules["Caption"][0].getAttribute("select"));
				if(!xmlNode) return;
	
				XMLDatabase.setNodeValue(xmlNode, this.applyRuleSetOnNode("Caption", this.value));
			}
		}
	}
	
	/* ***********************
	  Private functions
	************************/
	
	this.__blur = function(){
		this.slideUp();
		//this.oExt.dispatchEvent("onmouseout")
		//if(this.oExt.onmouseout) this.oExt.onmouseout();
		
		//this.__setStyleClass(this.oExt, "", [this.baseCSSname + "Focus"]);
	}
	
	this.keyHandler = function(key, ctrlKey, shiftKey, altKey){
		//this.__keyHandler(key, ctrlKey, shiftKey, altKey);
		if(!this.XMLRoot) return;
		
		switch(key){
			case 38:
			//UP
				if(!this.value && !this.indicator) return;
				var node = this.getNextTraverseSelected(this.indicator || this.value, false);
				if(node) this.select(node);
				
			break;
			case 40:
			//DOWN
				var node;
				
				if(!this.value && !this.indicator){
					node = this.getFirstTraverseNode();
					if(!node) return;
				}
				else node = this.getNextTraverseSelected(this.indicator || this.value, true);
				if(node) this.select(node);
				
			break;
		}
	}
	
	/* *********
		INIT
	**********/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */

	this.slideToggle = function(e){
		if(!e) e = event;
		
		if(this.isOpen) this.slideUp();
		else this.slideDown(e);
	}

	this.slideDown = function(e){
		if(this.dispatchEvent("onslidedown") === false) return false;
		
		this.isOpen = true;
		
		this.oSlider.style.display = "block";
		this.oSlider.style[IS_IE ? "overflowY" : "overflow"] = "hidden";
		
		this.oSlider.style.display = "";
		//this.__setStyleClass(this.oExt, this.baseCSSname + "Down");
		
		/*var HT = this.sliderHeight;
		new GuiAnimation(this.oSlider, this.direction == "up" ? 'scrolltop' : 'scrollheight', 0, HT, this.animType, this.animSteps, this.animSpeed, 
			function(container){
				container.style[IS_IE ? "overflowY" : "overflow"] = "auto";
			});*/

		//var pos = jpf.compat.getAbsolutePosition(this.oExt);
		this.oSlider.style.height = (this.sliderHeight - 1) + "px";
		this.oSlider.style.width = (this.jml.getAttribute("width") - 2) + "px";
		jpf.Popup.show(this.uniqueId, 0, this.jml.getAttribute("height"), true, this.oLoc, this.jml.getAttribute("width"), this.containerHeight,
			function(container){
				container.style[IS_IE ? "overflowY" : "overflow"] = "auto";
			});
	}
	
	this.slideUp = function(){
		if(this.isOpen == 2) return;
		if(this.dispatchEvent("onslideup") === false) return false;
		
		this.isOpen = false;
		if(this.value){
			var htmlNode = XMLDatabase.findHTMLNode(this.value, this);
			if(htmlNode) this.__setStyleClass(htmlNode, '', ["hover"]);
		}
		
		//this.__setStyleClass(this.oExt, '', [this.baseCSSname + "Down"]);
		jpf.Popup.hide();
	}
	this.addEventListener("onpopuphide", this.slideUp);
	
	this.setMaxItems = function(count){
		this.sliderHeight = count ? (Math.min(this.maxItems, count) * 18) + 1 : 10;
		this.containerHeight = count ? (Math.min(this.maxItems, count) * 18) + 1 : 10;
		if(this.containerHeight > 20) this.containerHeight = Math.ceil(this.containerHeight*0.9);
	}
	
	this.disable = this.enable = function(){}
	
	this.__removeClearMessage = function(){
		//var oEmpty = this.oSlider.ownerDocument.getElementById("empty" + this.uniqueId);
		//if(oEmpty) oEmpty.parentNode.removeChild(oEmpty);
		//else this.oInt.innerHTML = ""; //clear if no empty message is supported
		var nodes = this.oSlider.childNodes;
		for(var i=0;i<nodes.length;i++){
			if(nodes[i].getAttribute("id").match(/empty/))
				this.oSlider.removeChild(nodes[i]);
		}
	}
	
	this.draw = function(){
		this.animType 		= this.__getOption("Main", "animtype") || 1;
		this.clickOpen 	= this.__getOption("Main", "clickopen") || "button";

		this.oExt = jdwin.CreateWidget("button");
		
		this.oLoc = this.pHtmlNode.appendChild(document.createElement("div"));
		this.oLoc.style.position = "absolute";
		this.oLoc.style.left = this.jml.getAttribute("left");
		this.oLoc.style.top = this.jml.getAttribute("top");
		
		//Build Main Skin
		/*this.oExt = this.__getExternal(null, null, function(oExt){
			oExt.setAttribute("onmouseover", 'var o = jpf.lookup(' + this.uniqueId + ');o.__setStyleClass(o.oExt, o.baseCSSname + "over");');
			oExt.setAttribute("onmouseout", 'var o = jpf.lookup(' + this.uniqueId + ');if(o.isOpen) return;o.__setStyleClass(o.oExt, "", [o.baseCSSname + "over"]);');
			
			//Button
			var oButton = this.__getLayoutNode("Main", "button", oExt);
			if(oButton){
				oButton.setAttribute("onmousedown", 'jpf.lookup(' + this.uniqueId + ').slideToggle(event);');
				//oButton.setAttribute("onmouseup", 'var o = jpf.lookup(" + this.uniqueId + ");o.__setStyleClass(o.oExt, '', [o.oExt.className.split(' ')[0] + 'down'])");
				//oButton.setAttribute("onmouseout", 'var o = jpf.lookup(" + this.uniqueId + ");o.__setStyleClass(o.oExt, '', [o.oExt.className.split(' ')[0] + 'down'])");
			}
			
			//Label
			var oLabel = this.__getLayoutNode("Main", "label", oExt);
			if(this.clickOpen == "both"){
				oLabel.parentNode.setAttribute("onmousedown", 'jpf.lookup(' + this.uniqueId + ').slideToggle(event);');
			}
		});
		this.oLabel = this.__getLayoutNode("Main", "label", this.oExt);
		this.oIcon = this.__getLayoutNode("Main", "icon", this.oExt);
		if(this.oButton) this.oButton = this.__getLayoutNode("Main", "button", this.oExt);*/
		
		//Slider
		/*var oSlider = this.__getLayoutNode("Container", null, oExt);
		oSlider.setAttribute("onmouseover", "event.cancelBubble = true");
		oSlider.setAttribute("onmouseout", "event.cancelBubble = true");*/
		this.oSlider = XMLDatabase.htmlImport(this.__getLayoutNode("Container"), document.body);
		this.oInt = this.__getLayoutNode("Container", "contents", this.oSlider);
		
		//Set up the popup
		this.pHtmlDoc = jpf.Popup.setContent(this.uniqueId, this.oSlider, jpf.PresentationServer.getTemplate(this.skinName).selectSingleNode("style").firstChild.nodeValue);
		
		//Get Options form skin
		this.listtype = parseInt(this.__getLayoutNode("Main", "type")) || 1; //Types: 1=One dimensional List, 2=Two dimensional List
	}
	
	this.__loadJML = function(x){
		this.name = x.getAttribute("id");
		this.maxItems = x.getAttribute("max-items") || 5;
		this.disableremove = x.getAttribute("disableremove") != "false";
		this.direction = x.getAttribute("direction") || "down";
		this.clearOnNoSelection = x.getAttribute("clearonnoselection") == "true";
		
		//deskrun
		this.bgswitch = x.getAttribute("bgswitch") ? true : false;
		if(this.bgswitch){
			this.bgoptions = x.getAttribute("bgoptions") ? x.getAttribute("bgoptions").split("\|") : ["vertical", 2];
			
			this.oExt.InitButton(0, 0, 0, this.bgoptions[1], this.mediaPath.replace(/jav\:\//, "") + x.getAttribute("bgswitch"), this.parentNode.offsetHeight ? 1 : 0);
			
			this.oExt.locked = false;
			this.oExt.clicked = false;
			this.oExt.disabled = false;
			//this.setCaption("");
			//if(x.getAttribute("color")) this.setColor(x.getAttribute("color"));
			
			var clr = "0x000000";//eval(color.replace(/#/, "0x"));
			
			var il = this.jml.getAttribute("in_left");
			var it = this.jml.getAttribute("in_top");
			var ib = this.jml.getAttribute("in_bottom");
			var ir = this.jml.getAttribute("in_right");
			var s = this.jml.getAttribute("center");
			this.oExt.SetFont(0,"Arial",10,0,clr,il?il:4,it?it:4,ir?ir:18,ib?ib:0,s);
			this.oExt.SetFont(1,"Arial",10,0,clr,il?il:4,it?it:4,ir?ir:18,ib?ib:0,s);
			this.oExt.SetFont(2,"Arial",10,0,clr,il?il:4,it?it:4,ir?ir:18,ib?ib:0,s);
		}
		
		var jmlNode = this;
		this.oExt.onbuttonclick = function(){
			jmlNode.slideToggle({});
		}
		//deskrun
		
		if(x.childNodes.length) this.loadInlineData(x);
		
		this.setMaxItems();
		
		if(x.getAttribute("multibinding") == "true" && !x.getAttribute("bind"))
			this.inherit(jpf.MultiLevelBinding); /** @inherits jpf.MultiLevelBinding */
	}
	
	this.__destroy = function(){
		jpf.Popup.removeContent(this.uniqueId);
	}
}
/*FILEHEAD(/in/Components/mediaflow/MFList.js)SIZE(12317)TIME(1203730484247)*/

/**
 * @constructor
 */
jpf.MFList = function(pHtmlNode){
	jpf.register(this, "MFList", GUI_NODE);
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	/* ********************************************************************
										PROPERTIES
	*********************************************************************/

	//Options
	this.isMFNode = true;
	this.focussable = true; // This object can get the focus
	this.multiselect = true; // Initially Disable MultiSelect
	this.buttons = [];
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/
	
	/* ***********************
				ACTIONS
	************************/
	
	this.Remove = function(xmlNode){
		if(xmlNode) this.select(xmlNode);

		var sel = this.getSelection();
		for(var i=0;i<sel.length;i++){
			//Use Action Tracker
			this.executeAction("removeNode", [sel[i]], "Remove", sel[i]);
		}
	}
	
	this.Add = function(xmlNode, value){
		//XML from Argument
		if(xmlNode) return this.receiveAddData(xmlNode);
		
		var addXMLNode, node = this.actions["Add"][0];
		if(!node) throw new Error(0, "Could not get Node for Action");

		//Hard Coded XML
		if(node.firstChild) 
			addXMLNode = node.firstChild.cloneNode(true);
		//Execute Client Side Response
		else if(node.getAttribute("object"))
			addXMLNode = self[node.getAttribute("object")][node.getAttribute("method")]();
		else if(node.getAttribute("method"))
			addXMLNode = self[node.getAttribute("method")]();
		else if(node.getAttribute("eval"))
			addXMLNode = eval(node.getAttribute("eval"));

		if(addXMLNode != null) return addXMLNode ? this.receiveAddData(addXMLNode) : false;
		
		//Remote XML
		RPC.callRPCFromNode(node, this.value, new Function('o', 'jpf.lookup(' + this.uniqueId + ').receiveAddData(o)'));
	}
	
	this.receiveAddData = function(xmlNode){
		if(typeof xmlNode != "object") xmlNode = jpf.getObject("XMLDOM", xmlNode).documentElement.firstChild;
		if(xmlNode.getAttribute("id")) xmlNode.setAttribute("id", "")
		
		this.executeAction("appendChildNode", [this.XMLRoot, xmlNode], "Odd", xmlNode);
		this.select(xmlNode);
	}
	
	/* ********************************************************************
										PRIVATE METHODS
	*********************************************************************/
	
	/* ***********************
				Skin
	************************/

	this.deInitNode = function(xmlNode, htmlNode){
		//unsupported
	}
	
	this.updateNode = function(xmlNode, htmlNode){
		//unsupported
		/*
		var elIcon = this.getLayoutNode("Item", "icon", htmlNode);
		
		if(elIcon) 
			elIcon.style.backgroundImage = "url(" + this.iconPath + this.applyRuleSetOnNode("Icon", xmlNode) + ")";
		else{
			var elImage = this.getLayoutNode("Item", "image", htmlNode);//.style.backgroundImage = "url(" + this.applyRuleSetOnNode("Image", xmlNode) + ")";
			if(elImage){
				if(elImage.nodeType == 1) elImage.style.backgroundImage = "url(" + this.applyRuleSetOnNode("Image", xmlNode) + ")";
				else elImage.nodeValue = this.applyRuleSetOnNode("Image", xmlNode);
			}
		}
		
			
		var elCaption = this.getLayoutNode("Item", "caption", htmlNode);
		if(elCaption)
			this.getLayoutNode("Item", "caption", htmlNode).parentNode.innerHTML = this.applyRuleSetOnNode("Caption", xmlNode);
		*/
	}
	
	this.moveNode = function(xmlNode, htmlNode){
		//unsupported
		/*
		if(!htmlNode) return;
		var oPHtmlNode = htmlNode.parentNode;
		var beforeNode = xmlNode.nextSibling ? XMLDatabase.findHTMLNode(this.getNextTraverse(xmlNode), this) : null;

		oPHtmlNode.insertBefore(htmlNode, beforeNode);
		*/
		//if(this.emptyMessage && !oPHtmlNode.childNodes.length) this.setEmpty(oPHtmlNode);
	}
	
	/* ***********************
		Keyboard Support
	************************/
	
	//Handler for a plane list
	this.keyHandler = function(key, ctrlKey, shiftKey, altKey){
		if(!this.selected) return;
		//error after delete...

		switch(key){
			case 13:
				this.select(this.selected);
				if(this.onchoose) this.onchoose();
			break;
			case 32:
				this.select(this.selected);
			break;
			case 46:
			//DELETE
				this.Remove();
			break;
			case 37:
			//LEFT
				var margin = jpf.compat.getBox(jpf.getStyle(this.selected, "margin"));
			
				if(!this.value) return;
				var node = this.getNextTraverseSelected(this.value, false);
				if(node) this.select(node, shiftKey);
				
				if(this.selected.offsetTop < this.oExt.scrollTop)
					this.oExt.scrollTop = this.selected.offsetTop - margin[0];
			break;
			case 38:
			//UP
				var margin = jpf.compat.getBox(jpf.getStyle(this.selected, "margin"));
				
				if(!this.value) return;
				var hasScroll = this.oExt.scrollHeight > this.oExt.offsetHeight;
				var items = Math.floor((this.oExt.offsetWidth - (hasScroll ? 15 : 0)) / (this.selected.offsetWidth+margin[1]+margin[3]));
				var node = this.getNextTraverseSelected(this.value, false, items);
				if(node) this.select(node);
				
				if(this.selected.offsetTop < this.oExt.scrollTop)
					this.oExt.scrollTop = this.selected.offsetTop - margin[0];
			break;
			case 39:
			//RIGHT
				var margin = jpf.compat.getBox(jpf.getStyle(this.selected, "margin"));
				
				if(!this.value) return;
				var node = this.getNextTraverseSelected(this.value, true);
				if(node) this.select(node, shiftKey);
				
				if(this.selected.offsetTop + this.selected.offsetHeight > this.oExt.scrollTop + this.oExt.offsetHeight)
					this.oExt.scrollTop = this.selected.offsetTop - this.oExt.offsetHeight + this.selected.offsetHeight + margin[0];
					
			break;
			case 40:
			//DOWN
				var margin = jpf.compat.getBox(jpf.getStyle(this.selected, "margin"));
				
				if(!this.value) return;
				var hasScroll = this.oExt.scrollHeight > this.oExt.offsetHeight;
				var items = Math.floor((this.oExt.offsetWidth - (hasScroll ? 15 : 0)) / (this.selected.offsetWidth+margin[1]+margin[3]));
				var node = this.getNextTraverseSelected(this.value, true, items);
				if(node) this.select(node);
				
				if(this.selected.offsetTop + this.selected.offsetHeight > this.oExt.scrollTop + this.oExt.offsetHeight)
					this.oExt.scrollTop = this.selected.offsetTop - this.oExt.offsetHeight + this.selected.offsetHeight + 10;
				
			break;
			case 65:
				if(ctrlKey){
					this.selectAll();	
					return false;
				}
			break;
			default: 
			return;
		}
		
		return false;
	}
	
	/* ***********************
			  CACHING
	************************/
	
	this.__getCurrentFragment = function(){
		//if(!this.value) return false;

		var fragment = {
			nodeType : 1,
			buttons : this.buttons
		}
		
		jdshell.update();
		for(var i=0;i<this.buttons.length;i++)
			this.buttons[i].Hide();
		
		this.buttons = [];
		
		return fragment;
	}
	
	this.__setCurrentFragment = function(fragment){
		this.buttons = fragment.buttons;
		
		jdshell.update();
		for(var i=0;i<this.buttons.length;i++)
			this.buttons[i].Show();

		//Select First Node....
		var nodes = this.getTraverseNodes();
		if(nodes.length) if(this.autoselect) this.select(nodes[0]);
		if(!me.isFocussed(this)) this.blur();
	}

	this.__findNode = function(cacheNode, id){
		//if(!cacheNode) return document.getElementById(id);
		//return cacheNode.getElementById(id);
	}
	
	this.__setClearMessage = function(msg){
		
	}
	
	this.__removeClearMessage = function(){
		//unsupported
	}
	
	this.inherit(jpf.Cache); /** @inherits jpf.Cache */

	/* ***********************
			DATABINDING
	************************/
	
	this.nodes = [];
	
	this.bLookup = {};
	this.__add = function(xmlNode, Lid, xmlParentNode, htmlParentNode, beforeNode){
		if(this.bLookup[Lid]) return;
		var btn = jdwin.CreateWidget("button");

		var userdata = [xmlNode, btn,this];
		btn.onbuttonclick = function(){
			var pthis = userdata[2];
			pthis.select(userdata[0]);//unsupported: , event.ctrlKey, event.shiftKey);
			if(pthis.current) pthis.current.clicked = false;
			pthis.current = userdata[1];
			pthis.current.clicked = true;
		}
				
		//[xmlNode, btn]
		btn.disabled = false;
		btn.InitButton(0, 0, 3, 3, this.applyRuleSetOnNode("Image", xmlNode), this.parentNode.offsetHeight ? 1 : 0);

		//elSelect.setAttribute("ondblclick", 'jpf.lookup(' + this.uniqueId + ').run_Event("onchoose")');
		
		this.buttons.push(btn);
		this.bLookup[Lid] = btn;
	}
	
	this.__fill = function(){
		if(!this.oExt.offsetHeight) return;
		
		this.posInited = false;
		this.show();
	}
	
	/* ***********************
				Select
	************************/
	
	this.__select = function(htmlNode, xmlNode){
		if(this.value){
			var Lid = this.value.getAttribute(XMLDatabase.xmlIdTag) + "|" + this.uniqueId;
			this.bLookup[Lid].clicked = false;
		}
		
		var Lid = xmlNode.getAttribute(XMLDatabase.xmlIdTag) + "|" + this.uniqueId;

		this.bLookup[Lid].clicked = true;
	}
	
	this.__deselect = function(){
		
	}
	
	this.__indicate = function(){
		
	}
	
	/* ***********************
				Focus
	************************/
	
	this.__focus = function(){
		
	}
	
	this.__blur = function(){
		
	}
	
	/* ***********************
				SELECT
	************************/
	
	this.__calcSelectRange = function(xmlStartNode, xmlEndNode){
		var r = [], loopNode = xmlStartNode;
		while(loopNode && loopNode != xmlEndNode.nextSibling){
			r.push(loopNode);
			loopNode = loopNode.nextSibling;
		}

		if(r[r.length-1] != xmlEndNode){
			var r = [], loopNode = xmlStartNode;
			while(loopNode && loopNode != xmlEndNode.previousSibling){
				r.push(loopNode);
				loopNode = loopNode.previousSibling;
			};
		}
		
		return r;
	}
	
	this.__selectDefault = function(XMLRoot){
		this.select(XMLRoot.selectSingleNode(this.ruleTraverse));
	}
	
	this.inherit(jpf.MultiSelect); /** @inherits jpf.MultiSelect */
	
	/* ***********************
	  Other Inheritance
	************************/
	
	this.inherit(jpf.DataBinding); /** @inherits jpf.DataBinding */

	/* *********
		INIT
	**********/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.draw = function(){
		//Build Main Skin
		this.oExt = this.pHtmlNode.appendChild(document.createElement("div"));
		if(this.jml.getAttribute("background")) this.oExt.style.background = "no-repeat url(" + this.mediaPath.replace(/jav\:\//, "") + this.jml.getAttribute("background") + ")";
		this.oExt.style.position = "absolute";
		this.oExt.host = this;
	}
	
	this.__loadJML = function(x){
		this.listtype = parseInt(x.getAttribute("list-type")) || 2; //Types: 1=One dimensional List, 2=Two dimensional List
		this.behaviour = parseInt(x.getAttribute("behaviour")) || 1; //Types: 1=Check on click, 2=Check independent
		
		this.multiselect = x.getAttribute("multiselect") != "false";
		this.autoselect = x.getAttribute("autoselect") != "false";
		
		//this.setAnchor(x.getAttribute("left"), x.getAttribute("top"), x.getAttribute("right"), x.getAttribute("bottom"), x.getAttribute("width"), x.getAttribute("height"));
	}
	
	/* ***********************
		Deskrun Support
	************************/
	DeskRun.register(this);
	
	this.show = function(){
		this.oExt.style.display = "block";

		if(!this.posInited){
			this.posInited = true;
			var pos = jpf.compat.getAbsolutePosition(this.oExt);

			var width = 31;
			var spacing = 3;
			var linelen = Math.floor((this.oExt.offsetWidth - spacing)/(width + spacing));
			
			for(var i=0;i<this.buttons.length;i++){
				var posh = i % linelen;
				var posv = Math.floor(i/linelen);

				this.buttons[i].MoveTo(pos[0] + (posh * (width+spacing)) + spacing, pos[1] + (posv * (width+spacing)) + spacing);
			}
		}
		
		for(var i=0;i<this.buttons.length;i++){
			this.buttons[i].Show();
		}
	}
	
	this.hide = function(){
		this.oExt.style.display = "none";
		
		for(var i=0;i<this.buttons.length;i++){
			this.buttons[i].Hide();
		}
	}
}

/*FILEHEAD(/in/Components/mediaflow/MFMenu.js)SIZE(8873)TIME(1203730484247)*/

/**
 * @constructor
 */
jpf.MFMenu = function(pHtmlNode){
	jpf.register(this, "MFMenu", MF_NODE);
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	/* ********************************************************************
										PROPERTIES
	*********************************************************************/

	//Options
	this.focussable = false; // This object can't get the focus
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/
	
	/* ********************************************************************
										PRIVATE METHODS
	*********************************************************************/
	
	this.display = function(x, y, noanim, opener){
		//TEMP SPEED enhancement
		//noanim = true;
		
		this.opener = opener;
		if(this.ondisplay) this.ondisplay();
		
		//this.draw(null, null, true);
		this.setPos(x, y);
		this.showMenu();
		
		/*if(event){
			event.cancelBubble = true;
		   event.returnValue  = false;
		}*/
	}
	
	this.setDisabled = function(list){
		if(!this.oExt) return (this.todo = list);
		var o = this.oExt.firstChild.firstChild;
		//this.showMenu(true);
		
		for(var i=0;i<list.length;i++){
			if(o.childNodes[i].disabled == list[i]) continue;
			o.childNodes[i].disabled = list[i];
			
			var q = o.childNodes[i].lastChild;//.previousSibling
			o.childNodes[i].className = this.skin.clsItemOut;

			if(list[i] == false) enable(q);
			else if(list[i] == true) disable(q);
		}
	}
	
	this.setPos = function(x, y){
		var ht, curht = y;
		
		for(var i=0;i<this.nodes.length;i++){
			ht = this.nodes[i].GetHeight();
			this.nodes[i].Move(x, ht);
			curht += ht;
		}
	}
	
	this.showMenu = function(){
		for(var i=0;i<this.nodes.length;i++){
			this.nodes[i].Show();
		}
	}
	
	this.hideMenu = function(hideOpener){
		for(var i=0;i<this.nodes.length;i++){
			this.nodes[i].Hide();
		}
		
		currentMenu = null;
	}
	
	this.normalize = function(){
		this.hideMenu();
		for(var i=0;i<this.last.length;i++){
			this.last[i].style.visibility = "";
			this.last[i].style.filter = "";
		}
	}
	
	this.setValue = function(value, matchCaption){
		var nodes = this.jml.childNodes;
		for(var i=0;i<nodes.length;i++){
			if(nodes[i].nodeType != 1) continue;
			var tagName = nodes[i].tagName.replace(/^j\:/, "");
			if(tagName == "Item" && (matchCaption ? nodes[i].firstChild.nodeValue : nodes[i].getAttribute("value")) == value) this.value = nodes[i];
		}
	}
	
	this.clearSelection = function(){
		this.value = null;
	}
	
	this.select = function(data){
		if(!this.onselect) this.hideMenu(true);
		
		if(this.onAnyClick) this.onAnyClick();
		if(this.onselect) this.onselect(data);
		
		return;
	}
	
	/* ***********************
				Skin
	************************/

	this.deInitNode = function(xmlNode, htmlNode){
		//Remove htmlNodes from tree
		htmlNode.parentNode.removeChild(htmlNode);
	}
	
	this.updateNode = function(xmlNode, htmlNode){
		//Update Identity (Look)
		if(this.__getLayoutNode("Item", "icon", htmlNode)) 
			this.__getLayoutNode("Item", "icon", htmlNode).style.backgroundImage = "url(" + this.iconPath + this.applyRuleSetOnNode("Icon", xmlNode) + ")";
		else this.__getLayoutNode("Item", "Image", htmlNode).style.backgroundImage = "url(" + this.applyRuleSetOnNode("Image", xmlNode) + ")";
			
		this.__getLayoutNode("Item", "caption", htmlNode).nodeValue = this.applyRuleSetOnNode("Caption", xmlNode);
	}
	
	/* ***********************
		Keyboard Support
	************************/
	
	//Handler for a plane list
	this.keyHandler = function(key, ctrlKey, shiftKey, altKey){
		if(!this.selected) return;
		//error after delete...

		switch(key){
			case 13:
				this.select(this.selected);
				if(this.onchoose) this.onchoose();
			break;
			case 37:
			//LEFT
			case 38:
			//UP
				var margin = jpf.compat.getBox(jpf.getStyle(this.selected, "margin"));
				
				if(!this.value) return;
				var hasScroll = this.oExt.scrollHeight > this.oExt.offsetHeight;
				var items = Math.floor((this.oExt.offsetWidth - (hasScroll ? 15 : 0)) / (this.selected.offsetWidth+margin[1]+margin[3]));
				var node = this.getNextTraverseSelected(this.value, false, items);
				if(node) this.select(node);
				
				if(this.selected.offsetTop < this.oExt.scrollTop)
					this.oExt.scrollTop = this.selected.offsetTop - margin[0];
			break;
			case 39:
			//RIGHT
			case 40:
			//DOWN
				var margin = jpf.compat.getBox(jpf.getStyle(this.selected, "margin"));
				
				if(!this.value) return;
				var hasScroll = this.oExt.scrollHeight > this.oExt.offsetHeight;
				var items = Math.floor((this.oExt.offsetWidth - (hasScroll ? 15 : 0)) / (this.selected.offsetWidth+margin[1]+margin[3]));
				var node = this.getNextTraverseSelected(this.value, true, items);
				if(node) this.select(node);
				
				if(this.selected.offsetTop + this.selected.offsetHeight > this.oExt.scrollTop + this.oExt.offsetHeight)
					this.oExt.scrollTop = this.selected.offsetTop - this.oExt.offsetHeight + this.selected.offsetHeight + 10;
				
			break;
			default: 
			return;
		}
		
		return false;
	}
	
	/* ***********************
			  CACHING
	************************/
	
	this.__getCurrentFragment = function(){
		//if(!this.value) return false;

		var fragment = jpf.isIE55 ? new DocFrag() : document.createDocumentFragment(); //IE55
		while(this.oExt.childNodes.length){
			fragment.appendChild(this.oExt.childNodes[0]);
		}
		
		return fragment;
	}
	
	this.__setCurrentFragment = function(fragment){
		jpf.isIE55 ? fragment.reinsert(this.oExt) : this.oExt.appendChild(fragment); //IE55
		
		//Select First Node....
		if(this.oExt.firstChild){
			this.select(this.oExt.firstChild);
			if(!me.isFocussed(this)) this.blur();
		}
	}

	this.__findNode = function(cacheNode, id){
		if(!cacheNode) return document.getElementById(id);
		return cacheNode.getElementById(id);
	}
	
	this.__setClearMessage = function(msg){
		//this.oExt.innerHTML = "";//<div style='text-align:center;font-family:MS Sans Serif;font-size:8pt;padding:3px;cursor:default'>" + msg + "</div>";
	}
	
	this.inherit(jpf.Cache); /** @inherits jpf.Cache */

	/* ***********************
			DATABINDING
	************************/
	
	this.nodes = [];
	
	this.__add = function(xmlNode, Lid, xmlParentNode, htmlParentNode, beforeNode){
		var item = this.addItem(
			this.applyRuleSetOnNode("Caption", xmlNode),
			this.applyRuleSetOnNode("Icon", xmlNode),
			this.applyRuleSetOnNode("Disabled", xmlNode),
			this.applyRuleSetOnNode("Submenu", xmlNode),
			this.applyRuleSetOnNode("Value", xmlNode)
		);
		
		item.setAttribute("id", Lid);
	}
	
	this.doItemClick = function(data, state){
		this.select(data[0]);
		this.hideMenu();
	}
	
	this.addItem = function(caption, icon, disabled, submenu, value, onclick){
		var elItem = JDeploy.CreateComponent("button");
		elItem.SetOnButtonChange(this, "doItemClick", [value, btn]);
		elItem.SetWidgetActive(1);
		elItem.InitButton(0, 0, 0, 3, icon, 0);

		this.nodes.push(elItem);
		
		return elItem;
	}
	
	this.hideSubMenu = function(){
		if(!this.showingSubMenu) return;
		self[this.showingSubMenu].oExt.style.display = "none";
		this.showingSubMenu = null;
	}
	
	this.showSubMenu = function(htmlNode, submenu){
		if(this.showingSubMenu == submenu) return;
		
		var pos = jpf.compat.getAbsolutePosition(htmlNode);
		/*self[submenu].oExt.style.left = pos[0] + htmlNode.offsetWidth - 2;
		self[submenu].oExt.style.top = pos[1] - 2;
		self[submenu].oExt.style.display = "block";*/
		self[submenu].display(pos[0] + htmlNode.offsetWidth - 2, pos[1] - 2, false, this);
		
		this.showingSubMenu = submenu;
	}
	
	this.addDivider = function(){
		//this.nodes.push();
	}
	
	this.__fill = function(){
	}
	
	/* ***********************
	  Other Inheritance
	************************/
	
	this.inherit(jpf.DataBinding); /** @inherits jpf.DataBinding */

	/* *********
		INIT
	**********/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.draw = function(){
		//Build JML defined contents (if any
		var nodes = this.jml.childNodes;
		for(var i=0;i<nodes.length;i++){
			if(nodes[i].nodeType != 1) continue;
			var tagName = nodes[i].tagName.replace(/^j\:/, "");

			if(tagName == "Item") this.addItem(nodes[i].firstChild.nodeValue, nodes[i].getAttribute("icon"), nodes[i].getAttribute("disabled"), nodes[i].getAttribute("submenu"), nodes[i].getAttribute("value"), nodes[i].getAttribute("onclick"));
			else if(tagName == "Divider") this.addDivider();
		}
		
		if(this.nodes.length) this.__fill();
	}
	
	this.__loadJML = function(x){}
	
	/* ***********************
		Deskrun Support
	************************/
	DeskRun.register(this);
	
	this.show = function(){
	}
	
	this.hide = function(){
	}
}

jpf.currentMenu = null;

/*FILEHEAD(/in/Components/mediaflow/MFSlider.js)SIZE(4835)TIME(1203730484247)*/

/**
 * @constructor
 */
jpf.MFSlider = function(pHtmlNode){
	jpf.register(this, "MFSlider", MF_NODE);
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;

	/* ***********************
	  		Inheritance
	************************/
	this.inherit(jpf.DataBinding); /** @inherits jpf.DataBinding */
	
	/* ********************************************************************
										PROPERTIES
	*********************************************************************/
	
	//Options
	this.focussable = false; // This object cant get the focus
	this.disabled = false; // Object is enabled
	this.inherit(jpf.Validation); /** @inherits jpf.Validation */
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/
	
	this.setValue = function(value){
		if(value == "") return;
		this.value = value;

		if(Math.abs(this.oExt.pos - value) > 0.00000001) this.oExt.pos = value;
	}
	
	this.getValue = function(){
		return this.oExt.pos;
	}
	
	/* ***********************
				Actions
	************************/
	
	this.Change = function(value){
		var node = this.getNodeFromRule("Value", this.XMLRoot);
		if(!node){
			this.setValue(value);
			return;
		}

		if(!this.errBox && this.form) this.errBox = this.form.getErrorBox(this.name);
		if(this.errBox && this.errBox.isVisible() && this.isValid()){
			this.clearError();
			this.errBox.hide();
		}

		var atAction = node.nodeType == 1 || node.nodeType == 3 || node.nodeType == 4 ? "setTextNode" : "setAttribute";
		var args = node.nodeType == 1 ? [node, value] : (node.nodeType == 3 || node.nodeType == 4 ? [node.parentNode, value] : [node.selectSingleNode(".."), node.nodeName, value]);
		//alert(node.ownerDocument.selectSingleNode("//node()[@v='" + node.nodeValue + "']").parentNode.parentNode.parentNode.parentNode.parentNode.xml);
		//alert(this.XMLRoot.xml);
		//Use Action Tracker
		this.executeAction(atAction, args, "Change", this.XMLRoot);
	}
	
	/* ***********************
		Keyboard Support
	************************/
	
	//Handler for a plane list
	this.keyHandler = function(key, ctrlKey, shiftKey, altKey){
		switch(key){
			case 37:
			//LEFT
			break;
			case 38:
			//UP
			break;
			case 39:
			//RIGHT
			break;
			case 40:
			//DOWN
			break;
			default: 
			return;
		}
		
		return false;
	}
	
	/* ***********************
			Databinding
	************************/
	
	this.__xmlUpdate = function(action, xmlNode, listenNode, UndoObj){
		//Action Tracker Support
		if(UndoObj) UndoObj.xmlNode = this.XMLRoot;
		
		//Refresh Properties
		//var value = this.applyRuleSetOnNode("Value", this.XMLRoot);
		//if(value != this.getValue()) this.setValue(value || "");
		
		var value = this.applyRuleSetOnNode("Value", this.XMLRoot);
		if((value || typeof value == "string")){
			if(value != this.getValue()) this.setValue(value);
		}
		else this.setValue("");
	}
	
	this.__load = function(XMLRoot, id){
		//Add listener to XMLRoot Node
		XMLDatabase.addNodeListener(XMLRoot, this);
		
		var value = (this.bindingRules ? this.applyRuleSetOnNode("Value", XMLRoot) : (this.jml.firstChild ? this.jml.firstChild.nodeValue : false));
		if((value || typeof value == "string")){
			if(value != this.getValue()) this.setValue(value);
		}
		else this.setValue("");
	}
	
	/* ***********************
				INIT
	************************/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.changeSlider = function(e){
		this.Change(e.pos);
	}
	
	this.draw = function(){
		this.oExt = jdwin.CreateWidget("slider");

		/*var img = document.body.appendChild(document.createElement("IMG"));
		img.src = this.mediaPath + this.jml.getAttribute("slider");
		img.style.position = "absolute";
		img.style.left = "10px";
		img.style.top = "10px";
		img.style.width = "200px";
		img.style.height = "200px";
		img.style.zIndex = 10000;*/
		var il = this.jml.getAttribute("in_left");
		var it = this.jml.getAttribute("in_top");
		var ib = this.jml.getAttribute("in_bottom");
		var ir = this.jml.getAttribute("in_right");
		
		this.oExt.InitSlider( 0,0, il?il:0, it?it:0, ir?ir:0,ib?ib:0,
									 this.jml.getAttribute("direction") == "vertical" ? 1 : 0 ,
									 this.mediaPath.replace(/jav\:\//, "") + this.jml.getAttribute("bgimage"),this.mediaPath.replace(/jav\:\//, "") + this.jml.getAttribute("sliderimage"),0);
									 // this.parentNode.offsetHeight ? 1 : 0); //horizontal 0, vertical 1

		var jmlNode = this;
		this.oExt.SetOnSliderChange(1,0,function(e){
			jmlNode.Change(e.pos);
		});
	}
	
	this.__loadJML = function(x){
		if(x.getAttribute("value")) this.setValue(x.getAttribute("value"));
	}
	
	DeskRun.register(this);
}
/*FILEHEAD(/in/Components/Menu.js)SIZE(11484)TIME(1203730484247)*/

/**
 * Component displaying a skinnable list of options which can be selected. 
 * Selection of multiple items can be allowed. Items can be renamed
 * individually and deleted individually or in groups.
 *
 * @classDescription		This class creates a new menu
 * @return {Menu} Returns a new menu
 * @type {Menu}
 * @constructor
 * @allowchild item, divider, {smartbinding}
 * @addnode components:menu
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.4
 */
jpf.menu = function(pHtmlNode){
	jpf.register(this, "menu", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	/* ********************************************************************
										PROPERTIES
	*********************************************************************/

	//Options
	this.focussable = true; // This object can't get the focus
	
	/* ********************************************************************
										PRIVATE PROPERTIES
	*********************************************************************/
	this.nodes = [];
	this.xpaths = [];
	
	/* ********************************************************************
										PRIVATE METHODS
	*********************************************************************/
	
	this.display = function(x, y, noanim, opener, xmlNode){
		this.opener = opener;
		this.dispatchEvent("ondisplay");
		//debugger;
		
		//Show/Hide Child Nodes Based on XML
		for(var c=0,last,d=0,i=0;i<this.xpaths.length;i++){
			if(!this.xpaths[i]){
				jpf.compat.getNode(this.oInt, [i]).style.display = d == 0 && !last ? "none" : "block";
				if(d == 0 && last) last.style.display = "none";
				last = jpf.compat.getNode(this.oInt, [i]);
				d = 0;
			}
			else{
				var dBlock = !xmlNode && this.xpaths[i] == "." || xmlNode && xmlNode.selectSingleNode(this.xpaths[i]);
				jpf.compat.getNode(this.oInt, [i]).style.display = dBlock ? "block" : "none";
				if(dBlock){ d++; c++; }
			}
		}
		if(d == 0 && last) last.style.display = "none";
		if(!c) return;
		
		this.setPos(x, y);
		this.showMenu(noanim);
		
		this.lastFocus = jpf.window.getFocussedObject();
		this.focus();
		this.lastFocus.__focus();
		
		this.xmlReference = xmlNode;
		
		/*if(event){
			event.cancelBubble = true;
		   event.returnValue  = false;
		}*/
	}
	
	this.setDisabled = function(list){
		if(!this.oExt) return (this.todo = list);
		var o = this.oExt.firstChild.firstChild;
		//this.showMenu(true);
		
		for(var i=0;i<list.length;i++){
			if(o.childNodes[i].disabled == list[i]) continue;
			o.childNodes[i].disabled = list[i];
			
			var q = o.childNodes[i].lastChild;//.previousSibling

			if(list[i] == false) jpf.compat.enable(q);
			else if(list[i] == true) jpf.compat.disable(q);
		}
	}
	
	this.setPos = function(x, y){
		/*dh = (this.oExt.offsetHeight+y) - document.body.clientHeight;
		dw = (this.oExt.offsetWidth+x)  - document.body.clientWidth;
		
		var px = x - (dw > 0 ? dw : 0) + document.body.scrollLeft;
		var py = y - (dh > 0 ? dh : 0) + document.body.scrollTop;
		
		if(!this.menuNode){
			this.oExt.style.display = "block";
			var diffX = (this.oExt.offsetWidth + x + this.parentNode.offsetLeft) - document.body.clientWidth;
			var diffY = (this.oExt.offsetHeight + y + this.parentNode.offsetTop) - document.body.clientHeight;
			this.oExt.style.display = "none";
		}*/
		
		this.oExt.style.left = (x - (jpf.isGecko ? 3 : 0)) + "px";//px - (diffX > 0 ? diffX : 0);
		this.oExt.style.top = (y - (jpf.isGecko ? 3 : 0)) + "px";//py - (diffY > 0 ? diffY : 0);
	}
	
	this.showMenu = function(noanim){
		if(noanim){
			//this.oExt.style.visibility = "visible";
			this.oExt.style.display = "block";
		}
		else{
			//this.oExt.style.visibility = "visible";
			this.oExt.style.display = "block";
			//if(IS_IE) fadeIn(this.oExt, 0.15);
			new jpf.GuiAnimation(this.oExt, 'fade', 0, 1, 0, 7, 10);
		}
		
		jpf.currentMenu = this;
	}
	
	this.hideMenu = function(hideOpener, nofocus){
		this.oExt.style.display = "none";
		if(!nofocus) this.lastFocus.focus();
		else this.lastFocus.__blur();
		//this.oExt.style.visibility = "";
		
		this.hideSubMenu();
		
		jpf.currentMenu = null;
		
		if(hideOpener && this.opener) this.opener.hideMenu(true);
	}
	
	this.normalize = function(){
		this.hideMenu();
		for(var i=0;i<this.last.length;i++){
			//this.last[i].style.visibility = "";
			this.last[i].style.filter = "";
		}
	}
	
	this.setValue = function(value, matchCaption){
		var nodes = this.jml.childNodes;
		for(var i=0;i<nodes.length;i++){
			if(nodes[i].nodeType != 1) continue;
			var tagName = nodes[i][jpf.TAGNAME];
			if(tagName == "item" && (matchCaption ? nodes[i].firstChild.nodeValue : nodes[i].getAttribute("value")) == value) this.value = nodes[i];
		}
	}
	
	this.clearSelection = function(){
		this.value = null;
	}
	
	this.select = function(o, id, subctx, e){
		//if(isFading(o)) return;
		
		//if(e) this.evnt = e;
		
		this.setValue(o.firstChild.nodeValue, true);

		//if(!this.onselect) 
		this.hideMenu(true);
		
		this.dispatchEvent("onanyclick");
		this.dispatchEvent("onafterselect");
		
		if(o.getAttribute("action")){
			strfunc = o.getAttribute("action");
			if(jpf.isIE) strfunc = strfunc.split("\n")[2];
			eval(strfunc);
		}
		
		return;

		//var method = this.data[id];
		//this.oExt.style.visibility = "hidden";
		//o.style.visibility = "visible";
		//for(var i=0;i<this.oInt.childNodes.length;i++) this.oInt.childNodes[i].style.visibility = "visible";
		//(this.last = this.oInt.childNodes)
		this.last = [o];
		//fadeOut(o, 0.30);
		setTimeout('jpf.lookup('+this.uniqueId+').normalize()', 250);
		//if(typeof method == "function") method();
	}
	
	/* ***********************
				Skin
	************************/
	
	this.__deInitNode = function(xmlNode, htmlNode){
		//Remove htmlNodes from tree
		htmlNode.parentNode.removeChild(htmlNode);
	}
	
	this.__updateNode = function(xmlNode, htmlNode){
		//Update Identity (Look)
		if(this.__getLayoutNode("Item", "icon", htmlNode)) 
			this.__getLayoutNode("Item", "icon", htmlNode).style.backgroundImage = "url(" + this.iconPath + this.applyRuleSetOnNode("icon", xmlNode) + ")";
		else this.__getLayoutNode("Item", "Image", htmlNode).style.backgroundImage = "url(" + this.applyRuleSetOnNode("image", xmlNode) + ")";
			
		this.__getLayoutNode("Item", "caption", htmlNode).nodeValue = this.applyRuleSetOnNode("caption", xmlNode);
	}
	
	
	/* ***********************
		Keyboard Support
	************************/
	
	//Handler for a plane list
	this.keyHandler = function(key, ctrlKey, shiftKey, altKey){
 		switch(key){
			case 13:
			break;
			case 37:
			//LEFT
			case 38:
			//UP
			break;
			case 39:
			//RIGHT
			case 40:
			//DOWN
			break;
			default: 
			return;
		}
		
		return false;
	}
	
	
	this.inherit(jpf.Cache); /** @inherits jpf.Cache */

	/* ***********************
			DATABINDING
	************************/
	
	this.nodes = [];
	
	this.__add = function(xmlNode, Lid, xmlParentNode, htmlParentNode, beforeNode){
		var item = this.addItem(
			this.applyRuleSetOnNode("caption", xmlNode),
			this.applyRuleSetOnNode("icon", xmlNode),
			this.applyRuleSetOnNode("disabled", xmlNode),
			this.applyRuleSetOnNode("submenu", xmlNode),
			this.applyRuleSetOnNode("value", xmlNode),
			this.applyRuleSetOnNode("onclick", xmlNode),
			this.applyRuleSetOnNode("method", xmlNode),
			this.applyRuleSetOnNode("select", xmlNode)
		);
		
		item.setAttribute("id", Lid);
	}
	
	this.addItem = function(caption, icon, disabled, submenu, value, onclick, method, xpath){
		this.__getNewContext("Item");
		this.__getLayoutNode("Item", "caption").nodeValue = caption;
		//var elImage = this.__getLayoutNode("Item", "image");
		var elItem = this.__getLayoutNode("Item");
		//if(onclick) elItem.setAttribute("action", onclick);
		//if(elImage.nodeType == 1) elImage.setAttribute("style", "background-image:url(" + this.applyRuleSetOnNode("image", xmlNode) + ")");
		//else elImage.nodeValue = this.applyRuleSetOnNode("image", xmlNode);
		
		if(submenu) this.__setStyleClass(elItem, "submenu");

		elItem.setAttribute("onmouseup", 'jpf.lookup(' + this.uniqueId + ').select(this, null, null, event)'); 
		elItem.setAttribute("onmouseover", 'var o = jpf.lookup(' + this.uniqueId + ');o.__setStyleClass(this, "hover");' + (submenu ? 'o.showSubMenu(this, "' + submenu + '")' : 'o.hideSubMenu();')); 
		elItem.setAttribute("onmouseout", 'if(jpf.XMLDatabase.isChildOf(this, event.toElement ? event.toElement : event.explicitOriginalTarget))return;var o = jpf.lookup(' + this.uniqueId + ');o.__setStyleClass(this, "", ["hover"]);' + (submenu && false ? 'o.hideSubMenu()' : "")); 
		if(onclick || method) elItem.setAttribute("onclick", onclick || method + "(jpf.lookup(" + this.uniqueId + ").xmlReference)");
		
		this.xpaths.push(xpath || ".");
		this.nodes.push(elItem);
		
		return elItem;
	}
	
	this.hideSubMenu = function(){
		if(!this.showingSubMenu) return;
		self[this.showingSubMenu].oExt.style.display = "none";
		this.showingSubMenu = null;
	}
	
	this.showSubMenu = function(htmlNode, submenu){
		if(this.showingSubMenu == submenu) return;
		
		var pos = jpf.compat.getAbsolutePosition(htmlNode);
		/*self[submenu].oExt.style.left = pos[0] + htmlNode.offsetWidth - 2;
		self[submenu].oExt.style.top = pos[1] - 2;
		self[submenu].oExt.style.display = "block";*/
		self[submenu].display(pos[0] + htmlNode.offsetWidth - 2, pos[1] - 2, false, this);
		
		this.showingSubMenu = submenu;
	}
	
	this.addDivider = function(){
		this.__getNewContext("Divider");
		
		this.xpaths.push(false);
		this.nodes.push(this.__getLayoutNode("Divider"));
	}
	
	this.__fill = function(){
		jpf.XMLDatabase.htmlImport(this.nodes, this.oInt);
		this.nodes.length = 0;
	}
	
	/* ***********************
	  Other Inheritance
	************************/
	
	this.inherit(jpf.Presentation); /** @inherits jpf.Presentation */
	
	this.__blur = function(){
		if(!this.oExt) return;
		this.__setStyleClass(this.oExt, "", [this.baseCSSname + "Focus"]);
		this.hideMenu(null, true);
	}
	
	this.inherit(jpf.DataBinding); /** @inherits jpf.DataBinding */

	/* *********
		INIT
	**********/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.draw = function(){
		//Build Main Skin
		this.oExt = this.__getExternal();
		this.oInt = this.__getLayoutNode("Main", "container", this.oExt);
		this.oExt.onmousedown = function(e){(e || event).cancelBubble = true;}
		
		//Build JML defined contents (if any
		var nodes = this.jml.childNodes;
		for(var i=0;i<nodes.length;i++){
			if(nodes[i].nodeType != 1) continue;
			var tagName = nodes[i][jpf.TAGNAME];

			if(tagName == "item") this.addItem(nodes[i].firstChild.nodeValue, nodes[i].getAttribute("icon"), nodes[i].getAttribute("disabled"), nodes[i].getAttribute("submenu"), nodes[i].getAttribute("value"), nodes[i].getAttribute("onclick"), nodes[i].getAttribute("method"), nodes[i].getAttribute("select"));
			else if(tagName == "divider") this.addDivider();
		}
		
		if(this.nodes.length) this.__fill();
	}
	
	this.__loadJML = function(x){}
}

jpf.currentMenu = null;
/*FILEHEAD(/in/Components/ModalWindow.js)SIZE(20508)TIME(1213483123975)*/

//Fix this to only include the widget support when needed is 6Kb

jpf.WinServer = {
	count : 9000,
	wins : [],
	
	setTop : function(win){
		win.setZIndex(this.count++);
		this.wins.remove(win);
		this.wins.push(win);
		return win;
	},
	
	setNext : function(){
		if(this.wins.length < 2) return;
		var nwin, start = this.wins.shift();
		do{
			if(this.setTop(nwin || start).visible) break;
			nwin = this.wins.shift();
		}while(start != nwin);
	},
	
	setPrevious : function(){
		if(this.wins.length < 2) return;
		this.wins.unshift(this.wins.pop());
		var nwin, start = this.wins.pop();
		do{
			if(this.setTop(nwin || start).visible) break;
			nwin = this.wins.pop();
		}while(start != nwin);
	},
	
	remove : function(win){
		this.wins.remove(win);	
	}
}

/**
 * Component displaying a skinnable, draggable window with optionally
 * a min, max, edit and close button. This component is also used
 * as a portal widget container. Furthermore this component supports
 * docking in an alignment layout.
 *
 * @classDescription		This class creates a new window
 * @return {ModalWindow} Returns a new window
 * @type {ModalWindow}
 * @constructor
 * @allowchild {components}, {smartbinding}, {anyjml}
 * @addnode components:modalwindow
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.4
 */
jpf.modalwindow = function(pHtmlNode, tagName, jmlNode, isWidget){
	jpf.register(this, "modalwindow", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	this.focussable = true;
	
	/* ***********************
	  		Inheritance
	************************/
	this.inherit(jpf.Presentation); /** @inherits jpf.Presentation */
	this.inherit(jpf.DelayedRender); /** @inherits jpf.DelayedRender */
	
	this.editableParts = {"Main" : [["title","@title"]]};

	/* ********************************************************************
										PROPERTIES
	*********************************************************************/
	
	this.minWT = null;
	this.minHT = null;

	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/
	
	this.setCaption = function(caption){
		this.oTitle.nodeValue = caption;
	}
	
	this.setIcon = function(icon){
		if(!this.oIcon) return;
		
		if(this.oIcon.tagName.toLowerCase() == "img") this.oIcon.src = this.iconPath + icon;
		else this.oIcon.style.backgroundImage = "url(" + this.iconPath + ")";
	}
	
	this.display = function(center, x, y){
		this.setProperty("visible", true);
		
		if(x) this.oExt.style.left = x + "px";
		if(y) this.oExt.style.top = y + "px";
		if(center){
			this.oExt.style.left = Math.max(0,((jpf.getWindowWidth() - this.oExt.offsetWidth)/2)) + "px";
			this.oExt.style.top = Math.max(0,((jpf.getWindowHeight() - this.oExt.offsetHeight)/3)) + "px";
		}
		
		if(!this.isModal) jpf.WinServer.setTop(this);
	}
	
	
	this.syncAlignment = function(oItem){
		if(oItem.hidden == 3) jpf.WinServer.setTop(this);

		if(oItem.state > 0){
			this.__setStyleClass(this.oExt, this.baseCSSname + "Min", [this.baseCSSname + "Edit", this.baseCSSname + "Max"]);
		}
		else{
			this.__setStyleClass(this.oExt, "", [this.baseCSSname + "Min", this.baseCSSname + "Edit", this.baseCSSname + "Max"]);
		}
	}
	
	
	this.close = function(){
		this.setProperty("visible", false);
		this.__setStyleClass(this.oExt, "", [this.baseCSSname + "Min", this.baseCSSname + "Edit", this.baseCSSname + "Max"]);
		this.dispatchEvent('onclose');
		state[0] = state[1] = state[2] = 1
	}
	
	var state = [];
	var lastheight = null;
	this.min = function(){
		//toggle
		if(state[0] < 0){
			state[0] = 1;
			this.__setStyleClass(this.oExt, "", [this.baseCSSname + "Min"]);
			
			if(this.aData && this.aData.hidden != 3) this.aData.restore();
			else{
				if(this.aData && this.aData.hidden == 3) this.aData.restore();
				this.oExt.style.height = (lastheight - jpf.compat.getHeightDiff(this.oExt)) + "px";
			}
			
			this.dispatchEvent('onrestore')
		}
		else{
			state[0] = -1;
			state[1] = 1;
			if(state[2] < 1) this.max();
			state[2] = 1;
			this.__setStyleClass(this.oExt, this.baseCSSname + "Min", [this.baseCSSname + "Edit", this.baseCSSname + "Max"]);

			if(this.aData && this.aData.hidden != 3) this.aData.minimize(this.minheight);
			else{
				if(this.aData && this.aData.hidden == 3) this.aData.minimize(this.minheight);
				lastheight = this.oExt.offsetHeight;
				this.oExt.style.height = Math.max(0, this.minheight - jpf.compat.getHeightDiff(this.oExt)) + "px";
			}
			
			this.dispatchEvent('onminimize')
		}
		
		if(this.aData) this.purgeAlignment();
	}
	
	var startpos = null;
	this.max = function(){
		//toggle
		if(state[2] < 0){
			state[2] = 1;
			this.__setStyleClass(this.oExt, "", [this.baseCSSname + "Max"]);
			
			this.oExt.style.left = startpos[0];
			this.oExt.style.top = startpos[1];
			this.oExt.style.width = startpos[2];
			this.oExt.style.height = startpos[3];
			
			var pNode = (this.oExt.parentNode == document.body ? document.documentElement : this.oExt.parentNode);
			pNode.style.overflow = startpos[4];
			
			jpf.layoutServer.play(this.pHtmlNode);
			if(this.aData && this.aData.state > 0 && this.aData.hidden != 3){
				this.aData.restore();
				this.purgeAlignment();
			}
			
			this.dispatchEvent('onrestore')
		}
		else{
			state[2] = -1;
			state[1] = 1;
			if(state[0] < 1) this.min();
			state[0] = 1;
			this.__setStyleClass(this.oExt, this.baseCSSname + "Max", [this.baseCSSname + "Min", this.baseCSSname + "Edit"]);

			var pNode = (this.oExt.parentNode == document.body ? document.documentElement : this.oExt.parentNode);
			startpos = [this.oExt.style.left, this.oExt.style.top, this.oExt.style.width, this.oExt.style.height, pNode.style.overflow];
			
			var diff = jpf.compat.getDiff(this.oExt);
			var verdiff = diff[1];
			var hordiff = diff[0];
			
			var box = jpf.compat.getBox(jpf.compat.getStyle(this.oExt, "borderWidth"));
			
			pNode.style.overflow = "hidden";
			this.oExt.style.left = (-1 * box[3]) + "px";
			this.oExt.style.top = (-1 * box[0]) + "px";
			
			var htmlNode = this.oExt;
			jpf.layoutServer.pause(this.pHtmlNode, function(){
				htmlNode.style.width = (htmlNode.parentNode.offsetWidth - hordiff + box[1] + box[3]) + "px";
				htmlNode.style.height = (htmlNode.parentNode.offsetHeight - verdiff + box[0] + box[2]) + "px";
			});
			jpf.WinServer.setTop(this)
			
			this.dispatchEvent('onmaximize')
		}
	}
	
	
	this.edit = function(oHtml){
		//toggle
		if(state[1] < 0){
			if(this.dispatchEvent('oneditstop') === false) return false;
			
			state[1] = 1;
			this.__setStyleClass(this.oExt, "", [this.baseCSSname + "Edit"]);
			if(oHtml) oHtml.innerHTML = "edit"; //hack
		}
		else{
			state[1] = -1;
			state[0] = 1;
			this.__setStyleClass(this.oExt, this.baseCSSname + "Edit", [this.baseCSSname + "Min"]);
			if(oHtml) oHtml.innerHTML = "close"; //hack
			
			this.dispatchEvent('oneditstart');
		}
	}
	
	var hEls = [];
	this.__handlePropSet = function(prop, value){
		switch(prop){
			case "visible":
				if(jpf.isTrue(value)){
					//if(!x && !y && !center) center = true;
			
					this.render();
					
					if(this.isModal){ 
						this.oCover.style.height = Math.max(document.body.scrollHeight,document.documentElement.offsetHeight)+'px';
						this.oCover.style.width = Math.max(document.body.scrollWidth,document.documentElement.offsetWidth)+'px';
						this.oCover.style.display = "block";
					}

					//!jpf.isIE && 
					if(jpf.layoutServer) jpf.layoutServer.forceResize(this.oInt); //this should be recursive down
					
					if(this.center){
						this.oExt.style.left = ((jpf.getWindowWidth() - this.oExt.offsetWidth)/2) + "px";
						this.oExt.style.top = ((jpf.getWindowHeight() - this.oExt.offsetHeight)/3) + "px";
					}
					
					if(!this.isRendered){
						this.addEventListener("onafterrender", function(){
							this.dispatchEvent("ondisplay");
							this.removeEventListener("ondisplay", arguments.callee);
						});
					}
					else this.dispatchEvent("ondisplay");
					
					if(!jpf.canHaveHtmlOverSelects && this.hideSelects){
						hEls = [];
						var nodes = document.getElementsByTagName("select");
						for(var i=0;i<nodes.length;i++){
							var oStyle = jpf.compat.getStyle(nodes[i], "display");
							hEls.push([nodes[i], oStyle]);
							nodes[i].style.display = "none";
						}
					}
				}
				else if(jpf.isFalse(value)){
					//this.setProperty("visible", false);
					if(this.isModal) this.oCover.style.display = "none";
					this.dispatchEvent("onclose");
					
					if(!jpf.canHaveHtmlOverSelects && this.hideSelects){
						for(var i=0;i<hEls.length;i++){
							hEls[i][0].style.display = hEls[i][1];
						}
					}
				}
			break;
		}
	}
	
	this.keyHandler = function(key, ctrlKey, shiftKey, altKey){
		switch(key){
			case 27:
				if(this.btnclose && !this.aData) this.close();
			break;
			default:
			break;
		}
	}
	
	/* ********************************************************************
										PRIVATE METHODS
	*********************************************************************/

	//this should be put in a baseclass and rewritten to use setDragMode
	if(isWidget){
		//Should be moved to an init function
		this.positionHolder = document.body.appendChild(document.createElement("div"));
		
		var winNode = this;
		this.winMouseDown = function(e){
			if(!e) e = event;
			MOVER = this;
			//jpf.Plane.show(MOVER.host.showDragBox());
	
			this.coX = e.clientX;
			this.stX = this.host.oExt.offsetLeft;// - 10
			this.coY = e.clientY;
			this.stY = this.host.oExt.offsetTop;// - 10
	
			var htmlNode = this.host.oExt;
			var p = this.host.positionHolder;
			p.className = "position_holder";
			
			htmlNode.parentNode.insertBefore(p, htmlNode);
			//p.style.width = (htmlNode.offsetWidth - 2) + "px";
			p.style.height = (htmlNode.offsetHeight - (jpf.isIE6 ? 0 : 13)) + "px";
			
			var diff = jpf.compat.getDiff(htmlNode);
			var lastSize = [htmlNode.style.width, htmlNode.style.height];
			htmlNode.style.width = (htmlNode.offsetWidth - diff[0]) + "px";
			//htmlNode.style.height = (htmlNode.offsetHeight - diff[1]) + "px";
			var toX = e.clientX - this.coX + this.stX;
			var toY = e.clientY - this.coY + this.stY;
			htmlNode.style.left = toX + "px";
			htmlNode.style.top = toY + "px";
			htmlNode.style.position = "absolute";
			htmlNode.style.zIndex = htmlNode.parentNode.style.zIndex = 100000;
			htmlNode.parentNode.style.position = "relative";
			htmlNode.parentNode.style.left = "0"; //hack
			jpf.Animate.fade(htmlNode, 0.8);
			
			jpf.DragMode.mode = true;
	
			document.cData = [htmlNode, p];
			document.onmousemove = this.host.winMouseMove;
			document.onmouseup = function(){
				document.onmousemove = document.onmouseup = null;
				
				htmlNode.style.position = "";//relative";
				htmlNode.style.left = 0;
				htmlNode.style.top = 0;
				htmlNode.style.width = lastSize[0];
				//htmlNode.style.height = lastSize[1];
				htmlNode.style.zIndex = htmlNode.parentNode.style.zIndex = 1;
				//htmlNode.parentNode.style.position = "static";
				p.parentNode.insertBefore(htmlNode, p);
				p.parentNode.removeChild(p);
				jpf.Animate.fade(htmlNode, 1);
				
				//Hack, temp fix
				var grids = winNode.getElementsByTagName("datagrid");
				for(var i=0;i<grids.length;i++){
					grids[i].updateWindowSize(true);
				}
				
				//MOVER.host.hideDragBox();
				//jpf.Plane.hide();
				//MOVER.host.set_Top();
				
				jpf.DragMode.mode = null;
			}
			
			e.cancelBubble = true;
			return false;
		}
		
		function insertInColumn(el, ey){
			//search for position
			var pos = jpf.compat.getAbsolutePosition(el);
			var cy = ey - pos[1];
			var nodes = el.childNodes;
			for(var th=0,i=0;i<nodes.length;i++){
				if(nodes[i].nodeType != 1 || jpf.getStyle(nodes[i], "position") == "absolute") continue;
				th = nodes[i].offsetTop + nodes[i].offsetHeight;
				if(th > cy){
					if(th - (nodes[i].offsetHeight/2) > cy)
						el.insertBefore(document.cData[1], nodes[i]);
					else
						el.insertBefore(document.cData[1], nodes[i].nextSibling);
					break;	
				}
			}
			if(i == nodes.length) el.appendChild(document.cData[1]);	
		}
		
		this.winMouseMove = function(e){
			if(!e) e = event;
			
			var o = MOVER;
			
			var toX = e.clientX - o.coX + o.stX;
			var toY = e.clientY - o.coY + o.stY;
			
			var db = MOVER.host.oExt;//.host.showDragBox();
			
			//status = "(" + toX + ", " + toY + ")";
			
			db.style.top = "10000px";
			var ex = e.clientX+document.documentElement.scrollLeft;
			var ey = e.clientY+document.documentElement.scrollTop;
			var el = document.elementFromPoint(ex, ey);
			if(el.isColumn){
				insertInColumn(el, ey);
			}
			else{
				//search for element
				while(el.parentNode && !el.isColumn){
					el = el.parentNode;
				}
				if(el.isColumn) insertInColumn(el, ey);
				else status = "notfound" + new Date();
			}
			
			db.style.left = toX + "px";
			db.style.top = toY + "px";
			
			e.cancelBubble = true;
		}
	}
	else{
		this.winMouseDown = function(e){
			if(!e) e = event;
			if(this.host.aData){
				if(!(state[2] < 0)) this.host.startDocking(e);
				return;
			}
			
			if(!this.host.draggable) return;
			
			if(!e) e = event;
			MOVER = this;
			//jpf.Plane.show(MOVER.host.showDragBox());
	
			this.coX = e.clientX;
			this.stX = this.host.oExt.offsetLeft;
			this.coY = e.clientY;
			this.stY = this.host.oExt.offsetTop;
	
			document.onmousemove = this.host.winMouseMove;
			document.onmouseup = function(){
				document.onmousemove = document.onmouseup = null;
				
				//MOVER.host.hideDragBox();
				//jpf.Plane.hide();
				//MOVER.host.set_Top();
			}
			
			return false;
		}
		
		this.winMouseMove = function(e){
			if(!e) e = event;
			
			var o = MOVER;
			
			var toX = e.clientX - o.coX + o.stX;
			var toY = e.clientY - o.coY + o.stY;
			
			var db = MOVER.host.oExt;//.host.showDragBox();
			
			//status = "(" + toX + ", " + toY + ")";
			
			db.style.left = toX + "px";
			db.style.top = toY + "px";
			
			//e.cancelBubble = true;
		}
	}
	
	/* *********
		INIT
	**********/
	this.inherit(jpf.Docking); /** @inherits jpf.Docking */
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.setZIndex = function(value){
		this.oExt.style.zIndex = value + 1;
		if(this.isModal) this.oCover.style.zIndex = value;
	}

	function addButton(prop, type, func, oButtons){
		if(!this[prop]) this[prop] = jpf.isTrue(this.jml.getAttribute(prop));
		if(this[prop] && this.__hasLayoutNode(type)){
			this.__getNewContext(type); 
			var btn = oButtons.appendChild(this.__getLayoutNode(type));
			btn.setAttribute("onclick", func);
			btn.setAttribute("onmousedown", "jpf.setStyleClass(this, 'down');event.cancelBubble = true;");
			btn.setAttribute("onmouseup", "jpf.setStyleClass(this, '', ['down'])");
			btn.setAttribute("onmouseover", "jpf.setStyleClass(this, 'hover')");
			btn.setAttribute("onmouseout", "jpf.setStyleClass(this, '', ['hover', 'down'])");
		}
	}
	
	this.draw = function(){
		this.popout = this.jml.getAttribute("popout") == "true";
		if(this.popout) this.pHtmlNode = document.body;
		
		this.oExt = this.__getExternal(null, null, function(oExt){
			var oButtons = this.__getLayoutNode("Main", "buttons", oExt);
			
			addButton.call(this, "btnclose", "CloseBtn", "jpf.lookup(" + this.uniqueId + ").close()", oButtons);
			addButton.call(this, "btnmax", "MaxBtn", "jpf.lookup(" + this.uniqueId + ").max()", oButtons);
			addButton.call(this, "btnmin", "MinBtn", "jpf.lookup(" + this.uniqueId + ").min()", oButtons);
			
			if(isWidget && $xmlns(this.jml, "config", jpf.ns.jpf).length)
				addButton.call(this, "btnedit", "EditBtn", "jpf.lookup(" + this.uniqueId + ").edit(this)", oButtons);
		});
		this.oTitle = this.__getLayoutNode("Main", "title", this.oExt);
		this.oIcon = this.__getLayoutNode("Main", "icon", this.oExt);
		this.oDrag = this.__getLayoutNode("Main", "drag", this.oExt);

		if(!isWidget){
			var oCover = this.__getLayoutNode("Cover");
			if(oCover){
				this.oCover = jpf.XMLDatabase.htmlImport(oCover, this.pHtmlNode);
				this.oCover.style.display = "none";
			}
		}
		
		this.movable = this.jml.getAttribute("movable") != "false";
		if(this.movable) this.oDrag.onmousedown = this.winMouseDown;
		this.oDrag.host = this;
		
		if(this.hasFeature(__MULTILANG__)) this.__makeEditable("Main", this.oExt, this.jml);
		
		if(!this.hasFeature(__DATABINDING__) && (this.jml.getAttribute("smartbinding") || this.jml.getAttribute("actions"))){
			this.inherit(jpf.DataBinding); /** @inherits jpf.DataBinding */
			this.inherit(jpf.Transaction); /** @inherits jpf.Transaction */
			this.inherit(jpf.EditTransaction); /** @inherits jpf.EditTransaction */
		}
	}
	
	this.__loadJML = function(x, skinName){
		if(x.getAttribute("minwidth")) this.minWT = x.getAttribute("minwidth");
		if(x.getAttribute("minheight")) this.minHT = x.getAttribute("minheight");
		if(x.getAttribute("title")) this.setCaption(x.getAttribute("title"));
		if(x.getAttribute("icon")) this.setIcon(x.getAttribute("icon"));

		//if(x.getAttribute("zindex")) this.setZIndex(x.getAttribute("zindex"));
		
		this.hideSelects = x.getAttribute("hide-selects") == "true";
		this.center = x.getAttribute("center") == "true";
		this.isModal = this.oCover && (x.getAttribute("modal") != "false");
		this.draggable = x.getAttribute("draggable") != "false";
		
		if(this.center) this.oExt.style.position = "absolute";
		if(!this.isModal){
			this.oExt.onmousedown = function(e){
				if(!this.host.aData && !this.host.modal || this.host.aData.hidden == 3)
					jpf.WinServer.setTop(this.host);
				//(e || event).cancelBubble = true;
			}
		}
		
		jpf.WinServer.setTop(this);
		
		var oInt = this.__getLayoutNode("Main", "container", this.oExt);
		var oSettings = this.__getLayoutNode("Main", "settings_content", this.oExt);
			
		//jpf.PresentationServer.defaultSkin = skinName;

		if(!isWidget){
			this.oInt = this.oInt ? 
				jpf.JMLParser.replaceNode(oInt, this.oInt) : 
				jpf.JMLParser.parseChildren(this.jml, oInt, this, true);
		}
		else{
			var oConfig = $xmlns(this.jml, "config", jpf.ns.jpf)[0];
			if(oConfig) oConfig.parentNode.removeChild(oConfig);
			var oBody = $xmlns(this.jml, "body", jpf.ns.jpf)[0];//jpf.XMLDatabase.selectSingleNode("j:body", this.jml);
			oBody.parentNode.removeChild(oBody);

			jpf.JMLParser.parseChildren(this.jml, null, this);
			
			if(oConfig) this.jml.appendChild(oConfig);
			this.jml.appendChild(oBody);
		
			if(oSettings && oConfig){
				this.oSettings = this.oSettings ? 
					jpf.JMLParser.replaceNode(oSettings, this.oSettings) : 
					jpf.JMLParser.parseChildren(oConfig, oSettings, this, true);
			}
			
			this.oInt = this.oInt ? 
				jpf.JMLParser.replaceNode(oInt, this.oInt) : 
				jpf.JMLParser.parseChildren(oBody, oInt, this, true);
			
			if(oBody.getAttribute("cssclass"))
				this.__setStyleClass(this.oInt, oBody.getAttribute("cssclass"))
		}
		
		//jpf.PresentationServer.defaultSkin = null;
		
		//this.close();
		if(this.isModal) this.oCover.style.display = "none";
		if(!this.jml.getAttribute("visible") || jpf.isFalse(this.jml.getAttribute("visible"))){
			this.oExt.style.display = "none";
			this.visible = false;
		}
		
		this.minwidth = this.__getOption("Main", "min-width");
		this.minheight = this.__getOption("Main", "min-height");
	}	
	
	this.__destroy = function(){
		if(this.oDrag){
			this.oDrag.host = null;
			jpf.removeNode(this.oDrag);
			this.oDrag = null;
		}
		this.oTitle = null;
		this.oIcon = null;
		this.oCover = null;
		
		if(this.oExt)
			this.oExt.onmousedown = null;
	}
}
/*FILEHEAD(/in/Components/Pages.js)SIZE(1472)TIME(1203730484247)*/

/**
 * Component displaying a rectangle which displays different
 * content based on the page that is currently set as active.
 *
 * @classDescription		This class creates a new pages object
 * @return {Pages} Returns a new pages object
 * @type {Pages}
 * @constructor
 * @addnode components:pages, components:switch
 * @alias switch
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.4
 */
jpf["switch"] = 
jpf.pages = function(pHtmlNode, tagName){
	jpf.register(this, tagName || "pages", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	/* ***********************
	  Other Inheritance
	************************/
	this.inherit(jpf.BaseTab); /** @inherits jpf.BaseTab */
	
	this.focussable = false;
	
	/* ********************************************************************
										PRIVATE METHODS
	*********************************************************************/
	
	/* *********
		INIT
	**********/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.draw = function(){
		//Build Main Skin
		this.oExt = this.__getExternal();
		this.oPages = this.__getLayoutNode("Main", "pages", this.oExt);
	}
	
	this.__loadJML = function(x){
		this.switchType = x.getAttribute("switchtype") || "incremental";
		
		this.__drawTabs();
	}
}
/*FILEHEAD(/in/Components/Palette.js)SIZE(4199)TIME(1203730484247)*/

/**
 * Component displaying a set of choices to the user which allows
 * him/her to pick a specific color. This component also gives the
 * user a choice to add a custom color.
 *
 * @classDescription		This class creates a new palette component
 * @return {Palette} Returns a new pages palette component
 * @type {Palette}
 * @constructor
 * @allowchild {smartbinding}
 * @addnode components:palette
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.4
 */
jpf.palette = function(pHtmlNode){
	jpf.register(this, "palette", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	/* ***********************
	  		Inheritance
	************************/
	this.inherit(jpf.Presentation); /** @inherits jpf.Presentation */
	
	this.inherit(jpf.DataBinding); /** @inherits jpf.DataBinding */
	
	/* ********************************************************************
										PROPERTIES
	*********************************************************************/

	//Options
	this.focussable = true; // This object can get the focus
	this.value = null;
	this.inherit(jpf.Validation); /** @inherits jpf.Validation */
	this.inherit(jpf.XForms); /** @inherits jpf.XForms */
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/

	this.setValue = function(value){
		this.value = value;
		
		this.oViewer.style.backgroundColor = value;
	}
	
	this.getValue = function(){
		return this.value ? this.value.nodeValue : "";
	}
	
	this.addColor = function(clr, oContainer){
		if(!oContainer) oContainer = this.oCustom;
		
		var oItem = this.__getLayoutNode("Item");
		
		if(oContainer == this.oCustom){
			oItem.setAttribute("onmousedown", "jpf.lookup(" + this.uniqueId + ").doCustom(this)");
			oItem.setAttribute("ondblclick", "jpf.lookup(" + this.uniqueId + ").doCustom(this, true)");
		}
		else oItem.setAttribute("onmousedown", "jpf.lookup(" + this.uniqueId + ").change(this.style.backgroundColor.replace(/^#/, ''))");
		
		oItem = jpf.XMLDatabase.htmlImport(oItem, oContainer, null, true);
		this.__getLayoutNode("Item", "background", oItem).style.backgroundColor = clr;
	}
	
	this.setCustom = function(oItem, clr){
		oItem.style.backgroundColor = clr;
		this.change(clr);
	}
	
	this.doCustom = function(oItem, force_create){
		if(force_create || oItem.style.backgroundColor == "#ffffff"){
			this.dispatchEvent("oncreatecustom", {htmlNode : oItem});
		}
		else this.change(oItem.style.backgroundColor.replace(/^#/, ""));
	}
	
	/* ***********************
		Keyboard Support
	************************/
	
	this.keyHandler = function(key){}
	
	this.__focus = function(){
	}
	
	this.__blur = function(){
	}
	
	this.focussable = true;
	
	/* ***********************
			Databinding
	************************/
	this.defaultValue = "ff0000";
	
	/* *********
		INIT
	**********/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */

	this.colors = [
		"fc0025", "ffd800", "7dff00", "32ffe0", "0026ff", "cd00ff", "ffffff", "e5e5e5", "d9d9d9",
		"de003a", "ffc600", "009022", "00bee1", "003e83", "dc0098", "737373", "666666", "000000"
	];
	
	this.draw = function(){
		//Build Main Skin
		this.oExt = this.__getExternal();
		this.oViewer = this.__getLayoutNode("Main", "viewer", this.oExt);
		this.oStandard = this.__getLayoutNode("Main", "standard", this.oExt);
		this.oCustom = this.__getLayoutNode("Main", "custom", this.oExt);
		
		for(var i=0;i<this.colors.length;i++) this.addColor(this.colors[i], this.oStandard);
		for(var i=0;i<9;i++) this.addColor("ffffff");

		//this.oViewer.setAttribute("ondblclick", "jpf.lookup(" + this.uniqueId + ").openColorPicker()");
	}
	
	this.__loadJML = function(x){
		this.name = x.getAttribute("id");
		this.inline = x.getAttribute("inline") == "true";
		this.direction = x.getAttribute("direction") || "down";
	}
}
/*FILEHEAD(/in/Components/Picture.js)SIZE(1771)TIME(1202849967875)*/

/**
 * Component displaying a picture.
 *
 * @classDescription		This class creates a new picture
 * @return {Picture} Returns a new pages picture
 * @type {Picture}
 * @constructor
 * @allowchild {smartbinding}
 * @addnode components:picture
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.4
 */
jpf.picture = function(pHtmlNode){
	jpf.register(this, "picture", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	this.editableParts = {"Main" : [["image","@src"]]};
	
	this.setValue = function(value){
		//this.setProperty("value", value);
	}
	
	this.__supportedProperties = ["value"];
	this.__handlePropSet = function(prop, value){
		switch(prop){
			case "value":
				var imgNode = this.__getLayoutNode("Main", "image", this.oExt);
				if(imgNode.nodeType == 1) imgNode.style.backgroundImage = "url("+ value+")";
				else imgNode.nodeValue = value;
			break;
		}
	}
	
	this.draw = function(){
		//Build Main Skin
		this.oInt = this.oExt = this.__getExternal();
		this.oExt.onclick = function(e){this.host.dispatchEvent("onclick", {htmlEvent : e || event});}
	}
	
	this.__loadJML = function(x){
		if(x.getAttribute("src"))
			this.setProperty("value", x.getAttribute("src"));
		
			this.__makeEditable("Main", this.oExt, this.jml);
		
		jpf.JMLParser.parseChildren(x, null, this);
	}
	
	this.inherit(jpf.BaseSimple); /** @inherits jpf.BaseSimple */
}

/*FILEHEAD(/in/Components/Portal.js)SIZE(9635)TIME(1205790104099)*/

/**
 * Component displaying a rectangle consisting of one or more columns
 * which contain zero or more windows. Each window is loaded with specific
 * content described in a piece of JML also referred to as a "widget". Each
 * widget can have specific data loaded from a datasource. Each widget can 
 * be instantiated more than once.
 *
 * @classDescription		This class creates a new portal
 * @return {Portal} Returns a new pages portal
 * @type {Portal}
 * @constructor
 * @allowchild {smartbinding}
 * @addnode components:portal
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.9
 */
jpf.portal = function(pHtmlNode){
	jpf.register(this, "portal", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	/* ********************************************************************
										PROPERTIES
	*********************************************************************/
	
	/* ********************************************************************
										PRIVATE METHODS
	*********************************************************************/

	/* ***********************
				Skin
	************************/

	this.__deInitNode = function(xmlNode, htmlNode){
		if(!htmlNode) return;

		//Remove htmlNodes from tree
		htmlNode.parentNode.removeChild(htmlNode);
	}
	
	this.__updateNode = function(xmlNode, htmlNode){
		this.applyRuleSetOnNode("icon", xmlNode);
	}
	
	this.__moveNode = function(xmlNode, htmlNode){
		if(!htmlNode) return;
	}
	
	/* ***********************
		Keyboard Support
	************************/
	
	//Handler for a plane list
	this.__keyHandler = function(key, ctrlKey, shiftKey, altKey){
		if(!this.selected) return;

		switch(key){
			default:
			break;
		}
	}
	
	/* ***********************
			  CACHING
	************************/
	
	this.__getCurrentFragment = function(){
		//if(!this.value) return false;

		var fragment = jpf.hasDocumentFragment ? document.createDocumentFragment() : new DocumentFragment(); //IE55
		while(this.columns[0].childNodes.length){
			fragment.appendChild(this.columns[0].childNodes[0]);
		}

		return fragment;
	}
	
	this.__setCurrentFragment = function(fragment){
		jpf.hasDocumentFragment ? this.oInt.appendChild(fragment) : fragment.reinsert(this.oInt); //IE55
		
		if(!jpf.window.isFocussed(this)) this.blur();
	}

	this.__findNode = function(cacheNode, id){
		if(!cacheNode) return this.pHtmlDoc.getElementById(id);
		return cacheNode.getElementById(id);
	}
	
	this.__setClearMessage = function(msg){
		var oEmpty = jpf.XMLDatabase.htmlImport(this.__getLayoutNode("Empty"), this.oInt);
		var empty = this.__getLayoutNode("Empty", "caption", oEmpty);
		if(empty) jpf.XMLDatabase.setNodeValue(empty, msg || "");
		if(oEmpty) oEmpty.setAttribute("id", "empty" + this.uniqueId);
	}
	
	this.__removeClearMessage = function(){
		var oEmpty = document.getElementById("empty" + this.uniqueId);
		if(oEmpty) oEmpty.parentNode.removeChild(oEmpty);
		//else this.oInt.innerHTML = ""; //clear if no empty message is supported
	}
	
	this.inherit(jpf.Cache); /** @inherits jpf.Cache */

	/* ***********************
			DATABINDING
	************************/
	
	var portalNode = this;
	function createWidget(xmlNode, widget, dataNode){
		/* Model replacement - needs to be build
		var models = xmlNode.selectNodes("//model/@id");
		for(var i=0;i<models.lenth;i++){
			xmlNode.selectNodes("//node()[@model='" + models[i]
		}
		*/
		
		//also replace widget id's
		
		var name = xmlNode.getAttribute("name");

		if(!jpf.canInsertGlobalCode){
			var nodes = xmlNode.childNodes;
			for(var i=0;i<nodes.length;i++){
				if(nodes[i][jpf.TAGNAME] == "script"){
					nodes[i].firstChild.nodeValue += "\nself." + name + " = " + name + ";";
				}
			}
		}
		
		//Load Widget
		widget.jml = xmlNode;
		widget.loadSkin("default:PortalWindow");
		widget.btnedit = true;
		widget.btnmin = true;
		widget.btnclose = true;
		
		widget.draw();//name
		widget.__loadJML(xmlNode, name);
		widget.setCaption(portalNode.applyRuleSetOnNode("caption", dataNode));
		widget.setIcon(portalNode.applyRuleSetOnNode("icon", dataNode));
		
		if(xmlNode.getAttribute("width")) widget.setWidth(xmlNode.getAttribute("width"));
		else widget.oExt.style.width = "auto";
		//if(xmlNode.getAttribute("height")) widget.setHeight(xmlNode.getAttribute("height"));
		//else widget.oExt.style.height = "auto";
		
		widget.display(0, 0);

		//Create WidgetClass
		if(!self[name]){alert("could not find class '" + name + "'");}
		
		//instantiate class
		var widgetClass = new self[name]();
		portalNode.widgets.push(widgetClass);
		widgetClass.init(dataNode, widget);
	}
	
	this.widgets = [];
	var widget_cache = {}
	this.__add = function(dataNode, Lid, xmlParentNode, htmlParentNode, beforeNode){
		//Build window
		var widget = new jpf.modalwindow(this.columns[this.applyRuleSetOnNode("column", dataNode) || 0], null, null, true);
		widget.parentNode = this;
		widget.inherit(jpf.JmlDomAPI);
		//this.applyRuleSetOnNode("border", xmlNode);
		
		var srcUrl = this.applyRuleSetOnNode("src", dataNode) || "file:" + this.applyRuleSetOnNode("url", dataNode);
		
		if(widget_cache[srcUrl]){
			var xmlNode = widget_cache[srcUrl];
			if(jpf.isSafariOld) xmlNode = jpf.getJmlDocFromString(xmlNode).documentElement;
			createWidget(xmlNode, widget, dataNode);
		}
		else{
			jpf.setModel(srcUrl, {
				load : function(xmlNode){
					if(!xmlNode || this.isLoaded) return;
					
					//hmmm this is not as optimized as I'd like (going throught the xml parser twice)
					var strXml = xmlNode.xml || xmlNode.serialize();
					
					if(jpf.isSafariOld){
						strXml = strXml.replace(/name/, "name='" + xmlNode.getAttribute("name") + "'");
						widget_cache[srcUrl] = strXml;
					}
					else{
						xmlNode = jpf.getJmlDocFromString(strXml).documentElement;
						widget_cache[srcUrl] = xmlNode.cloneNode(true);
					}
					
					createWidget(xmlNode, widget, dataNode);
					this.isLoaded = true;
				},
				
				setModel : function(model, xpath){
					model.register(this, xpath);
				}
			});
		}
	}
	
	this.__fill = function(){
	}
	
	this.addEventListener("onxmlupdate", function(e){
		if(e.action.match(/add|insert|move/)){
			jpf.JMLParser.parseLastPass();
		}
	});
	
	/* ***********************
	  Other Inheritance
	************************/
	
	this.inherit(jpf.Presentation); /** @inherits jpf.Presentation */
	this.inherit(jpf.MultiSelect); /** @inherits jpf.MultiSelect */
	this.inherit(jpf.DataBinding); /** @inherits jpf.DataBinding */
	
	this.__selectDefault = function(xmlNode){
		/*if(this.select(this.getFirstTraverseNode(xmlNode))) return true;
		else{
			var nodes = this.getTraverseNodes(xmlNode);
			for(var i=0;i<nodes.length;i++){
				if(this.__selectDefault(nodes[i])) return true;
			}
		}*/
	}
	
	/* *********
		INIT
	**********/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	var totalWidth = 0;
	this.columns = [];
	this.addColumn = function(size){
		this.__getNewContext("Column");
		var col = jpf.XMLDatabase.htmlImport(this.__getLayoutNode("Column"), this.oInt);
		var id = this.columns.push(col) - 1;
		
		//col.style.left = totalWidth + (size.match(/%/) ? "%" : "px");
		totalWidth += parseFloat(size);
		
		col.style.width = size + (size.match(/%|px|pt/) ? "" : "px");//"33.33%";
		col.isColumn = true;
		col.host = this;
	}
	
	this.draw = function(){
		//Build Main Skin
		this.oExt = this.__getExternal(); 
		this.oInt = this.__getLayoutNode("Main", "container", this.oExt);

		//Create columns
		var cols = (this.jml.getAttribute("columns") || "33.33%,33.33%,33.33%").split(",");
		for(var i=0;i<cols.length;i++){
			this.addColumn(cols[i]);
		}

		//if(this.jml.childNodes.length) this.loadInlineData(this.jml);
		jpf.JMLParser.parseChildren(this.jml, null, this);
		
		if(document.elementFromPointAdd)
			document.elementFromPointAdd(this.oExt);
	}
	
	this.__loadJML = function(x){
		
	}
	
	this.loadInlineData = function(x){
		var hasIcon, strData = [], nodes = x.childNodes;

		for(var i=nodes.length-1;i>=0;i--){
			if(nodes[i].nodeType != 1) continue;
			if(nodes[i][jpf.TAGNAME] != "item") continue;
			
			hasIcon = nodes[i].getAttribute("icon") || "icoAnything.gif";
			strData.unshift("<item " + (hasIcon ? "icon='" + hasIcon + "'" : "") + " value='" + (nodes[i].getAttributeNode("value") ? nodes[i].getAttribute("value") : nodes[i].firstChild.nodeValue) + "'>" + nodes[i].firstChild.nodeValue + "</item>");
			nodes[i].parentNode.removeChild(nodes[i]);
		}

		if(strData.length){
			var sNode = new jpf.SmartBinding(null, jpf.XMLDatabase.getObject("XMLDOM", "<smartbindings xmlns='" + jpf.ns.jpf + "'><bindings><caption select='text()' />" + (hasIcon ? "<icon select='@icon'/>" : "") + "<value select='@value'/><traverse select='item' /></bindings><model><items>" + strData.join("") + "</items></model></smartbindings>").documentElement);
			jpf.JMLParser.addToSbStack(this.uniqueId, sNode);
		}
		
		if(x.childNodes.length)
			jpf.JMLParser.parseChildren(x, null, this);
	}
}

/**
 * @constructor
 */
jpf.PortalWidget = function(){
	this.init = function(xmlSettings, oWidget){
		this.xmlSettings = xmlSettings
		this.oWidget = oWidget;
		
		if(this.__init) this.__init(xmlSettings, oWidget);
	}
}

/*FILEHEAD(/in/Components/Progressbar.js)SIZE(3717)TIME(1203730484247)*/

/**
 * Component graphically representing a percentage value which time based 
 * increases automatically. This component is ofter used to show the progress 
 * of a process. The progress can be either indicative or exact.
 *
 * @classDescription		This class creates a new progressbar
 * @return {Progressbar} Returns a new pages progressbar
 * @type {Progressbar}
 * @constructor
 * @allowchild {smartbinding}
 * @addnode components:progressbar
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.9
 */
jpf.progressbar = function(pHtmlNode){
	jpf.register(this, "progressbar", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;

	/* ***********************
	  		Inheritance
	************************/
	this.inherit(jpf.Presentation); /** @inherits jpf.Presentation */
	
	this.inherit(jpf.DataBinding); /** @inherits jpf.DataBinding */

	/* ********************************************************************
										PROPERTIES
	*********************************************************************/
	
	//Options
	this.focussable = true; // This object can get the focus

	/* ***************
		API
	****************/
	this.value = 0;
	this.min = 0;
	this.max = 1;
	
	this.setCaption = function(value){
		this.oCaption.nodeValue = value;
	}
	
	this.getValue = function(){
		return this.value;
	}
	
	this.setValue = function(value){
		this.value = parseInt(value);
		this.oSlider.style.width = Math.max(0, Math.round((this.oExt.offsetWidth-5) * (value/(this.max-this.min)))) + "px";
		
		this.setCaption(Math.round((value/(this.max-this.min))*100) + "%");
	}
	
	this.clear = function(restart, restart_time){
		this.dispatchEvent("onclear");
		
		clearInterval(this.timer);
		this.setValue(this.min);
		this.oSlider.style.display = "none";
		this.__setStyleClass(this.oExt, "", [this.baseCSSname + "Running"]);
		
		if(restart) this.timer = setInterval("jpf.lookup(" + this.uniqueId + ").start(" + restart_time + ")");
	}
	
	this.start = function(time){
		clearInterval(this.timer);
		this.oSlider.style.display = "block";
		this.timer = setInterval("jpf.lookup(" + this.uniqueId + ").__step()", time || 1000);
		this.__setStyleClass(this.oExt, this.baseCSSname + "Running");
	}
	
	this.__step = function(){
		if(this.value == this.max) return;
		this.setValue(this.value + 1);
	}
	
	this.pause = function(){
		clearInterval(this.timer);
	}
	
	this.stop = function(restart, time, restart_time){
		clearInterval(this.timer);
		this.setValue(this.max);
		this.timer = setTimeout("jpf.lookup(" + this.uniqueId + ").clear(" + restart + ", " + (restart_time || 0) + ")", time || 500);
	}
	
	this.__supportedProperties = ["value"];
	this.__handlePropSet = function(prop, value){
		switch(prop){
			case "value":
				this.setValue(value);
			break;
		}
	}
	
	/* *********
		INIT
	**********/
	
	/* ***************
		Init
	****************/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.draw = function(clear, parentNode, Node, transform){
		//Build Main Skin
		this.oExt = this.__getExternal();
		this.oSlider = this.__getLayoutNode("Main", "progress", this.oExt);
		this.oCaption = this.__getLayoutNode("Main", "caption", this.oExt);
	}
	
	this.__loadJML = function(x){
		//this.setCaption(x.firstChild ? x.firstChild.nodeValue : "");
		this.min = x.getAttribute("min") || 0;
		this.max = x.getAttribute("max") || 100;
		
		if(x.getAttribute("autostart")) this.start();
	}
}

/*FILEHEAD(/in/Components/Radiobutton.js)SIZE(10961)TIME(1203730484247)*/

/**
 * @constructor
 * @private
 */
jpf.radiogroup = function(oChild){
	jpf.register(this, "radiogroup", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = oChild.pHtmlNode
	
	this.inherit(jpf.DataBinding); /** @inherits jpf.DataBinding */

	this.inherit(jpf.Validation); /** @inherits jpf.Validation */
	
	this.inherit(jpf.XForms); /** @inherits jpf.XForms */

	this.radiobuttons = [];
	this.isShowing = true;
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/

	this.addRadio = function(oRB){
		this.radiobuttons.push(oRB);
		if(!this.isShowing){
			oRB.hide();
			//if(oRB.tNode)
				//oRB.tNode.style.display = "none";
		}
	}
	
	this.setValue = function(value){
		for(var i=0;i<this.radiobuttons.length;i++){
			if(this.radiobuttons[i].check_value	== value){
				var oRB = this.radiobuttons[i];
				if(this.current && this.current != oRB) 
					this.current.uncheck();
				oRB.check();
				this.current = oRB;
				break;
			}
		}

		return this.setProperty("value", value);
		//return false;
	}

	this.setCurrent = function(oRB){
		if(this.current && this.current != oRB) this.current.uncheck();
		this.value = oRB.check_value;
		oRB.check();
		this.current = oRB;
	}

	this.getValue = function(){
		return this.current ? this.current.check_value : "";
	}
	
	this.__setCurrent = function(oRB){
		if(this.current) this.current.uncheck();
		this.current = oRB;
		this.value = oRB.check_value;
		this.change(oRB.check_value);
	}
			
	this.disable = function(){
		for(var i=0;i<this.radiobuttons.length;i++){
			this.radiobuttons[i].disable();
		}
	}
	
	this.enable = function(){
		for(var i=0;i<this.radiobuttons.length;i++){
			this.radiobuttons[i].enable();
		}
	}
	
	this.setZIndex = function(value){
		for(var i=0;i<this.radiobuttons.length;i++){
			this.radiobuttons[i].setZIndex(value);
		}
	}
	
	this.show = function(){
		this.isShowing = true;
		for(var i=0;i<this.radiobuttons.length;i++){
			this.radiobuttons[i].show();
			//if(this.radiobuttons[i].tNode)
				//this.radiobuttons[i].tNode.style.display = "block";
		}
	}
	
	this.hide = function(){
		this.isShowing = false;
		for(var i=0;i<this.radiobuttons.length;i++){
			this.radiobuttons[i].hide();
			//if(this.radiobuttons[i].tNode)
				//this.radiobuttons[i].tNode.style.display = "none";
		}
	}
	
	this.focus = this.blur = function(){}
	
	//These should be moved to inside the form
	this.isValid = function(checkRequired){
		if(checkRequired && this.required){
			var value = this.getValue();
			if(!value || value.toString().length == 0) return false;
		}
		
		//for(var i=0;i<vRules.length;i++) if(!eval(vRules[i])) return false;
		//if(this.vRules.length) return eval("(" + this.vRules.join(") && (") + ")");
		return true;
	}
	
	this.init = function(oRB){
		if(this.inited) return;
		
		x = oRB.jml;//.cloneNode(true);//.parentNode.insertBefore(oRB.jml.cloneNode(true), oChild.jml);
		//x.removeAttribute("value");
		this.oExt = oRB.oExt;
		
		//this.processBindclass = oRB.processBindclass;
		//this.processBindclass(x);
		
		this.jml = x;
		
		//this.setCurrent(oRB);
		this.inited = true;
		
		return this;
	}
	
	this.init(oChild);
	
	this.__supportedProperties = ["value"];
	this.__handlePropSet = function(prop, value){
		switch(prop){
			case "value":
				// Set Value
				for(var i=0;i<this.radiobuttons.length;i++){
					if(this.radiobuttons[i].check_value	== value)
						return this.setCurrent(this.radiobuttons[i]);
				}
			break;
		}
	}
	
	this.draw = function(){}
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	//if(self.Validation) this.inherit(jpf.Validation); /** @inherits jpf.Validation */
	this.loadJML(this.jml);
}

/**
 * Component displaying a rectangle which is one of a set of options
 * the user can choose to represent a value.
 *
 * @classDescription		This class creates a new radiobutton
 * @return {Radiobutton} Returns a new radiobutton
 * @type {Radiobutton}
 * @constructor
 * @allowchild {smartbinding}
 * @addnode components:radiobutton
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.9
 */
jpf.radiobutton = function(pHtmlNode){
	jpf.register(this, "radiobutton", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	/* ***********************
	  		Inheritance
	************************/	
	this.inherit(jpf.Presentation); /** @inherits jpf.Presentation */
	
	this.editableParts = {"Main" : [["label","text()"]]};
	
	/* ********************************************************************
										PROPERTIES
	*********************************************************************/
	
	//Options
	this.focussable = true; // This object can get the focus
	//this.inherit(jpf.Validation); /** @inherits jpf.Validation */
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/

	this.setValue = function(value){
		this.check_value = value;
	}
	
	this.getValue = function(){
		return this.checked ? this.check_value : null;
	}
	
	this.setError = function(value){
		this.__setStyleClass(this.oExt, this.baseCSSname + "Error");
	}
	
	this.clearError = function(value){
		this.__setStyleClass(this.oExt, "", [this.baseCSSname + "Error"]);
	}
	
	this.__enable = function(){
		if(this.oInt) this.oInt.disabled = false;
		
		if(this.oExt.tagName.toLowerCase() == "input"){
			this.oExt.onclick = function(e){
				this.host.dispatchEvent("onclick", {htmlEvent : e || event});
				if(this.host.oInt.checked){
					//this.host.oContainer.setValue(this.host.check_value);
					this.host.oContainer.current = this.host;
					this.host.oContainer.change(this.host.check_value);
					//this.host.oContainer.setProperty("value", this.host.check_value);
				}
				//if(this.checked) this.host.oContainer.__setCurrent(this.host);
			}
		}
		else{
			this.oExt.onclick = function(e){
				this.host.dispatchEvent("onclick", {htmlEvent : e || event});
				//this.host.oContainer.setValue(this.host.check_value);
				//this.host.oContainer.__setCurrent(this.host);
				this.host.oContainer.current = this.host;
				this.host.oContainer.change(this.host.check_value);
				//this.host.oContainer.setProperty("value", this.host.check_value);
			}
		}
	}
	
	this.__disable = function(){
		if(this.oInt) this.oInt.disabled = true;
		this.oExt.onclick = null
	}
	
	this.doBgSwitch = function(nr){
		if(this.bgswitch && (this.bgoptions[1] >= nr || nr == 4)){
			if(nr == 4) nr = this.bgoptions[1] + 1;
			
			var strBG = this.bgoptions[0] == "vertical" ? 
				"0 -" + (parseInt(this.bgoptions[2])*(nr-1)) + "px": 
				"-" + (parseInt(this.bgoptions[2])*(nr-1)) + "px 0";

			this.__getLayoutNode("Main", "background", this.oExt).style.backgroundPosition = strBG;
		}
	}
	
	this.check = function(){
		this.__setStyleClass(this.oExt, this.baseCSSname + "Checked");
		this.checked = true;
		if(this.oInt.tagName.toLowerCase() == "input")
			this.oInt.checked = true;
		this.doBgSwitch(2);
	}
	
	this.uncheck = function(){
		this.__setStyleClass(this.oExt, "", [this.baseCSSname + "Checked"]);
		this.checked = false;
		if(this.oInt.tagName.toLowerCase() == "input")
			this.oInt.checked = false;
		this.doBgSwitch(1);
	}
	
	/* ********************************************************************
										PRIVATE METHODS
	*********************************************************************/

	/* ***********************
		Keyboard Support
	************************/
	
	this.keyHandler = function(key){
		this.dispatchEvent("onkeypress", {keyCode : key});
		
		if(key == 13 || key == 32){
			//this.check();
			this.oContainer.current = this;
			this.oContainer.change(this.check_value);
		}
	}
	
	/* ***********************
				Focus
	************************/
	
	this.__focus = function(){
		if(!this.oExt) return;
		if(this.oInt && this.oInt.disabled) return false;
		
		this.__setStyleClass(this.oExt, this.baseCSSname + "Focus");
	}
	
	this.__blur = function(){
		if(!this.oExt) return;
		this.__setStyleClass(this.oExt, "", [this.baseCSSname + "Focus"]);
	}
	
	this.focussable = true;

	/* *********
		INIT
	**********/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.draw = function(){
		//Build Main Skin
		this.oExt = this.__getExternal(null, null, function(oExt){
			var oInt = this.__getLayoutNode("Main", "input", oExt);
			if(oInt.tagName.toLowerCase() == "input") oInt.setAttribute("name", this.jml.getAttribute("id"));
		});
		this.oInt = this.__getLayoutNode("Main", "input", this.oExt);
		
		if(this.jml.firstChild){
			this.tNode = this.__getLayoutNode("Main", "label", this.oExt);
			if(!this.tNode){
				this.tNode = document.createElement("span");
				this.tNode.className = "labelfont";
				pHtmlNode.insertBefore(this.tNode, this.oExt.nextSibling);
			}
			
			this.tNode.innerHTML = this.jml.xml || (this.jml.serialize ? this.jml.serialize() : this.jml.innerHTML);
		}
		
			this.__makeEditable("Main", this.oExt, this.jml);
		
		this.enable();

		if(self[this.jml.getAttribute("id")].tagName != "radiogroup"){
			var oC = new jpf.radiogroup(this);
			oC.name = this.jml.getAttribute("id");
			oC.labelEl = this.labelEl;
			oC.errBox = this.errBox;
			oC.parentNode = this.parentNode;
			
			self[oC.name] = oC;
		}
		
		this.oContainer = self[this.jml.getAttribute("id")];
		this.oContainer.addRadio(this);
		this.processBindclass = function(){}
	}

	this.__loadJML = function(x){
		this.name = x.getAttribute("id");
		this.check_value = x.getAttribute("value");
		
		this.bgswitch = x.getAttribute("bgswitch") ? true : false;
		if(this.bgswitch){
			this.__getLayoutNode("Main", "background", this.oExt).style.backgroundImage = "url(" + this.mediaPath + x.getAttribute("bgswitch") + ")";
			this.__getLayoutNode("Main", "background", this.oExt).style.backgroundRepeat = "no-repeat";

			this.bgoptions = x.getAttribute("bgoptions") ? x.getAttribute("bgoptions").split("\|") : ["vertical", 2, 16];
			if(!this.bgoptions[2]) this.bgoptions[2] = parseInt(this.jml.getAttribute("height"));
		}
		
		this.form = this.oContainer.form;
		
		if(x.getAttribute("checked") == "true") this.oContainer.setValue(this.check_value);//setCurrent(this);
	}
}

/*FILEHEAD(/in/Components/Repeat.js)SIZE(5319)TIME(1203730484247)*/

/*
<j:Repeat traverse="version">
	<j:Label id="lblV1" model="#lstProducts:select:version[1]" skin="default:LabelVersion" dragEnabled="true" dragMoveEnabled="true" bind-attach="root">
		<j:bind select="."><![CDATA[<b>&#8364; {@price}</b>{@title}]]></j:bind>
	</j:Label>
	<j:Button width="100" cssclass="orderButton" onclick="addOrder(1);return false;">Add to order &gt;</j:Button>
</j:Repeat>
*/

/**
 * Component allowing for a set of JML tags to be repeated based
 * on bound data.
 *
 * @classDescription		This class creates a new repeat construct
 * @return {Repeat} Returns a new repeat construct
 * @type {Repeat}
 * @constructor
 * @allowchild {smartbinding}
 * @addnode components:repeat
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.9
 */
jpf.repeat = function(pHtmlNode){
	jpf.register(this, "repeat", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	/* ********************************************************************
										PROPERTIES
	*********************************************************************/

	this.focussable = false; // This object can get the focus
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/
	
	/* ********************************************************************
										PRIVATE METHODS
	*********************************************************************/

	/* ***********************
			DATABINDING
	************************/
	this.inherit(jpf.DataBinding); /** @inherits jpf.DataBinding */
	
	this.caching = true;
	this.nodes = {};
	
	this.addItem = function(xmlNode, beforeNode, nr){
		var Lid = jpf.XMLDatabase.nodeConnect(this.documentId, xmlNode, null, this);
		var htmlNode = this.oExt.insertBefore(document.createElement("div"), beforeNode || null);
		var oItem = this.nodes[Lid] = {childNodes : [], hasFeature : function(){return 0}, oExt : htmlNode};
		
		//Create JML Nodes
		var jmlNode = this.template.cloneNode(true);
		jmlNode.setAttribute("model", "#" + this.name + ":select:(" + this.traverseRule + ")[" + (nr+1) + "]");
		jpf.JMLParser.parseChildren(jmlNode, htmlNode, oItem);
	}
	
	this.removeItem = function(Lid){
		var oItem = this.nodes[Lid];
		var nodes = oItem.childNodes;
		for(var i=0;i<nodes.length;i++){
			nodes[i].destroySelf();	
		}
		jpf.removeNode(oItem.oExt);
		delete this.nodes[Lid];
	}
	
	this.clear = function(){
		var Lid;
		for(Lid in this.nodes){
			this.removeItem(Lid);
		}
	}
	this.getCache = function(){return false;}
	
	this.__load = function(XMLRoot){
		//Add listener to XMLRoot Node
		jpf.XMLDatabase.addNodeListener(XMLRoot, this);
		
		var nodes = this.getTraverseNodes();
		for(var i=0;i<nodes.length;i++){
			this.addItem(nodes[i], null, i);
		}
		
		jpf.JMLParser.parseLastPass();
	}

	/* ******** __XMLUPDATE ***********
		Set properties of control

		INTERFACE:
		this.__xmlUpdate(action, xmlNode [, listenNode [, UndoObj]] );
	****************************/
	this.__xmlUpdate = function(action, xmlNode, listenNode, UndoObj){
		var Lid = xmlNode.getAttribute(jpf.XMLDatabase.xmlIdTag);
		if(!this.isTraverseNode(xmlNode)) return;
		
		var htmlNode = this.nodes[Lid];
		
		//Check Move -- if value node isn't the node that was moved then only perform a normal update
		if(action == "move" && foundNode == startNode){
			var isInThis = jpf.XMLDatabase.isChildOf(this.XMLRoot, xmlNode.parentNode, true);
			var wasInThis = jpf.XMLDatabase.isChildOf(this.XMLRoot, UndoObj.pNode, true);

			//Move if both previous and current position is within this object
			if(isInThis && wasInThis){
				//xmlNode, htmlNode
				//Not supported right now
			}

			//Add if only current position is within this object
			else if(isInThis) action = "add";

			//Remove if only previous position is within this object
			else if(wasInThis) action = "remove";
		}
		else if(action == "move-away"){
			var goesToThis = jpf.XMLDatabase.isChildOf(this.XMLRoot, UndoObj.toPnode, true);
			if(!goesToThis) action = "remove";
		}
		
		if(action == "remove"){
			this.removeItem(Lid);
		}
		else if(action.match(add/insert)){
			this.addItem(xmlNode, null, 5); //HACK, please determine number by position of xmlnode
			jpf.JMLParser.parseLastPass();
		}
		else if(action == "synchronize"){
			
		}
	}
	
	/* *********
		INIT
	**********/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.draw = function(){
		//Build Main Skin
		this.oExt = pHtmlNode.appendChild(document.createElement("div")); 
		this.oInt = this.oExt;
	}
	
	this.__loadJML = function(x){
		this.traverseRule = x.getAttribute("nodeset") || "node()";
		var sNode = new jpf.SmartBinding(null, jpf.getObject("XMLDOM", "<smartbindings xmlns='" + jpf.ns.jpf + "'><bindings><traverse select='" + this.traverseRule.replace(/'/g, "\\'") + "' /></bindings></smartbindings>").documentElement);
		jpf.JMLParser.addToSbStack(this.uniqueId, sNode);
		
		this.template = x;
	}
	
	this.__destroy = function(){
		
	}
}

/*FILEHEAD(/in/Components/RichTextEditor.js)SIZE(7385)TIME(1203730484247)*/

/**
 * Component allowing the user to view and edit text in a rich
 * text format. This allows the user to make certain sections of 
 * the text bold, italic, underlined and apply many other styles.
 *
 * @classDescription		This class creates a new rich text box
 * @return {Richtextbox} Returns a new rich text box
 * @type {Richtextbox}
 * @constructor
 * @allowchild [cdata], {smartbinding}
 * @addnode components:richtextbox
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.9
 */
jpf.richtextbox = function(pHtmlNode){
	jpf.register(this, "richtextbox", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;

	/* ***********************
	  		Inheritance
	************************/
	//this.inherit(jpf.Presentation); /** @inherits jpf.Presentation */
	this.inherit(jpf.DataBinding); /** @inherits jpf.DataBinding */
	
	/* ********************************************************************
										PROPERTIES
	*********************************************************************/
	
	//Options
	this.focussable = true; // This object can get the focus
	this.inherit(jpf.Validation); /** @inherits jpf.Validation */
	this.inherit(jpf.XForms); /** @inherits jpf.XForms */
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/
	
	/* ***************
		API
	****************/
	
	this.getValue = function(textonly){
		var value = this.router.getActiveEditor().getValue();
		return textonly ? value.replace(/<[^>]+>/, "") : value;
	}
	
	this.setValue = function(value){
		if(!this.router) return this.value = value;
		this.router.getActiveEditor().setValue(value);
	}
	
	this.getValueList = function(){
		return this.router.getValue();
	}
	
	this.setValueList = function(){
		this.router.setValue(arguments);
	}
	
	this.setEditorHTML = function(id, html){
		this.router.getEditor(id).setValue(html);
	}
	
	this.getEditor = function(id){
		return this.router.getEditor(id);
	}
	
	this.selectAll = function(){
		this.router.getActiveEditor().selectAll();
	}
	
	this.insertImage = function(path){
		this.router.getActiveEditor().insertImage(path);
	}
	
	/* ***************
		PRIVATE
	****************/
	
	this.exec = function(value, gui, type){
		var Editor = this.router.getActiveEditor();
		if(!Editor) return alert("Please select an area to edit");
		
		//Font Color
		if(value == "ForeColor"){
			var sColor = this.dlgHelper.ChooseColorDlg(this.oDoc.queryCommandValue(value));
			sColor = sColor.toString(16);
			if(sColor.length < 6) sColor = "000000".substring(0,6-sColor.length).concat(sColor);
			this.oDoc.execCommand(value, false, sColor);
		}
		//Execute a standard command
		else this.oDoc.selection.createRange().execCommand(value, true, type);
		
		//Check for possible Local Images
		if(value == "InsertImage") Editor.fixContent();
		
		//Set Buttons
		this.redoButtons();
		
		this.change(this.getValue());
	}
	
	this.redoButtons = function(){
		if(!this.toolbar) return;

		//Sync Buttons with current selection
		var bar = this.toolbar.bars[0].children;
		for(var i=0;i<bar.length;i++){
			if(bar[i].tagName != "Button" || !bar[i].isBoolean) continue;
			bar[i].setValue(this.oDoc.queryCommandValue(bar[i].sValue));
		}
	}
	
	/* ***************
		FOCUS
	****************/
	
	this.keyHandler = function(){}
	
	this.__focus = function(){
		if(this.oExt){
			//this.oExt.contentEditable = true;
			this.oExt.firstChild.contentWindow.focus();
			this.router.focus();
			
			return false;
		}
	}
	
	this.__blur = function(){
		//this.oExt.contentWindow.blur();
		//document.body.click();//focus();
		//this.oDoc.body.focus();
		//this.oExt.contentEditable = false;
	}
	
	this.focussable = true;
	
	/* ***************
		XML Support
	****************/
	
	this.__load = function(XMLRoot, id){
		//Add listener to XMLRoot Node
		jpf.XMLDatabase.addNodeListener(XMLRoot, this);
		
		var value = this.applyRuleSetOnNode("value", XMLRoot);
		this.setValue(value || "");
	}
	
	this.__xmlUpdate = function(action, xmlNode, listenNode, UndoObj){
		//Action Tracker Support
		if(UndoObj) UndoObj.xmlNode = this.XMLRoot;
		
		var value = this.applyRuleSetOnNode("value", this.XMLRoot);
		if(value != this.getValue()) this.setValue(value || "");
	}
	
	this.inherit(jpf.DataBinding); /** @inherits jpf.DataBinding */
	
	/* ***************
		INIT
	****************/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.register = function(o){
		this.router = o;
		this.router.host = this;
		
		if(this.template) this.router.load(this.template);
		else this.router.Init();
		
		if(this.value) this.setValue(this.value);
	}
	
	this.draw = function(clear, parentNode){
		//Setup IFRAME
		this.oExt = this.pHtmlNode.appendChild(document.createElement("DIV"));
		this.oExt.style.width = "100px";
		this.oExt.style.height = "100px";
		this.oExt.innerHTML = "<IFRAME id='me" + this.uniqueId + "' src='empty.html' width='100%' height='100%'></IFRAME>";//));

		//Initialize Iframe
		var win = this.pHtmlDoc.getElementById("me" + this.uniqueId).contentWindow;//jpf.compat.initializeIframe("me" + this.uniqueId, strInit);
		this.oDoc = win.document;
		
		if(jpf.isIE){
			var strInit = "<html><head><style>BODY{background-color:white;} P{margin : 0px;} BODY{background-color:white;margin:0px;overflow:auto;}</style><script>HOST=" + this.uniqueId + "</script><script src='" + BASEPATH + "Library/Widgets/RTEHelper.js'></script><script src='" + BASEPATH + "Library/Widgets/RTETemplateViewer.js'></script></head><body></body>";
			
			this.oDoc.open();
			this.oDoc.write(strInit);
			this.oDoc.close();
		}

		this.oDoc.onkeydown = this.oDoc.onmousedown = this.oDoc.onmouseup = this.oDoc.onclick = function(e){}
		
		if(jpf.isIE){
			document.body.insertAdjacentHTML("beforeend", "<OBJECT id=dlgHelper CLASSID='clsid:3050f819-98b5-11cf-bb82-00aa00bdce0b' width='0px' height='0px'></OBJECT>");
			this.dlgHelper = document.getElementById("dlgHelper");
		}

		//this.oDoc.body.
		this.oExt.firstChild.host = 
		this.oExt.host = this;
		
		//Prevent selection from outside elements
		for(var i=0;i<document.all.length;i++){
			//if(document.all[i].tagName.toLowerCase() != "input" && document.all[i].tagName.toLowerCase() != "select") document.all[i].unselectable = "On";
			//else document.all[i].unselectable = "Off";
		}
	}
	
	this.__loadJML = function(x){
		// XML Options for later: Overflow, Font 
		this.template = x.getAttribute("template") || null;
		this.toolbar = x.getAttribute("toolbar")  ? self[x.getAttribute("toolbar")] : false;

		if(x.firstChild) this.setValue(x.innerHTML || (jpf.isIE ? x.firstChild.xml : x.xml));
	}
	
	this.__destroy = function(){
		this.router.host = null;
		this.oDoc.onkeydown = this.oDoc.onmousedown = this.oDoc.onmouseup = this.oDoc.onclick = null;
		this.oExt.firstChild.host = null;
	}
}

/*FILEHEAD(/in/Components/RTEHelper.js)SIZE(5332)TIME(1203730484247)*/

/*FILEHEAD(/in/Components/RTETemplateViewer.js)SIZE(2172)TIME(1203730484247)*/

/*FILEHEAD(/in/Components/Slider.js)SIZE(9042)TIME(1203730484247)*/

/**
 * Component allowing the user to select a value from a range of
 * values between a minimum and a maximum value. 
 *
 * @classDescription		This class creates a new slider
 * @return {Slider} Returns a new slider
 * @type {Slider}
 * @constructor
 * @allowchild {smartbinding}
 * @addnode components:slider, components:range
 * @alias range
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.9
 */
jpf.range = 
jpf.slider = function(pHtmlNode, tagName){
	jpf.register(this, tagName || "slider", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;

	/* ***********************
	  		Inheritance
	************************/
	this.inherit(jpf.Presentation); /** @inherits jpf.Presentation */
	
	this.inherit(jpf.DataBinding); /** @inherits jpf.DataBinding */
	
	/* ********************************************************************
										PROPERTIES
	*********************************************************************/
	
	//Options
	this.focussable = true; // This object can get the focus
	this.nonSizingHeight = true;
	this.disabled = false; // Object is enabled
	this.inherit(jpf.Validation); /** @inherits jpf.Validation */
	this.inherit(jpf.XForms); /** @inherits jpf.XForms */
	this.value = 0;
	
	this.__supportedProperties = ["value"];
	this.__handlePropSet = function(prop, value){
		switch(prop){
			case "value":
				this.value = Math.max(this.min, Math.min(this.max, value));
				var multiplier = (value-this.min)/(this.max-this.min);

				if(this.direction == "horizontal"){
					var max = (this.oContainer.offsetWidth - jpf.compat.getWidthDiff(this.oContainer)) - this.oSlider.offsetWidth;
					var min = parseInt(jpf.compat.getBox(jpf.compat.getStyle(this.oContainer, "padding"))[3]);
					this.oSlider.style.left = (((max-min)*multiplier) + min) + "px";
				}
				else{
					var max = (this.oContainer.offsetHeight - jpf.compat.getHeightDiff(this.oContainer)) - this.oSlider.offsetHeight;
					var min = parseInt(jpf.compat.getBox(jpf.compat.getStyle(this.oContainer, "padding"))[0]);
					this.oSlider.style.top = (((max-min)*(1-multiplier)) + min) + "px";
				}
				
				if(this.oLabel){
					//Percentage
					if(this.mask == "%"){
						this.oLabel.nodeValue = Math.round(multiplier * 100) + "%";
					}
					//Number
					else if(this.mask == "#"){
						status = this.value;
						this.oLabel.nodeValue = this.slideStep ? (Math.round(this.value / this.slideStep) * this.slideStep) : this.value;
					}
					//Lookup
					else{
						this.oLabel.nodeValue = this.mask[Math.round(value - this.min)/(this.slideStep||1)]; //optional floor ??	
					}
						
				}
			break;
		}
	}
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/
	
	this.setValue = function(value){
		this.setProperty("value", value);
	}
	
	this.getValue = function(){
		return this.slideStep ? Math.round(parseInt(this.value) / this.slideStep) * this.slideStep : this.value;
		
		if(this.direction == "horizontal"){
			var max = (this.oContainer.offsetWidth - jpf.compat.getWidthDiff(this.oContainer)) - this.oSlider.offsetWidth;
			var min = parseInt(jpf.compat.getBox(jpf.compat.getStyle(this.oContainer, "padding"))[3]);
			var value = (this.oSlider.style.left-min)/(max-min);
		}
		else{
			var max = (this.oContainer.offsetHeight - jpf.compat.getHeightDiff(this.oContainer)) - this.oSlider.offsetHeight;
			var min = parseInt(jpf.compat.getBox(jpf.compat.getStyle(this.oContainer, "padding"))[0]);
			var value = (this.oSlider.style.top-min)/(max-min);
		}

		return value;
	}
	
	/* ***********************
		Keyboard Support
	************************/
	
	//Handler for a plane list
	this.keyHandler = function(key, ctrlKey, shiftKey, altKey){
		switch(key){
			case 37:
			//LEFT
				if(this.direction != "horizontal") return;
				this.setValue(this.value - (ctrlKey ? 0.01 : 0.1));
			break;
			case 38:
			//UP
				if(this.direction != "vertical") return;
				this.setValue(this.value + (ctrlKey ? 0.01 : 0.1));
			break;
			case 39:
			//RIGHT
				if(this.direction != "horizontal") return;
				this.setValue(this.value + (ctrlKey ? 0.01 : 0.1));
			break;
			case 40:
			//DOWN
				if(this.direction != "vertical") return;
				this.setValue(this.value - (ctrlKey ? 0.01 : 0.1));
			break;
			default: 
			return;
		}
		
		return false;
	}
	
	/* ***********************
				INIT
	************************/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.draw = function(){
		//Build Main Skin
		this.oExt = this.__getExternal();
		this.oLabel = this.__getLayoutNode("Main", "status", this.oExt);
		this.oMarkers = this.__getLayoutNode("Main", "markers", this.oExt);
		this.oSlider = this.__getLayoutNode("Main", "slider", this.oExt);
		this.oInt = this.oContainer = this.__getLayoutNode("Main", "container", this.oExt);
		this.oSlider.host = this;
		
		this.oSlider.style.left = (parseInt(jpf.compat.getBox(jpf.compat.getStyle(this.oExt, "padding"))[3])) + "px";
		
		this.oSlider.onmousedown = function(e){
			if(this.host.disabled) return false;
			
			if(!e) e = event;
			document.dragNode = this;

			this.x = (e.clientX || e.x);
			this.y = (e.clientY || e.y);
			this.stX = this.offsetLeft;
			this.siX = this.offsetWidth
			this.stY = this.offsetTop;
			this.siY = this.offsetheight
			
			if(this.host.direction == "horizontal"){
				this.max = parseInt(jpf.compat.getStyle(this.host.oContainer, "width")) - this.offsetWidth;
				this.min = parseInt(jpf.compat.getBox(jpf.compat.getStyle(this.host.oContainer, "padding"))[3]);
			}
			else{
				this.max = parseInt(jpf.compat.getStyle(this.host.oContainer, "height")) - this.offsetHeight;
				this.min = parseInt(jpf.compat.getBox(jpf.compat.getStyle(this.host.oContainer, "padding"))[0]);
			}
			
			this.host.__setStyleClass(this, "btndown", ["btnover"]);
			
			jpf.DragMode.mode = true;
			
			function getValue(o, e, slideDiscreet){
				var to = o.host.direction == "horizontal" ? (e.clientX || e.x) - o.x + o.stX : (e.clientY || e.y) - o.y + o.stY;
				to = (to > o.max ? o.max : (to < o.min ? o.min : to));
				var value = (((to - o.min)*100/(o.max - o.min)/100)*(o.host.max-o.host.min))+o.host.min;
				
				value = slideDiscreet ? (Math.round(value / slideDiscreet) * slideDiscreet) : value
				value = o.host.direction == "horizontal" ? value : 1-value

				return value;
			}
			
			document.onmousemove = function(e){
				var o = this.dragNode;
				this.value = -1; //reset value
				o.host.setValue(getValue(o, e || event, o.host.slideDiscreet));
				//o.host.__handlePropSet("value", getValue(o, e || event, o.host.slideDiscreet));
			}
			
			document.onmouseup = function(e){
				var o = this.dragNode;
				this.dragNode = null;
				o.onmouseout();
				
				this.value = -1; //reset value
				o.host.change(getValue(o, e || event, o.host.slideDiscreet || o.host.slideSnap));
				
				document.onmousemove = null;
				document.onmouseup = null;
				
				jpf.DragMode.mode = null;
			}
			
			//event.cancelBubble = true;
			return false;
		}
		
		this.oSlider.onmouseup = 
		this.oSlider.onmouseover = function(){
			if(document.dragNode != this) this.host.__setStyleClass(this, "btnover", ["btndown"]);
		}
		
		this.oSlider.onmouseout = function(){
			if(document.dragNode != this) this.host.__setStyleClass(this, "", ["btndown", "btnover"]);
		}
	}
	
	this.__loadJML = function(x){
		this.direction = x.getAttribute("direction") || "horizontal";
		this.slideStep = parseInt(x.getAttribute("step")) || 0;
		this.mask = x.getAttribute("mask") || "%";
		if(!this.mask.match(/^(%|#)$/)) this.mask = x.getAttribute("mask").split(";");
		this.min = parseInt(x.getAttribute("min")) || 0;
		this.max = parseInt(x.getAttribute("max")) || 6;
		this.slideDiscreet = x.getAttribute("slide") == "discreet";
		this.slideSnap = x.getAttribute("slide") == "snap";
		
		this.__handlePropSet("value", this.min);
		
		//Set step 
		if(this.slideStep){
			var count = (this.max-this.min)/this.slideStep;
			for(var o,nodes=[],i=0;i<count+1;i++){
				this.__getNewContext("Marker");
				o = this.__getLayoutNode("Marker");
				var leftPos = Math.max(0, (i*(1/count)*100) - 1);
				o.setAttribute("style", "left:" + leftPos + "%");
				nodes.push(o);
			}
			
			jpf.XMLDatabase.htmlImport(nodes, this.oMarkers);
		}
		
		jpf.JMLParser.parseChildren(this.jml, null, this);
	}
	
	this.__destroy = function(){
		this.oSlider.host = null;
		this.oSlider.onmousedown = null;
		this.oSlider.onmouseup = null;
		this.oSlider.onmouseover = null;
		this.oSlider.onmouseout = null;
	}
}

/*FILEHEAD(/in/Components/Sourceedit.js)SIZE(8207)TIME(1203730484247)*/

//IDEAS:
// Ctrl-E delete line
// Ctrl-R replace function.. regexp support

/**
 * @constructor
 */
jpf.sourceedit = function(pHtmlNode){
	jpf.register(this, "sourceedit", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	/* ***********************
	  		Inheritance
	************************/
	this.inherit(jpf.Presentation); /** @inherits jpf.Presentation */
	
	this.inherit(jpf.DataBinding); /** @inherits jpf.DataBinding */
	
	/* ********************************************************************
										PROPERTIES
	*********************************************************************/
	
	//Options
	this.focussable = true; // This object can get the focus
	this.disabled = false; // Object is enabled
	this.value = null;
	this.inherit(jpf.Validation); /** @inherits jpf.Validation */
	this.inherit(jpf.XForms); /** @inherits jpf.XForms */
	
	this.toolbars = new Array();
	this.buttons = new Array();
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/
	
	//API
	
	this.WordWrap = function(){
		this.oTxt.style.width = "100%";	
	}
	
	this.setValue = function(value){
		if(jpf.hasInnerText) this.oTxt.innerText = value;
		else this.oTxt.value = value;	
	}
	
	this.getValue = function(){
		return this.oTxt.innerText;
	}
	
	this.find = function(text, noshow){
		/*
			scope
			
			0 Default. Match partial words. 
			1 Match backwards. 
			2 Match whole words only. 
			4 Match case. 
			131072 Match bytes. 
			536870912 Match diacritical marks. 
			1073741824 Match Kashida character. 
			2147483648 Match AlefHamza character. 

		*/

		var o = this.oTxt;
		o.focus();
		var r = document.selection.createRange();//o.createTextRange();
		r.collapse(false);
		var found = r.findText(text, 100000);
		
		if(found) r.select();
		else{
			//eigenlijk mooier om bovenaan te beginnen.. maar later...
			var r = document.selection.createRange();
			r.select();
			if(!noshow) this.showSearch(true);
		}
	}
	
	this.gotoLineNumber = function(ln, selectLine){
		var o = this.oTxt;
		o.focus();
		
		var r = o.createTextRange();//document.selection.createRange();
		r.moveEnd("character", 1);
		
		var ar = o.innerText.split("\n");
		var rs = ar.slice(0, ln);
		for(var i=0;i<rs.length;i++) r.findText(rs[i]);
		if(!selectLine) r.collapse();
		r.select();
		
		if(this.onshowlinenr) this.onshowlinenr(this.getLineNumber());
	}
	
	this.getLineNumber = function(){
		var o = this.oTxt;

		var r = document.selection.createRange();
		r.moveEnd("character", 1);
		var q = r.duplicate();//o.createTextRange();
		q.moveToElementText(o);
		//q.collapse();
		q.setEndPoint("EndToEnd", r);

		var str = q.text;
		return str.split("\n").length + (r.text == "" ? 1 : 0);
	}
	
	this.selectAll = function(){
		this.oTxt.select();
	}
	
	/* ***********************
				FOCUS
	************************/
	
	this.__focus = function(){
		if(document.activeElement == this.oTxt) return;
		//return; //TEMP SOLUTION
		try{
			this.oTxt.focus();
		}catch(e){}
	}
	
	this.__blur = function(){
		this.oTxt.blur();
	}
	
	this.focussable = true;
	
	/* ***********************
			Databinding
	************************/
	
	this.__xmlUpdate = function(action, xmlNode, listenNode, UndoObj){
		//Action Tracker Support
		if(UndoObj) UndoObj.xmlNode = this.XMLRoot;
		
		//Refresh Properties
		//var value = this.applyRuleSetOnNode("value", this.XMLRoot);
		//if(value != this.getValue()) this.setValue(value || "");
		
		var value = this.applyRuleSetOnNode("value", this.XMLRoot);
		if((value || typeof value == "string")){
			if(value != this.getValue()) this.setValue(value);
		}
		else this.setValue("");
	}
	
	this.__load = function(XMLRoot, id){
		//Add listener to XMLRoot Node
		jpf.XMLDatabase.addNodeListener(XMLRoot, this);
		
		var value = (this.bindingRules ? this.applyRuleSetOnNode("value", XMLRoot) : (this.jml.firstChild ? this.jml.firstChild.nodeValue : false));

		if((value || typeof value == "string")){
			if(value != this.getValue()) this.setValue(value);
		}
		else this.setValue("");
	}
	
	/* ********************************************************************
										PRIVATE METHODS
	*********************************************************************/
	
	/* ***********************
		SEARCH|GOTO|KEYBOARD
	************************/
	
	this.lastSearch = "";
	this.lastGoto = "";
	
	this.showSearch = function(noclear){
		this.oFind.className = this.baseCSSname + "_find";
		if(!noclear) this.oFindInput.value = this.lastSearch;
		this.oFindLabel.nodeValue = "Search";
		
		//setting function
		this.oFindInput.onkeydown = new Function('e', 'if(!e) e = event;if(e.keyCode==13){jpf.lookup('+this.uniqueId+').find(this.value);return false}')
		
		this.showBox();
	}
	
	this.showGoto = function(){
		this.oFind.className = this.baseCSSname + "_goto";
		this.oFindInput.value = this.lastGoto;
		this.oFindLabel.nodeValue = "Goto Line:";
		
		//setting function
		this.oFindInput.onkeydown = new Function('e', 'if(!e) e = event;if(e.keyCode==13){jpf.lookup('+this.uniqueId+').gotoLineNumber(this.value);return false}')
		
		this.showBox();
	}
	
	this.showBox = function(){
		this.oFind.style.top = this.oExt.scrollTop + 15;
		
		this.oFind.style.display = "block";
		this.oFindInput.select();
		this.oFindInput.focus();
	}
	
	this.hideBox = function(){
		this.oFind.style.display = "none";
		
		if(this.oFindLabel.innerHTML == "Search")
			this.lastSearch = this.oFindInput.value;
		else
			this.lastGoto = this.oFindInput.value;
	}
	
	this.keyHandler = function(key, ctrlKey){
		if(key == 114 && this.lastSearch){
			this.find(this.lastSearch, true);
			return false;
		}
		else if(ctrlKey && key == 70){
			if(!document.selection) return false;
			
			//Find
			this.showSearch();
			return false;
		}
		else if(ctrlKey && key == 71){
			if(!document.selection) return false;
			
			//Goto Line
			this.showGoto();
			return false;
		}
		else if(key == 27){
			this.hideBox();
			return false;
		}
		else if(key == 9){
			if(!jpf.hasMsRangeObject) return;
			var r = document.selection.createRange();
			r.text = "	";
			return false;
		}
	}
	
	/* ***************
		Init
	****************/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.draw = function(){
		//Build Main Skin
		this.oExt = this.__getExternal();
		this.oTxt = this.__getLayoutNode("Main", "input", this.oExt);
		this.oTxt.host = this;
		
		this.oFind = jpf.XMLDatabase.htmlImport(this.__getLayoutNode("FindPopup"), this.oExt);
		this.oFindLabel = this.__getLayoutNode("FindPopup", "label", this.oFind);
		this.oFindInput = this.__getLayoutNode("FindPopup", "input", this.oFind);

		//this.oExt.onmousedown = 
		this.oExt.onfocus = function(e){
			if(!e) e = event;
			
			if(e.offsetX < this.offsetWidth - 23 && e.offsetY < this.offsetHeight - 23){
				setTimeout('jpf.lookup(' + this.host.uniqueId + ').focus()', 100);
				e.cancelBubble = true;
			}
		}
		
		this.oTxt.onselectstart = function(e){if(!e) e = event;e.cancelBubble = true};
		this.oTxt.onmousemove = 
		this.oTxt.onmouseover = function(e){if(!e) e = event;e.cancelBubble = true;}
		
		this.oTxt.onmousedown = function(e){
			if(!e) e = event;
			
			jpf.window.__focus(this.host);
			e.cancelBubble = true;	
		}
		
		this.oTxt.onmouseup = 
		this.oTxt.onkeydown = 
		this.oTxt.onkeyup = function(e){
			if(!e) e = event;
			
			if(this.host.onshowlinenr) this.host.onshowlinenr(this.host.getLineNumber());
			if(e.keyCode == 9) return false;
		}
	}
	
	this.__loadJML = function(x){
		this.setValue(x.firstChild ? x.firstChild.nodeValue : "");
		
		this.__focus();
	}
}

/*FILEHEAD(/in/Components/Splitter.js)SIZE(12122)TIME(1213483123975)*/

/**
 * @constructor
 * @private
 */
jpf.splitter = function(pHtmlNode){
	jpf.register(this, "splitter", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	var jmlNode = this;
	this.focussable = true; // This object can get the focus
	
	/* ***********************
	  		Inheritance
	************************/
	this.inherit(jpf.Presentation); /** @inherits jpf.Presentation */
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/
	
	this.update = function(){
		//Optimize this to not recalc for certain cases
		var b = this.type == "vertical" ?
			{fsize : "fwidth", size : "width", offsetPos : "offsetLeft", offsetSize : "offsetWidth", pos : "left"} : 
			{fsize : "fheight", size : "height", offsetPos : "offsetTop", offsetSize : "offsetHeight", pos : "top"};
		
		var jmlNode = this.refNode;
		var htmlNode = this.refHtml;
		
		var v = jpf.layoutServer.vars;
		var oItem = this.oItem;
		
		var itemStart = htmlNode ? htmlNode[b.offsetPos] : v[b.pos + "_" + oItem.id];
		var itemSize = htmlNode ? htmlNode[b.offsetSize] : v[b.size + "_" + oItem.id];
		
		var row = oItem.parent.children;
		for(var z=0,i=0;i<row.length;i++) if(!row[i][b.fsize]) z++;

		if(!oItem[b.fsize] && z > 1){
			for(var rTotal=0, rSize=0, i=oItem.stackId+1;i<row.length;i++){
				if(!row[i][b.fsize]){
					rTotal += row[i].weight || 1;
					rSize += (row[i].node ? row[i].oHtml[b.offsetSize] : v[b.size + "_" + row[i].id]);
				}
			}
			
			var diff = this.oExt[b.offsetPos] - itemStart - itemSize;
			var rEach = (rSize - diff)/rTotal;
			
			for(var i=0;i<oItem.stackId;i++){
				if(!row[i][b.fsize]) row[i].original.weight = (row[i].node ? row[i].oHtml[b.offsetSize] : v[b.size + "_" + row[i].id]) / rEach;
			}

			oItem.original.weight = (itemSize + diff) / rEach
			needRecalc = true;
		}
		else{
			var isNumber = oItem[b.fsize] ? oItem[b.fsize].match(/^\d+$/) : false;
			var isPercentage = oItem[b.fsize] ? oItem[b.fsize].match(/^([\d\.]+)\%$/) : false;
			if(isNumber || isPercentage || !oItem[b.fsize]){
				var diff = this.oExt[b.offsetPos] - itemStart - itemSize;
				var newHeight = this.oExt[b.offsetPos] - itemStart;
				
				for(var total=0, size=0, i=oItem.stackId+1;i<row.length;i++){
					if(!row[i][b.fsize]){
						total += row[i].weight || 1;
						size += (row[i].node ? row[i].oHtml[b.offsetSize] : v[b.size + "_" + row[i].id]);
					}
				}
				
				if(total > 0){
					var ratio = ((size-diff)/total)/(size/total);
					for(var i=oItem.stackId+1;i<row.length;i++)
						row[i].original.weight = ratio * (row[i].weight || 1);
				}
				else{
					for(var i=oItem.stackId+1;i<row.length;i++){
						if(row[i][b.fsize].match(/^\d+$/)){
							//should check for max here as well
							var nHeight = (row[i].node ? row[i].oHtml[b.offsetSize] : v[b.size + "_" + row[i].id]) - diff;
							row[i].original[b.fsize] = "" + Math.max(0, nHeight, row[i].minheight || 0);
							if(row[i][b.fsize] - nHeight != 0) diff = row[i][b.fsize] - nHeight;
							else break;
						}
						else if(row[i][b.fsize].match(/^([\d\.]+)\%$/)){
							var nHeight = (row[i].node ? row[i].oHtml[b.offsetSize] : v[b.size + "_" + row[i].id]) - diff;
							row[i].original[b.fsize] = Math.max(0, ((parseFloat(RegExp.$1)/(row[i].node ? row[i].oHtml[b.offsetSize] : v[b.size + "_" + row[i].id])) * nHeight)) + "%";
							//check fheight
							break;
						}
					}
				}
				
				if(oItem.original[b.fsize]){
					oItem.original[b.fsize] = isPercentage ? 
						((parseFloat(isPercentage[1])/itemSize) * newHeight) + "%" :
						"" + newHeight;
				}
				
				//if(total > 0  || isPercentage) needRecalc = true;
				needRecalc = true;
			}
		}
	
		if(needRecalc){
			jpf.layoutServer.compile(this.oExt.parentNode);
			jpf.layoutServer.activateRules(this.oExt.parentNode);
			
			return;
		}

		jpf.layoutServer.forceResize(this.oExt.parentNode);
	}
	
	this.onmouseup = function(){
		jmlNode.__setStyleClass(jmlNode.oExt, "", ["moving"]);
		jpf.Plane.hide();
		
		jmlNode.update();
		jmlNode.__setStyleClass(document.body, "", ["n-resize", "w-resize"]);
		
		jpf.DragMode.clear();
	}
	
	this.onmousemove = function(e){
		if(!e) e = event;

		if(jmlNode.type == "vertical"){
			if(e.clientX >= 0){
				var pos = jpf.compat.getAbsolutePosition(jmlNode.oExt.offsetParent);
				jmlNode.oExt.style.left = (Math.min(jmlNode.max, Math.max(jmlNode.min, (e.clientX - pos[0]) - jmlNode.tx))) + "px";
			}
		}
		else{
			if(e.clientY >= 0){
				var pos = jpf.compat.getAbsolutePosition(jmlNode.oExt.offsetParent);
				jmlNode.oExt.style.top = (Math.min(jmlNode.max, Math.max(jmlNode.min, (e.clientY - pos[1]) - jmlNode.ty))) + "px";
			}
		}
		
		e.returnValue = false;
		e.cancelBubble = true;
	}

	/* *********
		INIT
	**********/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	var lastinit, sizeArr, verdiff, hordiff;
	this.init = function(size, refNode, oItem){
		/*var li = size + min + max + (refNode.uniqueId || refNode);
		if(li == lastinit) return;
		lastinit = li;*/
		this.min = 0;
		this.max = 1000000;
		this.size = parseInt(size) || 3;
		this.refNode = null;
		this.refHtml = null;
		
		var pNode;
		if(refNode){
			if(typeof refNode != "object") refNode = jpf.lookup(refNode);
			this.refNode = refNode;
			this.refHtml = this.refNode.oExt;
			pNode = this.refHtml.parentNode;

			oItem = refNode.aData.calcData;
		}
		else pNode = oItem.pHtml;
		
		this.oItem = oItem;
		if(pNode && pNode != this.oExt.parentNode) pNode.appendChild(this.oExt);
		
		var diff = jpf.compat.getDiff(this.oExt);
		verdiff = diff[0];
		hordiff = diff[1];
		sizeArr = [];
		
		this.type = oItem.parent.vbox ? "horizontal" : "vertical";
		
		var layout = jpf.layoutServer.get(this.oExt.parentNode).layout;
		var name = "splitter" + this.uniqueId;
		layout.addRule("var " + name + " = jpf.lookup(" + this.uniqueId + ").oExt");
		
		var vleft = [name + ".style.left = "];
		var vtop = [name + ".style.top = "];
		var vwidth = [name + ".style.width = -" + hordiff + " + "];
		var vheight = [name + ".style.height = -" + verdiff + " + "];
		var oNext = oItem.parent.children[oItem.stackId+1];
		
		if(this.type == "horizontal"){
			vwidth.push("Math.max(");
			if(oItem.node){
				vleft.push(oItem.id + ".offsetLeft");
				vtop.push(oItem.id + ".offsetTop + " + oItem.id + ".offsetHeight");
				vwidth.push(oItem.id + ".offsetWidth");
			}
			else{
				vleft.push("v.left_" + oItem.id);
				vtop.push("v.top_" + oItem.id + " + v.height_" + oItem.id);
				vwidth.push("v.width_" + oItem.id);
			}
			vwidth.push(",", oNext.node ? oNext.id + ".offsetWidth" : "v.width_" + oNext.id, ")");
			
			layout.addRule(vwidth.join(""));
			this.oExt.style.height = (oItem.splitter - hordiff) + "px";
		}
		else{
			vheight.push("Math.max(");
			if(oItem.node){
				vleft.push(oItem.id + ".offsetLeft + " + oItem.id + ".offsetWidth");
				vtop.push(oItem.id + ".offsetTop");
				vheight.push(oItem.id + ".offsetHeight");
			}
			else{
				vleft.push("v.left_" + oItem.id + " + v.width_" + oItem.id);
				vtop.push("v.top_" + oItem.id);
				vheight.push("v.height_" + oItem.id);
			}
			vheight.push(",", oNext.node ? oNext.id + ".offsetHeight" : "v.height_" + oNext.id, ")");
			
			layout.addRule(vheight.join(""));
			this.oExt.style.width = (oItem.splitter - hordiff) + "px";
		}
		
		layout.addRule(vleft.join(""));
		layout.addRule(vtop.join(""));

		//if(!jpf.p) jpf.p = new jpf.ProfilerClass();
		//jpf.p.start();
 		
 		//Determine min and max
 		var row = oItem.parent.children;
		if(this.type == "vertical"){
			layout.addRule(name + ".host.min = " + (oItem.node ? "document.getElementById('" + oItem.id + "').offsetLeft" : "v.left_" + oItem.id) + " + " + parseInt(oItem.minwidth || oItem.childminwidth || 10));

			var max = [], extra = [];
			for(var hasRest=false,i=oItem.stackId+1;i<row.length;i++){
				if(!row[i].fwidth) hasRest = true;
			}
			
			for(var d, i=oItem.stackId+1;i<row.length;i++){
				d = row[i];
				
				//should take care here of minwidth due to html padding and html borders
				if(d.minwidth || d.childminheight) max.push(parseInt(d.minwidth || d.childminheight));
				else if(d.fwidth){
					if(!hasRest && i == oItem.stackId+1) max.push(10);
					else if(d.fwidth.indexOf("%") != -1)
						max.push("(" + d.parent.innerspace + ") * " + (parseFloat(d.fwidth)/100));
					else max.push(d.fwidth);
				}
				else max.push(10);
				
				max.push(d.edgeMargin);
			}
			
			layout.addRule(name + ".host.max = v.left_" + oItem.parent.id + " + v.width_" + oItem.parent.id + " - (" + (max.join("+")||0) + ")");
		}
		else{
			layout.addRule(name + ".host.min = " + (oItem.node ? "document.getElementById('" + oItem.id + "').offsetTop" : "v.top_" + oItem.id) + " + " + parseInt(oItem.minheight || oItem.childminheight || 10));

			var max = [], extra = [];
			for(var hasRest=false,i=oItem.stackId+1;i<row.length;i++){
				if(!row[i].fheight) hasRest = true;
			}
			
			//This line prevents splitters from sizing minimized items without a rest
			if(!hasRest && oNext.state > 0) return this.oExt.parentNode.removeChild(this.oExt);
			
			for(var d, i=oItem.stackId+1;i<row.length;i++){
				d = row[i];
				
				//should take care here of minwidth due to html padding and html borders
				if(d.minheight || d.childminheight) max.push(parseInt(d.minheight || d.childminheight));
				else if(d.fheight){
					if(!hasRest && i == oItem.stackId+1) max.push(10);
					else if(d.fheight.indexOf("%") != -1)
						max.push("(" + d.parent.innerspace + ") * " + (parseFloat(d.fheight)/100));
					else max.push(d.fheight);
				}
				else max.push(10);
				
				max.push(d.edgeMargin);
			}

			layout.addRule(name + ".host.max = v.top_" + oItem.parent.id + " + v.height_" + oItem.parent.id + " - (" + (max.join("+")||0) + ")");
		}

		//jpf.p.stop();
		//document.title = jpf.p.totalTime;	
		
		this.__setStyleClass(this.oExt, this.type, [this.type == "horizontal" ? "vertical" : "horizontal"]);
		
		if(this.type == "vertical") this.__setStyleClass(this.oExt, "w-resize", ["n-resize"]);
		else this.__setStyleClass(this.oExt, "n-resize", ["w-resize"]);

		return this;
	}
	
	this.draw = function(){
		//Build Main Skin
		this.oExt = this.__getExternal();

		this.oExt.onmousedown = function(e){
			if(!e) e = event;
			
			var pos = jpf.compat.getAbsolutePosition(this);
			if(jmlNode.type == "vertical") jmlNode.tx = e.clientX - pos[0];
			else jmlNode.ty = e.clientY - pos[1];
			jmlNode.startPos = jmlNode.type == "vertical" ? this.offsetLeft : this.offsetTop;
			
			e.returnValue = false;
			e.cancelBubble = true;
			
			jpf.Plane.show(this);
			jmlNode.__setStyleClass(this, "moving");
			
			jmlNode.__setStyleClass(document.body, jmlNode.type == "vertical" ? "w-resize" : "n-resize", [jmlNode.type == "vertical" ? "n-resize" : "w-resize"]);
			jpf.DragMode.setMode("splitter" + jmlNode.uniqueId);
		}
	}
		
	this.__loadJML = function(x){
		if(x.getAttribute("left") || x.getAttribute("top")){
			var O1 = x.getAttribute("left") || x.getAttribute("top");
			var O2 = x.getAttribute("right") || x.getAttribute("bottom");
			O1 = O1.split(/\s*,\s*/);
			O2 = O2.split(/\s*,\s*/);
			
			for(var i=0;i<O1.length;i++) O1[i] = O1[i];
			for(var i=0;i<O2.length;i++) O2[i] = O2[i];
				
			//Not a perfect hack, but ok, for now
			setTimeout(function(){
				jmlNode.init(x.getAttribute("type"), x.getAttribute("size"), x.getAttribute("min"), x.getAttribute("max"), x.getAttribute("change"), O1, O2);
			});
		}
	}
	
	jpf.Plane.init();
	jpf.DragMode.defineMode("splitter" + this.uniqueId, this);
	
	this.__destroy = function(){
		jpf.DragMode.removeMode("splitter" + this.uniqueId);
	}
}
/*FILEHEAD(/in/Components/State.js)SIZE(4641)TIME(1203730484247)*/

jpf.StateServer = {
	states : {},
	groups : {},
	locs : {},
	
	removeGroup : function(name, elState){
		this.groups[name].remove(elState);
		if(!this.groups[name].length){
			self[name].destroy();
			self[name] = null;
			delete this.groups[name];
		}
	},
	
	addGroup : function(name, elState){
		if(!this.groups[name]){
			this.groups[name] = [];
			self[name] = new jpf.state();
			self[name].name = name;
			self[name].toggle = function(){
				for(var next=0,i=0;i<jpf.StateServer.groups[name].length;i++){
					if(jpf.StateServer.groups[name][i].active){
						next = i+1;
						break;
					}
				}
				
				jpf.StateServer.groups[name][next == jpf.StateServer.groups[name].length ? 0 : next].activate();
			}
		}
		
		this.groups[name].push(elState);
	},
	
	removeState : function(elState){
		delete this.states[elState.name];
	},
	
	addState : function(elState){
		this.states[elState.name] = elState;
	}
}

/**
 * Component that sets the name of a state of the application. 
 * This state is set by specifying the state of individual constituants 
 * and variables which can be used in dynamic properties of JML components.
 *
 * @classDescription		This class creates a new state
 * @return {State} Returns a new state
 * @type {State}
 * @constructor
 * @addnode global:state
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.9
 */
jpf.state = function(pHtmlNode){
	jpf.register(this, "state", NOGUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	/* ***********************
	  		Inheritance
	************************/
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/
	
	this.setValue = function(value){
		this.active = 9999;
		this.setProperty("active", value);
	}
	
	/*this.getValue = function(){
		return this.value;
	}*/
	
	//this group stuff can prolly be more optimized
	this.activate = function(){
		this.active = 9999;
		this.setProperty("active", true);
	}
	
	this.deactivate = function(){
		this.setProperty("active", false);
	}
	
	/* *********
		INIT
	**********/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.__supportedProperties = ["active"];
	this.__handlePropSet = function(prop, value){
		if(prop == "active"){
			//Activate State
			if(jpf.isTrue(value)){
				if(this.group){
					var nodes = jpf.StateServer.groups[this.group];
					for(var i=0;i<nodes.length;i++){
						if(nodes[i] != this && nodes[i].active !== false)
							nodes[i].deactivate();
					}
				}
				
				var q = this.__signalElements;
				for(var i=0;i<q.length;i++){
					if(!self[q[i][0]] || !self[q[i][0]].setProperty){
						throw new Error(0, jpf.formErrorString(1013, this, "Setting State", "Could not find object to give state: '" + q[i][0] + "' on property '" + q[i][1] + "'"));
					}
					
					self[q[i][0]].setProperty(q[i][1], this[q[i].join(".")]); 
				}
				
				if(this.group){
					var attr = this.jml.attributes;
					for(var i=0;i<attr.length;i++){
						if(attr[i].nodeName.match(/^on|^(?:group|id)$|^.*\..*$/)) continue;
						self[this.group].setProperty(attr[i].nodeName, attr[i].nodeValue);
					}
				}
				
				this.dispatchEvent("onstatechange");
				
				jpf.status("Setting state '" + this.name + "' to ACTIVE");
			}
			
			//Deactivate State
			else{
				this.setProperty("active", false);
				this.dispatchEvent("onstatechange");
				
				jpf.status("Setting state '" + this.name + "' to INACTIVE");
			}
		}
	}
	this.__signalElements = [];
	
	this.__loadJML = function(x){
		jpf.StateServer.addState(this);
		
		this.group = x.getAttribute("group");
		if(this.group) jpf.StateServer.addGroup(this.group, this);
		
		if(x.getAttribute("location")) jpf.StateServer.locs[x.getAttribute("location")] = this;
		
		//Properties initialization
		var attr = x.attributes;
		for(var s,i=0;i<attr.length;i++){
			if(attr[i].nodeName.match(/^on|^(?:group|id)$/)) continue;
			
			s = attr[i].nodeName.split(".");
			if(s.length == 2) this.__signalElements.push(s);
			
			this[attr[i].nodeName] = attr[i].nodeValue;
		}
	}	
	
	this.__destroy = function(){
		this.__signalElements = null;
		jpf.StateServer.removeState(this);
		if(this.group) jpf.StateServer.removeGroup(this.group, this);
	}
}

/*FILEHEAD(/in/Components/Statusbar.js)SIZE(3910)TIME(1213483123975)*/

/**
 * Component displaying a bar consisting of panels containing text and icons.
 * This component is usually placed in the bottom of the screen to display 
 * context sensitive and global information about the state of the application.
 *
 * @classDescription		This class creates a new statusbar
 * @return {Statusbar} Returns a new statusbar
 * @type {Statusbar}
 * @constructor
 * @allowchild panel
 * @addnode components:statusbar
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.9
 */
jpf.statusbar = function(pHtmlNode){
	jpf.register(this, "statusbar", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;

	var rest;
	this.panels = [];

	/* ***********************
	  		Inheritance
	************************/
	this.inherit(jpf.Presentation); /** @inherits jpf.Presentation */
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/
	
	this.getPanel = function(id){
		return this.panels[id];
	}
	
	this.addPanel = function(xmlNode){
		this.__getNewContext("Panel");
		var p = this.__getLayoutNode("Panel");
		if(xmlNode.getAttribute("css")) p.setAttribute("style", xmlNode.getAttribute("css"));
		
		var elPanel = jpf.XMLDatabase.htmlImport(p, this.oInt, this.oInt.firstChild);
		var elPanelInt = this.__getLayoutNode("Panel", "container", elPanel);
		
		var oPanel = {
			host : this,
			oExt : elPanel,
			oInt : elPanelInt,
			oIcon : this.__getLayoutNode("Panel", "icon", elPanel),
			oCaption : this.__getLayoutNode("Panel", "caption", elPanel),
			
			setCaption : function(caption){
				this.oInt.innerHTML = caption;
			},
			
			setIcon : function(iconURL){
				if(this.oIcon.tagName && this.oIcon.tagName.match(/^img$/i)) elIcon.src = this.host.iconPath + iconURL;
				else this.oIcon.style.backgroundImage = "url(" + this.host.iconPath + iconURL + ")";
			},
			
			setStatus : function(iconURL, caption){
				this.setIcon(iconURL);
				this.setCaption(caption);
			}
		};
		
		if(xmlNode.getAttribute("icon")){
			oPanel.setIcon(xmlNode.getAttribute("icon"));
			this.__setStyleClass(oPanel.oExt, "win_panel_icon");
		}
		
		var wt = xmlNode.getAttribute("width");
		if(wt == "rest" || wt == "*"){
			this.__setStyleClass(oPanel.oExt, "rest");
			rest = oPanel;
		}
		else if(wt) oPanel.oExt.style.width = wt + "px";
		
		if(xmlNode.getAttribute("height")) oPanel.oExt.style.height = xmlNode.getAttribute("height") + "px";
		if(oPanel.oCaption) oPanel.setCaption(xmlNode.firstChild ? xmlNode.firstChild.nodeValue : "");
		if(xmlNode.getAttribute("id")) this.panels[xmlNode.getAttribute("id")] = oPanel
		this.panels.push(oPanel);
		
		//parse children
		if(this.lastpages){
			var childs = this.lastpages[id].childNodes;
			for(var i=childs.length-1;i>=0;i--) elPanelInt.insertBefore(childs[i], elPanelInt.firstChild);
		}
		else if(elPanelInt && !oPanel.oCaption) jpf.JMLParser.parseChildren(xmlNode, elPanelInt, this);
		
		return oPanel;
	}
	
	/* *********
		INIT
	**********/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.draw = function(){
		//Build Main Skin
		this.oExt = this.__getExternal();
		this.oInt = this.__getLayoutNode("Main", "container", this.oExt);
		this.oCorner = this.__getLayoutNode("Main", "corner", this.oExt)
		
		rest = null;
		var nodes = this.jml.childNodes;
		for(var p,i=0;i<nodes.length;i++){
			if(nodes[i].nodeType != 1) continue;
			var tagName = nodes[i][jpf.TAGNAME];

			if(tagName == "panel"){
				p = this.addPanel(nodes[i]);
				if(this.panels.length == 1) this.__setStyleClass(p.oExt, "first");
			}
		}
		
		if(p) this.__setStyleClass(p.oExt, "last");
		//if(rest) this.oInt.appendChild(rest.oExt);
	}
}

/*FILEHEAD(/in/Components/Submitform.js)SIZE(24287)TIME(1203730484247)*/

/**
 * Component allowing special form functionality to a set of JML
 * components. Since v0.98 this component is alias for j:xforms offering
 * xform compatible strategies with relation to submitting the form's data.
 * This component also offers form paging, including validation between
 * and over pages. Buttons placed inside this component can contain an action
 * attribute specifying wether they behave as next, previous or finish(submit)
 * buttons.
 *
 * @classDescription		This class creates a new submitform
 * @return {Submitform} Returns a new submitform
 * @type {Submitform}
 * @constructor
 * @allowchild page, {components}, {anyjml}
 * @addnode components:submitform, components:xforms
 * @alias jpf.xforms
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.9
 */
jpf.xforms = 
jpf.submitform = function(pHtmlNode, tagName){
	jpf.register(this, tagName || "submitform", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	/* ***********************
	  		Inheritance
	************************/
	this.inherit(jpf.DataBinding); /** @inherits jpf.DataBinding */
	this.inherit(jpf.BaseTab); /** @inherits jpf.BaseTab */
	this.inherit(jpf.ValidationGroup); /** @inherits jpf.ValidationGroup */
	
	/* ********************************************************************
										PRIVATE PROPERTIES
	*********************************************************************/
	this.elements = {};
	var buttons = {
		"next" : [],
		"previous" : [],
		"submit" : [],
		"follow" : []
	};
	
	this.focussable = false;
	//this.allowMultipleErrors = true;
	
	this.inputs = [];
	this.errorEl = {};
	this.cq = {};
	this.reqs = [];
	this.conditionDeps = {};
	this.depends = {};

	this.loadValueDeps = {};
	this.loadValues = {};
	
	this.listsHeldBack = {};
	this.nextHeldBack = {};
	
	this.activePage = 0;
	this.zCount = 1000000;
	
	this.clear = function(){}
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/
	
	this.showLoader = function(checked, nr){
		if(checked){
			var page = nr ? this.getPage(nr) : this.getNextPage();
			if(!page || page.isRendered) return;
		}
		
		if(this.loadState){
			this.loadState.style.display = "block";
			
			var message = this.getPage().jml.getAttribute("loadmessage");
			if(message) (jpf.XMLDatabase.selectSingleNode("div[@class='msg']", this.loadState) || this.loadState).innerHTML = message;
		}
	}
	
	this.hideLoader = function(){
		if(this.loadState)
			this.loadState.style.display = "none";
	}
	
	var nextpagenr;
	this.getNextPage = function(){
		var nextpage, pageNr = this.activePage;
		do{
			nextpage = this.getPage(++pageNr);
		}while(nextpage && !this.testCondition(nextpage.condition));
		
		nextpagenr = pageNr;
		return nextpage;
	}
	
	this.next = function(no_error){
		if(!this.testing && !this.isValid(null, null, this.getPage())){
			this.hideLoader();
			return;//checkRequired
		}
		
		//var nextpage = nextpagenr ? this.getPage(nextpagenr) : this.getNextPage();
		//if(this.dispatchEvent("onbeforeswitch", nextpagenr) === false)return false;

		//this.getPage().hide();
		this.setActiveTab(this.activePage+1);//nextpagenr
		//this.activePage = nextpagenr;
		
		//if(!no_error && !nextpage) throw new Error(1006, jpf.formErrorString(1006, this, "Form", "End of pages reached."));
		
		//nextpage.show();
		//if(nextpage.isRendered) this.hideLoader();
		//else nextpage.addEventListener("onafterrender", function(){this.parentNode.hideLoader()});
		
		for(var prop in buttons){
			if(!prop.match(/next|previous|submit/)) continue;
			this.updateButtons(prop);
		}
		
		nextpagenr = null;
		
		/*var jmlNode = this;
		setTimeout(function(){
			jmlNode.dispatchEvent("onafterswitch", jmlNode.activePage, nextpage);
		}, 1);*/
	}
	
	this.previous = function(){
		//var active = this.activePage;
		//do{var prevpage = this.getPage(--active);}
		//while(prevpage && !this.testCondition(prevpage.condition));
		
		//if(this.dispatchEvent("onbeforeswitch", active) === false) return false;
		
		this.setActiveTab(this.activePage-1);
		//this.getPage().hide();
		//this.activePage = active;

		//if(!prevpage) throw new Error(1006, jpf.formErrorString(1006, this, "Form", "End of pages reached."));
		
		//prevpage.show();
		
		//if(prevpage.isRendered) this.hideLoader();
		//else prevpage.addEventListener("onafterrender", function(){this.parentNode.hideLoader()});
		
		for(var prop in buttons){
			if(!prop.match(/next|previous|submit/)) continue;
			this.updateButtons(prop);
		}

		//this.dispatchEvent("onafterswitch", this.activePage);
	}
	
	this.__enable = function(){
		forbuttons('enable');
	}
	
	this.__disable = function(){
		forbuttons('disable');
	}
	
	function forbuttons(feat){
		var arr = ["next", "previous", "submit", "follow"];
		for(var k=0;k<arr.length;k++){
			for(var i=0;i<buttons[arr[k]].length;i++){
				buttons[arr[k]][i][feat]();
			}
		}
	}
	
	this.processValueChange = function(oFormEl){
		if(this.conditionDeps[oFormEl.name]){
			var c = this.conditionDeps[oFormEl.name];
			for(var i=0;i<c.length;i++){
				if(this.testCondition(c[i].condition)) c[i].setActive();
				else c[i].setInactive();
			}
		}
		
		for(var prop in buttons){
			if(!prop.match(/next|previous|submit/)) continue;
			this.updateButtons(prop);
		}

		this.setLoadValues(oFormEl.name);
	}
	
	/* ***********************
				Actions
	************************/
	
	/* ********************************************************************
										PRIVATE METHODS
	*********************************************************************/
	this.addInput = function(objEl){
		var name = objEl.name;
		objEl.validgroup = this;

		if(this.elements[name] && !this.elements[name].length){
			this.elements[name] = [this.elements[name]];
			this.elements[name].getValue = new Function('for(var i=0;i<this.length;i++) if(this[i].oInt.checked) return this[i].getValue();');
		}

		if(this.elements[name]) this.elements[name].push(objEl);
		else this.elements[name] = objEl;

		if(this.cq[name]){
			for(var i=0;i<this.cq[name].length;i++){
				this.cq[name][i][1].call(this.cq[name][i][0], objEl);
				objEl.labelEl = this.cq[name][i][0];
			}
		}
		
		if(objEl.jml.getAttribute("dependson")){
			var o = self[objEl.jml.getAttribute("dependson")];
			if(!this.depends[o.name]) this.depends[o.name] = [];
			this.depends[o.name].push(objEl);
			objEl.setInactive();
		}
		
		if(objEl.nodeType == GUI_NODE) objEl.setZIndex(--this.zCount);
		
		if(this.listsHeldBack[name]){
			var ld = this.listsHeldBack[name];
			this.loadLists(ld[0], ld[1], ld[2]);
			this.listsHeldBack[name] = null;
		}

		if(this.nQuest && objEl.jml.getAttribute("checknext") == "true"){
			if(this.lastEl){
				this.lastEl.nextEl = objEl;
				objEl.prevEl = this.lastEl;
			}
			this.lastEl = objEl;
			
			if(objEl.prevEl && objEl.jml.getAttribute("show") != "true" && !this.nextHeldBack[name] && !objHasValue(objEl)) objEl.setInactive(true);
			else if(this.condActiveCheck[objEl.name]) this.condActiveCheck[objEl.name].setActive();
			
			//terrible code, but what the heck
			if(this.condActiveCheck[objEl.name]){
				objEl.container = this.condActiveCheck[objEl.name];
				
				function activateHandler(){
					if(this.form.hasActiveElement(this.container)) this.container.setActive();
					else this.container.setInactive();
				}
				
				objEl.addEventListener("onactivate", activateHandler);
				objEl.addEventListener("ondeactivate", activateHandler);
			}
		}
	}
	
	this.hasActiveElement = function(objEl){
		var nodes = objEl.jml.getElementsByTagName("*");
		for(var i=0;i<nodes.length;i++){
			if(!nodes[i].getAttribute("id")) continue;
			var comp = this.elements[nodes[i].getAttribute("id")];
			if(comp && comp.form == this && comp.isActive) return true;
		}
		
		return false;
	}
	
	this.condActiveCheck = {};
	this.getButtons = function(action){return buttons[action];}
	
	this.registerButton = function(action, oBtn){
		buttons[action].push(oBtn);
		
		if(oBtn.condition) this.parseCondition(oBtn, oBtn.condition);
		this.updateButtons(action, oBtn);
		
		if(action == "follow") return;
		
		var jmlNode = this;
		oBtn.onclick = function(){
			jmlNode.showLoader(true);
			setTimeout(function(){jmlNode[action]()}, 10);
		};
		
		/*
			new Function(
				'jpf.lookup(' + this.uniqueId + ').showLoader(true);setTimeout("jpf.lookup(' + this.uniqueId + ').' + action + '()", 10)'
			);
		
			action == "previous" ?
				'jpf.lookup(' + this.uniqueId + ').' + action + '()' :
				'jpf.lookup(' + this.uniqueId + ').showLoader();setTimeout("jpf.lookup(' + this.uniqueId + ').' + action + '()", 10)'
			);
		*/
	}
	
	//refactor to give buttons classes, so they can decide what to do when inactive
	this.updateButtons = function(action, singleBtn){
		return false;//
		
		if(!buttons[action]) return false;
		
		var result = true;
		if(action == "previous" && this.activePage == 0) result = false;
		else if(!this.testing && action == "next" && !this.isValid()) result = false;
		else if(action == "next"){
			var cp = this.activePage;
			do{var nextpage = this.getPage(++cp);
			}while(nextpage && !this.testCondition(nextpage.condition));

			if(!nextpage) result = false;
		}

		if(this.testing) return true;

		var buttons = singleBtn ? [singleBtn] : buttons[action];
		for(var i=0;i<buttons.length;i++){
			if(result && (!buttons[i].condition || this.testCondition(buttons[i].condition))) buttons[i].setActive();
			else buttons[i].setInactive();
		}

		return true;
	}
	
	this.setLoadValues = function(item, clearElements, noload){
		var lvDep = this.loadValueDeps[item];
		if(!lvDep) return;
		//alert(item);
		for(var i=0;i<lvDep.length;i++){
			try{if(!eval(lvDep[i][1])) throw new Error();}catch(e){
				if(clearElements){
					var oEl = self[lvDep[i][0].getAttribute("element")];
					if(oEl) this.clearNextQuestionDepencies(oEl, true);//might be less optimized...

					if(lvDep[i][0].tagName == "LoadValue")
						this.dispatchEvent("onclearloadvalue", lvDep[i][0]);

					/*else if(lvDep[i][0].getAttribute("lid")){
						var lid = lvDep[i][0].getAttribute("lid");
						var nodes = this.XMLRoot.selectSingleNode("node()[@lid='" + lid + "']");
						
						for(var i=0;i<nodes.length;i++){
							jpf.XMLDatabase.removeNode(nodes[i]);
						}
					}*/
				}
				continue;
			}
			
			if(noload) continue;
			
			if(lvDep[i][0].getAttribute("runonrequest") != "true"){
				this.processLoadRule(lvDep[i][0], lvDep[i][2], lvDep[i]);
			}
			else if(self[lvDep[i][0].getAttribute("element")]){
				//This should be different :'(
				self[lvDep[i][0].getAttribute("element")].clear();
			}
		}
	}
	
	this.processLoadRule = function(xmlCommNode, isList, data){
		//Extend with Method etc
		if(!jpf.Teleport.hasLoadRule(xmlCommNode)) return;
		
		this.dispatchEvent(isList ? "onbeforeloadlist" : "onbeforeloadvalue");
		
		//Process basedon arguments
		var nodes = xmlCommNode.childNodes;//selectNodes("node()[@arg-type | @arg-nr]"); //Safari bugs on this XPath... hack!
		if(nodes.length){
			var arr, arg = xmlCommNode.getAttribute(jpf.Teleport.lastRuleFound.args);
			arg = arg ? arg.split(";") : [];

			if(xmlCommNode.getAttribute("argarray")) arr = [];
			for(var j=0;j<nodes.length;j++){
				if(nodes[j].nodeType != 1) continue; //for safari
				if(nodes[j].getAttribute("argtype").match(/fixed|param|nocheck/)){ //Where does item come from??? || item == nodes[j].getAttribute("element")
					var el = self[nodes[j].getAttribute("element")];
					var xpath = el.getMainBindXpath();
					var xNode = jpf.XMLDatabase.createNodeFromXpath(this.XMLRoot, xpath);
					var nType = xNode.nodeType;
					(arr || arg)[nodes[j].getAttribute("argnr") || j] = "xpath:" + xpath + (nType == 1 ? "/text()" : "");
				}
				else if(nodes[j].getAttribute("argtype") == "xpath"){
					(arr || arg)[nodes[j].getAttribute("argnr") || j] = "xpath:" + nodes[j].getAttribute("select");//jpf.getXmlValue(this.XMLRoot, );
				}
			}

			if(xmlCommNode.getAttribute("argarray")){
				arg[xmlCommNode.getAttribute("argarray")] = "(" + arr.join(",") + ")";
			}

			xmlCommNode.setAttribute(jpf.Teleport.lastRuleFound.args, arg.join(";"));
		}

		//this.XMLRoot.firstChild
		//if(confirm("do you want to debug?")) throw new Error();
		
		var jNode = self[xmlCommNode.getAttribute("element")];
		if(jNode && jNode.nodeType == GUI_NODE) jNode.__setStyleClass(jNode.oExt, "loading", ["loaded"]);
		
		//if(!isList && !data[0].getAttribute("lid")) data[0].setAttribute("lid", jpf.getUniqueId());
		jpf.Teleport.callMethodFromNode(xmlCommNode, this.XMLRoot, Function('data', 'state', 'extra', 'jpf.lookup(' + this.uniqueId + ').' + (isList ? 'loadLists' : 'loadValues') + '(data, state, extra)'), null, data);
	}
	
	this.registerCondition = function(objEl, strCondition, no_parse){
		if(!no_parse) this.parseCondition(objEl, strCondition);
		
		var forceActive = false;
		if(objEl.onlyWhenActive){
			var nodes = objEl.jml.getElementsByTagName("*");
			for(var i=0;i<nodes.length;i++){
				if(!nodes[i].getAttribute("id")) continue;
				
				if(this.nextHeldBack[nodes[i].getAttribute("id")]) forceActive = true;
				else if(nodes[i].getAttribute("ref") && this.XMLRoot && jpf.XMLDatabase.getNodeValue(this.XMLRoot.selectSingleNode(nodes[i].getAttribute("ref"))) != ""){
					forceActive = true;
					nodes[i].setAttribute("show", "true");
				}
				
				this.condActiveCheck[nodes[i].getAttribute("id")] = objEl;
			}
		}

		if(forceActive || this.testCondition(objEl.condition) && (!objEl.onlyWhenActive || this.hasActiveElement(objEl, true))) objEl.setActive();
		else objEl.setInactive();
		
		var matches = !no_parse ? 
			strCondition.match(/(\W|^)(\w+)(?:\=|\!\=)/g) :
			strCondition.match(/(\b|^)([\w\.]+)/g);
		if(!matches) return;
		
		for(var i=0;i<matches.length;i++){
			if(!no_parse){
				var m = matches[i].replace(/(?:\=|\!\=)$/, "").replace(/(^\s+|\s+$)/g, "");
			}
			else{
				var m = matches[i].split(".");
				if(m.length < 2) continue;
				m = m[0];
			}
			
			if(!this.conditionDeps[m]) this.conditionDeps[m] = Array();
			this.conditionDeps[m].push(objEl);
		}
	}
	
	this.testCondition = function(strCondition){
		//somename='somestr' and (sothername='que' or iets='niets') and test=15

		try{
			return eval(strCondition);
		}
		catch(e){
			return false;
			//throw new Error(1009, jpf.formErrorString(1009, this, "Form", "Invalid conditional statement [" + strCondition + "] : " + e.message));
		}
	}
	
	this.loadValues = function(data, state, extra){
		if(state != __HTTP_SUCCESS__){
			if(extra.retries < jpf.maxHttpRetries) return extra.tpModule.retry(extra.id);
			else throw new Error(1010, jpf.formErrorString(1010, this, "LoadVaLue", "Could not load values with LoadValue query :\n\n" + extra.message));
		}

		if(extra.userdata[0].getAttribute("returntype") == "array"){
			//integrate array
			for(var i=0;i<data.length;i++){
				var pnode = this.XMLRoot.selectSingleNode("//" + data[i][0]);
				jpf.XMLDatabase.setTextNode(pnode, data[i][1] || "");
			}
		}
		else{
			//integrate xml
			if(typeof data != "object") data = jpf.getObject("XMLDOM", data).documentElement;
			var nodes = data.childNodes;
			var strUnique = extra.userdata[0].getAttribute("unique");

			for(var i=nodes.length-1;i>=0;i--){
				var xmlNode = nodes[i];
				var unique = strUnique ? xmlNode.selectSingleNode(strUnique) : false;
				
				var node = unique ? this.XMLRoot.selectSingleNode("node()[" + strUnique + " = '" + unique.nodeValue + "']") : null;
				if(node){
					//Move all this into the XMLDatabase
					jpf.XMLDatabase.copyConnections(node, xmlNode);
					jpf.XMLDatabase.notifyListeners(xmlNode);
					
					//node.setAttribute("lid", data.getAttribute("lid"));
					
					//hack!! - should be recursive
					var valueNode = xmlNode.selectSingleNode("value");
					if(valueNode){
						jpf.XMLDatabase.copyConnections(node.selectSingleNode("value"), valueNode);
						jpf.XMLDatabase.notifyListeners(valueNode);
					}
				}
				
				this.XMLRoot.insertBefore(xmlNode, node); //consider using replaceChild here
				if(node) this.XMLRoot.removeChild(node);
				jpf.XMLDatabase.applyChanges("attribute", xmlNode);
			}
		}

		this.dispatchEvent("onafterloadvalue");
	}
	
	this.loadLists = function(data, state, extra){
		if(state != __HTTP_SUCCESS__){
			if(extra.retries < jpf.maxHttpRetries) return extra.tpModule.retry(extra.id);
			else throw new Error(1011, jpf.formErrorString(1011, this, "Load List", "Could not load data with LoadList query :\n\n" + extra.message));
		}
		
		if(!self[extra.userdata[0].getAttribute("element")])
			return this.listsHeldBack[extra.userdata[0].getAttribute("element")] = [data, state, extra];
		
		//set style
		var jNode = self[extra.userdata[0].getAttribute("element")];
		if(jNode && jNode.nodeType == GUI_NODE){
			jNode.__setStyleClass(jNode.oExt, "loaded", ["loading"]);
			setTimeout("var jNode = jpf.lookup(" + jNode.uniqueId + ");jNode.__setStyleClass(jNode.oExt, '', ['loading', 'loaded']);", 500);
		}

		if(extra.userdata[0].getAttribute("clearonload") == "true"){
			jNode.clearSelection();
			//this.setLoadValues(jNode.name, true);
			this.clearNextQuestionDepencies(jNode, true);
		}
		
		//load xml in element
		jNode.load(data);
		//if(!jNode.value){
			//this.clearNextQuestionDepencies(jNode, true);
		//}
		
		this.dispatchEvent("onafterloadlist");
	}
	
	/*this.isValid = function(checkReq, setError, page){
		if(!page) page = this.getPage() || this;
		var found = checkValidChildren(page, checkReq, setError);
		
		//Global Rules
		//
		
		return !found;
	}
	
	this.validate = function(){
		if(!this.isValid()){
			
		}
	}*/
	
	//HACK!
	this.reset = function(){
	  //Clear all error states
		for(name in this.elements){		
			var el = this.elements[name];
			
			//Hack!!! maybe traverse
			if(el.length){
				throw new Error(0, jpf.formErrorString(this, "clearing form", "Found controls without a name or with a name that isn't unique. Please give all elements of your submitform an id: '" + name + "'"));
			}
			
			el.clearError();
			if(this.errorEl[name])
				this.errorEl[name].hide();
			
			if(el.hasFeature(__MULTIBINDING__)) el.getSelectionSmartBinding().clear();
			else el.clear();
		}
	}
	
	/* ***********************
			Databinding
	************************/
	
	this.__xmlUpdate = function(action, xmlNode, listenNode, UndoObj){
		//this.setConnections(this.XMLRoot, "select");
		//if(confirm("debug? " + this.toString())) debugger;
		this.dispatchEvent("onxmlupdate");
	}
	
	this.smartBinding = {};
	this.__load = function(XMLRoot, id){
		jpf.XMLDatabase.addNodeListener(XMLRoot, this);
		//this.setConnections(jpf.XMLDatabase.getElement(XMLRoot, 0), "select");	
		//this.setConnections(XMLRoot, "select");	
	}
	
	function objHasValue(objEl){
		var oCheck = objEl.hasFeature(__MULTISELECT__) ? objEl.getSelectionSmartBinding() : objEl;
		if(!oCheck) return false;
		return oCheck.applyRuleSetOnNode(oCheck.mainBind, oCheck.XMLRoot, null, true);
	}
	
	//Reset form
	function onafterload(){
		//Clear all error states
		for(name in this.elements){
			if(jpf.isSafari && (!this.elements[name] || !this.elements[name].__jmlLoaders)) continue;
			
			//Hack!!! maybe traverse
			if(this.elements[name].length){
				throw new Error(1012, jpf.formErrorString(1012, this, "clearing form", "Found controls without a name or with a name that isn't unique("+name+"). Please give all elements of your submitform an id: '" + name + "'"));
			}
			
			this.elements[name].clearError();
			if(this.errorEl[name])
				this.errorEl[name].hide();
		}
		
		if(this.nQuest){
			//Show all controls and labels which are in the nquest stack
			for(name in this.elements){
				
				var objEl = this.elements[name];
				
				if(objEl.jml.getAttribute("checknext") == "true"){
					if(objHasValue(objEl)){//oCheck.value || 
						objEl.setActive();
						if(this.condActiveCheck[name])
							this.condActiveCheck[name].setActive();
					}
					else{
						objEl.setInactive(true);
					}
				}
				else{
					//que ???
					if(objEl.tagName == "Radiogroup" && objEl.current)
						objEl.current.uncheck();
				}
			}
		}

		if(this.nQuest && this.XMLRoot.childNodes.length > 0){
			var element = this.nQuest.getAttribute("final");
			var jmlNode = self[element].jml;//jpf.XMLDatabase.selectSingleNode(".//node()[@id='" + element + "']", this.jml);

			if(jmlNode && !jpf.XMLDatabase.getBoundValue(jmlNode, this.XMLRoot)){
				var fNextQNode = jpf.XMLDatabase.selectSingleNode(".//node()[@checknext='true']", this.jml);
				if(!fNextQNode) return;
				self[fNextQNode.getAttribute("id")].dispatchEvent("onafterchange");
			}
		}
	}
	this.addEventListener("onafterload", onafterload);
	this.addEventListener("onafterinsert", onafterload);
	
	this.addEventListener("onbeforeload", function(){
		if(!this.smartBinding || !this.smartBinding.actions) return;
		var nodes = this.smartBinding.actions.LoadList;
		if(nodes){
			for(var objEl, i=0;i<nodes.length;i++){
				if(!nodes[i].getAttribute("element") || !(objEl = this.elements[nodes[i].getAttribute("element")])) continue;
				objEl.clear();
			}
		}
		
		var nodes = this.smartBinding.actions.NextQuestion;
		if(nodes){
			for(var objEl, i=0;i<nodes.length;i++){
				if(!nodes[i].getAttribute("final") || !(objEl = this.elements[nodes[i].getAttribute("element")])) continue;
				objEl.clear();
			}
		}
	});
	
	/* *********
		INIT
	**********/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.addOther = function(tagName, oJml){
		if(tagName == "LoadState"){
			var htmlNode = jpf.compat.getFirstElement(oJml);
			this.loadState = jpf.XMLDatabase.htmlImport(htmlNode, this.oInt);
			this.loadState.style.display = "none";
		}
	}
	
	this.draw = function(){
		//Build Main Skin
		this.oPages = this.oExt = this.__getExternal(); 
		this.oInt = this.__getLayoutNode("Main", "container", this.oExt);
		this.oExt.host = this;
	}
	
	/**
	 * @syntax
	 *  <j:submitform 
	 *    [action="url" method="get|post|urlencoded-post" [ref="/"] ]
	 *    [submit="<save_data>"] 
	 *    [submittype="json|xml|native"]
	 *    [useelements="boolean"]
	 *    [model="id"]
	 *  >
	 *    <j:Button action="submit" [submission="@id"] [model=""] />
	 *  </j:submitform>
	 */
	this.submit = function(submissionId){
		if(!this.isValid()) return;
		if(!this.model) return; //error?
		
		var type = this.method == "urlencoded-post" ? "native" : (this.type || "xml");
		var instruction = submissionId || this.action ? ((this.method.match(/post/) ? "url.post:" : "url:") + this.action) : "";
		
		this.model.submit(instruction, type, this.useComponents, this.ref);
	}
	
	this.setModel = function(model, xpath){
		this.model = model;
	}
	
	this.__loadJML = function(x){

		this.testing = x.getAttribute("testing") == "true";

		this.action = this.jml.getAttribute("action");
		this.ref = this.jml.getAttribute("ref");
		this.type = this.jml.getAttribute("submittype") || "native";
		this.method = (this.jml.getAttribute("method") || "get").toLowerCase();
		this.useComponents = this.jml.getAttribute("usecomponents") || true;
		
		jpf.setModel(x.getAttribute("model"), this);
		
		this.__drawTabs(function(xmlPage){
			this.validation = xmlPage.getAttribute("validation") || "true";
			this.invalidmsg = xmlPage.getAttribute("invalidmsg");
		});
	}
}

/*FILEHEAD(/in/Components/Tab.js)SIZE(1621)TIME(1203730484247)*/

/**
 * Component displaying a page and several buttons allowing a
 * user to switch between the pages. Each page can contain
 * arbitrary JML. Each page can render it's content during
 * startup of the application or when the page is activated.
 *
 * @classDescription		This class creates a new tab component
 * @return {Tab} Returns a new tab component
 * @type {Tab}
 * @constructor
 * @allowchild page
 * @addnode components:tab
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.1
 */
jpf.tab = function(pHtmlNode){
	jpf.register(this, "tab", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	this.hasButtons = true;
	this.focussable = true; // This object can get the focus
	
	/* ***********************
	  Other Inheritance
	************************/
	this.inherit(jpf.BaseTab); /** @inherits jpf.BaseTab */
	this.keyHandler = this.__keyHandler;
	
	/* ********************************************************************
										PRIVATE METHODS
	*********************************************************************/
	
	/* *********
		INIT
	**********/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.draw = function(){
		//Build Main Skin
		this.oExt = this.__getExternal();
		this.oPages = this.__getLayoutNode("Main", "pages", this.oExt);
		this.oButtons = this.__getLayoutNode("Main", "buttons", this.oExt);
	}
	
	this.__loadJML = function(x){
		this.__drawTabs();
	}
}

/*FILEHEAD(/in/Components/Text.js)SIZE(9831)TIME(1203730484247)*/

/**
 * Component displaying a rectangle containing arbritrary (X)HTML.
 * This component can be databound and use databounding rules to
 * convert data into (X)HTML using for instance XSLT or JSLT.
 *
 * @classDescription		This class creates a new text component
 * @return {Text} Returns a new text component
 * @type {Text}
 * @constructor
 * @addnode components:text
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.1
 */
jpf.text = function(pHtmlNode){
	jpf.register(this, "text", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	/* ***********************
	  		Inheritance
	************************/
	this.inherit(jpf.Presentation); /** @inherits jpf.Presentation */
	
	this.inherit(jpf.DataBinding); /** @inherits jpf.DataBinding */
	
	/* ********************************************************************
										PROPERTIES
	*********************************************************************/
	
	//Options
	this.focussable = true; // This object can't get the focus

	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/
	
	this.getValue = function(){
		return this.oInt.innerHTML;
	}
	
	this.keyHandler = function(key,ctrlKey,shiftKey,altKey){
		switch(key){
			case 33:
			//PGUP
				this.oInt.scrollTop -= this.oInt.offsetHeight;
			break;
			case 34:
			//PGDN
				this.oInt.scrollTop += this.oInt.offsetHeight;
			break;
			case 35:
				//END
				this.oInt.scrollTop = this.oInt.scrollHeight;
			break;
			case 36:
			//HOME
				this.oInt.scrollTop = 0;
			break;
			case 38:
				this.oInt.scrollTop -= 10;
			break;
			case 40:
				this.oInt.scrollTop += 10;
			break;
			default:
			return;
		}
		
		return false;
	}
	
	this.setValue = 
	this.loadHTML = function(strHTML, doInsert, cacheObj){
		if(typeof strHTML != "string") strHTML = strHTML ? strHTML.toString() : "";
		
		if(this.protection){
			strHTML = strHTML.replace(/<a /gi, "<a target='_blank' ");
			strHTML = strHTML.replace(/<object.*?\/object>/g, "");
			strHTML = strHTML.replace(/<script.*?\/script>/g, "");
			strHTML = strHTML.replace(new RegExp("ondblclick|onclick|onmouseover|onmouseout|onmousedown|onmousemove|onkeypress|onkeydown|onkeyup|onchange|onpropertychange", "g"), "ona");
		}

		if(doInsert){
			if(cacheObj) cacheObj.contents += strHTML;
			else this.oInt.insertAdjacentHTML("beforeend", strHTML);
		}
		else{
			strHTML = strHTML.replace(/\<\?xml version="1\.0" encoding="UTF-16"\?\>/, "");
		
			//var win = window.open();
			//win.document.write(strHTML);
			if(cacheObj) cacheObj.contents = strHTML;
			else this.oInt.innerHTML = strHTML;//.replace(/<img[.\r\n]*?>/ig, "")
		}
		
		//Iframe bug fix for IE (leaves screen white);
		if(jpf.cannotSizeIframe && this.oIframe) this.oIframe.style.width = this.oIframe.offsetWidth + "px";

		if(this.scrolldown) this.oInt.scrollTop = this.oInt.scrollHeight;
	}
	
	this.__clear = function(){
		//this.oInt.innerHTML = "<div style='text-align:center;font-family:MS Sans Serif;font-size:8pt'>" + this.msg + "</div>";
	}
	
	/* ***************
		DATABINDING
	****************/
	
	this.__xmlUpdate = function(action, xmlNode, listenNode, UndoObj){
		if(this.addOnly && action != "add") return;
		
		//Action Tracker Support
		if(UndoObj) UndoObj.xmlNode = this.addOnly ? xmlNode : this.XMLRoot;//(contents ? contents.XMLRoot : this.XMLRoot);
		
		//Refresh Properties
		if(this.addOnly){
			jpf.XMLDatabase.nodeConnect(this.documentId, xmlNode, null, this);
			var cacheObj = this.getNodeFromCache(listenNode.getAttribute("id")+"|"+this.uniqueId);

			this.loadHTML(this.applyRuleSetOnNode("value", xmlNode) || "", true, cacheObj);
		}
		else this.loadHTML(this.applyRuleSetOnNode("value", this.XMLRoot) || "");
	}
	
	this.__load = function(node){
		//Add listener to XMLRoot Node
		jpf.XMLDatabase.addNodeListener(node, this);
		var value = this.applyRuleSetOnNode("value", node);

		if(value || typeof value == "string"){
			if(this.caching){
				var cacheObj = this.getNodeFromCache(node.getAttribute("id")+"|"+this.uniqueId);
				if(cacheObj) cacheObj.contents = value;
			}
			this.loadHTML(value);
		}
		else this.loadHTML("");
	}
	
	/* ***********************
			DRAGDROP
	************************/
	this.__showDragIndicator = function(sel, e){
		var x = e.offsetX + 22;
		var y = e.offsetY;

		this.oDrag.startX = x;
		this.oDrag.startY = y;

		
		document.body.appendChild(this.oDrag);
		//this.oDrag.getElementsByTagName("DIV")[0].innerHTML = this.selected.innerHTML;
		//this.oDrag.getElementsByTagName("IMG")[0].src = this.selected.parentNode.parentNode.childNodes[1].firstChild.src;
		var oInt = this.__getLayoutNode("Main", "caption", this.oDrag);
		if(oInt.nodeType != 1) oInt = oInt.parentNode;
		
		oInt.innerHTML = this.applyRuleSetOnNode("caption", this.XMLRoot) || "";
		
		return this.oDrag;
	}
	
	this.__hideDragIndicator = function(){
		this.oDrag.style.display = "none";
	}
	
	this.__moveDragIndicator = function(e){
		this.oDrag.style.left = (e.clientX - this.oDrag.startX) + "px";
		this.oDrag.style.top = (e.clientY - this.oDrag.startY) + "px";
	}
	
	this.__initDragDrop = function(){
		//don't execute when only receiving;
		
		this.oDrag = document.body.appendChild(this.oExt.cloneNode(true));
		this.oDrag.id = "";
		
		this.oDrag.style.zIndex = 1000000;
		this.oDrag.style.position = "absolute";
		this.oDrag.style.cursor = "default";
		this.oDrag.style.filter = "progid:DXImageTransform.Microsoft.Alpha(opacity=50)";
		this.oDrag.style.MozOpacity = 0.5;
		this.oDrag.style.opacity = 0.5;
		this.oDrag.style.display = "none";
		
		//remove id's
	}
	
	this.__dragout = 
	this.__dragover = 
	this.__dragdrop = function(){}
	
	this.inherit(jpf.DragDrop); /** @inherits jpf.DragDrop */
	
	/* ***********************
			  CACHING
	************************/
	
	this.__getCurrentFragment = function(){
		return {
			nodeType : 1,
			contents : this.oInt.innerHTML
		}
	}
	
	this.__setCurrentFragment = function(fragment){
		this.oInt.innerHTML = fragment.contents;
		if(this.scrolldown) this.oInt.scrollTop = this.oInt.scrollHeight;
	}

	this.__findNode = function(cacheNode, id){
		id = id.split("\|");
		
		if((cacheNode ? cacheNode : this).XMLRoot.selectSingleNode("descendant-or-self::node()[@id='" + (id[0]+"|"+id[1]) + "']")) 
			return (cacheNode ? cacheNode : null);

		return false;
	}
	
	this.__setClearMessage = function(msg){
		/*var oEmpty = XMLDatabase.htmlImport(this.__getLayoutNode("Empty"), this.oInt);
		var empty = this.__getLayoutNode("Empty", "caption", oEmpty);
		if(empty) empty.nodeValue = msg;
		if(oEmpty) oEmpty.setAttribute("id", "empty" + this.uniqueId);*/
		
		//hack!
		this.oInt.innerHTML = "";
	}
	
	this.__removeClearMessage = function(){
		var oEmpty = document.getElementById("empty" + this.uniqueId);
		if(oEmpty) oEmpty.parentNode.removeChild(oEmpty);
		else this.oInt.innerHTML = ""; //clear if no empty message is supported
	}
	
	this.inherit(jpf.Cache); /** @inherits jpf.Cache */
	this.caching = false; //Fix for now
	
	/* *********
		INIT
	**********/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.draw = function(){
		this.oExt = this.__getExternal(); 
		this.oInt = this.__getLayoutNode("Main", "container", this.oExt);
		
		if(this.oInt.tagName.toLowerCase() == "iframe"){
			if(jpf.isIE){
				this.oIframe = this.oInt;
				var iStyle = this.skin.selectSingleNode("iframe_style");
				this.oIframe.contentWindow.document.write("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"><head><style>" + (iStyle ? iStyle.firstChild.nodeValue : "") + "</style><script>document.onkeydown = function(e){if(!e) e = event;if(" + 'top.jpf.disableF5' + " && e.keyCode == 116){e.keyCode = 0;return false;}}</script></head><body oncontextmenu='return false'></body>");
				this.oInt = this.oIframe.contentWindow.document.body;
			}
			else{
				var node = document.createElement("div");
				this.oExt.parentNode.replaceChild(node, this.oExt);
				node.className = this.oExt.className;
				this.oExt = this.oInt = node;
			}
		}
		else{
			this.oInt.onselectstart = function(e){(e?e:event).cancelBubble = true;}
			this.oInt.oncontextmenu = function(e){
				if(!this.host.contextmenus) (e?e:event).cancelBubble = true;
			}
			this.oInt.style.cursor = "";
		
			this.oInt.onmouseover = function(e){
				if(!self.STATUSBAR) return;
				if(!e) e = event;
				
				if(e.srcElement.tagName.toLowerCase() == "a"){
					if(!this.lastStatus) this.lastStatus = STATUSBAR.getStatus();
					STATUSBAR.status("icoLink.gif", e.srcElement.getAttribute("href"));
				}
				else if(this.lastStatus){
					STATUSBAR.status(this.lastStatus[0], this.lastStatus[1]);
					this.lastStatus = false;
				}
			}
		}
	}

	this.__loadJML = function(x){
		if(x.getAttribute("behavior") == "addonly") this.addOnly = true;
		if(x.getAttribute("scrolldown") == "true") this.scrolldown = true;
		
		this.protection = x.getAttribute("protection") == "true";
		this.caching = false;// hack
		
		if(x.childNodes.length == 1 && x.firstChild.nodeType != 1) this.loadHTML(x.firstChild.nodeValue)
		else if(x.childNodes) jpf.JMLParser.parseChildren(x, this.oInt, this);
	}
	
	this.__destroy = function(){
		jpf.removeNode(this.oDrag);
		this.oDrag = null;
		this.oIframe = null;
	}
}

/*FILEHEAD(/in/Components/Textbox.js)SIZE(22114)TIME(1203730484247)*/

/**
 * Component displaying a rectangular area wich allows a
 * user to type information. The information typed can be
 * restricted by using masking. The information can also
 * be hidden from view when used in password mode. Furthermore
 * by supplying a dataset information typed can autocomplete.
 *
 * @classDescription		This class creates a new textbox
 * @return {Textbox} Returns a new textbox
 * @type {Textbox}
 * @constructor
 * @alias jpf.input
 * @alias jpf.secret
 * @alias jpf.textarea
 * @allowchild autocomplete
 * @addnode components:textbox, components:secret, components:input, components:textarea
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.1
 */
//XForms support
jpf.input = 
jpf.secret = 
jpf.textarea = 
jpf.textbox = function(pHtmlNode, tagName){
	jpf.register(this, tagName || "textbox", GUI_NODE);/** @inherits jpf.Class */

	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	/* ***********************
	  		Inheritance
	************************/
	this.inherit(jpf.Presentation); /** @inherits jpf.Presentation */
	
	this.inherit(jpf.DataBinding); /** @inherits jpf.DataBinding */

	/* ********************************************************************
										PROPERTIES
	*********************************************************************/
	
	//Options
	this.focussable = true; // This object can get the focus
	this.nonSizingHeight = true;
	this.inherit(jpf.XForms); /** @inherits jpf.XForms */
	
	var focusSelect = false;
	var masking = false;
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/

	this.setValue = function(value){
		debugger;
		return this.setProperty("value", value);
	}
	
	this.__clear = function(){
		this.value = "";
		
		if(this.oInt.tagName.toLowerCase().match(/input|textarea/i)) this.oInt.value = "";
		else{
			this.oInt.innerHTML = "";
			//try{this.oInt.focus();}catch(e){}
			
			if(!jpf.hasMsRangeObject) return;
			
			//will fail when object isn't visible
			//N.B. why a select in a clear function.. isn't consistent...
			try{
				var range = document.selection.createRange();
				range.moveStart("sentence", -1);
				//range.text = "";
				range.select();
			}catch(e){}
		}
	}
	
	this.getValue = function(){
		return this.isHTMLBox ? this.oInt.innerHTML : this.oInt.value;
	}
	
	this.insert = function(text){
		if(jpf.hasMsRangeObject){
			try{this.oInt.focus();}catch(e){}
			var range = document.selection.createRange();
			if(this.oninsert) text = this.oninsert(text);
			range.pasteHTML(text);
			range.collapse(true);
			range.select();
		}
		else{
			this.oInt.value += text;
		}
	}
	
	this.__enable = function(){this.oInt.disabled = false;}
	this.__disable = function(){this.oInt.disabled = true;}
	this.select = function(){this.oInt.select();}
	this.deselect = function(){this.oInt.deselect();}
	
	/* ********************************************************************
										PRIVATE METHODS
	*********************************************************************/

	this.__insertData = function(str){
		return this.setValue(str);
	}	
	
	/* ***********************
		Keyboard Support
	************************/
	this.keyHandler = function(){}
	
	//Normal
	this.keyHandlerWA = function(key, ctrlKey, shiftKey, altKey, e){
		if(this.dispatchEvent("onkeydown", {keyCode : key, ctrlKey : ctrlKey, shiftKey : shiftKey, altKey : altKey, htmlEvent : e}) === false) return false;
		
		if(false && jpf.isIE && (key == 86 && ctrlKey || key == 45 && shiftKey)){
			var text = window.clipboardData.getData("Text");
			if((text = this.dispatchEvent("onkeydown", {text : this.onpaste(text)}) === false)) return false;
			if(!text) text = window.clipboardData.getData("Text");
			
			this.oInt.focus();
			var range = document.selection.createRange();
			range.text = "";
			range.collapse();
			range.pasteHTML(text.replace(/\n/g, "<br />").replace(/\t/g, "&nbsp;&nbsp;&nbsp;"));
			
			return false;
		}
	}
	
	/* ***********************
				Focus
	************************/
	
	this.__focus = function(){
		if(!this.oExt || this.oExt.disabled) return;
		this.__setStyleClass(this.oExt, this.baseCSSname + "Focus");
		
		try{this.oInt.focus();}catch(e){}
		if(masking) this.setPosition();
		
		if(this.selectFocus){
			focusSelect = true;
			this.select();
		}
	}
	
	this.__blur = function(){
		if(!this.oExt) return;
		this.__setStyleClass(this.oExt, "", [this.baseCSSname + "Focus"]);
		
		if(masking){
			var r = this.oExt.createTextRange();
			r.collapse();
			r.select();
		}
		
		try{
			this.oExt.blur();
			document.body.focus();
		}catch(e){}
		
		if(this.changeTrigger == "enter")
			this.change(this.getValue());
			
		focusSelect = false;
		// check if we clicked on the oContainer. ifso dont hide it
		if(this.oContainer)
			setTimeout('var o = jpf.lookup(' + this.uniqueId + ');o.oContainer.style.display = "none"', 100);
	}
	
	this.__supportedProperties = ["value"];
	this.__handlePropSet = function(prop, value){
		switch(prop){
			case "value":
				// Set Value
				if(this.isHTMLBox){
					if(this.oInt.innerHTML != value)
						this.oInt.innerHTML = value;
				}
				else if(this.oInt.value != value){
					this.oInt.value = value;
				}
			break;
		}
	}
	
	/* *********
		INIT
	**********/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.draw = function(){
		//Build Main Skin
		this.oExt = this.__getExternal(null, null, function(oExt){
			if(this.jml.getAttribute("mask") == "PASSWORD" || this.tagName == "secret"){
				this.jml.removeAttribute("mask");
				this.__getLayoutNode("Main", "input").setAttribute("type", "password");
			}
			
			oExt.setAttribute("onmousedown", 'this.host.dispatchEvent("onmousedown", {htmlEvent : event});');
			oExt.setAttribute("onmouseup", 'this.host.dispatchEvent("onmouseup", {htmlEvent : event});');
			oExt.setAttribute("onclick", 'this.host.dispatchEvent("onclick", {htmlEvent : event});');
		}); 
		this.oInt = this.__getLayoutNode("Main", "input", this.oExt);	
		
		if(!jpf.hasContentEditable && !this.oInt.tagName.toLowerCase().match(/input|textarea/)){
			var node = this.oInt;
			this.oInt = node.parentNode.insertBefore(document.createElement("textarea"), node);
			node.parentNode.removeChild(node);
			this.oInt.className = node.className;
			if(this.oExt == node) this.oExt = this.oInt;
		}
		
		this.oInt.onselectstart = function(e){if(!e) e = event;e.cancelBubble = true}
		this.oInt.host = this;
		
		//temp fix
		this.oInt.onkeydown = function(e){
			if(this.disabled) return false;
			
			if(!e) e = event;
			
			//Change
			if(this.host.changeTrigger == "enter")
				if(e.keyCode == 13) this.host.change(this.host.getValue());
			else if(jpf.isSafari && this.host.XMLRoot) //safari issue (only old??)
				setTimeout('var o = jpf.lookup(' + this.host.uniqueId + ');o.change(o.getValue())');
			
			if(e.ctrlKey && (e.keyCode == 66 || e.keyCode == 73 || e.keyCode == 85)) return false; 
			
			//Autocomplete
			if(this.host.oContainer){
				var oTxt = this.host;
				var keyCode = e.keyCode;
				setTimeout(function(){oTxt.fillAutocomplete(keyCode);});
			}
			
			//Non masking
			if(!this.host.mask) return this.host.keyHandlerWA(e.keyCode, e.ctrlKey, e.shiftKey, e.altKey, e);
		}
		
		this.oInt.onkeyup = function(e){
			var keyCode = (e||event).keyCode, jmlNode = this.host;

			if(this.host.changeTrigger != "enter") {
				setTimeout(function(){
					if(!jmlNode.mask) jmlNode.change(jmlNode.getValue()); //this is a hack
					jmlNode.dispatchEvent("onkeyup", {keyCode : keyCode});
				});
			}
			else{
				jmlNode.dispatchEvent("onkeyup", {keyCode : keyCode});
			}
		}

		this.oInt.onfocus = function(){
			if(this.host.initial && this.value == this.host.initial){
				this.value = "";
				this.host.__setStyleClass(this.host.oExt, "", [this.host.baseCSSname + "Initial"]);
			}
		}
		
		this.oInt.onblur = function(){
			if(this.host.initial && this.value == ""){
				this.value = this.host.initial;
				this.host.__setStyleClass(this.host.oExt, this.host.baseCSSname + "Initial");
			}
		}

		if(!this.oInt.tagName.toLowerCase().match(/input|textarea/)){
			this.isHTMLBox = true;
			
			this.oInt.unselectable = "Off";
			this.oInt.contentEditable = true;
			this.oInt.style.width = "1px";
			
			this.oInt.select = function(){
				var r = document.selection.createRange();
				r.moveToElementText(this);
				r.select();
			}
		}
		
		this.oInt.deselect = function(){
			if(!document.selection) return;
			
			var r = document.selection.createRange();
			r.collapse();
			r.select();
		}
	}

	this.__loadJML = function(x){
		//Masking
		if(jpf.hasMsRangeObject){
			this.mask = x.getAttribute("mask");
			if(this.mask){
				masking = true;
				this.inherit(jpf.TextboxMask); /** @inherits jpf.TextboxMask */
				if(!this.mask.match(/PASSWORD/)) this.setMask(this.mask);
				this.maskmsg = x.getAttribute("maskmsg");
			}
		}
		
		//Initial Message
		this.initial = x.getAttribute("initial") || "";
		if(this.initial){
			this.oInt.onblur();
			this.setValue(this.initial);
		}
		
		//Triggering and Focus
		this.changeTrigger = jpf.XMLDatabase.getInheritedAttribute(x, "change") || "realtime";
		this.selectFocus = x.getAttribute("focusselect") == "true";
		if(this.mask){
			this.selectFocus = false;
			this.changeTrigger = "enter";
		}

		if(this.selectFocus){
			this.oInt.onmouseup = function(){
				if(focusSelect){
					this.select();
					focusSelect=false;
				}
				
				this.host.dispatchEvent("onmouseup");
				return false;
			}
		}
		
		//Special validation support using nativate max-length browser support
		if(x.getAttribute("maxlength") && this.oInt.tagName.toLowerCase().match(/input|textarea/))
			this.oInt.maxLength = parseInt(x.getAttribute("maxlength"));
		
		//Autocomplete
		var ac = $xmlns(x, "autocomplete", jpf.ns.jpf)[0];
		if(ac){
			this.inherit(jpf.TextboxAutocomplete); /** @inherits jpf.TextboxAutocomplete */
			this.initAutocomplete(ac);
		}
		
		jpf.JMLParser.parseChildren(this.jml, null, this);
	}
	
	this.__destroy = function(){
		this.oInt.onkeypress = 
		this.oInt.onmouseup = 
		this.oInt.onkeydown = 
		this.oInt.onkeyup = 
		this.oInt.onselectstart = null;
	}
}

/**
 * @constructor
 * @private
 */
jpf.TextboxMask = function(){
	/*
		Special Masking Values:
		- PASSWORD
		
		<j:Textbox name="custref" mask="CS20999999" maskmsg="" validation="/CS200[3-5]\d{4}/" invalidmsg="" bind="custref/text()" />
	*/
	
	var _FALSE_ = 9128748732;

	var _REF = {
		"0" : "\\d",
		"1" : "[12]",
		"9" : "[\\d ]",
		"#" : "[\\d +-]",
		"L" : "[A-Za-z]",
		"?" : "[A-Za-z ]",
		"A" : "[A-Za-z0-9]",
		"a" : "[A-Za-z0-9 ]",
		"X" : "[0-9A-Fa-f]",
		"V" : "[0-9A-Fa-fV]", //Vonage virtual mac address
		"x" : "[0-9A-Fa-f ]",
		"&" : "[^\s]",
		"C" : "."
	};

	var lastPos = -1;
	var masking = false;
	var initial, pos, myvalue, format, fcase, replaceChar, oExt = this.oExt;

	this.setPosition = function(setpos){
		setPosition(setpos || lastPos || 0);
	}

	this.__clear = function(){
		this.value = "";
		if(this.mask) return this.setValue("");
	}
	
	this.__supportedProperties = ["value"];
	this.__handlePropSet = function(prop, value){
		switch(prop){
			case "value":
				var data = "";
				if(this.includeNonTypedChars){
					for(var i=0;i<initial.length;i++){
						if(initial.substr(i,1) != value.substr(i,1)) data += value.substr(i,1);//initial.substr(i,1) == replaceChar
					}
				}
				
				this.__insertData(data || value);
			break;
		}
	}
	
	/* ***********************
			Keyboard Support
	************************/
	
	this.keyHandler = function(key, ctrlKey, shiftKey, altKey, e){
		if(this.dispatchEvent("onkeydown", {keyCode : key, ctrlKey : ctrlKey, shiftKey : shiftKey, altKey : altKey, htmlEvent : e}) === false) return false;

		switch(key){
			case 39:	
			//RIGHT
				setPosition(lastPos+1);
			break;
			case 37:
			//LEFT
				setPosition(lastPos-1);
			break;
			case 35:
			case 34:
				setPosition(myvalue.length);
			break;
			case 33:
			case 36:
				setPosition(0);
			break;
			case 8:
			//BACKSPACE
				deletePosition(lastPos-1);
				setPosition(lastPos-1);
			break;
			case 46:
			//DEL
				deletePosition(lastPos);
				setPosition(lastPos);
			break;
			default:
				if(key == 67 && ctrlKey)
					window.clipboardData.setData("Text", this.getValue());  
				/*else if((key == 86 && ctrlKey) || (shiftKey && key == 45)){
					this.setValue(window.clipboardData.getData("Text"));
					setPosition(lastPos);
				}*/
				else return;
			break;
		}
			
		return false
	}
	
	/* ***********************
			Init
	************************/
	
	this.__initMasking = function(){
		///this.keyHandler = this._keyHandler;
		this.keyHandlerWA = this._keyHandler; //temp solution
		masking = true;

		this.oInt.onkeypress = function(){
			var chr = String.fromCharCode(self.event.keyCode);
			chr = (self.event.shiftKey ? chr.toUpperCase() : chr.toLowerCase());
			if(setCharacter(chr)) setPosition(lastPos + 1);

			return false;
		}
		
		this.oInt.onmouseup = function(){
         var pos = Math.min(calcPosFromCursor(), myvalue.length);
         setPosition(pos);
         return false;
     }
		
		this.oInt.onpaste = function(){
			event.returnValue = false;
			this.host.setValue(window.clipboardData.getData("Text") || "");
			//setPosition(lastPos);
			setTimeout(function(){setPosition(lastPos);}, 1); //HACK good enough for now...
		}
		
		this.getValue = function(){
			if(this.includeNonTypedChars) return initial == this.oInt.value ? "" : this.oInt.value.replace(new RegExp(replaceChar, "g"), "");
			else return myvalue.join("");
		}
		
		this.setValue = function(value){
			if(this.includeNonTypedChars){
				for(var data="",i=0;i<initial.length;i++){
					if(initial.substr(i,1) != value.substr(i,1)) data += value.substr(i,1);//initial.substr(i,1) == replaceChar
				}
			}
			this.__insertData(data);
		}
	}
	
	this.setMask = function(m){
		if(!masking) this.__initMasking();
		
		var m = m.split(";");
		replaceChar = m.pop();
		this.includeNonTypedChars = parseInt(m.pop()) !== 0, mask = m.join(""); //why a join here???
		var validation = "", visual="", mode_case="-", strmode = false, startRight = false, chr;
		pos=[], format="", fcase="";
		
		for(var looppos=-1,i=0;i<mask.length;i++){
			chr = mask.substr(i,1);
			
			if(!chr.match(/[\!\'\"\>\<\\]/)) looppos++;
			else{
				if(chr == "!") startRight = true;
				else if(chr == "<" || chr == ">") mode_case = chr;
				else if(chr == "'" || chr == "\"") strmode = !strmode;
				continue;
			}
			
			if(!strmode && _REF[chr]){
				pos.push(looppos);
				visual += replaceChar;
				format += chr;
				fcase += mode_case;
				validation += _REF[chr];
			}
			else visual += chr;
		}

		this.oInt.value = visual;
		initial = visual;
		//pos = pos;
		myvalue = [];
		//format = format;
		//fcase = fcase;
		replaceChar = replaceChar;
		
		//setPosition(0);//startRight ? pos.length-1 : 0);
		
		//validation..
		//forgot \ escaping...
	}
	
	function checkChar(chr, p){
		var f = format.substr(p, 1);
		var c = fcase.substr(p, 1);
	
		if(chr.match(new RegExp(_REF[f])) == null) return _FALSE_;
		if(c == ">") return chr.toUpperCase();
		if(c == "<") return chr.toLowerCase();
		return chr;
	}
	
	function setPosition(p){
		if(p < 0) p = 0;

		var range = oExt.createTextRange();
		range.expand("textedit");
		range.select();
		
		if(pos[p] == null){
			range.collapse(false);
			range.select();
			lastPos = pos.length;
			return false;
		}
		
		range.collapse();
		range.moveStart("character", pos[p]);
		range.moveEnd("character", 1);
		range.select();

		lastPos = p;
	}
	
	function setCharacter(chr){
		if(pos[lastPos] == null) return false;
		
		var chr = checkChar(chr, lastPos);
		if(chr == _FALSE_) return false;

		var range = oExt.createTextRange();
		range.expand("textedit");
		range.collapse();
		range.moveStart("character", pos[lastPos]);
		range.moveEnd("character", 1);
		range.text = chr;
		if(jpf.window.getFocussedObject == this) range.select();
		
		myvalue[lastPos] = chr;
		
		return true;
	}
	
	function deletePosition(p){
		if(pos[p] == null) return false;
		
		var range = oExt.createTextRange();
		range.expand("textedit");
		range.collapse();
		range.moveStart("character", pos[p]);
		range.moveEnd("character", 1);
		range.text = replaceChar;
		range.select();
		
		//ipv lastPos
		myvalue[p] = " ";
	}
	
	this.__insertData = function(str){
		if(str == this.getValue()) return;
		str = this.dispatchEvent("oninsert", {data : str}) || str;
		
		if(!str){
			if(!this.getValue()) return; //maybe not so good fix... might still flicker when content is cleared
			for(var i=this.getValue().length-1;i>=0;i--) deletePosition(i);
			setPosition(0);	
			return;
		}
		
		for(var i=0;i<str.length;i++){
			lastPos = i;
			setCharacter(str.substr(i,1));
		}
		if(str.length) lastPos++;
	}
	
	function calcPosFromCursor(){
		var range = document.selection.createRange();
		r2 = range.duplicate();
		r2.expand("textedit");
		r2.setEndPoint("EndToStart", range);
		var lt = r2.text.length;
	
		for(var i=0;i<pos.length;i++)
			if(pos[i] > lt) return i == 0 ? 0 : i-1;
	}
}

/**
 * @constructor
 * @private
 */
jpf.TextboxAutocomplete = function(){
	/*
		missing features:
		- web service based autocomplete
	*/
	var autocomplete = {};
	
	this.initAutocomplete = function(ac){
		ac.parentNode.removeChild(ac);
		autocomplete.nodeset = ac.getAttribute("nodeset").split(":");
		autocomplete.method = ac.getAttribute("method");
		autocomplete.value = ac.getAttribute("value");
		autocomplete.count = parseInt(ac.getAttribute("count")) || 5;
		autocomplete.sort = ac.getAttribute("sort");
		autocomplete.lastStart = -1;
		
		this.oContainer = jpf.XMLDatabase.htmlImport(this.__getLayoutNode("Container"), this.oExt.parentNode, this.oExt.nextSibling);	
	}
	
	this.fillAutocomplete = function(keyCode){
		if(keyCode){
			switch(keyCode){
				case 9:
				case 27: 
				case 13:  
					return this.oContainer.style.display = "none";
				case 40: //DOWN
					if(autocomplete.suggestData && autocomplete.lastStart < autocomplete.suggestData.length){
						this.clear();
						var value = autocomplete.suggestData[autocomplete.lastStart++];
						this.oInt.value = value; //hack!
						this.change(value);
						//this.oInt.select(); this.oInt.focus();
						this.oContainer.style.display = "none";
						return;
					}
				break;
				case 38: //UP
					if(autocomplete.lastStart > 0){
						if(autocomplete.lastStart >= autocomplete.suggestData.length) 
							autocomplete.lastStart = autocomplete.suggestData.length - 1;

						this.clear();
						var value = autocomplete.suggestData[autocomplete.lastStart--];
						this.oInt.value = value; //hack!
						this.change(value);
						//this.oInt.select(); this.oInt.focus();
						this.oContainer.style.display = "none";
						return;
					}
				break;
			}
			
			if(keyCode > 10 && keyCode < 20) return;
		}
		
		if(autocomplete.method){
			var start=0, suggestData = self[autocomplete.method]();
			autocomplete.count = suggestData.length;
		}
		else{
			if(this.oInt.value.length==0){
				this.oContainer.style.display = "none";
				return;
			}
			if(!autocomplete.suggestData){
				//Get data from model
				var nodes = self[autocomplete.nodeset[0]].data.selectNodes(autocomplete.nodeset[1]);
				for(var value, suggestData=[],i=0;i<nodes.length;i++){
					value = jpf.getXmlValue(nodes[i], autocomplete.value);
					if(value) suggestData.push(value.toLowerCase());
				}
				if(autocomplete.sort) suggestData.sort();
				autocomplete.suggestData = suggestData;
			}
			else{
				suggestData = autocomplete.suggestData;
			}
			
			//Find Startpoint in lookup list
			var value = this.oInt.value.toUpperCase();
			for(var start=suggestData.length-autocomplete.count,i=0;i<suggestData.length;i++){
				if(value <= suggestData[i].toUpperCase()){
					start = i;
					break;
				}
			}
			
			autocomplete.lastStart = start;
		}
		
		//Create html items
		this.oContainer.innerHTML = "";
		
		for(var arr=[],j=start;j<Math.min(start+autocomplete.count, suggestData.length);j++){
			this.__getNewContext("Item")
			var oItem = this.__getLayoutNode("Item");
			jpf.XMLDatabase.setNodeValue(this.__getLayoutNode("Item", "caption"), suggestData[j]);
			
			oItem.setAttribute("onmouseover", 'this.className = "hover"');
			oItem.setAttribute("onmouseout", 'this.className = ""');
			oItem.setAttribute("onmousedown", 'event.cancelBubble = true');
			oItem.setAttribute("onclick", 'var o = jpf.lookup(' + this.uniqueId + ');o.oInt.value = this.innerHTML;o.change(this.innerHTML);o.oInt.select();o.oInt.focus();o.oContainer.style.display = "none";');
			
			arr.push(this.__getLayoutNode("Item"));
		}
		jpf.XMLDatabase.htmlImport(arr, this.oContainer);
		
		this.oContainer.style.display = "block";
	}
	
	this.setAutocomplete = function(model, traverse, value){
		autocomplete.lastStart = -1;
		autocomplete.suggestData = null;
		
		autocomplete.nodeset = [model, traverse];
		autocomplete.value = value;
		this.oContainer.style.display = "none";
	}
}

/*FILEHEAD(/in/Components/Tinymce.js)SIZE(3890)TIME(1203730484247)*/

/**
 * Component displaying the tinyMCE rich text editor. This
 * component functions as a wrapper to this popular editor
 * allowing full integration in Javeline PlatForm including
 * databinding and markup support.
 *
 * @classDescription		This class creates a new tinymce instance
 * @return {TinyMCE} Returns a new tinymce instance
 * @type {TinyMCE}
 * @constructor
 * @allowchild {smartbinding}
 * @addnode components:tinymce
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.9
 */
jpf.tinymce = function(pHtmlNode){
	jpf.register(this, "tinymce", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	/* ***********************
	  		Inheritance
	************************/
	this.inherit(jpf.DataBinding); /** @inherits jpf.DataBinding */
	
	/* ********************************************************************
										PROPERTIES
	*********************************************************************/
	
	//Options
	this.focussable = true; // This object can't get the focus
	this.inherit(jpf.Validation); /** @inherits jpf.Validation */
	this.inherit(jpf.XForms); /** @inherits jpf.XForms */

	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/
	
	this.getValue = function(){
		this.oExt.contentWindow.getEditorHtml();
	}
	
	this.keyHandler = function(key,ctrlKey,shiftKey,altKey){
		switch(key){
			default:
			return;
		}
		
		return false;
	}
	
	this.setValue = 
	this.loadHTML = function(strHTML){
		if(this.oExt.contentWindow.setEditorHtml && this.oExt.contentWindow.getEditorHtml() != strHTML)
			this.oExt.contentWindow.setEditorHtml(strHTML);
	}
	
	this.__clear = function(){
		if(this.oExt.contentWindow.setEditorHtml)
			this.oExt.contentWindow.setEditorHtml("");
	}
	
	this.__focus = function(){
		try{
			this.oExt.contentWindow.document.getElementsByTagName("IFRAME")[0].contentWindow.document.body.focus();
		}catch(e){}
	}
	this.__blur = function(){}
	
	/* ***************
		DATABINDING
	****************/
	
	this.__xmlUpdate = function(action, xmlNode, listenNode, UndoObj){
		//Action Tracker Support
		if(UndoObj) UndoObj.xmlNode = this.XMLRoot;//(contents ? contents.XMLRoot : this.XMLRoot);
		
		//Refresh Properties
		this.loadHTML(this.applyRuleSetOnNode("contents", this.XMLRoot) || "");
	}
	
	this.__load = function(node){
		//Add listener to XMLRoot Node
		jpf.XMLDatabase.addNodeListener(node, this);
		this.loadHTML(this.applyRuleSetOnNode("contents", node) || "");
	}
	
	/* *********
		INIT
	**********/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.initFrame = function(win){
		if(this.XMLRoot) this.reload();
	}
	
	this.draw = function(){
		pHtmlNode.insertAdjacentHTML("beforeend", "<iframe id='iframe_" + this.uniqueId + "' width='100%' height='100%' src='tinymce/HTMLEditor.htm?" + this.uniqueId + "'></iframe>");
		this.oExt = this.oInt = document.getElementById("iframe_" + this.uniqueId);
		this.oExt.contentWindow.uniqueId = this.uniqueId;
		this.oExt.contentWindow.host = this;
		
		this.oExt.host = this;
		this.oExt.onblur = function(){
			if(this.host.XMLRoot)
				this.host.change(this.contentWindow.getEditorHtml());	
		}
	}

	this.__loadJML = function(x){
		if(x.childNodes.length == 1 && x.firstChild.nodeType != 1) this.loadHTML(x.firstChild.nodeValue)
		else if(x.childNodes) jpf.JMLParser.parseChildren(x, this.oInt, this);
	}
	
	this.__destroy = function(){
		this.oExt.onblur = null;
	}
}

/*FILEHEAD(/in/Components/Toc.js)SIZE(6071)TIME(1205790104099)*/

/**
 * Component acting as the navigational instrument for any
 * component based on BaseTab. This component displays buttons
 * which can be used to navigate the different pages of for instance
 * a Submitform or Pages component. This component is page validation
 * aware and can display current page progress when connected to
 * a Submitform.
 *
 * @classDescription		This class creates a new toc
 * @return {Toc} Returns a new toc
 * @type {Toc}
 * @constructor
 * @addnode components:toc
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.8
 */
jpf.toc = function(pHtmlNode){
	jpf.register(this, "toc", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;

	/* ***********************
	  		Inheritance
	************************/
	this.inherit(jpf.Presentation); /** @inherits jpf.Presentation */
	
	this.editableParts = {"Page" : [["caption","@caption"]]};
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/
	
	this.represent = function(oJmlNode){
		this.oJmlNode = oJmlNode;
		var toc = this;
		
		oJmlNode.addEventListener("onafterswitch", function(e){
			toc.setActivePage(e.pageId);
		});
		
		if(oJmlNode.drawed) this.createReflection()
		else oJmlNode.addEventListener("ondraw", function(){toc.createReflection()});
	}
	
	this.createReflection = function(){
		var pages = this.oJmlNode.getPages();
		
		for(var l={},p=[],i=0;i<pages.length;i++){
			this.__getNewContext("Page");
			var oCaption = this.__getLayoutNode("Page", "caption");
			var oPage = this.__getLayoutNode("Page");
			this.__setStyleClass(oPage, "page" + i);
			
			oPage.setAttribute("onmouseover", 'jpf.lookup(' + this.uniqueId + ').__setStyleClass(this, "hover", null);');
			oPage.setAttribute("onmouseout", 'jpf.lookup(' + this.uniqueId + ').__setStyleClass(this, "", ["hover"]);');
			
			if(!pages[i].jml.getAttribute("caption")){
				jpf.issueWarning(0, "Page element without caption found.");
				//continue;
			}
			else{
				jpf.XMLDatabase.setNodeValue(oCaption, pages[i].jml.getAttribute("caption") || "");
			}

			oPage.setAttribute("onmousedown", 'setTimeout(function(){jpf.lookup(' + this.uniqueId + ').gotoPage(' + i + ')});');
			p.push(jpf.XMLDatabase.htmlImport(oPage, this.oInt));
			l[i] = p[p.length-1];
			
				this.__makeEditable("Page", p[i], pages[i].jml);
		}
		
		//XMLDatabase.htmlImport(p, this.oInt);
		this.pages = p;
		this.pagelookup = l;
		
		this.setActivePage(0);
		
		if(jpf.isGecko){
			var tocNode = this;
			setTimeout(function(){
				tocNode.oExt.style.height = tocNode.oExt.offsetHeight+1 + "px";
				tocNode.oExt.style.height = tocNode.oExt.offsetHeight-1 + "px";
			}, 10);
		}
	}
	
	this.gotoPage = function(nr){
		if(this.disabled) return false;
		if(this.oJmlNode.isValid && !this.oJmlNode.testing){
			var pages = this.oJmlNode.getPages();
			var activePage = this.oJmlNode.activePage;
			for(var i=activePage;i<nr;i++){
				pages[i].oExt.style.position = "absolute"; //hack
				pages[i].oExt.style.top = "-10000px"; //hack
				pages[i].oExt.style.display = "block"; //hack
				var test = !this.oJmlNode.isValid || this.oJmlNode.isValid(i < activePage, i < activePage, pages[i]);//false, activePage == i, pages[i], true);
				pages[i].oExt.style.display = ""; //hack
				pages[i].oExt.style.position = ""; //hack
				pages[i].oExt.style.top = ""; //hack
				pages[i].oExt.style.left = ""; //hack
				pages[i].oExt.style.width = "1px";
				pages[i].oExt.style.width = "";
	
				if(!test) return this.oJmlNode.setActiveTab(i);
			}
		}
		
		if(this.oJmlNode.showLoader) this.oJmlNode.showLoader(true, nr); 

		var oJmlNode = this.oJmlNode;
		setTimeout(function(){
			oJmlNode.setActiveTab(nr);
		}, 1);
		//setTimeout("jpf.lookup(" + this.oJmlNode.uniqueId + ").setActiveTab(" + nr + ");", 1);
	}
	
	this.setActivePage = function(active){
		if(this.disabled) return false;
		
		//Find previous known index and make sure it has known indexes after
		if(!this.pagelookup[active]){
			var page, last, is_between;
			for(page in this.pagelookup){
				if(page < active) last = page;
				if(page > active) is_between = true;
			}
			if(!last || !is_between) return; //exit if there are no known indexes
			active = last;
		}

		for(var isPast=true, i=0;i<this.pages.length;i++){
			if(this.pagelookup[active] == this.pages[i]){
				this.__setStyleClass(this.pages[i], "present", ["future", "past"]);
				isPast = false;
			}
			else if(isPast) this.__setStyleClass(this.pages[i], "past", ["future", "present"]);
			else this.__setStyleClass(this.pages[i], "future", ["past", "present"]);
			
			if(i == this.pages.length-1) this.__setStyleClass(this.pages[i], "last");
		}
	}
	
	/* *********
		INIT
	**********/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.draw = function(){
		//Build Main Skin
		this.oExt = this.__getExternal(); 
		this.oCaption = this.__getLayoutNode("Main", "caption", this.oExt);
		this.oInt = this.__getLayoutNode("Main", "container", this.oExt);
	}
	
	this.__loadJML = function(x){
		//if(!x.getAttribute("represent")) return;
		
		if(!x.getAttribute("represent")) throw new Error(1013, jpf.formErrorString(1013, this, "Find representation", "Could not find representation for the Toc: '" + x.getAttribute("represent") + "'"))
		
		var jmlNode = this;
		setTimeout(function(){
			jmlNode.represent(self[jmlNode.jml.getAttribute("represent")]);
		});
	}
}
/*FILEHEAD(/in/Components/Toolbar.js)SIZE(7071)TIME(1205790104099)*/

/**
 * Component displaying a bar containing Buttons and other JML components.
 * This component is usually positioned in the top of an application allowing
 * the user to choose from grouped tool buttons.
 *
 * @classDescription		This class creates a new toolbar
 * @return {Toolbar} Returns a new toolbar
 * @type {Toolbar}
 * @constructor
 * @allowchild bar
 * @define bar
 * @allowchild divider
 * @define divider
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.4
 */
jpf.toolbar = function(pHtmlNode){
	jpf.register(this, "toolbar", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;

	var lastbars = null, bars = [];

	/* ***********************
	  		Inheritance
	************************/
	this.inherit(jpf.Presentation); /** @inherits jpf.Presentation */
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/
	
	this.addDivider = function(elBar){
		elBar.children.push({
			tagName : "Divider",
			oExt : jpf.XMLDatabase.htmlImport(this.__getLayoutNode("Divider"), elBar.oInt),
			hide : function(){this.oExt.style.display = "none";},
			show : function(){this.oExt.style.display = "block";},
			getElementsByTagName : function(){return [];}
		});
	}
	
	this.addBar = function(xmlNode){
		this.__getNewContext("Bar");
		var p = this.__getLayoutNode("Bar");
		if(xmlNode.getAttribute("css")) p.setAttribute("style", xmlNode.getAttribute("css"));
		
		var elBar = jpf.XMLDatabase.htmlImport(p, this.oInt);
		var elBarInt = this.__getLayoutNode("Bar", "container", elBar);
		var isMenu = xmlNode.getAttribute("type") == "menu";
		if(isMenu) this.__setStyleClass(elBar, "menubar");

		var oBar = {
			jml : xmlNode,
			oExt : elBar,
			oInt : elBarInt,
			isMenu : isMenu,
			children : []
		};
		oBar.inherit = jpf.inherit;
		oBar.inherit(jpf.JmlDomAPI);
		oBar.childNodes = oBar.children;
		this.childNodes.push(oBar);
		
		if(xmlNode.getAttribute("height")) oBar.oExt.style.height = xmlNode.getAttribute("height") + "px";
		var id = bars.push(oBar) - 1;
		
		//parse children
		if(lastbars){
			var childs = lastbars[id].children;
			for(var i=0;i<childs.length;i++){
				if(childs[i].tagName == "divider") this.addDivider(oBar);
				else{
					childs[i].parentNode = oBar;
					elBarInt.appendChild(childs[i].oExt);
					oBar.children.push(childs[i]);
				}
			}
			oBar.childNodes = lastbars[id].childNodes;
		}
		else{
			var nodes = xmlNode.childNodes;
			for(var i=0;i<nodes.length;i++){
				if(nodes[i].nodeType != 1) continue;
				var tagName = nodes[i][jpf.TAGNAME];
				
				if(tagName == "divider") this.addDivider(oBar);
				else{
					var o = jpf.document.createElement(null, nodes[i], elBarInt, oBar);
					//oBar.childNodes.push(o);
					this.__setStyleClass(o.oExt, "toolbar_item");
					
					if(tagName == "button"){
						if(nodes[i].getAttribute("submenu")) this.setMenuButton(o, nodes[i], xmlNode, oBar);
						o.focussable = false;
					}
					
					o.barId = oBar.children.push(o) - 1;
					//o.focussable = false;
					
					//if(!o.onclick){
						var toolbar = this;
						o.addEventListener("onclick", function(){toolbar.dispatchEvent("onitemclick", {value : this.sValue});});
					//}
				}
			}
		}

		return oBar;
	}
	
	this.setMenuButton = function(o, node, xmlNode, oBar){
		o.submenu = node.getAttribute("submenu");
		o.bar = this;
		o.subbar = oBar;
		o.__setStateBehaviour();
		o.__blurhook = function(){if(this.value){this.__setState("Down", {}, "onmousedown");this.hideMenu()}}
		
		o.addEventListener("onmousedown", function(e){
			if(!e) e = event;
			
			if(this.value){
				self[this.submenu].hideMenu();
				this.__setState("Over", {}, "ontbover");
				if(this.bar.hasMoved) this.value = false;
				this.bar.menuIsPressed = false;
				return;
			}

			this.bar.menuIsPressed = this;
			
			var pos = jpf.compat.getAbsolutePosition(this.oExt, self[this.submenu].oExt.offsetParent || self[this.submenu].oExt.parentNode);
			self[this.submenu].oExt.style.left = pos[0] + "px";
			self[this.submenu].oExt.style.top = (pos[1]+this.oExt.offsetHeight) + "px";
			//self[this.submenu].oExt.style.visibility = "visible";
			//self[this.submenu].oExt.style.display = "block";
			self[this.submenu].showMenu();
			e.cancelBubble = true;
			//self[this.submenu].display(pos[0], pos[1]+this.oExt.offsetHeight, false, this);
			
			this.bar.hasMoved = false;
		});
		
		o.addEventListener("onmouseover", function(){
			if(this.bar.menuIsPressed && this.bar.menuIsPressed != this){
				this.bar.menuIsPressed.setValue(false);
				self[this.bar.menuIsPressed.submenu].hideMenu();
				
				this.setValue(true);
				
				this.bar.menuIsPressed = this;
				var pos = jpf.compat.getAbsolutePosition(this.oExt, self[this.submenu].oExt.offsetParent || self[this.submenu].oExt.parentNode);
				self[this.submenu].display(pos[0], pos[1]+this.oExt.offsetHeight, true, this);
				
				jpf.window.__focus(this);
				
				this.bar.hasMoved = true;
			}
		});
			
		//keyboard hook
		o.addEventListener("onkeydown", function(key){
			switch(key){
				case 37:
					//left
					var id = this.barId == 0 ? this.subbar.children.length-1 : this.barId-1;
					this.subbar.children[id].dispatchEvent("onmouseover");
				break;
				case 39:
					//right
					var id = this.barId >= this.subbar.children.length-1 ? 0 : this.barId+1;
					this.subbar.children[id].dispatchEvent("onmouseover");
				break;
			}
		});
		
		o.hideMenu = function(){
			this.setValue(false);
			//this.oExt.onmouseout({});
			this.__setState("Out", {}, "onmouseout");
			this.bar.menuIsPressed = false;
		}
	}
	
	/* *********
		INIT
	**********/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.draw = function(){
		//Build Main Skin
		this.oExt = this.__getExternal(); 
		this.oInt = this.__getLayoutNode("Main", "container", this.oExt);
	}
	
	this.__loadJML = function(x){
		if(bars.length){
			lastbars = bars;
			bars = []; 
			this.childNodes = [];
		}
		
		lastpages = null;

		var nodes = this.jml.childNodes;
		for(var i=0;i<nodes.length;i++){
			if(nodes[i].nodeType != 1) continue;
			var tagName = nodes[i][jpf.TAGNAME];

			if(tagName == "bar"){
				var p = this.addBar(nodes[i]);
				if(i == 0) this.__setStyleClass(p.oExt, "first");
				if(i == nodes.length-2) this.__setStyleClass(p.oExt, "last");
			}
		}

		lastbars = null;

		/* // Rich Text Editor
		
		var nodes = this.oExt.getElementsByTagName("*");
		for(var i=0;i<nodes.length;i++){
			if(nodes[i].tagName.toLowerCase() != "input" && nodes[i].tagName.toLowerCase() != "select") nodes[i].unselectable = "On";
			else nodes[i].unselectable = "Off";
		}*/
	}
}

/*FILEHEAD(/in/Components/Tree.js)SIZE(32950)TIME(1213461485214)*/

/* ***************
	TREE
****************/

var HAS_CHILD = 1<<1;
var IS_CLOSED = 1<<2;
var IS_LAST = 1<<3;
var IS_ROOT = 1<<4;

/**
 * Component displaying data whilst being aware of it's tree like structure and
 * allowing for special interaction to walk and view the data in an intuitive
 * manner for the user.
 *
 * @classDescription		This class creates a new tree
 * @return {Tree} Returns a new tree
 * @type {Tree}
 * @constructor
 * @allowchild {smartbinding}
 * @addnode components:tree
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.4
 */
jpf.tree = function(pHtmlNode){
	jpf.register(this, "tree", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	/* ********************************************************************
										PROPERTIES
	*********************************************************************/
	
	//Options
	this.isTreeArch = true; // Tree Architecture for loading Data
	this.focussable = true; // This object can get the focus
	this.inherit(jpf.Validation); /** @inherits jpf.Validation */
	this.inherit(jpf.XForms); /** @inherits jpf.XForms */
	
	this.clearMessage = "There are no items";
	this.startClosed = true;
	this.animType = 0;
	this.animSteps = 3;
	this.animSpeed = 20;
	
	this.dynCssClasses = [];
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/
	
	this.openAll = function(){

	}

	this.closeAll = function(){

	}
	
	this.selectPath = function(path){
		
	}
	
	/* ********************************************************************
										PRIVATE METHODS
	*********************************************************************/
	
	/* ***********************
			DRAGDROP
	************************/
	this.__showDragIndicator = function(sel, e){
		var x = e.offsetX + 22;
		var y = e.offsetY;

		this.oDrag.startX = x;
		this.oDrag.startY = y;

		
		document.body.appendChild(this.oDrag);
		//this.oDrag.getElementsByTagName("DIV")[0].innerHTML = this.selected.innerHTML;
		//this.oDrag.getElementsByTagName("IMG")[0].src = this.selected.parentNode.parentNode.childNodes[1].firstChild.src;
		this.__updateNode(this.value, this.oDrag);
		
		return this.oDrag;
	}
	
	this.__hideDragIndicator = function(){
		this.oDrag.style.display = "none";
	}
	
	this.__moveDragIndicator = function(e){
		this.oDrag.style.left = (e.clientX - this.oDrag.startX) + "px";
		this.oDrag.style.top = (e.clientY - this.oDrag.startY) + "px";
	}
	
	this.__initDragDrop = function(){
		if(!this.__hasLayoutNode("DragIndicator")) return;
		this.oDrag = jpf.XMLDatabase.htmlImport(this.__getLayoutNode("DragIndicator"), document.body);
		
		this.oDrag.style.zIndex = 1000000;
		this.oDrag.style.position = "absolute";
		this.oDrag.style.cursor = "default";
		this.oDrag.style.display = "none";
	}
	
	this.findValueNode = function(el){
		if(!el) return null;

		while(el && el.nodeType == 1 && !el.getAttribute(jpf.XMLDatabase.htmlIdTag)){
			el = el.parentNode;
		}

		return el && el.nodeType == 1 && el.getAttribute(jpf.XMLDatabase.htmlIdTag) ? el : null;
	}
	
	this.__dragout = function(dragdata){
		if(this.lastel) this.__setStyleClass(this.lastel, "", ["dragDenied", "dragInsert", "dragAppend", "selected", "indicate"]);
		this.__setStyleClass(this.selected, "selected", ["dragDenied", "dragInsert", "dragAppend", "indicate"]);
		
		/*if(this.lastel) this.__dragdeselect(this.lastel);
		this.__dragdeselect(this.selected);
		this.__select(this.selected);*/
		this.lastel = null;
	}

	this.__dragover = function(el, dragdata, extra){
		if(el == this.oExt) return;
		
		this.__setStyleClass(this.lastel || this.selected, "", ["dragDenied", "dragInsert", "dragAppend", "selected", "indicate"]);
		//if(this.lastel) this.__dragdeselect(this.lastel);
		//else this.__dragdeselect(this.selected);
		
		
		this.__setStyleClass(this.lastel = this.findValueNode(el), extra ? (extra[1].getAttribute("operation") == "insert-before" ? "dragInsert" : "dragAppend") : "dragDenied");
		//this.__dragselect(this.lastel = this.findValueNode(el));
	}

	this.__dragdrop = function(el, dragdata, extra){
		this.__setStyleClass(this.lastel || this.selected, !this.lastel && this.selected || this.lastel == this.selected ? "selected" : "", ["dragDenied", "dragInsert", "dragAppend", "selected", "indicate"]);
		//if(this.lastel) this.__dragdeselect(this.lastel);
		//this.__dragdeselect(this.selected);
		//this.__select(this.selected);
		
		this.lastel = null;
	}
	
	this.inherit(jpf.DragDrop); /** @inherits jpf.DragDrop */
	
	/* ***********************
		Sliding Functions
	************************/
	
	this.slideToggle = function(htmlNode, force){
		if(this.noCollapse) return;
		
		var id = htmlNode.getAttribute(jpf.XMLDatabase.htmlIdTag);
		while(!id && htmlNode.parentNode)
			var id = (htmlNode = htmlNode.parentNode).getAttribute(jpf.XMLDatabase.htmlIdTag);

		/*var xmlNode = jpf.XMLDatabase.getNodeById(id);
		var hasChildren = this.getTraverseNodes(xmlNode).length || this.emptyMessage && this.applyRuleSetOnNode("empty", xmlNode);
		if(!hasChildren) return false;
		else if(!htmlNode.className.match(/plus|min/)) this.fixItem(xmlNode, htmlNode);*/

		var container = this.__getLayoutNode("Item", "container", htmlNode);
		if(jpf.getStyle(container, "display") == "block"){
			if(force == 1) return;
			htmlNode.className = htmlNode.className.replace(/min/, "plus");
			this.slideClose(container, jpf.XMLDatabase.getNode(htmlNode));
		}
		else{
			if(force == 2) return;
			htmlNode.className = htmlNode.className.replace(/plus/, "min");
			this.slideOpen(container, jpf.XMLDatabase.getNode(htmlNode));
		}
	}
	
	//htmlNode || xmlNode
	var lastOpened = {};
	this.slideOpen = function(container, xmlNode){
		var htmlNode = jpf.XMLDatabase.findHTMLNode(xmlNode, this);
		if(!container)container = this.__findContainer(htmlNode);

		if(this.singleopen){
			var pNode = this.getTraverseParent(xmlNode)
			var p = (pNode || this.XMLRoot).getAttribute(jpf.XMLDatabase.xmlIdTag);
			if(lastOpened[p] && lastOpened[p][1] != xmlNode && this.getTraverseParent(lastOpened[p][1]) == pNode) 
				this.slideToggle(lastOpened[p][0], 2);//lastOpened[p][1]);
			lastOpened[p] = [htmlNode, xmlNode];
		}
		
		container.style.display = "block";

		new jpf.GuiAnimation(container, 'scrollheight', 0, container.scrollHeight, this.animType, this.animSteps, this.animSpeed, 
			function(container, data){
				if(data[1] && data[0].hasLoadStatus(data[1], "potential")){
					//'jpf.lookup(' + data[0].uniqueId + ').doUpdate(jpf.XMLDatabase.getElementById("' + data[1].getAttribute(jpf.XMLDatabase.xmlIdTag) + '"));'
					setTimeout(function(){data[0].doUpdate(data[1], container);});
					container.style.height = "auto";
				}
				else{
					//container.style.overflow = "visible";
					container.style.height = "auto";
				}
			}, [this, xmlNode]);
			
		/*animate([[container.style, "height", container.offsetHeight, container.scrollHeight], [container, "scrollTop", container.scrollHeight, container.scrollHeight]], 3, 10, function (o){
			container.style.overflow = "visible";
			container.style.height = "auto";
		});*/
	}

	this.slideClose = function(container, xmlNode){
		if(this.noCollapse) return;
		
		if(this.singleopen){
			var p = (this.getTraverseParent(xmlNode) || this.XMLRoot).getAttribute(jpf.XMLDatabase.xmlIdTag);
			lastOpened[p] = null;
		}
		
		container.style.height = container.offsetHeight;
		container.style.overflow = "hidden";

		new jpf.GuiAnimation(container, 'scrollheight', container.offsetHeight, 0, this.animType, this.animSteps, this.animSpeed, 
			function(container, data){
				container.style.display = "none";
			});
		
		/*animate([[container.style, "height", container.offsetHeight, 1], [container, "scrollTop", container.scrollHeight, container.scrollHeight]], 3, 10, function(container, data){
			container.style.display = "none";
		});*/
	}

	//check databinding for how this is normally implemented
	//PROCINSTR
	this.doUpdate = function(xmlNode, container){
		var rule = this.getNodeFromRule("insert", xmlNode, null, true);
		var xmlContext = rule ? xmlNode.selectSingleNode(rule.getAttribute("select") || ".") : null;
		
		if(rule && xmlContext){
			this.setLoadStatus(xmlNode, "loading");
			
			if(rule.getAttribute("get")) this.getModel().insertFrom(rule.getAttribute("get"), xmlContext, xmlContext, this);
			else{
				var data = this.applyRuleSetOnNode("insert", xmlNode);
				if(data) this.insert(data, xmlContext);
			}
		}
		else if(!this.prerender){
			this.setLoadStatus(xmlNode, "loading");
			var result = this.__addNodes(xmlNode, container, true); //checkChildren ???
			xmlUpdateHandler.call(this, "insert", xmlNode, result);
		}
	}
	
	/* ***********************
				Skin
	************************/

	this.State = {};
	this.State[0] 											= "";
	this.State[HAS_CHILD] 								= "min";
	this.State[HAS_CHILD | IS_CLOSED] 				= "plus";
	this.State[IS_LAST] 									= "last";
	this.State[IS_LAST | HAS_CHILD] 					= "minlast";
	this.State[IS_LAST | HAS_CHILD | IS_CLOSED] 	= "pluslast";
	this.State[IS_ROOT] 									= "root";

	this.fixItem = function(xmlNode, htmlNode, isDeleting, oneLeft, noChildren){
		if(!htmlNode) return;

		if(isDeleting){
			//if isLast fix previousSibling
			if(prevSib = this.getNextTraverse(xmlNode, true))
				this.fixItem(prevSib, this.getNodeFromCache(prevSib.getAttribute(jpf.XMLDatabase.xmlIdTag)+"|"+this.uniqueId), null, true);

			//if no sibling fix parent
			if(!this.emptyMessage && xmlNode.parentNode.selectNodes(this.ruleTraverse).length == 1)
				this.fixItem(xmlNode.parentNode, this.getNodeFromCache(xmlNode.parentNode.getAttribute(jpf.XMLDatabase.xmlIdTag)+"|"+this.uniqueId), null, false, true); 
		}
		else{
			var container = this.__getLayoutNode("Item", "container", htmlNode);
			if(noChildren) var hasChildren = false;
			else if(xmlNode.selectNodes(this.ruleTraverse).length > 0) var hasChildren = true;
			else if(this.bindingRules["insert"] && this.getNodeFromRule("insert", xmlNode)) var hasChildren = true;
			else var hasChildren = false;
			
			var isClosed = hasChildren && container.style.display != "block";
			var isLast = this.getNextTraverse(xmlNode, null, oneLeft ? 2 : 1) ? false : true;

			var state = (hasChildren ? HAS_CHILD : 0) | (isClosed ? IS_CLOSED : 0) | (isLast ? IS_LAST : 0);
			this.__setStyleClass(this.__getLayoutNode("Item", "class", htmlNode), this.State[state], ["min", "plus", "last", "minlast", "pluslast"]);
			this.__setStyleClass(this.__getLayoutNode("Item", "container", htmlNode), this.State[state], ["min", "plus", "last", "minlast", "pluslast"]);
			
			if(!hasChildren) container.style.display = "none";
			
			if(state & HAS_CHILD){
				this.__getLayoutNode("Item", "openclose", htmlNode).onmousedown = new Function('e', 'if(!e) e = event; if(e.button == 2) return;var o = jpf.lookup(' + this.uniqueId + ');o.slideToggle(this);if(o.onmousedown) o.onmousedown(e, this);jpf.cancelBubble(e, o);');
				this.__getLayoutNode("Item", "icon", htmlNode)[this.opencloseaction || "ondblclick"] = new Function('var o = jpf.lookup(' + this.uniqueId + '); ' +
					'o.cancelRename();' + 
					' o.slideToggle(this);o.choose();');
				this.__getLayoutNode("Item", "select", htmlNode)[this.opencloseaction || "ondblclick"] = new Function('var o = jpf.lookup(' + this.uniqueId + '); ' +
					'o.cancelRename();' + 
					' this.dorename=false;o.slideToggle(this);o.choose();');
			}
			/*else{
				//Experimental
				this.__getLayoutNode("Item", "openclose", htmlNode).onmousedown = null;
				this.__getLayoutNode("Item", "icon", htmlNode)[this.opencloseaction || "ondblclick"] = null;
				this.__getLayoutNode("Item", "select", htmlNode)[this.opencloseaction || "ondblclick"] = null;
			}*/
		}
	}

	//This can be optimized by NOT using getLayoutNode all the time
	this.initNode = function(xmlNode, state, Lid){
		//Setup Nodes Interaction
		this.__getNewContext("Item");
		
		var hasChildren = state & HAS_CHILD || this.emptyMessage && this.applyRuleSetOnNode("empty", xmlNode);
		
		//should be restructured and combined events set per element 
		this.__getLayoutNode("Item").setAttribute("onmouseover", 'var o = jpf.lookup(' + this.uniqueId + ');if(o.onmouseover) o.onmouseover(event, this)');
		this.__getLayoutNode("Item").setAttribute("onmouseout", 'var o = jpf.lookup(' + this.uniqueId + ');if(o.onmouseout) o.onmouseout(event, this)');
		this.__getLayoutNode("Item").setAttribute("onmousedown", 'var o = jpf.lookup(' + this.uniqueId + ');if(o.onmousedown) o.onmousedown(event, this);');
		
		//Set open/close skin class & interaction
		this.__setStyleClass(this.__getLayoutNode("Item", "class"), this.State[state]).setAttribute(jpf.XMLDatabase.htmlIdTag, Lid);
		this.__setStyleClass(this.__getLayoutNode("Item", "container"), this.State[state])
		this.__setStyleClass(this.__getLayoutNode("Item"), xmlNode.tagName)
		var elOpenClose = this.__getLayoutNode("Item", "openclose");
		if(hasChildren) elOpenClose.setAttribute(this.opencloseaction || "onmousedown", 'var o = jpf.lookup(' + this.uniqueId + ');o.slideToggle(this);if(o.onmousedown) o.onmousedown(event, this);jpf.cancelBubble(event,o);');
		
		//Icon interaction
		var elIcon = this.__getLayoutNode("Item", "icon");
		if(hasChildren){
			var strFunc = 'var o = jpf.lookup(' + this.uniqueId + '); ' +
				'o.cancelRename();' + 
				'o.slideToggle(this);jpf.cancelBubble(event,o);o.choose();';
			if(this.opencloseaction != "onmousedown") elIcon.setAttribute(this.opencloseaction || "ondblclick", strFunc);
		}
		if(elIcon){
			elIcon.setAttribute("onmousedown", 'jpf.lookup(' + this.uniqueId + ').select(this);' + (strFunc && this.opencloseaction == "onmousedown" ? strFunc : ""));
			if(!elIcon.getAttribute("ondblclick")) elIcon.setAttribute("ondblclick", 'jpf.lookup(' + this.uniqueId + ').choose();');
		}
		
		//Select interaction
		var elSelect = this.__getLayoutNode("Item", "select");
		if(hasChildren){
			var strFunc2 = 'var o = jpf.lookup(' + this.uniqueId + ');' +
				'o.cancelRename();' + 
				'o.slideToggle(this);jpf.cancelBubble(event,o)';
			if(this.opencloseaction != "onmousedown") elSelect.setAttribute(this.opencloseaction || "ondblclick", strFunc2);
		}
		//if(event.button != 1) return; 
		elSelect.setAttribute("onmousedown", 'var o = jpf.lookup(' + this.uniqueId + ');if(!o.renaming && o.isFocussed() && jpf.XMLDatabase.isChildOf(o.selected, this) && o.value) this.dorename = true;o.select(this);if(o.onmousedown) o.onmousedown(event, this);' + (strFunc2 && this.opencloseaction == "onmousedown" ? strFunc2 : ""));
		if(!elSelect.getAttribute("ondblclick")) elSelect.setAttribute("ondblclick", 'var o = jpf.lookup(' + this.uniqueId + ');' +
			'o.cancelRename();' + 
			'o.choose();');

		elSelect.setAttribute("onmouseup", 'if(this.dorename) jpf.lookup(' + this.uniqueId + ').startDelayedRename(event); this.dorename = false;');
		
		//elItem.setAttribute("contextmenu", 'alert(1);var o = jpf.lookup(' + this.uniqueId + ');o.dispatchEvent("oncontextMenu", o.value);');
		
		//Setup Nodes Identity (Look)
		if(elIcon){
			var iconURL = this.applyRuleSetOnNode("icon", xmlNode);
			if(iconURL){
				if(elIcon.tagName.match(/^img$/i)) elIcon.setAttribute("src", this.iconPath + iconURL);
				else elIcon.setAttribute("style", "background-image:url(" + this.iconPath + iconURL + ")");
			}
		}

		var elCaption = this.__getLayoutNode("Item", "caption");
		if(elCaption) jpf.XMLDatabase.setNodeValue(elCaption, this.applyRuleSetOnNode("caption", xmlNode));
		
		var cssClass = this.applyRuleSetOnNode("css", xmlNode);
		if(cssClass){
			this.__setStyleClass(this.__getLayoutNode("Item", null, this.__getLayoutNode("Item")), cssClass);
			if(cssClass) this.dynCssClasses.push(cssClass);
		}

		return this.__getLayoutNode("Item");
	}
	
	this.__deInitNode = function(xmlNode, htmlNode){
		//Lookup container
		var containerNode = this.__getLayoutNode("Item", "container", htmlNode);
		var pContainer = htmlNode.parentNode;
		
		//Remove htmlNodes from tree
		containerNode.parentNode.removeChild(containerNode);
		pContainer.removeChild(htmlNode);
		
		//Fix Images (+, - and lines)
		if(xmlNode.parentNode != this.XMLRoot) this.fixItem(xmlNode, htmlNode, true);
		
		if(this.emptyMessage && !pContainer.childNodes.length) this.setEmpty(pContainer);
		
		//Fix look (tree thing)
		this.fixItem(xmlNode, htmlNode, true);
		//this.fixItem(xmlNode.parentNode, jpf.XMLDatabase.findHTMLNode(xmlNode.parentNode, this));
		/*throw new Error();
		if(xmlNode.previousSibling) //should use traverse here
			this.fixItem(xmlNode.previousSibling, jpf.XMLDatabase.findHTMLNode(xmlNode.previousSibling, this));*/
	}
	
	this.__moveNode = function(xmlNode, htmlNode){
		if(!self.jpf.debug && !htmlNode) return;
		
		var oPHtmlNode = htmlNode.parentNode;
		var pHtmlNode = jpf.XMLDatabase.findHTMLNode(xmlNode.parentNode, this);
		//if(!pHtmlNode) return;
		
		var beforeNode = xmlNode.nextSibling ? jpf.XMLDatabase.findHTMLNode(this.getNextTraverse(xmlNode), this) : null;
		var pContainer = pHtmlNode ? this.__getLayoutNode("Item", "container", pHtmlNode) : this.oInt;
		var container = this.__getLayoutNode("Item", "container", htmlNode);

		if(pContainer != oPHtmlNode && this.getTraverseNodes(xmlNode.parentNode).length == 1) this.clearEmpty(pContainer);

		pContainer.insertBefore(htmlNode, beforeNode);
		pContainer.insertBefore(container, beforeNode);
		
		if(!this.startClosed){
			//pContainer.style.display = "block";
			//pContainer.style.height = "auto";
		}
		
		if(this.emptyMessage && !oPHtmlNode.childNodes.length) this.setEmpty(oPHtmlNode);
		
		if(this.openOnAdd && pHtmlNode != this.oInt && pContainer.style.display != "block") 
			this.slideOpen(pContainer, pHtmlNode);
		
		//Fix look (tree thing)
		this.fixItem(xmlNode, htmlNode);
		this.fixItem(xmlNode.parentNode, jpf.XMLDatabase.findHTMLNode(xmlNode.parentNode, this));
		if(this.getNextTraverse(xmlNode, true)){ //should use traverse here
			this.fixItem(this.getNextTraverse(xmlNode, true), jpf.XMLDatabase.findHTMLNode(this.getNextTraverse(xmlNode, true), this));
		}
	}
	
	this.__updateNode = function(xmlNode, htmlNode){
		//Update Identity (Look)
		var elIcon = this.__getLayoutNode("Item", "icon", htmlNode);
		//if(!elIcon) alert(htmlNode.outerHTML);
		var iconURL = this.applyRuleSetOnNode("icon", xmlNode);
		if(elIcon && iconURL){
			if(elIcon.tagName && elIcon.tagName.match(/^img$/i)) elIcon.src = this.iconPath + iconURL;
			else elIcon.style.backgroundImage = "url(" + this.iconPath + iconURL + ")";
		}

		var elCaption = this.__getLayoutNode("Item", "caption", htmlNode);
		if(elCaption){
			if(elCaption.nodeType == 1)
				elCaption.innerHTML = this.applyRuleSetOnNode("caption", xmlNode);
			else elCaption.nodeValue = this.applyRuleSetOnNode("caption", xmlNode);
		}

		var cssClass = this.applyRuleSetOnNode("css", xmlNode);
		if(cssClass || this.dynCssClasses.length){
			this.__setStyleClass(htmlNode, cssClass, this.dynCssClasses);
			if(cssClass && !this.dynCssClasses.contains(cssClass)) this.dynCssClasses.push(cssClass);
		}
	}
	
	this.clearEmpty = function(container){
		container.innerHTML = "";
	}
		
	this.setEmpty = function(container){
		this.__getNewContext("Empty");
		var oItem = this.__getLayoutNode("Empty");
		this.__getLayoutNode("Empty", "caption").nodeValue = this.emptyMessage;
		jpf.XMLDatabase.htmlImport(oItem, container);
		
		if(!this.startClosed){
			if(container.style){
				//container.style.display = "block";
				//container.style.height = "auto";
			}
			//else container.setAttribute("style", "display:block;height:auto;");
		}
	}
	
	this.__setLoading = function(xmlNode, container){
		this.__getNewContext("Loading");
		this.setLoadStatus(xmlNode, "potential");
		jpf.XMLDatabase.htmlImport(this.__getLayoutNode("Loading"), container);
	}
	
	this.__removeLoading = function(htmlNode){
		if(!htmlNode) return;
		this.__getLayoutNode("Item", "container", htmlNode).innerHTML = "";
	}
	
	function xmlUpdateHandler(e){
		/*
			Display the animation if the item added is 
			* Not in the cache
			- Being insterted using xmlUpdate
			- there is at least 1 child inserted
		*/
		
		if(e.action == "move-away")
			this.fixItem(e.xmlNode, jpf.XMLDatabase.findHTMLNode(e.xmlNode, this), true);

		if(e.action != "insert") return;
		
		var htmlNode = this.getNodeFromCache(e.xmlNode.getAttribute(jpf.XMLDatabase.xmlIdTag)+"|"+this.uniqueId);
		if(!htmlNode) return;
		if(this.hasLoadStatus(e.xmlNode, "loading") && e.result.length > 0){
			var container = this.__getLayoutNode("Item", "container", htmlNode);
			this.slideOpen(container, e.xmlNode);
		}
		else this.fixItem(e.xmlNode, htmlNode);
		
		//Can this be removed?? (because it was added in the insert function)
		if(this.hasLoadStatus(e.xmlNode, "loading"))
			this.setLoadStatus(e.xmlNode, "loaded");
	}
	
	this.addEventListener("onxmlupdate", xmlUpdateHandler);
	
	/* ***********************
		Keyboard Support
	************************/
	this.addEventListener("onbeforerename", function(){
		if(this.tempsel){
			clearTimeout(this.timer);
			this.select(this.tempsel);
			this.tempsel = null;
			this.timer = null;
		}
	});
	
	this.keyHandler = function(key, ctrlKey, shiftKey, altKey){
		if(!this.selected) return;
		//if(!this.selected || this.dragging) return;
		//var img = this.selected.parentNode.parentNode.firstChild.firstChild;

		switch(key){
			case 109:
			case 37:
			//LEFT
				if(this.tempsel){
					clearTimeout(this.timer);
					this.select(this.tempsel);
					this.tempsel = null;
					this.timer = null;
				}
			
				if(this.value.selectSingleNode(this.ruleTraverse))
					this.slideToggle(this.selected, 2)
			break;
			case 107:
			case 39:
			//RIGHT
				if(this.tempsel){
					clearTimeout(this.timer);
					this.select(this.tempsel);
					this.tempsel = null;
					this.timer = null;
				}
			
				if(this.value.selectSingleNode(this.ruleTraverse))
					this.slideToggle(this.selected, 1)
			break;
			case 46:
			//DELETE
				var xmlNode = this.value;
				var i=0, ln=1, nextNode = xmlNode;
				this.remove(xmlNode, true);
			break;
			case 187:
			//+
				if(shiftKey) this.keyHandler(39);
			break;
			case 189:
			//-
				if(!shiftKey) this.keyHandler(37);
			break;
			case 38:
			//UP
				if(!this.value && !this.tempsel) return;
				var node = this.tempsel ? jpf.XMLDatabase.getNode(this.tempsel) : this.value;
				
				var sNode = this.getNextTraverse(node, true);
				if(sNode){
					var nodes = sNode.selectNodes(this.ruleTraverse);
					
					do{
						var container = this.__getLayoutNode("Item", "container", this.getNodeFromCache(jpf.XMLDatabase.getID(sNode, this)));
						if(jpf.getStyle(container, "display") == "block"){
							if(nodes.length) sNode = nodes[nodes.length-1];
							else break;
						}
						else break;
					}while(sNode && (nodes = sNode.selectNodes(this.ruleTraverse)).length);
				}
				else if(node.parentNode == this.XMLRoot) return;
				else sNode = node.parentNode;

				if(sNode && sNode.nodeType == 1){
					clearTimeout(this.timer);
					var id = jpf.XMLDatabase.getID(sNode, this);
					this.__deselect(this.tempsel || this.selected);
					this.tempsel = this.__select(document.getElementById(id));//SHOULD BE FAKE SELECT
					this.timer = setTimeout('var o = jpf.lookup(' + this.uniqueId + ');o.tempsel=null;o.timer=null;o.select(document.getElementById("' + id + '"));', 300);
				}
				
				if(this.tempsel && this.tempsel.offsetTop < this.oExt.scrollTop)
					this.oExt.scrollTop = this.tempsel.offsetTop;
				
				return false;
			break;
			case 40:
			//DOWN
				if(!this.value && !this.tempsel) return;
				var node = this.tempsel ? jpf.XMLDatabase.getNode(this.tempsel) : this.value;
				
				var sNode = node.selectSingleNode(this.ruleTraverse);
				if(sNode){
					var container = this.__getLayoutNode("Item", "container", this.getNodeFromCache(jpf.XMLDatabase.getID(node, this)));
					if(jpf.getStyle(container, "display") != "block") sNode = null;
				}
				
				while(!sNode && node.parentNode){
					var i=0, nodes = node.parentNode.selectNodes(this.ruleTraverse);
					while(nodes[i] && nodes[i] != node) i++;
					sNode	= nodes[i+1];
					node = node.parentNode;
				}
				
				if(sNode && sNode.nodeType == 1){
					clearTimeout(this.timer);
					var id = jpf.XMLDatabase.getID(sNode, this);
					this.__deselect(this.tempsel || this.selected);
					this.tempsel = this.__select(document.getElementById(id));//SHOULD BE FAKE SELECT
					this.timer = setTimeout('var o = jpf.lookup(' + this.uniqueId + ');o.tempsel=null;o.select(document.getElementById("' + id + '"));', 300);
				}
				
				if(this.tempsel && this.tempsel.offsetTop + this.tempsel.offsetHeight > this.oExt.scrollTop + this.oExt.offsetHeight)
					this.oExt.scrollTop = this.tempsel.offsetTop - this.oExt.offsetHeight + this.tempsel.offsetHeight + 10;
				
				return false;
			break;
		}
	}
	
	/* ***********************
			  RENAME
	************************/
	this.__getCaptionElement = function(){
		var x = this.__getLayoutNode("Item", "caption", this.selected);
		return x.nodeType == 1 ? x : x.parentNode;
	}
	
	/* ***********************
			DATABINDING
	************************/

	this.nodes = [];

	this.__add = function(xmlNode, Lid, xmlParentNode, htmlParentNode, beforeNode, isLast){
		//Why is this function called 3 times when adding one node? (hack/should)
		var loadChildren = this.bindingRules["insert"] ? this.getNodeFromRule("insert", xmlNode) : false;
		var hasChildren = loadChildren || xmlNode.selectSingleNode(this.ruleTraverse) ? true : false;
		
		var startClosed = this.startClosed;// || this.applyRuleSetOnNode("collapse", xmlNode, ".") !== false;
		var state = (hasChildren ? HAS_CHILD : 0) | (startClosed && hasChildren  || loadChildren ? IS_CLOSED : 0) | (isLast ? IS_LAST : 0);

		var htmlNode = this.initNode(xmlNode, state, Lid);
		var container = this.__getLayoutNode("Item", "container");
		if(!startClosed && !this.noCollapse) container.setAttribute("style", "overflow:visible;height:auto;display:block;");
		
		//TEMP on for dynamic subloading
		if(!hasChildren || loadChildren) container.setAttribute("style", "display:none;");
		
		//Dynamic SubLoading (Insertion) of SubTree
		if(loadChildren && !this.hasLoadStatus(xmlNode))
			this.__setLoading(xmlNode, container);
		else if(!this.getTraverseNodes(xmlNode).length && this.applyRuleSetOnNode("empty", xmlNode))
			this.setEmpty(container);
		
		if(!htmlParentNode && xmlParentNode == this.XMLRoot){
			this.nodes.push(htmlNode);
			if(!jpf.XMLDatabase.isChildOf(htmlNode, container, true)) this.nodes.push(container);
			
			this.__setStyleClass(htmlNode, "root");
			this.__setStyleClass(container, "root");
		}
		else{
			if(!htmlParentNode){
				var htmlParentNode = jpf.XMLDatabase.findHTMLNode(xmlNode.parentNode, this);
				htmlParentNode = htmlParentNode ? this.__getLayoutNode("Item", "container", htmlParentNode) : this.oInt;
			}
			
			if(htmlParentNode == this.oInt){
				this.__setStyleClass(htmlNode, "root");
				this.__setStyleClass(container, "root");
			}
			
			if(!beforeNode && this.getNextTraverse(xmlNode)) beforeNode = jpf.XMLDatabase.findHTMLNode(this.getNextTraverse(xmlNode), this);
			if(beforeNode && beforeNode.parentNode != htmlParentNode) beforeNode = null;
		
			if(htmlParentNode.style && this.getTraverseNodes(xmlNode.parentNode).length == 1) this.clearEmpty(htmlParentNode);
		
			//alert("|" + htmlNode.nodeType + "-" + htmlParentNode.nodeType + "-" + beforeNode + ":" + container.nodeType);
			//Insert Node into Tree
			if(htmlParentNode.style){
				jpf.XMLDatabase.htmlImport(htmlNode, htmlParentNode, beforeNode);
				if(!jpf.XMLDatabase.isChildOf(htmlNode, container, true)) 
					var container = jpf.XMLDatabase.htmlImport(container, htmlParentNode, beforeNode);
			}
			else{
				htmlParentNode.insertBefore(htmlNode, beforeNode);
				htmlParentNode.insertBefore(container, beforeNode);
			}

			//Fix parent if child is added to drawn parentNode
			if(htmlParentNode.style){
				if(!startClosed && this.openOnAdd && htmlParentNode != this.oInt && htmlParentNode.style.display != "block") 
					this.slideOpen(htmlParentNode, xmlParentNode);
				
				//this.fixItem(xmlNode, htmlNode); this one shouldn't be called, because it should be set right at init
				this.fixItem(xmlParentNode, jpf.XMLDatabase.findHTMLNode(xmlParentNode, this));
				if(this.getNextTraverse(xmlNode, true)){ //should use traverse here
					this.fixItem(this.getNextTraverse(xmlNode, true), jpf.XMLDatabase.findHTMLNode(this.getNextTraverse(xmlNode, true), this));
				}
			}
		}
		
		if(this.prerender) this.__addNodes(xmlNode, container, true); //checkChildren ???
		else{
			this.setLoadStatus(xmlNode, "potential");
		}

		return container;
	}
	
	this.__fill = function(){
		//if(!this.nodes.length) return;
		//this.oInt.innerHTML = "";
		jpf.XMLDatabase.htmlImport(this.nodes, this.oInt);
		this.nodes.length = 0;

		//for(var i=0;i<this.nodes.length;i++)
			//jpf.XMLDatabase.htmlImport(this.nodes[i], this.oInt);
		//this.nodes.length = 0;
	}
	
	this.__getParentNode = function(htmlNode){
		return htmlNode ? this.__getLayoutNode("Item", "container", htmlNode) : this.oInt;
	}
	
	/* ***********************
	  		SELECT
	************************/
	
	this.__calcSelectRange = function(xmlStartNode, xmlEndNode){
		//should be implemented :)
		return [xmlStartNode, xmlEndNode];
	}
	
	this.__findContainer = function(htmlNode){
		return this.__getLayoutNode("Item", "container", htmlNode);
	}
	
	this.inherit(jpf.MultiSelect); /** @inherits jpf.MultiSelect */
	this.inherit(jpf.Cache); /** @inherits jpf.Cache */
	this.multiselect = false; // Initially Disable MultiSelect
	
	this.__selectDefault = function(xmlNode){
		if(this.select(this.getFirstTraverseNode(xmlNode))) return true;
		else{
			var nodes = this.getTraverseNodes(xmlNode);
			for(var i=0;i<nodes.length;i++){
				if(this.__selectDefault(nodes[i])) return true;
			}
		}
	}
	
	/* ***********************
	  Other Inheritance
	************************/
	
	this.inherit(jpf.Presentation); /** @inherits jpf.Presentation */
	this.inherit(jpf.DataBinding); /** @inherits jpf.DataBinding */
	
	this.inherit(jpf.Rename); /** @inherits jpf.Rename */
	
	/* *********
		INIT
	**********/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	//render the outer framework of this object
	this.draw = function(){
		//Build Main Skin
		this.oExt = this.__getExternal(); 
		this.oInt = this.__getLayoutNode("Main", "container", this.oExt);
		this.opencloseaction = this.__getOption("Main", "openclose");
		
		//Need fix...
		//this.oExt.style.MozUserSelect = "none";

		this.oExt.onclick = function(e){
			this.host.dispatchEvent("onclick", {htmlEvent : e || event});
		}
	}
	
	this.__loadJML = function(x){
		this.openOnAdd = !jpf.isFalse(x.getAttribute("openonadd"));
		this.startClosed = !jpf.isFalse(this.jml.getAttribute("startclosed") || this.__getOption("Main", "startclosed"));
		this.noCollapse = jpf.isTrue(this.jml.getAttribute("nocollapse"));
		if(this.noCollapse) this.startClosed = false;
		this.singleopen = jpf.isTrue(this.jml.getAttribute("singleopen"));
		this.prerender = !jpf.isFalse(this.jml.getAttribute("prerender"));
		
		jpf.JMLParser.parseChildren(this.jml, null, this);
	}
	
	this.__destroy = function(){
		this.oExt.onclick = null;
		jpf.removeNode(this.oDrag);
		this.oDrag = null;
	}
}

/*FILEHEAD(/in/Components/Workarea.js)SIZE(10032)TIME(1203730484247)*/

/**
 * Component displaying an area containing elements which can be freely 
 * placed and moved in the two dimensional plane. Individual elements 
 * can be locked, their z-indexes can be changed. This component
 * allows for alignment of multiple elements.
 *
 * @classDescription		This class creates a new workarea
 * @return {Workarea} Returns a new workarea
 * @type {Workarea}
 * @constructor
 * @allowchild {smartbinding}
 * @addnode components:workarea
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.4
 */
jpf.workarea = function(pHtmlNode){
	jpf.register(this, "workarea", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;
	
	/* ***********************
			  RENAME
	************************/
	
	this.__getCaptionElement = function(){
		var x = this.__getLayoutNode("Item", "caption", this.selected);
		return x.nodeType == 1 ? x : x.parentNode;
	}
	
	this.addEventListener("onafterselect",function(e){
		if(this.hasFeature(__VALIDATION__)) this.validate();
	});
	
	/* ***********************
	  Other Inheritance
	************************/
	this.inherit(jpf.BaseList); /** @inherits jpf.BaseList */
	
	this.keyHandler = function(key, ctrlKey, shiftKey, altKey){
		if(!this.value) return;
		var value = (ctrlKey ? 10 : (shiftKey ? 100 : 1));
		
		switch(key){
			case 37:
				this.MoveTo(this.value, parseInt(this.applyRuleSetOnNode("left", this.value)) - value, this.applyRuleSetOnNode("top", this.value));  
			return false;
			case 38:
				this.MoveTo(this.value, this.applyRuleSetOnNode("left", this.value), parseInt(this.applyRuleSetOnNode("top", this.value)) - value);
			return false;
			case 39:  
				this.MoveTo(this.value, parseInt(this.applyRuleSetOnNode("left", this.value)) + value, this.applyRuleSetOnNode("top", this.value));
			return false;
			case 40:
				this.MoveTo(this.value, this.applyRuleSetOnNode("left", this.value), parseInt(this.applyRuleSetOnNode("top", this.value)) + value);
			return false;
		}
	}
	
	this.inherit(jpf.Rename); /** @inherits jpf.Rename */
	
	/* ***********************
			DRAGDROP
	************************/
	
	this.__showDragIndicator = function(sel, e){
		var x = e.offsetX;
		var y = e.offsetY;

		this.oDrag.startX = x;
		this.oDrag.startY = y;
		
		document.body.appendChild(this.oDrag);
		//this.oDrag.getElementsByTagName("DIV")[0].innerHTML = this.selected.innerHTML;
		//this.oDrag.getElementsByTagName("IMG")[0].src = this.selected.parentNode.parentNode.childNodes[1].firstChild.src;
		this.__updateNode(this.value, this.oDrag, true);
		
		return this.oDrag;
	}
	
	this.__hideDragIndicator = function(){
		this.oDrag.style.display = "none";
	}
	
	this.__moveDragIndicator = function(e){
		this.oDrag.style.left = (e.clientX - this.oDrag.startX) + "px";
		this.oDrag.style.top = (e.clientY - this.oDrag.startY) + "px";
	}
	
	this.__initDragDrop = function(){
		if(!this.__hasLayoutNode("DragIndicator")) return;
		this.oDrag = jpf.XMLDatabase.htmlImport(this.__getLayoutNode("DragIndicator"), document.body);
		
		this.oDrag.style.zIndex = 1000000;
		this.oDrag.style.position = "absolute";
		this.oDrag.style.cursor = "default";
		this.oDrag.style.display = "none";
	}
	
	this.__dragout = function(el, dragdata){
		var htmlNode = jpf.XMLDatabase.findHTMLNode(dragdata.data, this);
		if(htmlNode) htmlNode.style.display = "block";
	}
	this.__dragover = function(el, dragdata, candrop){
		var htmlNode = jpf.XMLDatabase.findHTMLNode(dragdata.data, this);
		if(htmlNode){
			htmlNode.style.display = candrop[0] && jpf.XMLDatabase.isChildOf(this.XMLRoot, candrop[0], true) ? "none" : "block"; 
		}
	}
	this.__dragstart = function(el, dragdata){
		var htmlNode = jpf.XMLDatabase.findHTMLNode(dragdata.data, this);
		if(htmlNode) htmlNode.style.display = "none";
	}
	this.__dragdrop = function(el, dragdata, candrop){
		//if(!dragdata.resultNode.
	}
	
	this.addEventListener("ondragstart", function(e){
		return this.applyRuleSetOnNode("move", e.data) ? true : false;
	});
	
	this.addEventListener("ondragdrop", function(e){ 
		if(e.candrop && e.host == this){
			var pos = jpf.compat.getAbsolutePosition(this.oInt, null, true);
			this.MoveTo(e.data, (e.x - pos[0] - e.indicator.startX), (e.y - pos[1] - e.indicator.startY));
			
			return false;
		}
	});
	
	this.MoveTo = function(xmlNode, x, y){
		//Use Action Tracker
		var lnode = this.getNodeFromRule("left", xmlNode, null, null, true);
		var tnode = this.getNodeFromRule("top", xmlNode, null, null, true);
		
		var attrs = {};
		attrs[lnode.nodeName] = x;
		attrs[tnode.nodeName] = y;
		
		var exec = this.executeAction("setAttributes", [xmlNode, attrs], "moveto", xmlNode);
		if(exec !== false) return xmlNode;
		
		this.dispatchEvent("onmoveitem", {xmlNode : xmlNode, x : x, y : y});
	}
	
	this.SetZindex = function(xmlNode, value){
		var node = this.getNodeFromRule("zindex", xmlNode, null, null, true);
		if(!node) return;
		
		var atAction = node.nodeType == 1 || node.nodeType == 3 || node.nodeType == 4 ? "setTextNode" : "setAttribute";
		var args = node.nodeType == 1 ? [node, value] : (node.nodeType == 3 || node.nodeType == 4 ? [node.parentNode, value] : [node.ownerElement || node.selectSingleNode(".."), node.nodeName, value]);

		//Use Action Tracker
		this.executeAction(atAction, args, "setzindex", xmlNode);
	}	
	
	this.inherit(jpf.DragDrop); /** @inherits jpf.DragDrop */
	
	/* *********
		Item creation
	**********/
	
	this.__updateModifier = function(xmlNode, htmlNode){
		htmlNode.style.left = (this.applyRuleSetOnNode("left", xmlNode) || 10) + "px";
		htmlNode.style.top = (this.applyRuleSetOnNode("top", xmlNode) || 10) + "px";
		htmlNode.style.width = (this.applyRuleSetOnNode("width", xmlNode) || 100) + "px";
		htmlNode.style.height = (this.applyRuleSetOnNode("height", xmlNode) || 100) + "px";
		
		var zindex = parseInt(this.applyRuleSetOnNode("zindex", xmlNode));
		var curzindex = parseInt(jpf.compat.getStyle(htmlNode, jpf.descPropJs ? "zIndex" : "z-index")) || 1;
		if(curzindex != zindex){
			var nodes = this.getTraverseNodes();
			for(var res=[],i=0;i<nodes.length;i++){
				if(nodes[i] == xmlNode) continue;
				res[nodes[i].getAttribute("zindex")] = nodes[i];
			}
			res[curzindex] = xmlNode;

			if(curzindex < zindex){
				for(var k=curzindex;k<zindex;k++){
					if(!res[k+1]) continue;
					res[k+1].setAttribute("zindex", k);
					jpf.XMLDatabase.findHTMLNode(res[k+1], this).style.zIndex = k;
				}
			}
			else{
				for(var k=zindex;k<curzindex;k++){
					if(!res[k]) continue;
					res[k].setAttribute("zindex", k+1);
					jpf.XMLDatabase.findHTMLNode(res[k], this).style.zIndex = k+1;
				}
			}

			htmlNode.style.zIndex = zindex;
		}
	}
	
	this.__addModifier = function(xmlNode, htmlNode){
		if(!xmlNode.getAttribute("zindex")){
			xmlNode.setAttribute("zindex", this.oExt.childNodes.length+1);
		}
		
		var x, y;
		if(jpf.DragServer.dragdata){
			var pos = jpf.compat.getAbsolutePosition(this.oInt, null, true);
			if(!xmlNode.getAttribute("left")) xmlNode.setAttribute("left", (jpf.DragServer.dragdata.x - pos[0] - jpf.DragServer.dragdata.indicator.startX));
			if(!xmlNode.getAttribute("top")) xmlNode.setAttribute("top", (jpf.DragServer.dragdata.y - pos[1] - jpf.DragServer.dragdata.indicator.startY));
		}

		if(htmlNode.style){
			htmlNode.style.left = (this.applyRuleSetOnNode("left", xmlNode) || 10) + "px";
			htmlNode.style.top = (this.applyRuleSetOnNode("top", xmlNode) || 10) + "px";
			htmlNode.style.width = (this.applyRuleSetOnNode("width", xmlNode) || 100) + "px";
			htmlNode.style.height = (this.applyRuleSetOnNode("height", xmlNode) || 100) + "px";
			htmlNode.style.zIndex = (this.oExt.childNodes.length+1);
		}
		else{
			var style = [];
			style.push("left:" + (this.applyRuleSetOnNode("left", xmlNode) || 10) + "px");
			style.push("top:" + (this.applyRuleSetOnNode("top", xmlNode) || 10) + "px");
			style.push("width:" + (this.applyRuleSetOnNode("width", xmlNode) || 100) + "px");
			style.push("height:" + (this.applyRuleSetOnNode("height", xmlNode) || 100) + "px");
			style.push("z-index:" + (this.oExt.childNodes.length+1));
			htmlNode.setAttribute("style", style.join(";"));
		}
	}
	
	/* *********
		INIT
	**********/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.draw = function(){
		//Build Main Skin
		this.oExt = this.__getExternal(); 
		this.oInt = this.__getLayoutNode("Main", "container", this.oExt);

		/*this.oExt.onmousedown = function(e){
			if(!e) e = event;
			if(e.ctrlKey || e.shiftKey) return;
			
			var srcElement = IS_IE ? e.srcElement : e.target;
			debugger;
			if(this.host.allowDeselect && (srcElement == this || srcElement.getAttribute(XMLDatabase.htmlIdTag)))
				this.host.clearSelection(); //hacky
		}*/
		
		this.oExt.onclick = function(e){
			this.host.dispatchEvent("onclick", {htmlEvent : e || event});
		}

		//Get Options form skin
		this.listtype = parseInt(this.__getLayoutNode("Main", "type")) || 1; //Types: 1=One dimensional List, 2=Two dimensional List
		this.behaviour = parseInt(this.__getLayoutNode("Main", "behaviour")) || 1; //Types: 1=Check on click, 2=Check independent
	}
	
	this.__loadJML = function(x){
		if(this.jml.childNodes.length) this.loadInlineData(this.jml);
		
		if(this.hasFeature(__MULTIBINDING__) && x.getAttribute("value")) this.setValue(x.getAttribute("value"));
		
		// this.doOptimize(true);
		
		if(x.getAttribute("multibinding") == "true" && !x.getAttribute("ref")) 
			this.inherit(jpf.MultiLevelBinding); /** @inherits jpf.MultiLevelBinding */
	}
	
	this.__destroy = function(){
		this.oExt.onclick = null;
		jpf.removeNode(this.oDrag);
		this.oDrag = null;
	}
}

/*FILEHEAD(/in/Components/Xslt.js)SIZE(3613)TIME(1203730484247)*/

/**
 * Component displaying the contents of a XSLT transformation on
 * the bound dataset. This component can create a containing element
 * when none is provided.
 *
 * @classDescription		This class creates a new Xslt component
 * @return {Xslt} Returns a new Xslt component
 * @type {Xslt}
 * @constructor
 * @allowchild [cdata]
 * @addnode components:xslt
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.9
 */
jpf.xslt = function(pHtmlNode){
	jpf.register(this, "xslt", GUI_NODE);/** @inherits jpf.Class */
	this.pHtmlNode = pHtmlNode || document.body;
	this.pHtmlDoc = this.pHtmlNode.ownerDocument;

	/* ***********************
	  		Inheritance
	************************/
	
	this.inherit(jpf.DataBinding); /** @inherits jpf.DataBinding */
	
	/* ********************************************************************
										PROPERTIES
	*********************************************************************/
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/
	
	
	/* ***************
		DATABINDING
	****************/
	this.mainBind = "contents";
	
	/* *********
		INIT
	**********/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.parse = function(code){
		this.setProperty("value", code);
	}

	this.__clear = function(a,b){
		//BUG: WTF? clear gets called before load AND if there is nothing to load but with different args
		//IF YOU CLEAR HERE A REDRAW WITH THE SAME CONTENT WILL FAIL 
		if(b==true){
			this.oInt.innerHTML = "";//alert(a+"-"+b);
			// WHY . if i dont do this the setProperty loses its update. 
			this.setProperty("value","");
		}
		//alert(this.uniqueId);
		//this.oInt.innerHTML = "";
	}
	
	this.__supportedProperties = ["value"];
	this.__handlePropSet = function(prop, code){
		switch(prop){
			case "value":
				if(this.createJml){
					if(typeof code == "string") code = jpf.XMLDatabase.getXml(code);
					// To really make it dynamic, the objects created should be 
					// deconstructed and the xml should be attached and detached
					// of the this.jml xml. 
					jpf.JMLParser.parseChildren(code, this.oInt, this);
					if(jpf.JMLParser.inited) jpf.JMLParser.parseLastPass();
				}
				else{
					this.oInt.innerHTML = code;
				}
			break;
		}
	}
	
	this.draw = function(){
		//Build Main Skin
		//alert("REDRAW");
		this.oInt = this.oExt = this.jml.parentNode.lastChild == this.jml.parentNode.firstChild ? pHtmlNode : pHtmlNode.appendChild(document.createElement("div"));
		if(this.jml.getAttribute("cssclass")) this.oExt.className = this.jml.getAttribute("cssclass");
	}
	
	this.__loadJML = function(x){
		this.createJml = jpf.isTrue(x.getAttribute("jml"));

		var nodes = x.childNodes;
		if(nodes.length){
			var bind = x.getAttribute("ref") || "."; x.removeAttribute("ref");
			var strBind = "<smartbinding><bindings><contents select='" + bind + "'><xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'><xsl:template match='" + bind + "'></xsl:template></xsl:stylesheet></contents></bindings></smartbinding>";
			var xmlNode = jpf.XMLDatabase.getXml(strBind);
			var tNode = xmlNode.firstChild.firstChild.firstChild.firstChild
			for(var i=0;i<nodes.length;i++){
				//if(tNode.ownerDocument.importNode
				tNode.appendChild(nodes[i]);
			}
			
			jpf.JMLParser.addToSbStack(this.uniqueId, new jpf.SmartBinding(null, xmlNode));
		}
	}
}
/*FILEHEAD(/in/Components/_base/BaseButton.js)SIZE(4087)TIME(1203730484247)*/

/**
 * Baseclass of a Button component
 *
 * @constructor
 * @baseclass
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.8
 */
jpf.BaseButton = function(pHtmlNode){
		
	/* ***************
		Init
	****************/

	this.refKeyDown = 0;			// Number of keys pressed. 
	this.refMouseDown = 0;		// Mouse button down?
	this.mouseOver = false;		// Mouse hovering over the button?
	this.mouseLeft = false;		// Has the mouse left the control since pressing the button.
	
	/* ***********************
		Keyboard Support
	************************/
	
	this.keyHandler = function(key, ctrlKey, shiftKey, altKey, evnt){
		switch(key){
			case 32:
			case 13:
				if (!evnt.repeat) // Only when first pressed, not on autorepeat.
				{
					this.refKeyDown++;
					return this.__updateState(evnt);
				}
				else return false;
		}
	}

	this.keyUpHandler = function(key, ctrlKey, shiftKey, altKey, evnt){
		switch(key){
			case 32:
			case 13:
				this.refKeyDown--;
				if (this.refKeyDown + this.refMouseDown == 0 && !this.disabled){
					//if(this.oExt.onclick) this.oExt.onclick(evnt, true);
					//else if(this.oExt.onmouseup) 
					this.oExt.onmouseup(evnt, true);
				}
				return this.__updateState(evnt);
		}
	}

	this.states = {"Out":1,"Over":2,"Down":3}
	
	this.__updateState = function(e, strEvent)
	{
		if (this.disabled)
		{
			this.refKeyDown = 0;
			this.refMouseDown = 0;
			this.mouseOver = false;
			return false;
		}
		else
		{
			if (this.refKeyDown > 0 || (this.refMouseDown > 0 && this.mouseOver) || (this.isBoolean && this.value))
				this.__setState ("Down", e, strEvent);
			else if (this.mouseOver)
				this.__setState ("Over", e, strEvent);
			else this.__setState ("Out", e, strEvent);
		}
	}	
	
	this.__setupEvents = function()
	{
		this.oExt.onmousedown = function(e) { this.host.refMouseDown = 1; this.host.mouseLeft=false; this.host.__updateState(e || event, "onmousedown"); };
		this.oExt.onmouseup = function(e, force) {
			if(!e) e = event;
			if(e) e.cancelBubble = true;
			
			if(!force && (!this.host.mouseOver || !this.host.refMouseDown)) return;
			this.host.refMouseDown = 0; this.host.__updateState (e, "onmouseup"); 

			// If this is coming from a mouse click, we shouldn't have left the button.
			if (this.host.disabled || (e && e.type == "click" && this.host.mouseLeft == true))
				return false;
				
			// If there are still buttons down, this is not a real click.
			if (this.host.refMouseDown + this.host.refKeyDown)
				return false;	
	
			if (this.host.__clickHandler && this.host.__clickHandler())
				this.host.__updateState (e || event, "onclick");
			else this.host.dispatchEvent("onclick", {htmlEvent : e});
			
			return false;
		};
		this.oExt.onmousemove = function(e) { this.host.mouseOver = true; this.host.__updateState (e || event, "onmouseover"); };
		this.oExt.onmouseout = function(e) { 
			if(!e) e = event;
			
			//Check if the mouse out is meant for us
			var tEl = e.explicitOriginalTarget || e.toElement;
			if(this == tEl || jpf.XMLDatabase.isChildOf(this, tEl)) return;
				
			this.host.mouseOver = false; this.host.refMouseDown = 0; this.host.mouseLeft=true; this.host.__updateState (e || event, "onmouseout"); 
		};

		if(jpf.hasClickFastBug) this.oExt.ondblclick = this.oExt.onmouseup;
	}
	
	this.__destroy = function(){
		this.oExt.onmousedown = null;
		this.oExt.onmouseup = null;
		this.oExt.onmouseover = null;
		this.oExt.onmouseout = null;
		this.oExt.onclick = null;
		this.oExt.ondblclick = null;
	}
	
	this.__focus = function(){
		if(!this.oExt) return;
		this.__setStyleClass(this.oExt, this.baseCSSname + "Focus");
	}

	this.__blur = function(e){
		if(!this.oExt) return; //FIREFOX BUG!
		if(!e) e = event;
		
		this.__setStyleClass(this.oExt, "", [this.baseCSSname + "Focus"]);
		this.refKeyDown = 0;
		this.refMouseDown = 0;
		this.mouseLeft=true;
		
		if(e) this.__updateState(e, "onblur");
	}	
}

/*FILEHEAD(/in/Components/_base/BaseFastList.js)SIZE(16716)TIME(1203730484247)*/

/**
 * Baseclass of a Fastlist component
 *
 * @constructor
 * @baseclass
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.8
 */
jpf.BaseFastList = function(){
	/* ********************************************************************
										PROPERTIES
	*********************************************************************/

	//Options
	this.inherit(jpf.Validation); /** @inherits jpf.Validation */
	this.inherit(jpf.XForms); /** @inherits jpf.XForms */
	this.focussable = true; // This object can get the focus
	this.multiselect = true; // Initially Disable MultiSelect
	
	this.dynCssClasses = [];
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/
	
	/* ********************************************************************
										PRIVATE METHODS
	*********************************************************************/

	/* ***********************
				Skin
	************************/

	this.__deInitNode = function(xmlNode, htmlNode){
		if(!htmlNode) return;

		//Remove htmlNodes from tree
		htmlNode.parentNode.removeChild(htmlNode);
	}

	this.scrollTo = function(xmlNode, updateScrollbar){
		this.lastScroll = xmlNode;
		
		var xNodes = this.getTraverseNodes();
		for(var j=xNodes.length-1;j>=0;j--){
			if(xNodes[j] == xmlNode) break;
		}
		
		if(updateScrollbar){
			this.sb.setPosition(j/(xNodes.length-this.nodeCount), true);
		}
		
		var sNodes = {}, selNodes = this.getSelection();
		for(var i=selNodes.length-1;i>=0;i--){
			sNodes[selNodes[i].getAttribute(jpf.XMLDatabase.xmlIdTag)] = true;
			this.__deselect(document.getElementById(selNodes[i].getAttribute(jpf.XMLDatabase.xmlIdTag) + "|" + this.uniqueId));
		}
		
		var nodes = this.oInt.childNodes;
		for(var id, i=0;i<nodes.length;i++){
			if(nodes[i].nodeType != 1) continue;
			xmlNode = xNodes[j++];
			
			if(!xmlNode) nodes[i].style.display = "none";
			else{
				nodes[i].setAttribute(jpf.XMLDatabase.htmlIdTag, xmlNode.getAttribute(jpf.XMLDatabase.xmlIdTag) + "|" + this.uniqueId);
				this.__updateNode(xmlNode, nodes[i]);
				nodes[i].style.display = "block"; // or inline
				
				if(sNodes[xmlNode.getAttribute(jpf.XMLDatabase.xmlIdTag)])
					this.__select(nodes[i]);
			}
		}
	}

	this.__updateNode = function(xmlNode, htmlNode){
		//Update Identity (Look)
		var elIcon = this.__getLayoutNode("Item", "icon", htmlNode);
		
		if(elIcon){
			if(elIcon.nodeType == 1) elIcon.style.backgroundImage = "url(" + this.iconPath + this.applyRuleSetOnNode("icon", xmlNode) + ")";
			else elIcon.nodeValue = this.iconPath + this.applyRuleSetOnNode("icon", xmlNode);
		}
		else{
			var elImage = this.__getLayoutNode("Item", "image", htmlNode);//.style.backgroundImage = "url(" + this.applyRuleSetOnNode("image", xmlNode) + ")";
			if(elImage){
				if(elImage.nodeType == 1) elImage.style.backgroundImage = "url(" + this.applyRuleSetOnNode("image", xmlNode) + ")";
				else elImage.nodeValue = this.applyRuleSetOnNode("image", xmlNode);
			}
		}
			
		//this.__getLayoutNode("Item", "caption", htmlNode).nodeValue = this.applyRuleSetOnNode("caption", xmlNode);
		var elCaption = this.__getLayoutNode("Item", "caption", htmlNode);
		if(elCaption){
			if(elCaption.nodeType == 1)
				elCaption.innerHTML = this.applyRuleSetOnNode("caption", xmlNode);
			else elCaption.nodeValue = this.applyRuleSetOnNode("caption", xmlNode);
		}

		var cssClass = this.applyRuleSetOnNode("css", xmlNode);
		if(cssClass || this.dynCssClasses.length){
			this.__setStyleClass(htmlNode, cssClass, this.dynCssClasses);
			if(cssClass && !this.dynCssClasses.contains(cssClass)) this.dynCssClasses.push(cssClass);
		}
	}
	
	this.__moveNode = function(xmlNode, htmlNode){
		if(!htmlNode) return;
		var oPHtmlNode = htmlNode.parentNode;
		var beforeNode = xmlNode.nextSibling ? jpf.XMLDatabase.findHTMLNode(this.getNextTraverse(xmlNode), this) : null;

		oPHtmlNode.insertBefore(htmlNode, beforeNode);
		
		//if(this.emptyMessage && !oPHtmlNode.childNodes.length) this.setEmpty(oPHtmlNode);
	}
	
	/* ***********************
		Keyboard Support
	************************/
	
	//Handler for a plane list
	this.__keyHandler = function(key, ctrlKey, shiftKey, altKey){
		if(!this.selected) return;
		//error after delete...
		
		var jNode = this;
		function selscroll(sel, scroll){
			if(!jNode.selected){
				jNode.scrollTo(scroll || sel, true);
				
				if(ctrlKey) jNode.setIndicator(sel);
				else jNode.select(sel, null, shiftKey);
			}
		}

		switch(key){
			case 13:
				this.choose(this.selected);
			break;
			case 32:
				this.select(this.indicator, true);
			break;
			case 46:
			//DELETE
				if(this.disableremove) return;
			
				this.remove(null, true);
			break;
			case 37:
			//LEFT
				var margin = jpf.compat.getBox(jpf.getStyle(this.selected, "margin"));
			
				if(!this.value) return;
				var node = this.getNextTraverseSelected(this.indicator || this.value, false);
				if(node){
					if(ctrlKey) this.setIndicator(node);
					else this.select(node, null, shiftKey);
					
					if(!this.selected) selscroll(node, this.getNextTraverse(this.lastScroll, true));
					if(!this.selected) selscroll(node, node);
				}
			break;
			case 38:
			//UP
				var margin = jpf.compat.getBox(jpf.getStyle(this.selected, "margin"));
				
				if(!this.value && !this.indicator) return;
				var hasScroll = this.oExt.scrollHeight > this.oExt.offsetHeight;
				var items = Math.floor((this.oExt.offsetWidth - (hasScroll ? 15 : 0)) / (this.selected.offsetWidth+margin[1]+margin[3]));
				var node = this.getNextTraverseSelected(this.indicator || this.value, false, items);

				if(node){
					if(ctrlKey) this.setIndicator(node);
					else this.select(node, null, shiftKey);
					
					if(!this.selected) selscroll(node, this.getNextTraverse(this.lastScroll, true));
					if(!this.selected) selscroll(node, node);
				}
			break;
			case 39:
			//RIGHT
				var margin = jpf.compat.getBox(jpf.getStyle(this.selected, "margin"));
				
				if(!this.value) return;
				var node = this.getNextTraverseSelected(this.indicator || this.value, true);
				if(node){
					if(ctrlKey) this.setIndicator(node);
					else this.select(node, null, shiftKey);
					
					if(!this.selected) selscroll(node, this.getNextTraverse(this.lastScroll, true));
					if(!this.selected) selscroll(node, node);
				}
			break;
			case 40:
			//DOWN
				var margin = jpf.compat.getBox(jpf.getStyle(this.selected, "margin"));
				if(!this.value && !this.indicator) return;
				var hasScroll = this.oExt.scrollHeight > this.oExt.offsetHeight;
				var items = Math.floor((this.oExt.offsetWidth - (hasScroll ? 15 : 0)) / (this.selected.offsetWidth+margin[1]+margin[3]));
				var node = this.getNextTraverseSelected(this.indicator || this.value, true, items);
				if(node){
					if(ctrlKey) this.setIndicator(node);
					else this.select(node, null, shiftKey);

					var s2 = this.getNextTraverseSelected(node, true, items);
					if(s2 && !document.getElementById(s2.getAttribute(jpf.XMLDatabase.xmlIdTag) + "|" + this.uniqueId)){
						if(!this.selected) selscroll(node, this.getNextTraverse(this.lastScroll));
						if(!this.selected) selscroll(node, node);
					}
					else if(s2 == node){
						var nodes = this.getTraverseNodes();
						if(!this.selected) selscroll(node, nodes[nodes.length-this.nodeCount+1]);
						if(!this.selected) selscroll(node, node);
					}
				}
				
				//if(this.selected.offsetTop + this.selected.offsetHeight > this.oExt.scrollTop + this.oExt.offsetHeight - (hasScroll ? 10 : 0))
					//this.oExt.scrollTop = this.selected.offsetTop - this.oExt.offsetHeight + this.selected.offsetHeight + 10 + (hasScroll ? 10 : 0);
				
			break;
			case 33:
			//PGUP
				if(!this.value && !this.indicator) return;
				
				var node = this.getNextTraverseSelected(this.indicator || this.value, false, this.nodeCount-1);//items*lines);
				if(!node) node = this.getFirstTraverseNode();
				
				this.scrollTo(node, true);
				if(node){
					if(ctrlKey) this.setIndicator(node);
					else this.select(node, null, shiftKey);
				}
			break;
			case 34:
			//PGDN
				if(!this.value && !this.indicator) return;
				var node = this.getNextTraverseSelected(this.indicator || this.value, true, this.nodeCount-1);
				if(!node) node = this.getLastTraverseNode();
				
				var xNodes = this.getTraverseNodes();
				for(var j=xNodes.length-1;j>=0;j--) if(xNodes[j] == node) break;
				if(j>xNodes.length-this.nodeCount-1) j = xNodes.length-this.nodeCount+1;
				this.scrollTo(xNodes[j], true);
				if(xNodes[j] != node) node = xNodes[xNodes.length-1];
				
				if(node){
					if(ctrlKey) this.setIndicator(node);
					else this.select(node, null, shiftKey);
				}
			break;
			case 36:
				//HOME
				var xmlNode = this.getFirstTraverseNode();
				this.scrollTo(xmlNode, true);
				this.select(xmlNode, null, shiftKey);
				//this.oInt.scrollTop = 0;
				//Q.scrollIntoView(true);
			break;
			case 35:
				//END
				var nodes = this.getTraverseNodes(xmlNode || this.XMLRoot);//.selectNodes(this.ruleTraverse);
				this.scrollTo(nodes[nodes.length-this.nodeCount+1], true);
				this.select(nodes[nodes.length-1], null, shiftKey);
				//Q.scrollIntoView(true);
			break;
			default:
				if(key == 65 && ctrlKey){
					this.selectAll();
				}
				else if(this.bindingRules["caption"]){
					//this should move to a onkeypress based function
					if(!this.lookup || new Date().getTime() - this.lookup.date.getTime() > 300) this.lookup = {
						str : "",
						date : new Date()
					};
					
					this.lookup.str += String.fromCharCode(key);
	
					var nodes = this.getTraverseNodes();
					for(var i=0;i<nodes.length;i++){
						if(this.applyRuleSetOnNode("caption", nodes[i]).substr(0, this.lookup.str.length).toUpperCase() == this.lookup.str){
							this.scrollTo(nodes[i], true);
							this.select(nodes[i]);
							return;
						}
					}
					
					return;
				}
			break;
		};
		
		this.lookup = null;
		return false;
	}
	
	
	/* ***********************
			DATABINDING
	************************/
	
	this.nodes = [];
	
	this.nodeCount = 0;
	this.__add = function(xmlNode, Lid, xmlParentNode, htmlParentNode, beforeNode){
		if(!this.oInt.childNodes.length) this.nodeCount = 0;
		
		//Check if more items should be added
		if(this.nodeCount > 9){//this.oInt.scrollHeight >= this.oInt.offsetHeight){
			// || this.oInt.scrollWidth > this.oInt.offsetWidth
			return false;
		}
		this.nodeCount++;
		
		//Build Row
		this.__getNewContext("Item");
		var Item = this.__getLayoutNode("Item");
		var elSelect = this.__getLayoutNode("Item", "select");
		var elIcon = this.__getLayoutNode("Item", "icon");
		var elImage = this.__getLayoutNode("Item", "image");
		var elCheckbox = this.__getLayoutNode("Item", "checkbox");
		var elCaption = this.__getLayoutNode("Item", "caption");
		
		Item.setAttribute("id", Lid);
		
		//elSelect.setAttribute("oncontextmenu", 'jpf.lookup(' + this.uniqueId + ').dispatchEvent("oncontextmenu", event);');
		elSelect.setAttribute("ondblclick", 'jpf.lookup(' + this.uniqueId + ').choose()');
		elSelect.setAttribute(this.itemSelectEvent || "onmousedown", 'jpf.lookup(' + this.uniqueId + ').select(this, event.ctrlKey, event.shiftKey)'); 
		elSelect.setAttribute("onmouseover", 'jpf.lookup(' + this.uniqueId + ').__setStyleClass(this, "hover");');
		elSelect.setAttribute("onmouseout", 'jpf.lookup(' + this.uniqueId + ').__setStyleClass(this, "", ["hover"]);'); 
		
		//Setup Nodes Identity (Look)
		if(elIcon){
			if(elIcon.nodeType == 1) elIcon.setAttribute("style", "background-image:url(" + this.iconPath + this.applyRuleSetOnNode("icon", xmlNode) + ")");
			else elIcon.nodeValue = this.iconPath + this.applyRuleSetOnNode("icon", xmlNode);
		}
		else if(elImage){
			if(elImage.nodeType == 1) elImage.setAttribute("style", "background-image:url(" + this.applyRuleSetOnNode("image", xmlNode) + ")");
			else elImage.nodeValue = this.applyRuleSetOnNode("image", xmlNode);
		}
		
		if(elCaption) jpf.XMLDatabase.setNodeValue(elCaption, this.applyRuleSetOnNode("caption", xmlNode));
		
		var cssClass = this.applyRuleSetOnNode("css", xmlNode);
		if(cssClass){
			this.__setStyleClass(Item, cssClass);
			if(cssClass) this.dynCssClasses.push(cssClass);
		}

		jpf.XMLDatabase.htmlImport(Item, htmlParentNode || this.oInt, beforeNode);
		/*
		if(htmlParentNode) jpf.XMLDatabase.htmlImport(Item, htmlParentNode || this.oInt, beforeNode);
		else this.nodes.push(Item);
		*/
	}
	
	this.__fill = function(){
		//jpf.XMLDatabase.htmlImport(this.nodes, this.oInt);
		//this.nodes.length = 0;
		//alert((this == prevMainBG) + ":" + this.oInt.outerHTML + ":" + this.XMLRoot.xml);
		
		var jmlNode = this;
		this.lastScroll = this.getFirstTraverseNode();
		if(this.sb) this.sb.attach(this.oExt, this.nodeCount, this.getTraverseNodes().length, function(time, perc){
			var nodes = jmlNode.getTraverseNodes();
			jmlNode.scrollTo(nodes[Math.round((nodes.length-jmlNode.nodeCount+1)*perc)]);
		});
	}
	
	/* ***********************
				SELECT
	************************/
	
	this.__calcSelectRange = function(xmlStartNode, xmlEndNode){
		var r = [], loopNode = xmlStartNode;
		while(loopNode && loopNode != xmlEndNode.nextSibling){
			if(this.applyRuleSetOnNode("select", loopNode, ".") !== false) r.push(loopNode);
			loopNode = loopNode.nextSibling;
		}

		if(r[r.length-1] != xmlEndNode){
			var r = [], loopNode = xmlStartNode;
			while(loopNode && loopNode != xmlEndNode.previousSibling){
				if(this.applyRuleSetOnNode("select", loopNode, ".") !== false) r.push(loopNode);
				loopNode = loopNode.previousSibling;
			};
		}
		
		return r;
	}
	
	this.__selectDefault = function(XMLRoot){
		this.select(this.getTraverseNodes()[0]);
	}
	
	this.inherit(jpf.MultiSelect); /** @inherits jpf.MultiSelect */
	this.inherit(jpf.Cache); /** @inherits jpf.Cache */
	
	/* ***********************
	  Other Inheritance
	************************/
	
	this.inherit(jpf.Presentation); /** @inherits jpf.Presentation */
	this.inherit(jpf.DataBinding); /** @inherits jpf.DataBinding */
	
	this.loadInlineData = function(x){
		var hasIcon, strData = [], nodes = x.childNodes;

		for(var i=nodes.length-1;i>=0;i--){
			if(nodes[i].nodeType != 1) continue;
			if(nodes[i][jpf.TAGNAME] != "item") continue;
			
			hasIcon = nodes[i].getAttribute("icon") || "icoAnything.gif";
			strData.unshift("<item " + (hasIcon ? "icon='" + hasIcon + "'" : "") + " value='" + (nodes[i].getAttributeNode("value") ? nodes[i].getAttribute("value") : nodes[i].firstChild.nodeValue) + "'>" + nodes[i].firstChild.nodeValue + "</item>");
			nodes[i].parentNode.removeChild(nodes[i]);
		}

		if(strData.length){
			var sNode = new jpf.SmartBinding(null, jpf.getObject("XMLDOM", "<smartbindings xmlns='" + jpf.ns.jpf + "'><bindings><caption select='text()' />" + (hasIcon ? "<Icon select='@icon'/>" : "") + "<value select='@value'/><traverse select='item' /></bindings><model><items>" + strData.join("") + "</items></model></smartbindings>").documentElement);
			jpf.JMLParser.addToSbStack(this.uniqueId, sNode);
		}
		
		if(x.childNodes.length)
			jpf.JMLParser.parseChildren(x, null, this);
	}
	
	this.loadFillData = function(str){
		var parts = str.split("-");
		var start = parseInt(parts[0]);
		var end = parseInt(parts[1]);
		
		strData = [];
		for(var i=start;i<end+1;i++){
			strData.push("<item>" + (i+"").pad(Math.max(parts[0].length, parts[1].length), "0") + "</item>");
		}
		
		if(strData.length){
			var sNode = new jpf.SmartBinding(null, jpf.getObject("XMLDOM", "<smartbindings xmlns='" + jpf.ns.jpf + "'><bindings><caption select='text()' /><value select='text()'/><traverse select='item' /></bindings><model><items>" + strData.join("") + "</items></model></smartbindings>").documentElement);
			jpf.JMLParser.addToSbStack(this.uniqueId, sNode);
		}
	}
}

/*FILEHEAD(/in/Components/_base/BaseList.js)SIZE(20298)TIME(1213483123975)*/

/**
 * Baseclass of a List component
 *
 * @constructor
 * @baseclass
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.8
 */
jpf.BaseList = function(){
	/* ********************************************************************
										PROPERTIES
	*********************************************************************/

	//Options
	this.inherit(jpf.Validation); /** @inherits jpf.Validation */
	this.inherit(jpf.XForms); /** @inherits jpf.XForms */
	this.focussable = true; // This object can get the focus
	this.multiselect = true; // Initially Disable MultiSelect
	
	this.dynCssClasses = [];
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/
	
	/* ********************************************************************
										PRIVATE METHODS
	*********************************************************************/

	/* ***********************
				Skin
	************************/

	this.__deInitNode = function(xmlNode, htmlNode){
		if(!htmlNode) return;

		//Remove htmlNodes from tree
		htmlNode.parentNode.removeChild(htmlNode);
	}
	
	this.__updateNode = function(xmlNode, htmlNode, noModifier){
		//Update Identity (Look)
		var elIcon = this.__getLayoutNode("Item", "icon", htmlNode);
		
		if(elIcon){
			if(elIcon.nodeType == 1) elIcon.style.backgroundImage = "url(" + this.iconPath + this.applyRuleSetOnNode("icon", xmlNode) + ")";
			else elIcon.nodeValue = this.iconPath + this.applyRuleSetOnNode("icon", xmlNode);
		}
		else{
			var elImage = this.__getLayoutNode("Item", "image", htmlNode);//.style.backgroundImage = "url(" + this.applyRuleSetOnNode("image", xmlNode) + ")";
			if(elImage){
				if(elImage.nodeType == 1) elImage.style.backgroundImage = "url(" + this.mediaPath + this.applyRuleSetOnNode("image", xmlNode) + ")";
				else elImage.nodeValue = this.mediaPath + this.applyRuleSetOnNode("image", xmlNode);
			}
		}
			
		//this.__getLayoutNode("Item", "caption", htmlNode).nodeValue = this.applyRuleSetOnNode("Caption", xmlNode);
		var elCaption = this.__getLayoutNode("Item", "caption", htmlNode);
		if(elCaption){
			if(elCaption.nodeType == 1)
				elCaption.innerHTML = this.applyRuleSetOnNode("caption", xmlNode);
			else elCaption.nodeValue = this.applyRuleSetOnNode("caption", xmlNode);
		}
		
		htmlNode.title = this.applyRuleSetOnNode("title", xmlNode) || "";
		
		var cssClass = this.applyRuleSetOnNode("css", xmlNode);
		if(cssClass || this.dynCssClasses.length){
			this.__setStyleClass(htmlNode, cssClass, this.dynCssClasses);
			if(cssClass && !this.dynCssClasses.contains(cssClass)) this.dynCssClasses.push(cssClass);
		}
		
		if(!noModifier && this.__updateModifier) this.__updateModifier(xmlNode, htmlNode);
	}
	
	this.__moveNode = function(xmlNode, htmlNode){
		if(!htmlNode) return;
		var oPHtmlNode = htmlNode.parentNode;
		var beforeNode = xmlNode.nextSibling ? jpf.XMLDatabase.findHTMLNode(this.getNextTraverse(xmlNode), this) : null;

		oPHtmlNode.insertBefore(htmlNode, beforeNode);
		
		//if(this.emptyMessage && !oPHtmlNode.childNodes.length) this.setEmpty(oPHtmlNode);
	}
	
	/* ***********************
		Keyboard Support
	************************/
	
	//Handler for a plane list
	/**
	 * @todo  something goes wrong when selecting using space, doing mode="check"
	 */
	this.__keyHandler = function(key, ctrlKey, shiftKey, altKey){
		if(!this.selected) return;
		//error after delete...

		switch(key){
			case 13:
				this.select(this.indicator, true);
				this.choose(this.selected);
			break;
			case 32:
				this.select(this.indicator, true);
			break;
			case 109:
			case 46:
			//DELETE
				if(this.disableremove) return;
			
				this.remove(null, this.mode != "check");
			break;
			case 37:
			//LEFT
				var margin = jpf.compat.getBox(jpf.getStyle(this.selected, "margin"));
			
				if(!this.value && !this.indicator) return;
				var node = this.getNextTraverseSelected(this.indicator || this.value, false);
				if(node){
					if(ctrlKey || this.ctrlSelect) this.setIndicator(node);
					else this.select(node, null, shiftKey);
				}
				
				if(this.selected.offsetTop < this.oExt.scrollTop)
					this.oExt.scrollTop = this.selected.offsetTop - margin[0];
			break;
			case 38:
			//UP
				var margin = jpf.compat.getBox(jpf.getStyle(this.selected, "margin"));
				
				if(!this.value && !this.indicator) return;
				var hasScroll = this.oExt.scrollHeight > this.oExt.offsetHeight;
				var items = Math.floor((this.oExt.offsetWidth - (hasScroll ? 15 : 0)) / (this.selected.offsetWidth+margin[1]+margin[3]));
				var node = this.getNextTraverseSelected(this.indicator || this.value, false, items);
				if(node){
					if(ctrlKey || this.ctrlSelect) this.setIndicator(node);
					else this.select(node, null, shiftKey);
				}
				
				if(this.selected.offsetTop < this.oExt.scrollTop)
					this.oExt.scrollTop = this.selected.offsetTop - margin[0];
			break;
			case 39:
			//RIGHT
				var margin = jpf.compat.getBox(jpf.getStyle(this.selected, "margin"));
				
				if(!this.value && !this.indicator) return;
				var node = this.getNextTraverseSelected(this.indicator || this.value, true);
				if(node){
					if(ctrlKey || this.ctrlSelect) this.setIndicator(node);
					else this.select(node, null, shiftKey);
				}
				
				if(this.selected.offsetTop + this.selected.offsetHeight > this.oExt.scrollTop + this.oExt.offsetHeight)
					this.oExt.scrollTop = this.selected.offsetTop - this.oExt.offsetHeight + this.selected.offsetHeight + margin[0];
					
			break;
			case 40:
			//DOWN
				var margin = jpf.compat.getBox(jpf.getStyle(this.selected, "margin"));
				
				if(!this.value && !this.indicator) return;
				var hasScroll = this.oExt.scrollHeight > this.oExt.offsetHeight;
				var items = Math.floor((this.oExt.offsetWidth - (hasScroll ? 15 : 0)) / (this.selected.offsetWidth+margin[1]+margin[3]));
				var node = this.getNextTraverseSelected(this.indicator || this.value, true, items);
				if(node){
					if(ctrlKey || this.ctrlSelect) this.setIndicator(node);
					else this.select(node, null, shiftKey);
				}
				
				if(this.selected.offsetTop + this.selected.offsetHeight > this.oExt.scrollTop + this.oExt.offsetHeight - (hasScroll ? 10 : 0))
					this.oExt.scrollTop = this.selected.offsetTop - this.oExt.offsetHeight + this.selected.offsetHeight + 10 + (hasScroll ? 10 : 0);
				
			break;
			case 33:
			//PGUP
				var margin = jpf.compat.getBox(jpf.getStyle(this.selected, "margin"));
				
				if(!this.value && !this.indicator) return;
				var hasScrollY = this.oExt.scrollHeight > this.oExt.offsetHeight;
				var hasScrollX = this.oExt.scrollWidth > this.oExt.offsetWidth;
				var items = Math.floor((this.oExt.offsetWidth - (hasScrollY ? 15 : 0)) / (this.selected.offsetWidth+margin[1]+margin[3]));
				var lines = Math.floor((this.oExt.offsetHeight - (hasScrollX ? 15 : 0)) / (this.selected.offsetHeight+margin[0]+margin[2]));
				var node = this.getNextTraverseSelected(this.indicator || this.value, false, items*lines);
				if(!node) node = this.getFirstTraverseNode();
				if(node){
					if(ctrlKey || this.ctrlSelect) this.setIndicator(node);
					else this.select(node, null, shiftKey);
				}
				
				if(this.selected.offsetTop < this.oExt.scrollTop)
					this.oExt.scrollTop = this.selected.offsetTop - margin[0];
			break;
			case 34:
			//PGDN
				var margin = jpf.compat.getBox(jpf.getStyle(this.selected, "margin"));
				
				if(!this.value && !this.indicator) return;
				var hasScrollY = this.oExt.scrollHeight > this.oExt.offsetHeight;
				var hasScrollX = this.oExt.scrollWidth > this.oExt.offsetWidth;
				var items = Math.floor((this.oExt.offsetWidth - (hasScrollY ? 15 : 0)) / (this.selected.offsetWidth+margin[1]+margin[3]));
				var lines = Math.floor((this.oExt.offsetHeight - (hasScrollX ? 15 : 0)) / (this.selected.offsetHeight+margin[0]+margin[2]));
				var node = this.getNextTraverseSelected(this.indicator || this.value, true, items*lines);
				if(!node) node = this.getLastTraverseNode();
				if(node){
					if(ctrlKey || this.ctrlSelect) this.setIndicator(node);
					else this.select(node, null, shiftKey);
				}
				
				if(this.selected.offsetTop + this.selected.offsetHeight > this.oExt.scrollTop + this.oExt.offsetHeight - (hasScrollY ? 10 : 0))
					this.oExt.scrollTop = this.selected.offsetTop - this.oExt.offsetHeight + this.selected.offsetHeight + 10 + (hasScrollY ? 10 : 0);
			break;
			case 36:
				//HOME
				this.select(this.getFirstTraverseNode(), false, shiftKey);
				this.oInt.scrollTop = 0;
				//Q.scrollIntoView(true);
			break;
			case 35:
				//END
				this.select(this.getLastTraverseNode(), false, shiftKey);
				this.oInt.scrollTop = this.oInt.scrollHeight;
				//Q.scrollIntoView(true);
			break;
			case 107:
				//+
				if(this.more) this.startMore();
			break;
			default:
				if(key == 65 && ctrlKey){
					this.selectAll();
				}
				else if(this.bindingRules["caption"]){
					//this should move to a onkeypress based function
					if(!this.lookup || new Date().getTime() - this.lookup.date.getTime() > 300) this.lookup = {
						str : "",
						date : new Date()
					};
					
					this.lookup.str += String.fromCharCode(key);
	
					var nodes = this.getTraverseNodes();
					for(var v,i=0;i<nodes.length;i++){
						v = this.applyRuleSetOnNode("caption", nodes[i]);
						if(v && v.substr(0, this.lookup.str.length).toUpperCase() == this.lookup.str){
							if(!this.isSelected(nodes[i])) this.select(nodes[i]);
							if(this.selected) this.oInt.scrollTop = this.selected.offsetTop - (this.oInt.offsetHeight - this.selected.offsetHeight)/2;
							return;
						}
					}
					
					return;
				}
			break;
		};
		
		this.lookup = null;
		return false;
	}
	
	
	/* ***********************
			DATABINDING
	************************/
	
	this.nodes = [];
	
	this.__add = function(xmlNode, Lid, xmlParentNode, htmlParentNode, beforeNode){
		//Build Row
		this.__getNewContext("Item");
		var Item = this.__getLayoutNode("Item");
		var elSelect = this.__getLayoutNode("Item", "select");
		var elIcon = this.__getLayoutNode("Item", "icon");
		var elImage = this.__getLayoutNode("Item", "image");
		var elCheckbox = this.__getLayoutNode("Item", "checkbox");
		var elCaption = this.__getLayoutNode("Item", "caption");
		
		Item.setAttribute("id", Lid);
		
		//elSelect.setAttribute("oncontextmenu", 'jpf.lookup(' + this.uniqueId + ').dispatchEvent("oncontextmenu", event);');
		elSelect.setAttribute("onmouseover", 'jpf.lookup(' + this.uniqueId + ').__setStyleClass(this, "hover");');
		elSelect.setAttribute("onmouseout", 'jpf.lookup(' + this.uniqueId + ').__setStyleClass(this, "", ["hover"]);'); 

		if(this.hasFeature(__RENAME__)){
			elSelect.setAttribute("ondblclick", 'var o = jpf.lookup(' + this.uniqueId + '); ' +
				'o.cancelRename();' + 
				' o.choose()');
			elSelect.setAttribute(this.itemSelectEvent || "onmousedown", 'var o = jpf.lookup(' + this.uniqueId + ');if(!o.renaming && o.isFocussed() && jpf.XMLDatabase.isChildOf(o.selected, this, true) && o.value) this.dorename = true;o.select(this, event.ctrlKey, event.shiftKey)'); 
			elSelect.setAttribute("onmouseup", 'if(this.dorename) jpf.lookup(' + this.uniqueId + ').startDelayedRename(event); this.dorename = false;');
		}
		else{
			elSelect.setAttribute("ondblclick", 'var o = jpf.lookup(' + this.uniqueId + '); o.choose()');
			elSelect.setAttribute(this.itemSelectEvent || "onmousedown", 'var o = jpf.lookup(' + this.uniqueId + '); o.select(this, event.ctrlKey, event.shiftKey)'); 
		}
		
		//Setup Nodes Identity (Look)
		if(elIcon){
			if(elIcon.nodeType == 1) elIcon.setAttribute("style", "background-image:url(" + this.iconPath + this.applyRuleSetOnNode("icon", xmlNode) + ")");
			else elIcon.nodeValue = this.iconPath + this.applyRuleSetOnNode("icon", xmlNode);
		}
		else if(elImage){
			if(elImage.nodeType == 1) elImage.setAttribute("style", "background-image:url(" + this.mediaPath + this.applyRuleSetOnNode("image", xmlNode) + ")");
			else{
				if(jpf.isSafariOld){ //HAAAAACCCCKKKKKK!!! this should be changed... blrgh..
					var p = elImage.ownerElement.parentNode;
					var img = p.appendChild(p.ownerDocument.createElement("img"));
					img.setAttribute("src", this.mediaPath + this.applyRuleSetOnNode("image", xmlNode));
				}
				else{
					elImage.nodeValue = this.mediaPath + this.applyRuleSetOnNode("image", xmlNode);
				}
			}
		}
		
		if(elCaption){
			jpf.XMLDatabase.setNodeValue(elCaption, this.applyRuleSetOnNode("caption", xmlNode));
			
		}
		Item.setAttribute("title", this.applyRuleSetOnNode("title", xmlNode) || "");
		
		var cssClass = this.applyRuleSetOnNode("css", xmlNode);
		if(cssClass){
			this.__setStyleClass(Item, cssClass);
			if(cssClass) this.dynCssClasses.push(cssClass);
		}

		if(this.__addModifier) this.__addModifier(xmlNode, Item);

		if(htmlParentNode) jpf.XMLDatabase.htmlImport(Item, htmlParentNode, beforeNode);
		else this.nodes.push(Item);
	}
	
	this.__fill = function(){
		if(this.more && !this.moreItem){
			this.__getNewContext("Item");
			var Item = this.__getLayoutNode("Item");
			var elCaption = this.__getLayoutNode("Item", "caption");
			var elSelect = this.__getLayoutNode("Item", "select");
			
			Item.setAttribute("class", "more");
			elSelect.setAttribute("onmousedown", 'jpf.lookup(' + this.uniqueId + ').__setStyleClass(this, "more_down");');
			elSelect.setAttribute("onmouseout", 'jpf.lookup(' + this.uniqueId + ').__setStyleClass(this, "", ["more_down"]);');
			elSelect.setAttribute("onmouseup", 'jpf.lookup(' + this.uniqueId + ').startMore(this)');
			
			if(elCaption) jpf.XMLDatabase.setNodeValue(elCaption, this.jml.getAttribute("more").match(/Caption:(.*)(;|$)/)[1]);
			this.nodes.push(Item);
		}
		
		jpf.XMLDatabase.htmlImport(this.nodes, this.oInt);
		this.nodes.length = 0;

		
		if(this.more && !this.moreItem){
			this.moreItem = this.oInt.lastChild;
		}
	}
	
	var lastAddedMore;
	this.startMore = function(o){
		this.__setStyleClass(o, "", ["more_down"]);
		
		var addedNode = this.add();
		this.select(addedNode, null, null, null, null, true);
		this.oInt.appendChild(this.moreItem);
		
		var undoLastAction = function(){
			this.getActionTracker().undo(this.autoselect ? 2 : 1);
			
			this.removeEventListener("oncancelrename", undoLastAction);
			this.removeEventListener("onbeforerename", removeSetRenameEvent);
			this.removeEventListener("onafterrename", afterRename);
		}
		var afterRename = function(){
			//this.select(addedNode);
			this.removeEventListener("onafterrename", afterRename);
		};
		var removeSetRenameEvent = function(e){
			this.removeEventListener("oncancelrename", undoLastAction);
			this.removeEventListener("onbeforerename", removeSetRenameEvent);
			
			//There is already a choice with the same value
			var xmlNode = this.findXmlNodeByValue(e.arguments[1]);
			if(xmlNode || !e.arguments[1]){
				this.getActionTracker().undo(this.autoselect ? 2 : 1);
				if(!this.isSelected(xmlNode)) this.select(xmlNode);
				this.removeEventListener("onafterrename", afterRename);
				return false;
			}
		};
		
		this.addEventListener("oncancelrename", undoLastAction);
		this.addEventListener("onbeforerename", removeSetRenameEvent);
		this.addEventListener("onafterrename", afterRename);
		
		if(this.mode == "radio"){
			this.moreItem.style.display = "none";
			if(lastAddedMore) this.removeEventListener("onxmlupdate", lastAddedMore);
			lastAddedMore = function(){this.moreItem.style.display = addedNode.parentNode ? "none" : "block";}
			this.addEventListener("onxmlupdate", lastAddedMore);
		}
		
		this.startDelayedRename({}, 1);
	}
	
	/* ***********************
				SELECT
	************************/
	
	this.__calcSelectRange = function(xmlStartNode, xmlEndNode){
		var r = [];
		var nodes = this.getTraverseNodes();
		for(var f=false,i=0;i<nodes.length;i++){
			if(nodes[i] == xmlStartNode) f = true;
			if(f) r.push(nodes[i]);
			if(nodes[i] == xmlEndNode) f = false;
		}
		
		if(!r.length || f){
			r = [];
			for(var f=false,i=nodes.length-1;i>=0;i--){
				if(nodes[i] == xmlStartNode) f = true;
				if(f) r.push(nodes[i]);
				if(nodes[i] == xmlEndNode) f = false;
			}
		}
		
		return r;
	}
	
	this.__selectDefault = function(XMLRoot){
		this.select(this.getTraverseNodes()[0]);
	}
	
	this.inherit(jpf.MultiSelect); /** @inherits jpf.MultiSelect */
	this.inherit(jpf.Cache); /** @inherits jpf.Cache */
	
	/* ***********************
	  Other Inheritance
	************************/
	
	this.inherit(jpf.Presentation); /** @inherits jpf.Presentation */
	this.inherit(jpf.DataBinding); /** @inherits jpf.DataBinding */
	
	//Added XForms support
	
	/**
	 * @private
	 *
	 * @allowchild  item, choices
 	 * @define  item 
 	 * @attribute  value  
 	 * @attribute  icon  
 	 * @attribute  image  
 	 * @allowchild  [cdata], label
 	 * @define  choices 
 	 * @allowchild  item
	 */
	this.loadInlineData = function(x){
		var value, caption, hasImage, hasIcon, strData = [], nodes = ($xmlns(x, "choices", jpf.ns.jpf)[0] || x).childNodes;

		for(var i=nodes.length-1;i>=0;i--){
			if(nodes[i].nodeType != 1) continue;
			if(nodes[i][jpf.TAGNAME] != "item") continue;
			
			hasIcon = nodes[i].getAttribute("icon") || "icoAnything.gif";
			hasImage = nodes[i].getAttribute("image");
			caption = jpf.getXmlValue(nodes[i], "label/text()|text()");// || (nodes[i].firstChild ? nodes[i].firstChild.nodeValue : "")
			value = jpf.getXmlValue(nodes[i], "value/text()|@value|text()").replace(/'/g, ""); // hack

			strData.unshift(
				"<item " + 
				(hasImage ? "image='" + hasImage + "'" : (hasIcon ? "icon='" + hasIcon + "'" : "")) + 
				" value='" + value + "'>" + caption + "</item>");

			nodes[i].parentNode.removeChild(nodes[i]);
		}

		if(strData.length){
			var sNode = new jpf.SmartBinding(null, jpf.getObject("XMLDOM", "<smartbindings xmlns='" + jpf.ns.jpf + "'><bindings><caption select='text()' />" + (hasImage ? "<image select='@image' />" : (hasIcon ? "<icon select='@icon'/>" : "")) + "<value select='@value'/><traverse select='item' /></bindings><model><items>" + strData.join("") + "</items></model></smartbindings>").documentElement);
			jpf.JMLParser.addToSbStack(this.uniqueId, sNode);
		}
		
		if(x.childNodes.length)
			jpf.JMLParser.parseChildren(x, null, this);
	}
	
	this.loadFillData = function(str){
		var parts = str.split("-");
		var start = parseInt(parts[0]);
		var end = parseInt(parts[1]);
		
		strData = [];
		for(var i=start;i<end+1;i++){
			strData.push("<item>" + (i+"").pad(Math.max(parts[0].length, parts[1].length), "0") + "</item>");
		}
		
		if(strData.length){
			var sNode = new jpf.SmartBinding(null, jpf.getObject("XMLDOM", "<smartbindings xmlns='" + jpf.ns.jpf + "'><bindings><caption select='text()' /><value select='text()'/><traverse select='item' /></bindings><model><items>" + strData.join("") + "</items></model></smartbindings>").documentElement);
			jpf.JMLParser.addToSbStack(this.uniqueId, sNode);
		}
	}
}

/*FILEHEAD(/in/Components/_base/BaseSimple.js)SIZE(2765)TIME(1203730484247)*/

/**
 * Baseclass of a Simple component
 *
 * @constructor
 * @baseclass
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.8
 */
jpf.BaseSimple = function(){
	/* ***********************
	  		Inheritance
	************************/
	this.inherit(jpf.Presentation); /** @inherits jpf.Presentation */

	this.inherit(jpf.DataBinding); /** @inherits jpf.DataBinding */
	
	/* ********************************************************************
										PROPERTIES
	*********************************************************************/
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/
	
	this.getValue = function(){
		return this.value;
	}

	/* ***********************
			DRAGDROP
	************************/
	
	this.__showDragIndicator = function(sel, e){
		var x = e.offsetX + 22;
		var y = e.offsetY;

		this.oDrag.startX = x;
		this.oDrag.startY = y;

		
		document.body.appendChild(this.oDrag);
		//this.oDrag.getElementsByTagName("DIV")[0].innerHTML = this.selected.innerHTML;
		//this.oDrag.getElementsByTagName("IMG")[0].src = this.selected.parentNode.parentNode.childNodes[1].firstChild.src;
		var oInt = this.__getLayoutNode("Main", "caption", this.oDrag);
		if(oInt.nodeType != 1) oInt = oInt.parentNode;
		
		oInt.innerHTML = this.applyRuleSetOnNode("caption", this.XMLRoot) || "";
		
		return this.oDrag;
	}
	
	this.__hideDragIndicator = function(){
		this.oDrag.style.display = "none";
	}
	
	this.__moveDragIndicator = function(e){
		this.oDrag.style.left = (e.clientX - this.oDrag.startX + document.documentElement.scrollLeft) + "px";
		this.oDrag.style.top = (e.clientY - this.oDrag.startY + document.documentElement.scrollTop) + "px";
	}
	
	this.__initDragDrop = function(){
		this.oDrag = document.body.appendChild(this.oExt.cloneNode(true));
		
		this.oDrag.style.zIndex = 1000000;
		this.oDrag.style.position = "absolute";
		this.oDrag.style.cursor = "default";
		this.oDrag.style.filter = "progid:DXImageTransform.Microsoft.Alpha(opacity=50)";
		this.oDrag.style.MozOpacity = 0.5;
		this.oDrag.style.opacity = 0.5;
		this.oDrag.style.display = "none";
	}
	
	this.__dragout = 
	this.__dragover = 
	this.__dragdrop = function(){}
	
	this.inherit(jpf.DragDrop); /** @inherits jpf.DragDrop */
	
	
	/* *********
		INIT
	**********/
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */

	this.setFormEl = function(formEl){
		this.formEl = formEl;
	}
}

/*FILEHEAD(/in/Components/_base/BaseTab.js)SIZE(11923)TIME(1213198732173)*/

/**
 * Baseclass of a Paged component
 *
 * @constructor
 * @baseclass
 * @allowchild page
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.8
 */
jpf.BaseTab = function(){
	/* ********************************************************************
										PROPERTIES
	*********************************************************************/

	this.activePage = -1;
	this.isPaged = true;
	this.focussable = true;
	var lastpages = [], pages = [], pageLUT = {};

	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/
	
	this.setActiveTab = function(active){
		return this.setProperty("activepage", active);	
	}

	this.__setActiveTab = function(active, no_event){
		if(typeof active == "string") active = pageLUT[active] || parseInt(active);
		if(!active) active = 0;
		
		if(!no_event && this.dispatchEvent("onbeforeswitch", {pageId : active, page : pages[active]}) === false){
			if(this.hideLoader) this.hideLoader(); 
			return false;
		}
		if(this.switchType == "hide-all" && (jpf.hasDeskRun || jpf.hasWebRun)) DeskRun.hideAll();
		if(!pages[active]) return false;
		
		// if we have a fake-page structure, only update the tabs visiblity when active==0	
		if(this.activePage > -1) pages[this.activePage].deactivate(pages[active].fake);
		pages[active].activate();
		
		this.activePage = active;
		
		if(jpf.layoutServer) jpf.layoutServer.forceResize(pages[active].oInt);
		
		if(jpf.hasDeskRun || jpf.hasWebRun){
			if(this.switchType == "hide-all") DeskRun.showAll();
			else DeskRun.fixShow();
		}
		
		if(this.hideLoader){
			if(pages[active].isRendered) this.hideLoader(); 
			else nextpage.addEventListener("onafterrender", function(){this.parentNode.hideLoader()});
		}
		
		if(!no_event){
			if(pages[active].isRendered) this.dispatchEvent("onafterswitch", {pageId : active, page : pages[active]});
			else pages[active].addEventListener("onafterrender", function(){
				this.parentNode.dispatchEvent("onafterswitch", {pageId : active, page : pages[active]});
			});
		}
		
		return true;
	}
	
	this.__supportedProperties = ["activepage"];
	this.__handlePropSet = function(prop, value, reqValue){
		if(prop == "activepage") return this.__setActiveTab(value);
	}
	
	this.getPages = function(){return pages}
	this.getPage = function(id){return pages[id || id === 0 ? id : this.activePage]}
	this.getPageName = function(id){return pages[id || id === 0 ? id : this.activePage].jml.getAttribute("name");}
	this.getPageId = function(name){return pageLUT[name];}
	
	function forpages(feat){
		for(var i=0;i<pages.length;i++)
			pages[i][feat]();
	}
	
	/* ***********************
		DISABLING
	************************/
	
	this.__enable = function(){
		forpages("enable");
	}
	
	this.__disable = function(){
		forpages("disable");
	}
	
	/* ********************************************************************
										PRIVATE METHODS
	*********************************************************************/

	this.addPage = function(xmlNode, userfunc){
		var id = pages.push(new jpf.TabPage(xmlNode, this)) - 1;
		if(pages[id].jml.getAttribute("name")) pageLUT[pages[id].jml.getAttribute("name")] = id;
		pages[id].draw(this.hasButtons, id, lastpages[id]);
		if(userfunc) userfunc.call(pages[id], xmlNode);
		return pages[id];
	}
	
	/**
	 * @experimental
	 */
	this.add = function(caption){
		var xmlNode = XMLDatabase.getXml('<j:Page caption="' + caption + '" xmlns:j="http://www.javeline.net/j" />');
		var id = pages.push(new TabPage(xmlNode, this)) - 1;
		if(pages[id].jml.getAttribute("name")) pageLUT[pages[id].jml.getAttribute("name")] = id;
		pages[id].draw(this.hasButtons, id);
		return pages[id];
	}
	
	/* ***********************
		Keyboard Support
	************************/
	
	//Handler for a plane list
	this.__keyHandler = function(key, ctrlKey, shiftKey, altKey){
		switch(key){
			case 9:
			
			break;
			case 13:
			
			break;
			case 32:
			
			break;
			case 37:
			//LEFT
				prevPage = this.activePage-1;
				while(prevPage >= 0 && !pages[prevPage].isVisible())
					prevPage--;
				if (prevPage >= 0)
					this.setActiveTab(prevPage);
			break;
			case 39:
			//RIGHT
				nextPage = this.activePage+1;
				while(nextPage < pages.length && !pages[nextPage].isVisible())
					nextPage++;
				if (nextPage < pages.length)
					this.setActiveTab(nextPage);	
			break;
			default:
			
			return;
		}
		
		//return false;
	}
	

	/* ***********************
	  Other Inheritance
	************************/
	this.inherit(jpf.Presentation); /** @inherits jpf.Presentation */
	
	this.editableParts = {"Button" : [["caption","@caption"]]};
	
	this.__drawTabs = function(userfunc){
		if(pages.length){
			lastpages = pages;
			pages = []; 
		}
		
		var nodes = this.jml.childNodes;
		for(var i=0;i<nodes.length;i++){
			if(nodes[i].nodeType != 1) continue;
			var tagName = nodes[i][jpf.TAGNAME];

			if(tagName == "page")
				this.addPage(nodes[i], userfunc);
			else if(tagName == "case" && nodes[i].getAttribute("id")) //or should this give an error?
				jpf.NameServer.register("case", nodes[i].getAttribute("id"), this.addPage(nodes[i], userfunc));
			else if(tagName == "loader") this.setLoading(nodes[i]);
			else if(this.addOther) this.addOther(tagName, nodes[i]);
		}
		
		lastpages = null;
		
		if(pages.length){
			pages[0].setFirst();
			if(pages.length > 1) pages[pages.length-1].setLast();
		}

		if(pages.length && this.activepage == 0) this.__setActiveTab(0);
		else if(pages.length){
			this.activepage = 0;
			this.__setActiveTab(0, true);
		}
		else jpf.JMLParser.parseChildren(this.jml, this.oExt, this);
	}
}

/**
 * Object representing a Page in a Paged component.
 *
 * @constructor
 * @define  page  
 * @allowchild  {components}, {anyjml}
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.8
 */
jpf.TabPage = function(JML, pJmlNode){
	jpf.register(this, "tabPage", GUI_NODE);/** @inherits jpf.Class */

	this.jml = JML;
	this.name = this.jml.getAttribute("name");
	this.fake = this.jml.getAttribute("fake") == 'true';
	
	if(this.name) jpf.setReference(this.name, this);
	this.hasButtons = false;
	this.pHtmlNode = pJmlNode.oPages;
	
	this.parentNode = pJmlNode;
	
	//Hack!!! somehow loadJml parts should be done here...
	if(this.jml.getAttribute("actiontracker")){
		this.__ActionTracker = self[this.jml.getAttribute("actiontracker")] ? 
			jpf.JMLParser.getActionTracker(this.jml.getAttribute("actiontracker")) :
			jpf.setReference(this.jml.getAttribute("actiontracker"), jpf.NameServer.register("actiontracker", this.jml.getAttribute("actiontracker"), new jpf.ActionTracker(this)));
	}
	
	this.editableParts = {"Button" : [["caption","@caption"]]};
	
	this.setCaption = function(caption){
		this.caption = caption;
		jpf.XMLDatabase.setNodeValue(pJmlNode.__getLayoutNode("Button", "caption", this.oButton), caption);
	}
	
	var position = 0;
	this.setFirst = function(){
		position = 1;
		pJmlNode.__setStyleClass(this.oButton, "firstbtn");
	}
	
	this.setLast = function(){
		position = -1;
		pJmlNode.__setStyleClass(this.oButton, "lastbtn");
	}

	/*this.getCaption = function(caption){
		return jpf.XMLDatabase.getNodeValue(pJmlNode.__getLayoutNode("Button", "caption", this.oButton));
	}*/
	
	// Actually, these two should be clearly marked as internals as they allow for total 
	// loss of any active tab, or activating more than one.	
	this.deactivate = function(fakeOther){
		if(this.disabled) return false;

		this.isActive = false
		
		if(this.hasButtons){
			if(position > 0) pJmlNode.__setStyleClass(this.oButton, "", ["firstcurbtn"]);
			pJmlNode.__setStyleClass(this.oButton, "", ["curbtn"]);
		}
		if(!this.fake && !fakeOther)pJmlNode.__setStyleClass(this.oExt, "", ["curpage"]);
	}
	
	this.activate = function(){
		if(this.disabled) return false;
		
		if(this.hasButtons){
			if(position > 0) pJmlNode.__setStyleClass(this.oButton, "firstcurbtn");
			pJmlNode.__setStyleClass(this.oButton, "curbtn");
		}
		if(!this.fake)pJmlNode.__setStyleClass(this.oExt, "curpage");
		
		this.isActive = true;
		
		this.render();
	}
	
	this.hide = function(){
		//if(this.oButton) this.oButton.style.display = "none";
		//this.oExt.style.display = "none";
		
		if (this.isActive)
		{
			this.deactivate();
			
			// Try to find a next page, if any.
			var nextPage = this.parentNode.activePage + 1;
			while (nextPage < this.parentNode.getPages().length && !this.parentNode.getPage(nextPage).isVisible())
				nextPage++;
			if (nextPage == this.parentNode.getPages().length)
			{
				// Try to find a previous page, if any.
				nextPage = this.parentNode.activePage - 1;
				while (nextPage >= 0 && this.parentNode.getPages().length && !this.parentNode.getPage(nextPage).isVisible())
					nextPage--;
			}
			
			if (nextPage >= 0)
				this.parentNode.getPage(nextPage).activate();		
		}
	}
	
	this.show = function(){
		//if(this.oButton) this.oButton.style.display = "block";
		//this.oExt.style.display = "block";
		
		if (!this.isActive){
			this.activate();
			var pages = this.parentNode.getPages();
			for(var i=0;i<pages.length;i++){
				if(pages[i] == this){
					pJmlNode.setActiveTab(i);
					break;
				}
			}
		}
	}
	
	this.draw = function(drawButtons, id, lastPage){
		this.hasButtons = drawButtons;
		this.caption = this.jml.getAttribute("caption");
		
		if(drawButtons){
			pJmlNode.__getNewContext("Button");
			var elBtn = pJmlNode.__getLayoutNode("Button");
			elBtn.setAttribute(pJmlNode.__getOption("Main", "select") || "onmousedown", 'jpf.lookup(' + pJmlNode.uniqueId + ').setActiveTab(' + id + ');if(!jpf.isSafariOld) this.onmouseout()');
			elBtn.setAttribute("onmouseover", 'var o = jpf.lookup(' + pJmlNode.uniqueId + ');if(' + id + ' != o.activePage) o.__setStyleClass(this, "over");');
			elBtn.setAttribute("onmouseout", 'var o = jpf.lookup(' + pJmlNode.uniqueId + '); o.__setStyleClass(this, "", ["over"]);');
			this.oButton = jpf.XMLDatabase.htmlImport(elBtn, pJmlNode.oButtons);
			
			this.setCaption(this.caption);
			
				pJmlNode.__makeEditable("Button", this.oButton, this.jml);
		}
		
		this.oExt = pJmlNode.__getExternal("Page", pJmlNode.oPages, null, this.jml);
		this.oInt = pJmlNode.__getLayoutNode("Page", "container", this.oExt);
		
		if(lastPage){
			jpf.JMLParser.replaceNode(this.oInt, lastPage.oInt);
			this.oInt.setAttribute("id", lastPage.oInt.getAttribute("id"));
		}
		else jpf.JMLParser.parseChildren(this.jml, this.oInt, this, true);
	}
	
	this.__destroy = function(){
		this.oButton = null;
	}
	
	/* ***********************
		OTHER INHERITANCE
	************************/
	
	this.inherit(jpf.DelayedRender); /** @inherits jpf.DelayedRender */
	
	//Hack
	this.addEventListener("onbeforerender", function(){pJmlNode.dispatchEvent("onbeforerender", {page : this});});
	this.addEventListener("onafterrender", function(){pJmlNode.dispatchEvent("onafterrender", {page : this});});
	
	//this.inherit(jpf.Presentation); /** @inherits jpf.Presentation */
	this.inherit(jpf.JmlNode); /** @inherits jpf.JmlNode */
	
	this.inherit(jpf.JmlDomAPI); /** @inherits jpf.JmlDomAPI */
}

/*FILEHEAD(/in/Core/TelePort.js)SIZE(4040)TIME(1203730484247)*/
__HTTP_SUCCESS__ = 1;
__HTTP_TIMEOUT__ = 2;
__HTTP_ERROR__ = 3;

__RPC_SUCCESS__ = 1;
__RPC_TIMEOUT__ = 2;
__RPC_ERROR__ = 3;


/**
 * @define teleport 
 * @allowchild  rpc, poll, socket
 */
jpf.Teleport = {
	modules : new Array(),
	named : {},

	register : function(obj){
		var id = false, data = {
			obj : obj
		};

		return this.modules.push(data) - 1;
	},

	getModules : function(){
		return this.modules;
	},

	getModuleByName : function(defname){
		return this.named[defname]
	},

	// Set Communication
	Init : function(){
		this.inited = true;

		var comdef = document.documentElement.getElementsByTagName("head")[0].getElementsByTagName(IS_IE ? "teleport" : "j:teleport")[0];
		if(!comdef && document.documentElement.getElementsByTagNameNS) comdef = document.documentElement.getElementsByTagNameNS("http://javeline.nl/j", "j:teleport")[0];
		if(!comdef){
			this.isInited = true;
			return issueWarning(1006, "Could not find Javeline TelePort Definition")
		}
		if(comdef.getAttribute("src")){
			new HTTP().getXml(HOST_PATH + comdef.getAttribute("src"), function(xmlNode, state, extra){
				if(state != __RPC_SUCCESS__){
					if(extra.retries < MAX_RETRIES) return HTTP.retry(extra.id);
					else throw new Error(1021, jpf.formErrrorString(1021, null, "Application", "Could not load Javeline TelePort Definition:\n\n" + extra.message));
				}

				jpf.TelePort.xml = xmlNode;
				jpf.TelePort.isInited = true;

				//if(self.PACKAGED) jpf.TelePort.load();
			}, true);
		}
		else{
			var xmlNode = comdef.firstChild ? XMLDatabase.getDataIsland(comdef.firstChild) : null

			jpf.TelePort.xml = xmlNode;
			jpf.TelePort.isInited = true;

			//if(self.PACKAGED) jpf.TelePort.load();
		}
	},

	// Load TelePort Definition
	loadJML : function(x){
		if(x) this.jml = x;
		if(!x) return;

		var nodes = this.jml.childNodes;
		if(!nodes.length) return;

		for(var i=0;i<nodes.length;i++){
			if(nodes[i].nodeType != 1) continue;

			//Socket Communication
			if(nodes[i][jpf.TAGNAME] == "socket")
				jpf.setReference(nodes[i].getAttribute("id"), new jpf.socket()).load(nodes[i]);

			//Polling Engine
			else if(nodes[i][jpf.TAGNAME] == "poll")
				jpf.setReference(nodes[i].getAttribute("id"), new jpf.poll().load(nodes[i]));

			//Initialize Communication Component
			else jpf.setReference(nodes[i].getAttribute("id"), new jpf.BaseComm(nodes[i]));
		}

		this.loaded = true;
		if(this.onload) this.onload();
	}
}

/**
 * @constructor
 * @baseclass
 */
jpf.BaseComm = function(x){
	jpf.makeClass(this);
	this.uniqueId = jpf.all.push(this) - 1;
	this.jml = x;

	this.toString = function(){
		return "[Javeline TelePort Component : " + (this.name || "") + " (" + this.type + ")]";
	}

	if(this.jml){
		this.name = x.getAttribute("id");
		this.type = x[jpf.TAGNAME];

		// Inherit from the specified baseclass
		if(!jpf[this.type]) throw new Error(1023, jpf.formErrorString(1023, null, "TelePort baseclass", "Could not find Javeline TelePort Component '" + this.type + "'", this.jml));
		
		this.inherit(jpf[this.type]); /** @inherits jpf[this.type] */

		if(this.useHTTP){
			// Inherit from HTTP Module
			if(!jpf.http) throw new Error(1024, jpf.formErrorString(1024, null, "Teleport baseclass", "Could not find Javeline TelePort HTTP Component", this.jml));
			this.inherit(jpf.http); /** @inherits jpf.http */
		}

		if(this.jml.getAttribute("protocol")){
			// Inherit from Module
			if(!jpf[this.jml.getAttribute("protocol").toLowerCase()]) throw new Error(1025, jpf.formErrorString(1025, null, "Teleport baseclass", "Could not find Javeline TelePort RPC Component '" + this.jml.getAttribute("protocol") + "'", this.jml));
			this.inherit(jpf[this.jml.getAttribute("protocol").toLowerCase()]); /** @inherits jpf[this.jml.getAttribute("protocol").toLowerCase()] */
		}
	}

	// Load Comm definition
	if(this.jml) this.load(this.jml);
}


jpf.Init.run('TelePort');
/*FILEHEAD(/in/Core/Window.js)SIZE(10600)TIME(1213483123975)*/

jpf.windowManager = {
	destroy : function(frm){
		//Remove All Cross Window References Created on Init by jpf.windowManager
		//for(var i=0;i<this.globals.length;i++) frm.win[this.globals[i]] = null;
	},
	
	root : self,
	userdata : [],
	
	/* ********************************************************************
											FORMS
	*********************************************************************/
	forms : new Array(),
	
	addForm : function(xmlFormNode){
		var x = {
			jml : xmlFormNode,
			show : function(){
				alert("not implemented");
			}
		};
		this.forms.push(jpf.setReference(x.name, x, true));
		return x;
	},
	
	getForm : function(value){
		for(var i=0;i<this.forms.length;i++) if(this.forms[i].name == value) return this.forms[i];
		
		return this.forms.length ? this.forms[0] : false;
	},
	
	closeAll : function(){
		for(var i=0;i<this.forms.length;i++) if(this.forms[i].name != "main" && this.forms[i].type != "modal") this.forms[i].hide();
	}
}

/* ****************
	FORM CLASS
*****************/

/**
 * Object representing the window of the JML application
 *
 * @classDescription		This class creates a new window
 * @return {Window} Returns a new window
 * @type {Window}
 * @constructor
 * @jpfclass
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.8
 */
jpf.WindowImplementation = function(){
	jpf.register(this, "window", NOGUI_NODE);/** @inherits jpf.Class */
	this.jpf = jpf;
	
	this.toString = function(){
		return "[Javeline Component : " + (this.name || "") + " (jpf.window)]";
	}
	
	this.getActionTracker = function(){return this.__ActionTracker}
	
	/* ***********************
			API
	************************/
	
	this.loadCodeFile = function(url){
		//if(jpf.isSafari) return;
		if(self[url]) jpf.importClass(self[url], true, this.win);
		else jpf.include(url);//, this.document);
	}

	/*
	this.loadCodeFile = function(url){
		jpf.include(url, this.document);
	}*/
	
	this.flash = function(){
		if(jpf.hasDeskRun) jdwin.Flash();
	}
	
	this.show = function(){
		if(jpf.hasDeskRun) jdwin.Show();
	}
	
	this.hide = function(){
		if(jpf.hasDeskRun) jdwin.Hide();

		else{
			this.loaded = false;
			if(this.win) this.win.close();
		}
	}
	
	this.focus = function(){
		if(jpf.hasDeskRun) jdwin.SetFocus();
		else this.win.focus();
	}
	
	this.isActive = function(){
		var root = jpf.getRoot();
		return (root ? root.activeWindow == self : false);
	}
	
	this.setIcon = function(url){
		if(jpf.hasDeskRun) jdwin.icon = parseInt(url) == url ? parseInt(url) : url;
	}
	
	this.setTitle = function(value){
		this.title = value || "";
		
		if(jpf.hasDeskRun) jdwin.caption = value;
		else if(this.win && this.win.document) this.win.document.title = (value || "");
	}
	
	/* ***********************
			Init
	************************/
	
	this.loadJML = function(x){
		if(x[jpf.TAGNAME] == "deskrun") this.loadDeskRun(x);
		else{
			
		}
	}
	
	var jdwin = jpf.hasDeskRun ? window.external : null, jdshell = jpf.hasDeskRun ? jdwin.shell : null;
	this.loadDeskRun = function(q){
		jdwin.style = q.getAttribute("style") || "ismain|taskbar|btn-close|btn-max|btn-min|resizable";

		jpf.appsettings.drRegName = q.getAttribute("record");
		if(q.getAttribute("minwidth")) jdwin.setMin(q.getAttribute("minwidth"), q.getAttribute("minheight"));
		if(q.getAttribute("record")&& jdshell.RegGet(jpf.appsettings.drRegName + "/window")){
			var winpos = jdshell.RegGet(jpf.appsettings.drRegName + "/window");
			if(winpos){
				winpos = winpos.split(",");
				window.external.width = Math.max(q.getAttribute("minwidth"), Math.min(parseInt(winpos[2]),window.external.shell.GetSysValue("deskwidth")));
				window.external.height = Math.max(q.getAttribute("minheight"), Math.min(parseInt(winpos[3]),window.external.shell.GetSysValue("deskheight")));
				window.external.left = Math.max(0,Math.min(parseInt(winpos[0]),screen.width - window.external.width));
				window.external.top = Math.max(0,Math.min(parseInt(winpos[1]),screen.height - window.external.height));
			}
		}
		else{
			jdwin.left = q.getAttribute("left") || 200;
			jdwin.top = q.getAttribute("top") || 200;
			jdwin.width = q.getAttribute("width") || 800;
			jdwin.height = q.getAttribute("height") || 600;
		}
		
		jdwin.caption = q.getAttribute("caption") || "Javeline DeskRun";
		jdwin.icon = q.getAttribute("icon") || 100;

		var ct = $xmlns(q, "context", jpf.ns.jpf);		
		if(ct.length){
			ct = ct[0];
			if(!jpf.appsettings.tray) jpf.appsettings.tray = window.external.CreateWidget("trayicon")
			var tray = jpf.appsettings.tray;

			tray.icon = q.getAttribute("tray") || 100;
			tray.tip = q.getAttribute("tooltip") || "Javeline DeskRun";
			tray.PopupClear();
			tray.PopupItemAdd("Exit", 3);
			tray.PopupItemAdd("SEP", function(){});
			
			var nodes = ct.childNodes;
			for(var i=nodes.length-1;i>=0;i--){
				if(nodes[i].nodeType != 1) continue;
				
				if(nodes[i][jpf.TAGNAME] == "divider"){
					tray.PopupItemAdd("SEP", function(){});
				}
				else{
					tray.PopupItemAdd(jpf.getXmlValue(nodes[i], "."), nodes[i].getAttribute("href") ? new Function("window.open('" + nodes[i].getAttribute("href") + "')") : new Function(nodes[i].getAttribute("onclick")));
				}
			}
		}

		jdwin.shell.debug = jpf.debug ? 7 : 0;
		jdwin.Show();
		jdwin.SetFocus();
	}
	
	/* ******** FOCUS METHODS *********
		Methods handling focus in
		the form object.
	*********************************/
	this.__f = Array();
	
	this.__focus = function(o, norun){
		//CHANGE THIS FUNCTION TO DETECT IF OBJECT IS VISIBLE
		if(this.__fObject == o) return;
		if(this.__fObject) this.__fObject.blur(true);
		//if(this.__fObject) this.__fObject.oExt.style.border = "2px solid black";
		(this.__fObject = o).focus(true);
		//if(o.oExt) o.oExt.style.border = "2px solid red";

		if(this.onmovefocus) this.onmovefocus(this.__fObject);
		
		o.dispatchEvent("xforms-focus");
		o.dispatchEvent("DOMFocusIn");
		
		jpf.status("Focus given to " + this.__fObject.name + " [" + this.__fObject.tagName + "]");
	}
	
	this.__blur = function(o){
		//NOT A GOOD SOLUTION
		if(this.__fObject == o) this.__fObject = null;
		if(this.onmovefocus) this.onmovefocus(this.__fObject);
		
		o.dispatchEvent("DOMFocusOut");
	}
	
	this.isFocussed = function(o){return this.__fObject == o;}
	this.getFocussedObject = function(){return this.__fObject;}
	
	this.__removeFocus = function(o){
		this.__f[o.tabIndex] = null;
		delete this.__f[o.tabIndex];
	}
	
	this.__addFocus = function(o, tabIndex){
		if(o.__FID == null) o.__FID = tabIndex !== null ? tabIndex : this.__f.length;
		
		var cComp = this.__f[o.__FID];
		if(cComp && cComp.jml && !cComp.jml.getAttribute("tabseq")){
			//cComp.setTabIndex(this.__f.length);
			this.__f[o.__FID] = null;
			cComp.__FID = this.__f.push(cComp) - 1;
			
		}
		
		if(this.__f[o.__FID] && this.__f[o.__FID] != o) throw new Error(1027, jpf.formErrorString(1027, null, "Tab switching", "TabIndex Already in use: '" + o.__FID + "' for " + o.toString() + ".\n It's in use by " + cComp.toString()));
		
		this.__f[o.__FID] = o;
		o.tabIndex = tabIndex;
	}
	
	this.moveNext = function(shiftKey, relObject){
		var next = null, o = relObject || jpf.window.__fObject, start = o ? o.__FID : jpf.window.__f.length;

		if(jpf.window.__fObject && jpf.window.__f.length < 2) return;
		
		do{
			next = (o ? parseInt(o.__FID) + (shiftKey ? -1 : 1) : (next != null ? next + (shiftKey ? -1 : 1) : 0));
			
			if(start == next) return; //No visible enabled element was found
			
			if(next >= jpf.window.__f.length) next = 0;
			else if(next < 0) next = jpf.window.__f.length-1;
			
			o = jpf.window.__f[next];
			
		}while(!o || o.disabled || o == jpf.window.__fObject || (o.oExt && !o.oExt.offsetHeight) || !o.focussable);
		
		jpf.window.__focus(o);
		
		this.dispatchEvent("xforms-" + (shiftKey ? "previous" : "next"));
	}
	
	/* ********************************
		Destroy
	*********************************/
	
	this.destroy = function(){
		ActionTracker = this.ActionTracker = null;
		
		jpf.destroy(this);
		jpf.windowManager.destroy(this);
		jpf = this.win = this.window = this.document = null;
		
		window.onfocus = null;
		window.onerror = null;
		window.onunload = null;
		window.onbeforeunload = null;
		window.onblur = null;
		
		document.body.innerHTML = "";
	}
}

/**
 * Object representing the document of the JML application.
 *
 * @classDescription		This class creates a new document
 * @return {Document} Returns a new document
 * @type {Document}
 * @constructor
 * @jpfclass
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.8
 */
jpf.DocumentImplementation = function(){
	jpf.makeClass(this);
	this.inherit(jpf.JmlDomAPI); /** @inherits jpf.JmlDomAPI */
	this.nodeType = DOC_NODE;

	/* ******** createElement ***********
		Create Javeline GUI Element
	
		INTERFACE:
		this.createElement(x, p, win, ro);
	****************************/
	//JML
	//if(jpf.isOpera) x.scopeName = x[jpf.TAGNAME] != x.tagName ? "j" : ""; //This might break
	//if(jpf.isSafariOld) x.scopeName = !x.namespaceURI || x.namespaceURI.indexOf("http://www.w3.org/") != -1 ? "" : "j";
	//if(!jpf.isIE && !self.NAMESPACE) NAMESPACE = "prefix";//x.scopeName == undefined ? "prefix" : "scopeName";
	//(x.prefix || x.scopeName) == this.lastNsPrefix
	this.createElement = function(tagName, jmlNode, parentHtmlNode, pJmlNode){
		jpf.status("Creating Element " + tagName);
		if(!tagName) tagName = jmlNode[jpf.TAGNAME];

		if(!jpf[tagName] || typeof jpf[tagName] != "function") throw new Error(1017, jpf.formErrorString(1017, null, "Initialization", "Could not find Class Definition '" + tagName + "'.", x));
		if(!jpf[tagName]) throw new Error(0, "Could not find class " + tagName);
		
		if(!jpf.JMLParser.jml) throw new Error(0, "Unspecified error");
		var x = jmlNode || jpf.JMLParser.jml.ownerDocument.createElement(tagName); //namespace?
		
		//Create Object en Reference
		var o = new jpf[tagName](parentHtmlNode, tagName, x);

		//Process JML
		if(o.loadJML) o.loadJML(x, pJmlNode);
		if(x.getAttribute("id")) jpf.setReference(x.getAttribute("id"), o);
		
		return o;
	}
}

/*FILEHEAD(/in/Core/JmlNode.js)SIZE(21706)TIME(1213491118609)*/
__JMLNODE__ = 1<<15;
__VALIDATION__ = 1<<6;


/**
 * Baseclass for any Javeline Markup Language component.
 *
 * @constructor
 * @baseclass
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.4
 */
jpf.JmlNode = function(){
	/**
	 * Returns a string representation of this component.
	 *
	 * @return  {String}  a representation of this component
	 */
	this.toString = function(){
		return "[Javeline Component : " + (this.name || "") + " (" + this.tagName + ")]";
	}
	
	this.__regbase = this.__regbase|__JMLNODE__;
	
	/* ***********************
		BASIC METHODS
	************************/
	
	/**
	 * Set the different between the left edge and the right edge of this component in pixels.
	 *
	 * @param  {Integer}  value  reguired 
	 */
	this.setWidth = function(value, diff){this.oExt.style.width = Math.max(0, (value - (!diff && diff!==0 ? jpf.compat.getWidthDiff(this.oExt) : diff))) + "px";}
	
	/**
	 * Set the different between the top edge and the bottom edge of this component in pixels.
	 *
	 * @param  {Integer}  value  reguired 
	 */
	this.setHeight = function(value, diff){ this.oExt.style.height = Math.max(0, (value - (!diff && diff!==0 ? jpf.compat.getHeightDiff(this.oExt) : diff))) + "px";}
	this.setLeft = function(value){this.oExt.style.position = "absolute";this.oExt.style.left = value + "px"}
	this.setTop = function(value){this.oExt.style.position = "absolute";this.oExt.style.top = value + "px"}
	
	this.setZIndex = function(value){this.setProperty("zindex", value);}
	this.enable = function(){this.setProperty("disabled", false);}
	this.disable = function(){this.setProperty("disabled", true);}

	var noAlignUpdate = false;
	if(!this.show) this.show = function(s){noAlignUpdate = s;this.setProperty("visible", true);noAlignUpdate = false;};
	if(!this.hide) this.hide = function(s){noAlignUpdate = s;this.setProperty("visible", false);noAlignUpdate = false;};
	
	this.getWidth = function(){return this.oExt ? this.oExt.offsetWidth : null}
	this.getHeight = function(){return this.oExt ? this.oExt.offsetHeight : null}
	this.getLeft = function(){return this.oExt ? this.oExt.offsetLeft : null}
	this.getTop = function(){return this.oExt ? this.oExt.offsetTop : null}
	this.getZIndex = function(){return this.oExt ? jpf.compat.getStyle(this.oExt, "zIndex") : null}
	
	this.isVisible = function(value){return this.oExt ? this.oExt.style.display != "none" : null;}
	
	/* ***********************
		JML
	************************/
	this.loadJML = function(x, pJmlNode, ignoreBindclass, id){
		this.name = x.getAttribute("id");
		
		if(x){
			if(!this.parentNode) this.parentNode = pJmlNode;
			
			this.jml = x;
		}
		else x = this.jml;
		
		var attr = x.attributes;
		for(var i=0;i<attr.length;i++){
			if(attr[i].nodeName.substr(0,2) == "on") this.addEventListener(attr[i].nodeName, new Function(attr[i].nodeValue));
		}
		
		//Drawing
		if(this.nodeType != NOGUI_NODE){
			this.inherit(jpf.JmlDomAPI); /** @inherits jpf.JmlDomAPI */
			
			
			this.inherit(jpf.MultiLang); /** @inherits jpf.MultiLang */
			
			if(this.loadSkin) this.loadSkin();
			
			//Draw
			this.draw();
			
			if(id) this.oExt.setAttribute("id", id);
			//this.__initLayout(x);
			
			this.drawed = true;
			this.dispatchEvent("ondraw");
		}
		
		if(this.nodeType == GUI_NODE){
			if(self.jpf.debug && !jpf.hasDeskRun && !jpf.hasWebRun) this.oExt.setAttribute("uniqueId", this.uniqueId);
		}
		
		if(!ignoreBindclass){
			if(!this.hasFeature(__DATABINDING__) && x.getAttribute("smartbinding")){
				this.inherit(jpf.DataBinding);
				this.__xmlUpdate = this.__load = function(){}
			}
		}
		
		/* ************************
			Read JML and set a collection of commonly used settings
		*************************/
		
		if(x.getAttribute("actiontracker")){
			this.__ActionTracker = self[x.getAttribute("actiontracker")] ? 
				jpf.JMLParser.getActionTracker(x.getAttribute("actiontracker")) :
				jpf.setReference(x.getAttribute("actiontracker"), jpf.NameServer.register("actiontracker", x.getAttribute("actiontracker"), new jpf.ActionTracker(this)));
		}

		//Load subJML
		if(x.getAttribute("jml")){
			this.insertJML(x.getAttribute("jml"));
			x.removeAttribute("jml");
		}
		else if(this.__loadJML) this.__loadJML(x);
		
		this.dispatchEvent("onloadjml"); //Stupid IE crashes silently when this is put at the end of the function
		
		//Layout handling
		//should all layout properties be dynamic???
		if(this.nodeType == GUI_NODE){
			this.inherit(jpf.Alignment); /** @inherits jpf.Alignment */
			this.inherit(jpf.Anchoring); /** @inherits jpf.Anchoring */

			if(x.getAttribute("align") || x.parentNode[jpf.TAGNAME].match(/^(?:vbox|hbox)$/)) 
				this.enableAlignment();
			else
			if(x.getAttribute("left") || x.getAttribute("right") || x.getAttribute("top") || x.getAttribute("bottom"))
				this.enableAnchoring();
			else
			{
				var diff = jpf.compat.getDiff(this.oExt);
				
				if(x.getAttribute("left")) this.setLeft(x.getAttribute("left"));
				if(x.getAttribute("top")) this.setTop(x.getAttribute("top"));
				if(x.getAttribute("width")) this.setWidth(x.getAttribute("width"), diff[0]);
				if(x.getAttribute("height")) this.setHeight(x.getAttribute("height"), diff[1]);
			}
		}
		
		//Grid handling
		if(jpf.isTrue(x.getAttribute("autosize"))){
			this.oExt.style.overflow = "visible";
			this.oExt.style.height = "auto";
		}
		
		//Process JML Handlers
		for(var i=this.__jmlLoaders.length-1;i>=0;i--)
			this.__jmlLoaders[i].call(this, x);
		//this.__jmlLoaders = undefined; // Why was this here?
		
		//if(this.nodeType == NOGUI_NODE) return; //Dynamic properties shouldnt be added for nongui nodes.
		
		//Dynamic Properties
		if(!this.__supportedProperties) this.__supportedProperties = [];
		if(this.nodeType != NOGUI_NODE){
			//Default Dynamic Properties for NONGUI NODES
			this.__supportedProperties.push("focussable", "zindex", "visible", "disabled", "disable-keyboard", "contextmenu");
			if(this.visible === null) this.visible = true; //default value;
			if(jpf.isFalse(x.getAttribute("visible"))){
				this.oExt.style.display = "none";
				this.visible = false;
			}
		}
		
		for(var i=this.__supportedProperties.length-1;i>=0;--i){
			var pValue = x.getAttribute(this.__supportedProperties[i]);
			if(!pValue) continue;
			
			jpf.JMLParser.stateStack.push([this, this.__supportedProperties[i], pValue]);
		}
		
		//Set focussable if needed
		if(this.focussable) this.handlePropSet("focussable", true);
	}
	
	var jmlNode = this;
	this.handlePropSet = function(prop, value, force){
		if(!force && this.XMLRoot && this.bindingRules && this.bindingRules[prop])
			return jpf.XMLDatabase.setNodeValue(this.getNodeFromRule(prop.toLowerCase(), this.XMLRoot, null, null, true), value, true);
		
		this[prop] = value;
		
		/* **** TODO:
		- Fix width/height/left/top/right/bottom with integration in anchoring en alignment
		**********/

		// this code sufferes from a little overhead from unrequired execution at init
		switch(prop){
			case "focussable":
				this.focussable = !jpf.isFalse(value);
				if(this.focussable) jpf.window.__addFocus(this, this.tabIndex || this.jml.getAttribute("tabseq"));
				else jpf.window.__removeFocus(this);
			break;
			case "zindex":
				this.oExt.style.zIndex = value;
			break;
			case "visible":
				if(jpf.isFalse(value)){
					//this.oExt.style.display = "none";
					
					if(!noAlignUpdate && this.hasFeature(__ALIGNMENT__) && this.aData){
						this.disableAlignment(true);
						//setTimeout(function(){jmlNode.oExt.style.display = "none";});
					}
					else 
						this.oExt.style.display = "none";
					
					if(jpf.window.isFocussed(this)) jpf.window.moveNext();
					//if(!noAlignUpdate && this.hasFeature(__ANCHORING__)) this.disableAnchoring(true);//jpf.JMLParser.loaded
					this.visible = false;
				}
				else if(jpf.isTrue(value)){
					//if(!noAlignUpdate && this.hasFeature(__ANCHORING__)) this.enableAnchoring(true);//jpf.JMLParser.loaded
					if(!noAlignUpdate && this.hasFeature(__ALIGNMENT__) && this.aData){
						this.enableAlignment(true);
						//setTimeout(function(){jmlNode.oExt.style.display = "block";});
					}
					else 
						this.oExt.style.display = "block"; //Some form of inheritance detection
					this.visible = true;
				}
			break;
			case "disabled":
				if(jpf.isTrue(value)){
					this.disabled = false;
					if(this.hasFeature(__PRESENTATION__)) 
						this.__setStyleClass(this.oExt, this.baseCSSname + "Disabled");
					
					if(this.__disable) this.__disable();
					
					this.dispatchEvent("xforms-disabled");
					this.dispatchEvent("xforms-readonly");
					
					this.disabled = true;
				}
				else{
					if(this.hasFeature(__DATABINDING__) && jpf.appsettings.autoDisable & !this.isBoundComplete()) return false;
					this.disabled = false;
					
					if(this.hasFeature(__PRESENTATION__))
						this.__setStyleClass(this.oExt, null, [this.baseCSSname + "Disabled"]);
					
					if(this.__enable) this.__enable();
					
					this.dispatchEvent("xforms-enabled");
					this.dispatchEvent("xforms-readwrite");
				}
			break;
			case "disable-keyboard":
				this.disableKeyboard = jpf.isTrue(value);
			break;
			case "width":
				this.setWidth(value);
			break;
			case "height":
				this.setHeight(value);
			break;
			case "contextmenu":
				this.contextmenus = [value];
			break;
		}
		
		if(this.__handlePropSet){
			return this.__handlePropSet(prop, value);
		}
	}
	/* make this:
		- insertJML(xmlNode)
		- insertJML(xmlString)
		- insertJML(instruction)
		- replaceJML(xmlNode)
		- replaceJML(xmlString)
		- replaceJML(instruction)
	*/
	
	this.replaceJML = function(jmlDefNode, oInt, oIntJML, isHidden){
		jpf.status("Remove all jml from element");
		
		//Remove All the childNodes
		for(var i=0;i<this.childNodes.length;i++){
			var oItem = this.childNodes[i];
			var nodes = oItem.childNodes;
			for(var k=0;k<nodes.length;k++) nodes[k].destroySelf();	
			jpf.removeNode(oItem.oExt);
		}
		this.childNodes.length = 0;
		
		//Do an insertJML
		this.insertJML(jmlDefNode, oInt, oIntJML, isHidden);
	}
	
	this.insertJML = function(jmlDefNode, oInt, oIntJML, isHidden){
		jpf.status("Loading sub jml from external source");
		
		var jmlNode = this;
		var callback = function(data, state, extra){
			if(state != __HTTP_SUCCESS__){
				if(state == __HTTP_TIMEOUT__ && extra.retries < jpf.maxHttpRetries) return extra.tpModule.retry(extra.id);
				else{
					var commError = new Error(1019, jpf.formErrorString(1019, jmlNode, "Loading extra jml from datasource", "Could not load JML from remote resource \n\n" + extra.message));
					if(jmlNode.dispatchEvent("onerror", jpf.extend({error : commError, state : status}, extra)) !== false)
						throw commError;
					return;
				}
			}
			
			jpf.status("Runtime inserting jml");
	
			var JML = oIntJML || jmlNode.jml;
			/*
				This only works when j:application was found inside the 
				html tag (instead of in a seperate file). Add conditional
				to use xmlImport
			*/
			JML.insertAdjacentHTML(JML.getAttribute("insert") || "beforeend", data.length ? data[0] : data);
			jpf.JMLParser.parseFirstPass(JML);
			jpf.JMLParser.parseChildren(JML, oInt || jmlNode.oInt, null, null, isHidden && (oInt || jmlNode.oInt).style.offsetHeight ? true : false);
			
			jpf.layoutServer.activateGrid();
			jpf.layoutServer.activateRules();//document.body ?? is this allright
			
			jpf.JMLParser.parseLastPass();
		}
		
		if(typeof jmlDefNode == "string"){
			//Process Instruction
			if(jmlDefNode.match(/^(?:url|url.post|rpc|call|eval|cookie|gears):/))
				return jpf.getData(jmlDefNode, null, callback);
			//Jml string
			else jmlDefNode = XMLDatabase.getXml(jmlDefNode);
		}
		
		//Xml Node is assumed
		return callback(jmlDefNode, __HTTP_SUCCESS__);
	}
	
	this.setTabIndex = function(tabIndex){
		jpf.window.__removeFocus(this);
		jpf.window.__addFocus(this, tabIndex);
	}
	
	/* ***********************
		FOCUS
	************************/
	
	if(this.focussable){
		this.focus = function(noset){
			this.__focus(this);
			if(!noset) jpf.window.__focus(this);
			
			this.dispatchEvent("onfocus");
		}
		
		this.blur = function(noset){
			this.__blur(this);
			if(!noset) jpf.window.__blur(this);
			
			this.dispatchEvent("onblur");
		}
		
		this.isFocussed = function(){
			return jpf.window.isFocussed(this);
		}
	}
	else this.focussable = false;

	if(this.hasFeature(__DATABINDING__) && !this.hasFeature(__MULTISELECT__) && !this.change){
		/* ***********************
				Change Action
		************************/
		/**
		 * @action
		 * @param  {variant}  string  optional  New value of this component.
		 */
		this.change = function(value){
			
			if(this.errBox && this.errBox.isVisible() && this.isValid())
				this.clearError();
			
			//Not databound
			if((!this.createModel || !this.jml.getAttribute("ref")) && !this.XMLRoot){
				if(this.dispatchEvent("onbeforechange", {value : value}) === false) return;
				this.setProperty("value", value);
				return this.dispatchEvent("onafterchange", {value : value});
			}
			
			this.executeActionByRuleSet("change", this.mainBind, this.XMLRoot, value);
		}	
	}
	
	//this.getNodeFromRule = function(){return false}
	if(this.setValue && !this.clear) this.clear = function(nomsg){
		if(this.__setClearMessage){
			if(!nomsg) this.__setClearMessage(this.msg);
			else if(this.__removeClearMessage) this.__removeClearMessage();
		}
		
		//this.setValue("")
		this.value = -99999; //force resetting
		this.__handlePropSet ? this.__handlePropSet("value", "") : this.setValue("");
	}
	
	//ContextMenu support
	this.addEventListener("oncontextmenu", function(e){
		if(!this.contextmenus) return;
		var contextmenu, xmlNode = this.hasFeature(__MULTISELECT__) ? this.value : this.XMLRoot;
		
		for(var i=0;i<this.contextmenus.length;i++){
			var isRef = typeof this.contextmenus[i] == "string";
			if(!isRef) var sel = this.contextmenus[i].getAttribute("select");
			if(isRef || xmlNode && xmlNode.selectSingleNode(sel || ".") || !xmlNode && !sel){
				var menuId = isRef ? this.contextmenus[i] : this.contextmenus[i].getAttribute("menu")
				
				if(!self[menuId]){
					throw new Error(0, jpf.formErrorString(jmlParent, "Showing contextmenu", "Could not find contextmenu by name: '" + menuId + "'"));
				}
				
				self[menuId].display(e.htmlEvent.clientX+document.documentElement.scrollLeft, e.htmlEvent.clientY+document.documentElement.scrollTop, null, null, xmlNode);
				e.htmlEvent.returnValue = false;
				break;
			}
		}
		
		//IE6 compatiblity
		if(!jpf.appsettings.disableRightClick){
			document.oncontextmenu = function(){
				document.oncontextmenu = null;
				return false;
			}
		}
	});
}

/* ***********************
	Set Window events
************************/

window.onbeforeunload = function(){
	if(!jpf.window) return;
	
	var returnValue;
	if(jpf.hasDeskRun) 
		window.external.shell.RegSet(jpf.appsettings.drRegName + "/window",window.external.left + "," + window.external.top + "," + window.external.width + "," + window.external.height);
	
	if(jpf.window.onexit) returnValue = jpf.window.onexit();
	if(jpf.window.isActive()) jpf.getRoot().activeWindow = null;
	
	return returnValue;
}
if(jpf.hasDeskRun) window.external.onbeforeunload = window.onbeforeunload;

window.onunload = function(){
	if(!jpf.window) return;

	jpf.window.isExiting = true;
	jpf.window.destroy();

	//if(jpf.hasDeskRun)
		//window.external.shell.RegSet(jpf.appsettings.drRegName + "/window",window.external.left + "," + window.external.top + "," + window.external.width + "," + window.external.height);
}

window.onfocus = function(){
	if(!jpf.window) return;

	/*var k = jpf.getRoot();
	//if(k.wtimer) clearTimeout(k.wtimer);
	k.activeWindow = self;*/

	if(jpf.window.onfocus) jpf.window.onfocus();
}

window.onblur = function(){
	if(!jpf.window) return;

	//if(document.activeElement != document.body)
		//jpf.getRoot().wtimer = setTimeout("jpf.getRoot().activeWindow = null;", 100);
	
	if(jpf.window.onblur) jpf.window.onblur();
}


/* *****************************

	KEYBOARD & FOCUS HANDLING
	
******************************/

document.oncontextmenu = function(){
	if(jpf.appsettings.disableRightClick) return false;
}

document.onmousedown = function(e){
	if(!e) e = event;
	var o = jpf.findHost(jpf.hasEventSrcElement ? e.srcElement : e.target);
	if(jpf.window && jpf.window.__f.contains(o)&& !o.disabled && o.focussable) jpf.window.__focus(o);
	else if(jpf.window && jpf.window.__fObject){
		//Especially for focussing elements
		jpf.window.__fObject.blur(true);
		//me.__fObject.focus(true);
		jpf.window.__fObject = null;
	}
	
	//Hide current menu
	//if(self.jpf.currentMenu) jpf.currentMenu.hideMenu(true)
	
	//Contextmenu
	if(e.button == 2 && jpf.window.getFocussedObject())
		jpf.window.getFocussedObject().dispatchEvent("oncontextmenu", {htmlEvent : e});
	
	if(self.jpf.JMLParser && !self.jpf.appsettings.allowSelect || jpf.DragMode.mode) //Non IE
		return false
}

document.onselectstart = function(){
	if(self.jpf.JMLParser && !self.jpf.appsettings.allowSelect || jpf.DragMode.mode) //IE
		return false
}

document.onkeyup = function(e){
	if(!e) e = event;
	
	//KEYBOARD FORWARDING TO FOCUSSED OBJECT
	if(jpf.window && jpf.window.__fObject && !jpf.window.__fObject.disableKeyboard && jpf.window.__fObject.keyUpHandler && jpf.window.__fObject.keyUpHandler(e.keyCode, e.ctrlKey, e.shiftKey, e.altkey, e) == false){
		return false;
	}
}



document.onkeydown = function(e){
	if(!e) e = event;


	if(jpf.currentMenu && e.keyCode == "27") 
		jpf.currentMenu.hideMenu(true);
		
	//Contextmenu handling
	if(e.keyCode == 93 && jpf.window.getFocussedObject()){
		var pos, o = jpf.window.getFocussedObject();
		if(o.value) pos = jpf.compat.getAbsolutePosition(o.selected);
		else pos = jpf.compat.getAbsolutePosition(o.oExt);
		o.dispatchEvent("oncontextmenu", {htmlEvent : {clientX:pos[0]+10-document.documentElement.scrollLeft,clientY:pos[1]+10-document.documentElement.scrollTop}});
	}


	//HOTKEY
	if(jpf.onhotkey && jpf.onhotkey(e.keyCode, e.ctrlKey, e.shiftKey, e.altKey, e) === false){
		e.returnValue = false;e.cancelBubble = true; if(jpf.canDisableKeyCodes) try{e.keyCode = 0;}catch(e){}
		return false;
	}
	
	//HOTKEY QUICKFIX.. please fix using addeventlistener
	if(jpf.ondebugkey && jpf.ondebugkey(e.keyCode, e.ctrlKey, e.shiftKey, e.altKey, e) === false){
		e.returnValue = false;e.cancelBubble = true; if(jpf.canDisableKeyCodes) try{e.keyCode = 0;}catch(e){}
		return false;
	}
	
	
	if(!jpf.window) return;
	
	//DRAG & DROP
	if(jpf.window.dragging && e.keyCode == 27){
		if(document.body.lastHost && document.body.lastHost.dragOut) document.body.lastHost.dragOut(jpf.dragHost); 
		return jpf.DragServer.stopdrag();
	}
	
	//KEYBOARD FORWARDING TO FOCUSSED OBJECT
	if(jpf.window && jpf.window.__fObject && !jpf.window.__fObject.disableKeyboard && jpf.window.__fObject.keyHandler && jpf.window.__fObject.keyHandler(e.keyCode, e.ctrlKey, e.shiftKey, e.altkey, e) === false){
		e.returnValue = false;e.cancelBubble = true; if(jpf.canDisableKeyCodes) try{e.keyCode = 0;}catch(e){}
		return false;
	}
	
	//FOCUS HANDLING
	else if(e.keyCode == 9 && jpf.window.__f.length > 1){
		if(!jpf.currentMenu) jpf.window.moveNext(e.shiftKey);
		e.returnValue = false;
		return false;
	}
	
	//Disable backspace behaviour triggering the backbutton behaviour
	if(jpf.appsettings.disableBackspace && e.keyCode == 8){
		e.keyCode = 0;
	}
	
	//Disable space behaviour of scrolling down the page
	/*if(Application.disableSpace && e.keyCode == 32 && e.srcElement.tagName.toLowerCase() != "input"){
		e.keyCode = 0;
		e.returnValue = false;
	}*/
	
	//Disable F5 refresh behaviour
	if(jpf.appsettings.disableF5 && e.keyCode == 116){
		e.keyCode = 0;
		//return false;
	}
	
	if(e.keyCode == 27){ //or up down right left pageup pagedown home end unless body is selected
		e.returnValue = false;
	}
	
}

/*FILEHEAD(/in/Core/JMLParser.js)SIZE(26752)TIME(1213483123975)*/
/**
 * @parser
 */
jpf.JMLParser = {
	sbInit : {},
	
	stateStack : [],
	modelInit : [],

	/* ******** INIT ***********
		Initialize Application
	
		INTERFACE:
		this.Init();
	****************************/
	parse : function(x){
		jpf.status("Start parsing main application");
		jpf.Profiler.start();
		this.jml = x;
		
		//Check for children in Jml node
		if(!x.childNodes.length) throw new Error(1014, jpf.formErrorString(1014, null, "jpf.JMLParser", "Init\nMessage : Parser got JML without any children"));
		
		//First pass parsing of all JML documents
		for(var docs=[x],i=0;i<jpf.IncludeStack.length;i++) if(jpf.IncludeStack[i].nodeType) docs.push(jpf.IncludeStack[i]);
		this.parseFirstPass(docs);


		//Create window and document
		jpf.window = new jpf.WindowImplementation();
		jpf.document = new jpf.DocumentImplementation();
		jpf.window.document = jpf.document;
		jpf.window.__ActionTracker = new jpf.ActionTracker();
		
		//Main parsing pass
		jpf.JMLParser.parseChildren(x, document.body, jpf.document);//, this);
		
		//Set location based on state http://url#state
		var loc = location.href.split("?")[0].split("#")[1];
		if(loc && jpf.StateServer.locs[loc])
			jpf.StateServer.locs[loc].activate();
		
		//Activate Layout Rules [Maybe change idef to something more specific]
		if(jpf.appsettings.layout){
			jpf.setModel(jpf.appsettings.layout, {
				load : function(xmlNode){
					if(!xmlNode || this.isLoaded) return;
					
					if(!xmlNode) throw new Error(0, jpf.formErrorString(0, null, "Loading default layout", "Could not find default layout using processing instruction: '" + jpf.appsettings.layout + "'"));
					jpf.layoutServer.loadXml(xmlNode);
					this.isLoaded = true;
				},
				
				setModel : function(model, xpath){
					if(typeof model == "string") model = jpf.NameServer.get("model", model);
					model.register(this, xpath);
				}
			});
		}
		jpf.layoutServer.activateGrid();
		jpf.layoutServer.activateRules();

		//Last pass parsing
		setTimeout('jpf.JMLParser.parseLastPass();', 1);
		
		//Set init flag for subparsers
		this.inited = true;
		
		
		jpf.Profiler.end();
		jpf.status("[TIME] Total load time: " + jpf.Profiler.totalTime + "ms");
		jpf.Profiler.start(true);
	},
	
	parseFirstPass : function(xmlDocs){
		jpf.status("Parse First Pass");
		
		for(var i=0;i<xmlDocs.length;i++) this.preLoadRef(xmlDocs[i], ["teleport", "presentation", "settings", "skin", "bindings[@id]", "actions[@id]", "dragdrop[@id]"]);
		for(var i=0;i<xmlDocs.length;i++) this.preLoadRef(xmlDocs[i], ["style", "model[@id]", "smartbinding[@id]"], true);
	},
	
	preLoadRef : function(xmlNode, sel, parseLocalModel){
		/*BUG: IE document handling bugs
		- removed to see what this does
		if(jpf.isIE){
			if(xmlNode.style) return;
		}*/

		var prefix = jpf.findPrefix(xmlNode, jpf.ns.jpf); if(prefix) prefix += ":";
		var nodes = jpf.XMLDatabase.selectNodes("//" + prefix + sel.join("|//" + prefix) + (parseLocalModel ? "|" + prefix + "model" : ""), xmlNode);

		//for(var i=nodes.length-1;i>=0;i--){
		for(var i=0;i<nodes.length;i++){
			//Check if node should be rendered
			if(jpf.XMLDatabase.getInheritedAttribute(nodes[i], "render") == "runtime") continue;

			//Process Node
			if(this.handler[nodes[i][jpf.TAGNAME]]){
				jpf.status("Processing [preload] '" + nodes[i][jpf.TAGNAME] + "' node");

				this.handler[nodes[i][jpf.TAGNAME]](nodes[i]);
			}

			//Remove Node
			if(nodes[i][jpf.TAGNAME] != "presentation" && nodes[i].parentNode)
				nodes[i].parentNode.removeChild(nodes[i]);
		}
	},
	

	/**
	 * @private
	 * 
	 * @attribute grid
	 */
	reWhitespaces : /[\t\n\r]+/g,
	parseChildren : function(x, pHtmlNode, jmlParent, checkRender, noImpliedParent){
		//jpf.status("Parsing children of node '" + x.tagName + "'"); // The slow making line
		if(!jpf.Profiler.isStarted) jpf.Profiler.start();
		
		//if(!pHtmlNode) pHtmlNode = document.body;
		
		// Check for delayed rendering flag
		if(checkRender && jmlParent.hasFeature(__DELAYEDRENDER__) && jmlParent.__checkDelay(x)){
			jpf.status("Delaying rendering of children");
			
			return pHtmlNode;
		}
		if(jmlParent) jmlParent.isRendered = true;

		// Dynamicaly load JML
		if(x.getAttribute("jml")){
			jmlParent.insertJML(x.getAttribute("jml"), pHtmlNode, x, true);
			x.removeAttribute("jml");
			return;
		}
		
		if(x.namespaceURI == jpf.ns.jpf) this.lastNsPrefix = x.prefix || x.scopeName;
				
		//Loop through Nodes
		for(var oCount=0,i=0;i<x.childNodes.length;i++){
			var q = x.childNodes[i];
			if(q.nodeType == 8) continue;

			// Text nodes and comments
			if(q.nodeType != 1){
				if(!pHtmlNode) continue;
				
				if(q.nodeType == 3 || pHtmlNode.style && q.nodeType == 4){
					//if(jmlParent.name == "barTest") debugger;
					pHtmlNode.appendChild(pHtmlNode.ownerDocument.createTextNode(!jpf.hasTextNodeWhiteSpaceBug ? q.nodeValue : q.nodeValue.replace(this.reWhitespaces, " ")));
				}
				else if(q.nodeType == 4)
					pHtmlNode.appendChild(pHtmlNode.ownerDocument.createCDataSection(q.nodeValue));
				//pHtmlNode.appendChild(q);
				//jpf.XMLDatabase.htmlImport(q, pHtmlNode); 
				
				jpf.KeywordServer.addElement(q.nodeValue.replace(/^\$(.*)\$$/, "$1"), {htmlNode : pHtmlNode});
				continue;
			}
			
			//Parse node using namespace handler
			if(!this.nsHandler[q.namespaceURI || jpf.ns.xhtml]) continue; //ignore tag
			this.nsHandler[q.namespaceURI || jpf.ns.xhtml].call(this, q, pHtmlNode, jmlParent, noImpliedParent);
		}
		
		if(pHtmlNode){
			// Grid layout support
			var gridCols = x.getAttribute("grid");
			if(gridCols) jpf.layoutServer.addGrid("var o = jpf.lookup(" + jmlParent.uniqueId + ");if(o.oExt.offsetHeight) jpf.compat.gridPlace(o)", pHtmlNode);
	
			//Calculate Alignment and Anchoring
			if(jmlParent.vbox)
				jmlParent.vbox.compileAlignment();
				//jpf.layoutServer.compile(pHtmlNode);
			
			//jpf.layoutServer.activateRules(pHtmlNode);
		}
		
		return pHtmlNode;
	},
	
	addNamespaceHandler : function(xmlns, func){
		this.nsHandler[xmlns] = func;
	},
	
	//Benchmark this with ifs please
	/**
	 *
	 * @define include
	 * @addnode global:include
	 */
	nsHandler : {
		//Javeline PlatForm
		"http://www.javeline.com/2005/PlatForm" : function(x, pHtmlNode, jmlParent, noImpliedParent){
			var tagName = x[jpf.TAGNAME];
			
			// Includes
			if(tagName == "include"){
				jpf.status("Switching to include context");
				
				var xmlNode = jpf.IncludeStack[x.getAttribute("iid")];
				if(!xmlNode) return jpf.issueWarning(0, "No include file found");
				
				this.parseChildren(xmlNode, pHtmlNode, jmlParent, null, true);
			}

			// Handler
			else if(this.handler[tagName]){
				jpf.status("Processing '" + tagName + "' node");
				
				this.handler[tagName](x, noImpliedParent ? null : jmlParent);
			}
			
			//XForms
			else if(jmlParent && (jmlParent.hasFeature(__XFORMS__) && this.xforms[tagName] || jmlParent.setCaption && this.xforms[tagName] > 2)){
				switch(this.xforms[tagName]){
					case 1: //Set Event
						if(x.getAttribute("ev:event")){
							jmlParent.dispatchEvent(x.getAttribute("ev:event"), function(){
								this.executeXFormStack(x);
							});
						}
						else jmlParent.executeXFormStack(x);
					break;
					case 2: //Parse in Element
						jmlParent.parseXFormTag(x);
					break;
					case 3: //Label
						if(jmlParent.setCaption){
							jmlParent.setCaption(x.firstChild.nodeValue); //or replace it or something...
							break;
						}
					
						//Create element using this function
						var oLabel = this.nsHandler[jpf.ns.jpf].call(this, x, jmlParent.oExt.parentNode, jmlParent.parentNode);
						
						//Set Dom stuff
						oLabel.parentNode = jmlParent.parentNode;
						for(var i=0;i<jmlParent.parentNode.childNodes.length;i++){
							if(jmlParent.parentNode.childNodes[i] == jmlParent){
								jmlParent.parentNode.childNodes[i] = oLabel;
							}
							else if(jmlParent.parentNode.childNodes[i] == oLabel){
								jmlParent.parentNode.childNodes[i] = jmlParent;
								break;
							}
						}
						
						//Insert element to parentHtmlNode of jmlParent and before the node
						oLabel.oExt.parentNode.insertBefore(oLabel.oExt, jmlParent.oExt);
						
						//Use for
						oLabel.setFor(jmlParent);
					break;
				}
			}
			
			//JML Components
			else if(pHtmlNode){
				if(!jpf[tagName] || typeof jpf[tagName] != "function") throw new Error(1017, jpf.formErrorString(1017, null, "Initialization", "Could not find Class Definition '" + tagName + "'.", x));
				if(!jpf[tagName]) throw new Error(0, "Could not find class " + tagName);
				var objName = tagName;
				
				//Check if Class is loaded in current Window
				//if(!self[tagName]) main.window.jpf.importClass(main.window[tagName], false, window);
		
				if(tagName == "select1" && x.getAttribute("appearance") == "minimal"){
					objName = "dropdown";
				}
		
				//Create Object en Reference
				var o = new jpf[objName](pHtmlNode, tagName, x);
				if(x.getAttribute("id")) jpf.setReference(x.getAttribute("id"), o);
	
				//Process JML
				if(o.loadJML) o.loadJML(x, jmlParent);
			}
			
			return o;
		}
	
		//XML Schema Definition
		,"http://www.w3.org/2001/XMLSchema" : function(x, pHtmlNode, jmlParent, noImpliedParent){
			var type = jpf.XSDParser.parse(x);
			if(type && jmlParent) jmlParent.setProperty("datatype", type);
		}
	
		//XHTML
		,"http://www.w3.org/1999/xhtml" :  function(x, pHtmlNode, jmlParent, noImpliedParent){
			var parseWhole = x.tagName.match(/table|object|embed/i) ? true : false;
			
			// Move all this to the respective browser libs in a wrapper function
			if(x.tagName == "option"){
				var o = pHtmlNode.appendChild(pHtmlNode.ownerDocument.createElement("option"));
				if(x.getAttribute("value")) o.setAttribute("value", x.getAttribute("value"));
			}
			else if(jpf.isIE){
				var o = x.ownerDocument == pHtmlNode.ownerDocument ? pHtmlNode.appendChild(x.cloneNode(false)) : jpf.XMLDatabase.htmlImport(x.cloneNode(parseWhole), pHtmlNode);
			}
			
			//SAFARI importing cloned node kills safari.. temp workaround in place
			else if(jpf.isSafari){
				//o = pHtmlNode.appendChild(pHtmlNode.ownerDocument.importNode(x));//.cloneNode(false)
				var o = x.ownerDocument == pHtmlNode.ownerDocument ? pHtmlNode.appendChild(x) : jpf.XMLDatabase.htmlImport(x.cloneNode(parseWhole), pHtmlNode);
			}
			else{
				var o = x.ownerDocument == pHtmlNode.ownerDocument ? pHtmlNode.appendChild(x.cloneNode(false)) : jpf.XMLDatabase.htmlImport(x.cloneNode(false), pHtmlNode);
				//o = pHtmlNode.appendChild(pHtmlNode.ownerDocument.importNode(x.cloneNode(false), false));	
			}
			
			//Check attributes for j:left etc and j:repeat-nodeset
			var tagName, prefix = this.lastNsPrefix || jpf.findPrefix(x.parentNode, jpf.ns.jpf) || "";
			if(prefix){
				if(!jpf.supportNamespaces) x.ownerDocument.setProperty("SelectionNamespaces", "xmlns:" + prefix + "='" + jpf.ns.jpf + "'");
				prefix += ":";
			}
			
			var done = {}, aNodes = x.selectNodes("@" + prefix + "*");
			for(var i=0;i<aNodes.length;i++){
				tagName = aNodes[i][jpf.TAGNAME];
				
				if(tagName.match(/^(left|top|right|bottom|width|height|align)$/)){
					if(done["position"]) continue;
					done["position"] = true;
					//Create positioning object - remove attributes when done
					var html = new jpf.HtmlWrapper(pHtmlNode, o, prefix);
					
					if(x.getAttribute(prefix + "align") || x.getAttribute(prefix + "align-position")){
						html.enableAlignment()
					}
					else if(x.getAttribute(prefix + "width") || x.getAttribute(prefix + "height") || x.getAttribute(prefix + "left") || x.getAttribute(prefix + "top") || x.getAttribute(prefix + "right") || x.getAttribute(prefix + "bottom") || x.getAttribute(prefix + "anchoring") == "true"){
						html.getDiff();
						html.setHorizontal(x.getAttribute(prefix + "left"), x.getAttribute(prefix + "right"), x.getAttribute(prefix + "width"));
						html.setVertical(x.getAttribute(prefix + "top"), x.getAttribute(prefix + "bottom"), x.getAttribute(prefix + "height"));
					}

					//return o;
				}
				/* XForms support
					- repeat-model 
					- repeat-bind 
					- repeat-nodeset 
					- repeat-startindex 
					- repeat-number 
				*/
				else if(tagName.match(/^repeat-/)){
					if(done["repeat"]) continue;
					done["repeat"] = true;
					//Create repeat object - remove attributes when done
					
				}
			}
			
			if(jpf.canUseInnerHtmlWithTables || !parseWhole)
				this.parseChildren(x, o, jmlParent);
			else{
				jpf.issueWarning(0, "Not parsing children of table, ignoring all Javeline Platform Elements.");
			}
			
			
			return o;
		}
	},
	
	xforms : {
		"label" : 3, //any non-has-children node
		
		"action" : 1, //stacked processing
		"dispatch" : 1,
		"rebuild" : 1,
		"recalculate" : 1,
		"revalidate" : 1,
		"refresh" : 1,
		"setfocus" : 1,
		"load" : 1,
		"setvalue" : 1,
		"send" : 1,
		"reset" : 1,
		"message" : 1,
		"insert" : 1,
		"delete" : 1,
		
		"filename" : 2, //widget specific processing
		"mediatype" : 2,
		"itemset" : 2,
		"item" : 2,
		"choices" : 2,
		"copy" : 2,
		"help" : 2,
		"hint" : 2
	},
	
			
	handler : {
		/**
		 * @define script
		 * @addnode global:script, anyjml:script
		 */
		"script" : function(q){
			//if(IS_SAFARI) return;
			if(q.getAttribute("src")){
				//temp solution
				if(jpf.isOpera) setTimeout(function(){jpf.window.loadCodeFile(jpf.hostPath + q.getAttribute("src"));},1000);
				else jpf.window.loadCodeFile(jpf.hostPath + q.getAttribute("src"));
			}
			else if(q.firstChild){
				var scode = q.firstChild.nodeValue;// + ";\nvar __LoadedScript = true;"
				if(jpf.hasExecScript) window.execScript(scode); 
				//else if(jpf.isGecko)
				//	document.body.insertAdjacentHTML("beforeend", "<script>" + scode + "</script>");
				else eval(scode);
					
				//if(!__LoadedScript)
				//	throw new Error(0, jpf.formErrorString(0, null, "Inserting Code Block", "An Error has occurred inserting the javascript code block", q));
			}
		},
		
		/**
		 * @define style
		 * @addnode global:style, anyjml:style
		 */
		"style" : function(q){
			jpf.importCssString(document, q.firstChild.nodeValue);
		},
		
		/**
		 * @define comment
		 * @addnode anyjml:comment
		 */
		"comment" : function (q){
			//do nothing
		},
		
		/**
		 * @define presentation
		 * @addnode global:presentation, anyjml:presentation
		 */
		"presentation" : function(q){
			var name = "skin" + Math.round(Math.random()*100000);
			q.parentNode.setAttribute("skin", name);
			jpf.PresentationServer.skins[name] = {name:name,templates:{}}
			var t = q.parentNode[jpf.TAGNAME];
			var skin = q.ownerDocument.createElement("skin"); skin.appendChild(q);
			jpf.PresentationServer.skins[name].templates[t] = skin;
		},
		
		/**
		 * @define skin
		 * @addnode global:skin, anyjml:skin
		 */
		"skin" : function(q, jmlParent){
			if(jmlParent){
				var name = "skin" + Math.round(Math.random()*100000);
				q.parentNode.setAttribute("skin", name);
				jpf.PresentationServer.skins[name] = {name:name,templates:{}}
				jpf.PresentationServer.skins[name].templates[q.parentNode[jpf.TAGNAME]] = q;
			}
			else if(q.childNodes.length){
				jpf.PresentationServer.Init(q);
			}
			else{
				var path = q.getAttribute("src") ? 
					jpf.getAbsolutePath(jpf.hostPath, q.getAttribute("src")) : 
					jpf.getAbsolutePath(jpf.hostPath, q.getAttribute("name")) + "/index.xml";
				
				jpf.loadJMLInclude(q, new jpf.http(), true, path);
			}
		},
		
		
		"model" : function(q, jmlParent){
			if(jmlParent && !jmlParent.hasFeature(__DATABINDING__)) jmlParent = null;
			
			//Model
			var modelId, m = new jpf.Model().register(jmlParent).loadJML(q);
			if(jmlParent){
				modelId = "model" + this.uniqueId;
				jmlParent.jml.setAttribute("model", modelId);
			}
			else modelId = q.getAttribute("id")
			
			if(!jpf.JMLParser.globalModel) jpf.JMLParser.globalModel = m;
			else jpf.JMLParser.globalModel = -1;
			
			return modelId ? jpf.setReference(modelId, jpf.NameServer.register("model", modelId, m)) : m;
		},
		
		"smartbinding" : function(q, jmlParent){
			var bc = new jpf.SmartBinding(q.getAttribute("id"), q);
			if(q.getAttribute("id")) jpf.NameServer.register("smartbinding", q.getAttribute("id"), bc)
			if(jmlParent && jmlParent.hasFeature(__DATABINDING__)) jpf.JMLParser.addToSbStack(jmlParent.uniqueId, bc);
		},
		//getFromSbStack
		
		/**
		 * @define ref
		 * @addnode smartbinding:ref
		 */
		"ref" : function(q, jmlParent){
			var bc = jpf.JMLParser.getFromSbStack(jmlParent.uniqueId) || jpf.JMLParser.addToSbStack(jmlParent.uniqueId, new jpf.SmartBinding());
			bc.addBindRule(q, jmlParent);
		}, //not referencable
		
		/**
		 * @addnode global:bindings, smartbinding:bindings
		 */
		"bindings" : function(q, jmlParent){
			var rules = jpf.getRules(q);
			if(q.getAttribute("id")) jpf.NameServer.register("bindings", q.getAttribute("id"), rules);
			if(jmlParent && jmlParent.hasFeature(__DATABINDING__)){
				var bc = jpf.JMLParser.getFromSbStack(jmlParent.uniqueId) || jpf.JMLParser.addToSbStack(jmlParent.uniqueId, new jpf.SmartBinding());
				bc.addBindings(rules, q);
			}
		},
		
		/**
		 * @define action
		 * @addnode smartbinding:action
		 */
		"action" : function(q, jmlParent){
			var bc = jpf.JMLParser.getFromSbStack(jmlParent.uniqueId) || jpf.JMLParser.addToSbStack(jmlParent.uniqueId, new jpf.SmartBinding());
			bc.addActionRule(q, jmlParent);
		}, //not referencable
		
		/**
		 * @addnode global:actions, smartbinding:actions
		 */
		"actions" : function(q, jmlParent){
			var rules = jpf.getRules(q);
			if(q.getAttribute("id")) jpf.NameServer.register("actions", q.getAttribute("id"), rules);
			if(jmlParent && jmlParent.hasFeature(__DATABINDING__)){
				var bc = jpf.JMLParser.getFromSbStack(jmlParent.uniqueId) || jpf.JMLParser.addToSbStack(jmlParent.uniqueId, new jpf.SmartBinding());
				bc.addActions(rules, q);
			}
		},
		
		"actiontracker" : function(q, jmlParent){
			var at;
			
			if(q.getAttribute("id")) 
				at = jpf.setReference(q.getAttribute("id"), jpf.NameServer.register("actiontracker", q.getAttribute("id"), new jpf.ActionTracker()));
			if(jmlParent) jmlParent.__ActionTracker = at || new jpf.ActionTracker(jmlParent);
			
			if(!q.getAttribute("id") && !jmlParent){
				throw new Error(1016, jpf.formErrorString(1016, null, "ActionTracker", "Could not create ActionTracker without an id specified"));
			}
		},
		
		/**
		 * @define contextmenu 
		 * @addnode global:contextmenu, smartbinding:contextmenu
		 */
		"contextmenu" : function(q, jmlParent){
			if(!jmlParent) return; //not supported
			
			if(!jmlParent.contextmenus) jmlParent.contextmenus = [];
			jmlParent.contextmenus.push(q);
		},

		"allow-drag" : function(q, jmlParent){
			var bc = jpf.JMLParser.getFromSbStack(jmlParent.uniqueId) || jpf.JMLParser.addToSbStack(jmlParent.uniqueId, new jpf.SmartBinding());
			bc.addDragRule(q, jmlParent);
		},  //not referencable
		
		"allow-drop" : function(q, jmlParent){
			var bc = jpf.JMLParser.getFromSbStack(jmlParent.uniqueId) || jpf.JMLParser.addToSbStack(jmlParent.uniqueId, new jpf.SmartBinding());
			bc.addDropRule(q, jmlParent);
		},  //not referencable
		
		/**
		 * @addnode global:dragdrop[@id], smartbinding:dragdrop
		 */
		"dragdrop" : function(q, jmlParent){
			var rules = jpf.getRules(q);
			if(q.getAttribute("id")) jpf.NameServer.register("dragdrop", q.getAttribute("id"), rules);
			if(jmlParent && jmlParent.hasFeature(__DATABINDING__)){
				var bc = jpf.JMLParser.getFromSbStack(jmlParent.uniqueId) || jpf.JMLParser.addToSbStack(jmlParent.uniqueId, new jpf.SmartBinding());
				bc.addDragDrop(rules, q);
			}
		},
			
		"socket" : function(q){
			var o = new Socket();
			jpf.setReference(x.getAttribute("id"), o);
			o.load(q);
		},

		"poll" : function(q){
			jpf.setReference(x.getAttribute("id"), new jpf.poll().load(q));
		},
		
		//problem:
		"teleport" : function(q){
			//Initialize Communication Component
			//jpf.setReference(x.getAttribute("id"), new jpf.BaseComm(x));
			jpf.Teleport.loadJML(q);
		},
		
		
		/**
		 * @define remotesmartbindings
		 */
		"remotesmartbindings" : function(q){
			//Remote Smart Bindings
			jpf.XMLDatabase.loadRDB(q);
		},
		
		/**
		 * @define appsettings
		 */
		"appsettings" : function(q, jmlParent){
			this.foundSettings = true;
			this.lastSettings = q;
			
			jpf.appsettings.loadJML(q);
		}
		
		/**
		 * @define deskrun
		 */
		, "deskrun" : function(q){
			if(!jpf.hasDeskRun) return;
			jpf.window.loadJML(q);
		}
		
		, "window" : function(q){
			jpf.windowManager.addForm(q);
		},
		
		"loader" : function(q){
			//ignore, handled elsewhere
		}
	},
	
	getSmartBinding : function(id){return jpf.NameServer.get("smartbinding", id)},

	getActionTracker : function(id){
		var at = jpf.NameServer.get("actiontracker", id);
		if(at) return at;
		if(self[id]) return self[id].getActionTracker();
	},
	
	replaceNode : function(newNode, oldNode){
		var nodes = oldNode.childNodes;
		for(var i=nodes.length-1;i>=0;i--) 
			newNode.insertBefore(nodes[i], newNode.firstChild);
			
		newNode.onresize = oldNode.onresize;
		
		return newNode;
	},
	
	/* ******** parseLastPass ***********
		Process Databinding Rules of all objects set
	
		INTERFACE:
		this.parseLastPass();
	****************************/
	parseLastPass : function(){
		
		
		jpf.status("Processing SmartBinding hooks");
		
		/*
			All these component dependant things might
			be suited better to be in a component generation
			called event
		*/
		
		while(this.hasNewSbStackItems){
			var sbInit = this.sbInit; this.sbInit = {};
			this.hasNewSbStackItems = false;
			
			//Initialize Databinding for all GUI Elements in Form
			for(var uniqueId in sbInit){
				if(parseInt(uniqueId) != uniqueId) continue;
	
				//Retrieve Jml Node
				var jNode = jpf.lookup(uniqueId);
	
				//Set Main smartbinding
				if(sbInit[uniqueId][0]) jNode.setSmartBinding(sbInit[uniqueId][0]);
				
				//Set selection smartbinding if any
				if(sbInit[uniqueId][1]) jNode.setSelectionSmartBinding(sbInit[uniqueId][1]);
			}
		}
		
		// Initialize state bindings
		for(var i=0;i<this.stateStack.length;i++){
			if(this.stateStack[i][1] == "visible" && (jpf.isFalse(this.stateStack[i][2]) || jpf.isTrue(this.stateStack[i][2]))) continue;
			this.stateStack[i][0].setDynamicProperty(this.stateStack[i][1], this.stateStack[i][2]);
		}

		//Initialize Models
		while(this.hasNewModelStackItems){
			var jmlNode, modelInit = this.modelInit; this.modelInit = {};
			this.hasNewModelStackItems = false;
			
			for(var data,i=0;i<modelInit.length;i++){
				data = modelInit[i][1];
				data[0] = data[0].substr(1);
				
				jmlNode = eval(data[0]);
				if(jmlNode.connect) jmlNode.connect(modelInit[i][0], null, data[2], data[1] || "select");
				else jmlNode.setModel(new jpf.Model().loadFrom(data.join(":")));
			}
		}
		
		//Call the onload event
		if(jpf.onload){
			jpf.onload();
			jpf.onload = null;
		}
		
		var models = jpf.NameServer.getAll("model");
		for(var i=0;i<models.length;i++) models[i].dispatchEvent("xforms-ready");
		
		if(!this.loaded){
			if(jpf.window.useDeskRun) jpf.window.deskrun.Show();
			
			// Set the default selected element
			jpf.window.moveNext();
			
			this.loaded = true;
		}

		this.sbInit = {};
		this.modelInit = [];
		this.stateStack = [];
		// END OF ENTIRE APPLICATION STARTUP
		
		jpf.status("Initialization finished");
		jpf.Profiler.end();
		jpf.status("[TIME] Total time for SmartBindings: " + jpf.Profiler.totalTime + "ms");
	}
	
	
	, addToSbStack : function(uniqueId, sNode, nr){
		this.hasNewSbStackItems = true;
		if(!this.sbInit[uniqueId]) this.sbInit[uniqueId] = [];
		this.sbInit[uniqueId][nr||0] = sNode;
		return sNode;
	},
	
	getFromSbStack : function(uniqueId, nr){
		return this.sbInit[uniqueId] ? this.sbInit[uniqueId][nr || 0] : null;
	},
	
	stackHasBindings : function(uniqueId){
		return this.sbInit[uniqueId] && this.sbInit[uniqueId][0] && this.sbInit[uniqueId][0].bindings;
	},
	
	modelInit : [],
	addToModelStack : function(o, data){
		this.hasNewModelStackItems = true;
		this.modelInit.push([o, data]);
	}
}


jpf.Init.run('jpf.JMLParser');
/*FILEHEAD(/in/Core/Highlighter/shCore.uncompressed.js)SIZE(19068)TIME(1166375348945)*/

/**
 * Code Syntax Highlighter.
 * Version 1.3.0
 * Copyright (C) 2004 Alex Gorbatchev.
 * http://www.dreamprojections.com/syntaxhighlighter/
 * 
 * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General 
 * Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) 
 * any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied 
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 
 * details.
 *
 * You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to 
 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
 */

//
// create namespaces
//
var dp = {
	sh :
	{
		Toolbar : {},
		Utils	: {},
		RegexLib: {},
		Brushes	: {},
		Strings : {},
		Version : '1.4.1'
	}
};

dp.sh.Strings = {
	AboutDialog : '<html><head><title>About...</title></head><body class="dp-about"><table cellspacing="0"><tr><td class="copy"><p class="title">dp.SyntaxHighlighter</div><div class="para">Version: {V}</p><p><a href="http://www.dreamprojections.com/syntaxhighlighter/?ref=about" target="_blank">http://www.dreamprojections.com/SyntaxHighlighter</a></p>&copy;2004-2005 Alex Gorbatchev. All right reserved.</td></tr><tr><td class="footer"><input type="button" class="close" value="OK" onClick="window.close()"/></td></tr></table></body></html>'
};

dp.SyntaxHighlighter = dp.sh;

//
// Toolbar functions
//

dp.sh.Toolbar.Commands = {
	ExpandSource: {
		label: '+ expand source',
		check: function(highlighter) { return highlighter.collapse; },
		func: function(sender, highlighter)
		{
			sender.parentNode.removeChild(sender);
			highlighter.div.className = highlighter.div.className.replace('collapsed', '');
		}
	},
	
	// opens a new windows and puts the original unformatted source code inside.
	ViewSource: {
		label: 'view plain',
		func: function(sender, highlighter)
		{
			var code = highlighter.originalCode.replace(/</g, '&lt;');
			var wnd = window.open('', '_blank', 'width=750, height=400, location=0, resizable=1, menubar=0, scrollbars=1');
			wnd.document.write('<textarea style="width:99%;height:99%">' + code + '</textarea>');
			wnd.document.close();
		}
	},
	
	// copies the original source code in to the clipboard (IE only)
	CopyToClipboard: {
		label: 'copy to clipboard',
		check: function() { return window.clipboardData != null; },
		func: function(sender, highlighter)
		{
			window.clipboardData.setData('text', highlighter.originalCode);
			alert('The code is in your clipboard now');
		}
	},
	
	// creates an invisible iframe, puts the original source code inside and prints it
	PrintSource: {
		label: 'print',
		func: function(sender, highlighter)
		{
			var iframe = document.createElement('IFRAME');
			var doc = null;

			// this hides the iframe
			iframe.style.cssText = 'position:absolute;width:0px;height:0px;left:-500px;top:-500px;';
			
			document.body.appendChild(iframe);
			doc = iframe.contentWindow.document;

			dp.sh.Utils.CopyStyles(doc, window.document);
			doc.write('<div class="' + highlighter.div.className.replace('collapsed', '') + ' printing">' + highlighter.div.innerHTML + '</div>');
			doc.close();

			iframe.contentWindow.focus();
			iframe.contentWindow.print();
			
			alert('Printing...');
			
			document.body.removeChild(iframe);
		}
	},
	
	About: {
		label: '?',
		func: function(highlighter)
		{
			var wnd	= window.open('', '_blank', 'dialog,width=300,height=150,scrollbars=0');
			var doc	= wnd.document;

			dp.sh.Utils.CopyStyles(doc, window.document);
			
			doc.write(dp.sh.Strings.AboutDialog.replace('{V}', dp.sh.Version));
			doc.close();
			wnd.focus();
		}
	}
};

// creates a <div /> with all toolbar links
dp.sh.Toolbar.Create = function(highlighter)
{
	var div = document.createElement('DIV');
	
	div.className = 'tools';
	
	for(var name in dp.sh.Toolbar.Commands)
	{
		var cmd = dp.sh.Toolbar.Commands[name];
		
		if(cmd.check != null && !cmd.check(highlighter))
			continue;
		
		div.innerHTML += '<a href="#" onclick="dp.sh.Toolbar.Command(\'' + name + '\',this);return false;">' + cmd.label + '</a>';
	}
	
	return div;
}

// executes toolbar command by name
dp.sh.Toolbar.Command = function(name, sender)
{
	var n = sender;
	
	while(n != null && n.className.indexOf('dp-highlighter') == -1)
		n = n.parentNode;
	
	if(n != null)
		dp.sh.Toolbar.Commands[name].func(sender, n.highlighter);
}

// copies all <link rel="stylesheet" /> from 'target' window to 'dest'
dp.sh.Utils.CopyStyles = function(destDoc, sourceDoc)
{
	var links = sourceDoc.getElementsByTagName('link');

	for(var i = 0; i < links.length; i++)
		if(links[i].rel.toLowerCase() == 'stylesheet')
			destDoc.write('<link type="text/css" rel="stylesheet" href="' + links[i].href + '"></link>');
}

//
// Common reusable regular expressions
//
dp.sh.RegexLib = {
	MultiLineCComments : new RegExp('/\\*[\\s\\S]*?\\*/', 'gm'),
	SingleLineCComments : new RegExp('//.*$', 'gm'),
	SingleLinePerlComments : new RegExp('#.*$', 'gm'),
	DoubleQuotedString : new RegExp('"(?:\\.|(\\\\\\")|[^\\""])*"','g'),
	SingleQuotedString : new RegExp("'(?:\\.|(\\\\\\')|[^\\''])*'", 'g')
};

//
// Match object
//
dp.sh.Match = function(value, index, css)
{
	this.value = value;
	this.index = index;
	this.length = value.length;
	this.css = css;
}

//
// Highlighter object
//
dp.sh.Highlighter = function()
{
	this.noGutter = false;
	this.addControls = true;
	this.collapse = false;
	this.tabsToSpaces = true;
	this.wrapColumn = 80;
	this.showColumns = true;
}

// static callback for the match sorting
dp.sh.Highlighter.SortCallback = function(m1, m2)
{
	// sort matches by index first
	if(m1.index < m2.index)
		return -1;
	else if(m1.index > m2.index)
		return 1;
	else
	{
		// if index is the same, sort by length
		if(m1.length < m2.length)
			return -1;
		else if(m1.length > m2.length)
			return 1;
	}
	return 0;
}

dp.sh.Highlighter.prototype.CreateElement = function(name)
{
	var result = document.createElement(name);
	result.highlighter = this;
	return result;
}

// gets a list of all matches for a given regular expression
dp.sh.Highlighter.prototype.GetMatches = function(regex, css)
{
	var index = 0;
	var match = null;

	while((match = regex.exec(this.code)) != null)
		this.matches[this.matches.length] = new dp.sh.Match(match[0], match.index, css);
}

dp.sh.Highlighter.prototype.AddBit = function(str, css)
{
	if(str == null || str.length == 0)
		return;

	var span = this.CreateElement('SPAN');
	
	str = str.replace(/&/g, '&amp;');
	str = str.replace(/ /g, '&nbsp;');
	str = str.replace(/</g, '&lt;');
	str = str.replace(/\n/gm, '&nbsp;<br>');

	// when adding a piece of code, check to see if it has line breaks in it 
	// and if it does, wrap individual line breaks with span tags
	if(css != null)
	{
		var regex = new RegExp('<br>', 'gi');
		
		if(regex.test(str))
		{
			var lines = str.split('&nbsp;<br>');
			
			str = '';
			
			for(var i = 0; i < lines.length; i++)
			{
				span = this.CreateElement('SPAN');
				span.className = css;
				span.innerHTML = lines[i];
				
				this.div.appendChild(span);
				
				// don't add a <BR> for the last line
				if(i + 1 < lines.length)
					this.div.appendChild(this.CreateElement('BR'));
			}
		}
		else
		{
			span.className = css;
			span.innerHTML = str;
			this.div.appendChild(span);
		}
	}
	else
	{
		span.innerHTML = str;
		this.div.appendChild(span);
	}
}

// checks if one match is inside any other match
dp.sh.Highlighter.prototype.IsInside = function(match)
{
	if(match == null || match.length == 0)
		return false;
	
	for(var i = 0; i < this.matches.length; i++)
	{
		var c = this.matches[i];
		
		if(c == null)
			continue;

		if((match.index > c.index) && (match.index < c.index + c.length))
			return true;
	}
	
	return false;
}

dp.sh.Highlighter.prototype.ProcessRegexList = function()
{
	for(var i = 0; i < this.regexList.length; i++)
		this.GetMatches(this.regexList[i].regex, this.regexList[i].css);
}

dp.sh.Highlighter.prototype.ProcessSmartTabs = function(code)
{
	var lines	= code.split('\n');
	var result	= '';
	var tabSize	= 4;
	var tab		= '\t';

	// This function inserts specified amount of spaces in the string
	// where a tab is while removing that given tab. 
	function InsertSpaces(line, pos, count)
	{
		var left	= line.substr(0, pos);
		var right	= line.substr(pos + 1, line.length);	// pos + 1 will get rid of the tab
		var spaces	= '';
		
		for(var i = 0; i < count; i++)
			spaces += ' ';
		
		return left + spaces + right;
	}

	// This function process one line for 'smart tabs'
	function ProcessLine(line, tabSize)
	{
		if(line.indexOf(tab) == -1)
			return line;

		var pos = 0;

		while((pos = line.indexOf(tab)) != -1)
		{
			// This is pretty much all there is to the 'smart tabs' logic.
			// Based on the position within the line and size of a tab, 
			// calculate the amount of spaces we need to insert.
			var spaces = tabSize - pos % tabSize;
			
			line = InsertSpaces(line, pos, spaces);
		}
		
		return line;
	}

	// Go through all the lines and do the 'smart tabs' magic.
	for(var i = 0; i < lines.length; i++)
		result += ProcessLine(lines[i], tabSize) + '\n';
	
	return result;
}

dp.sh.Highlighter.prototype.SwitchToList = function()
{
	// thanks to Lachlan Donald from SitePoint.com for this <br/> tag fix.
	var html = this.div.innerHTML.replace(/<(br)\/?>/gi, '\n');
	var lines = html.split('\n');
	
	if(this.addControls == true)
		this.bar.appendChild(dp.sh.Toolbar.Create(this));

	// add columns ruler
	if(this.showColumns)
	{
		var div = this.CreateElement('div');
		var columns = this.CreateElement('div');
		var showEvery = 10;
		var i = 1;
		
		while(i <= 150)
		{
			if(i % showEvery == 0)
			{
				div.innerHTML += i;
				i += (i + '').length;
			}
			else
			{
				div.innerHTML += '&middot;';
				i++;
			}
		}
		
		columns.className = 'columns';
		columns.appendChild(div);
		this.bar.appendChild(columns);
	}

	for(var i = 0, lineIndex = this.firstLine; i < lines.length - 1; i++, lineIndex++)
	{
		var li = this.CreateElement('LI');
		var span = this.CreateElement('SPAN');
		
		// uses .line1 and .line2 css styles for alternating lines
		li.className = (i % 2 == 0) ? 'alt' : '';
		span.innerHTML = lines[i] + '&nbsp;';

		li.appendChild(span);
		this.ol.appendChild(li);
	}
	
	this.div.innerHTML	= '';
}

dp.sh.Highlighter.prototype.Highlight = function(code)
{
	function Trim(str)
	{
		return str.replace(/^\s*(.*?)[\s\n]*$/g, '$1');
	}
	
	function Chop(str)
	{
		return str.replace(/\n*$/, '').replace(/^\n*/, '');
	}

	function Unindent(str)
	{
		var lines = str.split('\n');
		var indents = new Array();
		var regex = new RegExp('^\\s*', 'g');
		var min = 1000;

		// go through every line and check for common number of indents
		for(var i = 0; i < lines.length && min > 0; i++)
		{
			if(Trim(lines[i]).length == 0)
				continue;
				
			var matches = regex.exec(lines[i]);

			if(matches != null && matches.length > 0)
				min = Math.min(matches[0].length, min);
		}

		// trim minimum common number of white space from the begining of every line
		if(min > 0)
			for(var i = 0; i < lines.length; i++)
				lines[i] = lines[i].substr(min);

		return lines.join('\n');
	}
	
	// This function returns a portions of the string from pos1 to pos2 inclusive
	function Copy(string, pos1, pos2)
	{
		return string.substr(pos1, pos2 - pos1);
	}

	var pos	= 0;
	
	this.originalCode = code;
	this.code = Chop(Unindent(code));
	this.div = this.CreateElement('DIV');
	this.bar = this.CreateElement('DIV');
	this.ol = this.CreateElement('OL');
	this.matches = new Array();

	this.div.className = 'dp-highlighter';
	this.div.highlighter = this;
	
	this.bar.className = 'bar';
	
	// set the first line
	this.ol.start = this.firstLine;

	if(this.CssClass != null)
		this.ol.className = this.CssClass;

	if(this.collapse)
		this.div.className += ' collapsed';
	
	if(this.noGutter)
		this.div.className += ' nogutter';

	// replace tabs with spaces
	if(this.tabsToSpaces == true)
		this.code = this.ProcessSmartTabs(this.code);

	this.ProcessRegexList();	

	// if no matches found, add entire code as plain text
	if(this.matches.length == 0)
	{
		this.AddBit(this.code, null);
		this.SwitchToList();
		this.div.appendChild(this.ol);
		return;
	}

	// sort the matches
	this.matches = this.matches.sort(dp.sh.Highlighter.SortCallback);

	// The following loop checks to see if any of the matches are inside
	// of other matches. This process would get rid of highligted strings
	// inside comments, keywords inside strings and so on.
	for(var i = 0; i < this.matches.length; i++)
		if(this.IsInside(this.matches[i]))
			this.matches[i] = null;

	// Finally, go through the final list of matches and pull the all
	// together adding everything in between that isn't a match.
	for(var i = 0; i < this.matches.length; i++)
	{
		var match = this.matches[i];

		if(match == null || match.length == 0)
			continue;

		this.AddBit(Copy(this.code, pos, match.index), null);
		this.AddBit(match.value, match.css);

		pos = match.index + match.length;
	}
	
	this.AddBit(this.code.substr(pos), null);

	this.SwitchToList();
	//this.div.appendChild(this.bar);
	this.div.appendChild(this.ol);
}

dp.sh.Highlighter.prototype.GetKeywords = function(str) 
{
	return '\\b' + str.replace(/ /g, '\\b|\\b') + '\\b';
}

// highlightes all elements identified by name and gets source code from specified property
dp.sh.HighlightAll = function(name, showGutter /* optional */, showControls /* optional */, collapseAll /* optional */, firstLine /* optional */, showColumns /* optional */)
{
	function FindValue()
	{
		var a = arguments;
		
		for(var i = 0; i < a.length; i++)
		{
			if(a[i] == null)
				continue;
				
			if(typeof(a[i]) == 'string' && a[i] != '')
				return a[i] + '';
		
			if(typeof(a[i]) == 'object' && a[i].value != '')
				return a[i].value + '';
		}
		
		return null;
	}
	
	function IsOptionSet(value, list)
	{
		for(var i = 0; i < list.length; i++)
			if(list[i] == value)
				return true;
		
		return false;
	}
	
	function GetOptionValue(name, list, defaultValue)
	{
		var regex = new RegExp('^' + name + '\\[(\\w+)\\]$', 'gi');
		var matches = null;

		for(var i = 0; i < list.length; i++)
			if((matches = regex.exec(list[i])) != null)
				return matches[1];
		
		return defaultValue;
	}

	var elements = document.getElementsByName(name);
	var highlighter = null;
	var registered = new Object();
	var propertyName = 'value';
	
	// if no code blocks found, leave
	if(elements == null)
		return;

	// register all brushes
	for(var brush in dp.sh.Brushes)
	{
		var aliases = dp.sh.Brushes[brush].Aliases;

		if(aliases == null)
			continue;
		
		for(var i = 0; i < aliases.length; i++)
			registered[aliases[i]] = brush;
	}

	for(var i = 0; i < elements.length; i++)
	{
		var element = elements[i];
		var options = FindValue(
				element.attributes['class'], element.className, 
				element.attributes['language'], element.language
				);
		var language = '';
		
		if(options == null)
			continue;
		
		options = options.split(':');
		
		language = options[0].toLowerCase();

		if(registered[language] == null)
			continue;
		
		// instantiate a brush
		highlighter = new dp.sh.Brushes[registered[language]]();
		
		// hide the original element
		element.style.display = 'none';

		highlighter.noGutter = (showGutter == null) ? IsOptionSet('nogutter', options) : !showGutter;
		highlighter.addControls = (showControls == null) ? !IsOptionSet('nocontrols', options) : showControls;
		highlighter.collapse = (collapseAll == null) ? IsOptionSet('collapse', options) : collapseAll;
		highlighter.showColumns = (showColumns == null) ? IsOptionSet('showcolumns', options) : showColumns;
		
		// first line idea comes from Andrew Collington, thanks!
		highlighter.firstLine = (firstLine == null) ? parseInt(GetOptionValue('firstline', options, 1)) : firstLine;

		highlighter.Highlight(element[propertyName]);

		element.parentNode.insertBefore(highlighter.div, element);
	}	
}

// highlightes all elements identified by name and gets source code from specified property
dp.sh.HighlightString = function(strCode, showGutter /* optional */, showControls /* optional */, collapseAll /* optional */, firstLine /* optional */, showColumns /* optional */)
{
	function FindValue()
	{
		var a = arguments;
		
		for(var i = 0; i < a.length; i++)
		{
			if(a[i] == null)
				continue;
				
			if(typeof(a[i]) == 'string' && a[i] != '')
				return a[i] + '';
		
			if(typeof(a[i]) == 'object' && a[i].value != '')
				return a[i].value + '';
		}
		
		return null;
	}
	
	function IsOptionSet(value, list)
	{
		for(var i = 0; i < list.length; i++)
			if(list[i] == value)
				return true;
		
		return false;
	}
	
	function GetOptionValue(name, list, defaultValue)
	{
		var regex = new RegExp('^' + name + '\\[(\\w+)\\]$', 'gi');
		var matches = null;

		for(var i = 0; i < list.length; i++)
			if((matches = regex.exec(list[i])) != null)
				return matches[1];
		
		return defaultValue;
	}

	var highlighter = null;
	var registered = new Object();
	var propertyName = 'value';
	
	// register all brushes
	for(var brush in dp.sh.Brushes)
	{
		var aliases = dp.sh.Brushes[brush].Aliases;

		if(aliases == null)
			continue;
		
		for(var i = 0; i < aliases.length; i++)
			registered[aliases[i]] = brush;
	}

	var options = "";
	var language = "js";

	if(registered[language] == null)
		return;
	
	// instantiate a brush
	highlighter = new dp.sh.Brushes[registered[language]]();
	
	highlighter.noGutter = (showGutter == null) ? IsOptionSet('nogutter', options) : !showGutter;
	highlighter.addControls = (showControls == null) ? !IsOptionSet('nocontrols', options) : showControls;
	highlighter.collapse = (collapseAll == null) ? IsOptionSet('collapse', options) : collapseAll;
	highlighter.showColumns = (showColumns == null) ? IsOptionSet('showcolumns', options) : showColumns;
	
	// first line idea comes from Andrew Collington, thanks!
	highlighter.firstLine = (firstLine == null) ? parseInt(GetOptionValue('firstline', options, 1)) : firstLine;

	highlighter.Highlight(strCode);

	return highlighter.div;
}


/*FILEHEAD(/in/Core/Highlighter/shBrushJScript.js)SIZE(1316)TIME(1166375348945)*/

dp.sh.Brushes.JScript = function()
{
	var keywords =	'abstract boolean break byte case catch char class const continue debugger ' +
					'default delete do double else enum export extends false final finally float ' +
					'for function goto if implements import in instanceof int interface long native ' +
					'new null package private protected public return short static super switch ' +
					'synchronized this throw throws transient true try typeof var void volatile while with';

	this.regexList = [
		{ regex: dp.sh.RegexLib.SingleLineCComments,				css: 'comment' },			// one line comments
		{ regex: dp.sh.RegexLib.MultiLineCComments,					css: 'comment' },			// multiline comments
		{ regex: dp.sh.RegexLib.DoubleQuotedString,					css: 'string' },			// double quoted strings
		{ regex: dp.sh.RegexLib.SingleQuotedString,					css: 'string' },			// single quoted strings
		{ regex: new RegExp('^\\s*#.*', 'gm'),						css: 'preprocessor' },		// preprocessor tags like #region and #endregion
		{ regex: new RegExp(this.GetKeywords(keywords), 'gm'),		css: 'keyword' }			// keywords
		];

	this.CssClass = 'dp-c';
}

dp.sh.Brushes.JScript.prototype	= new dp.sh.Highlighter();
dp.sh.Brushes.JScript.Aliases	= ['js', 'jscript', 'javascript'];

/*FILEHEAD(/in/Core/Highlighter/SyntaxHighlighter.css.js)SIZE(4449)TIME(1166375348945)*/

var SyntaxHighlighterCSS = '.dp-highlighter{	font-family: "Courier New" , Courier, mono;	font-size: 12px;	border: 1px solid #CCCCCC;	background-color: #fff;	overflow: auto;	max-height : 400px;	white-space : nowrap;}.dp-highlighter .bar{	padding-left: 45px;}.dp-highlighter.collapsed .bar, .dp-highlighter.nogutter .bar{	padding-left: 0px;}.dp-highlighter ol{	margin: 0px 0px 1px 45px; 	padding: 0px;	color: #2B91AF;}.dp-highlighter.nogutter ol{	list-style-type: none;	margin-left: 0px;}.dp-highlighter ol li, .dp-highlighter .columns div{	border-left: 3px solid #6CE26C;	background-color: #fff;	padding-left: 10px;	line-height: 14px;}.dp-highlighter.nogutter ol li, .dp-highlighter.nogutter .columns div{	border: 0;}.dp-highlighter .columns{	color: gray;	overflow: hidden;	width: 100%;}.dp-highlighter .columns div{	padding-bottom: 5px;}.dp-highlighter ol li.alt{	background-color: #f8f8f8;}.dp-highlighter ol li span{	color: Black;}.dp-highlighter.collapsed ol{	margin: 0px;}.dp-highlighter.collapsed ol li{	display: none;}.dp-highlighter.printing {	border: none;}.dp-highlighter.printing .tools{	display: none !important;}.dp-highlighter.printing li{	display: list-item !important;}.dp-highlighter .tools{	padding: 3px 8px 3px 10px;	border-bottom: 1px solid #2B91AF;	font: 9px Verdana, Geneva, Arial, Helvetica, sans-serif;	color: silver;}.dp-highlighter.collapsed .tools{	border-bottom: 0;}.dp-highlighter .tools a{	font-size: 9px;	color: gray;	text-decoration: none;	margin-right: 10px;}.dp-highlighter .tools a:hover{	color: red;	text-decoration: underline;}.dp-about { background-color: #fff; margin: 0px; padding: 0px; }.dp-about table { width: 100%; height: 100%; font-size: 11px; font-family: Tahoma, Verdana, Arial, sans-serif !important; }.dp-about td { padding: 10px; vertical-align: top; }.dp-about .copy { border-bottom: 1px solid #ACA899; height: 95%; }.dp-about .title { color: red; font-weight: bold; }.dp-about .para { margin: 0 0 4px 0; }.dp-about .footer { background-color: #ECEADB; border-top: 1px solid #fff; text-align: right; }.dp-about .close { font-size: 11px; font-family: Tahoma, Verdana, Arial, sans-serif !important; background-color: #ECEADB; width: 60px; height: 22px; }.dp-c {}.dp-c .comment { color: green; }.dp-c .string { color: blue; }.dp-c .preprocessor { color: gray; }.dp-c .keyword { color: blue; }.dp-c .vars { color: #d00; }.dp-vb {}.dp-vb .comment { color: green; }.dp-vb .string { color: blue; }.dp-vb .preprocessor { color: gray; }.dp-vb .keyword { color: blue; }.dp-sql {}.dp-sql .comment { color: green; }.dp-sql .string { color: red; }.dp-sql .keyword { color: blue; }.dp-sql .func { color: #ff1493; }.dp-sql .op { color: #808080; }.dp-xml {}.dp-xml .cdata { color: #ff1493; }.dp-xml .comments { color: green; }.dp-xml .tag { font-weight: bold; color: blue; }.dp-xml .tag-name { color: black; font-weight: bold; }.dp-xml .attribute { color: red; }.dp-xml .attribute-value { color: blue; }.dp-delphi {}.dp-delphi .comment { color: #008200; font-style: italic; }.dp-delphi .string { color: blue; }.dp-delphi .number { color: blue; }.dp-delphi .directive { color: #008284; }.dp-delphi .keyword { font-weight: bold; color: navy; }.dp-delphi .vars { color: #000; }.dp-py {}.dp-py .comment { color: green; }.dp-py .string { color: red; }.dp-py .docstring { color: green; }.dp-py .keyword { color: blue; font-weight: bold;}.dp-py .builtins { color: #ff1493; }.dp-py .magicmethods { color: #808080; }.dp-py .exceptions { color: brown; }.dp-py .types { color: brown; font-style: italic; }.dp-py .commonlibs { color: #8A2BE2; font-style: italic; }.dp-rb {}.dp-rb .comment { color: #c00; }.dp-rb .string  { color: #f0c; }.dp-rb .symbol  { color: #02b902; }.dp-rb .keyword { color: #069; }.dp-rb .variable { color: #6cf; }.dp-css {}.dp-css .comment { color: green; }.dp-css .string { color: red; }.dp-css .keyword { color: blue; }.dp-css .colors { color: darkred; }.dp-css .vars { color: #d00; }.dp-j {}.dp-j .comment { color: rgb(63,127,95); }.dp-j .string { color: rgb(42,0,255); }.dp-j .keyword { color: rgb(127,0,85); font-weight: bold }.dp-j .annotation { color: #646464; }.dp-j .number { color: #C00000; }.dp-cpp {}.dp-cpp .comment { color: #e00; }.dp-cpp .string { color: red; }.dp-cpp .preprocessor { color: #CD00CD; font-weight: bold; }.dp-cpp .keyword { color: #5697D9; font-weight: bold; }.dp-cpp .datatypes { color: #2E8B57; font-weight: bold; }';

/*FILEHEAD(/in/Core/Kernel/Animation.js)SIZE(3311)TIME(1203730484247)*/

jpf.Animate = {
	sequences : [],
	register : function(o){
		return this.sequences.push(o) - 1;
	},
	destroy : function(id){
		this.sequences[id] = null;
	},
	findSeq : function(id){
		return this.sequences[id];
	},
	
	//Animation Modules
	left : function(oHTML, value){oHTML.style.left = value + "px";},
	right : function(oHTML, value){oHTML.style.right = value + "px";},
	top : function(oHTML, value){oHTML.style.top = value + "px";},
	width : function(oHTML, value, center){oHTML.style.width = value + "px";},
	height : function(oHTML, value, center){oHTML.style.height = value + "px";},
	scrollTop : function(oHTML, value, center){oHTML.scrollTop = value;},
	"height-rsz" : function(oHTML, value, center){oHTML.style.height = value + "px";if(jpf.hasSingleResizeEvent) window.onresize();},
	
	mleft : function(oHTML, value){oHTML.style.marginLeft = value + "px";},
	
	scrollwidth : function(oHTML, value){
		oHTML.style.width = value + "px";
		oHTML.scrollLeft = oHTML.scrollWidth;
	},
	
	scrollheight_old : function(oHTML, value){
		try{
			oHTML.style.height = value + "px";
			oHTML.scrollTop = oHTML.scrollHeight;
		}catch(e){alert(value)}
	},
	
	scrollheight : function(oHTML, value){
		oHTML.style.height = value + "px";
		oHTML.scrollTop = oHTML.scrollHeight - oHTML.offsetHeight;
	},
	
	scrolltop : function(oHTML, value){
		oHTML.style.height = value + "px";
		oHTML.style.top = (-1 * value - 2) + "px";
		oHTML.scrollTop = 0;//oHTML.scrollHeight - oHTML.offsetHeight;
	},
	
	clipright : function(oHTML, value, center){
		oHTML.style.clip = "rect(auto, auto, auto, " + value + "px)";
		oHTML.style.marginLeft = (-1*value) + "px";
	},
	
	fade : function(oHTML, value){
		if(jpf.hasStyleFilters) oHTML.style.filter = "alpha(opacity=" + parseInt(value*100) + ")";
		//else if(false && jpf.isGecko) oHTML.style.MozOpacity = value-0.000001;
		else oHTML.style.opacity = value;
	}
}

/**
 * @constructor
 */
jpf.GuiAnimation = function(oHTML, type, fromValue, toValue, animtype, frames, interval, onfinish, userdata){
	this.uniqueId = jpf.Animate.register(this);
	this.method = jpf.Animate[type];

	this.oHTML = oHTML;
	this.onfinish = onfinish;
	this.userdata = userdata;
	this.interval = interval;
	this.frames = frames;
	
	//Compile steps
	this.steps = [fromValue];
	this.step = 0;
	
	var steps = parseInt(frames);
	var scalex = (toValue - fromValue)/((Math.pow(steps,2)+2*steps+1)/(4*steps));
	for(var i=0;i<frames;i++){
		if(animtype == 0 && !value) var value = (toValue - fromValue)/frames; 
		else if(animtype == 1) var value = scalex*Math.pow(((steps-i))/steps,3); 
		else if(animtype == 2) var value = scalex * Math.pow(i/frames, 3); 

		this.steps.push(Math.max(0, this.steps[this.steps.length-1] + value - (i==0?1:0)));
	}
	this.steps[this.steps.length-1] = Math.max(1, toValue-1);

	//Stop
	this.stop = function(){
		clearTimeout(this.timer);
		jpf.Animate.destroy(this.uniqueId);
	}

	//Play
	jpf.AnimateStep(0, this.uniqueId);
}

jpf.AnimateStep = function (step, uniqueId){
	var o = jpf.Animate.findSeq(uniqueId);
	if(!o) return;
	
	try{o.method(o.oHTML, o.steps[step]);}catch(e){}

	if(step < o.frames) o.timer = setTimeout('jpf.AnimateStep(' + (step+1) + ', ' + uniqueId + ')', o.interval);
	else if(o.onfinish) o.onfinish(o.oHTML, o.userdata);
}

/*FILEHEAD(/in/Core/Kernel/browsers/isGecko.js)SIZE(4856)TIME(1205790104099)*/
function runGecko(){
	
jpf.importClass(runNonIe, true, self);

DocumentFragment.prototype.getElementById = function(id){
	return this.childNodes.length ? this.childNodes[0].ownerDocument.getElementById(id) : null;
}

/* ***************************************************************************
	XML Serialization
****************************************************************************/

//XMLDocument.xml
XMLDocument.prototype.__defineGetter__("xml", function(){
	return (new XMLSerializer()).serializeToString(this);
});
XMLDocument.prototype.__defineSetter__("xml", function(){
	throw new Error(1042, jpf.formErrorString(1042, null, "XML serializer", "Invalid assignment on read-only property 'xml'."));
});

//Node.xml
Node.prototype.__defineGetter__("xml", function(){
	if(this.nodeType == 3 || this.nodeType == 4 || this.nodeType == 2) return this.nodeValue;
	return (new XMLSerializer()).serializeToString(this);
});

//Node.xml
Element.prototype.__defineGetter__("xml", function(){
	return (new XMLSerializer()).serializeToString(this);
});

/* ***************************************************************************
	XSLT
****************************************************************************/


//XMLDocument.selectNodes
HTMLDocument.prototype.selectNodes = 
XMLDocument.prototype.selectNodes = function(sExpr, contextNode){
	var oResult = this.evaluate(sExpr, (contextNode?contextNode:this), this.createNSResolver(this.documentElement), XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
	var nodeList = new Array(oResult.snapshotLength);
	nodeList.expr = sExpr;
	for(var i=0;i<nodeList.length;i++) nodeList[i] = oResult.snapshotItem(i);
	return nodeList;
}

//Element.selectNodes
Element.prototype.selectNodes = function(sExpr){
	var doc = this.ownerDocument;
	if(doc.selectNodes)
		return doc.selectNodes(sExpr, this);
	else
		throw new Error(1047, jpf.formErrorString(1047, null, "xPath selection", "Method selectNodes is only supported by XML Nodes"));
};

//XMLDocument.selectSingleNode
HTMLDocument.prototype.selectSingleNode = 
XMLDocument.prototype.selectSingleNode = function(sExpr, contextNode){
	var nodeList = this.selectNodes(sExpr + "[1]", contextNode?contextNode:null);
	return nodeList.length > 0 ? nodeList[0] : null;
}

//Element.selectSingleNode
Element.prototype.selectSingleNode = function(sExpr){
	var doc = this.ownerDocument;
	if(doc.selectSingleNode)
		return doc.selectSingleNode(sExpr, this);
	else
		throw new Error(1048, jpf.formErrorString(1048, null, "XPath Selection", "Method selectSingleNode is only supported by XML Nodes. \nInfo : " + e));
};


/* ******** Error Compatibility **********************************************
	Error Object like IE
****************************************************************************/

function Error(nr, msg){
	if(!jpf.debugwin.useDebugger) jpf.debugwin.errorHandler(msg, "", 0);
	
	this.message = msg;
	this.nr = nr;
}

/* ******** XML Compatibility ************************************************
	Extensions to the XMLDatabase
****************************************************************************/

if(jpf.XMLDatabaseImplementation){
	jpf.XMLDatabaseImplementation.prototype.htmlImport = function(xmlNode, htmlNode, beforeNode, test){
		if(!htmlNode) alert(this.htmlImport.caller);
		
		if(xmlNode.length != null && !xmlNode.nodeType){
			for(var str='',i=0;i<xmlNode.length;i++) str += xmlNode[i].xml;
			var str = str.replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/<([^>]+)\/>/g, "<$1></$1>");
			(beforeNode || htmlNode).insertAdjacentHTML(beforeNode ? "beforebegin" : "beforeend", str);

			return;
		}
		
		if(htmlNode.ownerDocument != document) return htmlNode.insertBefore(xmlNode, beforeNode);
		
		var strHTML = (xmlNode.outerHTML || (xmlNode.nodeType == 1 ? xmlNode.xml : xmlNode.nodeValue)).replace(/&lt;/g, "<").replace(/&gt;/g, ">");
		var pNode = (beforeNode || htmlNode);
		if(pNode.nodeType == 11){
			var id = xmlNode.getAttribute("id");
			if(!id) throw new Error(1049, jpf.formErrorString(1049, null, "XMLDatabase", "Inserting Cache Item in Document Fragment without an ID"));
			
			document.body.insertAdjacentHTML(beforeNode ? "beforebegin" : "beforeend", strHTML);
			pNode.appendChild(document.getElementById(id));
		}
		else{
			if(xmlNode.tagName.match(/tbody|td|tr/)) pNode.insertBefore(pNode.ownerDocument.createElement(xmlNode.tagName.toLowerCase()), beforeNode || null);
			else pNode.insertAdjacentHTML(beforeNode ? "beforebegin" : "beforeend", strHTML);
		}
		
		return beforeNode ? beforeNode.previousSibling : htmlNode.lastChild;
	}
}


}
/*FILEHEAD(/in/Core/Kernel/browsers/isIE.js)SIZE(8551)TIME(1203730484247)*/
function runIE(){

/* ******** XML Compatibility ************************************************
	Extensions to the XMLDatabase
****************************************************************************/

var hasIE7Security = hasIESecurity = false;
if(self.XLMHttpRequest) try{new XLMHttpRequest()}catch(e){hasIE7Security=true}
try{new ActiveXObject("microsoft.XMLHTTP")}catch(e){hasIESecurity=true}

if(hasIESecurity) jpf.importClass(function(){
	__CONTENT_IFRAME
}, true, self);

jpf.getObject = hasIESecurity ? 
function(type, message, no_error, isDataIsland){
	if(type == "HTTP"){
		if(jpf.availHTTP.length) return jpf.availHTTP.pop();
		//if((jpf.hasDeskRun||jpf.hasWebRun) && !self.USENATIVEHTTP) return jdshell.CreateComponent("XMLHTTP");
		
		return new XMLHttpRequest();
	}
	else if(type == "XMLDOM"){
		var xmlParser = getDOMParser(message, no_error);
		return xmlParser;
	}
} :
function(type, message, no_error, isDataIsland){
	if(type == "HTTP"){
		if(jpf.availHTTP.length) return jpf.availHTTP.pop();
		//if((jpf.hasDeskRun||jpf.hasWebRun) && !self.USENATIVEHTTP) return jdshell.CreateComponent("XMLHTTP");

		//if(jpf.isIE7 && !hasIE7Security) return new XMLHttpRequest();
		return new ActiveXObject("microsoft.XMLHTTP");
	}
	else if(type == "XMLDOM"){
		var xmlParser = new ActiveXObject("microsoft.XMLDOM");
		
		xmlParser.setProperty("SelectionLanguage", "XPath");
		//xmlParser.setProperty("SelectionNamespaces", "xmlns:j='http://www.javeline.com/2001/PlatForm'");
		
		//if(!isDataIsland) xmlParser.preserveWhiteSpace = true;
		if(message){
			if(jpf.cantParseXmlDefinition) message = message.replace(/\] \]/g, "] ]").replace(/^<\?[^>]*\?>/, "");//replace xml definition <?xml .* ?> for IE5.0 
			
			xmlParser.loadXML(message);
		}
		if(!no_error) this.xmlParseError(xmlParser);
		
		return xmlParser;
	}
};

jpf.xmlParseError = function(xml){
	var xmlParseError = xml.parseError;
	if(xmlParseError != 0){
		/*
			http://msdn.microsoft.com/library/en-us/xmlsdk30/htm/xmobjpmexmldomparseerror.asp?frame=true
		
			errorCode 	Contains the error code of the last parse error. Read-only. 
			filepos 		Contains the absolute file position where the error occurred. Read-only. 
			line 			Specifies the line number that contains the error. Read-only. 
			linepos 		Contains the character position within the line where the error occurred. Read-only. 
			reason 		Explains the reason for the error. Read-only. 
			srcText 		Returns the full text of the line containing the error. Read-only. 
			url 			Contains the URL of the XML document containing the last error. Read-only. 
		*/
		
		throw new Error(1050, jpf.formErrorString(1050, null, "XML Parse error on line " +  xmlParseError.line, xmlParseError.reason + "Source Text:\n" + xmlParseError.srcText.replace(/\t/gi, " ")));
	}
	
	return xml;
}

//function extendXmlDb(){
if(jpf.XMLDatabaseImplementation){

jpf.XMLDatabaseImplementation.prototype.htmlImport = function(xmlNode, htmlNode, beforeNode){
	if(xmlNode.length != null && !xmlNode.nodeType){
		for(var str='',i=0;i<xmlNode.length;i++) str += xmlNode[i].xml;
		var str = jpf.html_entity_decode(str).replace(/style="background-image:([^"]*)"/g, "find='$1' style='background-image:$1'");
		try{(beforeNode || htmlNode).insertAdjacentHTML(beforeNode ? "beforebegin" : "beforeend", str);}
		catch(e){
			//IE table hack
			document.body.insertAdjacentHTML("beforeend", "<table><tr>" + str + "</tr></table>");
			var x = document.body.lastChild.firstChild.firstChild;
			for(var i=x.childNodes.length-1;i>=0;i--) htmlNode.appendChild(x.childNodes[jpf.hasDynamicItemList ? 0 : i]);
		}

		//Fix IE image loading bug
		if(!this.nodes) this.nodes = [];
		var id = this.nodes.push(htmlNode.getElementsByTagName("*")) - 1;
		setTimeout('jpf.XMLDatabase.doNodes(' + id + ')');

		return;
	}
	
	//== ??? OR !=
	if(htmlNode.ownerDocument && htmlNode.ownerDocument != document && xmlNode.ownerDocument == htmlNode.ownerDocument) 
		return htmlNode.insertBefore(xmlNode, beforeNode);
	//if(htmlNode.ownerDocument && htmlNode.ownerDocument != document) return htmlNode.insertBefore(xmlNode, beforeNode);

	var strHTML = jpf.html_entity_decode(xmlNode.outerHTML || xmlNode.xml || xmlNode.nodeValue);
	var pNode = (beforeNode || htmlNode);
	if(pNode.nodeType == 11){
		var id = xmlNode.getAttribute("id");
		if(!id) throw new Error(1049, jpf.formErrorString(1049, null, "XMLDatabase", "Inserting Cache Item in Document Fragment without an ID"));
		
		document.body.insertAdjacentHTML(beforeNode ? "beforebegin" : "beforeend", strHTML);
		pNode.appendChild(document.getElementById(id));
	}
	else pNode.insertAdjacentHTML(beforeNode ? "beforebegin" : "beforeend", strHTML);
	
	return beforeNode ? beforeNode.previousSibling : htmlNode.lastChild;
}

jpf.XMLDatabaseImplementation.prototype.doNodes = function(id){
	var nodes = this.nodes[id];
	for(var i=0;i<nodes.length;i++){
		if(nodes[i].getAttribute("find")) nodes[i].style.backgroundImage = nodes[i].getAttribute("find");
	}
	this.nodes[id] = null;
}

//Initialize XMLDatabase
jpf.XMLDatabase = new jpf.XMLDatabaseImplementation();

}

//jpf.Init.addConditional(extendXmlDb, self, 'XMLDatabaseImplementation');
if(!hasIESecurity) jpf.Init.run('XMLDatabase');


//IE5.5 compat
jpf.getOwnerDocument = function(node){
	o = node;
	while(o.parentNode && o.nodeType != 9) o = o.parentNode;
	//node.ownerDocument = o;
	return o;
}

if(!document.createDocumentFragment){
	/**
	 * @constructor
	 */
	function DocumentFragment(){
		this.childNodes = [];
		
		this.appendChild = function(childNode){
			this.childNodes.push(childNode);
		}
		
		this.reinsert = function(parent){
			for(var i=0;i<this.childNodes.length;i++){
				parent.appendChild(this.childNodes[i]);
			}
		}
	}
}


jpf.Popup2 = {
	cache : {},
	setContent : function(cacheId, content, style, width, height){
		if(!this.popup) this.init();

		this.cache[cacheId] = {
			content : content,
			style : style,
			width : width,
			height : height
		};
		if(content.parentNode) content.parentNode.removeChild(content);
		if(style) jpf.importCssString(this.popup.document, style);
		
		return this.popup.document;
	},
	removeContent : function(cacheId){
		this.cache[cacheId] = null;
		delete this.cache[cacheId];
	},
	init : function(){
		this.popup = window.createPopup();
		
		this.popup.document.write('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml" xmlns:j=jpf.ns.jpf xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><head><script>var jpf = {all:[],lookup:function(uniqueId){return this.all[uniqueId]||{__setStyleClass:function(){}};}};function destroy(){jpf.all=null;}</script><style>HTML{border:0;overflow:hidden;margin:0}BODY{margin:0}</style></head><body onmouseover="if(!self.jpf) return;if(this.c){jpf.all = this.c.all;this.c.Popup.parentDoc=self;}"></body></html>');
		
		var c = jpf;
		this.popup.document.body.onmousemove = function(){this.c = c}
	},
	show : function(cacheId, x, y, animate, ref, width, height, callback){
		if(!this.popup) this.init();
		var o = this.cache[cacheId];
		//if(this.last != cacheId) 
		this.popup.document.body.innerHTML = o.content.outerHTML;

		if(animate){
			var iVal, steps = 7, i = 0, popup = this.popup;
			iVal = setInterval(function(){
				var value = ++i*((height || o.height)/steps);
				popup.show(x, y, width || o.width, value, ref);
				popup.document.body.firstChild.style.marginTop = (i-steps-1)*((height || o.height)/steps);
				if(i > steps){
					clearInterval(iVal)
					callback(popup.document.body.firstChild);
				}
			}, 10);
		}
		else{
			this.popup.show(x, y, width || o.width, height || o.height, ref);
		}

		this.last = cacheId;
	},
	hide : function(){
		if(this.popup) this.popup.hide();
	},
	forceHide : function(){
		if(this.last) jpf.lookup(this.last).dispatchEvent("onpopuphide");
	},
	destroy : function(){
		if(!this.popup) return;
		this.popup.document.body.c = null;
		this.popup.document.body.onmouseover = null;
	}
}
	
	jpf.importClass(runXpath, true, self);

}
/*FILEHEAD(/in/Core/Kernel/browsers/isOpera.js)SIZE(5247)TIME(1203730484247)*/
function runOpera(){

setTimeoutOpera = setTimeout;
lookupOperaCall = [];
setTimeout = function(call, time){
	if(typeof call == "string") return setTimeoutOpera(call, time);
	return setTimeoutOpera("lookupOperaCall[" + (lookupOperaCall.push(call)-1) + "]()", time);
}

//HTMLHtmlElement = document.createElement("html").constructor;
//HTMLElement = {};
//HTMLElement.prototype = HTMLHtmlElement.__proto__.__proto__;
//HTMLDocument = Document = document.constructor;
var x = new DOMParser();
XMLDocument = DOMParser.constructor;
//Element = x.parseFromString("<Single />", "text/xml").documentElement.constructor;
x = null;

/* ***************************************************************************
	XML Serialization
****************************************************************************/

//XMLDocument.xml

//Node.xml
/*Node.prototype.serialize = function(){
	return (new XMLSerializer()).serializeToString(this);
}*/
//Node.xml

Node.prototype.serialize = 
XMLDocument.prototype.serialize = 
Element.prototype.serialize = function(){
	return (new XMLSerializer()).serializeToString(this);
}


//XMLDocument.selectNodes
Document.prototype.selectNodes = 
XMLDocument.prototype.selectNodes = 
HTMLDocument.prototype.selectNodes = function(sExpr, contextNode){
	var oResult = this.evaluate(sExpr, (contextNode?contextNode:this), this.createNSResolver(this.documentElement), XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
	var nodeList = new Array(oResult.snapshotLength);
	nodeList.expr = sExpr;
	for(var i=0;i<nodeList.length;i++) nodeList[i] = oResult.snapshotItem(i);
	return nodeList;
}

//Element.selectNodes
Element.prototype.selectNodes = function(sExpr){
	var doc = this.ownerDocument;
	if(!doc.selectSingleNode){
		doc.selectSingleNode = HTMLDocument.prototype.selectSingleNode;
		doc.selectNodes = HTMLDocument.prototype.selectNodes;
	}
	
	if(doc.selectNodes)
		return doc.selectNodes(sExpr, this);
	else
		throw new Error(1047, jpf.formErrorString(1047, null, "XPath Selection", "Method selectNodes is only supported by XML Nodes"));
};

//XMLDocument.selectSingleNode
Document.prototype.selectSingleNode = 
XMLDocument.prototype.selectSingleNode = 
HTMLDocument.prototype.selectSingleNode = function(sExpr, contextNode){
	var nodeList = this.selectNodes(sExpr + "[1]", contextNode?contextNode:null);
	return nodeList.length > 0 ? nodeList[0] : null;
}

//Element.selectSingleNode
Element.prototype.selectSingleNode = function(sExpr){
	var doc = this.ownerDocument;
	if(!doc.selectSingleNode){
		doc.selectSingleNode = HTMLDocument.prototype.selectSingleNode;
		doc.selectNodes = HTMLDocument.prototype.selectNodes;
	}
	
	if(doc.selectSingleNode)
		return doc.selectSingleNode(sExpr, this);
	else
		throw new Error(1048, jpf.formErrorString(1048, null, "XPath Selection", "Method selectSingleNode is only supported by XML Nodes. \nInfo : " + e));
};



jpf.compat.getWidthDiff = function(oHtml){
	return Math.max(0, (parseInt(jpf.compat.getStyle(oHtml, "padding-left"))||0) + (parseInt(jpf.compat.getStyle(oHtml, "padding-right"))||0) + (parseInt(jpf.compat.getStyle(oHtml, "border-left-width"))||0) + (parseInt(jpf.compat.getStyle(oHtml, "border-right-width"))||0));
}

jpf.compat.getHeightDiff = function(oHtml){
	return Math.max(0, (parseInt(jpf.compat.getStyle(oHtml, "padding-top"))||0) + (parseInt(jpf.compat.getStyle(oHtml, "padding-bottom"))||0) + (parseInt(jpf.compat.getStyle(oHtml, "border-top-width"))||0) + (parseInt(jpf.compat.getStyle(oHtml, "border-bottom-width"))||0));
}

jpf.compat.getDiff = function(oHtml){
	var pNode = oHtml.parentNode; var nSibling = oHtml.nextSibling;
	if(!oHtml.offsetHeight) document.body.appendChild(oHtml);

	/*
	alert(
		jpf.compat.getStyle(oHtml, "padding") + ":" + jpf.compat.getStyle(oHtml, "border-width") + ":" + oHtml.offsetWidth + ":" + jpf.compat.getStyle(oHtml, "width") + ":" + oHtml.clientWidth + ":" + oHtml.currentStyle.width + "\n" +
		jpf.compat.getStyle(oHtml, "padding") + ":" + jpf.compat.getStyle(oHtml, "border-width") + ":" + oHtml.offsetHeight + ":" + jpf.compat.getStyle(oHtml, "height") + ":" + oHtml.clientHeight + ":" + oHtml.currentStyle.height + "\n" +
		diff
	);
	*/
	
	var diff = [
		Math.max(0, parseInt(jpf.compat.getStyle(oHtml, "padding-left")) + parseInt(oHtml.currentStyle.paddingRight) + parseInt(jpf.compat.getStyle(oHtml, "border-left-width")) + parseInt(jpf.compat.getStyle(oHtml, "border-right-width")) || 0),
		Math.max(0, parseInt(jpf.compat.getStyle(oHtml, "padding-top")) + parseInt(oHtml.currentStyle.paddingBottom) + parseInt(jpf.compat.getStyle(oHtml, "border-top-width")) + parseInt(jpf.compat.getStyle(oHtml, "border-bottom-width")) || 0)
	];
	if(oHtml.tagName.match(/frame/i)) alert(diff);
	//alert(parseInt(oHtml.currentStyle.paddingLeft) + ":" +  parseInt(oHtml.currentStyle.paddingRight) + ":" +  parseInt(oHtml.currentStyle.borderLeftWidth) + ":" +  parseInt(oHtml.currentStyle.borderRightWidth));

	pNode.insertBefore(oHtml, nSibling);
	
	return diff;
}


jpf.importClass(runNonIe, true, self);

}
/*FILEHEAD(/in/Core/Kernel/browsers/isSafari.js)SIZE(3632)TIME(1203730484247)*/
function runSafari(){
	
setTimeoutSafari = setTimeout;
lookupSafariCall = [];
setTimeout = function(call, time){
	if(typeof call == "string") return setTimeoutSafari(call, time);
	return setTimeoutSafari("lookupSafariCall[" + (lookupSafariCall.push(call)-1) + "]()", time);
}

if(jpf.isSafariOld){
	HTMLHtmlElement = document.createElement("html").constructor;
	Node = HTMLElement = {};
	HTMLElement.prototype = HTMLHtmlElement.__proto__.__proto__;
	HTMLDocument = Document = document.constructor;
	var x = new DOMParser();
	XMLDocument = x.constructor;
	Element = x.parseFromString("<Single />", "text/xml").documentElement.constructor;
	x = null;
}

/* ***************************************************************************
	XML Serialization
****************************************************************************/

//XMLDocument.xml
Document.prototype.serialize = 
Node.prototype.serialize = 
XMLDocument.prototype.serialize = function(){
	return (new XMLSerializer()).serializeToString(this);
}
//Node.xml
/*Node.prototype.serialize = function(){
	return (new XMLSerializer()).serializeToString(this);
}*/
//Node.xml


if(jpf.isSafariOld || jpf.isSafari){
	//XMLDocument.selectNodes
	HTMLDocument.prototype.selectNodes = 
	XMLDocument.prototype.selectNodes = function(sExpr, contextNode){
		return jpf.XPath.selectNodes(sExpr, contextNode || this);
	}
	
	//Element.selectNodes
	Element.prototype.selectNodes = function(sExpr, contextNode){
		return jpf.XPath.selectNodes(sExpr, contextNode || this);
	};
	
	//XMLDocument.selectSingleNode
	HTMLDocument.prototype.selectSingleNode = 
	XMLDocument.prototype.selectSingleNode = function(sExpr, contextNode){
		return jpf.XPath.selectNodes(sExpr, contextNode || this)[0];
	}
	
	//Element.selectSingleNode
	Element.prototype.selectSingleNode = function(sExpr, contextNode){
		return jpf.XPath.selectNodes(sExpr, contextNode || this)[0];
	};
	
	jpf.importClass(runXpath, true, self);
	jpf.importClass(runXslt, true, self);
}
/*else{
	//XMLDocument.selectNodes
	HTMLDocument.prototype.selectNodes = 
	XMLDocument.prototype.selectNodes = function(sExpr, contextNode){
		var oResult = this.evaluate(sExpr, (contextNode?contextNode:this), this.createNSResolver(this.documentElement), XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
		var nodeList = new Array(oResult.snapshotLength);
		nodeList.expr = sExpr;
		for(i=0;i<nodeList.length;i++) nodeList[i] = oResult.snapshotItem(i);
		return nodeList;
	
	}
	
	//Element.selectNodes
	Element.prototype.selectNodes = function(sExpr){
		var doc = this.ownerDocument;
		if(doc.selectNodes)
			return doc.selectNodes(sExpr, this);
		else
			throw new Error(1047, jpf.formErrorString(1047, null, "xPath selection", "Method selectNodes is only supported by XML Nodes"));
	};
	
	//XMLDocument.selectSingleNode
	HTMLDocument.prototype.selectSingleNode = 
	XMLDocument.prototype.selectSingleNode = function(sExpr, contextNode){
		var nodeList = this.selectNodes(sExpr + "[1]", contextNode?contextNode:null);
		return nodeList.length > 0 ? nodeList[0] : null;
	}
	
	//Element.selectSingleNode
	Element.prototype.selectSingleNode = function(sExpr){
		var doc = this.ownerDocument;
		if(doc.selectSingleNode)
			return doc.selectSingleNode(sExpr, this);
		else
			throw new Error(1048, jpf.formErrorString(1048, null, "XPath Selection", "Method selectSingleNode is only supported by XML Nodes. \nInfo : " + e));
	};
}*/


	jpf.importClass(runNonIe, true, self);

}
/*FILEHEAD(/in/Core/Kernel/browsers/JS.js)SIZE(3831)TIME(1203730484247)*/

/*FILEHEAD(/in/Core/Kernel/browsers/JSLT.js)SIZE(18695)TIME(1213461485214)*/

//eval("var x = function(a){" + "alert(ruben)" + "}");

/**
 * Object returning an implementation of an JSLT parser.
 *
 * @classDescription		This class creates a new JSLT parser
 * @return {JSLTImplementation} Returns a new JSLT parser
 * @type {JSLTImplementation}
 * @constructor
 * @parser
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.9
 */
jpf.JsltImplementation = function(){

	//------------------------------------------------------------------------------------
	// compile functions
	function isString() {
		if (typeof arguments[0] == 'string') return true;
		if (typeof arguments[0] == 'object' && arguments[0].constructor) return (arguments[0].constructor.toString().match(/string/i) != null);
		return false;
	}
	function jesc(s,esc){
		if(!esc)return s;if(!s)return '';
		if(esc.toLowerCase()=='q')return s.replace(/&/g,"&amp;").replace(/\'/g,"\\&squot").replace(/\"/g,"\\&quot").replace(/\r?\n/g,"\\n");
		return s;
	}
	function jcpy(s,n,p){if(!n)return;if(p){var t = n.selectNodes(p);if(!t || t.length==0)return;for(var i = 0;i<t.length;i++)s[s.length]=t[i].xml;}else s[s.length]=n.xml;}
	function jxml(n,p){if(!n)return;if(p){var o = [];var t = n.selectNodes(p);if(!t || t.length==0)return;for(var i = 0;i<t.length;i++)o[o.length]=t[i].xml;}else return n.xml;return o.join('');}
	function jval(n,p){
		if(!n)return '';if(p)n = n.selectSingleNode(p);if(!n)return '';if(n.nodeType == 1) n=n.firstChild;
		return n?n.nodeValue:'';
	}
	function jloc(n,f,p){if(!n)return;n = isString(p)?n.selectSingleNode(p):p;if(!n)return;f(n);};
	function jdbg(a){jpf.status(a)};
	function jnod(n,p){if(!n)return '';if(p)n = n.selectSingleNode(p);if(!n)return null;return n;}
	function jnds(n,p){if(!n)return '';if(p)n = n.selectNodes(p);if(!n)return null;return n;}
	function jexs(n,p){if(!n)return false;if(p)n = n.selectSingleNode(p);return n!=null;}
	function jemp(n,p){if(!n)return false;if(p)n = n.selectSingleNode(p);if(!n)return true;if(n.nodeType == 1) n=n.firstChild;return (n?n.nodeValue:'').match(/^[\s\r\n\t]*$/)!=null;}
	function jcnt(n,p){if(!n)return 0; var t= n.selectNodes(p);return t?t.length:0;}
	function jpak(n,f,p){
		var s=[];f(s,n);return s.join('');
	}
	function jstore(n,pk,f,p){
		if(!p)p='def';
		if(!pk[p])pk[p]=[];
		f(pk[p],n);return;
	}
	function jfetch(pk,p){
		if(!p)p='def';
		if(pk[p])return pk[p].join('');
		return '';
	}
	
	function jfra(f,t,sp,ep){if(!t)return;var end = ep==null?t.length:Math.min(t.length,(sp+ep));for(var i = (sp==null)?0:sp;i<end;i++)f(i,end,t[i]);}
	function jvls(n,p){
		var r=[];
		if(!n)return r; var t = n.selectNodes(p);if(!t)return r;
		for(var i = 0;i<t.length;i++){ 
			n = t[i];if(n.nodeType == 1) n=n.firstChild;r[i]=n?n.nodeValue:'';
		}
		return r;
	}
	function jpar(f,str){var n = parseXML(str).documentElement;f(n);}
	function jfor(n,f,p,sp,ep){
		if(!n)return;
		var t = n.selectNodes(p);
		var end = ep==null?t.length:Math.min(t.length,(sp+ep));
		for(var i = (sp==null)?0:sp;i<end;i++)f(i,end,t[i]);
	}
	
	// Sorting helpers
	var sort_intmask = ["", "0", "00", "000", "0000", "00000", "000000", "0000000", "00000000", "000000000", "0000000000", "00000000000", "000000000000", "0000000000000", "00000000000000" ];
	var sort_dateFmtStr;
	var sort_dateFormat;
	var sort_dateReplace; 
	function sort_dateFmt(str){
		sort_dateFmtStr = str;
		var result = str.match(/(D+|Y+|M+|h+|m+|s+)/g);
		if(!result)return;
		for(var pos={},i=0;i<result.length;i++) pos[result[i].substr(0,1)] = i+1;
		sort_dateFormat = new RegExp(str.replace(/[^\sDYMhms]/g,'\\$1').replace(/YYYY/, "(\\d\\d\\d\\d)").replace(/(DD|YY|MM|hh|mm|ss)/g, "(\\d\\d)"));
		sort_dateReplace = "$" + pos["M"] + "/$" + pos["D"] + "/$" + pos["Y"];
		if(pos["h"])sort_dateReplace += " - $"+pos["h"]+":$"+pos["m"]+":$"+pos["s"];
	}

	// Sorting methods for sort()
  	function sort_alpha(n)  { if(!n)return '';if(n.nodeType == 1) n=n.firstChild;return n?n.nodeValue:''; }
	function sort_number(n){
		var t = sort_alpha(n);
	  	return (t.length < sort_intmask.length ? sort_intmask[sort_intmask.length - t.length] : "") + t;
	}
	function sort_date(n,args){
		if(!sort_dateFormat || (args && sort_dateFmtStr!=args[0]))sort_dateFmt(args?args[0]:"*");
		var t = sort_alpha(n),d;
		if(sort_dateFmtStr=='*')d = Date.parse(t);
		else d = (new Date(t.replace(sort_dateFormat, sort_dateReplace))).getTime();
		t = ""+parseInt(d); if(t=="NaN")t="0";
		return (t.length < sort_intmask.length ? sort_intmask[sort_intmask.length - t.length] : "") + t;
	}
	
	function jsort(n,f,p,ps,sm,desc,sp,ep){
		sm = sm?sm:sort_alpha;
		var sa = [], t = n.selectNodes(p), i = t.length, args = null;
		if(typeof sm != "function"){var m = sm.shift();args = sm; sm = m;}		

		// build string-sortable list with sort method
		while(i--){
			var n = t[i].selectSingleNode(ps);
			if(n) sa[sa.length] = {toString:function(){return this.v;}, pn:t[i], v:sm(n,args)};
			else  sa[sa.length] = {toString:function(){return this.v;}, pn:t[i], v:''};
		}
		// sort it
		sa.sort();
		
		//iterate like foreach
		var end = ep==null?sa.length:Math.min(sa.length,(sp+ep));
		var start = (sp==null)?0:sp;
		if(desc){
			for(var i = end-1;i>=start;i--)f(end-i-1,end,sa[i].pn,sa[i].v);
		}else{
			for(var i = start;i<end;i++)f(i,end,sa[i].pn,sa[i].v);
		}
	}
	
	
	function japl(s,n,ma,p){
		if(!n)return;
		var m = n.selectNodes(p||'node()');
		for(var i=0;i<m.length;i++){
			var n = m[i];
			var f = ma[0][n.tagName];
			if(f)f(s,n);
			else{
				for(var k=1;k<ma.length;k++){
					var sn = n.selectSingleNode(ma[k][0]);
					if(sn){ma[k][1](s,sn);break;}
				}
			}
		}
	}
	
	function jmat(ma,f,p){	
		var s = p.split(/\|/), all = true;
		for(var i = 0;i<s.length;i++){
			if(!s[i].match(/^[\w_]+$/))all=false;
			ma[0][s[i]]=f;
		}
		if(!all){
			p = "self::"+p.replace(/\|/g,"|self::");
			ma[ma.length]=[p,f];
		}
	}
	

	//------------------------------------------------------------------------------------

	var types=['[','{','(','text','xpath','word','sep','ws','semi','sh','op','col','str','regex'];
	var closes=[']','}',')'];

	var func={'last':[0,'(i==len-1)'],
			    'first':[0,'(i==0)'],
				 'out':[0,'s[s.length]'],
				 'apply':[1,';japl(s,n,ma,',');'],
				 'copy':[1,';jcpy(s,n,',');'],
				 'xml':[1,'jxml(n,',')'],
				 'value':[1,'jval(n,',')'],
				 'exists':[1,'jexs(n,',')'],
				 'empty':[1,'jemp(n,',')'],
				 'values':[1,'jvls(n,',')'],
				 'node':[1,'jnod(n,',')'],
				 'nodes':[1,'jnds(n,',')'],
				 'count':[1,'jcnt(n,',')'],
				 'context':[1,'(n=n.selectSingleNode(','))'],
				 'foreach':[2,';jfor(n,function(i,len,n){','},',');'],
				 'sort':[2,';jsort(n,function(i,len,n,sv){','},',');'],
				 'local':[2,';jloc(n,function(n){','},',');'],	
				 'match':[2,';jmat(ma,function(s,n){','},',');'],
				 'pack':[2,'jpak(n,function(s,n){','},',')'],
				 'store':[2,'jstore(n,os,function(s,n){','},',');'],
				 'fetch':[1,'jfetch(os,',')'],

				 'parse':[2,'jpar(function(n){','},',');'],
				 'forarray':[3],
				 'macro':[4],
				 'pragma':[5],
				 '_':[6]};
	// s,n,i,len
		
	var short_0={'%':'s[s.length]='};
	var short_1={'$':['jval(n,',')'],
					 '&':['jnod(n,',')'],
					 '@':['(n=n.selectSingleNode(','))'],
					 '~':['jexs(n,',')'],
					 '!':['!jexs(n,',')'],
					 '#':['jcnt(n,',')'],
					 '^':[';japl(s,n,ma,',');']};
	var short_2={'*':[';jfor(n,function(i,len,n){','},',')']};
	
	//------------------------------------------------------------------------------------
	
	function dump_tree(n,s,w){
		for(var i =0;i<n.length;i++){
			var m=n[i], t  = m[0];
			if(t<3){
				s.push(w+types[t]);dump_tree(m[1],s,'&nbsp;&nbsp;'+w);s.push(closes[t]);s.push('\n');
			}else{
				s.push(w+types[t]+': '+m[1]+'\n');					
			}
		}
	}
				
	this.compile = function(str, trim_startspace){
		if(str.match(/^var s\=\[\]/)){try{eval("var f = function(n){" + str + "};");}catch(e){jpf.status(jpf.formatJS(str));throw new Error(0, "Could not parse Precompiled JSLT with: " + e.message);} return [f, str]; }

		var err		=[];	// error list
		var tree		=[];  // parse tree
		var stack	=[];  // scopestack
		var node 	= tree;
		var blevel=0, tpos=0;
		var istr = 0, icc = 0;
		var lm = 0;
		var macros={};
		//tokenize
		str = str.replace(/\/\*[\s\S]*?\*\//gm,"");
		str.replace(/([\w_\.]+)|([\s]*,[\s]*)|([\s]*;[\s]*)|((?:[\s]*)[\$\@\#\%\^\&\*\?\!](?:[\s]*))|([\s]*[\+\-\<\>\|\=]+[\s]*)|(\s*\:\s*)|(\s+)|(\\[\\\{\}\[\]\"\'\/])|(\[)|(\])|([\s]*\([\s]*)|([\s]*\)[\s]*)|([\s]*\{[\s]*)|([\s]*\}[\s]*)|(\')|(\")|(\/)/g,function(m,word,sep,semi,sh,op,col,ws,bs1,bo,bc,po,pc,co,cc,q1,q2,re,pos){
			// stack helper functions
			function add_track(t)		{
				var txt = trim_startspace?str.substr( tpos, pos-tpos).replace(/[\r\n]\s*/,'').replace(/^\s*[\r\n]/,'').replace(/\\s/g,' ').replace(/[\r\n\t]/g,''):str.substr( tpos, pos-tpos).replace(/[\r\n\t]/g,'');
				if(txt.length>0){ node[node.length]=[t,txt,tpos,pos];}
			}
			function add_node(t,data)	{node[node.length]=[t,data,pos];}
			function add_sub(t)			{var n = [];node[node.length]=[t,n,pos];stack[stack.length] = node;node = n;}
			function pop_sub(t)			{if(stack.length==0){err[err.length] = ["extra "+closes[t],pos];}else{node = stack.pop();var ot = node[node.length-1][0];if(ot!=t){err[err.length]=["scope mismatch "+types[ot]+" with "+types[t],pos];}}}

			// are we in textmode or entering textmode?
			if(blevel==0 || (bc && blevel==1 && !istr )){
				if(icc==0){
					if(bo){add_track(3);blevel++;} // begin codeblock
					if(bc){if(blevel==0)err[err.length] = ["extra ]",pos];else {blevel--;tpos = pos+1;}} // end codeblock
				}
				if(co){add_track(3);tpos = pos+1;icc++;} // add last text chunk
				if(cc){add_track(4);tpos = pos+1;icc--;if(icc<0)err[err.length]=["extra }",pos];} // xpath chunk
			}else{
				if(!istr){
					if(word){add_node(5,m);if(m=='macro')lm=1;else if(lm)macros[m]=1,lm=0;}
					if(sep)add_node(6,',');
					if(ws)add_node(7,m);
					if(semi)add_node(8,m);
					if(sh)add_node(9,m);
					if(op)add_node(10,m);
					if(col)add_node(11,m);
					if(bo){blevel++;add_sub(0);}
					if(bc){blevel--;pop_sub(0);}
					if(co)add_sub(1);
					if(cc)pop_sub(1);
					if(po)add_sub(2);
					if(pc)pop_sub(2);
				}		
				if(q1){ if(istr==0){istr=1;tpos=pos;}else if(istr==1){istr=0;pos+=1;add_track(12);} }	
				if(q2){ if(istr==0){istr=2;tpos=pos;}else if(istr==2){istr=0;pos+=1;add_track(12);} }
				if(re){ 
					if(istr==0){
						// only allow regex mode if we have no previous siblings or we have a , before us
						if(node.length==0 || node[node.length-1][0]==6){
							istr=3;tpos=pos;
						}else add_node(10,m);
					}
					else if(istr==3){istr=0;pos+=1;add_track(13);}
				}
			}
			return m;
		});
		if(blevel==0){
			var txt = str.substr( tpos, str.length-tpos).replace(/[\r\n\t]/g,'');
			if(txt.length>0){ node[node.length]=[3,txt,tpos,str.length];}}
		if( stack.length > 0 )for(var i = stack.length-1;i>=0;i--){
			var j = stack[i][stack[i].length-1];
			err[err.length] = ["unclosed tag "+types[j[0]],j[2]]; 
		}

		var s		=['var s=[],ma=[{}],os={};'];				
		
		var pragma_trace = 0;
		function line_pos(cpos){
			var l=0;str.replace(/\n/g,function(m,pos){if(pos<cpos)l++;return m;});
			return l;
		}
		
		//recursive compile
		function compile_recur(s,n,offset){

			var k=n.length;
			var d,e;
		//	var lt=14;
			for(var i = ((offset==null)?0:offset);i<k;i++){
				var t = n[i][0];
				// function expansion
				if(t==5){
					var nt1=(i<k-1)?n[i+1][0]:-1,nt2=(i<k-2)?n[i+2][0]:-1;
					var m = n[i][1];
					var d = func[m];
					// also dont insert ;'s
					if(d){
						
						switch(d[0]){
							case 0: s[s.length] = d[1]; break;
							case 1: // () type function
								if(nt1!=2){
									err[err.length]=["Function "+m+" syntax error",n[i][2]];	
								}else{
									s[s.length] = d[1];if(!compile_recur(s,n[i+1][1]))s[s.length]='null';s[s.length] = d[2];
									i++;
								}
								break; 
							case 2: // () {} type function
								if(nt1!=2 || nt2!=1){
									err[err.length]=["Function "+m+" syntax error",n[i][2]];	
								}else{							
									s[s.length] = d[1];compile_recur(s,n[i+2][1]);s[s.length] = d[2];
									if( !compile_recur(s, n[i+1][1] ) )s[s.length]='null';
									s[s.length] = d[3];
									i+=2;		
								}
								break;
							case 3://forarray
								//we should have ( word ws in .... , .. , ..  ) {}
								var o,ok;
								if( i>k-3 || n[i+1][0]!=2 || n[i+2][0]!=1 || (o=n[i+1][1])[0][0]!=5 ||
									(ok=o.length)<5 || o[1][0]!=7 || o[2][0]!=5 || o[2][1]!='in' ){
									err[err.length]=["forarray syntax error",n[i][2]];	
								}else{
									s[s.length]=';jfra(function(i,len,'+o[0][1]+'){';
									compile_recur(s,n[i+2][1]);
									s[s.length]='},';
									compile_recur(s,o, 3);
									s[s.length]=');';i+=2;
								}break; 
							case 4://macro
								//we should have ws, word, quote, code
								if( i>=k-4 || n[i+1][0]!=7 || n[i+2][0]!=5 || n[i+3][0]!=2 || n[i+4][0] != 1){
									err[err.length]=["macro syntax error at",n[0][2]];
								}else{	
									s[s.length] = 'function '+n[i+2][1]+'(s,n,';
									if(!compile_recur(s,n[i+3][1]))s[s.length]='null';
									s[s.length]='){';compile_recur(s,n[i+4][1]);s[s.length]='}';
									i+=4;
								}
								break;
							case 5://pragma
							{
								if( i>=k-3 || n[i+1][0]!=7 || n[i+2][0]!=5 || n[i+3][0]!=2){
									err[err.length]=["macro syntax error at",n[0][2]];
								}else{	
									switch(n[i+2][1]){
										case 'trace':{
											var ts =[];
											compile_recur(ts,n[i+3][1]);
											pragma_trace = eval(ts.join(''));
										}break;
									}
								}
								i+=3;
							}
							case 6://trace
							{
								s[s.length]=';alert("Trace: '+line_pos(n[i][2])+'");';
							}
						}							
					}else{
						if(macros[m] && nt1 == 2){
							s[s.length] = m+'(s,n,';if(!compile_recur(s,n[i+1][1]))s[s.length]='null';s[s.length] = ')';
							i++;
						}else s[s.length] = m;
					}
					// check our type
				}
				//shorthand expansion
				else if(t==9){
					var nt1=(i<k-1)?n[i+1][0]:-1,nt2=(i<k-2)?n[i+2][0]:-1;
					var m = n[i][1];
					
					if(nt1==12){
						if(nt2==1){
							if(d=short_2[m]){
								s[s.length] = d[0];compile_recur(s,n[i+2][1]);s[s.length] = d[1]+n[i+1][1]+d[2];
								i+=2;lt=1;
							}
							else s[s.length]=m;
						}
						else{
							if(d=short_1[m]){
								if(nt2==11)s[s.length]=m;
								else{
									s[s.length] = d[0]+n[i+1][1]+d[1];
									i++;
								}
							}
							else {
								if( d=short_0[m] )s[s.length]=d;
								else s[s.length]=m;
							}		
						}	
					}else{
						if( d=short_0[m] )s[s.length]=d;
						else s[s.length]=m;
					}		
				}
				// normal add
				else{
					if(t<3){
						s[s.length] = types[t];compile_recur(s,n[i][1]);s[s.length]=closes[t];

						// ; insertion code
						if( (t==1 && i<k-1 && n[i+1][0]==5 && n[i+1][1]!='else') ||  // }word
							 ( t==2 && i<k-1 && n[i+1][0]==5 && !n[i+1][1].match(/^\./) && // )word
							   (i==0 || n[i-1][0]!=5 || !n[i-1][1].match(/^(if|for)$/) ) ) )
						{
							s[s.length] = ';';
						}

					}
					else{
						
						if(t==3)s[s.length]=';s[s.length]="'+n[i][1].replace(/\"/g,"\\\"").replace(/\n/g,"\\n")+'";';
						else if(t==4){
							var m = n[i][1].match(/^\^([\w])\s?/);
							if(m){
								s[s.length]=';s[s.length]=jesc(jval(n,"'+n[i][1].substr(2).replace(/"/g,"\\\"")+'"),"'+m[1]+'");';
							}else{
								s[s.length]=';s[s.length]=jval(n,"'+n[i][1].replace(/"/g,"\\\"")+'");';
							}
						}
						else s[s.length]=n[i][1];
					}
				}
				//lt = n[i][0];
			}
			return k;
		}	
		if(err.length==0)compile_recur(s,tree);
						
		// return all parse errors
		if(err.length>0){
			var e=[];
			for(var i = 0;i<err.length;i++){
				e[e.length]='Parse error('+line_pos(err[i][1])+'): '+err[i][0]+'\n';


			}
			// lets spit out our parse tree

			//var out=[];
			//dump_tree(tree,out,'');
						
			throw new Error(0, "Could not parse JSLT with: " + e.join('') +"\n" );
		}

		s[s.length]=";return s.join('');";
		var strJS = s.join('');

		try{eval("var f = function(n){" + strJS + "};");}catch(e){
			//var treedump=[];
			//dump_tree(tree,treedump,'');	
			jpf.status(jpf.formatJS(strJS));
			throw new Error(0, "Could not parse JSLT with: " + e.message /*+ "\n" + treedump.join('')*/);
		}
	
		return [f, strJS];
	};
	
	/* ***********************************************
		//you can interchange nodes and strings
		apply(jsltStr, xmlStr);
		apply(jsltNode, xmlNode);
		
		returns string or false
	************************************************/
	this.cache = [];
	
	this.apply = function(jsltNode, xmlNode){
		var jsltFunc, cacheId, jsltStr, doTest;
		
		//Type detection xmlNode
		var xmlNode = jpf.XMLDatabase.getBindXmlNode(xmlNode);
		
		//Type detection jsltNode
		if(typeof jsltNode == "object"){
			doTest = jsltNode.getAttribute("test") == "1";
			
			//check the jslt node for cache setting
			cacheId = jsltNode.getAttribute("cache");
			jsltFunc = this.cache[cacheId];
			if(!jsltFunc) jsltStr = jsltNode.selectSingleNode('text()').nodeValue
		}
		else{
			cacheId = jsltNode;
			jsltFunc = this.cache[cacheId];
			if(!jsltFunc) jsltStr = jsltNode;
		}
		
		//Compile string
		if(!jsltFunc)
			jsltFunc = this.compile(jsltStr);
		
		this.lastJslt = jsltStr;
		this.lastJs = jsltFunc[0]; //if it crashes here there is something seriously wrong
		
		//Invalid code - Syntax Error
		if(!jsltFunc[0]) return false;
		
		//Caching
		if(!cacheId){
			if(typeof jsltNode == "object"){
				cacheId = this.cache.push(jsltFunc) - 1
				jsltNode.setAttribute("cache", cacheId);
			}
			else this.cache[jsltStr] = jsltFunc;
		}
		
		//Execute JSLT
		try{
			if(!xmlNode) return '';
			
			var str = jsltFunc[0](xmlNode);
			if(doTest) alert(str);
			return str;
		}
		catch(e){
			jpf.status(jpf.formatJS(jsltFunc[1]));
			throw new Error(0, jpf.formErrorString(0, null, "JSLT parsing", "Could not execute JSLT with: " + e.message));
		}
	}
}
jpf.JsltInstance = new jpf.JsltImplementation();

/*FILEHEAD(/in/Core/Kernel/browsers/nonIE.js)SIZE(17832)TIME(1205790104099)*/
function runNonIe(){


/* ******** HTML Interfaces **************************************************
	insertAdjacentHTML(), insertAdjacentText() and insertAdjacentElement()
****************************************************************************/
if(typeof HTMLElement!="undefined"){
	if(!HTMLElement.prototype.insertAdjacentElement){
		HTMLElement.prototype.insertAdjacentElement = function(where,parsedNode){
			switch(where.toLowerCase()){
				case "beforebegin":
					this.parentNode.insertBefore(parsedNode,this);
					break;
				case "afterbegin":
					this.insertBefore(parsedNode,this.firstChild);
					break;
				case "beforeend":
					this.appendChild(parsedNode);
					break;
				case "afterend":
					if (this.nextSibling) this.parentNode.insertBefore(parsedNode,this.nextSibling);
					else this.parentNode.appendChild(parsedNode);
					break;
			}
		};
	}

	if(!HTMLElement.prototype.insertAdjacentHTML){
		HTMLElement.prototype.insertAdjacentHTML = function(where,htmlStr){
			var r = this.ownerDocument.createRange();
			r.setStartBefore(jpf.isSafari ? document.body : this);
			var parsedHTML = r.createContextualFragment(htmlStr);
			this.insertAdjacentElement(where,parsedHTML);
		}
	}

	if(!HTMLElement.prototype.insertAdjacentText){
		HTMLElement.prototype.insertAdjacentText = function(where,txtStr){
			var parsedText = document.createTextNode(txtStr);
			this.insertAdjacentElement(where,parsedText);
		}
	}
	
	//HTMLElement.removeNode
	HTMLElement.prototype.removeNode = function(){
		if(!this.parentNode) return;
		this.parentNode.removeChild(this);
	}
	
	//Currently only supported by Gecko
	if(HTMLElement.prototype.__defineSetter__){
		//HTMLElement.innerText
		HTMLElement.prototype.__defineSetter__("innerText", function(sText){
			var s = "" + sText;
			this.innerHTML = s.replace(/\&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
		});
	
		HTMLElement.prototype.__defineGetter__("innerText", function(){
			return this.innerHTML.replace(/<[^>]+>/g,"").replace(/\s\s+/g, " ").replace(/^\s*|\s*$/g, " ")
		});
		
		HTMLElement.prototype.__defineGetter__("outerHTML", function(){
			return (new XMLSerializer()).serializeToString(this);
		});
	}
}

/* ******** XML Compatibility ************************************************
	Giving the Mozilla XML Parser the same interface as IE's Parser
****************************************************************************/
var IEPREFIX4XSLPARAM = "";
var ASYNCNOTSUPPORTED = false;

//Test if Async is supported
try{
	XMLDocument.prototype.async = true;
	ASYNCNOTSUPPORTED = true;
}catch(e){/*trap*/} 

Document.prototype.onreadystatechange = null;
Document.prototype.parseError = 0;

Array.prototype.item = function(i){return this[i];};
Array.prototype.expr = "";

XMLDocument.prototype.readyState = 0;

XMLDocument.prototype.__clearDOM = function(){
	while(this.hasChildNodes())
		this.removeChild(this.firstChild);
}

XMLDocument.prototype.__copyDOM = function(oDoc){
	this.__clearDOM();
	
	if(oDoc.nodeType == 9 || oDoc.nodeType == 11){
	   var oNodes = oDoc.childNodes;

	   for(var i=0;i<oNodes.length;i++)
			this.appendChild(this.importNode(oNodes[i], true));
	}
	else if(oDoc.nodeType == 1)
   	this.appendChild(this.importNode(oDoc, true));
}

//XMLDocument.loadXML();
XMLDocument.prototype.loadXML = function(strXML){
	jpf.XMLDatabase.setReadyState(this, 1);
	var sOldXML = this.xml || this.serialize();
	var oDoc = (new DOMParser()).parseFromString(strXML, "text/xml");
	jpf.XMLDatabase.setReadyState(this, 2);
	this.__copyDOM(oDoc);
	jpf.XMLDatabase.setReadyState(this, 3);
	jpf.XMLDatabase.loadHandler(this);
	return sOldXML;
};

Node.prototype.getElementById = function(id){}

HTMLElement.prototype.replaceNode = 
Element.prototype.replaceNode = function(xmlNode){
	if(!this.parentNode) return;
	this.parentNode.insertBefore(xmlNode, this);
	this.parentNode.removeChild(this);
}

//XMLDocument.load
XMLDocument.prototype.__load = XMLDocument.prototype.load;
XMLDocument.prototype.load = function(sURI){
	var oDoc = document.implementation.createDocument("", "", null);
	oDoc.__copyDOM(this);
	this.parseError = 0;
	jpf.XMLDatabase.setReadyState(this, 1);

	try{
		if(this.async == false && ASYNCNOTSUPPORTED){
			var tmp = new XMLHttpRequest();
			tmp.open("GET", sURI, false);
			tmp.overrideMimeType("text/xml");
			tmp.send(null);
			jpf.XMLDatabase.setReadyState(this, 2);
			this.__copyDOM(tmp.responseXML);
			jpf.XMLDatabase.setReadyState(this, 3);
		}
		else this.__load(sURI);
	}
	catch(objException){this.parseError = -1;}
	finally{jpf.XMLDatabase.loadHandler(this);}

	return oDoc;
}



//Element.transformNodeToObject
Element.prototype.transformNodeToObject = function(xslDoc, oResult){
	var oDoc = document.implementation.createDocument("", "", null);
	oDoc.__copyDOM(this);
	oDoc.transformNodeToObject(xslDoc, oResult);
}

//Document.transformNodeToObject
Document.prototype.transformNodeToObject = function(xslDoc, oResult){
	var xsltProcessor = null;
	
	try{
		xsltProcessor = new XSLTProcessor();
		
		if(xsltProcessor.reset){
			// new nsIXSLTProcessor is available
			var xslDoc = jpf.getObject("XMLDOM", xslDoc.xml || xslDoc.serialize());
			xsltProcessor.importStylesheet(xslDoc);
			var newFragment = xsltProcessor.transformToFragment(this, oResult);
			oResult.__copyDOM(newFragment);
		}
		else{
		    // only nsIXSLTProcessorObsolete is available
		    xsltProcessor.transformDocument(this, xslDoc, oResult, null);
		}
	}
	catch(e){
		if(xslDoc && oResult)
			throw new Error(1043, jpf.formErrorString(1043, null, "XSLT Transformation", "Failed to transform document. \nInfo : " + e));
		else if(!xslDoc)
			throw new Error(1044, jpf.formErrorString(1044, null, "XSLT Transformation", "No Stylesheet Document was provided. \nInfo : " + e));
		else if(!oResult)
			throw new Error(1045, jpf.formErrorString(1045, null, "XSLT Transformation", "No Result Document was provided. \nInfo : " + e));
		else if(xsltProcessor == null)
			throw new Error(1046, jpf.formErrorString(1046, null, "XSLT Transformation", "Could not instantiate an XSLTProcessor object. \nInfo : " + e));
		else
			throw e;
	}
};

//Element.transformNode
Element.prototype.transformNode = function(xslDoc){
	return jpf.getObject("XMLDOM", this.xml || this.serialize()).transformNode(xslDoc);
}

//Document.transformNode
Document.prototype.transformNode = function(xslDoc){
	var xsltProcessor = new XSLTProcessor();
	var xslDoc = jpf.getObject("XMLDOM", xslDoc.xml || xslDoc.serialize());
	xsltProcessor.importStylesheet(xslDoc);
	var newFragment = xsltProcessor.transformToFragment(this, document.implementation.createDocument("", "", null));

	return newFragment.xml || newFragment.serialize()
	
	/*try{
		var serializer = new XMLSerializer();
		str = serializer.serializeToString(out);
	}
	catch(e){
		throw new Error(0, "---- Javeline Error ----\nProcess : XSLT Transformation\nMessage : Failed to serialize result document. \nInfo : " + e);
	}
	
	return str;*/
}



//XMLDocument.setProperty
HTMLDocument.prototype.setProperty = 
XMLDocument.prototype.setProperty = function(x,y){};

/* ******** XML Compatibility ************************************************
	Extensions to the XMLDatabase
****************************************************************************/
jpf.getObject = function(type, message, no_error){
	if(type == "HTTP"){
		if(jpf.availHTTP.length) return jpf.availHTTP.pop();
		return new XMLHttpRequest();
	}
	else if(type == "XMLDOM"){
		if(message){
			var xmlParser = new DOMParser();
			xmlParser = xmlParser.parseFromString(message, "text/xml");
			if(!no_error) this.xmlParseError(xmlParser);
		}
		else{
			var xmlParser = document.implementation.createDocument("", "", null);
		}
		
		return xmlParser;
	}
}

jpf.xmlParseError = function(xml){
	if(xml.documentElement.tagName == "parsererror"){
		var str = xml.documentElement.firstChild.nodeValue.split("\n");
		var linenr = str[2].match(/\w+ (\d+)/)[1];
		var message = str[0].replace(/\w+ \w+ \w+: (.*)/, "$1");
		
		var srcText = xml.documentElement.lastChild.firstChild.nodeValue.split("\n")[0];
		throw new Error(1050, jpf.formErrorString(1050, null, "XML Parse Error on line " +  linenr, message + "\nSource Text : " + srcText.replace(/\t/gi, " ")));
	}
	
	return xml;
}

if(jpf.XMLDatabaseImplementation){
	jpf.XMLDatabaseImplementation.prototype.htmlImport = function(xmlNode, htmlNode, beforeNode, test){
		if(!htmlNode) alert("No HTML node given in htmlImport:" + this.htmlImport.caller);
		
		if(xmlNode.length != null && !xmlNode.nodeType){
			for(var str='',i=0;i<xmlNode.length;i++) str += xmlNode[i].serialize();
			var str = str.replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/<([^>]+)\/>/g, "<$1></$1>");
			(beforeNode || htmlNode).insertAdjacentHTML(beforeNode ? "beforebegin" : "beforeend", str);

			return;
		}

		if(htmlNode.ownerDocument != document) return htmlNode.insertBefore(xmlNode, beforeNode);
		
		var strHTML = (xmlNode.outerHTML || (xmlNode.nodeType == 1 ? xmlNode.serialize() : xmlNode.nodeValue)).replace(/&lt;/g, "<").replace(/&gt;/g, ">");
		var pNode = (beforeNode || htmlNode);
		if(pNode.nodeType == 11){
			var id = xmlNode.getAttribute("id");
			if(!id) throw new Error(1049, jpf.formErrorString(1049, null, "XMLDatabase", "Inserting Cache Item in Document Fragment without an ID"));
			
			document.body.insertAdjacentHTML(beforeNode ? "beforebegin" : "beforeend", strHTML);
			pNode.appendChild(document.getElementById(id));
		}
		else{
			//firefox bug??
			if(xmlNode.tagName.match(/tbody|td|tr/)) pNode.insertBefore(pNode.ownerDocument.createElement(xmlNode.tagName.toLowerCase()), beforeNode || null);
			else pNode.insertAdjacentHTML(beforeNode ? "beforebegin" : "beforeend", strHTML);
		}
		
		//var retNode = beforeNode ? beforeNode.previousSibling : htmlNode.lastChild;
		//if(!retNode.tagName || retNode.tagName.toLowerCase() != xmlNode.tagName.toLowerCase()) debugger;
		
		return beforeNode ? beforeNode.previousSibling : htmlNode.lastChild;
	}
	
	jpf.XMLDatabaseImplementation.prototype.setReadyState = function(oDoc, iReadyState) {
		oDoc.readyState = iReadyState;
		if(oDoc.onreadystatechange != null && typeof oDoc.onreadystatechange == "function")
			oDoc.onreadystatechange();
	}
	
	jpf.XMLDatabaseImplementation.prototype.loadHandler = function(oDoc){
		if(!oDoc.documentElement || oDoc.documentElement.tagName == "parsererror")
			oDoc.parseError = -1;
		
		jpf.XMLDatabase.setReadyState(oDoc, 4);
	}
	
	//Initialize XMLDatabase
	jpf.XMLDatabase = new jpf.XMLDatabaseImplementation();
}

//Fix XML Data-Island Support Problem with Form Tag
jpf.Init.add(function(){
	var nodes = document.getElementsByTagName("form");
	for(var i=0;i<nodes.length;i++) nodes[i].removeNode();
	var nodes = document.getElementsByTagName("xml");
	for(var i=0;i<nodes.length;i++) nodes[i].removeNode();
	nodes = null;
});

//IE Like Error Handling
MAXMSG = 3;
ERROR_COUNT = 0;

/*window.onerror = function(message, filename, linenr){
	if(++ERROR_COUNT > MAXMSG) return;
	filename = filename ? filename.match(/\/([^\/]*)$/)[1] : "[Mozilla Library]";
	new Error(0, "---- Javeline Error ----\nProcess : Javascript code in '" + filename +  "'\nLine : " + linenr + "\nMessage : " + message);
	return false;
}*/

if(document.body) document.body.focus = function(){}

/*
//CurIndex = 0;
//CurValue is []
//FoundValue is []
//FoundNode is null
//Loop through childNodes
//if(Child is position absolute/relative and overflow == "hidden" && !inSpace) continue;

//if (Child is position absolute/relative and has zIndex) or overflow == "hidden"
	//if(!is position absolute/relative) zIndex = 0
	//if zIndex >= FoundValue[CurIndex] 
		//if zIndex > CurValue[CurIndex];
			//clear all CurValue values after CurIndex
			//set CurValue[CurIndex] = zIndex
		//CurIndex++
		//if(inSpace && CurIndex >= FoundValue.length)
			//Set FoundNode is currentNode
			//Set FoundValue is CurValue
	//else continue; //Ignore this treedepth
//else if CurValue[CurIndex] continue; //Ignore this treedepth

//loop through childnodes recursively
*/

if(!document.elementFromPoint){
	Document.prototype.elementFromPointRemove = function(el){
		if(!this.RegElements) return;
		this.RegElements.remove(el);
	}
	
	Document.prototype.elementFromPointAdd = function(el){
		if(!this.RegElements) this.RegElements = [];
		this.RegElements.push(el);
	}
	
	Document.prototype.elementFromPointReset = function(RegElements){
		//define globals
		FoundValue = [];
		FoundNode = null;
		LastFoundAbs = document.documentElement;
	}
	
	Document.prototype.elementFromPoint = function(x, y){
		// Optimization, Keeping last found node makes it ignore all lower levels 
		// when there is no possibility of changing positions and zIndexes
		/*if(self.FoundNode){
			var sx = getElementPosX(FoundNode); 
			var sy = getElementPosY(FoundNode);
			var ex = sx + FoundNode.offsetWidth; var ey = sy + FoundNode.offsetHeight;
		}
		if(!self.FoundNode || !(x > sx && x < ex && y > sy && y < ey))*/
			document.elementFromPointReset();
	
		// Optimization only looking at registered nodes
		if(this.RegElements){
			for(var calc_z=-1,calc,i=0;i<this.RegElements.length;i++){
				var n = this.RegElements[i];
				if(getStyle(n, "display") == "none") continue;
	
				var sx = getElementPosX(n); 
				var sy = getElementPosY(n);
				var ex = sx + n.offsetWidth; var ey = sy + n.offsetHeight;
				
				if(x > sx && x < ex && y > sy && y < ey){
					var z = getElementZindex(n);
					if(z > calc_z){ //equal z-indexes not supported
						calc = [n, x, y, sx, sy];
						calc_z = z;
					}
				}
			}
			
			if(calc){
				efpi(calc[0], calc[1], calc[2], 0, FoundValue, calc[3], calc[4]);
				if(!FoundNode){
					FoundNode = calc[0];
					LastFoundAbs = calc[0];
					FoundValue = [calc_z];
				}
			}
		}
		
		if(!this.RegElements || !this.RegElements.length)
			efpi(document.body, x, y, 0, [], getElementPosX(document.body), getElementPosY(document.body));
			
		return FoundNode;
	}
	
	function getStyle(el, prop) {
		return document.defaultView.getComputedStyle(el,'').getPropertyValue(prop);
	}
	
	function efpi(from, x, y, CurIndex, CurValue, px, py){
		var StartValue = CurValue;
		var StartIndex = CurIndex;
		
		//Loop through childNodes
		var nodes = from.childNodes;
		for(var n,i=0;i<from.childNodes.length;i++){
			n = from.childNodes[i];
			if( n.nodeType == 1 && getStyle(n, 'display') != 'none' && n.offsetParent){
				var sx = px + n.offsetLeft - n.offsetParent.scrollLeft;//getElementPosX(n); 
				var sy = py + n.offsetTop - n.offsetParent.scrollTop;//getElementPosY(n);
				var ex = sx + n.offsetWidth; var ey = sy + n.offsetHeight;
				
				//if(Child is position absolute/relative and overflow == "hidden" && !inSpace) continue;
				var isAbs = getStyle(n, "position");
				isAbs = isAbs == "absolute" || isAbs == "relative";
				var isHidden = getStyle(n, "overflow") == "hidden";
				var inSpace = (x > sx && x < ex && y > sy && y < ey);
				if(isAbs && isHidden && !inSpace) continue;
		
				CurIndex = StartIndex;
				CurValue = StartValue.copy();
		
				//if (Child is position absolute/relative and has zIndex) or overflow == "hidden"
				var z = parseInt(getStyle(n, "z-index")) || 0;
				if(isAbs && (z || z == 0) || isHidden){
					//if(!is position absolute/relative) zIndex = 0
					if(!isAbs) z = 0;
					
					//if zIndex >= FoundValue[CurIndex] 
					if(z >= (FoundValue[CurIndex] || 0)){
						//if zIndex > CurValue[CurIndex];
						if(z > (CurValue[CurIndex] || 0)){
							//CurValue = StartValue.copy();
							
							//set CurValue[CurIndex] = zIndex
							CurValue[CurIndex] = z;
						}
						
						CurIndex++;
						
						//if(inSpace && CurIndex >= FoundValue.length)
						if(inSpace && CurIndex >= FoundValue.length){
							//Set FoundNode is currentNode
							FoundNode = n;
							//Set FoundValue is CurValue
							FoundValue = CurValue;//.copy();
							
							LastFoundAbs = n;
						}
					}
					//else continue; //Ignore this treedepth
					else continue;
				}
				//else if CurValue[CurIndex] continue; //Ignore this treedepth
				//else if(CurValue[CurIndex]) continue;
				else if(inSpace && CurIndex >= FoundValue.length){
					//Set FoundNode is currentNode
					FoundNode = n;
					//Set FoundValue is CurValue
					FoundValue = CurValue;//.copy();
				}
				
				//loop through childnodes recursively
				efpi(n, x, y, CurIndex, CurValue, isAbs ? sx : px, isAbs ? sy : py)
			}
		}
	}
	
	function getElementPosY(myObj){return myObj.offsetTop + parseInt(jpf.compat.getStyle(myObj, "border-top-width")) + (myObj.offsetParent ? getElementPosY(myObj.offsetParent) : 0)}
	function getElementPosX(myObj){return myObj.offsetLeft + parseInt(jpf.compat.getStyle(myObj, "border-left-width")) + (myObj.offsetParent ? getElementPosX(myObj.offsetParent) : 0)}
	function getElementZindex(myObj){
		//This is not quite sufficient and should be changed
		var z = 0, n, p = myObj;
		while(p && p.nodeType == 1){
			z = Math.max(z, parseInt(getStyle(p, "z-index")) || -1);
			p = p.parentNode;
		}
		return z;
	}
}

jpf.Init.run('XMLDatabase');

}
/*FILEHEAD(/in/Core/Kernel/browsers/XPath.js)SIZE(14342)TIME(1203730484247)*/
function runXpath(){

/**
 *	Workaround for the lack of having an XPath parser on safari
 *	It works on Safari's document and XMLDocument object.
 *	
 *	It doesn't support the full XPath spec, but just enought for
 *	the skinning engine which needs XPath on the HTML document.
 *	
 *	Supports:
 *	- Compilation of xpath statements
 *	- Caching of XPath statements
 *
 * @parser
 */
jpf.XPath = {
	cache : {},
	
	getChildNode : function(htmlNode, tagName, info, count, num, sResult){
		var numfound = 0, result = null, data = info[count];

		var nodes = htmlNode.childNodes;
		if(!nodes) return; //Weird bug in Safari
		for(var i=0;i<nodes.length;i++){
			if(tagName && (tagName != nodes[i].tagName) && (nodes[i].style ? nodes[i].tagName.toLowerCase() : nodes[i].tagName) != tagName)  continue;// || numsearch && ++numfound != numsearch

			if(data) data[0](nodes[i], data[1], info, count+1, numfound++ , sResult);
			else sResult.push(nodes[i]);
		}
		
		//commented out :  && (!numsearch || numsearch == numfound)
	},
	
	doQuery : function(htmlNode, qData, info, count, num, sResult){
		var result = null, data = info[count];
		var query = qData[0];
		var returnResult = qData[1];
		try{var qResult = eval(query);}catch(e){return;}
		
		if(returnResult) return sResult.push(qResult);
		if(!qResult) return;
		
		if(data) data[0](htmlNode, data[1], info, count+1, 0, sResult);
		else sResult.push(htmlNode);
	},
	
	getTextNode : function(htmlNode, empty, info, count, num, sResult){
		var result = null, data = info[count];

		var nodes = htmlNode.childNodes;
		for(var i=0;i<nodes.length;i++){
			if(nodes[i].nodeType != 3 && nodes[i].nodeType != 4) continue;
			
			if(data) data[0](nodes[i], data[1], info, count+1, i, sResult);
			else sResult.push(nodes[i]);
		}
	},
	
	getAnyNode : function(htmlNode, empty, info, count, num, sResult){
		var result = null, data = info[count];

		var sel = [], nodes = htmlNode.childNodes;
		for(var i=0;i<nodes.length;i++){
			if(data) data[0](nodes[i], data[1], info, count+1, i, sResult);
			else sResult.push(nodes[i]);
		}
	},
	
	getAttributeNode : function(htmlNode, attrName, info, count, num, sResult){
		if(!htmlNode || htmlNode.nodeType != 1) return;
		
		var result = null, data = info[count];
		var value = htmlNode.getAttributeNode(attrName);//htmlNode.attributes[attrName];//

		if(data) data[0](value, data[1], info, count+1, 0, sResult);
		else if(value) sResult.push(value);
	},
	
	getAllNodes : function(htmlNode, x, info, count, num, sResult){
		var result = null, data = info[count];
		var tagName = x[0];
		var inclSelf = x[1];
		var prefix = x[2];

		if(inclSelf && (htmlNode.tagName == tagName || tagName == "*")){
			if(data) data[0](htmlNode, data[1], info, count+1, 0, sResult);
			else sResult.push(htmlNode);
		}

		var nodes = $(tagName, htmlNode, tagName==prefix?"":prefix);//htmlNode.getElementsByTagName(tagName);
		for(var i=0;i<nodes.length;i++){
			if(data) data[0](nodes[i], data[1], info, count+1, i, sResult);
			else sResult.push(nodes[i]);
		}
	},
	
	getAllAncestorNodes : function(htmlNode, x, info, count, num, sResult){
		var result = null, data = info[count];
		var tagName = x[0];
		var inclSelf = x[1];
		var prefix = x[2];
		
		var i = 0, s = inclSelf ? htmlNode : htmlNode.parentNode;
		while(s && s.nodeType == 1){
			if(s.tagName == tagName || tagName == "*" || tagName == "node()"){
				if(data) data[0](s, data[1], info, count+1, ++i, sResult);
				else sResult.push(s);
			}
			s = s.parentNode
		}
	},
	
	getParentNode : function(htmlNode, empty, info, count, num, sResult){
		var result = null, data = info[count];
		var node = htmlNode.parentNode;
		
		if(data) data[0](node, data[1], info, count+1, 0, sResult);
		else if(node) sResult.push(node);
	},
	
	//precsiblg[3] might not be conform spec
	getPrecedingSibling : function(htmlNode, tagName, info, count, num, sResult){
		var result = null, data = info[count];
		
		var node = htmlNode.previousSibling;
		while(node){
			if(tagName != "node()" && (node.style ? node.tagName.toLowerCase() : node.tagName) != tagName){
				node = node.previousSibling;
				continue;
			}
			
			if(data) data[0](node, data[1], info, count+1, 0, sResult);
			else if(node){
				sResult.push(node);
				break;
			}
		}
	},
	
	//flwsiblg[3] might not be conform spec
	getFollowingSibling : function(htmlNode, tagName, info, count, num, sResult){
		var result = null, data = info[count];
		
		var node = htmlNode.nextSibling;
		while(node){
			if(tagName != "node()" && (node.style ? node.tagName.toLowerCase() : node.tagName) != tagName){
				node = node.nextSibling;
				continue;
			}
			
			if(data) data[0](node, data[1], info, count+1, 0, sResult);
			else if(node){
				sResult.push(node);
				break;
			}
		}
	},
	
	multiXpaths : function(contextNode, list, info, count, num, sResult){
		for(var i=0;i<list.length;i++){
			var info = list[i][0];
			var rootNode = (info[3] ? contextNode.ownerDocument.documentElement : contextNode);//document.body
			info[0](rootNode, info[1], list[i], 1, 0, sResult);
		}
		
		sResult.makeUnique();
	},
	
	compile : function(sExpr){
		sExpr = sExpr.replace(/\[(\d+)\]/g, "/##$1");
		sExpr = sExpr.replace(/\|\|(\d+)\|\|\d+/g, "##$1");
		sExpr = sExpr.replace(/\.\|\|\d+/g, ".");
		sExpr = sExpr.replace(/\[([^\]]*)\]/g, function(match, m1){
			return "/##" + m1.replace(/\|/g, "_@_");
		}); //wrong assumption think of |

		if(sExpr == "/" || sExpr == ".") return sExpr;
		
		//Mark // elements
		//sExpr = sExpr.replace(/\/\//g, "/[]/self::");
		sExpr = sExpr.replace(/\/\//g, "descendant::");
		
		//Check if this is an absolute query
		return this.processXpath(sExpr);
	},
	
	processXpath : function(sExpr){
		var results = new Array();
		sExpr = sExpr.replace(/('[^']*)\|([^']*')/g, "$1_@_$2");
		sExpr = sExpr.split("\|");
		for(var i=0;i<sExpr.length;i++)
			sExpr[i] = sExpr[i].replace(/_\@\_/g, "|");//replace(/('[^']*)\_\@\_([^']*')/g, "$1|$2");
		
		if(sExpr.length == 1) sExpr = sExpr[0];
		else{
			for(var i=0;i<sExpr.length;i++) sExpr[i] = this.processXpath(sExpr[i]);
			results.push([this.multiXpaths, sExpr]);
			return results;
		}
		
		var isAbsolute = sExpr.match(/^\/[^\/]/);
		var sections = sExpr.split("/");
		for(var i=0;i<sections.length;i++){
			if(sections[i] == "." || sections[i] == "") continue;
			else if(sections[i].match(/^[\w-_\.]+(?:\:[\w-_\.]+){0,1}$/)) results.push([this.getChildNode, sections[i]]);//.toUpperCase()
			else if(sections[i].match(/^\#\#(\d+)$/)) results.push([this.doQuery, ["num+1 == " + parseInt(RegExp.$1)]]);
			else if(sections[i].match(/^\#\#(.*)$/)){
				
				//FIX THIS CODE
				var query = RegExp.$1;
				var m = [query.match(/\(/g), query.match(/\)/g)];
				if(m[0] || m[1]){
					while(!m[0] && m[1] || m[0] && !m[1] || m[0].length != m[1].length){
						if(!sections[++i]) break;
						query += "/" + sections[i];
						m = [query.match(/\(/g), query.match(/\)/g)];
					}
				}
				
				results.push([this.doQuery, [this.compileQuery(query)]]);
			}
			else if(sections[i] == "*") results.push([this.getChildNode, null]); //FIX - put in def function
			else if(sections[i].substr(0,2) == "[]") results.push([this.getAllNodes, ["*", false]]);//sections[i].substr(2) || 
			else if(sections[i].match(/descendant-or-self::node\(\)$/)) results.push([this.getAllNodes, ["*", true]]);
			else if(sections[i].match(/descendant-or-self::([^\:]*)(?:\:(.*)){0,1}$/)) results.push([this.getAllNodes, [RegExp.$2 || RegExp.$1, true, RegExp.$1]]);
			else if(sections[i].match(/descendant::([^\:]*)(?:\:(.*)){0,1}$/)) results.push([this.getAllNodes, [RegExp.$2 || RegExp.$1, false, RegExp.$1]]);
			else if(sections[i].match(/ancestor-or-self::([^\:]*)(?:\:(.*)){0,1}$/)) results.push([this.getAllAncestorNodes, [RegExp.$2 || RegExp.$1, true, RegExp.$1]]);
			else if(sections[i].match(/ancestor::([^\:]*)(?:\:(.*)){0,1}$/)) results.push([this.getAllAncestorNodes, [RegExp.$2 || RegExp.$1, false, RegExp.$1]]);
			else if(sections[i].match(/^\@(.*)$/)) results.push([this.getAttributeNode, RegExp.$1]);
			else if(sections[i] == "text()") results.push([this.getTextNode, null]);
			else if(sections[i] == "node()") results.push([this.getAnyNode, null]);//FIX - put in def function
			else if(sections[i] == "..") results.push([this.getParentNode, null]);
			else if(sections[i].match(/following-sibling::(.*)$/)) results.push([this.getFollowingSibling, RegExp.$1.toLowerCase()]);
			else if(sections[i].match(/preceding-sibling::(.*)$/)) results.push([this.getPrecedingSibling, RegExp.$1.toLowerCase()]);
			else if(sections[i].match(/self::(.*)$/)) results.push([this.doQuery, ["jpf.XPath.doXpathFunc('local-name', htmlNode) == '" + RegExp.$1 + "'"]]);
			else{
				var query = sections[i];
			
				//FIX THIS CODE
				//add some checking here
				var m = [query.match(/\(/g), query.match(/\)/g)];
				if(m[0] || m[1]){
					while(!m[0] && m[1] || m[0] && !m[1] || m[0].length != m[1].length){
						if(!sections[++i]) break;
						query += "/" + sections[i];
						m = [query.match(/\(/g), query.match(/\)/g)];
					}
				}

				results.push([this.doQuery, [this.compileQuery(query), true]])
			
				//throw new Error(1503, "---- Javeline Error ----\nMessage : Could not match XPath statement: '" + sections[i] + "' in '" + sExpr + "'");
			}
		}

		results[0][3] = isAbsolute;
		return results;
	},
	
	compileQuery : function(code){
		var c = new jpf.CodeCompilation(code);
		return c.compile();
	},
	
	doXpathFunc : function(type, arg1, arg2, arg3){
		switch(type){
			case "not": return !arg1;
			case "position()": return num == arg1;
			case "format-number": return jpf.formatNumber(arg1); //this should actually do something
			case "floor": return Math.floor(arg1);
			case "ceiling": return Math.ceil(arg1);
			case "starts-with": return arg1 ? arg1.substr(0, arg2.length) == arg2 : false;
			case "string-length": return arg1 ? arg1.length : 0;
			case "count": return arg1 ? arg1.length : 0;
			case "last": return arg1 ? arg1[arg1.length-1] : null;
			case "local-name": return arg1 ? arg1.tagName : "";//[jpf.TAGNAME]
			case "substring": return arg1 && arg2 ? arg1.substring(arg2, arg3 || 0) : "";
			case "contains": return arg1 && arg2 ? arg1.indexOf(arg2) > -1 : false;
			case "concat": 
				for(var str="",i=1;i<arguments.length;i++){
					if(typeof arguments[i] == "object"){
						str += getNodeValue(arguments[i][0]);
						continue;
					}
					str += arguments[i];
				}
			return str;
		}
	},
	
	selectNodeExtended : function(sExpr, contextNode, match){
		var sResult = this.selectNodes(sExpr, contextNode);

		if(sResult.length == 0) return null;
		if(!match) return sResult[0];
		
		for(var i=0;i<sResult.length;i++){
			if(getNodeValue(sResult[i]) == match) return sResult[i];
		}
		
		return null;
	},
	
	selectNodes : function(sExpr, contextNode){
		if(!this.cache[sExpr]) this.cache[sExpr] = this.compile(sExpr);
		
		//jpf.status("Processing custom XPath: " + sExpr + ":" + contextNode.serialize().replace(/</g, "&lt;"));
		
		if(typeof this.cache[sExpr] == "string"){
			if(this.cache[sExpr] == ".") return [contextNode];
			if(this.cache[sExpr] == "/") return [contextNode.nodeType == 9 ? contextNode : contextNode.ownerDocument.documentElement];
		}

		if(typeof this.cache[sExpr] == "string" && this.cache[sExpr] == ".") return [contextNode];
		
		var info = this.cache[sExpr][0];
		var rootNode = (info[3] && !contextNode.nodeType == 9 ? contextNode.ownerDocument.documentElement : contextNode);//document.body
		var sResult = [];

		info[0](rootNode, info[1], this.cache[sExpr], 1, 0, sResult);
		
		return sResult;
	}
}

function getNodeValue(sResult){
	if(sResult.nodeType == 1) return sResult.firstChild ? sResult.firstChild.nodeValue : "";
	if(sResult.nodeType > 1 || sResult.nodeType < 5) return sResult.nodeValue;
	return sResult;
}

/**
 * @constructor
 * @private
 */
jpf.CodeCompilation = function(code){
	this.data = {
		F : [],
		S : [],
		I : [],
		X : []
	};
	
	this.compile = function(){
		code = code.replace(/ or /g, " || ");
		code = code.replace(/ and /g, " && ");
		code = code.replace(/!=/g, "{}");
		code = code.replace(/=/g, "==");
		code = code.replace(/\{\}/g, "!=");
		
		// Tokenize
		this.tokenize();
		
		// Insert
		this.insert();

		return code;
	}
	
	this.tokenize = function(){
		//Functions
		var data = this.data.F;
		code = code.replace(/(format-number|contains|substring|local-name|last|node|position|round|starts-with|string|string-length|sum|floor|ceiling|concat|count|not)\s*\(/g, function(d, match){return (data.push(match) - 1) + "F_";});

		//Strings
		var data = this.data.S;
		code = code.replace(/'([^']*)'/g, function(d, match){return (data.push(match) - 1) + "S_";});
		code = code.replace(/"([^"]*)"/g, function(d, match){return (data.push(match) - 1) + "S_";});

		//Xpath
		var data = this.data.X;
		code = code.replace(/(^|\W|\_)([\@\.\/A-Za-z][\.\@\/\w]*(?:\(\)){0,1})/g, function(d, m1, m2){return m1 + (data.push(m2) - 1) + "X_";});
		code = code.replace(/(\.[\.\@\/\w]*)/g, function(d, m1, m2){return (data.push(m1) - 1) + "X_";});
		
		//Ints
		var data = this.data.I; 
		code = code.replace(/(\d+)(\W)/g, function(d, m1, m2){return (data.push(m1) - 1) + "I_" + m2;});
	}
	
	this.insert = function(){
		var data = this.data;
		code = code.replace(/(\d+)X_\s*==\s*(\d+S_)/g, function(d, nr, str){
			return "jpf.XPath.selectNodeExtended('" +  data.X[nr].replace(/'/g, "\\'") + "', htmlNode, " + str + ")";
		});
		
		code = code.replace(/(\d+)([FISX])_/g, function(d, nr, type){
			var value = data[type][nr];
			
			if(type == "F"){
				return "jpf.XPath.doXpathFunc('" + value + "', ";
			}
			else if(type == "S"){
				return "'" + value + "'";	
			}
			else if(type == "I"){
				return value;
			}
			else if(type == "X"){
				return "jpf.XPath.selectNodeExtended('" + value.replace(/'/g, "\\'") + "', htmlNode)";
			}
		});
	}
}

}
/*FILEHEAD(/in/Core/Kernel/browsers/XSLT.js)SIZE(8100)TIME(1203730484247)*/
function runXslt(){

/**
 * @constructor
 * @parser
 */
jpf.XSLTProcessor = function(){
	this.templates = {};
	this.p = {
		"value-of" : function(context, xslNode, childStack, result){
			var xmlNode = jpf.XPath.selectNodes(xslNode.getAttribute("select"), context)[0];// + "[0]"

			if(!xmlNode) value = "";
			else if(xmlNode.nodeType == 1) value = xmlNode.firstChild ? xmlNode.firstChild.nodeValue : "";
			else value = typeof xmlNode == "object" ? xmlNode.nodeValue : xmlNode;
			
			result.appendChild(this.xmlDoc.createTextNode(value));
		},
		
		"copy-of" : function(context, xslNode, childStack, result){
			var xmlNode = jpf.XPath.selectNodes(xslNode.getAttribute("select"), context)[0];// + "[0]"
			if(xmlNode) result.appendChild(jpf.canImportNode ? result.ownerDocument.importNode(xmlNode, true) : xmlNode.cloneNode(true));
		},
		
		"if" : function(context, xslNode, childStack, result){
			if(jpf.XPath.selectNodes(xslNode.getAttribute("test"), context)[0]){// + "[0]"
				this.parseChildren(context, xslNode, childStack, result);
			}
		},
		
		"for-each" : function(context, xslNode, childStack, result){
			var nodes = jpf.XPath.selectNodes(xslNode.getAttribute("select"), context);
			for(var i=0;i<nodes.length;i++){
				this.parseChildren(nodes[i], xslNode, childStack, result);
			}
		},
		
		"choose" : function(context, xslNode, childStack, result){
			var nodes = xslNode.childNodes;
			for(var i=0;i<nodes.length;i++){
				if(!nodes[i].tagName) continue;
				
				if(nodes[i][jpf.TAGNAME] == "otherwise" || nodes[i][jpf.TAGNAME] == "when" && jpf.XPath.selectNodes(nodes[i].getAttribute("test"), context)[0])
					return this.parseChildren(context, nodes[i], childStack[i][2], result);
			}
		},
		
		"output" : function(context, xslNode, childStack, result){
			
		},
		
		"param" : function(context, xslNode, childStack, result){
			
		},
		
		"attribute" : function(context, xslNode, childStack, result){
			var nres = this.xmlDoc.createDocumentFragment();
			this.parseChildren(context, xslNode, childStack, nres);
			
			result.setAttribute(xslNode.getAttribute("name"), nres.xml);
		},
		
		"apply-templates" : function(context, xslNode, childStack, result){
			if(!xslNode){
				var t = this.templates["/"] || this.templates[context.tagName];
				if(t) this.parseChildren(t == this.templates["/"] ? context.ownerDocument : context, t[0], t[1], result);
			}
			else if(xslNode.getAttribute("select")){
				var t = this.templates[xslNode.getAttribute("select")];
				if(t){
					if(xslNode.getAttribute("select") == "/") return alert("Something went wrong. The / template was executed as a normal template");
					
					var nodes = context.selectNodes(xslNode.getAttribute("select"));
					for(var i=0;i<nodes.length;i++){
						this.parseChildren(nodes[i], t[0], t[1], result);
					}
				}
			}
			//Named templates should be in a different hash
			else if(xslNode.getAttribute("name")){
				var t = this.templates[xslNode.getAttribute("name")];
				if(t) this.parseChildren(context, t[0], t[1], result);
			}
			else{
				//Copy context
				var ncontext = context.cloneNode(true); //importnode here??
				var nres = this.xmlDoc.createDocumentFragment();
				
				var nodes = ncontext.childNodes;
				for(var tName, i=nodes.length-1;i>=0;i--){
					if(nodes[i].nodeType == 3 || nodes[i].nodeType == 4){
						//result.appendChild(this.xmlDoc.createTextNode(nodes[i].nodeValue));
						continue;
					}
					if(!nodes[i].nodeType == 1) continue;
					var n = nodes[i];

					//Loop through all templates
					for(tName in this.templates){
						if(tName == "/") continue;
						var t = this.templates[tName];
						
						var snodes = n.selectNodes("self::" + tName);
						for(var j=snodes.length-1;j>=0;j--){
							var s = snodes[j], p = s.parentNode;
							this.parseChildren(s, t[0], t[1], nres);
							if(nres.childNodes){
								for(var k=nres.childNodes.length-1;k>=0;k--){
									p.insertBefore(nres.childNodes[k], s);
								}
							}
							p.removeChild(s);
						}
					}
					
					if(n.parentNode){
						var p = n.parentNode;
						this.p["apply-templates"].call(this, n, xslNode, childStack, nres);
						if(nres.childNodes){
							for(var k=nres.childNodes.length-1;k>=0;k--){
								p.insertBefore(nres.childNodes[k], n);
							}
						}
						p.removeChild(n);
					}
				}
				
				for(var i=ncontext.childNodes.length-1;i>=0;i--){
					result.insertBefore(ncontext.childNodes[i], result.firstChild);
				}
			}
		},
		
		cache : {},
		"import" : function(context, xslNode, childStack, result){
			var file = xslNode.getAttribute("href");
			if(!this.cache[file]){
				var data = new jpf.http().get(file, false, true);
				this.cache[file] = data;
			}
			
			//compile
			//parseChildren
		},
		
		"include" : function(context, xslNode, childStack, result){
			
		},
		
		"when" : function(){},
		"otherwise" : function(){},
		
		"copy-clone" : function(context, xslNode, childStack, result){
			result = result.appendChild(jpf.canImportNode ? result.ownerDocument.importNode(xslNode, false) : xslNode.cloneNode(false));
			if(result.nodeType == 1){
				for(var i=0;i<result.attributes.length;i++){
					var blah = result.attributes[i].nodeValue; //stupid Safari shit

					if(!jpf.isSafariOld && result.attributes[i].nodeName.match(/^xmlns/)) continue;
					result.attributes[i].nodeValue = result.attributes[i].nodeValue.replace(/\{([^\}]+)\}/g, function(m, xpath){
						var xmlNode = jpf.XPath.selectNodes(xpath, context)[0];
						
						if(!xmlNode) value = "";
						else if(xmlNode.nodeType == 1) value = xmlNode.firstChild ? xmlNode.firstChild.nodeValue : "";
						else value = typeof xmlNode == "object" ? xmlNode.nodeValue : xmlNode;
						
						return value;
					});
					
					result.attributes[i].nodeValue; //stupid Safari shit
				}
			}
			
			this.parseChildren(context, xslNode, childStack, result);
		}
	}
	
	this.parseChildren = function(context, xslNode, childStack, result){
		if(!childStack) return;
		for(var i=0;i<childStack.length;i++){
			childStack[i][0].call(this, context, childStack[i][1], childStack[i][2], result);
		}
	}
	
	this.compile = function(xslNode){
		var nodes = xslNode.childNodes;
		for(var stack=[],i=0;i<nodes.length;i++){
			if(nodes[i].nodeType != 1 && nodes[i].nodeType != 3 && nodes[i].nodeType != 4) continue;
			
			if(nodes[i][jpf.TAGNAME] == "template"){
				this.templates[nodes[i].getAttribute("match") || nodes[i].getAttribute("name")] = [nodes[i], this.compile(nodes[i])];
			}
			else if(nodes[i][jpf.TAGNAME] == "stylesheet"){
				this.compile(nodes[i])
			}
			else if(nodes[i].prefix == "xsl"){
				var func = this.p[nodes[i][jpf.TAGNAME]];
				if(!func) alert("xsl:" + nodes[i][jpf.TAGNAME] + " is not supported at this time on this platform");
				else stack.push([func, nodes[i], this.compile(nodes[i])]);
			}
			else{
				stack.push([this.p["copy-clone"], nodes[i], this.compile(nodes[i])]);
			}
		}
		return stack;
	}
	
	this.importStylesheet = function(xslDoc){
		this.xslDoc = xslDoc.nodeType == 9 ? xslDoc.documentElement : xslDoc;
		xslStack = this.compile(xslDoc);

		//var t = this.templates["/"] ? "/" : false;
		//if(!t) for(t in this.templates) if(typeof this.templates[t] == "array") break;
		this.xslStack = [[this.p["apply-templates"], null]];//{getAttribute : function(n){if(n=="name") return t}
	}
	
	//return nodes
	this.transformToFragment = function(doc, newDoc){
		this.xmlDoc = newDoc.nodeType != 9 ? newDoc.ownerDocument : newDoc;//new DOMParser().parseFromString("<xsltresult></xsltresult>", "text/xml");//
		var docfrag = this.xmlDoc.createDocumentFragment();

		if(!jpf.isSafariOld && doc.nodeType == 9) doc = doc.documentElement;
		var result = this.parseChildren(doc, this.xslDoc, this.xslStack, docfrag);
		return docfrag;
	}
}

self.XSLTProcessor = jpf.XSLTProcessor;

}
/*FILEHEAD(/in/Core/Kernel/Class.js)SIZE(14232)TIME(1203730484247)*/

/**
 * BaseClass for any JavaScript Class offering property binding, event handling, constructor and destructor hooks.
 *
 * @classDescription		This class creates a new class
 * @return {Class} Returns a new class
 * @type {Class}
 * @constructor
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.8
 */
jpf.Class = function(){
	this.__jmlLoaders = [];
	this.__addJmlLoader = function(func){
		if(!this.__jmlLoaders) func.call(this, this.jml);
		else this.__jmlLoaders.push(func);
	}
	
	this.__jmlDestroyers = [];
	this.__addJmlDestroyer = function(func){this.__jmlDestroyers.push(func);}
	
	this.__regbase = 0;
	this.hasFeature = function(test){return this.__regbase&test}

	/* ***********************
		PROPERTY BINDING
	************************/
	
	
	var boundObjects = {};
	var myBoundPlaces = {}
	
	/*for(var i=0;i<this.__supportedProperties.length;i++){
		var p = uCaseFirst(this.__supportedProperties[i]);
		this["set" + p] = function(prop){return function(value){
			this.setProperty(prop, value);
		}}(this.__supportedProperties[i]);
		
		this["get" + p] = function(prop){return function(){
			return this.getProperty(prop);
		}}(this.__supportedProperties[i]);
	}*/
	
	/**
	 * Bind a property of another compontent to a property of this component.
	 *
	 * @param  {String}  myProp  required  String specifying the name of the property of this component of which the value is communicated to <code>bObject</code>.
	 * @param  {Class}  bObject   required  Instance of Class which will receive the property change message.
	 * @param  {String}  bProp  required  String specifying property of <code>bObject</code> which will be set using the value of <code>myProp</code> optionally processed using <code>strDynamicProp</code>.
	 * @param  {String}  strDynamicProp  optional  String specifying a JavaScript statement which contains the value of <code>myProp</code>. The string is used to calculate a new value.
	 */
	this.bindProperty = function(myProp, bObject, bProp, strDynamicProp){
		//#--ifdef 1
		if(!boundObjects[myProp]) boundObjects[myProp] = {};
		if(!boundObjects[myProp][bObject.uniqueId]) boundObjects[myProp][bObject.uniqueId] = [];
		
		if(boundObjects[myProp][bObject.uniqueId].contains(bProp)){
			throw new Error(0, jpf.formErrorString(0, this, "Property-binding", "Already bound " + bObject.name + "." + bProp + " to " + myProp));
		}
		
		if(strDynamicProp) boundObjects[myProp][bObject.uniqueId].push([bProp, strDynamicProp]);
		else boundObjects[myProp][bObject.uniqueId].pushUnique([bProp]); //The new array is always unique... or what?
		/* #--else
		
		if(!boundObjects[myProp]) boundObjects[myProp] = [];
		boundObjects[myProp].push([bObject, bProp, strDynamicProp]);
		
		#--endif */
		
		bObject.handlePropSet(bProp, strDynamicProp ? eval(strDynamicProp) : this[myProp]);
	}
	
	/**
	 * Remove the binding of a property of another compontent to a property of this component.
	 *
	 * @param  {String}  myProp  required  String specifying the name of the property of this component for which the property bind was registered.
	 * @param  {Class}  bObject   required  Instance of Class which received the property change message.
	 * @param  {String}  bProp  required  String specifying property of <code>bObject</code>.
	 */
	this.unbindProperty = function(myProp, bObject, bProp){
		//#--ifdef 1
		boundObjects[myProp][bObject.uniqueId].remove(bProp);
		/* #--else
		
		if(!boundObjects[myProp]) return;
		for(var i=0;i<boundObjects[myProp].length;i++){
			if(boundObjects[myProp][0] == bObject && boundObjects[myProp][1] == bProp){
				return boundObjects[myProp].removeIndex(i);
			}
		}
		
		#--endif */
	}
	
	/**
	 * Unbinds all bound properties for this componet.
	 */
	this.unbindAllProperties = function(){
		var prop;
		for(prop in myBoundPlaces){
			//Remove any bounds if relevant
			if(myBoundPlaces[prop] && typeof myBoundPlaces[prop] != "function"){
				for(var i=0;i<myBoundPlaces[prop].length;i++){
					if(!self[myBoundPlaces[prop][i][0]]) continue;
					self[myBoundPlaces[prop][i][0]].unbindProperty(myBoundPlaces[prop][i][1], this, prop);
				}
			}
		}
	}
	
	/**
	 * Gets an array of properties for this component which can be bound.
	 */
	this.getAvailableProperties = function(){
		return this.__supportedProperties.copy();
	}
	
	/**
	 * Sets a dynamic property from a string
	 * The string used for this function is the same as used in JML to set a dynamic property:
	 * <j:Button visible="{rbTest.value == 'up'}" />
	 *
	 * @param  {String}  prop  required  String specifying the name of the property of this component to set using a dynamic rule.
	 * @param  {String}  pValue  required  String specifying the dynamic property binding rule.
	 */
	this.setDynamicProperty = function(prop, pValue){
		//pValue.match(/^([{\[])(.*)[}\]]$/); // Find dynamic or calculated property
		var pStart = pValue.substr(0,1);

		var y = pValue.substr(pValue.length-1,1);
		if(pStart == "[" && y != "]" || pStart == "{" && y != "}" ){
			throw new Error(0, jpf.formErrorString(0, this, "Dynamic Property Binding", "Invalid binding found: " + pValue));	
		}
		
		//Remove any bounds if relevant
		if(myBoundPlaces[prop]){
			for(var i=0;i<myBoundPlaces[prop].length;i++){
				self[myBoundPlaces[prop][i][0]].unbindProperty(myBoundPlaces[prop][i][1], this, prop);
			}
		}

		//Two Way property binds
		if(pStart == "["){
			var p = pValue.substr(1,pValue.length-2).split(".");
			if(!self[p[0]]) return; 
			if(!p[1]) p[1] = self[p[0]].__supportedProperties[0]; // Default state property
			
			//Two way property binding
			self[p[0]].bindProperty(p[1], this, prop); myBoundPlaces[prop] = [p];
			this.bindProperty(prop, self[p[0]], p[1]);
		}
		
		//One Way Dynamic Properties
		else if(pStart == "{"){
			var p, matches = {}, pValue = pValue.substr(1,pValue.length-2);
			pValue.replace(/["'](?:\\.|[^"']+)*["']|\/(?:\\.|[^\/\\]+)*\/|(?:\W|^)([a-z]\w+\.\w+)(?!\()(?:\W|$)/g, function(m, m1){if(m1) matches[m1] = true;});
			pValue = pValue.replace(/\Wand\W/g, "&&").replace(/\Wor\W/g, "||");//.replace(/\!\=|(\=)/g, function(m, m1){if(!m1) return m; return m1+"="})
			myBoundPlaces[prop] = [];
			for(p in matches){
				if(typeof matches[p] == "function") continue;
				
				var o = p.split(".");
				if(!self[o[0]] || !self[o[0]].bindProperty) continue;  //return
				
				self[o[0]].bindProperty(o[1], this, prop, pValue); myBoundPlaces[prop].push(o); 
			}
			
		}
		else this.handlePropSet(prop, pValue);
	}
	
	
	/**
	 * Sets the value of a property of this component.
	 * Note: Only the value is set, dynamic properties will remain bound and the value will be overridden.
	 *
	 * @param  {String}  prop   required  String specifying the name of the property of this component to set using a dynamic rule.
	 * @param  {String}  value   required  String specifying the value of the property to set.
	 * @param  {Boolean}  reqValue  optional  When set to true and <code>value</code> is null the method will return.
	 * @param  {Boolean}  forceOnMe  optional  When set to true the function will set the property even though its the same value.
	 */
	this.setProperty = function(prop, value, reqValue, forceOnMe){
		if(reqValue && !value) return;

		if(this[prop] !== value){
			var oldvalue = this[prop];
			if(this.handlePropSet(prop, value, forceOnMe) === false){
				this[prop] = oldvalue;
				return false;
			}
		}
		
		
		var nodes = boundObjects[prop];
		if(!nodes) return;

		//#--ifdef 1
		var id, ovalue = value;
		for(id in nodes){
			if(jpf.isSafari && (typeof nodes[id] != "object" || !nodes[id])) continue;
			
			for(var o=jpf.lookup(id),i=nodes[id].length-1;i>=0;--i){
				try{
					value = nodes[id][i][1] ? eval(nodes[id][i][1]) : ovalue;
				}catch(e){
					throw new Error(0, jpf.formErrorString(0, this, "Property-binding", "Could not execute binding test: " + nodes[id][i][1]));
				}

				if(o[nodes[id][i][0]] != value)
					o.setProperty(nodes[id][i][0], value);//__handlePropSet
			}
		}
		/* #--else
		
		for(var i=0;i<nodes.length;i++){
			try{
				nodes[i][0].handlePropSet(nodes[i][1], nodes[i][2] ? eval(nodes[i][2]) : value);
			}catch(e){}
		}
		#--endif */
		
	}
	
	/**
	 * Gets the value of a property of this component.
	 *
	 * @param  {String}  prop   required  String specifying the name of the property of this component for which to get the value.
	 */
	this.getProperty = function(prop){
		return this[prop];
	}
	
	/* ***********************
		EVENT HANDLING
	************************/
	
	var events_stack = {};
	/**
	 * Calls all functions associated with the event.
	 *
	 * @param  {String}  eventName  required  String specifying the name of the event to dispatch.
	 * @return  {variant}  return value of the event
	 */
	this.dispatchEvent = function(eventName, data, e){
		var result, retValue;
		
		
		if(!e) e = new jpf.Event(eventName, data);
		if(!eventName) eventName = e.name; //maybe remove this???
		
		if(this.disabled) result = false;
		else{
			var arr = events_stack[eventName];
			
			if(arr && arr.length || this[eventName]){
				//for(var args=[],i=1;i<arguments.length;i++) args.push(arguments[i]);
				if(this[eventName]) result = this[eventName].call(this, e); //Backwards compatibility
				
				if(arr){
					for(var i=0;i<arr.length;i++){
						retValue = arr[i].call(this, e);
						if(retValue != undefined) result = retValue;
					}
				}
			}
		}
		
		if(e.canBubble()){
			var el = this.parentNode || jpf.document;
			retValue = el.dispatchEvent(eventName, null, e);


			if(retValue != undefined) result = retValue;
		}
		
		return e.returnValue !== undefined ? e.returnValue : result;
	}
	
	/**
	 * Add a function to be called when a event is called.
	 *
	 * @param  {String}  eventName    required  String specifying the name of the event for which to register a function.
	 * @param  {function}  func  required  Function to be called when event is dispatched.
	 */
	this.addEventListener = function(eventName, func){
		if(!events_stack[eventName]) events_stack[eventName] = [];
		events_stack[eventName].pushUnique(func);
	}
	
	/**
	 * Remove a function registered for an event.
	 *
	 * @param  {String}  eventName    required  String specifying the name of the event for which to unregister a function.
	 * @param  {function}  func  required  Function to be removed from the event.
	 */
	this.removeEventListener = function(eventName, func){
		if(events_stack[eventName]) events_stack[eventName].remove(func);
	}
	
	/**
	 * Checks if there is an event listener specified for the event.
	 *
	 * @param  {String}  eventName    required  String specifying the name of the event to check.
	 * @return  {Boolean}  Boolean specifying wether the event has listeners
	 */
	this.hasEventListener = function(eventName){
		return events_stack[eventName] && events_stack[eventName].length > 0;
	}
	
	/**
	 * Destructor of a Class.
	 * Calls all destructor functions and removes all mem leaking references.
	 * This function is called when exiting the application or closing the window.
	 */
	this.destroy = function(){
		if(!this.uniqueId) return;
		
		if(this.__destroy) this.__destroy();
		
		for(var i=this.__jmlDestroyers.length-1;i>=0;i--)
			this.__jmlDestroyers[i].call(this);
		this.__jmlDestroyers = undefined;
		
		if(this.oExt && !this.oExt.isNative && this.oExt.nodeType == 1){
			this.oExt.oncontextmenu = null;
			this.oExt.host = null;
		}
		if(this.oInt && !this.oExt.isNative && this.oInt.nodeType == 1) this.oInt.host = null;
		
		this.jml = null;
		
		// Remove from jpf.all
		jpf.all[this.uniqueId] = null;
		this.uniqueId = null;
	}
	
	/**
	 * Removes all the registrations of this component.
	 * Call this function to runtime remove this component.
	 */
	this.destroySelf = function(){
		if(!this.hasFeature) return;
		
		//Update JMLDOMApi as well
		
		// Remove id from global js space
		if(this.name) self[this.name] = null;
	
		// Remove from window.onresize - Should be in Anchoring or Alignment
		if(this.hasFeature(__ANCHORING__)) this.disableAnchoring();
		if(this.hasFeature(__ALIGNMENT__)) this.disableAlignment();
		
		// Remove dynamic properties - Should be in Class (clear events???)
		this.unbindAllProperties();
		
		// Remove data connections - Should be in DataBinding
		if(this.dataParent) this.dataParent.parent.disconnect(this);
		if(this.hasFeature(__DATABINDING__)){
			this.unloadBindings();
			this.unloadActions();
		}
		if(this.hasFeature(__DRAGDROP__))
			this.unloadDragDrop();
		
		// Remove from focus list - Should be in JmlNode
		if(this.focussable) jpf.window.__removeFocus(this);
		
		// Remove from multilang list listener (also on skin switching) - Should be in MultiLang
		if(this.hasFeature(__MULTILANG__)) this.__removeEditable();
		
		//Remove all cached Items - Should be in Cache
		if(this.hasFeature(__CACHE__)) this.clearAllCache();
		
		if(this.childNodes){
			for(var i=0;i<this.childNodes.length;i++){
				if(this.childNodes[i].destroySelf)
					this.childNodes[i].destroySelf();
				else
					jpf.removeNode(this.childNodes[i].oExt);
			}
		}
		
		if(this.destroy) this.destroy();
	}
}

/**
 * @constructor
 */
jpf.Event = function(name, data){
	this.name = name;
	jpf.extend(this, data); //ughh - 
	
	this.cancelBubble = false;
	//this.returnValue = undefined;
	
	this.canBubble = function(){
		return !this.cancelBubble && this.bubbleEvents[this.name];
	}
}
jpf.Event.prototype.bubbleEvents = {"onerror":true};

/*FILEHEAD(/in/Core/Kernel/Debug.js)SIZE(18950)TIME(1213483123975)*/

jpf.vardump = function(obj, depth, recur){
	if(!obj) return obj + "";
	if(!depth) depth = 0;

	switch(obj.dataType){
		case "string":	return "\"" + obj + "\"";
		case "number":	return obj;
		case "boolean": return obj ? "true" : "false";
		case "date": return "Date[" + new Date() + "]";
		case "array":
			var str = "{\n";
			for(var i=0;i<obj.length;i++){
				str += "     ".repeat(depth+1) + i + " => " + (!recur && depth > 0 ? typeof obj[i] : jpf.vardump(obj[i], depth+1, !recur)) + "\n";
			}
			str += "     ".repeat(depth) + "}";
			
			return str;
		default:
			if(typeof obj == "function") return "function";
			if(obj.xml) return depth==0 ? "[ " + obj.xml + " ]" : "XML Element";
			if(!recur && depth>0) return "object";
		
			//((typeof obj[prop]).match(/(function|object)/) ? RegExp.$1 : obj[prop])
			var str = "{\n";
			for(prop in obj){
				try{
					str += "     ".repeat(depth+1) + prop + " => " + (!recur && depth > 0? typeof obj[prop] : jpf.vardump(obj[prop], depth+1, !recur)) + "\n";
				}catch(e){
					str += "     ".repeat(depth+1) + prop + " => [ERROR]\n";
				}
			}
			str += "     ".repeat(depth) + "}";
			
			return str;
	}
}

jpf.alert_r = function(obj, recur){
	alert(jpf.vardump(obj, null, !recur));
}

jpf.ProfilerClass = function(){
	this.totalTime = 0;
	
	this.start = function(clear){
		if(clear) this.totalTime = 0;
		this.startTime = new Date();
		
		this.isStarted = true;
	}
	
	this.stop = 
	this.end = function(){
		if(!this.startTime) return;
		var startTime = this.startTime;
		var endTime = new Date();
		this.totalTime += (endTime.getMinutes()-startTime.getMinutes())*60000+(endTime.getSeconds()-startTime.getSeconds())*1000+(endTime.getMilliseconds()-startTime.getMilliseconds());
		
		this.isStarted = false;
	}
	
	this.addPoint = function(msg){
		this.end();
		jpf.status("[TIME] " + msg + ": " + this.totalTime + "ms");
		this.start(true);
	}
};

jpf.Profiler = new jpf.ProfilerClass();//backward compatibility

jpf.DebugInfoStack = [];

Function.prototype.toHTMLNode = function(highlight){
	var code, line1, line2;
	
	TYPE_OBJECT = "object";
	TYPE_NUMBER = "number";
	TYPE_STRING = "string";
	TYPE_ARRAY = "array";
	TYPE_DATE = "date";
	TYPE_REGEXP = "regexp";
	TYPE_BOOLEAN = "boolean";
	TYPE_FUNCTION = "function";
	TYPE_DOMNODE = "dom node";
	TYPE_JAVNODE = "Javeline Component";
	
	STATE_UNDEFINED = "undefined";
	STATE_NULL = "null";
	STATE_NAN = "nan";
	STATE_INFINITE = "infinite";

	/**
	 * @private
	 */
	function getType(variable){
		if(variable === null) return STATE_NULL;
		if(variable === undefined) return STATE_UNDEFINED;
		if(typeof variable == "number" && isNaN(variable)) return STATE_NAN;
		if(typeof variable == "number" && !isFinite(variable)) return STATE_INFINITE;

	
		if(typeof variable == "object"){
			if(variable.hasFeature) return TYPE_JAVNODE;
			if(variable.tagName || variable.nodeValue) return TYPE_DOMNODE;
		}
		
		if(variable.dataType == undefined) return TYPE_OBJECT;
		
		return variable.dataType;
	}
	
	//anonymous
	code = this.toString();
	endLine1 = code.indexOf("\n"); 
	line1 = code.slice(0, endLine1);
	line2 = code.slice(endLine1+1);
	
	res = /^function(\s+(.*?)\s*|\s*?)\((.*)\)(.*)$/.exec(line1);
	if(res){
		var name = res[1];
		var args = res[3];
		var last = res[4];

		if(this.arguments){
			var argName, namedArgs = args.split(",");
			args = [];

			for(var i=0;i<this.arguments.length;i++){
				//if(i != 0 && arr[i]) args += ", ";
				argName = (namedArgs[i].trim() || "__NOT_NAMED__");// args += "<b>" + arr[i] + "</b>";
				
				var info = ["Name: " + argName];
				var id = jpf.DebugInfoStack.push(info) - 1;
				
				args.push("<a href='javascript:void(0)' onclick='alert(jpf.DebugInfoStack[" + id + "].join(\"\\n\"));event.cancelBubble=true;'>" + argName + "</a>");
				info.push("Type: " + getType(this.arguments[i]));
				info.push("Value: " + jpf.vardump(this.arguments[i], null, true));
			}	
		}

		line2 = line2.replace(/\{/ , "");
		line2 = line2.substr(0, line2.length-2);

		if(!highlight){
			line2 = line2.replace(/ /g, "&nbsp;");
			line2 = line2.replace(/\t/g, "&nbsp;&nbsp;&nbsp;");
			line2 = line2.replace(/\n/g, "</nobr><br><nobr>&nbsp;&nbsp;&nbsp;");
			line2 = "{<br><nobr>&nbsp;&nbsp;&nbsp;" + line2 + "</nobr><br>}";
		}
		else{
			line2 = "{\n" + line2 + "\n}\n";
			var div = dp.SyntaxHighlighter.HighlightString(line2, false, false);
		}
		
		var d = document.createElement("div");
		res = "<div><div style='padding:0px 0px 2px 0px;cursor:default;' onclick='obj = this.lastChild.style;if(obj.display == \"block\"){obj.display = \"none\";this.firstChild.firstChild.src=\"images/debug/arrow_right.gif\"}else{obj.display = \"block\";this.firstChild.firstChild.src=\"images/debug/arrow_down.gif\"};event.cancelBubble=true'><nobr><img width='9' height='9' src='images/debug/arrow_right.gif' style='margin:0 3px 0 2px;' />"+(name.trim()||"function")+"("+args.join(", ")+")&nbsp;</nobr><div onclick='event.cancelBubble=true' onselectstart='event.cancelBubble=true' style='cursor:text;display:none;padding:0px;background-color:#EAEAEA;color:#222222;overflow:auto;margin-top:2px;'><blockquote></blockquote></div></div></div>";
		d.innerHTML = res;
		var b = d.getElementsByTagName("blockquote")[0];
		
		if(highlight){
			b.replaceNode(div);
		}
		else{
			b.insertAdjacentHTML("beforeBegin", line2);
			b.parentNode.removeChild(b);
		}

		return d.firstChild;
	}
	else{
		return this.toString();
	}
}

/* *****************
** Error Handler **
******************/

jpf.debugwin = {
	useDebugger : jpf.getcookie("debugger") == "true",
	
	init : function(){
		if(jpf.getcookie("highlight") == "true" && self.BASEPATH){
			//<script class="javascript" src="../Library/Core/Highlighter/shCore.uncompressed.js"></script>
			//<script class="javascript" src="../Library/Core/Highlighter/shBrushJScript.js"></script>
			jpf.include(BASEPATH + "Library/Core/Highlighter/shCore.uncompressed.js");	
			jpf.include(BASEPATH + "Library/Core/Highlighter/shBrushJScript.js");	
			//<link type="text/css" rel="stylesheet" href="../Library/Core/Highlighter/SyntaxHighlighter.css" />
			jpf.loadStylesheet(BASEPATH + "Library/Core/Highlighter/SyntaxHighlighter.css");
		}
		else if(self.SyntaxHighlighterCSS){
			jpf.importCssString(document, SyntaxHighlighterCSS);	
		}
		else{
			jpf.setcookie("highlight", false)
		}

		if(!this.useDebugger) window.onerror = function(message, filename, linenr){return jpf.debugwin.errorHandler(message, filename, linenr)};
		
		if(!this.useDebugger && (jpf.isOpera || jpf.isSafari)){
			self.Error = function(nr, msg){
				jpf.debugwin.errorHandler(msg, location.href, 0);
			}
		}
	},

	show : function(e, filename, linenr){
		var list = [], seen = {};
		
		//Opera doesnt support caller... weird...
		try{
			var loop = end = jpf.isIE ? this.show.caller.caller : this.show.caller.caller ? this.show.caller.caller.caller : this.show.caller.caller;
			if(loop){
				try{
					do{
						if(seen[loop.toString()]) break; //recursion checker
						seen[loop.toString()] = true;
						//str += loop.toHTML();
						list.push(loop.toHTMLNode(jpf.getcookie("highlight") == "true"));
						loop = loop.caller;
					}while(list.length < 30 && loop && loop.caller && loop.caller.caller != loop);
				}catch(a){
					list=[];	
				}
			}
		}
		catch(e){}
		
		errorInfo = "Exception caught on line " + linenr + " in file " + filename + "<br>Message: " + e.message;
			
		e.lineNr = linenr;
		e.fileName = filename;
	
		this.createWindow(e, list, errorInfo);//str
		
		//window.onerror = function(){window.onerror=null;return true}
		//throw new Error(0, "Stopping Error Prosecution");
	},

	createWindow : function (e, stackTrace, errorInfo){;
		if(!jpf.debugwin.win){
			var elError = jpf.debugwin.win = document.getElementById("javerror");
			if(!elError){
				if(document.body){
					elError = document.body.appendChild(document.createElement("div"));
					elError.id = "javerror";
				}
				else{
					document.write("<div id='javerror'></div>");
					elError = document.getElementById("javerror");
				}
				
				elError.style.position = jpf.supportFixedPosition ? "fixed" : "absolute";
		 		elError.style.zIndex = 10000000;
				elError.style.right = "10px";
				elError.style.top = "10px";
				elError.style.border = "2px outset";//solid #65863a
				elError.style.textAlign = "left";
				elError.style.MozBorderBottomColors = "black gray";
				elError.style.MozBorderRightColors = "black gray";
				elError.style.MozBorderTopColors = "#C0C0C0 #FFFFFF";
				elError.style.MozBorderLeftColors = "#C0C0C0 #FFFFFF";
				elError.style.padding = "10px";
				elError.style.width = "600px";
				elError.style.background = "#dfdfdf";
				
				jpf.importCssString(document, "#cbTW, #cbHighlight, #toggledebug{float:left} #override #javerror{letter-spacing:0;font-family:Arial} #javerror label{padding:5px 0 0 1px;width:auto;}");
			}
			
			document.body.style.display = "block";
			
			elError.style.display = "block";
			var parse = e.message.split(/\n===\n/);
			var errorMessage = parse[0].replace(/---- Javeline Error ----\n/g, "").replace(/</g, "&lt;").replace(/Message: \[(\d+)\]/g, "Message: [<a title='Visit the manual on error code $1' style='color:blue;text-decoration:none;' target='_blank' href='http://developer.javeline.net/projects/platform/wiki/ErrorCodes#$1'>$1</a>]").replace(/(\n|^)([\w ]+:)/gm, "$1<strong>$2</strong>").replace(/\n/g, "<br />");
			var jmlContext = jpf.formatXML(parse[1] ? parse[1].trim(true) : "").replace(/</g, "&lt;").replace(/\n/g, "<br />").replace(/\t/g, "&nbsp;&nbsp;&nbsp;");;
	
			elError.innerHTML = 
				"<div style='width:106px;height:74px;background:url(images/debug/platform_logo.gif) no-repeat;position:absolute;right:20px;top:5px;'></div><span onmouseover='this.style.backgroundColor=\"white\"' onmouseout='this.style.backgroundColor=\"#EEEEEE\"' onclick='this.parentNode.style.display=\"none\"' style='cursor:hand;cursor:pointer;float:right;margin:0px;font-size:8pt;font-family:Verdana;width:14px;text-align:center;height:14px;overflow:hidden;border:1px solid gray;color:gray;background-color:#EEEEEE;padding:0'>X</span><h1 style='width:353px;height:26px;background:url(images/debug/debug_title.gif) no-repeat;margin:0 0 6px 0;'></h1>" +
				"<div onselectstart='event.cancelBubble=true' style='border:1px solid black;padding:4px;font-family:Arial;font-size:10pt;background-color:white;margin-bottom:5px;'>" + errorMessage + "</div>" + 
				(jmlContext ? "<div style='cursor:default;border:1px solid gray;padding:4px;font-family:MS Sans Serif;font-size:8pt;background-color:#eaeaea;margin-bottom:1px;' onclick='obj = this.lastChild.style;if(obj.display == \"block\"){obj.display = \"none\";this.firstChild.src=\"images/debug/arrow_right.gif\"}else{obj.display = \"block\";this.firstChild.src=\"images/debug/arrow_down.gif\"}'><img width='9' height='9' src='images/debug/arrow_down.gif' />&nbsp;<strong>Javeline Markup Language</strong><br /><div onclick='event.cancelBubble=true' onselectstart='event.cancelBubble=true' style='border:1px solid red;cursor:text;background:white url(images/debug/shadow.gif) no-repeat 0 0;padding:4px 4px 20px 4px;font-size:9pt;font-family:Courier New;margin:3px;border:1px solid gray;max-height:200px;white-space:nowrap;overflow:auto;'>" + jmlContext + "</div></div>" : "") +
				"<div style='cursor:default;border:1px solid gray;padding:4px;font-family:MS Sans Serif;font-size:8pt;background-color:#eaeaea;margin-bottom:1px;' onclick='obj = this.lastChild.style;if(obj.display == \"block\"){obj.display = \"none\";this.firstChild.src=\"images/debug/arrow_right.gif\"}else{obj.display = \"block\";this.firstChild.src=\"images/debug/arrow_down.gif\"};'><div style='margin-right:5px;float:right;margin-top:-4px;'><input id='cbHighlight' type='checkbox' onclick='jpf.debugwin.toggleHighlighting(this.checked);event.cancelBubble = true;' " + (jpf.getcookie("highlight") == "true" ? "checked='checked'" : "") + "/><label for='cbHighlight' style='top:4px;position:relative;' onclick='event.cancelBubble=true'>Enable Syntax Coloring</label></div><img width='9' height='9' src='images/debug/arrow_right.gif' />&nbsp;<strong>Stack Trace</strong><br /><div style='display:none;background:white url(images/debug/shadow.gif) no-repeat 0 0;padding:4px;font-size:9pt;font-family:Courier New;margin:3px;border:1px solid gray;'><blockquote></blockquote></div></div>" +
				"<div style='cursor:default;border:1px solid gray;padding:4px;font-family:MS Sans Serif;font-size:8pt;background-color:#eaeaea;margin-bottom:1px;' onclick='obj = this.lastChild.style;if(obj.display == \"block\"){obj.display = \"none\";this.firstChild.nextSibling.src=\"images/debug/arrow_right.gif\"}else{obj.display = \"block\";this.firstChild.nextSibling.src=\"images/debug/arrow_down.gif\";this.lastChild.scrollTop=this.lastChild.scrollHeight};'><div style='margin-right:5px;float:right;margin-top:-4px;'><input id='cbTW' type='checkbox' onclick='jpf.debugwin.toggleLogWindow(this.checked);event.cancelBubble = true;' " + (jpf.getcookie("viewinwindow") == "true" ? "checked='checked'" : "") + "/><label for='cbTW' style='top:4px;position:relative;' onclick='event.cancelBubble=true'>View in window</label></div><img width='9' height='9' src='images/debug/arrow_right.gif' />&nbsp;<strong>Log Viewer</strong><br /><div id='jvlnviewlog' onclick='event.cancelBubble=true' onselectstart='event.cancelBubble=true' style='display:none;height:150px;overflow:auto;cursor:text;background:white url(images/debug/shadow.gif) no-repeat 0 0;padding:4px;font-size:9pt;font-family:Courier New;margin:3px;border:1px solid gray;'>" + jpf.debugInfo.replace(/\n/g, "<br />") + "</div></div>" +
				"<div style='cursor:default;border:1px solid gray;padding:4px;font-family:MS Sans Serif;font-size:8pt;background-color:#eaeaea;margin-bottom:1px;' onclick='obj = this.lastChild.style;if(obj.display == \"block\"){obj.display = \"none\";this.firstChild.src=\"images/debug/arrow_right.gif\"}else{obj.display = \"block\";this.firstChild.src=\"images/debug/arrow_down.gif\";this.lastChild.firstChild.focus()};'><img width='9' height='9' src='images/debug/arrow_right.gif' />&nbsp;<strong>Javascript console</strong><br /><div style='display:none' onclick='event.cancelBubble=true'><textarea onkeydown='if(event.keyCode == 9){this.nextSibling.focus();event.cancelBubble=true;return false;}' onselectstart='event.cancelBubble=true' style='background:white url(images/debug/shadow.gif) no-repeat 0 0;padding:4px;font-size:9pt;font-family:Courier New;margin:3px;border:1px solid gray;width:575px;height:100px;'>" + jpf.getcookie("jsexec") + "</textarea><button onclick='jpf.debugwin.jRunCode(this.previousSibling.value)' style='font-family:MS Sans Serif;font-size:8pt;margin:0 0 0 3px;' onkeydown='if(event.shiftKey && event.keyCode == 9){this.previousSibling.focus();event.cancelBubble=true;return false;}'>Execute</button></div></div>" +
				"<br style='line-height:5px'/><input id='toggledebug' type='checkbox' onclick='jpf.debugwin.toggleDebugger(this.checked)' /><label for='toggledebug' style='position:relative;top:4px;font-family:MS Sans Serif;font-size:8pt;'>Use browser's debugger</label><div style='width:97px;height:18px;background:url(images/debug/javeline_logo.gif) no-repeat;position:absolute;right:16px;bottom:11px;'></div>"
			var b = elError.getElementsByTagName("blockquote")[0];
			//" || "No stacktrace possible").replace(/\n/g, "<br />") + "
			if(stackTrace.length){
				for(var i=0;i<stackTrace.length;i++)
					b.parentNode.insertBefore(stackTrace[i], b);
				b.parentNode.removeChild(b);
			}
			else b.replaceNode(document.createTextNode("No stacktrace possible"));
			
			jpf.ondebug = function(str){
				var logView = document.getElementById("jvlnviewlog");
				if(!logView) return;
				
				logView.insertAdjacentHTML("beforeend", str);
				logView.style.display = "block";
				logView.scrollTop = logView.scrollHeight;
			}
			
			clearInterval(jpf.Init.interval);
			ERROR_HAS_OCCURRED = true;
		}
	},
	
	jRunCode : function(code){
		jpf.setcookie("jsexec", code);
		
		if(jpf.debugwin.useDebugger){
			var x = eval(code) || "";
			try{jpf.status(x.toString().replace(/</g, "&lt;").replace(/\n/g, "<br />"));}catch(e){jpf.status(x ? "Could not serialize object" : x)}
		}
		else{
			try{
				var x = eval(code) || "";
				try{jpf.status(x.toString().replace(/</g, "&lt;").replace(/\n/g, "<br />"));}catch(e){jpf.status(x ? "Could not serialize object" : x)}
			}
			catch(e){jpf.status("[ERROR] " + e.message)}
		}
	},
	
	toggleLogWindow : function (checked){
		if(checked){
			jpf.debugType = "window";
			jpf.win = window.open("", "debug");
			jpf.win.document.write(jpf.debugInfo);
		}
		else jpf.debugType = "memory";
		
		if(jpf.setcookie) jpf.setcookie("viewinwindow", checked)
	},
	
	toggleHighlighting : function (checked){
		jpf.setcookie("highlight", checked);
	},

	toggleDebugger : function(checked){
		this.useDebugger = checked;
	
		if(jpf.setcookie) jpf.setcookie("debugger", checked)
		
		if(!checked) window.onerror = this.errorHandler;
		else window.onerror = null; 
	},
	
	errorHandler : function(message, filename, linenr){
		if(!message) message = "";
		e = {
			message : "js file: [line: " + linenr + "] " + jpf.removePathContext(jpf.hostPath, filename) + "\n" + message
		}
		
		jpf.status("[ERROR on line " + linenr + "]:<br />" + message.split(/\n\n===\n/)[0].replace(/</g, "&lt;").replace(/\n/g, "<br />") + "<br />");
		this.show(e, filename, linenr);
		
		return true;
	},
	
	activate : function(msg){
		jpf.debugwin.toggleDebugger(false);

		if(document.getElementById("javerror")) document.getElementById("javerror").style.display = "block";
		else jpf.debugwin.errorHandler(msg || "User forced debug window to show", location.href, 0);//setTimeout('throw new Error(0, "User initiated error");');
	}
}

jpf.showDebugWindow = function(){
	jpf.debugwin.activate();
}

jpf.ondebugkey = function(keyCode, ctrlKey, shiftKey, altKey){
	//ctrlKey && keyCode == 71 || ctrlKey && altKey && keyCode == 68
	if(keyCode == 120 || ctrlKey && altKey && keyCode == 68){
		jpf.debugwin.activate();
	}
}
/*FILEHEAD(/in/Core/Kernel/ECMAext.js)SIZE(8156)TIME(1203730484247)*/
/* ******** OBJECT EXTENSIONS *********
	Fix Browser Incompatibility and
	implement extra functionalities
	like inheritence etc
*************************************/

/*Function.prototype.inherit = function(classRef){
	this.prototype = (classRef instanceof Function ? new classRef() : classRef);
}*/

jpf.parseUri = function(sourceUri){
    var uriPartNames = ["source","protocol","authority","domain","port","path","directoryPath","fileName","query","anchor"];
    var uriParts = new RegExp("^(?:([^:/?#.]+):)?(?://)?(([^:/?#]*)(?::(\\d*))?)?((/(?:[^?#](?![^?#/]*\\.[^?#/.]+(?:[\\?#]|$)))*/?)?([^?#/]*))?(?:\\?([^#]*))?(?:#(.*))?").exec(sourceUri);
    var uri = {};
    
    for(var i = 0; i < 10; i++){
        uri[uriPartNames[i]] = (uriParts[i] ? uriParts[i] : "");
    }
    
    // Always end directoryPath with a trailing backslash if a path was present in the source URI
    // Note that a trailing backslash is NOT automatically inserted within or appended to the "path" key
    if(uri.directoryPath.length > 0){
        uri.directoryPath = uri.directoryPath.replace(/\/?$/, "/");
    }
    
    return uri;
}

jpf.extend = function(dest){
	for(var i=1;i<arguments.length;i++){
		var src = arguments[i];
		for(var prop in src) dest[prop] = src[prop];
	}
	return dest;
}

jpf.formatNumber = function(nr){
	var str = new String(Math.round(parseFloat(nr)*100)/100).replace(/(\.\d?\d?)$/, function(m1){return m1.pad(3, "0", PAD_RIGHT)});
	if(str.indexOf(".") == -1) str += ".00";
	return str;
}

jpf.unserialize = function (str){
	if(!str) return str;
	eval("var data = " + str);
	return data;
}


jpf.isNull = function(value){
	if(value) return false;
	return (value == null || !String(value).length);
}

jpf.isArray = function(o){
	return (o && typeof o == "object" && o.length);
}

jpf.isTrue = function(c){
	return c === true || c === "true" || c === "on" || typeof c == "number" && c > 0 || c === "1";
}

jpf.isFalse = function(c){
	return c === false || c === "false" || c === "off" || c === 0 || c === "0";
}

jpf.isNot = function(c){
	// a var that is null, false, undefined, Infinity, NaN and c isn't a string
	return (!c && typeof c != "string" && c !== 0 || (typeof c == "number" && !isFinite(c)));
}

jpf.copyObject = function(o){
	var rv = new Object();
	for(prop in o) rv[prop] = o[prop];
	return rv;
}

jpf.copyArray = function(ar, Type){
	if(!ar) return ar;
	for(var car=[], i=0;i<ar.length;i++)
		car[i] = Type ? new Type(ar[i]) : ar[i];

	return car;
}

jpf.getAbsolutePath = function(base, src){
	return src.match(/^\w+\:\/\//) ? src : base + src;
}

jpf.removePathContext = function(base, src){
	if(!src) return "";
	if(src.indexOf(base) > -1) return src.substr(base.length);
	return src;
}

if(!self.isFinite){
	function isFinite(val){return val+1!=val;}
}

Array.prototype.copy = function(){
	var ar = new Array();
	for(var i=0;i<this.length;i++)
		ar[i] = this[i] && this[i].copy ? this[i].copy() : this[i];

	return ar;
}

Array.prototype.arrayAdd = function(){
	var s = this.copy();
	for(var i=0;i<arguments.length;i++){
		for(var j=0;j<s.length;j++){
			s[j] += arguments[i][j];
		}
	}

	return s;
}

Array.prototype.equals = function(obj){
	for(var i=0;i<this.length;i++) if(this[i] != obj[i]) return false;
	return true;
}

Array.prototype.makeUnique = function(){
	var newArr = [];
	for(var i=0;i<this.length;i++)
		if(!newArr.contains(this[i])) newArr.push(this[i]);

	this.length = 0;
	for(var i=0;i<newArr.length;i++)
		this.push(newArr[i]);
}

Array.prototype.contains = function(obj){
	for(var i=0;i<this.length;i++) if(this[i] == obj) return true;
	return false;
}

Array.prototype.indexOf = function(obj){
	for(var i=0;i<this.length;i++) if(this[i] == obj) return i;
	return -1;
}

Array.prototype.pushUnique = function(item){
	if(!this.contains(item)) this.push(item);
}

Array.prototype.search = function(){
	for(var i=0;i<arguments.length;i++){
		if(typeof this[i] != "array") continue;
		for(var j=0;j<arguments.length;j++){
			if(this[i][j] != arguments[j]) break;
			else if(j == arguments.length-1) return this[i];
		}
	}
}

//Mac workaround...
if(!Function.prototype.call){
	Function.prototype.call = function(obj, arg1, arg2, arg3){
		obj.tf = this;
		var rv = obj.tf(arg1, arg2, arg3);
		obj.tf = null;
		return rv;
	}
}

/*Object.prototype.runEvent = function(eventname, arg1, arg2, arg3){
	if(this[eventname]) this[eventname](arg1, arg2, arg3);
}*/

Array.prototype.remove = function(obj){
	for(var i=0;i<this.length;i++){
		if(this[i] != obj) continue;

		for(var j=i;j<this.length;j++)
			this[j] = this[j+1];
		this.length--;
		i--;
	}
}

Array.prototype.removeIndex = function(i){
	if(!this.length) return;
	
	for(var j=i;j<this.length;j++)
		this[j] = this[j+1];
	this.length--;
}

Array.prototype.insertIndex = function(obj, i){
	for(var j=this.length;j>=i;j--)
		this[j] = this[j-1];
	
	this[i] = obj;
}

Array.prototype.invert = function(){
	var l = this.length-1;
	for(var temp,i=0;i<Math.ceil(0.5*l);i++){
		temp = this[i];
		this[i] = this[l-i]
		this[l-i] = temp;
	}
	
	return this;
}

if(!Array.prototype.push){
	Array.prototype.push = function(item){
		this[this.length] = item;
		return this.length;
	}
}

if(!Array.prototype.pop){
	Array.prototype.pop = function(item){
		var item = this[this.length-1];
		delete this[this.length-1];
		this.length--;
		return item;
	}
}

if(!Array.prototype.shift){
	Array.prototype.shift = function(){
		var item = this[0];
		for(var i=0;i<this.length;i++) this[i] = this[i+1];
		this.length--;
		return item;
	}
}

if(!Array.prototype.join){
	Array.prototype.join = function(connect){
		for (var str = "", i=0;i<this.length;i++)
			str += this[i] + (i < this.length-1 ? connect : "");
		return str;
	}
}

Math.hexlist = "0123456789ABCDEF";
Math.decToHex = function(value){
	var hex = this.floor(value/16);
	hex = (hex >15 ? this.decToHex(hex) : this.hexlist.charAt(hex));

	return hex + "" + this.hexlist.charAt(this.floor(value%16));
}
Math.hexToDec = function(value){
	if(!/(.)(.)/.exec(value.toUpperCase())) return false;
	return this.hexlist.indexOf(RegExp.$1) * 16 + this.hexlist.indexOf(RegExp.$2);
}

String.prototype.uCaseFirst = function (str){return this.substr(0,1).toUpperCase() + this.substr(1)};
String.prototype.trim = function (){return this.replace(/\s*$/, "").replace(/^\s*/, "");}
String.prototype.repeat = function (times){for(var out="",i=0;i<times;i++) out += this;return out;}
String.prototype.count = function(str){return this.split(str).length-1;}
String.prototype.pad = function(l, s, t){
	return s || (s = " "), (l -= this.length) > 0 ? (s = new Array(Math.ceil(l / s.length)
		+ 1).join(s)).substr(0, t = !t ? l : t == 1 ? 0 : Math.ceil(l / 2))
		+ this + s.substr(0, l - t) : this;
};
PAD_LEFT = 0;
PAD_RIGHT = 1;
PAD_BOTH = 2;

jpf.formatXML = function(output){
	output = output.trim();

	var lines = output.split("\n");
	for(var i=0;i<lines.length;i++) lines[i] = lines[i].trim();
	lines = lines.join("\n").replace(/\>\r\n/g, ">").replace(/\>/g, ">\n").replace(/\n\</g, "<").replace(/\</g, "\n<").split("\n");
	lines.removeIndex(0);//test if this is actually always fine
	lines.removeIndex(lines.length);
	
	for(var depth=0,i=0;i<lines.length;i++)
		lines[i] = "\t".repeat((lines[i].match(/^\s*\<\//) ? --depth :  (lines[i].match(/^\s*\<[^\?][^>]+[^\/]\>/) ? depth++ : depth))) + lines[i];

	return lines.join("\n");
}

jpf.formatJS = function(x){
	var d=0;
	return x.replace(/;+/g,';').replace(/;}/g,'}').replace(/{;/g,'{').replace(/({)|(})|(;)/g,function(m,a,b,c){
		if(a)d++;if(b)d--;
		var o='';for(var i=0;i<d;i++)o+='\t\t';
		if(a)return '{\n'+o; if(b)return '\n'+o+'}';if(c)return ';\n'+o;
	}).replace(/\>/g,'&gt;').replace(/\</g,'&lt;');
}

jpf.pasteWindow = function(str){
	var win = window.open("about:blank");	
	win.document.write(str);
}

jpf.htmlentities = function(str){
	return str.replace(/</g, "&lt;");
}

jpf.html_entity_decode = function(str){
	return str.replace(/\&\#38;/g, "&").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&amp;/g, "&").replace(/&nbsp;/g, " ");
}

/*FILEHEAD(/in/Core/Kernel/History.js)SIZE(2905)TIME(1213547348372)*/

//Check out RSH
jpf.History = {
	inited : false,
	page : null,
	
	init : function(name){
		this.inited = true;
		this.hasChanged(name);
		
		if(jpf.isIE){
			var str = "<style>BODY, HTML{margin : 0;}h1{height : 100px;margin : 0;padding : 0;}</style><body><h1 id='" + name + "'>0</h1></body><script>var lastURL = -1;if(document.all){document.body.onscroll = checkUrl;}else{setInterval('checkUrl()', 200);}function checkUrl(){var nr=Math.round((document.all ? document.body : document.documentElement).scrollTop/100);top.jpf.History.hasChanged(document.getElementsByTagName('h1')[nr].id);lastURL = document.body.scrollTop;}checkUrl();</script>";
			if(top == self){
				document.body.insertAdjacentHTML("beforeend","<iframe name='nav' style2='position:absolute;left:10px;top:10px;height:100px;width:100px;z-index:1000' style='width:1px;height:1px;' src='about:blank'></iframe>");
				document.frames["nav"].document.open();
				document.frames["nav"].document.write(str);
				document.frames["nav"].document.close();
			}
			
			this.iframe = document.frames["nav"];// : document.getElementById("nav").contentWindow;
			
			//Check to see if url has been manually changed
			this.timer = setInterval(function(){
				status = jpf.History.changingHash;
				if(!jpf.History.changingHash && location.hash != "#" + jpf.History.page){
					jpf.History.hasChanged(location.hash.replace(/^#/, ""));
				}
			}, 200);
		}
		else{
			jpf.History.lastUrl = location.href;
			this.timer = setInterval(function(){
				if(jpf.History.lastUrl == location.href) return;
				
				jpf.History.lastUrl = location.href;
				var page = location.href.replace(/^.*#(.*)$/, "$1")
				jpf.History.hasChanged(page);
			}, 20);
		}
	},
	
	addPoint : function(name, timed){
		if(this.changing || this.page == name || location.hash == "#" + name) return;

		if(jpf.isIE && !timed)
			setTimeout(function(){jpf.History.addPoint(name, true);}, 300);
		
		this.changePage(name);
		if(!this.inited) return this.init(name);
		
		if(jpf.isIE){
			//var h = (jpf.isIE ? this.iframe.document:document).body.appendChild((jpf.isIE ? this.iframe.document:document).createElement('span'));
			var h = this.iframe.document.body.appendChild(this.iframe.document.createElement('h1'));
			h.id = name;
			h.innerHTML = this.length;
		};

		(jpf.isIE ? this.iframe : window).location.href = "#" + name;

		if(!jpf.isIE) History.lastUrl = location.href;
	},
	
	changePage : function(page){
		if(jpf.isIE){
			this.page = page;
			this.changingHash = true;
			setTimeout(function(){location.hash = page; jpf.History.changingHash = false;}, 300);
		}
	},
	
	hasChanged : function(page){
		if(page == this.page) return;
		this.changePage(page);
		
		this.changing = true;
		if(this.onchange) this.onchange(page);
		this.changing = false;
	}
}

/*FILEHEAD(/in/Core/Kernel/Patches.js)SIZE(16592)TIME(1203730484247)*/

jpf.compat = {
	maxWidth : 0,
	maxHeight : 0,
	
	getNumber : function(pos){
		return (/^\d+/.exec(pos) ? parseInt(RegExp.$1) : 0)
	},
	
	getBox : function(value){
		if(value == null || (!parseInt(value) && parseInt(value) != 0)) return [0,0,0,0];

		var x = value.split(" ");
		for(var i=0;i<x.length;i++) x[i]=parseInt(x[i]) || 0;
		switch(x.length){
			case 1:x[1]=x[0];x[2]=x[0];x[3]=x[0];break;
			case 2:x[2]=x[0];x[3]=x[1];break;
			case 3:x[3]=x[1];break;
		}

		return x;
	},
	
	getNode : function(data, tree){
		var nc = 0;//nodeCount

		//node = 1
		if(data != null){
			for(var i=0;i<data.childNodes.length;i++){
				if(data.childNodes[i].nodeType == 1){
					if(nc == tree[0]){
						data = data.childNodes[i];
						if(tree.length > 1){
							tree.shift();
							data = this.getNode(data, tree);
						}
						return data;
					}
					nc++
				}
			}
		}

		return false;
	},
	
	getFirstElement : function(xmlNode){
		try{xmlNode.firstChild.nodeType == 1 ? xmlNode.firstChild : xmlNode.firstChild.nextSibling}catch(e){
			throw new Error(1052, jpf.formErrorString(1052, null, "Skinning Engine", "Could not find first element for skin:\n" + (xmlNode ? xmlNode.xml : "null")));
		}

		return xmlNode.firstChild.nodeType == 1 ? xmlNode.firstChild : xmlNode.firstChild.nextSibling;
	},

	getLastElement : function(xmlNode){
		try{xmlNode.lastChild.nodeType == 1 ? xmlNode.lastChild : xmlNode.lastChild.nextSibling}catch(e){
			throw new Error(1053, jpf.formErrorString(1053, null, "Skinning Engine", "Could not find last element for skin:\n" + (xmlNode ? xmlNode.xml : "null")));
		}

		return xmlNode.lastChild.nodeType == 1 ? xmlNode.lastChild : xmlNode.lastChild.previousSibling;
	},

	/*
	HTMLElement.prototype.__defineGetter__("runtimeStyle", function() {
		return document.defaultView.getComputedStyle(this, null);
	});
	*/
	getStyle : function(el, prop) {
		if(
			typeof document.defaultView != "undefined" && 
			typeof document.defaultView.getComputedStyle != "undefined"
		){
			var cStyle = document.defaultView.getComputedStyle(el,'');
			return !cStyle ? "" : cStyle.getPropertyValue(prop);
		}
			
		return el.currentStyle[prop];
	},
	
	isInRect : function(oHtml, x, y){
		var pos = this.getAbsolutePosition(oHtml);
		if(x < pos[0] || y < pos[1] || x > oHtml.offsetWidth + pos[0] - 10 || y > oHtml.offsetHeight + pos[1] - 10) return false;
		return true;
	},
	
	getWidthDiff : function(oHtml){
		return jpf.isIE ? 
			Math.max(0, (parseInt(jpf.compat.getStyle(oHtml, "paddingLeft"))||0) + (parseInt(jpf.compat.getStyle(oHtml, "paddingRight"))||0) + (parseInt(jpf.compat.getStyle(oHtml, "borderLeftWidth"))||0) + (parseInt(jpf.compat.getStyle(oHtml, "borderRightWidth"))||0)) :
			Math.max(0, oHtml.offsetWidth - parseInt(jpf.compat.getStyle(oHtml, "width")));
	},
	
	getHeightDiff : function(oHtml){
		return jpf.isIE ? 
			Math.max(0, (parseInt(jpf.compat.getStyle(oHtml, "paddingTop"))||0) + (parseInt(jpf.compat.getStyle(oHtml, "paddingBottom"))||0) + (parseInt(jpf.compat.getStyle(oHtml, "borderTopWidth"))||0) + (parseInt(jpf.compat.getStyle(oHtml, "borderBottomWidth"))||0)) :
			Math.max(0, oHtml.offsetHeight - parseInt(jpf.compat.getStyle(oHtml, "height")));
	},
	
	getDiff : function(oHtml){
		if(!jpf.isIE && oHtml.tagName == "INPUT") return [6,6];
		
		var pNode;
		if(!oHtml.offsetHeight){
			pNode = oHtml.parentNode; var nSibling = oHtml.nextSibling;
			document.body.appendChild(oHtml);
		}

		var diff = jpf.isIE ? 
			[
				Math.max(0, (parseInt(jpf.compat.getStyle(oHtml, "paddingLeft"))||0) + (parseInt(jpf.compat.getStyle(oHtml, "paddingRight"))||0) + (parseInt(jpf.compat.getStyle(oHtml, "borderLeftWidth"))||0) + (parseInt(jpf.compat.getStyle(oHtml, "borderRightWidth"))||0)),
				Math.max(0, (parseInt(jpf.compat.getStyle(oHtml, "paddingTop"))||0) + (parseInt(jpf.compat.getStyle(oHtml, "paddingBottom"))||0) + (parseInt(jpf.compat.getStyle(oHtml, "borderTopWidth"))||0) + (parseInt(jpf.compat.getStyle(oHtml, "borderBottomWidth"))||0))
			] :
			[
				Math.max(0, oHtml.offsetWidth - parseInt(jpf.compat.getStyle(oHtml, "width"))),
				Math.max(0, oHtml.offsetHeight - parseInt(jpf.compat.getStyle(oHtml, "height")))
			];
		
		if(pNode) pNode.insertBefore(oHtml, nSibling);
		
		return diff;
	},
	
	getOverflowParent : function(o){
		//not sure if this is the correct way. should be tested
		
		var o = o.offsetParent;
		while(o && (this.getStyle(o, "overflow") != "hidden" || "absolute|relative".indexOf(this.getStyle(o, "position")) == -1)){
			o = o.offsetParent;
		}
		return o || document.documentElement;
	},
	
	getPositionedParent : function(o){
		var o = o.offsetParent;
		while(o && o.tagName.toLowerCase() != "body" && "absolute|relative".indexOf(this.getStyle(o, "position")) == -1){
			o = o.offsetParent;
		}
		return o || document.documentElement;
	},
	
	getAbsolutePosition : function(o, refParent, inclSelf){
		var s, wt = inclSelf ? 0 : o.offsetLeft, ht = inclSelf ? 0 : o.offsetTop;
		var o = inclSelf ? o : o.offsetParent;
		while(o && o.tagName.toLowerCase() != "body" && o != refParent){
			wt += (jpf.isOpera ? 0 : parseInt(this.getStyle(o, jpf.descPropJs ? "borderLeftWidth" : "border-left-width")) || 0) + o.offsetLeft;
			ht += (jpf.isOpera ? 0 : parseInt(this.getStyle(o, jpf.descPropJs ? "borderTopWidth" : "border-top-width")) || 0) + o.offsetTop;
			
			if(o.tagName.toLowerCase() == "table"){
				ht -= parseInt(o.border || 0) + parseInt(o.cellSpacing || 0);
				wt -= parseInt(o.border || 0) + parseInt(o.cellSpacing || 0)*2;
			}
			else if(o.tagName.toLowerCase() == "tr"){
				ht -= (cp = parseInt(o.parentNode.parentNode.cellSpacing));
				while(o.previousSibling)
					ht -= (o = o.previousSibling).offsetHeight + cp;
			}
	
			o = o.offsetParent;
		}

		return [wt, ht];
	},
	
	gridPlace : function(jmlNode){
		var jNodes = jmlNode.childNodes;
		for(var nodes=[],i=0;i<jNodes.length;i++) {
			if(jNodes[i].jml.getAttribute("left") || jNodes[i].jml.getAttribute("top") || jNodes[i].jml.getAttribute("right") || jNodes[i].jml.getAttribute("bottom")) continue;
			nodes.push(jNodes[i].oExt);
		}
		
		if (nodes.length == 0)
			return;

		var parentnode = jmlNode.jml;
		var rowheight = parseInt(parentnode.getAttribute("cellheight")) || 22;
		var between = parseInt(parentnode.getAttribute("cellpadding")) || 2;
		var columns = parentnode.getAttribute("grid").split(/\s*,\s*/);

		var margin = parentnode.getAttribute("margin") ? parentnode.getAttribute("margin").split(",") : [0,0,0,0];
		for (var i=0;i<margin.length;i++)
			if (typeof margin[i] == "string")
				margin[i] = parseInt(margin[i]);			

		// Calculate column widths
		var parentWidth = nodes[0].parentNode.offsetWidth;
		if (!parentWidth) 
			return; // Do nothing of the sort.

		var colWidths = new Array();
		var nColumns = columns.length;
		var totalWidth = 0;
		var assignedColumns = 0;
		var clientWidth = parentWidth - ((nColumns-1)*between + margin[3] + margin[1]);
		for (var x=0; x<nColumns; x++)
		{
			if(typeof columns[x] == "number")
				colWidths[x] = columns[x];
			else if(typeof columns[x] == "string")
			{
				if (columns[x].indexOf("%") > -1)
				{
					colWidths[x] = Math.floor((parseInt(columns[x]) * clientWidth) / 100);
				}
				else colWidths[x] = parseInt(columns[x]); // And if this is undefined, we'll catch it later.
			}
			
			if (colWidths[x])
			{
				assignedColumns++;
				totalWidth += colWidths[x];
			}
		}

		// Distribute whatever is left of the parent over the undefined columns.
		if (assignedColumns < nColumns)
		{
			var leftOver = Math.floor((parentWidth - totalWidth - ((nColumns-1)*between + margin[1] + margin[3]	)) / (nColumns-assignedColumns));
			for (var x=0; x<nColumns; x++)
				if (!colWidths[x] && colWidths[x] !== 0)
					colWidths[x] = leftOver;
		}
		
		var nTop = margin[0];
		var iNode = 0; // Node eye-terator.

		for(var y=0;y<nodes.length;y+=nColumns)
		{
			if (y) nTop += between;
			var maxHeight = rowheight;
			var oldHeight = maxHeight;
			var nLeft = margin[3];
			for(var x=0;x<nColumns;x++)
			{
				if(!nodes[iNode]) 
					break; // Done, break.
	
				nodes[iNode].style.position = "absolute";
				nodes[iNode].style.top = nTop + "px";
				nodes[iNode].style.left = nLeft + "px";
				
				//var diff = jpf.compat.getDiff(nodes[iNode]);

				if (jNodes[iNode].jml.getAttribute("width") == null) // Only if not directly specified.
					nodes[iNode].style.width = Math.max(colWidths[x] - (jpf.compat.getWidthDiff(nodes[iNode]) || 0), 0) + "px";

				//nColumns != 1 || 
				maxHeight = Math.max(
					jNodes[iNode].jml.getAttribute("autosize") != "true" && !jNodes[iNode].nonSizingHeight ? maxHeight : 0, 
					nodes[iNode].offsetHeight, 
					jpf.compat.getStyle(nodes[iNode], "overflow") == "visible" ? 
						nodes[iNode].scrollHeight : 0
					);
				//maxHeight = Math.max(columns.length != 1 || jNodes[iNode].jml.getAttribute("autosize") != "true" ? maxHeight : 0, nodes[iNode].offsetHeight, jpf.compat.getStyle(nodes[iNode], "overflow") == "visible" ? nodes[iNode].scrollHeight : 0);

				nLeft += Math.max(colWidths[x], 0) + between; // Equal to nodes[iNode].offsetWidth + between.
				iNode++;
			}
			
			//if(maxHeight > oldHeight){
				for(var x=0;x<nColumns;x++){
					var j = jNodes[iNode-x-1];
					var h = nodes[iNode-x-1];
					if (!j.nonSizingHeight && j.jml.getAttribute("autosize") != "true" && j.jml.getAttribute("height") == null){ // Only if not directly specified.
						h.style.height = Math.max(0,(maxHeight - (jpf.compat.getHeightDiff(h) || 0))) + "px";
					}
				}
			//}
			
			nTop += maxHeight;
		}
		
		// Resize the parent, if necessary - This should be optional...
		if (jmlNode.jml.getAttribute("height") == null && jmlNode.jml.getAttribute("autosize") != "false")
			jmlNode.oExt.style.height = Math.max(nTop+margin[2], 0) + "px";
	},
	
	disable : function (o){
		/*if (D.readyState != "complete") {
			window.setTimeout("disable(" + el.id + ")", 100);	// If document not finished rendered try later.
			return;
		}*/
		
		//o.style.filter = "chroma(color=red) dropshadow(color=buttonhighlight, offx=1, offy=1)";
		o.innerHTML =	"<span style='background: buttonshadow; filter: chroma(color=red) dropshadow(color=buttonhighlight, offx=1, offy=1); width: 100%; height: 100%;'>" +
						"<span style='filter: mask(color=red); width: 100%; height: 100%;'>" +
						o.innerHTML +
						"</span>" +
						"</span>";
		
		//o.firstChild.firstChild.backgroundColor = "Transparent";				
		//o.firstChild.firstChild.filter = "gray() chroma(color=#ffffff) chroma(color=#fefefe) chroma(color=#fdfdfd) chroma(color=#fcfcfc) chroma(color=#fbfbfb) chroma(color=#fafafa) chroma(color=#f9f9f9) chroma(color=#f8f8f8) chroma(color=#f7f7f7) chroma(color=#f6f6f6) chroma(color=#f5f5f5) chroma(color=#f4f4f4) chroma(color=#f3f3f3)  mask(color=#010101);"
	},
	
	enable : function(o){
		o.innerHTML = o.innerHTML.replace(/^<.*?><.*?>(.*)<.*?><.*?>$/, "$1");
	},
	
	initializeIframe : function(id, strInit){
		var doc = self.frames[id].document;
		
		doc.open();
		doc.write(strInit || "<html><head><style>BODY{margin:0px;border:thin;} DIV{display : inline;} *{-moz-box-sizing: border-box;}</style></head><body></body></html>");
		doc.close();
		
		if(!jpf.isIE) jpf.importClass(MozillaCompat, true, self.frames[id]);
		
		doc.body.obj = D.getElementById(id);
		doc.body.win = doc.win = self.frames[id];
		if(!jpf.isIE50) doc.body.obj.doc = doc;
		//this is not 100% but good enough for now...
		doc.body.obj.onresize = function(){this.doc.body.ll = null;}
		
		doc.onkeydown = function(e){
			if(!e) e = this.win.event;
			if(!this.ll) this.ll = jpf.compat.getAbsolutePosition(this.obj);
			return false;
		}
		
		doc.onmousedown = function(e){
			if(!e) e = this.win.event;
			if(document.body.onmousedown) D.body.onmousedown(e);
			if(document.onmousedown) D.onmousedown(e);
		}
		
		doc.onmouseup = function(e){
			if(!e) e = this.win.event;
			if(document.body.onmouseup) D.body.onmouseup(e);
			if(document.onmouseup) D.onmouseup(e);
		}
		
		doc.onclick = function(e){
			if(!e) e = this.win.event;
			if(document.body.onclick) D.body.onclick(e);
			if(document.onclick) D.onclick(e);
		}
		
		//all these events should actually be piped to the events of the container....
		doc.body.oncontextmenu = function(e){
			if(!e) e = this.win.event;
			if(!this.ll) this.ll = jpf.compat.getAbsolutePosition(this.obj);
			var s = this.ll;
			
			q = {
				offsetX : e.offsetX,
				offsetY : e.offsetY,
				x : e.x + s[0],
				y : e.y + s[1],
				button : e.button,
				clientX : e.x + s[0],
				clientY : e.y + s[1],
				srcElement : e.srcElement,
				target : e.target,
				targetElement : e.targetElement
			}

			if(this.host && this.host.oncontextmenu) this.host.oncontextmenu(q);
			if(document.body.oncontextmenu) D.body.oncontextmenu(q);
			if(document.oncontextmenu) D.oncontextmenu(q);
			
			return false;
		}

		doc.body.onmouseover = function(e){
			this.ll = jpf.compat.getAbsolutePosition(this.obj);
		}

		doc.body.onmousemove = function(e){
			if(!e) e = this.win.event;
			if(!this.ll) this.ll = jpf.compat.getAbsolutePosition(this.obj);
			var s = this.ll;
		
			q = {
				offsetX : e.offsetX,
				offsetY : e.offsetY,
				x : e.x + s[0] - 4,
				y : e.y + s[1] - 4,
				button : e.button,
				clientX : e.x + s[0] - 4,
				clientY : e.y + s[1] - 4,
				srcElement : e.srcElement,
				target : e.target,
				targetElement : e.targetElement
			}

			if(this.obj.onmousemove) this.obj.onmousemove(q);
			if(document.body.onmousemove) D.body.onmousemove(q);			
			if(document.onmousemove) D.onmousemove(q);
			
			return e.returnValue;
		}
		
		return self.frames[id];
	}
}


	/*this.setAnchor = function(left, top, right, bottom, width, height){
		if(!this.oExt.host) return;
		
		if(left || top || right || bottom) this.oExt.style.position = "absolute";
		if(left != null) this.oExt.style.left = left + "px";
		if(top != null) this.oExt.style.top = top + "px";
		
		var id = 'jpf.lookup(' + this.uniqueId + ').oExt';
		var ids = [];
		
		var pNode = this.oExt.parentNode; var nSibling = this.oExt.nextSibling;
		document.body.appendChild(this.oExt);

		var hordiff = Math.max(0, this.oExt.offsetWidth - parseInt(jpf.compat.getStyle(this.oExt, "width")) || 0);
		var verdiff = Math.max(0, this.oExt.offsetHeight - parseInt(jpf.compat.getStyle(this.oExt, "height")) || 0);
		//if(this.jml.getAttribute("id") == "btnSearch") alert(verdiff);

		pNode.insertBefore(this.oExt, nSibling);

		var pWidth = this.parentNode == document.body ? (document.all ? 'document.documentElement.offsetWidth' : 'window.innerWidth'): id + '.parentNode.offsetWidth';
		var pHeight = this.parentNode == document.body ? (document.all ? 'document.documentElement.offsetHeight' : 'window.innerHeight') : id + '.parentNode.offsetHeight';
		
		if(right != null && left != null){
			if(!this.parentNode.RULES) this.parentNode.RULES = new Array();//" + parentNode + ".offsetWidth
			ids.push(this.parentNode.RULES.push(id + ".style.width = (" +  pWidth + " - " + right + " - " + id + ".offsetLeft - " + hordiff + ") + 'px'")-1);
		}
		else{
			if(right != null){
				if(!this.parentNode.RULES) this.parentNode.RULES = new Array();
				ids.push(this.parentNode.RULES.push(id + ".style.left = (" +  pWidth + " - " + right + " - " + id + ".offsetWidth) + 'px'")-1);
			}
			if(width != null) this.oExt.style.width = (width-hordiff) + "px";
		}
		
		if(bottom != null && top != null){
			if(!this.parentNode.RULES) this.parentNode.RULES = new Array();
			ids.push(this.parentNode.RULES.push(id + ".style.height = (" +  pHeight + " - " + bottom + " - " + id + ".offsetTop - " + verdiff + ") + 'px'")-1);
		}
		else{
			if(bottom != null){
				if(!this.parentNode.RULES) this.parentNode.RULES = new Array();
				ids.push(this.parentNode.RULES.push(id + ".style.top = (" +  pHeight + " - " + bottom + " - " + id + ".offsetHeight) + 'px'")-1);
			}
			if(height != null) this.oExt.style.height = (height-verdiff) + "px";
		}
		*/
		/*if(this.anchorIds){
			for(var i=0;i<this.anchorIds.length;i++){
				this.parentNode.RULES[this.anchorIds[i]] = "";
			}
			
		}*/
		/*
		this.anchorIds = ids;
	}*/

/*FILEHEAD(/in/Core/Kernel/Print.js)SIZE(2505)TIME(1201688465117)*/

jpf.printServer = {
	lastContent : "",
	inited : false,
	
	init : function(){
		this.inited = true;
		this.contentShower = document.body.appendChild(document.createElement("DIV"));
		this.contentShower.id = "print_content"
		
		//LATER REPLACE THIS BY A SKIN
		with(this.contentShower.style){
			/*position = "absolute";
			left = "0px";
			top = "0px";*/
			width = "100%";
			height = "100%";
			backgroundColor = "white";
			zIndex = 100000000;
			//if(jpf.isIE) display = "none";
		}
		
		//if(!jpf.isIE){
			jpf.importCssString(document, "#print_content{display:none}");
			jpf.importCssString(document, "body #print_content, body #print_content *{display:block} body *{display:none}", "print");
			
			/*styleElement = document.createElement('style');
			styleElement.type = 'text/css';
			styleElement.media = 'print';
			styleElement.appendChild(document.createTextNode("#print_content {display:block}"));
			document.getElementsByTagName('head').item(0).appendChild(styleElement);*/
		//}
	},
	
	printContent : function(v){
		this.setContent(v);
		this.print();
	},
	
	setContent : function(v){
		if(!this.inited) this.init();
		this.lastContent = v;
		//if(!IS_IE) 
		this.contentShower.innerHTML = v;
	},
	
	print : function(){
		window.print();
	}
}
/*
window.onbeforeprint = function(){
	if(!PrintServer.lastContent && PrintServer.onbeforeprint) PrintServer.onbeforeprint();

	if(PrintServer.lastContent){
		PrintServer.contentShower.innerHTML = PrintServer.lastContent;
		PrintServer.lastContent = false;
		
		this.hidden = [];
		for(var i=0;i<document.body.childNodes.length;i++){
			if(document.body.childNodes[i].nodeType != 1) continue;
			
			if(document.body.childNodes[i].style.display == "none") 
				this.hidden.push(document.body.childNodes[i])
			document.body.childNodes[i].style.display = "none";
		}
		PrintServer.contentShower.style.display = "block";
	}
}

window.onafterprint = function(){
	if(PrintServer.inited){
		for(var i=0;i<document.body.childNodes.length;i++) {
			if(document.body.childNodes[i].nodeType != 1) continue;
			
			document.body.childNodes[i].style.display = "block";
		}
			
		for(var i=0;i<this.hidden.length;i++) 
			this.hidden[i].style.display = "none";
		
		PrintServer.contentShower.style.display = "none";
		if(self.hider) hider.style.display = "none";
		
		if(PrintServer.onafterprint) PrintServer.onafterprint();
	}
}*/

/*FILEHEAD(/in/Core/Kernel/Sort.js)SIZE(6670)TIME(1202849967875)*/

//<Traverse select="" sort="@blah" data-type={"string" | "number" | "date"} date-format="" sort-method="" order={"ascending" | "descending"} case-order={"upper-first" | "lower-first"} />
/*
	<Traverse select="group|contact" sort="self::group/@name|self::contact/screen/text()" order="ascending" case-order="upper-first" />
	<Traverse select="group|contact" sort="@date" date-format="DD-MM-YYYY" order="descending"/>
	<Traverse select="group|contact" sort-method="compare" />
*/

/**
 * Object representing the window of the JML application
 *
 * @classDescription		This class creates a new sort object
 * @return {Sort} Returns a new sort object
 * @type {Sort}
 * @constructor
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.8
 */
jpf.Sort = function(xmlNode){	
	var sort_intmask = ["", "0", "00", "000", "0000", "00000", "000000", "0000000", "00000000", "000000000", "0000000000", "00000000000", "000000000000", "0000000000000", "00000000000000" ];
	var isAscending, xpath, type, method, getNodes, dateFormat, dateReplace, sort_dateFmtStr, getValue;

	//use this function to parse the traverse node
	this.parseXml = function(xmlNode){
		isAscending = xmlNode.getAttribute("order") != "descending";
		xpath = xmlNode.getAttribute("sort");
		getNodes = self[xmlNode.getAttribute("nodesmethod")];
		getValue = function(item){return jpf.getXmlValue(item, xpath);}
		
		if(xmlNode.getAttribute("type")) method = eval("sort_" + xmlNode.getAttribute("type"));
		if(xmlNode.getAttribute("sortmethod")) method = self[xmlNode.getAttribute("sortmethod")];
		if(!method) method = sort_alpha;
		
		var str = xmlNode.getAttribute("dateformat"); 
		if(str){
			sort_dateFmtStr = str;
			var result = str.match(/(D+|Y+|M+|h+|m+|s+)/g);
			if(result) {
				for(var pos={},i=0;i<result.length;i++) pos[result[i].substr(0,1)] = i+1;
				dateFormat = new RegExp(str.replace(/[^\sDYMhms]/g,'\\$1').replace(/YYYY/, "(\\d\\d\\d\\d)").replace(/(DD|YY|MM|hh|mm|ss)/g, "(\\d\\d)"));
				dateReplace = "$" + pos["M"] + "/$" + pos["D"] + "/$" + pos["Y"];
				if(pos["h"]) dateReplace += " - $"+pos["h"]+":$"+pos["m"]+":$"+pos["s"];
			}
		}
	}
	if(xmlNode) this.parseXml(xmlNode);
	
	this.set = function(struct){
		var prop, x;
		for(prop in struct){
			x = struct[prop];
			eval(prop + " = x;");
		}

		if(struct["type"]) method = eval("sort_" + struct["type"]);
		if(struct["method"]) method = struct["method"];
		if(!method) method = sort_alpha;
	}
	
	//use this function in __xmlUpdate [this function isnt done yet]
	this.findSortSibling = function(pNode, xmlNode){
		var nodes = getNodes ? getNodes(pNode, xmlNode) : this.getTraverseNodes(pNode);

		for(var i=0;i<nodes.length;i++)
			if(!compare(xmlNode, nodes[i], true, sortSettings))
				return nodes[i];
	
		return null;
	}
	
	// Sorting methods for sort()
  	function sort_alpha(n)  { return n.toString().toLowerCase() }
	function sort_number(t){
	  	return (t.length < sort_intmask.length ? sort_intmask[sort_intmask.length - t.length] : "") + t;
	}
	function sort_date(t,args){
		if(!sort_dateFormat || (args && sort_dateFmtStr!=args[0])) sort_dateFmt(args? args[0] : "*");
		
		var d;
		if(sort_dateFmtStr == '*') d = Date.parse(t);
		else d = (new Date(t.replace(sort_dateFormat, sort_dateReplace))).getTime();
		t = ""+parseInt(d); if(t=="NaN")t="0";
		return (t.length < sort_intmask.length ? sort_intmask[sort_intmask.length - t.length] : "") + t;
	}
	
	/*
		sort(xpath, sort_xpath, sort_alpha, boolDesc, from, len)
		jsort(n,f,p,ps,sm,desc,sp,ep)
	*/
	
	//var isAscending, xpath, type, method, getNodes, dateFormat, dateReplace, sort_dateFmtStr, getValue;
	this.apply = function(n, args, func, start, len){
		var sa = [], i = n.length;

		// build string-sortable list with sort method
		while(i--){
			var v = getValue(n[i]);
			if(n) sa[sa.length] = {toString:function(){return this.v;}, pn:n[i], v:method(v, args, n[i])};
		}
		
		// sort it
		sa.sort();
		
		//iterate like foreach
		end = len ? Math.min(sa.length, start+len) : sa.length;
		if(!start) start = 0;
		
		if(func){
			if(isAscending) for(i = start;i<end;i++) f(i,end,sa[i].pn,sa[i].v);
			else for(i = end-1;i>=start;i--) f(end-i-1,end,sa[i].pn,sa[i].v);
		}
		else{
			//this could be optimized by reusing n... time it later
			var res = [];
			if(isAscending) for(i = start;i<end;i++) res[res.length] = sa[i].pn;
			else for(i = end-1;i>=start;i--) res[res.length] = sa[i].pn;
			return res;
		}
	}
	
	/*Implement this api for JSON support
	function jsort(n,f,p,ps,sm,desc,sp,ep){
		sm = sm ? sm : sort_alpha;
		var sa = [], t = n.selectNodes(p), i = t.length, args = null;
		if(typeof sm != "function"){var m = sm.shift();args = sm; sm = m;}		

		// build string-sortable list with sort method
		while(i--){
			var n = getValue(t[i]);
			if(n) sa[sa.length] = {toString:function(){return this.v;}, pn:t[i], v:sm(n,args)};
		}
		// sort it
		sa.sort();
		
		//iterate like foreach
		var end = ep==null?sa.length:Math.min(sa.length,(sp+ep));
		var start = (sp==null)?0:sp;
		if(desc){
			for(var i = end-1;i>=start;i--)f(end-i-1,end,sa[i].pn,sa[i].v);
		}else{
			for(var i = start;i<end;i++)f(i,end,sa[i].pn,sa[i].v);
		}
	}*/
}

/*

	//ebuddy sorting
	function compare(xmlNode1, xmlNode2, testEqual){
		//if(testEqual) return n1>=n2;
		//return (n1>n2);
	
		if(!xmlNode1) return true;
		if(!xmlNode2) return false;
		if(xmlNode1.tagName == "group"){
			var str1 = xmlNode1.getAttribute("name").toLowerCase();
			var str2 = xmlNode2.getAttribute("name").toLowerCase();
		}
		else{
			var str3 = xmlNode1.selectSingleNode("status/text()").nodeValue;
			var str4 = xmlNode2.selectSingleNode("status/text()").nodeValue;
			if(str3 == "FLN" && str4 != "FLN") return true;
			if(str3 != "FLN" && str4 == "FLN") return false;
		
			var str1 = xmlNode1.selectSingleNode("screen/text()").nodeValue.toLowerCase();
			var str2 = xmlNode2.selectSingleNode("screen/text()").nodeValue.toLowerCase();
		}
	
		if(testEqual && str1 == str2) return true;
	
		var len = Math.max(str1.length, str2.length);
		for(var i=0;i<len;i++) if(str1.charCodeAt(i) != str2.charCodeAt(i)){
			if(!str1.charCodeAt(i)) return true;
			return str1.charCodeAt(i) > str2.charCodeAt(i);
		}
	
		return false;
	}
	
	//ebuddy
	function getNodes(pNode, xmlNode){
		return doGroup ?
			pNode.selectNodes("group[@name]") :
			pNode.selectNodes("contact[" + (getXmlValue(xmlNode, "status/text()") == "FLN" ? "status/text()='FLN'" : "not(status/text()='FLN')") + "]");
	}
	
*/

/*FILEHEAD(/in/Core/Node/Alignment.js)SIZE(2954)TIME(1213483123975)*/
__ALIGNMENT__ = 1<<12;


/**
 * Baseclass adding Alignment features to this Component.
 *
 * @constructor
 * @baseclass
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.4
 */
jpf.Alignment = function(){
	this.__regbase = this.__regbase|__ALIGNMENT__;
	
	/**
	 * Sets properties used by the Alignment engine to position this component in its plane.
	 *
	 * @param  {String}  prop   required  String specifying the property to change. Possible values are: align, align-lean, align-position, align-span, align-margin, align-edge, align-splitter, width, height, min-width, min-height.
	 * @param  {String}  value   required  String specifying the value of the property.
	 * @param  {Boolean}  purge  optional  true  alignment is recalculated right after setting the property.
	 *                                    false  no recalculation is performed
	 */
	this.setAlignProperty = function(prop, value, purge){
		this.aData[prop] = value;
		if(purge) this.purgeAlignment();
	}
	
	/**
	 * Turns the alignment features off.
	 * @param  {Boolean}  purge  optional  true  alignment is recalculated right after setting the property.
	 *                                    false  no recalculation is performed
	 *
	 */
	var lastPosition, jmlNode = this;
	this.disableAlignment = function(purge){
		this.aData.prehide();
		if(purge) this.purgeAlignment();
	}
	
	/**
	 * Turns the alignment features on.
	 *
	 * @attribute  align 
	 * @attribute  splitter 
	 * @attribute  edge 
	 * @attribute  minwidth 
	 * @attribute  minheight 
	 */
	this.aData = null;
	this.enableAlignment = function(purge){
		var x = this.jml;

		if(!this.aData){
			//template support - assuming there are no vbox/hboxes for this parent
			var pNode;
			if(x.getAttribute("align")){
				if(!this.parentNode.vbox){
					var vbox = this.parentNode.vbox = new jpf.vbox(this.pHtmlNode, "vbox");
					vbox.parentNode = this.parentNode;
					vbox.loadJML(jpf.XMLDatabase.getXml("<vbox margin='" + (this.pHtmlNode.getAttribute("margin") || "0,0,0,0") + "' />"), this.parentNode);
				}
			}
			
			var l = jpf.layoutServer.get(this.pHtmlNode); // , (x.parentNode.getAttribute("margin") || "").split(/,\s*/)might be optimized by splitting only once
			this.aData = jpf.layoutServer.parseXml(x, l, this);
			
			if(x.getAttribute("align")) this.parentNode.vbox.addAlignNode(this)
			else{
				this.aData.stackId = this.parentNode.aData.children.push(this.aData) - 1;
				this.aData.parent = this.parentNode.aData;
			}
		}
		else{
			this.aData.preshow();
		}
		
		if(purge) this.purgeAlignment();
	}
	
	/**
	 * Calculate the rules for this component and activates them.
	 *
	 */
	this.purgeAlignment = function(){
		jpf.layoutServer.queue(this.pHtmlNode, true);
	}
	
	this.__addJmlLoader(function(x){
		this.dock = !jpf.isFalse(x.getAttribute("dock"));
	});
}
/*FILEHEAD(/in/Core/Node/Anchoring.js)SIZE(7241)TIME(1213483123975)*/
__ANCHORING__ = 1<<13;


/**
 * Baseclass adding Anchoring features to this Component.
 *
 * @constructor
 * @baseclass
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.3
 */
jpf.Anchoring = function(){
	this.__regbase = this.__regbase|__ANCHORING__;
	
	if(!this.oExt.getAttribute("id")) jpf.setUniqueHtmlId(this.oExt);
	var oHtmlDiff;
	
	/**
	 * Turns anchoring off.
	 *
	 */
	this.disableAnchoring = function(activate){
		jpf.layoutServer.removeRule(this.pHtmlNode, this.uniqueId + "h");
		jpf.layoutServer.removeRule(this.pHtmlNode, this.uniqueId + "v");
		
		if(activate) this.purgeAnchoring();
	}
	
	/**
	 * Enables anchoring based on attributes set in the JML of this component
	 *
	 * @param  {Boolean}  activate  optional  true  the anchoring rules are activated.
	 *                                      false  default  the anchoring rules remain unactivated.
	 */
	this.enableAnchoring = function(activate){
		this.getDiff();
		
		var x = this.jml;
		this.setHorizontal(
			x.getAttribute("left"),
			x.getAttribute("right"), x.getAttribute("width")
		);
		
		this.setVertical(
			x.getAttribute("top"),
			x.getAttribute("bottom"), x.getAttribute("height")
		);
		
		if(activate) this.purgeAnchoring();
	}
	
	this.getDiff = function(){
		oHtmlDiff = jpf.compat.getDiff(this.oExt);
	}
	
	/**
	 * @private
	 */
	this.moveAnchoringRules = function(newPNode, updateNow){
		var rules = [jpf.layoutServer.getRules(this.pHtmlNode, this.uniqueId + "h"), jpf.layoutServer.getRules(this.pHtmlNode, this.uniqueId + "v")];
		
		this.disableAnchoring();
		if(updateNow) jpf.layoutServer.activateRules(this.pHtmlNode);
		
		jpf.layoutServer.setRules(newPNode, this.uniqueId + "h", rules[0]);
		jpf.layoutServer.setRules(newPNode, this.uniqueId + "v", rules[1]);
		if(updateNow) jpf.layoutServer.activateRules(newPNode);
	}
	
	function setPercentage(value, pValue){
		return (typeof value == "string" ? value.replace(/(\d+)\%/g, "((" + pValue + " * $1)/100)") : value);
	}
	
	/**
	 * Sets the horizontal anchoring rules for this component
	 *
	 * @param  {Integer}  left  optional  Integer specifying the amount of pixels from the left border of this component to the left edge of it's parent's border.
	 * @param  {Integer}  right  optional  Integer specifying the amount of pixels from the right border of this component to the right edge of it's parent's border.
	 * @param  {Integer}  width  optional  Integer specifying the amount of pixels from the left border to the right border of this component.
	 * @param  {Boolean}  apply  optional  true  new anchoring rules are activated
	 *                                   false  new anchoring rules are not activated
	 */
	this.setHorizontal = function(left, right, width, apply){
		var rules = [];
		
		var id = this.oExt.getAttribute("id");
		if(jpf.isGecko) id = "document.getElementById('" + id + "')";
		var pWidth = (this.oExt.parentNode == this.pHtmlDoc.body ? (jpf.isIE ? "document.documentElement.offsetWidth" : "window.innerWidth") : id + ".parentNode.offsetWidth");
		var hordiff = oHtmlDiff[0];
		
		left = setPercentage(left, pWidth);
		right = setPercentage(right, pWidth);
		width = setPercentage(width, pWidth);
		
		if(left){
			if(parseInt(left) != left) rules.push(id + ".style.left = (" + left + ") + 'px'");
			else this.oExt.style.left = left + "px";
		}
		if(!left && right){
			if(parseInt(right) != right) rules.push(id + ".style.right = (" + right + ") + 'px'");
			else this.oExt.style.right = right + "px";
		}
		if(width){
			if(parseInt(width) != width) rules.push(id + ".style.width = (" + width + " - " + hordiff + ") + 'px'");
			else this.oExt.style.width = (width-hordiff) + "px";
		}

		if(right != null && left != null)
			rules.push(id + ".style.width = (" +  pWidth + " - (" + right + ") - (" + left + ") - " + hordiff + ") + 'px'");
		else if(right == null && left == null)
			rules.push(id + ".style.left = ((" + pWidth + " - " + (width || id + ".offsetWidth") + ")/2) + 'px'");
		else if(right != null)
			rules.push(id + ".style.left = (" +  pWidth + " - " + right + " - " + (width || id + ".offsetWidth") + ") + 'px'");
		
		this.oExt.style.position = "absolute";

		rules = 'try{' + rules.join(';}catch(e){};try{') + ';}catch(e){};';
		jpf.layoutServer.setRules(this.pHtmlNode, this.uniqueId + "h", rules, true);
		
		if(apply){
			eval(rules);
			jpf.layoutServer.activateRules(this.pHtmlNode, true);
		}
	}
	
	/**
	 * Sets the vertical anchoring rules for this component
	 *
	 * @param  {Integer}  top  optional  Integer specifying the amount of pixels from the top border of this component to the top edge of it's parent's border.
	 * @param  {Integer}  bottom  optional  Integer specifying the amount of pixels from the bottom border of this component to the bottom edge of it's parent's border.
	 * @param  {Integer}  height  optional  Integer specifying the amount of pixels from the top border to the bottom border of this component.
	 * @param  {Boolean}  apply  optional  true  new anchoring rules are activated
	 *                                    false  new anchoring rules are not activated
	 */
	this.setVertical = function(top, bottom, height, apply){
		var rules = [];
		
		var id = this.oExt.getAttribute("id");
		if(jpf.isGecko) id = "document.getElementById('" + id + "')";
		var pHeight = (this.oExt.parentNode == this.pHtmlDoc.body ? (jpf.isIE ? "document.documentElement.offsetHeight" : "window.innerHeight") : id + ".parentNode.offsetHeight");
		var verdiff = oHtmlDiff[1];
		
		top = setPercentage(top, pHeight);
		bottom = setPercentage(bottom, pHeight);
		height = setPercentage(height, pHeight);
		
		if(top){
			if(parseInt(top) != top) rules.push(id + ".style.top = (" + top + ") + 'px'");
			else this.oExt.style.top = top + "px";
		}
		if(!top && bottom){
			if(parseInt(bottom) != bottom) rules.push(id + ".style.bottom = (" + bottom + ") + 'px'");
			else this.oExt.style.bottom = bottom + "px";
		}
		if(height){
			if(parseInt(height) != height) rules.push(id + ".style.height = (" + height + " - " + verdiff + ") + 'px'");
			else this.oExt.style.height = (height-verdiff) + "px";
		}
		
		if(bottom != null && top != null)
			rules.push(id + ".style.height = (" +  pHeight + " - (" + bottom + ") - (" + top + ") - " + verdiff + ") + 'px'");
		else if(bottom == null && top == null)
			rules.push(id + ".style.top = ((" + pHeight + " - " + (height || id + ".offsetHeight") + ")/2) + 'px'");
		else if(bottom != null)
			rules.push(id + ".style.top = (" +  pHeight + " - " + bottom + " - " + (height || id + ".offsetHeight") + ") + 'px'");
		
		this.oExt.style.position = "absolute";
		
		var rules = 'try{' + rules.join(';}catch(e){};try{') + ';}catch(e){};';
		jpf.layoutServer.setRules(this.pHtmlNode, this.uniqueId + "v", rules, true);
		
		if(apply){
			eval(rules);
			jpf.layoutServer.activateRules(this.pHtmlNode, true);
		}
	}
	
	/**
	 * Activate the anchoring rules for this component.
	 *
	 */	
	this.purgeAnchoring = function(){
		jpf.layoutServer.queue(this.pHtmlNode);
	}
}

/*FILEHEAD(/in/Core/Node/Cache.js)SIZE(7285)TIME(1203730484247)*/
__CACHE__ = 1<<2;


/**
 * Baseclass adding Caching features to this Component.
 *
 * @constructor
 * @baseclass
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.4
 */
jpf.Cache = function(){
	/* ********************************************************************
										PROPERTIES
	*********************************************************************/
	var cache = {};
	this.caching = true; 
	
	this.__regbase = this.__regbase|__CACHE__;
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/
	
	/**
	 * Checks the cache for a cached item by ID. If the ID is found the 
	 * representation is loaded from cache and set active.
	 *
	 * @param  {String}  id  required  String specifying the id of the cache element which is looked up.
	 * @return  {Boolean}  true   the cache element is found and set active
	 *                   false  otherwise
	 * @see    DataBinding#load
	 */
	this.getCache = function(id){
		//Checking Current
		if(id == this.cacheID) return false;

		//Checking Cache...
		if(!cache[id]) return false;

		//Removing previous
		if(this.cacheID) this.clear(true);

		//Get Fragment and clear Cache Item
		var fragment = cache[id];

		this.documentId = fragment.documentId;
		this.cacheID = id;
		this.XMLRoot = fragment.XMLRoot;
		
		this.clearCacheItem(id);

		this.__setCurrentFragment(fragment);

		return true;
	}
	
	/**
	 * Sets cache element and it's ID
	 *
	 * @param  {String}  id            required  String specifying the id of the cache element to be stored.
	 * @param  {DocumentFragment}  fragment  required  Object to be stored.
	 */
	this.setCache = function(id, fragment){
		if(!this.caching) return;

		cache[id] = fragment;
	}
	
	/**
	 * Finds HTML presentation node in cache by ID
	 *
	 * @param  {String}  id  required  String specifying the id of the HTML node which is looked up.
	 * @return  {HTMLNode}  the HTML node found or null when nothing was found
	 */
	this.getNodeFromCache = function(id){
		var node = this.__findNode(null, id);
		if(node) return node;
		
		for(prop in cache){
			if(cache[prop] && cache[prop].nodeType){
				var node = this.__findNode(cache[prop], id);
				if(node) return node;
		 	}
		}
		
		return null;
	}
	
	/**
	 * Finds cache element by ID of HTML node in cache
	 *
	 * @param  {String}  id  required  String specifying the id of the HTML node which is looked up.
	 * @return  {DocumentFragement}  the cache element or null when nothing was found
	 */
	this.getCacheItemByHtmlId = function(id){
		var node = this.__findNode(null, id);
		if(node) return this.oInt;
		
		for(prop in cache){
			if(cache[prop] && cache[prop].nodeType){
				var node = this.__findNode(cache[prop], id);
				if(node) return cache[prop];
		 	}
		}
		
		return null;
	}
	
	/**
	 * Unloads data from this component and resets state displaying an empty message.
	 * Empty message is set on the {@link JmlNode#msg} property.
	 *
	 * @param  {Boolean}  nomsg  optional  Boolean specifying wether to display the empty message.
	 * @param  {Boolean}  do_event  optional  Boolean specifying wether to sent select events.
	 * @see DataBinding#load
	 */
	this.clear = function(nomsg, do_event){
		if(this.clearSelection) this.clearSelection(null, !do_event);

		if(this.caching){
			var fragment = this.__getCurrentFragment();
			if(!fragment) return;//this.__setClearMessage(this.msg);
			fragment.documentId = this.documentId;
			fragment.XMLRoot = this.XMLRoot;
		}
		else this.oInt.innerHTML = "";

		if(!nomsg) this.__setClearMessage(this.msg);
		else if(this.__removeClearMessage) this.__removeClearMessage();
		
		if(this.caching && (this.cacheID || this.XMLRoot)) 
			this.setCache(this.cacheID || this.XMLRoot.getAttribute(jpf.XMLDatabase.xmlIdTag) || "doc" + this.XMLRoot.getAttribute(jpf.XMLDatabase.xmlDocTag), fragment);

		this.documentId = null;
		this.XMLRoot = null;
		this.cacheID = null;
		this.dataset = {set:{},seq:[]};
	}
	
	/**
	 * @private
	 */
	this.clearAllTraverse = function(){
		if(this.clearSelection) this.clearSelection(null, true);
		this.oInt.innerHTML = "";
		this.__setClearMessage(this.msg);
		this.dataset = {set:{},seq:[]};
	}
	
	/**
	 * Removes an item from the cache.
	 *
	 * @param  {String}  id  required  String specifying the id of the HTML node which is looked up.
	 * @param  {Boolean}  remove optional  Boolean specifying wether to destroy the Fragment.
	 * @see DataBinding#clear
	 */
	this.clearCacheItem = function(id, remove){
		cache[id].documentId = null;
		cache[id].cacheID = null;
		cache[id].XMLRoot = null;
		
		if(remove) jpf.removeNode(cache[id]);
		
		cache[id] = null;
	}

	/**
	 * Removes all items from the cache
	 *
	 * @see DataBinding#clearCacheItem
	 */
	this.clearAllCache = function(){
		for(prop in cache){
			if(cache[prop]) this.clearCacheItem(prop, true);
		}
	}
	
	/**
	 * Gets the cache item by it's id
	 *
	 * @param  {String}  id  required  String specifying the id of the HTML node which is looked up.
	 * @see DataBinding#clearCacheItem
	 */
	this.getCacheItem = function(id){
		return cache[id];
	}
	
	/* ********************************************************************
										PRIVATE METHODS
	*********************************************************************/
	
	/**
	 * @attribute  caching 
	 */
	this.__addJmlLoader(function(x){
		this.caching = x.getAttribute("caching") != "false";
	});
	
	if(this.hasFeature(__MULTISELECT__)) this.inherit(jpf.MultiselectCache); /** @inherits jpf.MultiselectCache */
}


/**
 * @constructor
 * @private
 */
jpf.MultiselectCache = function(){
	this.__getCurrentFragment = function(){
		var fragment = jpf.hasDocumentFragment ? document.createDocumentFragment() : new DocumentFragment(); //IE55
		
		while(this.oInt.childNodes.length){
			fragment.appendChild(this.oInt.childNodes[0]);
		}
		fragment.dataset = this.dataset;

		return fragment;
	}
	
	this.__setCurrentFragment = function(fragment){
		jpf.hasDocumentFragment ? this.oInt.appendChild(fragment) : fragment.reinsert(this.oInt); //IE55
		this.dataset = fragment.dataset;
		if(!jpf.window.isFocussed(this)) this.blur();
	}

	this.__findNode = function(cacheNode, id){
		if(!cacheNode) return this.pHtmlDoc.getElementById(id);
		return cacheNode.getElementById(id);
	}
	
	this.__setClearMessage = function(msg){
		var xmlEmpty = this.__getLayoutNode("Empty");
		if(!xmlEmpty) return;
		
		var oEmpty = jpf.XMLDatabase.htmlImport(xmlEmpty, this.oInt);
		var empty = this.__getLayoutNode("Empty", "caption", oEmpty);
		if(empty) jpf.XMLDatabase.setNodeValue(empty, msg || "");
		if(oEmpty) oEmpty.setAttribute("id", "empty" + this.uniqueId);
	}
	
	this.__removeClearMessage = function(){
		var oEmpty = document.getElementById("empty" + this.uniqueId);
		if(oEmpty) oEmpty.parentNode.removeChild(oEmpty);
		//else this.oInt.innerHTML = ""; //clear if no empty message is supported
	}
}

/*FILEHEAD(/in/Core/Node/DataBinding.js)SIZE(71079)TIME(1205790104099)*/
__DATABINDING__ = 1<<1;


/**
 * Baseclass adding Databinding features to this Component.
 *
 * @constructor
 * @baseclass
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.4
 */
jpf.DataBinding = function(){
	/* ********************************************************************
										PROPERTIES
	*********************************************************************/

	var loadqueue;
	var __XMLOnload = [];
	var __XMLSelect = [];
	var __XMLChoice = [];

	this.__regbase = this.__regbase|__DATABINDING__;
	this.mainBind = "value";

	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/
	
	var sortObj;
	/**
	 * @private
	 */
	this.parseTraverse = function (xmlNode){
		this.ruleTraverse = xmlNode.getAttribute("select");
		sortObj = xmlNode.getAttribute("sort") ? new jpf.Sort(xmlNode) : null;
	}
	
	/**
	 * Sets the bind rule that determines which data nodes are iterated.
	 *
	 * @param  {xpath}  str  required  Xpath specifying a selection of the current dataset
	 * @see    SmartBinding
	 */
	this.setTraverseRule = function(str){
		var tNode = this.bindingRules["traverse"][0];
		tNode.setAttribute("select", str);
		this.parseTraverse(tNode);
		this.reload();
	}
	
	/**
	 * Gets a nodelist containing the data nodes which get representation in this component 
	 * (also known as {@info TraverseNodes "Traverse Nodes"}).
	 *
	 * @param  {XMLNode}  xmlNode  optional  XML Node specifying the parent node on which the traverse Xpath query is executed.
	 * @see    SmartBinding
	 * @define  TraverseNodes  Traverse Nodes are data nodes selected using the j:Traverse bind rule and are looped through to create items which are represented within a databound JML component.
	 */
	this.getTraverseNodes = function(xmlNode){
		if(sortObj){
			var nodes = jpf.XMLDatabase.getArrayFromNodelist((xmlNode || this.XMLRoot).selectNodes(this.ruleTraverse));
			return sortObj.apply(nodes);
		}
		
		return (xmlNode || this.XMLRoot).selectNodes(this.ruleTraverse);
	}
	
	/**
	 * Gets the first data node which gets representation in this component 
	 * (also known as {@info TraverseNodes "Traverse Node"}).
	 *
	 * @param  {XMLNode}  xmlNode  optional  XML Node specifying the parent node on which the traverse Xpath query is executed.
	 * @return  {XMLNode}  the first data node
	 * @see    SmartBinding
	 */
	this.getFirstTraverseNode = function(xmlNode){
		return (xmlNode || this.XMLRoot).selectSingleNode(this.ruleTraverse);
	}

	/**
	 * Gets the last data node which gets representation in this component 
	 * (also known as {@info TraverseNodes "Traverse Node"}).
	 *
	 * @param  {XMLNode}  xmlNode  optional  XML Node specifying the parent node on which the traverse Xpath query is executed.
	 * @return  {XMLNode}  the last data node 
	 * @see    SmartBinding
	 */
	this.getLastTraverseNode = function(xmlNode){
		var nodes = this.getTraverseNodes(xmlNode || this.XMLRoot);//.selectNodes(this.ruleTraverse);
		return nodes[nodes.length-1];
	}

	/**
	 * Determines wether an XML Node is a {@info TraverseNodes "Traverse Node"}
	 *
	 * @param  {XMLNode}  xmlNode  optional  XML Node specifying the parent node on which the traverse Xpath query is executed.
	 * @return  {Boolean}  true   if the XML Node is a Traverse Node
	 *                   false  otherwise.
	 * @see  SmartBinding
	 */
	this.isTraverseNode = function(xmlNode){
		/*
			Added optimization, only when an object has a tree architecture is it 
			important to go up to the traverse parent of the xmlNode, else the node 
			should always be based on the xmlroot of this component
		*/
		var nodes = this.getTraverseNodes(this.isTreeArch ? this.getTraverseParent(xmlNode) || this.XMLRoot : this.XMLRoot);
		for(var i=0;i<nodes.length;i++) if(nodes[i] == xmlNode) return true;
		return false;
	}

	/**
	 * Gets the next {@info TraverseNodes "Traverse Node"} to be selected from a given
	 * Traverse Node. The method can do this in either direction and also return the Nth
	 * node for this algorithm.
	 *
	 * @param  {XMLNode}  xmlNode  required  XML Node specifying the starting point for determining the next selection.
	 * @param  {Boolean}  up  optional  false  Boolean specifying the direction of the selection.
	 * @param  {Integer}  count  optional  1   Integer specifying the distance in number of nodes.
	 * @return  {XMLNode}  the data node to be selected next
	 * @see  SmartBinding
	 */
	this.getNextTraverseSelected = function(xmlNode, up, count){
		if(!xmlNode) var xmlNode = this.value;
		if(!count) count = 1;

		var i=0, nodes = this.getTraverseNodes(this.getTraverseParent(xmlNode) || this.XMLRoot);//.selectNodes(this.ruleTraverse);
		while(nodes[i] && nodes[i] != xmlNode) i++;
		var node = up == null ? nodes[i+count] || nodes[i-count] : (up ? nodes[i+count] : nodes[i-count]);
		return node || arguments[2] && (i < count || (i+1) > Math.floor(nodes.length/count)*count) ? node : (up ? nodes[nodes.length-1] : nodes[0]);
	}

	/**
	 * Gets the next {@info TraverseNodes "Traverse Node"}.
	 * The method can do this in either direction and also return the Nth next node.
	 *
	 * @param  {XMLNode}  xmlNode  required  XML Node specifying the starting point for determining the next node.
	 * @param  {Boolean}  up  optional  false  Boolean specifying the direction.
	 * @param  {Integer}  count  optional  1      Integer specifying the distance in number of nodes.
	 * @return  {XMLNode}  the next Traverse Node
	 * @see  SmartBinding
	 */
	this.getNextTraverse = function(xmlNode, up, count){
		if(!count) count = 1;
		if(!xmlNode) xmlNode = this.value;
		var i=0, nodes = this.getTraverseNodes(this.getTraverseParent(xmlNode) || this.XMLRoot);//.selectNodes(this.ruleTraverse);
		while(nodes[i] && nodes[i] != xmlNode) i++;
		return nodes[i+(up ? -1 * count : count)];
	}

	/**
	 * Gets the parent {@info TraverseNodes "Traverse Node"}.
	 * In some cases the traverse rules has a complex form like 'children/product'. 
	 * In that case the data tree is not used for representation, but a more complex transition,
	 * collapsing multiple levels into a single tree depth. For these situations the
	 * xmlNode.parentNode property won't give you the Traverse Parent, but this method
	 * will give you the right parent. 
	 *
	 * @param  {XMLNode}  xmlNode  required    XML Node for which the parent node will be determined.
	 * @return  {XMLNode}  the parent node
	 * @see  SmartBinding
	 */
	this.getTraverseParent = function(xmlNode){
		if(!xmlNode.parentNode || xmlNode == this.XMLRoot) return false;
		
		var x, id = xmlNode.getAttribute(jpf.XMLDatabase.xmlIdTag);
		if(!id){
			//return false;
			xmlNode.setAttribute(jpf.XMLDatabase.xmlIdTag, "temp");
			id = "temp";
		}

		/*do{
			xmlNode = xmlNode.parentNode;
			if(xmlNode == this.XMLRoot) return false;
			if(this.isTraverseNode(xmlNode)) return xmlNode;
		}while(xmlNode.parentNode);*/
		
		//This is not 100% correct, but good enough for now
		
		//temp untill I fixed the XPath implementation
		if(jpf.isSafari){
			var y = this.ruleTraverse.split("\|");
			for(var i=0;i<y.length;i++){
				x = xmlNode.selectSingleNode("ancestor::node()[(" + y[i] + "/@" + jpf.XMLDatabase.xmlIdTag + "='" + id + "')]");
				break;
			}
		}
		else{
			x = xmlNode.selectSingleNode("ancestor::node()[((" + this.ruleTraverse + ")/@" + jpf.XMLDatabase.xmlIdTag + ")='" + id + "']");
		}
		
		if(id == "temp") xmlNode.removeAttribute(jpf.XMLDatabase.xmlIdTag);
		return x;
	}
	
	/**
	 * Gets the Xpath statement from the main bind rule.
	 * Each databound component which does not implement MultiSelect has a main bind rule.
	 * This method gets the Xpath statement in the select attribute of this rule.
	 *
	 * @return  {String}  the Xpath statement
	 * @see  SmartBinding
	 */
	this.getMainBindXpath = function(){
		if(this.hasFeature(__MULTIBINDING__)) return this.getSelectionSmartBinding().getMainBindXpath();
		var m = this.getModel(true);
		return (m && m.connect ? m.connect.select + "/" : (this.dataParent ? this.dataParent.xpath + "/" : "")) + this.smartBinding.bindings[this.mainBind][0].getAttribute("select");
	}

	/**
	 * Checks wether this component is completely bound.
	 *
	 * @return  {Boolean}  true   this component is fully bound or not bound at all
	 *                   false  this component's bound process is not completed
	 * @see  SmartBinding
	 */
	this.isBoundComplete = function(){
		if(!this.smartBinding) return true;
		if(!this.XMLRoot) return false;
		if(this.hasFeature(__MULTIBINDING__) && !this.getSelectionSmartBinding().XMLRoot) return false;
		return true;
	}
	
	/**
	 * Queries the bound data for a string value
	 *
	 * @param  {String}  xpath  required  Xpath to be queried on the data this component is bound on.
	 * @return  {String}  value of the selected XML Node
	 */
	this.query = function(xpath){
		return jpf.getXmlValue(this.XMLRoot, xpath );
	}
	
	/**
	 * Queries the bound data for an array of string values
	 *
	 * @param  {String}  xpath  required  Xpath to be queried on the data this component is bound on.
	 * @return  {String}  value of the selected XML Node
	 */
	this.queryArray = function(xpath){
		return jpf.getXmlValues(this.XMLRoot, xpath );
	}
	
	/**
	 * @deprecated  As of JPF 0.8
	 *              {@link #isTraverseNode}
	 */
	this.traverseNode = function(node){
		var nodes = node.parentNode.selectNodes(this.ruleTraverse);
		for(var i=0;i<nodes.length;i++) if(nodes[i] == node) return true;
		return false;
	}
	
	/**
	 * Loads the binding rules from the j:bindings element
	 *
	 * @param  {Array}  rules    required  the rules array created using {@link Kernel#getRules(xmlNode)}
	 * @param  {XMLNode}  xmlNode  optional  reference to the j:bindings element
	 * @see  SmartBinding
	 */
	this.loadBindings = function(rules, node){
		if(this.bindingRules) this.unloadBindings();
		this.bindingRules = rules;
		
		jpf.status("Initializing Bindings for " + this.tagName + "[" + (this.name || '') + "]");
		
		if(this.bindingRules["traverse"])
			this.parseTraverse(this.bindingRules["traverse"][0]);

		if(this.__loaddatabinding) this.__loaddatabinding();

		// Load from queued load request
		if(loadqueue){
			this.load(loadqueue[0], loadqueue[1]);
			loadqueue = null;
		}
	}

	/**
	 * Unloads the binding rules from this component
	 *
	 * @see  SmartBinding
	 */
	this.unloadBindings = function(){
		if(this.__unloaddatabinding) this.__unloaddatabinding();
		
		var node = this.xmlBindings;//this.jml.selectSingleNode("Bindings");
		if(!node || !node.getAttribute("connect")) return;

		//Fails if parent window is closing...
		try{
			var o = eval(node.getAttribute("connect"));
			o.disconnect(this, node.getAttribute("type"));

		}catch(e){}//ignore that case

		this.bindingRules = null;

		return this.uniqueId;
	}

	/**
	 * Loads the action rules from the j:actions element
	 *
	 * @param  {Array}  rules    required  the rules array created using {@link Kernel#getRules(xmlNode)}
	 * @param  {XMLNode}  xmlNode  optional  reference to the j:bindings element
	 * @see  SmartBinding
	 */
	this.loadActions = function(rules, node){
		if(this.actionRules) this.unloadActions();
		this.actionRules = rules;
		
		jpf.status("Initializing Actions for " + this.tagName + "[" + (this.name || '') + "]");

		if(node && (jpf.isTrue(node.getAttribute("transaction")) || node.selectSingleNode("starttransaction|rollback|update"))){
			if(!this.hasFeature(__TRANSACTION__)) this.inherit(jpf.Transaction); /** @inherits jpf.Transaction */
			
			//Load ActionTracker & XMLDatabase
			if(!this.__ActionTracker) this.__ActionTracker = new jpf.ActionTracker(this);
			//XMLDatabase = this.parentWindow ? this.parentWindow.XMLDatabase : main.window.XMLDatabase;
			
			this.__ActionTracker.realtime = isTrue(node.getAttribute("realtime"));
			this.defaultMode = node.getAttribute("mode") || "update";
			
			//Turn caching off, it collides with rendering views on copies of data with the same id's
			this.caching = false;
		
			//When is this called?
			//this.XMLDatabase = new jpf.XMLDatabaseImplementation().Init(main.window.XMLDatabase, this.XMLRoot);
			//this.XMLRoot = jpf.XMLDatabase.root;
		}
	}

	/**
	 * Gets the ActionTracker this component communicates with.
	 *
	 * @return  {_ActionTracker}  Reference to the ActionTracker instance used by this component
	 * @see  SmartBinding
	 */
	this.getActionTracker = function(ignoreMe){
		if(!jpf.JmlDomAPI) return jpf.window.__ActionTracker;
		
		var pNode = this, tracker = ignoreMe ? null : this.__ActionTracker;
		if(!tracker && this.connectId) tracker = self[this.connectId].__ActionTracker;
		
		//jpf.XMLDatabase.getInheritedAttribute(this.jml, "actiontracker");
		while(!tracker){
			//if(!pNode.parentNode) throw new Error(1055, jpf.formErrorString(1055, this, "ActionTracker lookup", "Could not find ActionTracker by traversing upwards"));
			if(!pNode.parentNode) return jpf.window.__ActionTracker;
			
			tracker = (pNode = pNode.parentNode).__ActionTracker;
		}
		return tracker;
	}
	
	/**
	 * Unloads the action rules from this component
	 *
	 * @see  SmartBinding
	 */
	this.unloadActions = function(){
		this.xmlActions = null;
		this.actionRules = null;
		
		//Weird, this cannot be correct... (hack?)
		if(this.__ActionTracker){
			if(this.__ActionTracker.stackDone.length) jpf.issueWarning(0, "Component : " + this.name + " [" + this.tagName + "]\nMessage : ActionTracker still have undo stack filled with " + this.ActionTracker.stackDone.length + " items.")
		
			this.__ActionTracker = null;
		}
	}
	
	/**
	 * Executes an action using action rules set in the j:actions element
	 *
	 * @param  {String}  atAction   required  String specifying the function known to the ActionTracker of this component.
	 * @param  {Array}  args    required  Array containing the arguments to the function specified in <code>atAction</code>.
	 * @param  {String}  action   required  String specifying the name of the action rule defined in j:actions for this component.
	 * @param  {XMLNode}  xmlNode  required  XML data node specifying the context for the action rules.
	 * @param  {Boolean}  noevent  optional  Boolean specifying wether or not to call events.
	 * @param  {XMLNode}  contextNode  optional  XML node setting the context node for action processing (such as RPC calls). Usually the same as <code>xmlNode</code>
	 * @return  {Boolean}  specifies success or failure
	 * @see  SmartBinding
	 */
	this.executeAction = function(atAction, args, action, xmlNode, noevent, contextNode){
		if(this.disabled) return; //hack

		jpf.status("Executing action '" + action + "' for " + this.tagName + " [" + (this.name || "") + "]");

		//Get Rules from Array
		var id, rules = this.actionRules ? this.actionRules[action] : (!action.match(/Change|Select/) && jpf.appsettings.autoDisableActions ? false : []);
		if(!rules) return false;

		for(var node=null,i=0;i<(rules.length || 1);i++){
			if(
				!rules[i] || !rules[i].getAttribute("select") || 
				xmlNode.selectSingleNode(rules[i].getAttribute("select"))
			){
				//Call Event and cancel if it returns false
				if(!noevent){
					var eventres;
					//var evntres = this[evnt] ? this[evnt](args) : true;
					//if(typeof evntres == "boolean" && !evntres) 
					if((evntres = this.dispatchEvent("onbefore" + action.toLowerCase(), {arguments : args})) === false) return false;
					if(typeof evntres == "object" || typeof evntres == "array"){
						atAction = evntres[0];
						args = evntres[1];
					}
				}
				
				//Call ActionTracker and return ID of Action in Tracker
				if(typeof atAction == "string")
					id = this.getActionTracker().execute(atAction, args, rules[i], this, contextNode);
				//Only execute the action
				else if(rules[i]){
					if(typeof atAction == "function") atAction.call(this);
					if(rules[i]) new jpf.UndoData("", rules[i], args, this, contextNode).saveChange(false, this.getActionTracker());
				}

				//Call After Event
				this.dispatchEvent("onafter" + action.toLowerCase());

				return id;
			}
		}

		//Action not executed
		return false;
	}
	
	this.executeActionByRuleSet = function(atName, setName, xmlNode, value){
		var xpath, selInfo = this.getSelectFromRule(setName, xmlNode);
		var node = selInfo[1];

		if(node){
			if(jpf.XMLDatabase.getNodeValue(node) == value) return; // Do nothing if value is unchanged
			
			var atAction = node.nodeType == 1 || node.nodeType == 3 || node.nodeType == 4 ? "setTextNode" : "setAttribute";
			var args = node.nodeType == 1 ? [node, value] : (node.nodeType == 3 || node.nodeType == 4 ? [node.parentNode, value] : [node.ownerElement || node.selectSingleNode(".."), node.nodeName, value]);
		}
		else{
			if(!this.createModel) return false;
			var atAction = "setValueByXpath";
			var xpath = selInfo[0];
			
			if(!xmlNode){
				//Assuming this component is connnected to a model
				var model = this.getModel();
				if(!model || !model.data) return false;
				var xpath = (model.getXpathByJmlNode(this) || ".") + (xpath && xpath != "." ? "/" + xpath : "");
				var xmlNode = model.data;
			}
			
			var args = [xmlNode, value, xpath];
		}
		
		//Use Action Tracker
		this.executeAction(atAction, args, atName, xmlNode);
	}

	/**
	 * Connects a JML component to this component. 
	 * This connection is used to push data from this component to the other component.
	 * Whenever this component loads data, (a selection of) the data is pushed to
	 * the other component. For components inheriting from MultiSelect data is pushed
	 * when a selection occurs.
	 *
	 * @param  {JmlNode}  oComponent  required  JmlNode specifying the component which is connected to this component.
	 * @param  {Boolean}  dataOnly  optional  true  data is sent only once.
	 *                                        false  default  real connection is made.
	 * @param  {String}  xpath   optional  String specifying the Xpath statement used to select a subset of the data to sent.
	 * @param  {String}  type   optional  select  default  sents data when a node is selected
	 *                                        choice  sents data when a node is chosen (by double clicking, or pressing enter)
	 * @see  SmartBinding
	 * @see  #disconnect
	 */
	this.connect = function(o, dataOnly, xpath, type, noselect){
		if(o.dataParent) o.dataParent.parent.disconnect(o);
		
		if(!this.signalXmlUpdate) this.signalXmlUpdate = {};
		o.dataParent = {parent : this, xpath : xpath};
		
		//Onload - check if problem when doing setConnections to early
		if(dataOnly){
			if(!xpath && !this.value){throw new Error(1056, jpf.formErrorString(1056, null, "Connecting", "Illegal XPATH statement specified: '" + xpath + "'"))}

			if(__XMLOnload) return __XMLOnload.push([o, xpath]);
			else return o.load(xpath ? this.XMLRoot.selectSingleNode(xpath) : this.value);//(this.value || this.XMLRoot)
		}

		//jpf.debug Message
		//alert(this.tagName + ":" + o.tagName + " - " + type + "["+dataOnly+"]");

		//User action - Select || Choice
		if(!dataOnly) !type || type == "select" ? __XMLSelect.push({o:o,xpath:xpath}) : __XMLChoice.push({o:o,xpath:xpath});

		//Load Default
		if(type != "choice" && !noselect){
			if(this.value || !this.ruleTraverse && this.XMLRoot){
				var xmlNode = this.value || this.XMLRoot;
				if(xpath){
					xmlNode = xmlNode.selectSingleNode(xpath);
					if(!xmlNode){
						//Hack!!
						this.addEventListener("onxmlupdate", function(){
							this.connect(o, false, xpath, type);
							this.removeEventListener("onxmlupdate", arguments.callee);
						});
					}
				}
				
				if(xmlNode) o.load(xmlNode);
			}
			else{
				if(o.clear && !o.hasFeature(__MULTIBINDING__)) o.clear(); //adding o.hasFeature(__MULTIBINDING__) is a quick fix. should be only with the bind="" level
				if(o.disable) o.disable();
			}
		}
	}

	/**
	 * Disconnects a JML component from this component. 
	 *
	 * @param  {JmlNode}  oComponent  required  JmlNode specifying the component to be disconnected from this component.
	 * @param  {String}  type   optional  select  default  disconnects the select connection
	 *                                        choice  disconnects the choice connection
	 * @see  SmartBinding
	 * @see  #connect
	 */
	this.disconnect = function(o, type){
		//User action - Select || Choice
		var ar = !type || type == "select" ? __XMLSelect : __XMLChoice; //This should be both when there is no arg set

		this.signalXmlUpdate[o.uniqueId] = null;
		delete this.signalXmlUpdate[o.uniqueId];
		o.dataParent = null;

		//CAN BE OPTIMIZED IF NEEDED TO ONLY SET TO null
		for(var i=0;i<ar.length;i++){
			if(ar[i].o != o) continue;
	
			for(var j=i;j<ar.length;j++)
				ar[j] = ar[j+1];
			ar.length--;
			i--;
		}
	}

	/**
	 * Pushes data to connected components 
	 *
	 * @param  {XMLNode}  xmlNode  required  XML data node to be pushed to the connected components.
	 * @param  {String}  type   optional  select  default  pushes data to the components registered for selection
	 *                                     choice  pushes data to the components registered for choice
	 * @see  SmartBinding
	 * @see  #connect
	 * @see  #disconnect
	 */
	this.setConnections = function(xmlNode, type){
		var a = type == "both" ? __XMLChoice.concat(__XMLSelect) : (type == "choice" ? __XMLChoice : __XMLSelect);

		//Call Load of objects
		for(var i=0;i<a.length;i++){
			a[i].o.load(a[i].xpath && xmlNode ? xmlNode.selectSingleNode(a[i].xpath) : xmlNode);
		}

		//Set Onload Connections only Once
		if(!__XMLOnload) return;

		for(var i=0;i<__XMLOnload.length;i++)
			__XMLOnload[i][0].load(__XMLOnload[i][1] ? this.XMLRoot.selectSingleNode(__XMLOnload[i][1]) : this.value);//(this.value || this.XMLRoot)

		__XMLOnload = null;
	}
	
	this.importConnections = function(x){
		__XMLSelect = x;
	}
	
	this.getConnections = function(){
		return __XMLSelect;
	}
	
	this.removeConnections = function(){
		__XMLSelect = [];
	}

	/**
	 * Uses bind rules to convert data into a value string 
	 *
	 * @param  {String}  setname   required  String specifying the name of the binding rule set.
	 * @param  {XMLNode}  cnode  required  XML node to which the binding rules are applied.
	 * @param  {String}  def   optional  String specifiying the default (fallback) value for the query.
	 * @return  {String}  the calculated value
	 * @see  SmartBinding
	 */
	this.applyRuleSetOnNode = function(setname, cnode, def){
		if(!cnode) return "";

		//Get Rules from Array
		var ruleset = this.bindingRules;
		if(ruleset) var rules = ruleset[setname];

		if(!rules && !def) jpf.issueWarning(10001, "Could not find a SmartBindings rule for property '" + setname + "' for component " + this.name + " [" + this.tagName + "].")

		if(!rules) return def ? cnode.selectSingleNode(def) : false;
		//if(setname == "From") alert(value);

		for(var node=null,i=0;i<rules.length;i++){
			//if(self.gridFile && gridFile == this && setname == "Load") alert(rules[i].xml + ":\n" + cnode.xml);
			//if(!rules[i].getAttribute("select")) jpf.issueWarning(1057, jpf.formErrorString(1057, this, "Transforming data", "Missing XPath Select statement in Rule: \n" + rules[i].xml));//throw new Error

			var sel = (rules[i].getAttribute("select-eval") ? eval(rules[i].getAttribute("select-eval")) : rules[i].getAttribute("select")) || ".";
			var o = cnode.selectSingleNode(sel);
			//if(!o && this.createModel) o = jpf.XMLDatabase.createNodeFromXpath(cnode, sel);

			if(o){
				this.lastRule = rules[i];
				//this.lastXMLNode = cnode;

				//Return Node if rule contains RPC definition
				if(rules[i].getAttribute("rpc")) return rules[i];

				//Check for Default Value
				else if(rules[i].getAttribute("value")) return rules[i].getAttribute("value");

				//Process XSLT/JSLT Stylesheet if needed
				else if(rules[i].childNodes.length){
					var xsltNode;
					
					//Check Cache
					if(rules[i].getAttribute("cacheId")){
						xsltNode = jpf.NameServer.get("xslt", rules[i].getAttribute("cacheId"));
					}
					else{
						//Find Xslt Node
						var prefix = jpf.findPrefix(rules[i], jpf.ns.xslt);
						var xsltNode;
						
						if(rules[i].getElementsByTagNameNS){
							xsltNode = rules[i].getElementsByTagNameNS(jpf.ns.xslt, "*")[0];
						}
						else{
							var prefix = jpf.findPrefix(rules[i], jpf.ns.xslt, true);
							if(prefix){
								if(!jpf.supportNamespaces) rules[i].ownerDocument.setProperty("SelectionNamespaces", "xmlns:" + prefix + "='" + jpf.ns.xslt + "'");
								xsltNode = rules[i].selectSingleNode(prefix + ":*");
							}
						}
							
						if(xsltNode){
							if(xsltNode[jpf.TAGNAME] != "stylesheet"){
								//Add it
								var baseXslt = jpf.NameServer.get("base", "xslt");
								if(!baseXslt){
									baseXslt = jpf.getObject("XMLDOM", '<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:template match="node()"></xsl:template></xsl:stylesheet>').documentElement;
									jpf.NameServer.register("base", "xslt", xsltNode);
								}

								var xsltNode = baseXslt.cloneNode(true);
								for(var j=rules[i].childNodes.length;j>=0;j++)
									xsltNode.firstChild.appendChild(rules[i].childNodes[j]);
								
								//Set cache Item
								rules[i].setAttribute("cacheId", jpf.NameServer.add("xslt", xsltNode));
							}
						}
					}
					
					//XSLT
					if(xsltNode){
						var x = o.transformNode(xsltNode).replace(/^<\?xml version="1\.0" encoding="UTF-16"\?>/, "").replace(/\&lt\;/g, "<").replace(/\&gt\;/g, ">").replace(/\&amp\;/g, "&");
					}
					//JSLT
					else{
						var x = jpf.JsltInstance.apply(rules[i], o);
						
					}
					
					if(rules[i].getAttribute("method"))
						try{eval(rules[i].getAttribute("method"))}catch(e){return false;//throw new Error(0, "---- Javeline Error ----\nMessage : Could not find method '" + rules[i].getAttribute("method") + "' referenced in XML.")
					}
					
					return rules[i].getAttribute("method") ? self[rules[i].getAttribute("method")](x, this) : x;
				}

				//Execute Callback if any
				else if(rules[i].getAttribute("method")){
					try{eval(rules[i].getAttribute("method"))}catch(e){throw new Error(1058, jpf.formErrorString(1058, this, "Transforming data", "Could not find method '" + rules[i].getAttribute("method") + "' referenced in XML."))}

					return self[rules[i].getAttribute("method")](o, this);
					//if(!res) continue;
					//else return res;
				}
				
				//Execute Expression
				else if(rules[i].getAttribute("eval")){
					var func = new Function('xmlNode', 'control', "return " + rules[i].getAttribute("eval"));
					var value = func.call(this, o, this);
					if(!value) continue;
					return value;
				}

				//Process XMLElement
				else{
					if(o.nodeType == 1){
						if(!o.firstChild || o.firstChild.nodeType == 1 || o.firstChild.nodeType > 4) return " ";
						//(!o.firstChild || o.firstChild.nodeType == 1 && o.firstChild.nodeType > 4) ? o.appendChild(o.ownerDocument.createTextNode("")) : 
						
						o = o.firstChild;
					}
	
					//Return TextValue of Attribute | Text Node | CDATA Section
					//else if(o.nodeType == 2 || o.nodeType == 3 || o.nodeType == 4){
					var value;
					if(o.nodeType == 2){
						try{value = decodeURI(o.nodeValue);}catch(e){value = o.nodeValue}
						value = unescape(value);
					}
					else value = o.nodeValue;

					//Mask Support
					if(rules[i].getAttribute("mask")){
						if(value.match(/^(?:true|false)$/)) value = value=="true"?1:0;
						return rules[i].getAttribute("mask").split(";")[value];
					}
					else return value;
					//}
					//else return true;
				}

				//return (rules[i].getAttribute("default") || decodeURI(o.nodeValue));//(o.nodeType == 3 ? o.nodeValue : o)
			}
		}

		jpf.issueWarning(10002, "Could not find a SmartBindings rule for property '" + setname + "' which matches any data for component " + this.name + " [" + this.tagName + "].")

		//Applying failed
		return false;
	}

	/**
	 * Assigns a SmartBinding to this component
	 *
	 * @param  {variant}  sb  required  SmartBinding  object to be assigned to this component.
	 *                                String  specifying the name of the SmartBinding.
	 * @throws  Error  If no SmartBinding was passed to the method.
	 * @event  onsetsmartbinding  SmartBinding is added to this component
	 * @see  SmartBinding
	 */
	this.setSmartBinding = function(sb, part){
		if(typeof sb == "string") sb = jpf.JMLParser.getSmartBinding(sb);
		if(!sb) throw new Error(1059, jpf.formErrorString(1059, this, "setSmartBinding Method", "No SmartBinding was found."));
		this.smartBinding = sb;
		this.smartBinding.initialize(this);
		
		this.dispatchEvent("onsetsmartbinding");
	}
	
	/**
	 * Removes the SmartBinding to this component
	 *
	 * @see  SmartBinding
	 */
	this.removeSmartBinding = function(){
		if(this.smartBinding)
			this.smartBinding.deinitialize(this);
	}
	
	/**
	 * Gets the SmartBinding of this component
	 *
	 * @returns  {SmartBinding}  The SmartBinding object of this component
	 * @see  SmartBinding
	 */
	this.getSmartBinding = function(){
		return this.smartBinding;
	}
	
	/**
	 * Sets the reference which creates an implicit databound connection to data.
	 * This rule is usually set in the ref="" tag on the JML node for this component.
	 *
	 * @see  SmartBinding
	 */
	this.setRef = function(bindXPath){
		//ref=""
		//This function doesnt change the model (for now)
		//It also messes with other tags like bindings and actions dragdrop.. which it ignores

		var sb = new jpf.SmartBinding();
		var sModelId = refHandler.call(this, this.jml, bindXPath, this.hasFeature(__MULTISELECT__), sb);
		if(sModelId) jpf.setModel(sModelId, this, this.hasFeature(__MULTISELECT__));
		
		var o = this.hasFeature(__MULTISELECT__) ? this.getSelectionSmartBinding() : this;
		o.removeSmartBinding();
		o.setSmartBinding(sb);
	}
	
	/**
	 * Gets the model to which this component is connected.
	 * This is the model which acts as datasource for this component.
	 *
	 * @returns  {Model}  The model this component is connected to.
	 * @see  SmartBinding
	 */
	this.getModel = function(do_recur){
		if(do_recur && !this.model)
			return this.dataParent ? this.dataParent.parent.getModel(true) : null;
		
		return this.model;
	}
	
	/**
	 * Sets the model to which this component is connected.
	 * This is the model which acts as datasource for this component.
	 *
	 * @param  {Model}  model  required  The model this component is connected to.
	 * @param  {String}  xpath  optional  XPath used to query a subset of the data presented by the model.
	 * @see  SmartBinding
	 */
	this.setModel = function(model, xpath){
		if(typeof model == "string") model = jpf.NameServer.get("model", model);
		model.register(this, xpath);
	}
	
	/**
	 * Gets the data node or binding/action rule of a binding set.
	 *
	 * @param  {String}  setname   required  String specifying the name of the binding/action rule set.
	 * @param  {XMLNode}  cnode  required  XML node to which the binding rules are applied.
	 * @param  {Boolean}  isAction  optional  true  search is for an action rule.
	 *                                        false  otherwise.
	 * @param  {Boolean}  getRule  optional  true  search is for a binding rule.
	 *                                        false  otherwise
	 * @param  {Boolean}  createNode  optional  true  when the data node is not found it is created.
	 *                                        false  the data is never changed
	 * @returns  {XMLNode}  the requested node
	 * @see  SmartBinding
	 */
	this.getNodeFromRule = function(setname, cnode, isAction, getRule, createNode){
		//Get Rules from Array
		var ruleset = isAction ? this.actionRules : this.bindingRules;
		if(ruleset) var rules = ruleset[setname];
		if(!rules) return false;

		for(var i=0;i<rules.length;i++){
			
			var sel = (rules[i].getAttribute("select-eval") ? eval(rules[i].getAttribute("select-eval")) : rules[i].getAttribute("select")) || ".";
			if(!sel) return getRule ? rules[i] : false;
			if(!cnode) return false;
			
			var o = cnode.selectSingleNode(sel);
			if(o) return getRule ? rules[i] : o;
			
			if(createNode || rules[i].getAttribute("create") == "true"){
				var o = jpf.XMLDatabase.createNodeFromXpath(cnode, sel);
				return getRule ? rules[i] : o;
			}
		}

		//Retrieving Failed
		return false;
	}
	
	this.getSelectFromRule = function(setname, cnode){
		var rules = this.bindingRules[setname];
		if(!rules || !rules.length) return ["."];

		for(var first, i=0;i<rules.length;i++){
			var sel = (rules[i].getAttribute("select-eval") ? eval(rules[i].getAttribute("select-eval")) : rules[i].getAttribute("select")) || ".";
			if(!cnode) return [sel];
			if(i == 0) first = sel;
			
			var o = cnode.selectSingleNode(sel);
			if(o) return [sel, o];
		}
		
		return [first];
	}

	/**
	 * Returns bind rule
	 *
	 * @rare
	 */
	this.getBindRule = function(setname, id){
		var rule = false, rules = this.bindingRules ? this.bindingRules[setname] : null;
		if(!rules) return false;
		
		if(setname == "traverse") return rules[0];

		if(typeof id == "number") rule = rules[id];
		else if(typeof id == "object") rule = id;
		else{
			for(var i=0;i<rules.length;i++){
				if(rules[i].getAttribute("id") == id){
					rule = rules[i];
					break;
				}
			}
		}

		return rule;
	}
	
	/**
	 * Add Bind Rule : rule = {rpc:"comm;somefunc",arguments="xpath:@blah;xpath:@iets"}
	 *
	 * @rare
	 */
	this.setBindRule = function(type, id, attributes){
		var el;
		if(id || type == "traverse"){
			var rules = this.bindingRules ? this.bindingRules[type] : null;
			for(var i=0;rules&&i<rules.length;i++){
				if(rules[i].getAttribute("id") == id){
					el = rules[i]
					break;
				}
			}
		}
		if(!el)
			el = this.xmlBindings.appendChild(this.xmlBindings.ownerDocument.createElement(type));
		
		for(prop in attributes)
			if(typeof attributes[prop] == "string")
				el.setAttribute(prop, attributes[prop]);
		
		if(type == "traverse") this.parseTraverse(el);
	}

	/**
	 * Set Bind Rule to something different
	 *
	 * @rare
	 */
	this.removeBindRule = function(setname, id){
		var rule = this.getBindRule(setname, id);
		if(!rule) return false;

		rule.parentNode.removeChild(rule);
	}

	/**
	 * Reloads the data in this component.
	 *
	 */
	this.reload = function(){
		this.load(this.XMLRoot, this.cacheID, true);
	}

	/**
	 * Loads xml data in this component.
	 *
	 * @param  {variant}  xmlRootNode  optional  XMLNode  XML node which is loaded in this component. 
	 *                                          String  Serialize xml which is loaded in this component.
	 *                                          Null  Giving null clears this component {@link Cache#clear}.
	 * @param  {String}  cacheID   optional  XML node to which the binding rules are applied.
	 * @param  {Boolean}  forceNoCache  optional  true  Loads data without checking for a cached rendering.
	 *                                          false  default  Checks cache when loading the data.
	 * @event  onbeforeload  Before loading data in this component.
	 * @event  onafterload  After loading data in this component.
	 * @see  SmartBinding
	 * @see  Cache#clear
	 */
	this.load = function(xmlRootNode, cacheID, forceNoCache){
		jpf.status("Loading XML data in " + this.tagName + "[" + (this.name || '') + "]");
		
		jpf.Popup.forceHide(); //This should be put in a more general position
		
		// If control hasn't loaded databinding yet, buffer the call
		if(!this.bindingRules && this.jml && (!this.smartBinding || jpf.JMLParser.stackHasBindings(this.uniqueId))) //(this.jml.getAttribute("smartbinding") || this.jml.getAttribute("bindings"))) 
			return loadqueue = [xmlRootNode, cacheID];
		
		// Convert first argument to an xmlNode we can use;
		if(xmlRootNode) xmlRootNode = jpf.XMLDatabase.getBindXmlNode(xmlRootNode);
		
		// If no xmlRootNode is given we clear the control, disable it and return
		if(this.dataParent && this.dataParent.xpath) this.dataParent.parent.signalXmlUpdate[this.uniqueId] = !xmlRootNode;
		if(!xmlRootNode){
			this.clear(null, true);
			if(jpf.appsettings.autoDisable && !this.createModel) this.disable();
			this.setConnections();
			return;
		}
		this.disabled = false;
		
		// Remove listen root if available (support for listening to non-available data)
		if(this.listenRoot){
			jpf.XMLDatabase.removeNodeListener(this.listenRoot, this);
			this.listenRoot = null;
		}
		
		//Run onload event
		if(this.dispatchEvent("onbeforeload", {xmlNode : xmlRootNode}) === false) return false;
		
		// If reloading current document, and caching is disabled, exit
		if(this.caching && !forceNoCache && xmlRootNode == this.XMLRoot) return;
		
		// retrieve the cacheId
		if(!cacheID){
			cacheID = xmlRootNode.getAttribute(jpf.XMLDatabase.xmlIdTag) ||
				jpf.XMLDatabase.nodeConnect(jpf.XMLDatabase.getXmlDocId(xmlRootNode), xmlRootNode);
		}

		// Remove message notifying user the control is without data
		if(this.__removeClearMessage) this.__removeClearMessage();
		
		// Retrieve cached version of document if available
		if(this.caching && !forceNoCache && this.getCache(cacheID)){
			if(!this.hasFeature(__MULTISELECT__)) this.setConnections(this.XMLRoot, "select");
			else{
				var nodes = this.getTraverseNodes();
				
				//Information needs to be passed to the followers... even when cached...
				if(nodes.length && this.autoselect) this.select(nodes[0], null, null, null, true);
				else this.setConnections();
			}
			
			this.dispatchEvent('onafterload', {XMLRoot : xmlRootNode});
			return;
		}
		else this.clear(true);

		//Set usefull vars
		this.documentId = jpf.XMLDatabase.getXmlDocId(xmlRootNode);
		this.cacheID = cacheID;
		this.XMLRoot = xmlRootNode;

		// Draw Content
		this.__load(xmlRootNode);

		// Check if subtree should be loaded
		this.__loadSubData(xmlRootNode);
		
		this.disabled = true; //force enabling
		this.enable();

		// Check Connections
		if(!this.hasFeature(__MULTISELECT__)) this.setConnections(this.XMLRoot);

		// Run onafteronload event
		this.dispatchEvent('onafterload', {XMLRoot : xmlRootNode});
	}
	
	this.__loadSubData = function(xmlRootNode){
		if(this.hasLoadStatus(xmlRootNode)) return;
		
		//var loadNode = this.applyRuleSetOnNode("load", xmlRootNode);
		var loadNode, rule = this.getNodeFromRule("load", xmlRootNode, false, true);
		var sel = rule && rule.getAttribute("select") ? rule.getAttribute("select") : ".";

		if(rule && (loadNode = xmlRootNode.selectSingleNode(sel))){
			this.setLoadStatus(xmlRootNode, "loading");
			
			//||jpf.XMLDatabase.findModel(xmlRootNode)
			var mdl = this.getModel(true);
			if(!mdl) throw new Error(0, "Could not find model");

			var jmlNode = this;
			if(mdl.insertFrom(rule.getAttribute("get"), loadNode, this.XMLRoot, this, function(){jmlNode.setConnections(jmlNode.XMLRoot);}) === false){
				this.clear(true);
				if(jpf.appsettings.autoDisable) this.disable();
				this.setConnections(null, "select"); //causes strange behaviour
			}
		}
	}

	/**
	 * @private
	 */
	this.setLoadStatus = function(xmlNode, state, remove){
		//remove old status if any
		var ostatus = xmlNode.getAttribute("j_loaded");
		ostatus = ostatus ? ostatus.replace(new RegExp("\\|\\w+\\:" + this.uniqueId + "\\|", "g"), "") : "";
		if(!remove) ostatus += "|" + state + ":" + this.uniqueId + "|";
		xmlNode.setAttribute("j_loaded", ostatus);
	}
	
	/**
	 * @private
	 */
	this.removeLoadStatus = function(xmlNode){
		this.setLoadStatus(xmlNode, null, true);
	}

	/**
	 * @private
	 */
	this.hasLoadStatus = function(xmlNode, state){
		var ostatus = xmlNode.getAttribute("j_loaded");
		if(!ostatus) return false;

		return (ostatus.indexOf((state || "") + ":" + this.uniqueId + "|") != -1)
	}

	/**
	 * @deprecated  As of JPF 0.9
	 *              {@link Model#insert}
	 */
	this.insert = function(XMLRoot, parentXMLNode, clearContents){
		if(typeof XMLRoot != "object") XMLRoot = jpf.getObject("XMLDOM", XMLRoot).documentElement;
		if(!parentXMLNode) parentXMLNode = this.XMLRoot;
		
		if(this.dispatchEvent("onbeforeinsert", {xmlParentNode : parentXMLNode}) === false) return false;
		
		if(clearContents){
			//clean parent
			var nodes = parentXMLNode.childNodes;
			for(var i=nodes.length-1;i>=0;i--) parentXMLNode.removeChild(nodes[i]);
		}

		//Integrate XMLTree with parentNode
		var newNode = jpf.XMLDatabase.integrate(XMLRoot, parentXMLNode, true);

		//Call __XMLUpdate on all listeners
		jpf.XMLDatabase.applyChanges("insert", parentXMLNode);

		//Select or propagate new data
		if(this.selectable && this.autoselect){
			if(this.XMLRoot == newNode)
				newNode = this.XMLRoot.selectSingleNode(this.ruleTraverse);
			if(newNode) this.select(newNode);
		}
		else if(this.XMLRoot == newNode)
			this.setConnections(this.XMLRoot, "select");
		
		if(this.hasLoadStatus(XMLRoot, "loading"))
			this.setLoadStatus(XMLRoot, "loaded");

		this.dispatchEvent("onafterinsert");
	
		//Check Connections
		//this one shouldn't be called because they are listeners anyway...(else they will load twice)
		//if(this.value) this.setConnections(this.value, "select");
	}

	/* ********************************************************************
										PRIVATE METHODS
	*********************************************************************/
	this.inherit(this.hasFeature(__MULTISELECT__) ? jpf.MultiselectBinding : jpf.StandardBinding); /** @inherits this.hasFeature(__MULTISELECT__) ? jpf.MultiselectBinding : jpf.StandardBinding */
	
	function findModel(x, isSelection){
		return x.getAttribute((isSelection ? "select" : "") + "model") || jpf.XMLDatabase.getInheritedAttribute(x, null, function(xmlNode){
			if(isSelection && x == xmlNode) return false;
			if(xmlNode.getAttribute("model")){
				/*var isCompRef = xmlNode.getAttribute("model").substr(0,1) == "#";
				if(xmlNode.getAttribute("id") && self[xmlNode.getAttribute("id")].hasFeature(__DATABINDING__)){
					var data = xmlNode.getAttribute("model").split(":", 3);
					return "#" + xmlNode.getAttribute("id") + ((isCompRef ? data[2] : data[1]) || "");
				}*/
				return xmlNode.getAttribute("model");
			}
			if(xmlNode.getAttribute("smartbinding")){
				var bclass = x.getAttribute("smartbinding").split(" ")[0];
				if(jpf.NameServer.get("model", bclass)) return bclass + ":select";
			}
			return false
		});
	}

	/**
	 *
	 * @attribute  {String}  bind  Xpath specifying which node to bind to relative to the data loaded in this component.
	 * @attribute  {String}  select-bind  Xpath specifying which node to bind to set the selection of this component.
	 * @attribute  {String}  xslt  URL to an xslt file which when specified processes the selected xml to provide a value for this component.
	 * @attribute  {String}  bind-method  String specifying the JavaScript method which provides the value of this component based on the selected xml.
	 * @attribute  {String}  bind-attach  value  default  this component is bound to the selected xml node.
	 *                                  root            this component is bound to the loaded xml node.
	 */
	function refHandler(x, strBindRef, isSelection, sb){
		var strBind = [];
		
		//This needs to wait untill the bind element becomes available
		if(!strBindRef && x.getAttribute("bind")){
			var bindObj = jpf.NameServer.get("bind", x.getAttribute("bind"));
			
			if(!bindObj) throw new Error(0, jpf.formErrorString(0, this, "Binding Component", "Could not find bind element with name '" + x.getAttribute("bind") + "'"));
			
			/*
				nodeset="" -> <j:Rule select="." />
				readonly="" -> <j:Disabled select="." />
			*/
			strBindRef = bindObj.getAttribute("nodeset");
		}
		else 
			if(!strBindRef && x.getAttribute("ref")) strBindRef = x.getAttribute("ref");
		
		// Check bind tag
		//if(x.getAttribute("ref") && (!bclasses || bclasses.length < 2)){
			
		// Define model
		var modelId = findModel(x, isSelection);
		
		var xsltURL = x.getAttribute("xslt"), bindRoot, bindMethod = x.getAttribute("ref-method");
		//Having createModel check here is a hack, it should detect wether or not the node is/comes available, but too complex for now
		var bindWay = this.createModel || isSelection ? "root" : (jpf.XMLDatabase.getInheritedAttribute(x, "ref-attach") || "value"); 
		if(!modelId){
			if(jpf.JMLParser.globalModel){
				jpf.issueWarning(0, "Cannot find a model to connect to, will try to use default model to connect to SmartBinding", x);
				modelId = "@default";
			}
			else throw new Error(1062, jpf.formErrorString(1062, this, "init", "Could not find model to connect to SmartBinding", x));
		}
		
		if(bindWay == "value"){
			strBindRef.match(/^(.*?)((?:\@[\w-_\:]+|text\(\))(\[.*?\])?|[\w-_\:]+\[.*?\])?$/);
			var valuePath = RegExp.$1;
			if(!valuePath && valuePath !== "") throw new Error(1063, jpf.formErrorString(1063, this, "init SmartBindings", "Could not find xpath to determine XMLRoot: " + strBindRef, x));
			
			var modelIdParts = modelId.split(":", 3);
			var valueSelect = RegExp.$2 || ".";
			
			//Rebuild model string
			modelId = modelIdParts.shift();
			if(modelId.substr(0,1) == "#") modelId += (modelIdParts[0] ? ":" + modelIdParts.shift() : ":select")
			if(modelIdParts[0] || valuePath) modelId += ":" + ((modelIdParts[0] ? modelIdParts[0] + "/" : "") + (valuePath || ".")).replace(/\/$/, "").replace(/\/\/+/, "/");
		}
		strBind.push("<bindings>");

		strBind.push("<" + (this.mainBind || "value") + " select=\"" + (bindWay == "value" ? valueSelect + "\" " : strBindRef.replace(/\"/g, '\\"') + "\" ") + "create=\"true\" ");
		if(bindMethod) strBind.push("method='" + bindMethod + "'");
		if(xsltURL) strBind.push("/><include src='" + xsltURL + "' ");
		if(isSelection && x.getAttribute("selectcaption")) strBind.push("/><caption select='" + x.getAttribute("selectcaption") + "' "); //hack!
		strBind.push("/></bindings>");

		var sb;
		if(strBind.length){
			strBind.unshift("<smartbinding>");
			strBind.push("</smartbinding>");

			var sNode = jpf.getObject("XMLDOM", strBind.join("")).documentElement;
			jpf.loadJMLIncludes(sNode, new jpf.http(), true);
			
			if(sb) sb.loadJML(sNode);
			else jpf.JMLParser.addToSbStack(this.uniqueId, new jpf.SmartBinding(null, sNode), isSelection ? 1 : 0);
		}
		
		return modelId;
	}
	
	/**
	 *
	 * @attribute  {String}  smartbinding   String specifying the name of the SmartBinding for this component.
	 * @attribute  {Boolean}  dragEnabled  true  Component allows dragging of it's items.
	 *                                       false  Component does not allow dragging.
	 * @attribute  {Boolean}  dragMoveEnabled  true  Dragged items are moved or copied when holding the Ctrl key.
	 *                                       false  Dragged items are copied.
	 * @attribute  {Boolean}  dropEnabled  true  Component allows items to be dropped.
	 *                                       false  Component does not receive dropped items.
	 * @attribute  {String}  bindings   String specifying the name of the j:bindings element for this component.
	 * @attribute  {String}  actions   String specifying the name of the j:actions element for this component.
	 * @attribute  {String}  dragdrop   String specifying the name of the j:dragdrop element for this component.
	 * @attribute  {String}  empty   String containing the message displayed by this component when it contains no data.
	 */
	this.__addJmlLoader(function(x){
		var modelId, bclasses;
		if(x.getAttribute("smartbinding")){
			bclasses = x.getAttribute("smartbinding").split(" ");

			if(bclasses.length > 2) jpf.issueWarning(0, "Component : " + this.name + " [" + this.tagName + "]\nMessage : Found more than two smartbindinges, using only the first two.")
			
			for(var i=0;i<Math.min(2,bclasses.length);i++){
				var sNode = jpf.JMLParser.getSmartBinding(bclasses[i]);
	
				if(!sNode) throw new Error(1061, jpf.formErrorString(1061, this, "Jml Loader", "Could not find SmartBindings type set for " + this.tagName + " component with the name : '" + x.getAttribute("smartbinding") + "'"));
			
				jpf.JMLParser.addToSbStack(this.uniqueId, sNode);
			}
		}
		
		//Create model if necesary
		this.createModel = !jpf.isFalse(jpf.XMLDatabase.getInheritedAttribute(this.jml, "create-model"));
		
		
		if(x.getAttribute("ref") && bclasses && bclasses.length > 1) jpf.issueWarning(0, "Component : " + this.name + " [" + this.tagName + "]\nMessage : Found more than one smartbinding and an inline bindings rule, ignoring the bindings rule.")
		
		if((x.getAttribute("ref") || x.getAttribute("bind")) && this.hasFeature(__MULTISELECT__)){
			var sModelId = refHandler.call(this, x, null, true)
			if(sModelId) jpf.setModel(sModelId, this, true);
		}
		
		var strBind = [];
		
		//DragDrop
		if(this.hasFeature(__DRAGDROP__) && (x.getAttribute("dragEnabled") || x.getAttribute("dropEnabled"))){
			/*
			dragEnabled, dropEnabled dragMoveEnabled
			
			<j:allow-drag select="self::Item" />
			<j:allow-drop select="self::Item" target="self::Items" operation="list-append" />
			<j:allow-drop select="self::Item" target="self::Item" operation="insert-before" />
			*/

			strBind = ["<dragdrop>"];
			if(x.getAttribute("dragEnabled") == "true") strBind.push('<allow-drag select="." copy-condition="' + (x.getAttribute("dragMoveEnabled") == "true" ? "event.ctrlKey" : "true") + '"/>');
			if(x.getAttribute("dropEnabled")){
				var sel = x.getAttribute("dropEnabled") != "true" ? "select='" + x.getAttribute("dropEnabled") + "'" : (this.hasFeature(__MULTISELECT__) ? "select-eval=\"'self::' + this.ruleTraverse.split('|').join('|self::')\"" : "select='.'");
				
				strBind.push(
					'<allow-drop ' + sel + ' operation="list-append" copy-condition="' + (x.getAttribute("dragMoveEnabled") == "true" ? "event.ctrlKey" : "true") + '"/>',
					'<allow-drop ' + sel + ' target="." operation="insert-before" copy-condition="' + (x.getAttribute("dragMoveEnabled") == "true" ? "event.ctrlKey" : "true") + '"/>'
				);
			}
			strBind.push("</dragdrop>");
			
			var sNode = jpf.getObject("XMLDOM", strBind.join("")).documentElement;
			(jpf.JMLParser.getFromSbStack(this.uniqueId) || jpf.JMLParser.addToSbStack(this.uniqueId, new jpf.SmartBinding())).addDragDrop(jpf.getRules(sNode));
		}
		
		//Bindings
		if(x.getAttribute("bindings")){
			var sb = jpf.JMLParser.getFromSbStack(this.uniqueId) || jpf.JMLParser.addToSbStack(this.uniqueId, new jpf.SmartBinding());

			if(!jpf.NameServer.get("bindings", x.getAttribute("bindings")))
				throw new Error(1064, jpf.formErrorString(1064, this, "Connecting bindings", "Could not find bindings by name '" + x.getAttribute("bindings") + "'", x));
			
			sb.addBindings(jpf.NameServer.get("bindings", x.getAttribute("bindings")));
		}
		
		//Actions
		if(x.getAttribute("actions")){
			var sb = jpf.JMLParser.getFromSbStack(this.uniqueId) || jpf.JMLParser.addToSbStack(this.uniqueId, new jpf.SmartBinding());
			
			if(!jpf.NameServer.get("actions", x.getAttribute("actions")))
				throw new Error(1065, jpf.formErrorString(1065, this, "Connecting bindings", "Could not find actions by name '" + x.getAttribute("actions") + "'", x));
			
			sb.addActions(jpf.NameServer.get("actions", x.getAttribute("actions")));
		}
		
		//DragDrop
		if(x.getAttribute("dragdrop") && typeof x.getAttribute("dragdrop") == "string"){ //Strange IE behaviour
			var sb = jpf.JMLParser.getFromSbStack(this.uniqueId) || jpf.JMLParser.addToSbStack(this.uniqueId, new jpf.SmartBinding());
			
			if(!jpf.NameServer.get("dragdrop", x.getAttribute("dragdrop")))
				throw new Error(1066, jpf.formErrorString(1066, this, "Connecting dragdrop", "Could not find dragdrop by name '" + x.getAttribute("dragdrop") + "'", x));
			
			sb.addDragDrop(jpf.NameServer.get("dragdrop", x.getAttribute("dragdrop")));
		}

		if((x.getAttribute("ref") || x.getAttribute("bind")) && !this.hasFeature(__MULTISELECT__)){
			modelId = refHandler.call(this, x, null, false);
		}
		else{
			var sb = jpf.JMLParser.getFromSbStack(this.uniqueId);
			if(sb && !sb.model) modelId = findModel(x);
			//!this.hasFeature(__POTENTIAL_MULTIBINDING__) && 
		}

		if(x.getAttribute("empty")) this.msg = x.getAttribute("empty");
		
		if(!this.model && modelId) jpf.setModel(modelId, this, false);
		
		//handle defer update here...
		
	});

	//Trigger Databinding Connections
	this.addEventListener("onbeforeselect", function(e){
		var combinedvalue = null;
		
		if(this.indicator == this.value || e.list && e.list.length > 1 && this.getConnections().length){
			//Multiselect databinding handling... [experimental]
			if(e.list && e.list.length > 1 && this.getConnections().length){
				var oEl = this.XMLRoot.ownerDocument.createElement(this.value.tagName);
				var attr = {};
				
				//Fill basic nodes
				var nodes = e.list[0].attributes;
				for(var j=0;j<nodes.length;j++) attr[nodes[j].nodeName] = nodes[j].nodeValue;
				
				//Remove nodes
				for(var i=1;i<e.list.length;i++){
					for(prop in attr){
						if(typeof attr[prop] != "string") continue;
						
						if(!e.list[i].getAttributeNode(prop)) attr[prop] = undefined;
						else if(e.list[i].getAttribute(prop) != attr[prop]) attr[prop] = "";
					}
				}
				
				//Set attributes
				for(prop in attr){
					if(typeof attr[prop] != "string") continue;
					oEl.setAttribute(prop, attr[prop]);
				}
				
				//missing is childnodes... will implement later when needed...
				
				oEl.setAttribute(jpf.XMLDatabase.xmlIdTag, this.uniqueId);
				jpf.MultiSelectServer.register(oEl.getAttribute(jpf.XMLDatabase.xmlIdTag), oEl, e.list, this);
				jpf.XMLDatabase.addNodeListener(oEl, jpf.MultiSelectServer);
				
				combinedvalue = oEl;
			}
		}
		
		var jNode = this;
		setTimeout(function(){jNode.setConnections(combinedvalue || jNode.value);}, 10);
	});
	
	this.addEventListener("onafterdeselect", function(){
		//this.setConnections(this.value);
		setTimeout('var o = jpf.lookup(' + this.uniqueId + ');o.setConnections(null);', 10);
	});
}

/**
 * @constructor
 * @private
 */
jpf.StandardBinding = function(){
	if(!this.defaultValue) this.defaultValue = "";

	/* ******** __LOAD ***********
		initializes properties of control

		INTERFACE:
		this.__load(XMLRoot);
	****************************/
	this.__load = function(XMLRoot){
		//Add listener to XMLRoot Node
		jpf.XMLDatabase.addNodeListener(XMLRoot, this);

		//Set Properties
		
		
		this.setProperty("value", this.applyRuleSetOnNode(this.mainBind, this.XMLRoot) || this.defaultValue, null, true);
		
		
		//Think should be set in the event by the Validation Class
		if(this.errBox && this.isValid())
			this.clearError(); 
	}

	/* ******** __XMLUPDATE ***********
		Set properties of control

		INTERFACE:
		this.__xmlUpdate(action, xmlNode [, listenNode [, UndoObj]] );
	****************************/
	this.__xmlUpdate = function(action, xmlNode, listenNode, UndoObj){
		//Clear this component if some ancestor has been detached
		if(action == "redo-remove"){
			var testNode = this.XMLRoot;
			while(testNode && testNode.nodeType != 9) testNode = testNode.parentNode;
			if(!testNode){
				//Set Component in listening state untill data becomes available again.
				var model = this.getModel();
				
				if(!model) throw new Error(0, jpf.formErrorString(0, this, "Setting change notifier on component", "Component without a model is listening for changes", this.jml));
				
				return model.loadInJmlNode(this, model.getXpathByJmlNode(this));
			}
		}
		
		//Action Tracker Support
		if(UndoObj) UndoObj.xmlNode = this.XMLRoot;

		//Set Properties
	

		var value = this.applyRuleSetOnNode(this.mainBind, this.XMLRoot) || this.defaultValue;
		if(this.value != value) this.setProperty("value", value, null, true);
		
		
		//Think should be set in the event by the Validation Class
		if(this.errBox && this.isValid())
			this.clearError(); 
	}
	
	if(!this.clear){
		this.clear = function(nomsg, do_event){
			this.documentId = null;
			this.XMLRoot = null;
			this.cacheID = null;
			
			if(this.__clear) this.__clear(nomsg, do_event);
		}
	}
}

/**
 * @constructor
 * @private
 */
jpf.MultiselectBinding = function(){
	/* ******** __LOAD ***********
		Set listeners, calls HTML creation methods and
		initializes select and focus states of object.

		INTERFACE:
		this.__load(XMLRoot);
	****************************/
	this.__load = function(XMLRoot){
		//Add listener to XMLRoot Node
		jpf.XMLDatabase.addNodeListener(XMLRoot, this);

		if(!this.getTraverseNodes(XMLRoot).length) return this.clearAllTraverse();

		//Traverse through XMLTree
		var nodes = this.__addNodes(XMLRoot);

		//Build HTML
		this.__fill(nodes);

		//Select First Child
		if(this.selectable){
			if(this.autoselect){
				if(nodes.length) this.__selectDefault(XMLRoot);
				else this.setConnections();
			}
			else{
				this.clearSelection(null, true);
				var xmlNode = this.getFirstTraverseNode(); //should this be moved to the clearSelection function?
				if(xmlNode) this.setIndicator(xmlNode);
				this.setConnections(null, "both");
			}
		}
		if(this.focussable) jpf.window.isFocussed(this) ? this.__focus() : this.__blur();
	}

	/* ******** __XMLUPDATE ***********
		Loops through parents of changed node to find the first
		connected node. Based on the action it will change, remove
		or update the representation of the data.
		
		@todo  During remove - call all listen nodes with a redo-remove xmlUpdate

		INTERFACE:
		this.__xmlUpdate(action, xmlNode [, listenNode [, UndoObj]] );
	****************************/
	this.__xmlUpdate = function(action, xmlNode, listenNode, UndoObj, lastParent){
		var result, startNode = xmlNode;
		if(!listenNode) listenNode = this.XMLRoot;

		//Get First ParentNode connected
		do{
			if(action == "add" && this.isTraverseNode(xmlNode)) break; //Might want to comment this out for adding nodes under a traversed node
			if(xmlNode.getAttribute(jpf.XMLDatabase.xmlIdTag)){
				var htmlNode = this.getNodeFromCache(xmlNode.getAttribute(jpf.XMLDatabase.xmlIdTag)+"|"+this.uniqueId);
				//if(!htmlNode) alert(xmlNode.getAttribute("id")+"|"+this.uniqueId);

				if(startNode != xmlNode && action.match(/add|remove|insert|synchronize|add/)) action = "update";
				if(xmlNode == listenNode) break;

				if(htmlNode && !action.match(/insert|add|remove|synchronize/) && !this.isTraverseNode(xmlNode))
					action = "remove";
					//break???

				if(!htmlNode && !action.match(/insert|remove|synchronize|move/) && this.isTraverseNode(xmlNode)){
					action = "add";
					break;
				}

				if(htmlNode  || action == "move") break;
			}
			else if(!action.match(/insert|add|remove|synchronize|move-away|move/) && this.isTraverseNode(xmlNode)){
				action = "add";
				break;
			}
			if(xmlNode == listenNode) break;
			xmlNode = xmlNode.parentNode;
		}while(xmlNode && xmlNode.nodeType != 9)

		//if(xmlNode == listenNode && !action.match(/add|synchronize|insert/)) return; //deleting nodes in parentData of object

		var foundNode = xmlNode;
		if(xmlNode && xmlNode.nodeType == 9) xmlNode = startNode;
		
		if(action == "replacechild" && (UndoObj ? UndoObj.args[0] == this.XMLRoot : !this.XMLRoot.parentNode)){
			return this.load(UndoObj ? UndoObj.args[1] : listenNode); //Highly doubtfull this is exactly right...
		}

		//Action Tracker Support - && xmlNode correct here??? - UndoObj.xmlNode works but fishy....
		if(UndoObj && xmlNode && !UndoObj.xmlNode) UndoObj.xmlNode = xmlNode;

		//Check Move -- if value node isn't the node that was moved then only perform a normal update
		if(action == "move" && foundNode == startNode){
			//if(!htmlNode) alert(xmlNode.getAttribute("id")+"|"+this.uniqueId);
			var isInThis = jpf.XMLDatabase.isChildOf(this.XMLRoot, xmlNode.parentNode, true);
			var wasInThis = jpf.XMLDatabase.isChildOf(this.XMLRoot, UndoObj.pNode, true);

			//Move if both previous and current position is within this object
			if(isInThis && wasInThis) this.__moveNode(xmlNode, htmlNode);

			//Add if only current position is within this object
			else if(isInThis) action = "add";

			//Remove if only previous position is within this object
			else if(wasInThis) action = "remove";
		}
		else if(action == "move-away"){
			var goesToThis = jpf.XMLDatabase.isChildOf(this.XMLRoot, UndoObj.toPnode, true);
			if(!goesToThis) action = "remove";
		}
		
		//Remove loading message
		if(this.__removeClearMessage && this.__setClearMessage){
			if(this.getFirstTraverseNode()) this.__removeClearMessage();
			else this.__setClearMessage(this.msg)
		}

		//Check Insert
		if(action == "insert" && (this.isTreeArch || xmlNode == this.XMLRoot)){
			if(this.hasLoadStatus(xmlNode) && this.__removeLoading) this.__removeLoading(htmlNode);
			result = this.__addNodes(xmlNode, (this.__getParentNode ? this.__getParentNode(htmlNode) : htmlNode), true, false);//this.isTreeArch??
			this.__fill(result);

			if(this.selectable && !this.XMLRoot.selectSingleNode(this.ruleTraverse)) jpf.issueWarning(1106, "---- Javeline Error ----\nMessage : No traversable nodes were found for " + this.name + " [" + this.tagName + "]\nTraverse Rule : " + this.ruleTraverse);// + "\nXML string : " + this.XMLRoot.xml)
			if(this.selectable && !this.XMLRoot.selectSingleNode(this.ruleTraverse)) return;

			/*
				Handle Selection - This should actually be done for add/remove/move etc, where it checks wether 
				the selection needs to be adjusted based on the change in data. for instance when a selected node 
				is remove, it should be removed from the selection. Currently the Remove action does this, but
				this is wrong and should be moved to this function
			*/
			if(this.selectable){
				if(this.autoselect) this.select(this.value || this.XMLRoot.selectSingleNode(this.ruleTraverse));
				else this.setIndicator(this.XMLRoot.selectSingleNode(this.ruleTraverse));
			}
		}

		//Check Add
		else if(action == "add"){// || !htmlNode
			//var parentHTMLNode = this.getCacheItemByHtmlId(xmlNode.getAttribute(jpf.XMLDatabase.xmlIdTag)+"|"+this.uniqueId);
			//xmlNode.parentNode == this.XMLRoot ? this.oInt : 
			var parentHTMLNode = xmlNode.parentNode == this.XMLRoot ? this.oInt : this.getCacheItem(xmlNode.parentNode.getAttribute(jpf.XMLDatabase.xmlIdTag)) || this.getNodeFromCache(xmlNode.parentNode.getAttribute(jpf.XMLDatabase.xmlIdTag) + "|" + this.uniqueId);
			//This should be moved into a function (used in setCache as well)
			if(!parentHTMLNode) parentHTMLNode = this.getCacheItem(xmlNode.parentNode.getAttribute(jpf.XMLDatabase.xmlIdTag) || (xmlNode.parentNode.getAttribute(jpf.XMLDatabase.xmlDocTag) ? "doc" + xmlNode.parentNode.getAttribute(jpf.XMLDatabase.xmlDocTag) : false) ) || this.oInt;

			//Only update if node is in current representation or in cache
			if(parentHTMLNode || jpf.XMLDatabase.isChildOf(this.XMLRoot, xmlNode)){
				parentHTMLNode = (this.__findContainer && parentHTMLNode ? this.__findContainer(parentHTMLNode) : parentHTMLNode) || this.oInt;

				var beforeXMLNode = this.getNextTraverse(xmlNode);
				var beforeHTMLNode = beforeXMLNode ? this.getNodeFromCache(beforeXMLNode.getAttribute(jpf.XMLDatabase.xmlIdTag)+"|"+this.uniqueId) : null;

				result = this.__addNodes(xmlNode, parentHTMLNode, true, true, beforeHTMLNode);//&& this.isTreeArch

				if(parentHTMLNode) this.__fill(result);
			}
		}

		//Check Remove
		else if((action == "remove") && foundNode == xmlNode && xmlNode.parentNode){
			
			//Remove HTML Node
			if(htmlNode) this.__deInitNode(xmlNode, htmlNode);
			else if(xmlNode == this.XMLRoot) return this.load(null);
		}

		else if(htmlNode){
			this.__updateNode(xmlNode, htmlNode);
			
			//UpdateDefer 'niceties'
			if(action == "replacechild" && this.hasFeature(__MULTISELECT__) && this.value && xmlNode.getAttribute(jpf.XMLDatabase.xmlIdTag) == this.value.getAttribute(jpf.XMLDatabase.xmlIdTag)){
				this.value = xmlNode;
			}
			
			//if(action == "synchronize" && this.autoselect) this.reselect();
		}
		
		//Check Remove of the data (some ancestor) that this component is bound on
		else if(action == "redo-remove"){
			var testNode = this.XMLRoot;
			while(testNode && testNode.nodeType != 9) testNode = testNode.parentNode;
			if(!testNode){
				//Set Component in listening state untill data becomes available again.
				var model = this.getModel();
				
				if(!model) throw new Error(0, jpf.formErrorString(this, "Setting change notifier on componet", "Component without a model is listening for changes", this.jml));
				
				return model.loadInJmlNode(this, model.getXpathByJmlNode(this));
			}
		}

		var pNode = xmlNode ? xmlNode.parentNode : lastParent;
		if(pNode && pNode.nodeType == 1 && this.isTreeArch){
			do{
				var htmlNode = this.getNodeFromCache(pNode.getAttribute(jpf.XMLDatabase.xmlIdTag)+"|"+this.uniqueId);
				if(htmlNode) this.__updateNode(pNode, htmlNode);
			}while(pNode = this.getTraverseParent(pNode));
		}
		
		if(this.signalXmlUpdate && action.match(/^(?:synchronize|add|insert)$/)){
			var uniqueId;
			for(uniqueId in this.signalXmlUpdate){
				if(parseInt(uniqueId) != uniqueId) continue; //safari_old stuff
				
				var o = jpf.lookup(uniqueId);
				if(!this.value) continue;
				var xmlNode = this.value.selectSingleNode(o.dataParent.xpath);
				if(!xmlNode) continue;
				o.load(xmlNode);
			}
		}

		this.dispatchEvent("onxmlupdate", {action : action, xmlNode : xmlNode, result : result});
	}

	/* ******** __ADDNODES ***********
		Loop through NodeList of selected Traverse Nodes
		and check if it has representation. If it doesn't
		representation is created via __add().

		TODO:
		<Traverse select="" sort="@blah" data-type={"text" | "number" | "script"} method="" order={"ascending" | "descending"} case-order={"upper-first" | "lower-first"} />
		- Also: inserts (auto-sort) see e-messenger behaviour

		INTERFACE:
		this.__addNodes(xmlNode, HTMLParent, checkChildren);
	****************************/
	this.__addNodes = function(xmlNode, parent, checkChildren, isChild, insertBefore){
		if(!this.ruleTraverse){
			throw new Error(1060, jpf.formErrorString(1060, this, "adding Nodes for load", "No traverse SmartBinding rule was specified. This rule is required for a " + this.tagName + " component.", this.jml));
		}

		var isChild = isChild && this.isTraverseNode(xmlNode);
		var htmlNode, lastNode, nodes = isChild ? [xmlNode] : this.getTraverseNodes(xmlNode);//.selectNodes(this.ruleTraverse);
		var loadChildren = nodes.length && this.bindingRules["insert"] ? this.applyRuleSetOnNode("insert", xmlNode) : false;

		for(var i=0;i<nodes.length;i++){
			if(nodes[i].nodeType != 1) continue;

			if(checkChildren) htmlNode = this.getNodeFromCache(nodes[i].getAttribute(jpf.XMLDatabase.xmlIdTag)+"|"+this.uniqueId);

			if(!htmlNode){
				//Retrieve DataBind ID
				var Lid = jpf.XMLDatabase.nodeConnect(this.documentId, nodes[i], null, this);

				//Add Children
				var beforeNode = isChild ? insertBefore : (lastNode ? lastNode.nextSibling : null);//(parent || this.oInt).firstChild);
				var parentNode = this.__add(nodes[i], Lid, isChild ? xmlNode.parentNode : xmlNode, beforeNode ? parent || this.oInt : parent, beforeNode, !beforeNode && i==nodes.length-1);//Should use getTraverParent
				
				//Exit if component tells us its done with rendering
				if(parentNode === false){
					//Tag all needed xmlNodes for future reference
					for(var i=i;i<nodes.length;i++) jpf.XMLDatabase.nodeConnect(this.documentId, nodes[i], null, this);
					break;
				}

				//Parse Children Recursively -> optimize: don't check children that can't exist
				//if(this.isTreeArch) this.__addNodes(nodes[i], parentNode, checkChildren);
			}

			if(checkChildren) lastNode = htmlNode;// ? htmlNode.parentNode.parentNode : null;
		}

		return nodes;
	}
			
}

/*FILEHEAD(/in/Core/Node/DelayedRender.js)SIZE(3495)TIME(1203730484247)*/
__DELAYEDRENDER__ = 1<<11


/**
 * Baseclass adding Delayed rendering features to this Component.
 * A component can delay rendering of subcomponents when it offers the
 * ability to subrender JML components as children together with allowing
 * the components to become visible by some form of interaction. Examples 
 * of these components are ModalWindow, Tab, Pages, Submitform, Container.
 * For instance a Tab page in a container is initally hidden and does not
 * need to be rendered. When the tab button is pressed to activate the page
 * the page is rendered and then displayed. This can dramatically decrease
 * the startup time of the application.
 *
 * @constructor
 * @baseclass
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.8.9
 */
jpf.DelayedRender = function(){
	this.__regbase = this.__regbase|__DELAYEDRENDER__;
	this.isRendered = false;
	
	var withheld = false;
	
	this.__checkDelay = function(x){
		if(x.getAttribute("render") == "runtime"){
			x.setAttribute("render-status", "withheld");
			if(!jpf.JMLParser.renderWithheld) jpf.JMLParser.renderWithheld = [];
			jpf.JMLParser.renderWithheld.push(this);
			
			withheld = true;
			return true;
		}
		
		this.isRendered = true;
		return false;
	}
	
	/**
	 * 
	 *
	 * @param  {Boolean}  usedelay  optional  true  There is a delay between calling this function and the actual rendering, allowing the browsers render engine to draw (for instance a loader).
	 *                                      false  The components are rendered immediately
	 * @event onbeforerender  before components are rendered. Use this event to display a loader.
	 * @event onafterrender  after components are rendered. User this event to hide a loader.
	 * @attribute  {String}  render  init  default  components are rendered during init of the application.
	 *                             runtime  components are rendered when the user requests them.
	 * @attribute  {Boolean}  use-render-delay  true  The components are rendered immediately
	 *                                        false  default  There is a delay between calling this function and the actual rendering, allowing the browsers render engine to draw (for instance a loader).
	 */
	this.render = function(usedelay){
		if(this.isRendered || this.jml.getAttribute("render-status") != "withheld") return;
		this.dispatchEvent("onbeforerender");
		
		if(jpf.isNull(this.usedelay)) 
			this.usedelay = jpf.XMLDatabase.getInheritedAttribute(this.jml, "use-render-delay") == "true";

		if(this.usedelay || usedelay) setTimeout("jpf.lookup(" + this.uniqueId + ").__render()", 10);
		else this.__render();
	}

	this.__render = function(){
		if(this.isRendered) return;
		
		jpf.JMLParser.parseFirstPass(this.jml);
		jpf.JMLParser.parseChildren(this.jml, this.oInt, this);
		
		jpf.layoutServer.activateGrid();
		jpf.layoutServer.activateRules();//document.body
		
		jpf.Profiler.end();
		jpf.status("[TIME] Total load time: " + jpf.Profiler.totalTime + "ms");
		jpf.Profiler.start(true);
		
		jpf.JMLParser.parseLastPass();
		//setTimeout("jpf.JMLParser.parseLastPass();");

		this.jml.setAttribute("render-status", "done");
		this.jml.removeAttribute("render"); //Experimental
		this.isRendered = true;
		withheld = false;
		
		this.dispatchEvent("onafterrender");
	}
}

/*FILEHEAD(/in/Core/Node/Docking.js)SIZE(10424)TIME(1213483123975)*/
__DOCKING__ = 1<<18;


/**
 * Baseclass adding Docking features to this Component.
 *
 * @constructor
 * @baseclass
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.5
 */
jpf.Docking = function(){
	this.__regbase = this.__regbase|__DRAGDROP__;
	
	this.startDocking = function(e){
		if(!this.aData) return jpf.issueWarning(0, "Docking start without alignment set on this element");
		
		jpf.DockServer.start(this.aData, this, e);
	}
}

jpf.DockServer = {
	edge : 30,
	inited : false,
	
	init : function(){
		if(this.inited) return;
		this.inited = true;
		
		jpf.DragMode.defineMode("dockobject", this);
		
		if(!this.nextPositionMarker){
			this.nextPositionMarker = document.body.appendChild(document.createElement("div"));
			this.nextPositionMarker.style.border = "4px solid #555";
			this.nextPositionMarker.style.position = "absolute";
			this.nextPositionMarker.style.zIndex = 10000;
			this.nextPositionMarker.style.filter = "progid:DXImageTransform.Microsoft.Alpha(opacity=50);"
			this.nextPositionMarker.style.opacity = 0.5;
			jpf.setUniqueHtmlId(this.nextPositionMarker);
		}
	},
	
	start : function(oItem, jmlNode, e){
		if(!this.inited) jpf.DockServer.init();
		
		this.dragdata = {
			item : oItem,
			jmlNode : jmlNode,
			x : e.offsetX,
			y : e.offsetY
		}
		
		jpf.DragMode.setMode("dockobject");
		jpf.Plane.show(this.nextPositionMarker);
		
		var pos = jpf.compat.getAbsolutePosition(oItem.oHtml);
		var diff = jpf.compat.getDiff(this.nextPositionMarker);
		this.nextPositionMarker.style.left = pos[0] + "px";
		this.nextPositionMarker.style.top = pos[1] + "px";
		this.nextPositionMarker.style.width = (oItem.oHtml.offsetWidth-diff[0]) + "px"
		this.nextPositionMarker.style.height = (oItem.oHtml.offsetHeight-diff[1]) + "px";
		this.nextPositionMarker.style.display = "block";
		
		jpf.layoutServer.pause(oItem.oHtml.parentNode);
	},
	
	floatElement : function(e){
		this.dragdata.item.setPosition(e.clientX - this.dragdata.x, e.clientY - this.dragdata.y)
		
		if(this.dragdata.item.hidden != 3){
			this.dragdata.item.setFloat();
			this.dragdata.jmlNode.purgeAlignment();
		}
		else jpf.layoutServer.play(this.dragdata.item.oHtml.parentNode);
	},
	
	setPosition : function(e){
		var diff = jpf.compat.getDiff(this.nextPositionMarker);

		this.nextPositionMarker.style.left = (e.clientX - this.dragdata.x) + "px";
		this.nextPositionMarker.style.top = (e.clientY - this.dragdata.y) + "px";
		this.nextPositionMarker.style.width = (this.dragdata.item.size[0] - diff[0]) + "px";
		this.nextPositionMarker.style.height = ((this.dragdata.item.state < 0 ? this.dragdata.item.size[1] : this.dragdata.item.fheight) - diff[1]) + "px";
		
		document.body.style.cursor = "default";
		//jpf.setStyleClass(document.body, "", ["same", "south", "east", "north", "west"]);
	},
	
	onmousemove : function(e){
		if(!e) e = event;
		if(e.button < 1) return false;
		
		jpf.Plane.hide();
		jpf.DockServer.nextPositionMarker.style.top = "10000px";
		//jpf.DockServer.dragdata.jmlNode.oExt.style.top = "10000px";
		
		var el = document.elementFromPoint(e.clientX+document.documentElement.scrollLeft, e.clientY+document.documentElement.scrollTop);
		jpf.Plane.show(jpf.DockServer.nextPositionMarker);
		
		var o = el;
		while(o && !o.host && o.parentNode) o = o.parentNode;
		var jmlNode = o && o.host ? o.host : false;
		var htmlNode = jmlNode.oExt;
		if(!jmlNode.aData || !jmlNode.dock){
			document.body.style.cursor = "";
			jpf.setStyleClass(document.body, "same", ["south", "east", "north", "west"]);
			return jpf.DockServer.setPosition(e);
		}
		
		if(jpf.DockServer.dragdata.item == jmlNode.aData && jmlNode.aData.hidden == 3) return jpf.DockServer.setPosition(e);
		
		var calcData = jmlNode.aData.calcData;
		
		var pos = jpf.compat.getAbsolutePosition(htmlNode);
		var l = e.clientX - pos[0];
		var t = e.clientY - pos[1];
		
		var diff = jpf.compat.getDiff(jpf.DockServer.nextPositionMarker);
		var verdiff = diff[1];
		var hordiff = diff[0];
		
		var region;
		var vEdge = Math.min(jpf.DockServer.edge, htmlNode.offsetHeight/2);
		var hEdge = Math.min(jpf.DockServer.edge, htmlNode.offsetWidth/2);
		
		var r = htmlNode.offsetWidth - l;
		var b = htmlNode.offsetHeight - t;
		
		var p = b/vEdge, q = l/hEdge, z = t/vEdge, w = r/hEdge;
		
		if(p < Math.min(q,w,z)){
			if(b <= vEdge) region = "south";
		}
		else if(w < Math.min(p,z,q)){
			if(r <= hEdge) region = "east";
		}
		else if(q < Math.min(p,z,w)){
			if(l <= hEdge) region = "west";
		}
		else if(z < Math.min(q,w,p)){
			if(t <= vEdge) region = "north";
		}

		if(jpf.DockServer.dragdata.item == jmlNode.aData)
			region = "same";
		
		if(!region) return jpf.DockServer.setPosition(e);
	
		var nextPositionMarker = jpf.DockServer.nextPositionMarker;
		if(region == "west"){
			nextPositionMarker.style.left = pos[0] + "px";
			nextPositionMarker.style.top = pos[1] + "px";
			nextPositionMarker.style.width = ((htmlNode.offsetWidth/2)-hordiff) + "px"
			nextPositionMarker.style.height = (htmlNode.offsetHeight-verdiff) + "px";
		}
		else if(region == "north"){
			nextPositionMarker.style.left = pos[0] + "px";
			nextPositionMarker.style.top = pos[1] + "px";
			nextPositionMarker.style.width = (htmlNode.offsetWidth-hordiff) + "px"
			nextPositionMarker.style.height = (Math.ceil(htmlNode.offsetHeight/2)-verdiff) + "px";
		}
		else if(region == "east"){
			nextPositionMarker.style.left = (pos[0] + Math.ceil(htmlNode.offsetWidth/2)) + "px";
			nextPositionMarker.style.top = pos[1] + "px";
			nextPositionMarker.style.width = ((htmlNode.offsetWidth/2)-hordiff) + "px"
			nextPositionMarker.style.height = (htmlNode.offsetHeight-verdiff) + "px";
		}
		else if(region == "south"){
			nextPositionMarker.style.left = pos[0] + "px";
			nextPositionMarker.style.top = (pos[1] + Math.ceil(htmlNode.offsetHeight/2)) + "px";
			nextPositionMarker.style.width = (htmlNode.offsetWidth-hordiff) + "px"
			nextPositionMarker.style.height = (Math.ceil(htmlNode.offsetHeight/2)-verdiff) + "px";
		}
		else if(region == "same"){
			nextPositionMarker.style.left = pos[0] + "px";
			nextPositionMarker.style.top = pos[1] + "px";
			nextPositionMarker.style.width = (htmlNode.offsetWidth-hordiff) + "px"
			nextPositionMarker.style.height = (htmlNode.offsetHeight-verdiff) + "px";
		}
		
		document.body.style.cursor = "";
		jpf.setStyleClass(document.body, region, ["same", "south", "east", "north", "west"]);
	},
	
	onmouseup : function(e){
		if(!e) e = event;
		if(e.button < 1) return false;

		jpf.Plane.hide();
		jpf.DragMode.clear();
		jpf.DockServer.nextPositionMarker.style.display = "none";
		//jpf.DockServer.dragdata.jmlNode.oExt.style.top = "10000px";
		document.body.className = "";
		
		var el = document.elementFromPoint(e.clientX+document.documentElement.scrollLeft, e.clientY+document.documentElement.scrollTop);
		var o = el;
		while(o && !o.host && o.parentNode) o = o.parentNode;
		var jmlNode = o && o.host ? o.host : false;
		var htmlNode = jmlNode.oExt;
		var aData = jmlNode.aData;
		
		if(!jmlNode.aData || !jmlNode.dock || jpf.DockServer.dragdata.item == jmlNode.aData && jmlNode.aData.hidden == 3){
			//jpf.layoutServer.play(htmlNode.parentNode);
			return jpf.DockServer.floatElement(e);
		}
		if(jpf.DockServer.dragdata.item == jmlNode.aData) return jpf.layoutServer.play(htmlNode.parentNode);
		
		var pos = jpf.compat.getAbsolutePosition(htmlNode);
		var l = e.clientX - pos[0];
		var t = e.clientY - pos[1];
		
		var diff = jpf.compat.getDiff(jpf.DockServer.nextPositionMarker);
		var verdiff = diff[1];
		var hordiff = diff[0];
		
		var region;
		var vEdge = Math.min(jpf.DockServer.edge, htmlNode.offsetHeight/2);
		var hEdge = Math.min(jpf.DockServer.edge, htmlNode.offsetWidth/2);
		
		var r = htmlNode.offsetWidth - l;
		var b = htmlNode.offsetHeight - t;
		
		var p = b/vEdge, q = l/hEdge, z = t/vEdge, w = r/hEdge;
		
		if(p < Math.min(q,w,z)){
			if(b <= vEdge) region = "b";
		}
		else if(w < Math.min(p,z,q)){
			if(r <= hEdge) region = "r";
		}
		else if(q < Math.min(p,z,w)){
			if(l <= hEdge) region = "l";
		}
		else if(z < Math.min(q,w,p)){
			if(t <= vEdge) region = "t";
		}
	
		if(!region) return jpf.DockServer.floatElement(e);
	
		var pHtmlNode = htmlNode.parentNode;
		var l = jpf.layoutServer.layouts[pHtmlNode.getAttribute("id")];
		if(!l) return false;
		
		var root = l.root;//.copy();
		var current = aData;
		
		if(jpf.DockServer.dragdata.item.hidden == 3) 
			jpf.DockServer.dragdata.item.unfloat();
		
		var newItem = jpf.DockServer.dragdata.item;
		var pItem = newItem.parent;
		if(pItem.children.length == 2){
			var fixItem = pItem.children[newItem.stackId == 0 ? 1 : 0];
			fixItem.parent = pItem.parent;
			fixItem.stackId = pItem.stackId;
			fixItem.parent.children[fixItem.stackId] = fixItem;
			fixItem.weight = pItem.weight;
			fixItem.fwidth = pItem.fwidth;
			fixItem.fheight = pItem.fheight;
		}
		else{
			var nodes = pItem.children;
			for(var j=newItem.stackId;j<nodes.length;j++){
				nodes[j] = nodes[j+1];
				if(nodes[j]) nodes[j].stackId = j;
			}
			nodes.length--;
		}
	
		var type = region == "l" || region == "r" ? "hbox" : "vbox";
		var parent = current.parent;
		var newBox = jpf.layoutServer.getData(type, l.layout);
		newBox.splitter = current.splitter;
		newBox.edgeMargin = current.edgeMargin;
		newBox.id = jpf.layoutServer.metadata.push(newBox)-1;
		newBox.parent = parent;
		parent.children[current.stackId] = newBox;
		newBox.stackId = current.stackId;
		newBox.children = region == "b" || region == "r" ? [current, newItem] : [newItem, current];
		current.parent = newItem.parent = newBox
		current.stackId = region == "b" || region == "r" ? 0 : 1;
		newItem.stackId = region == "b" || region == "r" ? 1 : 0;
		
		//if(type == "vbox") 
		newBox.fwidth = current.fwidth;
		//else if(type == "hbox") 
		newBox.fheight = current.fheight;
		
		newItem.weight = current.weight = 1;//current.weight / 2;
		current.fwidth = current.fheight = null;
		
		var root = root.copy();
		l.layout.compile(root);
		l.layout.reset();
		jpf.layoutServer.activateRules(l.layout.parentNode);
	}
}

/*FILEHEAD(/in/Core/Node/DragDrop.js)SIZE(15106)TIME(1205790104099)*/
__DRAGDROP__ = 1<<5;


/**
 * Baseclass adding Drag&Drop features to this Component.
 *
 * @constructor
 * @baseclass
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.5
 */
jpf.DragDrop = function(){
	this.__regbase = this.__regbase|__DRAGDROP__;
	
	/* **********************
			Actions	
	***********************/
	
	/**
	 * Copies a data node to the dataset of this component.
	 *
	 * @action
	 * @param  {XMLNode}  pnode  optional  XML node specifying the parent node to which to copy the data node to. If none specified the root node of the data loaded in this component is used.
	 * @param  {XMLNode}  xmlNode  required  XML data node which is copied.
	 * @param  {XMLNode}  beforeNode  optional  XML node specifying the position where the data node is inserted.
	 */
	this.Copy = function(pnode, xmlNode, beforeNode){
		var xmlNode = xmlNode.cloneNode(true);

		//Use Action Tracker
		var exec = this.executeAction("appendChildNode", [pnode, xmlNode, beforeNode], "copy", xmlNode);
		if(exec !== false) return xmlNode;

	}
	
	/**
	 * Moves a data node to the dataset of this component.
	 *
	 * @action
	 * @param  {XMLNode}  pnode  optional  XML node specifying the parent node to which to move the data node to. If none specified the root node of the data loaded in this component is used.
	 * @param  {XMLNode}  xmlNode  required  XML data node which is copied.
	 * @param  {XMLNode}  beforeNode  optional  XML node specifying the position where the data node is inserted.
	 */
	this.Move = function(pnode, xmlNode, beforeNode){
		//Use Action Tracker
		var exec = this.executeAction("moveNode", [pnode, xmlNode, beforeNode], "move", xmlNode);
		if(exec !== false) return xmlNode;

	}
	
	/* **********************
		JML Integration
	***********************/
	/*
		<j:actions>
			<j:Move select="" rpc="" arguments="" />
			<j:Copy select="" rpc="" arguments="" />
		</j:actions>
		<j:dragdrop allowed="allow.cur" denied="deny.cur">
			<j:allow-drag select="Person" copy-condition="event.ctrlKey" />
			<j:allow-drop select="self::Person" target="Company|Office" action="list-append" copy-condition="event.ctrlKey" />
			<j:allow-drop select="self::Offer" target="Person" action="tree-append" copy-condition="event.ctrlKey" />
		</j:dragdrop>
	*/
	
	/**
	 * Determines wether the user is allowed to drag the passed XML node.
	 *
	 * @param  {XMLNode}  xmlNode  required  XML node subjected to the test.
	 * @return  {Boolean}  result of the test
	 */
	this.isDragAllowed = function(x){
		if(!this.dragdropRules || this.disabled) return false;
		var rules = this.dragdropRules["allow-drag"];
		if(!rules || !rules.length) return false;
		if(!x) return false;
		
		for(var i=0;i<rules.length;i++){
			if(x.selectSingleNode(rules[i].getAttribute("select-eval") ? eval(rules[i].getAttribute("select-eval")) : rules[i].getAttribute("select"))) return rules[i];//"self::" + 
		}
		
		return false;
	}
	
	/**
	 * Determines wether the user is allowed to dropped the passed XML node.
	 *
	 * @param  {XMLNode}  xmlNode  required  XML node subjected to the test.
	 * @return  {Boolean}  result of the test
	 */
	this.isDropAllowed = function(x, target){
		if(!this.dragdropRules || this.disabled) return false;
		var rules = this.dragdropRules["allow-drop"];
		if(!rules || !rules.length) return false;
		if(!target) return false;//throw new Error(0, "What now?");
		
		for(var i=0;i<rules.length;i++){
			var data = x.selectSingleNode(rules[i].getAttribute("select-eval") ? eval(rules[i].getAttribute("select-eval")) : rules[i].getAttribute("select"));//"self::" + 
			
			if(!rules[i].getAttribute("target")) var tgt = target == this.XMLRoot ? target : null;
			else var tgt = target.selectSingleNode(rules[i].getAttribute("target"));//"self::" + 
			
			if(data && tgt && !jpf.XMLDatabase.isChildOf(data, tgt, true))
				return [tgt, rules[i]];
		}
		
		return false;
	}
	
	this.__dragDrop = function(xmlReceiver, xmlNode, rule, defaction, isParent, srcRule, event){
		if(action == "tree-append" && isParent) return false;
		
		/*
			Possibilities:
			
			tree-append [default]: xmlNode.appendChild(movedNode);
			list-append          : xmlNode.parentNode.appendChild(movedNode);
			insert-before        : xmlNode.parentNode.insertBefore(movedNode, xmlNode);
		*/
		var action = rule.getAttribute("operation") || defaction;
		var ifcopy = rule.getAttribute("copycondition") ? eval(rule.getAttribute("copycondition")) : false;
		if(!ifcopy) ifcopy = srcRule.getAttribute("copycondition") ? eval(srcRule.getAttribute("copycondition")) : false;
		var actRule = ifcopy ? 'Copy' : 'Move';

		switch(action){
			case "list-append":
				var sNode = this[actRule](isParent ? xmlReceiver : xmlReceiver.parentNode, xmlNode);
			break;
			case "insert-before":
				var sNode = isParent ? 
					this[actRule](xmlReceiver, xmlNode) :
					this[actRule](xmlReceiver.parentNode, xmlNode, xmlReceiver); 
			break;
			case "tree-append":
				var sNode = this[actRule](xmlReceiver, xmlNode);
			break;
		}

		if(this.selectable && sNode) this.select(sNode);
		
		return sNode;
	}
	
	/* **********************
			Init
	***********************/

	var drag_inited;
	/**
	 * Loads the dragdrop rules from the j:dragdrop element
	 *
	 * @param  {Array}  rules    required  the rules array created using {@link Kernel#getRules(xmlNode)}
	 * @param  {XMLNode}  xmlNode  optional  reference to the j:dragdrop element
	 * @see  SmartBinding
	 */
	this.loadDragDrop = function(rules, node){
		jpf.status("Initializing Drag&Drop for " + this.tagName + "[" + (this.name || '') + "]");
		
		if(rules){
			if(this.dragdropRules) this.unloadDragDrop();

			//Set Properties
			this.dragdropRules = rules;
		}

		//Set cursors
		//SHOULD come from skin
		this.icoAllowed = "";//this.xmlDragDrop.getAttribute("allowed");
		this.icoDenied = "";//this.xmlDragDrop.getAttribute("denied");

		//Setup External Object
		this.oExt.dragdrop = false;

		this.oExt.onmousedown = function(e){
			if(!e) e = event;
			var fEl, srcEl = e.originalTarget || e.srcElement;
			if(this.host.hasFeature(__MULTISELECT__) && srcEl == this.host.oInt) return;
			this.host.dragging = 0;
			
			var srcElement = jpf.hasEventSrcElement ? e.srcElement : e.target;
			if(this.host.allowDeselect && (srcElement == this || srcElement.getAttribute(jpf.XMLDatabase.htmlIdTag)))
				return this.host.clearSelection(); //hacky
			
			//MultiSelect must have carret behaviour AND deselect at clicking white
			//for(prop in e) if(prop.match(/x/i)) str += prop + "\n";
			//alert(str);
			if(this.host.findValueNode) fEl = this.host.findValueNode(srcEl);
			var el = (fEl ? jpf.XMLDatabase.getNode(fEl) : jpf.XMLDatabase.findXMLNode(srcEl));
			if(this.selectable && (!this.host.value || el == this.host.XMLRoot) || !el) return;

			if(this.host.isDragAllowed(this.selectable ? this.host.value : el)){
				this.host.dragging = 1;

				jpf.DragServer.coordinates = {
					srcElement : srcEl, 
					offsetX : e.layerX ? e.layerX - srcEl.offsetLeft : e.offsetX, 
					offsetY : e.layerY ? e.layerY - srcEl.offsetTop : e.offsetY,
					clientX : e.clientX,
					clientY : e.clientY
				};
				
				jpf.DragServer.start(this.host);
			}
			
			//e.cancelBubble = true;
		}

		this.oExt.onmousemove = function(e){
			if(!e) e = event;
			if(this.host.dragging != 1) return;//e.button != 1 || 
			//if(Math.abs(jpf.DragServer.coordinates.offsetX - (e.layerX ? e.layerX - jpf.DragServer.coordinates.srcElement.offsetLeft : e.offsetX)) < 6 && Math.abs(jpf.DragServer.coordinates.offsetY - (e.layerX ? e.layerY - jpf.DragServer.coordinates.srcElement.offsetTop : e.offsetY)) < 6)
				//return;

			//jpf.DragServer.start(this.host);
		}
		
		this.oExt.onmouseup = function(){
			this.host.dragging = 0;
		}
		
		this.oExt.ondragmove = 
		this.oExt.ondragstart = function(){return false}
		
		if(document.elementFromPointAdd)
			document.elementFromPointAdd(this.oExt);

		if(this.__initDragDrop && (!rules || !drag_inited)) this.__initDragDrop();
		drag_inited = true;
	}
	//this.addEventListener("onskinchange", this.loadDragDrop);
	
	/**
	 * Unloads the dragdrop rules from this component
	 *
	 * @see  SmartBinding
	 */
	this.unloadDragDrop = function(){
		this.xmlDragDrop = null;
		this.dragdropRules = null;
		this.icoAllowed = null;
		this.icoDenied = null;
		this.oExt.dragdrop = null;
		this.oExt.onmousedown = null;
		this.oExt.onmousemove = null;
		this.oExt.onmouseup = null;
		this.oExt.ondragmove = null;
		this.oExt.ondragstart = null;
		
		if(document.elementFromPointRemove)
			document.elementFromPointRemove(this.oExt);
	}
}

jpf.DragServer = {
	Init : function(){
		jpf.DragMode.defineMode("dragdrop", this);
	},
	
	/* **********************
			API
	***********************/
	
	start : function(host){
		if(document.elementFromPointReset) document.elementFromPointReset();
		
		//Create Drag Object
		var selection = host.selectable ? host.getSelection()[0] : host.XMLRoot; //currently only a single item is supported
		
		var srcRule = host.isDragAllowed(selection);
		if(!srcRule) return;
		var data = selection.selectSingleNode(srcRule.getAttribute("select"));//"self::" + 
		
		if(host.hasEventListener("ondragdata"))
			data = host.dispatchEvent("ondragdata", {data : data});

		this.dragdata = {
			selection : selection, 
			data : data,
			indicator : host.__showDragIndicator(selection, this.coordinates),
			host : host
		};

		//EVENT - cancellable: ondragstart
		if(host.dispatchEvent("ondragstart", this.dragdata) === false) return false;//(this.host.tempsel ? select(this.host.tempsel) : false);
		host.dragging = 2;

		jpf.DragMode.setMode("dragdrop");
	},
	
	stop : function(runEvent){
		if(this.last) this.dragout();
		
		//Reset Objects
		this.dragdata.host.dragging = 0;
		this.dragdata.host.__hideDragIndicator();
		
		//????EVENT: ondragstop
		//if(runEvent && this.dragdata.host.ondragstop) this.dragdata.host.ondragstop();
		
		jpf.DragMode.clear();
		this.dragdata = null;
	},
	
	m_out : function(){this.style.cursor="default";if(this.__onmouseout) this.__onmouseout();this.onmouseout=this.__onmouseout || null;},
	
	dragover : function(o, el, e){
		if(!e) e = event;
		var fEl;
		if(o.findValueNode) fEl = o.findValueNode(el);
		//if(!fEl) return;
	
		//Check Permission
		var elSel = (fEl ? jpf.XMLDatabase.getNode(fEl) : jpf.XMLDatabase.findXMLNode(el));
		var candrop = o.isDropAllowed ? o.isDropAllowed(this.dragdata.selection, elSel) : false; 
		//EVENT - cancellable: ondragover
		if(o.dispatchEvent("ondragover") === false) candrop = false;
		
		//Set Cursor
		var srcEl = e.originalTarget || e.srcElement;
		srcEl.style.cursor = (candrop ? o.icoAllowed : o.icoDenied);
		if(srcEl.onmouseout != this.m_out){
			srcEl.__onmouseout = srcEl.onmouseout;
			srcEl.onmouseout = this.m_out;
		}
		//o.oExt.style.cursor = (candrop ? o.icoAllowed : o.icoDenied);
		
		//REQUIRED INTERFACE: __dragover()
		if(o && o.__dragover) o.__dragover(el, this.dragdata, candrop);
		
		this.last = o;
	},
	
	dragout : function(o){
		if(this.last == o) return false;
		
		//EVENT: ondragout
		if(o) o.dispatchEvent("ondragout");
		
		//REQUIRED INTERFACE: __dragout()
		if(this.last && this.last.__dragout) this.last.__dragout(null, this.dragdata);
		
		//Reset Cursor
		//o.oExt.style.cursor = "default";
		
		this.last = null;
	},
	
	dragdrop : function(o, el, srcO, e){
		//Check Permission
		var elSel = (o.findValueNode ? jpf.XMLDatabase.getNode(o.findValueNode(el)) : jpf.XMLDatabase.findXMLNode(el));
		var candrop = elSel && o.isDropAllowed ? o.isDropAllowed(this.dragdata.data, elSel) : false; 

		//EVENT - cancellable: ondragdrop
		if(candrop){
			if(o.dispatchEvent("ondragdrop", jpf.extend({}, this.dragdata, {candrop : candrop})) === false) candrop = false;
			else{
				var action = candrop[1].getAttribute("operation") || "list-append";
				if(action == "list-append" && o == this.dragdata.host) candrop = false;
			}
		}

		//Exit if not allowed
		if(!candrop){
			this.dragout(o);
			return false;
		}
		
		//Move XML
		var rNode = o.__dragDrop(candrop[0], this.dragdata.data, candrop[1], action, candrop[0] == o.XMLRoot, srcO.isDragAllowed(this.dragdata.selection), e);
		this.dragdata.resultNode = rNode;
		
		//REQUIRED INTERFACE: __dragdrop()
		if(o && o.__dragdrop) o.__dragdrop(el, this.dragdata, candrop);
		
		//Reset Cursor
		//o.oExt.style.cursor = "default";
		this.last = null;
	},
	
	/* **********************
		Mouse Movements
	***********************/
	
	onmousemove : function(e){
		if(!jpf.DragServer.dragdata) return;
		if(!e) e = event;
		var dragdata = jpf.DragServer.dragdata;
		
		if(!dragdata.started && Math.abs(jpf.DragServer.coordinates.clientX - e.clientX) < 6 && Math.abs(jpf.DragServer.coordinates.clientY - e.clientY) < 6) 
			return;
		
		if(!dragdata.started){
			if(dragdata.host.__dragstart) dragdata.host.__dragstart(null, dragdata);
			dragdata.started = true;
		}
			
		//get Element at x, y
		dragdata.indicator.style.display = "block";
		if(dragdata.indicator) dragdata.indicator.style.top = "10000px";

		jpf.DragServer.dragdata.x = e.clientX+document.documentElement.scrollLeft;
		jpf.DragServer.dragdata.y = e.clientY+document.documentElement.scrollTop;
		var el = document.elementFromPoint(jpf.DragServer.dragdata.x, jpf.DragServer.dragdata.y);
		
		//Set Indicator
		dragdata.host.__moveDragIndicator(e);

		//get Node and call events
		var receiver = jpf.findHost(el);
		
		//Run Events
		jpf.DragServer.dragout(receiver);
		if(receiver)
			jpf.DragServer.dragover(receiver, el, e);
		
		jpf.DragServer.lastTime = new Date().getTime();
	},
	
	onmouseup : function(e){
		if(!e) e = event;
		
		if(!jpf.DragServer.dragdata.started && Math.abs(jpf.DragServer.coordinates.clientX - e.clientX) < 6 && Math.abs(jpf.DragServer.coordinates.clientY - e.clientY) < 6) 
			return;
		
		//get Element at x, y
		var indicator = jpf.DragServer.dragdata.indicator;
		if(indicator) indicator.style.top = "10000px";
		
		jpf.DragServer.dragdata.x = e.clientX+document.documentElement.scrollLeft;
		jpf.DragServer.dragdata.y = e.clientY+document.documentElement.scrollTop;
		var el = document.elementFromPoint(jpf.DragServer.dragdata.x, jpf.DragServer.dragdata.y);
		
		//get Node and call events
		var host = jpf.findHost(el);
		
		//Run Events
		if(host != jpf.DragServer.host) jpf.DragServer.dragout(host);
		jpf.DragServer.dragdrop(host, el, jpf.DragServer.dragdata.host, e);
		jpf.DragServer.stop(true)
		
		//Clear Selection
		if(jpf.isNS){
			var selObj = window.getSelection();
			if(selObj) selObj.collapseToEnd();
		}
	}
}

jpf.Init.addConditional(function(){jpf.DragServer.Init();}, null, 'jpf');

/*FILEHEAD(/in/Core/Node/EditMode.js)SIZE(9953)TIME(1205790104099)*/
__EDITMODE__ = 1<<15;
__MULTILANG__ = 1<<16;


jpf.KeywordServer = {
	automatch : false,
	prefix : "sub.main.",
	words : {},
	texts : {},
	elements : {},
	count : 0,
	
	setWordListXml : function(xmlNode, prefix){
		if(typeof xmlNode == "string") xmlNode = jpf.getObject("XMLDOM", xmlNode).documentElement;
		this.parseSection(xmlNode, prefix);
	},
	
	parseSection : function(xmlNode, prefix){
		if(!prefix) prefix = "";
		
		if(xmlNode.tagName == "key"){
			prefix += "." + xmlNode.getAttribute("id");
			this.updateWordList(prefix, xmlNode.firstChild ? xmlNode.firstChild.nodeValue : "");
			return;
		}
		
		//if(xmlNode.tagName == "lang") prefix = xmlNode.getAttribute("id");
		if(xmlNode.tagName == "group") prefix += (prefix ? "." : "") + xmlNode.getAttribute("id");
		
		var nodes = xmlNode.childNodes;
		for(var i=0;i<nodes.length;i++) this.parseSection(nodes[i], prefix);
	},
	
	updateWordList : function(key, value){
		this.words[key] = value;
		if(!this.elements[key]) return;
		
		for(var i=0;i<this.elements[key].length;i++){
			if(this.elements[key][i].htmlNode.nodeType == 1)
				this.elements[key][i].htmlNode.innerHTML = value;
			else 
				this.elements[key][i].htmlNode.nodeValue = value;
		}
	},
	
	
	addElement : function(key, oEl){
		if(!this.elements[key]) this.elements[key] = [];
		return this.elements[key].push(oEl) -1;
	},
	
	removeElement : function(key, id){
		this.elements[key].removeIndex(id);
	},
	
	getWord : function(key){
		return this.words[key];
	}
}




/**
 * Baseclass adding Multilingual features to this Component.
 *
 * @constructor
 * @baseclass
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.5
 */
jpf.MultiLang = function(){
	this.__regbase = this.__regbase|__MULTILANG__;
	
	var reggedItems = [];
	this.__makeEditable = function(type, htmlNode, jmlNode){
		if(jmlNode.prefix != "j") return;//using a non-xml format is unsupported
		
		var config = this.editableParts[type];
		for(var i=0;i<config.length;i++){
			var subNode = this.__getLayoutNode(type, config[i][0], htmlNode);
			if(!subNode) continue;
			
			var xmlNode = config ? jpf.XMLDatabase.selectSingleNode(config[i][1], jmlNode) : jpf.XMLDatabase.getTextNode(jmlNode);
			if(!xmlNode) xmlNode = jpf.XMLDatabase.createNodeFromXpath(jmlNode, config[i][1]);
			var key = xmlNode.nodeValue.match(/^\$(.*)\$$/); // is this not conflicting?
			
			if(key){
				subNode = subNode.nodeType == 1 ? subNode : (subNode.nodeType == 3 || subNode.nodeType == 4 ? subNode.parentNode : subNode); //subNode.ownerElement || subNode.selectSinglesubNode("..")
				reggedItems.push([key[1], jpf.KeywordServer.addElement(key[1], {htmlNode : subNode})]);
			}
		}
	}
	
	this.__removeEditable = function(){
		for(var i=0;i<reggedItems.length;i++){
			jpf.KeywordServer.removeElement(reggedItems[i][0], reggedItems[i][1]);
		}
		
		reggedItems = [];
	}
}

//setTimeout('alert("Switch");jpf.KeywordServer.setWordListXml("<group id=\'main\'><key id=\'0\'>aaaaaaa</key></group>", "sub");', 1000);

/*FILEHEAD(/in/Core/Node/JmlDom.js)SIZE(5308)TIME(1203730484247)*/
__JMLDOM__ = 1<<14;


/**
 * Baseclass adding the Document Object Model (DOM) API to this Component.
 *
 * @constructor
 * @baseclass
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.5
 */
jpf.JmlDomAPI = function(){
	this.__regbase = this.__regbase|__JMLDOM__;
	this.childNodes = [];
	
	/**
	 * Adds a component to the end of the list of children of a specified parent component. 
	 * If the component already exists it is removed from current parent component, then added 
	 * to new parent component. 
	 *
	 * @param  {JmlNode}  jmlNode  required  the component to insert as child of this component
	 * @param  {Boolean}  noAlignUpdate  optional  true  Alignment rules are not updated
	 *                                           false  default  Alignment rules are updated
	 * @return  {JmlNode}  the appended node
	 */
	this.appendChild = function(jmlNode, noAlignUpdate){
		jmlNode.removeNode(true);
		
		if(jmlNode.hasFeature(__ALIGNMENT__)){
			var isDisabled = jmlNode.disableAlignment();
			if(isDisabled && !noAlignUpdate) jmlNode.purgeAlignment();
		}
		
		if(jmlNode.hasFeature(__ANCHORING__)) jmlNode.moveAnchoringRules(this.oInt, !noAlignUpdate);
		
		this.childNodes.push(jmlNode);
		jmlNode.parentNode = this;
		
		if(!this.oInt) return; //throw exception??
		this.oInt.appendChild(jmlNode.oExt);
		jmlNode.pHtmlNode = this.oInt;
		
		if(jmlNode.hasFeature(__ALIGNMENT__) && isDisabled){
			jmlNode.enableAlignment();
			if(!noAlignUpdate) jmlNode.purgeAlignment();
		}
		
		return jmlNode;
	}
	
	/**
	 * Inserts a component before another component in a list of children of a specified parent component. 
	 * If the component already exists it is removed from current parent component, then added 
	 * to new parent component. 
	 *
	 * @param  {JmlNode}  jmlNode  required  the component to insert as child of this component
	 * @param  {JmlNode}  beforeNode  required  the component before which <code>jmlNode</code> is inserted
	 * @param  {Boolean}  noAlignUpdate  optional  true  Alignment rules are not updated
	 *                                           false  default  Alignment rules are updated
	 * @return  {JmlNode}  the appended node
	 */
	this.insertBefore = function(jmlNode, beforeNode, noAlignUpdate){
		jmlNode.removeNode(true);
		
		if(jmlNode.hasFeature(__ALIGNMENT__)){
			var isDisabled = jmlNode.disableAlignment();
			if(isDisabled && !noAlignUpdate) jmlNode.purgeAlignment();
		}
		
		var index = this.childNodes.indexOf(beforeNode);
		if(index < 0) throw new Error(1072, jpf.formErrorString(1072, this, "Insert before DOM operation", "could not insert jmlNode, beforeNode could not be found"));
		
		if(jmlNode.hasFeature(__ANCHORING__)) this.moveAnchoringRules(this.oInt, !noAlignUpdate);
		
		this.childNodes = this.childNodes.slice(0, index).concat(jmlNode, this.childNodes.slice(index));
		jmlNode.parentNode = this;
		
		if(!this.oInt) return;
		this.oInt.insertBefore(jmlNode.oExt, beforeNode.oExt);
		jmlNode.pHtmlNode = this.oInt;
		
		if(jmlNode.hasFeature(__ALIGNMENT__) && isDisabled){
			jmlNode.enableAlignment();
			if(!noAlignUpdate) jmlNode.purgeAlignment();
		}
	}
	
	/**
	 * Removes this component from the document hierarchy. 
	 *
	 */
	this.removeNode = function(isAdmin){
		if(!this.parentNode) return;
		
		this.parentNode.childNodes.remove(this);
		this.oExt.parentNode.removeChild(this.oExt);
		
		if(isAdmin) return;
		
		this.destroy();
		
		if(this.hasFeature(__ANCHORING__)) this.disableAnchoring(this.oInt);
	}
	
	/**
	 * Returns a list of elements with the given tag name. 
	 * The subtree underneath the specified element is searched, excluding the element itself.
	 *
	 * @param  {String}  tagName  required  the tag name to look for. The special string "*" represents all elements. 
	 * @return  {Array}  containing any node matching the search string
	 */
	this.getElementsByTagName = function(tagName, norecur){
		tagName = tagName.toLowerCase();
		for(var result=[],i=0;i<this.childNodes.length;i++){
			if(this.childNodes[i].tagName == tagName) result.push(this.childNodes[i]);
			if(!norecur) result = result.concat(this.childNodes[i].getElementsByTagName(tagName));
		}
		return result;
	}
	
	//properties
	this.attributes = {
		length : function(){},
		item : function(){}
	}
	//this.nodeType = 1;
	this.nodeValue = "";
	this.firstChild = this.lastChild = this.nextSibling = this.previousSibling = null;
	this.namespaceURI = jpf.ns.jpf;
	
	//Clone itself same skin, data, bindings connections etc
	/**
	 * @notimplemented
	 */
	this.cloneNode = function(deep){}
	this.serialize = function(){}
	
	/**
	 * @notimplemented
	 */
	this.setAttribute = function(attrName, attrValue){}
	
	/**
	 * @notimplemented
	 */
	this.getAttribute = function(attrName){
		return this.jml.getAttribute(attrName);
	}
	
	if(this.parentNode && this.parentNode.hasFeature && this.parentNode.hasFeature(__JMLNODE__)){
		this.parentNode.childNodes.push(this);
	}
}
/*FILEHEAD(/in/Core/Node/MultiLevelBinding.js)SIZE(8677)TIME(1203730484247)*/
__MULTIBINDING__ = 1<<7;


/*
<BindClass>
	<Data connect="" select="" />
	<Bindings>
		<Value select="" />
	</Bindings>
	<Actions>
		<SelectAdd select="." />
		<SelectRemove select="." />
		<Change select="." />
	</Actions>
</BindClass>
*/

/**
 * Baseclass adding the ability to databind the selection of this Component.
 *
 * @constructor
 * @baseclass
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.5
 */
jpf.MultiLevelBinding = function(jmlNode){
	this.uniqueId = jpf.all.push(this) - 1;
	this.nodeType = NOGUI_NODE;
	this.tagName = "MultiBinding";
	this.name = jmlNode.name + "_multibinding";
	
	jmlNode.__regbase = jmlNode.__regbase|__MULTIBINDING__;
	
	jpf.makeClass(this);
	this.inherit(jpf.DataBinding); /** @inherits jpf.DataBinding */
	this.createModel = jmlNode.createModel; //This should be read dynamically..
	
	this.getActionTracker = function(ignoreMe){
		return jmlNode.getActionTracker(ignoreMe);
	}
	
	this.getHost = function(){return jmlNode;}
	
	this.changeSelection = function(list){
		var xmlNode, selNodes = this.getSelectionNodes(), traverseNodes = jmlNode.getTraverseNodes();
		//Find nodes that are removed from the selection
		for(var removeList=[],i=0;i<selNodes.length;i++){
			for(var k=0;k<traverseNodes.length;k++){
				xmlNode = null;
				if(this.compareNodes(selNodes[i], traverseNodes[k])){
					xmlNode = traverseNodes[k];
					break;
				}
			}
			
			if(!xmlNode || !list.contains(xmlNode)) removeList.push(selNodes[i]);
		}
		
		//Find nodes that are added to the selection
		for(var addList=[],i=0;i<list.length;i++){
			for(var found=false,k=0;k<selNodes.length;k++){
				if(this.compareNodes(selNodes[k], list[i])){
					found = true;
					break;
				}
			}
			
			if(!found) addList.push(mlNode.createSelectionNode(list[i]));
		}

		//Use Action Tracker
		this.executeAction("addRemoveNodes", [this.XMLRoot, addList, removeList], "changeselection", jmlNode.value);
	}
	
	this.change = function(value){
		if(!this.createModel && !this.XMLRoot) return;
		//if(value === undefined) value = this.value ? this.applyRuleSetOnNode("value", this.value) : "";
		
		this.executeActionByRuleSet("change", this.mainBind, this.XMLRoot, value);
	}

	if(jmlNode.hasFeature(__VALIDATION__)){
		this.addEventListener("onbeforechange", function(){jmlNode.dispatchEvent("onbeforechange")});
		this.addEventListener("onafterchange", function(){jmlNode.dispatchEvent("onafterchange")});
	}
	
	this.clear = function(nomsg, do_event){
		if(jmlNode.__showSelection) jmlNode.__showSelection("");
	}
	this.disable = function(){jmlNode.disable();this.disabled=true}
	this.enable = function(){jmlNode.enable();this.disabled=false}
	
	this.__xmlUpdate = function(action, xmlNode, listenNode, UndoObj){
		if(UndoObj) UndoObj.xmlNode = this.XMLRoot;
		this.__updateSelection();
		
		this.dispatchEvent("onxmlupdate", {action : action, xmlNode : xmlNode, listenNode : listenNode});
	}

	this.__load = function(XMLRoot){
		//if(jmlNode.name == "refSMArt_Situatie") debugger;
		//Add listener to XMLRoot Node
		jpf.XMLDatabase.addNodeListener(XMLRoot, this);
		this.__updateSelection();
	}
	
	this.__updateSelection = function(){
		if(!jmlNode.XMLRoot) return;
		
		if(jmlNode.multiselect){
			var xmlNode, selNodes = this.getSelectionNodes(), traverseNodes = jmlNode.getTraverseNodes();
			
			//Check if a selected node is not selected yet
			for(var i=0;i<selNodes.length;i++){
				for(var k=0;k<traverseNodes.length;k++){
					xmlNode = null;
					if(this.compareNodes(selNodes[i], traverseNodes[k])){
						xmlNode = traverseNodes[k];
						break;
					}
				}
				
				if(xmlNode && !jmlNode.isSelected(xmlNode)) jmlNode.select(xmlNode, null, null, null, null, true);
			}
			
			//Check if a currently selected item should be deselected
			var jSelNodes = jmlNode.getSelection();
			for(var i=0;i<jSelNodes.length;i++){
				for(var k=0;k<selNodes.length;k++){
					xmlNode = false;
					if(this.compareNodes(selNodes[k], jSelNodes[i])){
						xmlNode = true;
						break;
					}
				}
				
				if(!xmlNode) jmlNode.select(jSelNodes[i], null, null, null, null, true);
			}
			
			//jmlNode.selectList(selList);
		}
		else{
			if(!jmlNode.XMLRoot){
				//Selection is maintained and visualized, but no Nodes are selected
				if(jmlNode.__showSelection) jmlNode.__showSelection();
				return;
			}

			var xmlNode = jmlNode.findXmlNodeByValue(this.applyRuleSetOnNode(this.mainBind, this.XMLRoot));
			if(xmlNode){
				if(jmlNode.__showSelection) jmlNode.__showSelection(jmlNode.applyRuleSetOnNode("caption", xmlNode));
				if(jmlNode.value != xmlNode){
					jmlNode.select(xmlNode, null, null, null, null, true);
					jmlNode.dispatchEvent("onupdateselect");
					jmlNode.setConnections(xmlNode);
				}
			}
			else if(jmlNode.clearOnNoSelection) jmlNode.clearSelection(null, true);
		}
	}
	
	this.getSelectionNodes = function(){
		return this.XMLRoot.selectNodes(jmlNode.jml.getAttribute("ref"));//This should be read from the bindingRule //this.getTraverseNodes();
	}
	this.getSelectionValue = function(xmlNode){
		return jpf.getXmlValue(xmlNode, "text()")	
	}
	this.getSelectionNodeByValue = function(value, nodes){
		if(!nodes) nodes = this.getSelectionNodes();
		for(var i=0;i<nodes.length;i++){
			if(this.getSelectionValue(nodes[i]) == value) return nodes[i];
		}
		
		return false;
	}
	
	this.mode = "default";//"copy"
	this.xpath = "text()";
	this.createSelectionNode = function(xmlNode){
		if(this.mode == "copy"){
			return jpf.XMLDatabase.clearConnections(xmlNode.cloneNode(true));
		}
		else{
			var value = jmlNode.applyRuleSetOnNode(jmlNode.mainBind, xmlNode);
			var selNode = this.XMLRoot.ownerDocument.createElement(jmlNode.jml.getAttribute("ref"));
			jpf.XMLDatabase.createNodeFromXpath(selNode, this.xpath);
			jpf.XMLDatabase.setNodeValue(selNode.selectSingleNode(this.xpath), value);
			return selNode;
		}
	}
	
	this.compareNodes = function(selNode, traverseNode){
		if(this.mode == "copy"){
			//Other ways of linking should be considered here
			return jmlNode.applyRuleSetOnNode(jmlNode.mainBind, traverseNode) == jmlNode.applyRuleSetOnNode(jmlNode.mainBind, selNode);
		}
		else{
			return jmlNode.applyRuleSetOnNode(jmlNode.mainBind, traverseNode) == this.getSelectionValue(selNode);
		}
	}

	var mlNode = this;
	jmlNode.addEventListener("onafterselect", function (e){
		if(!mlNode.XMLRoot && !this.createModel) return;
		
		if(this.multiselect){
			mlNode.changeSelection(e.list);
		}
		else{
			mlNode.change(this.applyRuleSetOnNode(this.mainBind, e.xmlNode));
		}
	});
	
	//jmlNode.addEventListener("onxmlupdate", function(action, xmlNode){updateSelection.call(this, null, this.value)});
	jmlNode.addEventListener("onafterload", function(){
		if(this.multiselect){
			
		}
		else{
			var xmlNode = this.findXmlNodeByValue(mlNode.applyRuleSetOnNode(mlNode.mainBind, mlNode.XMLRoot));
			if(xmlNode){
				if(jmlNode.__showSelection) jmlNode.__showSelection(jmlNode.applyRuleSetOnNode("caption", xmlNode));
				jmlNode.select(xmlNode, null, null, null, null, true);
				jmlNode.setConnections(xmlNode);
			}
			else if(jmlNode.clearOnNoSelection){
				//This seems cumbersome... check abstraction
				var xmlNode = mlNode.getNodeFromRule(mlNode.mainBind, mlNode.XMLRoot, null, null, true);
				jpf.XMLDatabase.setNodeValue(xmlNode, "");
				if(this.__updateOtherBindings) this.__updateOtherBindings();
				if(this.__showSelection) this.__showSelection();
			}
		}
	});

	jmlNode.addEventListener("onafterdeselect", function(){
		if(!mlNode.XMLRoot) return;
		
		//Remove sel nodes
		if(this.multiselect){
			/*
			//Translate sel to a list of nodes in this xml space
			for(var removeList=[],xmlNode, value, i=0;i<sel.length;i++){
				xmlNode = mlNode.findXmlNodeByValue(this.applyRuleSetOnNode(this.mainBind, sel[i]));
				//Node to be unselected (removed) cannot be found. This should not happen.
				if(!xmlNode) continue;
				removeList.push(xmlNode);
			}
			
			//Remove node using ActionTracker
			if(removeList.length) mlNode.SelectRemove(removeList);
			*/
		}
		//Set value to ""
		else if(jmlNode.clearOnNoSelection){
			this.__updateOtherBindings();
			//mlNode.change("");
			
			//This should be researched better....
			jpf.XMLDatabase.setNodeValue(jpf.XMLDatabase.createNodeFromXpath(mlNode.XMLRoot, mlNode.bindingRules[mlNode.mainBind][0].getAttribute("select")), "", true);
		}
	});
}

/*FILEHEAD(/in/Core/Node/MultiSelect.js)SIZE(27983)TIME(1203730484247)*/
__MULTISELECT__ = 1<<8;


/**
 * Baseclass adding (multi) select features to this Component.
 *
 * @constructor
 * @baseclass
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.5
 */
jpf.MultiSelect = function(){
	/* ********************************************************************
										PROPERTIES
	*********************************************************************/
	
	this.value = null;
	this.selected = null;
	this.indicator = null;
	
	var selSmartBinding;
	var valueList = [];
	var selectedList = [];
	
	this.__regbase = this.__regbase|__MULTISELECT__;
	
	this.autoselect = true;
	this.selectable = true;
	this.multiselect = true;
	this.useindicator = true;
	
	/* ***********************
				ACTIONS
	************************/
	
	/**
	 * Removes (selected) {@info TraverseNodes "Traverse Node(s)"} from the data of this component.
	 *
	 * @action
	 * @param  {XMLNode}  xmlNode  optional  The XML node to be removed. If none is specified, the current selection is removed.
	 * @param  {Boolean}  do_select  optional  true  the next node is selected after removal
	 *                                       false  default  the selection is removed
	 * @return  {Boolean}  specifies if the removal succeeded
	 */
	this.remove = function(xmlNode, do_select){
		if(!xmlNode) xmlNode = valueList;
		if(!xmlNode) return;
		if(!xmlNode.nodeType){
			sel = xmlNode;
			xmlNode = null;//sel[0];
		}
		var rValue;
		
		// Determine next selection
		if(do_select){
			var i=0, nextNode = xmlNode||this.value, ln = this.getSelectCount();
			do{nextNode = this.getDefaultNext(nextNode); i++
			}while(nextNode && this.isSelected(nextNode) && i < ln);
		}
		
		// Remove node(s)
		if(xmlNode && xmlNode.nodeType){
			// Determine next selection
			rValue = this.executeAction("removeNode", [xmlNode], "remove", xmlNode);
		}
		else{
			if(this.actionRules && this.actionRules["RemoveGroup"])
				rValue = this.executeAction("removeNodeList", [sel], "removegroup", sel);
			else{
				for(var i=0;i<sel.length;i++){
					this.executeAction("removeNode", [sel[i]], "remove", sel[i]);
					//var rValue = 
					//if(rValue === false) return false;
				}
			}
		}
		
		//Fix selection if needed
		for(var lst=[],i=0;i<valueList.length;i++) if(valueList[i].parentNode) lst.push(valueList[i]);
		valueList = lst;
		
		if(do_select){
			if(nextNode && rValue !== false) this.select(nextNode);
		}
		else{
			if(valueList.length) this.setIndicator(valueList[0]);
			else{
				var xmlNode = this.getFirstTraverseNode();
				if(xmlNode) this.setIndicator(xmlNode);
			}
		}
		
		return rValue;
	}
	
	/**
	 * @alias  #remove
	 */
	this.removeGroup = this.remove;
	
	/**
	 * Adds a new {@info TraverseNodes "Traverse Node(s)"} to the data of this component.
	 *
	 * @action
	 * @param  {XMLNode}  xmlNode  optional  the XML node to be added. If none is specified the action will use the action rule to get the XML node to add.
	 * @param  {XMLNode}  beforeNode  optional  the XML node before which <code>xmlNode</code> is inserted.
	 * @param  {XMLNode}  pNode  optional  the XML node to which the <code>xmlNode</code> is added as a child.
	 * @return  {Boolean}  specifies if the removal succeeded
	 */
	this.add = function(xmlNode, beforeNode, pNode){
		var node = this.actionRules["add"][0];
		if(!node) throw new Error(0, jpf.formErrorString(0, this, "Add Action", "Could not find Add Node"));
		
		var jmlNode = this; //PROCINSTR
		var callback = function(addXmlNode, state, extra){
			if(state != __HTTP_SUCCESS__){
				if(state == __HTTP_TIMEOUT__ && extra.retries < jpf.maxHttpRetries) return extra.tpModule.retry(extra.id);
				else{
					var commError = new Error(1032, jpf.formErrorString(1032, jmlNode, "Loading xml data", "Could not add data for control " + jmlNode.name + "[" + jmlNode.tagName + "] \nUrl: " + extra.url + "\nInfo: " + extra.message + "\n\n" + xmlNode));
					if(jmlNode.dispatchEvent("onerror", jpf.extend({error : commError, state : status}, extra)) !== false)
						throw commError;
					return;
				}
			}
			
			if(typeof addXmlNode != "object") addXmlNode = jpf.getObject("XMLDOM", addXmlNode).documentElement;
			if(addXmlNode.getAttribute(jpf.XMLDatabase.xmlIdTag)) addXmlNode.setAttribute(jpf.XMLDatabase.xmlIdTag, "");
			
			var actionNode = jmlNode.getNodeFromRule("add", jmlNode.isTreeArch ? jmlNode.value : jmlNode.XMLRoot, true, true);
			if(!pNode && actionNode && actionNode.getAttribute("parent")) pNode = jmlNode.XMLRoot.selectSingleNode(actionNode.getAttribute("parent"));
			
			if(jmlNode.executeAction("appendChildNode", [pNode || jmlNode.XMLRoot, addXmlNode, beforeNode], "add", addXmlNode) !== false && jmlNode.autoselect)
				jmlNode.select(addXmlNode);
				
			return addXmlNode;
		}
		
		if(xmlNode) return callback(xmlNode, __HTTP_SUCCESS__);
		else if(node.getAttribute("get")) return jpf.getData(node.getAttribute("get"), node, callback)
		else if(node.firstChild) return callback(jpf.compat.getNode(node, [0]).cloneNode(true), __HTTP_SUCCESS__);
		
		return addXmlNode;
	}
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/
	if(!this.setValue){
		/**
		 * Sets the value of this component.
		 *
		 * @param  {String}  value  required  String specifying the value to set. For components inheriting from MultiSelect a selection will be made based on the j:Value bind rule. If no item is found, the selection will be cleared.
		 * @see #getValue
		 */
		this.setValue = function(value, no_event){
			if(!this.bindingRules || !this.XMLRoot) return;
			
			if(!this.bindingRules[this.mainBind]) throw new Error(1074, jpf.formErrorString(1074, this, "setValue Method", "Could not find default value bind rule for this control."))
			
			if(jpf.isNot(value)) return this.clearSelection(null, no_event);
			
			var xmlNode = this.findXmlNodeByValue(value);
			if(xmlNode) this.select(xmlNode, null, null, null, null, no_event);
			else return this.clearSelection(null, no_event);
		}
	}
 	
 	/**
 	 * @private
 	 */
	this.findXmlNodeByValue = function(value){
		var nodes = this.getTraverseNodes();
		for(var i=0;i<nodes.length;i++){
			if(this.applyRuleSetOnNode(this.mainBind, nodes[i]) == value){
				return nodes[i];
			}
		}
	}
	
	if(!this.getValue){
		/**
		 * Gets the value of this component.
		 * This is the value that is used for validation of this component.
		 *
		 * @return  {String}  the value of this component
		 * @see #setValue
		 */
		this.getValue = function(){
			if(!this.bindingRules) return false;
			
			if(!this.bindingRules[this.mainBind]) throw new Error(1074, jpf.formErrorString(1074, this, "getValue Method", "Could not find default value bind rule for this control."))
			
			if(!this.multiselect && !this.XMLRoot && selSmartBinding && selSmartBinding.XMLRoot) 
				return selSmartBinding.applyRuleSetOnNode(selSmartBinding.mainBind, selSmartBinding.XMLRoot, null, true);
			
			return this.applyRuleSetOnNode(this.mainBind, this.value, null, true);
		}
	}
	
	/**
	 * Sets the second level SmartBinding for Multilevel Databinding.
	 * For more information see {@link MultiLevelBinding}
	 *
	 * @return  {SmartBinding}  
	 * @see #getSelectionBindClass
	 */
	this.setSelectionSmartBinding = function(smartbinding, part){
		if(!selSmartBinding) selSmartBinding = new jpf.MultiLevelBinding(this);
		selSmartBinding.setSmartBinding(smartbinding, part);
		
		this.dispatchEvent("oninitselbind", {smartbinding : selSmartBinding});
	}
	
	/**
	 * Gets the second level SmartBinding for Multilevel Databinding.
	 * For more information see {@link MultiLevelBinding}
	 *
	 * @return  {SmartBinding}  
	 * @see #setSelectionBindClass
	 */
	this.getSelectionSmartBinding = function(){
		return selSmartBinding;
	}
	
	
	/**
	 * Select the current selection again.
	 *
	 * @todo Add support for multiselect
	 */
	this.reselect = function(){
		if(this.value) this.select(this.value, null, this.ctrlSelect, null, true);//no support for multiselect currently.
	}
	
	var buffered = null;
	/**
	 * Selects a single, or set of {@info TraverseNodes "Traverse Nodes"}.
	 * The selection can be visually represented in this component.
	 *
	 * @param  {variant}  xmlNode  required  XMLNode   XML node to be used in the selection as a start/end point or to toggle the selection on the node.
	 *                                        HTMLNode  HTML node used as visual representation of data node, to be used to determine the XML node for selection.
	 *                                        string    String specifying the value of the {@info TraverseNodes "Traverse Node"} to be selected.
	 * @param  {Boolean}  ctrlKey  optional  true  the Ctrl key was pressed
	 *                                        false  default  otherwise
	 * @param  {Boolean}  shiftKey  optional  true  the Shift key was pressed
	 *                                        false  default  otherwise
	 * @param  {Boolean}  fakeselect  optional  true  only visually make a selection
	 *                                        false  default  otherwise
	 * @param  {Boolean}  force  optional  true  force a reselect
	 *                                        false  default  otherwise
	 * @param  {Boolean}  no_event  optional  true  do not call any events
	 *                                        false  default  otherwise
	 * @return  {Boolean}  specifying wether the selection could be made
	 * @event  onbeforeselect  before a selection is made 
	 * @event  onafterselect  after a selection is made
	 */
	this.select = function(xmlNode, ctrlKey, shiftKey, fakeselect, force, no_event){
		if(!this.selectable || this.disabled) return;
		
		if(this.ctrlSelect && !shiftKey) ctrlKey = true;
		
		// Selection buffering (for async compatibility)
		if(!this.XMLRoot){
			buffered = [arguments, this.autoselect];
			this.autoselect = true;
			return;
		}
		
		if(buffered){
			var x = buffered;
			buffered = null;
			if(this.autoselect) this.autoselect = x[1];
			return this.select.apply(this, x[0]);
		}
		
		var htmlNode;

		/* **** Type Detection *****/
		//if(!this.XMLRoot) throw new Error(0, jpf.formErrorString(0, this, "select Method", "Cannot select on empty dataset.")); //warning?
		if(!xmlNode) throw new Error(1075, jpf.formErrorString(1075, this, "select Method", "Missing xmlNode reference"))

		if(typeof xmlNode != "object"){
			var str = xmlNode;
			xmlNode = jpf.XMLDatabase.getNodeById(xmlNode);
			
			//Select based on the value of the xml node
			if(!xmlNode){
				var sel = str.split("\|");
				var rule = (this.getBindRule("value") || this.getBindRule("caption"));
				if(!rule) throw new Error(0, jpf.formErrorString(0, this, "select Method", "Could not find rule to select by string with"))
				rule = rule.getAttribute("select");
				
				for(var i=0;i<(this.multiselect ? 1 : sel.length);i++){
					sel[i] = "node()[" + rule + "='" + sel[i].replace(/'/g, "\\'") + "']";
				}
				var xpath = sel.join("\|");
				
				var nodes = this.XMLRoot.selectNodes(xpath);
				for(var i=0;i<nodes.length;i++) this.select(nodes[i]);
				return;
			}
		}
		if(!xmlNode.style) htmlNode = this.caching ? this.getNodeFromCache(xmlNode.getAttribute(jpf.XMLDatabase.xmlIdTag)+"|"+this.uniqueId) : document.getElementById(xmlNode.getAttribute(jpf.XMLDatabase.xmlIdTag)+"|"+this.uniqueId); //IE55
		else{
			var id = (htmlNode = xmlNode).getAttribute(jpf.XMLDatabase.htmlIdTag);
			while(!id && htmlNode.parentNode)
				var id = (htmlNode = htmlNode.parentNode).getAttribute(jpf.XMLDatabase.htmlIdTag);
			
			xmlNode = jpf.XMLDatabase.getNodeById(id, this.XMLRoot);
		}

		if(!no_event && this.dispatchEvent('onbeforeselect', {xmlNode : xmlNode, htmlNode : htmlNode}) === false) return false;

		/* **** Selection *****/
		var lastIndicator = this.indicator;
		this.indicator = xmlNode;

		//Multiselect with SHIFT Key.
		if(shiftKey && this.multiselect){
			var range = this.__calcSelectRange(valueList[0] || lastIndicator, xmlNode);

			this.selectList(range);
			if(this.selected) this.__deindicate(this.selected);
			this.selected = this.__indicate(htmlNode);
		}
		
		//Multiselect with CTRL Key.
		else if(ctrlKey && this.multiselect){
			
			//Node will be unselected
			if(valueList.contains(xmlNode)){
				if(!fakeselect){
					selectedList.remove(htmlNode);
					valueList.remove(xmlNode);
				}
				
				if(this.value == xmlNode){
					this.clearSelection(true, true);
					
					if(valueList.length && !fakeselect){
						//this.selected = selectedList[0];
						this.value = valueList[0];
					}
				}
				else this.__deselect(htmlNode, xmlNode);
				
				if(this.selected) this.__deindicate(this.selected);
				this.selected = this.__indicate(htmlNode);
				
				if(htmlNode != this.selindicator){
					this.__deindicate(this.selindicator);
					this.selindicator = htmlNode;
				}
			}
			
			//Node will be selected 
			else{
				if(this.selindicator) this.__deindicate(this.selindicator);
				this.__indicate(htmlNode);
				this.selindicator = htmlNode;
				
				if(this.selected) this.__deindicate(this.selected);
				this.selected = this.__select(htmlNode);
				this.value = xmlNode;
			
				if(!fakeselect){
					selectedList.push(htmlNode);
					valueList.push(xmlNode);
				}
			}
		}
		
		//Return if selected Node is htmlNode during a fake select
		else if(htmlNode && selectedList.contains(htmlNode) && fakeselect) return;
		
		//Normal Selection
		else{
			if(!force && htmlNode && this.selected == htmlNode && valueList.length <= 1 && !this.reselectable && selectedList.contains(htmlNode)) return;
			if(this.value) this.clearSelection(null, true);
			if(this.selected) this.__deindicate(this.selected);

			this.selected = this.__indicate(htmlNode, xmlNode);
			this.selected = this.__select(htmlNode, xmlNode);
			this.value = xmlNode;
			
			selectedList.push(htmlNode);
			valueList.push(xmlNode);
		}

		if(!no_event){
			//You could autodetect this by checking how many listeners this component has
			if(this.delayedSelect){
				var jNode = this;
				setTimeout(function(){jNode.dispatchEvent("onafterselect", {list : valueList, xmlNode : xmlNode});}, 10);
			}
			else this.dispatchEvent("onafterselect", {list : valueList, xmlNode : xmlNode});
		}
		
		return true;
	}

	/**
	 * Choose a {@info TraverseNodes "Traverse Node"}.
	 * The user can do this by either pressing enter or double clicking a selection of this component.
	 *
	 * @param  {variant}  xmlNode  required  XMLNode   XML node to be choosen.
	 *                                        HTMLNode  HTML node used as visual representation of data node, to be used to determine the XML node to be choosen.
	 *                                        string    String specifying the value of the {@info TraverseNodes "Traverse Node"} to be choosen.
	 * @event  onbeforechoose  before a choice is made 
	 * @event  onafterchoose  after a choice is made
	 */
	this.choose = function(xmlNode){
		if(!this.selectable || this.disabled) return;
		
		if(this.dispatchEvent("onbeforechoose", {xmlNode : xmlNode}) === false) return false;
		
		if(xmlNode && !xmlNode.style) this.select(xmlNode);
		
		if(this.hasFeature(__DATABINDING__) && this.dispatchEvent("onafterchoose", {xmlNode : this.value}) !== false)
			this.setConnections(this.value, "choice");
	}
	
	/**
	 * Removes the selection of one or more selected nodes.
	 *
	 * @param  {Boolean}  singleNode  optional  true  deselect the currently indicated node
	 *                                        false  default deselect all selected nodes
	 * @param  {Boolean}  no_event  optional  true  do not call any events
	 *                                        false  default  otherwise
	 * @event  onbeforedeselect  before a choice is made 
	 * @event  onafterdeselect   after a choice is made
	 */
	this.clearSelection = function(singleNode, no_event){
		if(!this.selectable || this.disabled) return;
		
		var clSel = singleNode ? this.value : valueList;
		if(!no_event && this.dispatchEvent("onbeforedeselect", {xmlNode : clSel}) === false) return false;
		
		if(this.value){
			var htmlNode = this.caching ? this.getNodeFromCache(this.value.getAttribute(jpf.XMLDatabase.xmlIdTag)+"|"+this.uniqueId) : document.getElementById(this.value.getAttribute(jpf.XMLDatabase.xmlIdTag)+"|"+this.uniqueId); //IE55
			this.__deselect(htmlNode);
		}
		
		//if(this.selected) this.__deselect(this.selected);
		this.selected = this.value = null;
		
		if(!singleNode){
			for(var i=valueList.length-1;i>=0;i--){
				var htmlNode = this.caching ? this.getNodeFromCache(valueList[i].getAttribute(jpf.XMLDatabase.xmlIdTag)+"|"+this.uniqueId) : document.getElementById(valueList[i].getAttribute(jpf.XMLDatabase.xmlIdTag)+"|"+this.uniqueId); //IE55
				this.__deselect(htmlNode);
			}
			//for(var i=selectedList.length-1;i>=0;i--) this.__deselect(selectedList[i]);
			selectedList = [];
			valueList = [];
		}
		
		if(this.indicator){
			var htmlNode = this.caching ? this.getNodeFromCache(this.indicator.getAttribute(jpf.XMLDatabase.xmlIdTag)+"|"+this.uniqueId) : document.getElementById(this.indicator.getAttribute(jpf.XMLDatabase.xmlIdTag)+"|"+this.uniqueId); //IE55
			this.selected = this.__indicate(htmlNode);
		}
		
		if(!no_event) this.dispatchEvent("onafterdeselect", {xmlNode : clSel});
	}
	
	/**
	 * Selects a set of nodes
	 *
	 * @param  {Array}  xmlNodeList  required  Array consisting of XMLNodes or HTMLNodes specifying the selection to be made.
	 */
	this.selectList = function(xmlNodeList){
		if(!this.selectable || this.disabled) return;
		this.clearSelection(null, true);

		for(var i=0;i<xmlNodeList.length;i++){
			if(xmlNodeList[i].nodeType != 1) continue;
			var xmlNode = xmlNodeList[i];

			//Type Detection
			if(typeof xmlNode != "object") xmlNode = jpf.XMLDatabase.getNodeById(xmlNode);
			if(!xmlNode.style) htmlNode = this.__findNode(null, xmlNode.getAttribute(jpf.XMLDatabase.xmlIdTag) + "|" + this.uniqueId); //IE55
			else{
				htmlNode = xmlNode;
				xmlNode = jpf.XMLDatabase.getNodeById(htmlNode.getAttribute(jpf.XMLDatabase.htmlIdTag));
			}
			
			if(!xmlNode){
				jpf.issueWarning(0, "Component : " + this.name + " [" + this.tagName + "]\nMessage : xmlNode whilst selecting a list of xmlNodes could not be found. Ignoring.")
				continue;
			}

			//Select Node
			if(htmlNode){
				this.__select(htmlNode);
				selectedList.push(htmlNode);
			}
			valueList.push(xmlNode);
		}
		
		this.selected = selectedList[0];
		this.value = valueList[0];
	}
	
	/**
	 * Sets a {@info TraverseNodes "Traverse Nodes"} as the indicator for this component.
	 * The indicator is the position or 'cursor' of the selection. Using the keyboard
	 * a user can change the position of the indicator using the Ctrl key and arrows whilst
	 * not making a selection. When making a selection with the mouse or keyboard the indicator
	 * is always set to the selected node. Unlike a selection there can be only one indicator node.
	 *
	 * @param  {variant}  xmlNode  required  XMLNode   XML node to be used in the selection as a start/end point or to toggle the selection on the node.
	 *                                        HTMLNode  HTML node used as visual representation of data node, to be used to determine the XML node for selection.
	 *                                        string    String specifying the value of the {@info TraverseNodes "Traverse Node"} to be selected.
	 */
	this.setIndicator = function(xmlNode){
		/* **** Type Detection *****/
		if(!xmlNode) throw new Error(1075, jpf.formErrorString(1075, this, "select Method", "Missing xmlNode reference"));

		if(typeof xmlNode != "object") xmlNode = jpf.XMLDatabase.getNodeById(xmlNode);
		if(!xmlNode.style) htmlNode = this.caching ? this.getNodeFromCache(xmlNode.getAttribute(jpf.XMLDatabase.xmlIdTag)+"|"+this.uniqueId) : document.getElementById(xmlNode.getAttribute(jpf.XMLDatabase.xmlIdTag)+"|"+this.uniqueId); //IE55
		else{
			var id = (htmlNode = xmlNode).getAttribute(jpf.XMLDatabase.htmlIdTag);
			while(!id && htmlNode.parentNode)
				var id = (htmlNode = htmlNode.parentNode).getAttribute(jpf.XMLDatabase.htmlIdTag);

			xmlNode = jpf.XMLDatabase.getNodeById(id);
		}

		if(this.selected) this.__deindicate(this.selected);
		this.indicator = xmlNode;
		this.selected = this.__indicate(htmlNode);
	}
	
	/**
	 * Selects all the {@info TraverseNodes "Traverse Nodes"} of this component
	 *
	 */
	this.selectAll = function(){
		if(!this.multiselect || !this.selectable || this.disabled || !this.selected) return;
		var nodes = this.getTraverseNodes();
		//this.select(nodes[0]);
		//this.select(nodes[nodes.length-1], null, true);
		this.selectList(nodes);
	}
	
	/**
	 * Gets an Array or a DocumentFragment containing all the selected {@info TraverseNodes "Traverse Nodes"}
	 *
	 * @param  {Boolean}  xmldoc  optional  true  method returns a DocumentFragment.
	 *                                    false  method returns an Array
	 * @return  {variant}  current selection of this component
	 */
	this.getSelection = function(xmldoc){
		if(xmldoc){
			var r = this.XMLRoot ? this.XMLRoot.ownerDocument.createDocumentFragment() : jpf.getObject("XMLDOM").createDocumentFragment();
			for(var i=0;i<valueList.length;i++) jpf.XMLDatabase.clearConnections(r.appendChild(valueList[i].cloneNode(true)));
		}
		else for(var r=[],i=0;i<valueList.length;i++) r.push(valueList[i]);

		return r;
	}
	
	/**
	 * @private
	 */
	this.getSelectedNodes = function(){
		return valueList;
	}
	
	/**
	 * Selectes the next {@info TraverseNodes "Traverse Node"} to be selected from
	 * a given Traverse Node.
	 *
	 * @param  {XMLNode}  xmlNode  required  The 'context' Traverse Node.
	 */
	this.defaultSelectNext = function(xmlNode, isTree){
		var next = this.getNextTraverseSelected(xmlNode);
		//if(!next && xmlNode == this.XMLRoot) return;

		//Why not use this.isTreeArch ??
		if(next || !isTree) this.select(next ? next : this.getTraverseParent(xmlNode));
		else this.clearSelection(null, true);
	}

	/**
	 * Selects the next {@info TraverseNodes "Traverse Node"} when available.
	 *
	 * @param  {XMLNode}  xmlNode  required  The 'context' Traverse Node.
	 */	
	this.selectNext = function(){
		var xmlNode = this.getNextTraverse();
		if(xmlNode) this.select(xmlNode);
	}
	
	/**
	 * Selects the previous {@info TraverseNodes "Traverse Node"} when available.
	 *
	 * @param  {XMLNode}  xmlNode  required  The 'context' Traverse Node.
	 * @see  SmartBinding
	 */	
	this.selectPrevious = function(){
		var xmlNode = this.getNextTraverse(null, -1);
		if(xmlNode) this.select(xmlNode);	
	}
	
	/**
	 * @private
	 */
	this.getDefaultNext = function(xmlNode, isTree){
		var next = this.getNextTraverseSelected(xmlNode);
		//if(!next && xmlNode == this.XMLRoot) return;

		return next && next != xmlNode ? next : (isTree ? this.getTraverseParent(xmlNode) : false);
	}
	
	/**
	 * Gets the number of currently selected nodes.
	 *
	 * @return  {Integer}  the number of currently selected nodes.
	 */
	this.getSelectCount = function(){
		return valueList.length;
	}
	
	/**
	 * Determines wether a node is selected.
	 *
	 * @param  {XMLNode}  xmlNode  required  The XMLNode to be checked.
	 * @return  {Boolean}  true   the node is selected.
	 *                   false  otherwise
	 */
	this.isSelected = function(xmlNode){
		if(!xmlNode) return false;
		
		for(var i=0;i<valueList.length;i++){
			if(valueList[i] == xmlNode) return true;
		}
		
		return false;
	}
	
	/* ********************************************************************
										PRIVATE METHODS
	*********************************************************************/
	
	/**
	 * @attribute  {Boolean}  multiselect  true   default  The uses may select multiple nodes. Default is false for j:Dropdown.
	 *                                      false  The user cannot select multiple nodes.
	 * @attribute  {Boolean}  autoselect  true   default  After data is loaded in this component a selection is immediately made. Default is false for j:Dropdown.
	 *                                      false  No selection is made automatically
	 *                             string   all    After data is loaded in this component all {@info TraverseNodes "Traverse Nodes"} are selected.
	 * @attribute  {Boolean}  selectable  true   When set to true this component can receive a selection.
	 * @attribute  {Boolean}  ctrl-select  false  When set to true the user makes a selection as if it was holding the Ctrl key.
	 * @attribute  {Boolean}  allow-deselect  true   When set to true the user can remove the selection of a component.
	 * @attribute  {Boolean}  reselectable  false  When set to true selected nodes can be selected again such that the select events are called.
	 * @attribute  {String}  selected   String specifying the value of the {@info TraverseNodes "Traverse Node"} which should be selected after loading data in this component.
	 */
	this.__addJmlLoader(function(x){
		if(x.getAttribute("multiselect")) this.multiselect = x.getAttribute("multiselect") != "false";
		if(x.getAttribute("autoselect")) this.autoselect = x.getAttribute("autoselect") != "false";
		if(x.getAttribute("selectable")) this.selectable = x.getAttribute("selectable") != "false";
		if(x.getAttribute("ctrlselect")) this.ctrlSelect = x.getAttribute("ctrlselect") == "true";
		if(x.getAttribute("allowdeselect") || this.allowDeselect === undefined) 
			this.allowDeselect = x.getAttribute("allowdeselect") != "false";
		if(x.getAttribute("delayedselect") || this.delayedSelect === undefined) 
			this.delayedSelect = x.getAttribute("delayedselect") != "false";
			
		this.allowDeselect = x.getAttribute("allow-deselect") != "false";
		this.reselectable = x.getAttribute("reselectable") != "true";
		
		if(x.getAttribute("autoselect") == "all" && this.multiselect){
			this.addEventListener("onafterload", function(){
				this.selectAll();
			});
		}
		
		if(x.getAttributeNode("selected")){
			this.autoselect = true;
			this.selectXpath(x.getAttribute("selected"));
		}
	});
	
	// Select Bind class
	this.addEventListener("onbeforeselect", function(e){
		if(this.applyRuleSetOnNode("select", e.xmlNode, ".") === false) return false;
	});
}

/**
 * @private
 */
jpf.MultiSelectServer = {
	/**
	 * @private
	 */
	objects : {},
	
	/**
	 * @private
	 */
	register : function(xmlId, xmlNode, selList, jNode){
		if(!this.uniqueId) this.uniqueId = jpf.all.push(this) - 1;
		
		this.objects[xmlId] = {
			xml : xmlNode,
			list : selList,
			jNode : jNode
		}
	},
	
	__xmlUpdate : function(action, xmlNode, listenNode, UndoObj){
		if(action != "attribute") return;
		var data = this.objects[xmlNode.getAttribute(jpf.XMLDatabase.xmlIdTag)];
		if(!data) return;
		var nodes = xmlNode.attributes;

		for(var j=0;j<data.list.length;j++){
			//data[j].setAttribute(UndoObj.name, xmlNode.getAttribute(UndoObj.name));
			jpf.XMLDatabase.setAttribute(data.list[j], UndoObj.name, xmlNode.getAttribute(UndoObj.name));
		}
		
		//jpf.XMLDatabase.synchronize();
	}
}

/*FILEHEAD(/in/Core/Node/Presentation.js)SIZE(12169)TIME(1213483123975)*/
__PRESENTATION__ = 1<<9;


/*
<Root>
	<include src="src/blah.xml />
	<List>
		<style><![CDATA ]]></style>
		<Presentation>
		
		</Presentation>
	</List>
	<Datagrid>
		<style src="" />
		<Presentation>
		
		</Presentation>
	</Datagrid>
</Root>
*/

/**
 * @private
 * @define skin
 * @allowchild  style, presentation
 * @attribute src 
 */
jpf.PresentationServer = {
	skins : {},
	css : [],

	/* ***********
		Init
	************/

	Init : function(xmlNode, refNode, path){
		/*
			get data from refNode || xmlNode
			- name
			- icon-path
			- media-path
			
			all paths of the xmlNode are relative to the src attribute of refNode
			all paths of the refNode are relative to the index.html
			images/ is replaced if there is a refNode to the relative path from index to the skin + /images/
		*/
		var name = (refNode ? refNode.getAttribute("name") : null) || xmlNode.getAttribute("name");
		var base = "";//(refNode && refNode.getAttribute("src").match(/\//) || path) ? (path||refNode.getAttribute("src")).replace(/\/[^\/]*$/, "") + "/" : "";
		var mediaPath = (xmlNode.getAttribute("media-path") ? jpf.getAbsolutePath(base || jpf.hostPath, xmlNode.getAttribute("media-path")) : (refNode ? refNode.getAttribute("media-path") : null));
		var iconPath = (xmlNode.getAttribute("icon-path") ? jpf.getAbsolutePath(base || jpf.hostPath, xmlNode.getAttribute("icon-path")) : (refNode ? refNode.getAttribute("icon-path") : null));
		if(!name) name = "default";
		
		if(xmlNode.getAttribute("name")) document.body.className += " " + xmlNode.getAttribute("name");

		if(!this.skins[name]){
			this.skins[name] = {
				base : base,
				name : name,
				iconPath : iconPath === null ? "icons/" : iconPath,
				mediaPath : mediaPath === null ? "images/" : mediaPath,
				templates : {}
			}
		}
		if(!this.skins["default"]) this.skins["default"] = this.skins[name];

		var nodes = xmlNode.childNodes;
		for(var i=nodes.length-1;i>=0;i--){
			if(nodes[i].nodeType != 1) continue;

			//this.templates[nodes[i].tagName] = nodes[i];
			this.skins[name].templates[nodes[i][jpf.TAGNAME].toLowerCase()] = nodes[i];
			if(nodes[i].ownerDocument)
				this.importSkinDef(nodes[i], base, name);
		}
		
		this.purgeCSS(mediaPath || base + "images/", iconPath || base + "icons/");
	},

	/* ***********
		Import
	************/

	importSkinDef : function(xmlNode, basepath, name){
		var nodes = xmlNode.selectNodes("style");
		for(var i=0;i<nodes.length;i++){
			if(nodes[i].getAttribute("src"))jpf.loadStylesheet(nodes[i].getAttribute("src").replace(/src/,basepath + "/src"));
			else if(nodes[i].getAttribute("condition")){
				try{var test = eval(nodes[i].getAttribute("condition"));}catch(e){test=false;}
				if(test) this.css.push(nodes[i].firstChild.nodeValue);
			}
			else if(nodes[i].firstChild) this.css.push(nodes[i].firstChild.nodeValue);
		}
		
		var nodes = xmlNode.selectNodes("alias");
		for(var i=0;i<nodes.length;i++){
			if(!nodes[i].firstChild) continue;
			this.skins[name].templates[nodes[i].firstChild.nodeValue.toLowerCase()] = xmlNode;
		}
	},

	purgeCSS : function(imagepath, iconpath){
		if(!this.css.length) return;

		var cssString = this.css.join("\n").replace(/images\//g, imagepath).replace(/icons\//g, iconpath);
		jpf.importCssString(document, cssString);
		
		this.css = [];
	},

	/* ***********
		Retrieve
	************/
	
	setSkinPaths : function(skinName, jmlNode){
		skinName = skinName.split(":");
		var name = skinName[0], type = skinName[1];
		
		if(!this.skins[name]){
			throw new Error(1076, jpf.formErrorString(1076, null, "Retrieving Skin", "Could not find skin '" + name + "'", jmlNode.jml));
		}
		
		jmlNode.iconPath = this.skins[name].iconPath;
		jmlNode.mediaPath = this.skins[name].mediaPath;
	},

	getTemplate : function(skinName, cJml){
		skinName = skinName.split(":");
		var name = skinName[0], type = skinName[1];

		if(!this.skins[name]){
			throw new Error(1076, jpf.formErrorString(1076, null, "Retrieving Template", "Could not find skin '" + name + "'", cJml));
		}
		
		if(this.skins[name].templates[type])
			return this.skins[name].templates[type];
	}
}

/**
 * Baseclass adding skinning features to this Component.
 *
 * @constructor
 * @baseclass
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.5
 */
jpf.Presentation = function(){
	/* ********************************************************************
										PROPERTIES
	*********************************************************************/

	var pNodes;

	this.__regbase = this.__regbase|__PRESENTATION__;
	this.skinName = null;
	
	//var cachedExts = {};

	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/

	/**
	 * Switches the skin from the current skin to another one based on the identifier for the new skin.
	 *
	 * @param  {String}  skinName  required  Identifier for the new skin (for example: 'default:List' or 'win').
	 */
	this.changeSkin = function(skinName){
		if(this.skinName == skinName) return;

		if(this.selectable)
			var valueList = this.getSelection();//valueList;
		//cachedExts[this.cacheID] = this.oExt;

		this.baseCSSname = null;
		this.skinName = (skinName.indexOf(":") > -1 ? skinName : skinName + ":" + this.tagName).toLowerCase();
		/*var cacheID = new String(this.cacheID).split("\|");
		cacheID = (this.baseSkin == this.skinName ? "" : this.skinName + "|") + (cacheID[1] || cacheID[0]);

		if(cachedExts[cacheID]){
			this.oExt.parentNode.replaceChild(cachedExts[cacheID], this.oExt);
			this.oExt = cachedExts[cacheID];
			return;
		}
		else */
			this.pHtmlNode = this.oExt.parentNode;
			var beforeNode = this.oExt.nextSibling;
			this.oExt.parentNode.removeChild(this.oExt);
			var id = this.oExt.getAttribute("id");

		//Load the new skin
		if(this.loadSkin) this.loadSkin();

		//Drawing
		this.draw();
		if(id) this.oExt.setAttribute("id", id);
		if(beforeNode) this.oExt.parentNode.insertBefore(this.oExt, beforeNode);
		if(this.aData) this.aData.oHtml = this.oExt;
		//this.__initLayout(this.jml); hopefully not necesary because everything is done by id

		// Widget specific
		if(this.__loadJML) this.__loadJML(this.jml);
		
		//Process JML Handlers
		//for(var i=this.__jmlLoaders.length-1;i>=0;i--)
		//	this.__jmlLoaders[i].call(this, this.jml);
		
		//Process databinding
		jpf.JMLParser.parseLastPass();

		//Reload data
		if(this.hasFeature(__DATABINDING__) && this.XMLRoot) 
			this.load(this.XMLRoot, this.cacheID, true);
		
		//Dispatch event
		this.dispatchEvent("onskinchange");
		
		//DragDrop
		if(this.hasFeature(__DRAGDROP__)) this.loadDragDrop();
		
		//Set Properties
		if(this.selectable) this.selectList(valueList);
		if(this.disabled) this.disable();
		if(this.focussable && this.isFocussed()) this.focus();
		
		//More properties of the dynamic kind
		for(var i=this.__supportedProperties.length-1;i>=0;--i){
			var pValue = this[this.__supportedProperties[i]];
			if(!pValue) continue;
			
			this.handlePropSet(this.__supportedProperties[i], pValue, true);
		}
		
		//Anchoring
		if(this.hasFeature(__ANCHORING__)) this.purgeAnchoring();
		
		//Layout server
		jpf.layoutServer.activateRules(this.oExt.parentNode);
		jpf.layoutServer.forceResize(this.oExt.parentNode);
	}

	/**
	 * Initializes the skin for this component when none has been set up.
	 *
	 * @param  {String}  skinName  required  Identifier for the new skin (for example: 'default:List' or 'win').
	 */
	this.loadSkin = function(skinName){
		if(!skinName && this.jml) skinName = this.jml.getAttribute("skin");
		if(skinName) skinName = skinName.toLowerCase();
		if(!this.baseSkin) this.baseSkin = (skinName ? (skinName.indexOf(":") > -1 ? skinName : skinName + ":" + this.tagName) : null) || (jpf.PresentationServer.defaultSkin || "default") + ":" + this.tagName;
		if(!this.skinName) this.skinName = this.baseSkin;

		this.skin = jpf.PresentationServer.getTemplate(this.skinName, this.jml);
		if(!this.skin){
			this.baseName = this.skinName = "default:" + this.tagName;
			this.skin = jpf.PresentationServer.getTemplate(this.skinName, this.jml);
			
			if(!this.skin) throw new Error(1077, jpf.formErrorString(1077, this, "Presentation", "Could not load skin: " + this.skinName, this.jml));
		}
		if(this.skin) jpf.PresentationServer.setSkinPaths(this.skinName, this);

		pNodes = {}; //reset the pNodes array
		var nodes = this.skin.selectNodes("Presentation/node()");
		
		for(var i=0;i<nodes.length;i++){
			if(nodes[i].nodeType != 1) continue;
			pNodes[nodes[i].tagName] = nodes[i];
		}
	}

	this.__getNewContext = function(type, jmlNode){
		pNodes[type] = this.skin.selectSingleNode("node()/" + type).cloneNode(true);
	}

	this.__hasLayoutNode = function(type){
		return pNodes[type] ? true : false;
	}

	this.__getLayoutNode = function(type, section, htmlNode){
		var node = pNodes[type];
		if(!node) return false;
		if(!section) return jpf.compat.getFirstElement(node);

		var textNode = node.selectSingleNode("@" + section);

		//if(textNode) try{(htmlNode ? jpf.XMLDatabase.selectSingleNode(textNode.nodeValue, htmlNode) : getFirstElement(node).selectSingleNode(textNode.nodeValue))}catch(e){throw new Error(0, "---- Javeline Error ----\nMessage : Could not find Presentation Skin Item (" + e.message + "): '" + section + " -> " + textNode.nodeValue + "'\n" + node.xml)}
		
		if(!textNode) return null;
		return (htmlNode ? jpf.XMLDatabase.selectSingleNode(textNode.nodeValue, htmlNode) : jpf.compat.getFirstElement(node).selectSingleNode(textNode.nodeValue));
	}

	this.__getOption = function(type, section){
		var node = pNodes[type];
		if(!section) return jpf.compat.getFirstElement(node);
		var option = node.selectSingleNode("@" + section);

		return option ? option.nodeValue : "";
	}
	
	this.__getExternal = function(tag, pNode, func, jml){
		if(!pNode) pNode = this.pHtmlNode;
		if(!tag) tag = "Main";
		if(!jml) jml = this.jml;
		
		this.__getNewContext(tag);
		var oExt = this.__getLayoutNode(tag);
		if(jml && jml.getAttributeNode("css")) oExt.setAttribute("style", jml.getAttribute("css"));
		if(jml && jml.getAttributeNode("cssclass")) this.__setStyleClass(oExt, jml.getAttribute("cssclass"));
		if(func) func.call(this, oExt);

		oExt = jpf.XMLDatabase.htmlImport(oExt, pNode);
		oExt.host = this;
		if(jml && jml.getAttribute("bgimage")) oExt.style.backgroundImage = "url(" + jpf.getAbsolutePath(this.mediaPath, jml.getAttribute("bgimage")) + ")";
		
		if(!this.baseCSSname) this.baseCSSname = oExt.className.trim().split(" ")[0];
		
		return oExt;
	}
	
	/* ***********************
				Focus
	************************/

	this.__focus = function(){
		if(!this.oExt) return;
		this.__setStyleClass(this.oExt, this.baseCSSname + "Focus");
	}

	this.__blur = function(){
		if(!this.oExt) return;
		this.__setStyleClass(this.oExt, "", [this.baseCSSname + "Focus"]);
	}

	/* ***********************
				SELECT
	************************/

	if(this.hasFeature(__MULTISELECT__)){
		this.__select = function(o){
			if(!o || !o.style) return;
			return this.__setStyleClass(o, "selected");
		}
	
		this.__deselect = function(o){
			if(!o) return;
			return this.__setStyleClass(o, "", ["selected", "indicate"]);
		}
		
		this.__indicate = function(o){
			if(!o) return;
			return this.__setStyleClass(o, "indicate");
		}
	
		this.__deindicate = function(o){
			if(!o) return;
			return this.__setStyleClass(o, "", ["indicate"]);
		}
	}
	
	/* ***********************
			  CACHING
	************************/

	this.__setEmptyMessage = function(msg){

	}

	this.__removeEmptyMessage = function(){

	}

	/* ********************************************************************
										PRIVATE METHODS
	*********************************************************************/

	this.__setStyleClass = jpf.setStyleClass;
}

/*FILEHEAD(/in/Core/Node/Rename.js)SIZE(6995)TIME(1203730484247)*/
__RENAME__ = 1<<10;


/**
 * Baseclass adding renaming features to this Component.
 *
 * @constructor
 * @baseclass
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.5
 */
jpf.Rename = function(){
	/* **********************
		INTERFACE REQUIRED
		
		[none]
	***********************/
	
	/* ********************************************************************
										PROPERTIES
	*********************************************************************/
	
	this.__regbase = this.__regbase|__RENAME__;
	this.canrename = true;
	
	/* ********************************************************************
										PUBLIC METHODS
	*********************************************************************/
	
	/**
	 * Changes the data presented as the caption of a specified {@info TraverseNodes "Traverse Node(s)"}. 
	 * If none is specified the indicated node is used.
	 *
	 * @action
	 * @param  {XMLNode}  xmlNode  required  the Traverse Node to change the caption of.
	 * @param  {String}  value   required  the value to set as the caption of the <code>xmlNode</code>.
	 */
	this.rename = function(xmlNode, value){
		if(!xmlNode) xmlNode = this.indicator || this.value;
		if(!xmlNode) return;
		
		this.executeActionByRuleSet("rename", "caption", xmlNode, value);
	}
	
	/* ********************************************************************
										PRIVATE METHODS
	*********************************************************************/
	
	/**
	 * Starts the renaming process with a delay, allowing for cancellation when necesary.
	 * Cancellation is necesary for instance, when double click was intended, or a drag&drop operation.
	 *
	 */
	this.startDelayedRename = function(e, time){
		if(e.button == 2) return;
		clearTimeout(this.renameTimer);
		this.renameTimer = setTimeout('jpf.lookup(' + this.uniqueId + ').startRename()', time || 400);
	}
	
	/**
	 * Starts the renaming process.
	 *
	 */
	var renameSubject = null;
	this.startRename = function(force){
		if(!force && (this.actionRules && !this.getNodeFromRule("rename", this.indicator||this.value, true) || this.disabled || !this.canrename)) return false;
		this.focus();

		clearTimeout(this.renameTimer);
		if(this.dispatchEvent("onrenamestart") === false) return false;

		this.renaming = true;
		renameSubject = this.indicator || this.value;
		
		var o = this.__getCaptionElement ? this.__getCaptionElement() : this.selected;
		if(!o) return;
		o.style.cursor = "text";
		
		var p = o.parentNode;
		o.parentNode.replaceChild(this.oTxt, o);
		
		this.replacedNode = o;
		var xmlNode = this.getNodeFromRule("caption", this.indicator||this.value);
		this.oTxt[jpf.hasContentEditable ? "innerHTML" : "value"] = (xmlNode.nodeType == 2 ? unescape(decodeURI(xmlNode.nodeValue)) : jpf.XMLDatabase.getNodeValue(xmlNode)) || "";//o.innerHTML;
		this.oTxt.unselectable = "Off";
		this.oTxt.host = this;

		//this.oTxt.focus();
		this.oTxt.select();
	}
	
	/**
	 * Cancel the renaming process without changing data.
	 *
	 */
	this.cancelRename = function(no_event){
		clearTimeout(this.renameTimer);
		if(!this.renaming) return;
		
		this.renaming = false;
		var o = this.oTxt;
		if(o.parentNode) o.parentNode.replaceChild(this.replacedNode, o);
		this.replacedNode.style.cursor = "default";
		
		if(!no_event) this.dispatchEvent("oncancelrename");
		
		return true;
	}
	
	/**
	 * Stop renaming process and change the data according to the set value.
	 *
	 */
	this.stopRename = function(){
		//this.selected.innerHTML = this.oTxt.innerHTML;
		this.rename(renameSubject, this.oTxt[jpf.hasContentEditable ? "innerHTML" : "value"].replace(/<.*?nobr>/gi, ""));
		
		return false;
	}
	
	/* ********************************************************************
										HOOKS
	*********************************************************************/
	
	if(this.__deselect) this.__rdeselect = this.__deselect;
	if(this.__blur) this.__rdblur = this.__blur;
	if(this.__select) this.__rselect = this.__select;
		
	
	this.__select = function(o){
		if(this.renaming){
			this.cancelRename(true);
			this.stopRename();
		}
		
		return this.__rselect ? this.__rselect(o) : o;
	}
	
	this.__deselect = function(o){
		if(this.renaming){
			//Check if this is the same is the node to be renamed...
			//if(this.selected.parentNode.nodeType == 11) node = this.selected;
			
			this.cancelRename(true);
			this.stopRename();
			if(this.ctrlSelect) return false;
		}
		
		return this.__rdeselect ? this.__rdeselect(o) : o;
	}
	
	this.__blur = function(){
		if(this.renaming){
			this.cancelRename(true);
			this.stopRename();
		}
		
		if(this.__rdblur) this.__rdblur();
	}
	
	if(this.keyHandler) this.__keyHandler = this.keyHandler;
	
	/**
	 * @private
	 */
	this.keyHandler = function(key, ctrlKey, shiftKey, altKey){
		if(this.renaming){
			if(key == 27 || key == 13){
				this.cancelRename(key == 13);
				if(key == 13) this.stopRename();
			}
			
			return;
		}

		//F2
		if(key == 113){
			this.startRename();
			return false;
		}
		else if(this.__keyHandler) //Normal KeyHandler
			return this.__keyHandler(key, ctrlKey, shiftKey, altKey);
	}
	
	/* ********************************************************************
									EDIT FIELD
	*********************************************************************/
	if(!(this.oTxt = this.pHtmlDoc.getElementsByTagName("txt_rename")[0])){
		if(jpf.hasContentEditable){
			this.oTxt = document.createElement("DIV");
			this.oTxt.contentEditable = true;
			if(jpf.isIE6) this.oTxt.style.width = "1px";
			//this.oTxt.canHaveHTML = false;
		}
		else{
			this.oTxt = document.createElement("INPUT");
			this.oTxt.setAttribute("id", "txt_rename");
			//this.oTxt.style.width = "100%";
			this.oTxt.autocomplete = false;
	
		}
		this.oTxt.id = "txt_rename";
		this.oTxt.style.whiteSpace = "nowrap";
		this.oTxt.onselectstart = function(e){(e || event).cancelBubble = true};
		//this.oTxt.host = this;
		
		this.oTxt.onmouseover = this.oTxt.onmouseout = this.oTxt.oncontextmenu = 
		this.oTxt.onmousedown = function(e){(e || event).cancelBubble = true}
		
		this.oTxt.select = function(){
			if(!jpf.hasMsRangeObject) return this.focus();
			
			var r = document.selection.createRange();
			//r.moveEnd("character", this.oExt.innerText.length);
			try{r.moveToElementText(this);}catch(e){} //BUG!!!!
			r.select();
		}
		
		this.oTxt.onblur = function(){
			if(jpf.isGecko) return; //bug in firefox calling onblur too much
			this.host.cancelRename(true);
			this.host.stopRename();
		}
		
		this.__addJmlDestroyer(function(){
			this.oTxt.host = null;
			this.oTxt.onmouseover = null;
			this.oTxt.onmousedown = null;
			this.oTxt.select = null;
		});
	}

	/**
	 * @attribute  {Boolean}  rename  true  When set to true the use can rename items in this component.
	 */
	this.__addJmlLoader(function(x){
		this.canrename = x.getAttribute("canrename") != "false";
	});
}

/*FILEHEAD(/in/Core/Node/Transaction.js)SIZE(9338)TIME(1203730484247)*/
__TRANSACTION__ = 1<<3;


/**
 * Baseclass adding Transaction features to this Component.
 * Transactions are needed when a set of databound components change
 * data and these changes need to be approved or cancelled afterwards.
 * A good example is a property window with an OK and Cancel button. The
 * change should only be applied when OK is pressed. Because the components
 * bound to the data, will change the data immediately, Transaction 
 * forks the data before any change is made using the {@link #startTransaction} method. 
 * When OK is pressed, {@link #commit} should be called to merge back 
 * the forked data. When Cancel is pressed {@link #rollback} should be called; 
 * data is not merged, and the situation remains unchanged. 
 * <p>
 * This class takes care of proper ActionTracker handling and can call
 * stacked RPC calls when merging the data. Use the features from this
 * class to implement locking mechanism for your collaborative applications.
 *
 * @constructor
 * @baseclass
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.8.9
 */
jpf.Transaction = function(){
	/* ********************************************************************
										PROPERTIES
	*********************************************************************/
	
	this.__regbase = this.__regbase|__TRANSACTION__;
	var jmlNode = this;
	var addParent, transactionNode, mode, originalNode;
	
	/* ********************************************************************
										ACTIONS
	*********************************************************************/
	
	/**
	 * Adds or Updates data loaded in this component based on a previously
	 * forked copy of template data.
	 *
	 * @action
	 * @todo  check what's up with actiontracker usage... 
	 * @bug  when a commit is cancelled using the onbeforecommit event, the state of the component becomes undefined
	 */
	this.commit = function(){
		if(!this.inTransaction) return;
		
		//This should be move to after action has been executed
		this.__ActionTracker.purge();
		this.inTransaction = false;
		
		if(mode == "add"){
			//Use ActionTracker :: this.xmlData.selectSingleNode("DataBinding/@select") ? o.XMLRoot : o.value
			this.executeAction("appendChildNode", [addParent, transactionNode], "add", transactionNode);//o.value || 
		}
		else{
			//Reverse
			if(this.hasFeature(__MULTISELECT__))
				XMLDatabase.replaceChild(transactionNode, originalNode);
		
			//Use ActionTracker
			//getTraverseParent(o.value) || o.XMLRoot
			var at = this.__ActionTracker; this.__ActionTracker = self[this.jml.getAttribute("actiontracker")];//this.dataParent.parent.getActionTracker();
			this.executeAction("replaceNode", [originalNode, transactionNode], "update", transactionNode);
			this.__ActionTracker = at;
	
			if(!this.hasFeature(__MULTISELECT__)) //isn't this implicit?
				this.load(transactionNode);
		}
	}
	
	/**
	 * Rolls back the started transaction for changing the data of this component.
	 *
	 * @action
	 * @bug When there is no rollback action is defined. A Transaction can never be rolled back. This is incorrect behaviour
	 */
	this.rollback = function(){
		if(!this.inTransaction) return;
		
		return this.executeAction(function(){
			if(this.__ActionTracker){
				if(this.rpcMode == "realtime")
					this.__ActionTracker.undo(-1);
				this.__ActionTracker.reset();
			}
			//this.XMLDatabase.reset();
	
			//Cleanup
			if(this.hasFeature(__MULTISELECT__)){
				if(mode == "add") XMLDatabase.removeNode(transactionNode);
				else XMLDatabase.replaceChild(transactionNode, originalNode);
			}
			else{
				if(!this.XMLRoot.parentNode) this.load(originalNode);
			}
			
			this.inTransaction = false;
		}, null, "rollback", originalNode);
	}

	/**
	 * Starts a transaction for this component. This forks the currently 
	 * bound data and allows for changes to be made which can later be
	 * disgarded or committed.
	 *
	 * @action
	 */
	this.startTransaction = function(transMode){
		if(this.inTransaction) throw new Error(0, jpf.formErrorString(0, this, "Starting Transaction", "Cannot start a transaction without committing or rolling back previously started transaction.", this.oldRoot));
			
		this.inTransaction = true;
		mode = transMode || "update";
		transactionNode = null; addParent = null;
		
		if(mode != "add" && this.hasFeature(__MULTISELECT__) && !this.value) return;
		
		function startTransaction(){
			if(mode == "add"){
				if(!transactionNode) throw new Error(0, jpf.formErrorString(0, this, "Starting transaction", "Could not get a new node to add"));
				
				if(this.hasFeature(__MULTISELECT__)){
					if(!addParent){
						if(this.isTreeArch) addParent = this.value || this.XMLRoot;
						else addParent = this.XMLRoot;
					}
					
					//Add node without going through actiontracker
					jpf.XMLDatabase.appendChildNode(addParent, transactionNode);
					this.select(transactionNode); //select node to notify all other elements to bind to it
				}
				else{
					if(!addParent){
						if(this.dataParent){
							var p = this.dataParent.parent;
							if(p.isTreeArch) addParent = p.value || p.XMLRoot;
							else addParent = p.XMLRoot;
						}
						else addParent = this.XMLRoot.parentNode;
					}
					
					this.load(transactionNode);
				}
			}
			else{
				originalNode = this.hasFeature(__MULTISELECT__) ? this.value : this.XMLRoot;
				transactionNode = originalNode.cloneNode(true);//XMLDatabase.clearConnections(this.XMLRoot.cloneNode(true));
				//xmlNode.removeAttribute(XMLDatabase.xmlIdTag);
				
				//rename listening attributes
				
				if(this.hasFeature(__MULTISELECT__)){
					//Replace node without going through actiontracker
					XMLDatabase.replaceNode(originalNode, transactionNode);
					this.select(transactionNode);
				}
				else{
					this.load(transactionNode);
				}
			}
		}
		
		if(mode == "add"){
			var node = this.actionRules["add"];
			if(!node || !node[0]) throw new Error(0, jpf.formErrorString(0, this, "Add Action", "Could not find Add Node"));
			
			var callback = function(addXmlNode, state, extra){
				if(state != __HTTP_SUCCESS__){
					if(state == __HTTP_TIMEOUT__ && extra.retries < jpf.maxHttpRetries) return extra.tpModule.retry(extra.id);
					else{
						var commError = new Error(0, jpf.formErrorString(0, jmlNode, "Retrieving add node", "Could not add data for control " + jmlNode.name + "[" + jmlNode.tagName + "] \nUrl: " + extra.url + "\nInfo: " + extra.message + "\n\n" + xmlNode));
						if(jmlNode.dispatchEvent("onerror", jpf.extend({error : commError, state : status}, extra)) !== false)
							throw commError;
						return;
					}
				}
				
				if(typeof addXmlNode != "object") addXmlNode = jpf.getObject("XMLDOM", addXmlNode).documentElement;
				if(addXmlNode.getAttribute(jpf.XMLDatabase.xmlIdTag)) addXmlNode.setAttribute(jpf.XMLDatabase.xmlIdTag, "");
				
				var actionNode = jmlNode.getNodeFromRule("add", jmlNode.isTreeArch ? jmlNode.value : jmlNode.XMLRoot, true, true);
				if(actionNode && actionNode.getAttribute("parent")) addParent = jmlNode.XMLRoot.selectSingleNode(actionNode.getAttribute("parent"));
				
				transactionNode = addXmlNode;
				
				jmlNode.executeAction(startTransaction, null, "starttransaction", jmlNode.XMLRoot);
			}
			
			if(node.getAttribute("get")) return jpf.getData(node.getAttribute("get"), node, callback)
			else if(node.firstChild) return callback(jpf.compat.getNode(node, [0]).cloneNode(true), __HTTP_SUCCESS__);
		}
		else{
			this.executeAction(startTransaction, null, "starttransaction", this.XMLRoot);
		}
	}
	
	/**
	 * @alias
	 */
	this.add = function(){
		this.startTransaction("add");
	}

	if(this.hasFeature(__MULTISELECT__)){
		this.addEventListener("onbeforeselect", function(){
			if(this.inTransaction){
				return this.rollback();
			}
		});
		
		this.addEventListener("onafterselect", function(){
			this.startTransaction();
		});
	}
}

/**
 * @constructor
 * @baseclass
 */
jpf.EditTransaction = function(){
	this.ok = function(){
		if(this.apply()) 
			this.close();
	}
	
	this.apply = function(){
		if(this.validgroup && this.validgroupd.isValid()){
			this.commit();
			return true;
		}
		return false;
	}
	
	this.cancel = function(){
		this.rollback();
		this.close();
	}
	
	this.__load = function(XMLRoot){
		if(this.inTransaction) this.rollback();
		jpf.XMLDatabase.addNodeListener(XMLRoot, this);
	}
	
	this.__xmlUpdate = function(action, xmlNode, listenNode, UndoObj){
		if(this.inTransaction){
			this.dispatchEvent("ontransactionconflict", {action:action, xmlNode:xmlNode, UndoObj:UndoObj});
		}
	}
	
	this.addEventListener("ondisplay", function(){
		if(!this.validgroup && this.jml && this.jml.getAttribute("validgroup")) 
			this.validgroup = self[this.jml.getAttribute("validgroup")];
			
		if(!this.mode && this.jml) 
			this.mode = this.jml.getAttribute("mode") || "add";
		
		this.startTransaction(this.mode);
	});
	
	this.addEventListener("onclose", function(){
		if(this.inTransaction) this.rollback();
	});
}

/*FILEHEAD(/in/Core/Node/Validation.js)SIZE(13715)TIME(1203730484247)*/
__VALIDATION__ = 1<<6;


/**
 * Baseclass adding Validation features to this Component.
 *
 * @constructor
 * @baseclass
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.5
 */
jpf.Validation = function(){
	this.isActive = true;
	this.__regbase = this.__regbase|__VALIDATION__;
	
	/**
	 * Checks if this component's value is valid.
	 *
	 * @param  {Boolean}  checkRequired  optional  true  also include required check.
	 *                                           false  default  do not include required check.
	 * @return  {Boolean}  specifying wether the value is valid
	 * @see  ValidationGroup
	 * @see  Submitform
	 */
	this.isValid = function(checkRequired){
		if(checkRequired && this.required){
			var value = this.getValue();
			if(!value || value.toString().length == 0) return false;
		}
		
		//for(var i=0;i<vRules.length;i++) if(!eval(vRules[i])) return false;
		var isValid = (this.vRules.length ? eval("(" + this.vRules.join(") && (") + ")") : true);
		
		this.dispatchEvent("xforms-" + (isValid ? "valid" : "invalid"));
		
		return isValid;
	}
	
	/**
	 * @private
	 * @todo This method should also scroll the element into view
	 */
	this.showMe = function(){
		var p = this.parentNode;
		while(p){
			if(p.show) p.show();
			p = p.parentNode;
		}
	}
	
	/**
	 * Puts this component in the error state, optionally showing the 
	 * error box if this component's is invalid.
	 *
	 * @param  {Boolean}  force  optional  true  set this component in the error state and don't check if the component's value is invalid.
	 *                                   false  default  only do this when the component's value is invalid.
	 * @return  {Boolean}  boolean specifying wether the value is valid
	 * @see  ValidationGroup
	 * @see  Submitform
	 */
	this.validate = function(force){
		if(!this.validgroup) return;

		var hasError = false;
		if(force || !this.isValid()){
			this.setError();
			return true;
		}
		else{
			this.clearError();
			return false;
		}
		
		return !hasError;
	}
	
	/**
	 *	@private
	 */
	this.setError = function(value){
		if(this.__setStyleClass)
			this.__setStyleClass(this.oExt, this.baseCSSname + "Error");
		
		if(this.errBox){
			if(!this.validgroup.allowMultipleErrors)
				this.validgroup.hideAllErrors();
			
			this.errBox.setMessage(this.invalidmsg);
			this.showMe();
			
			if(this.validgroup){
				this.oExt.parentNode.insertBefore(this.errBox.oExt, this.oExt.nextSibling);
				
				if(jpf.getStyle(this.errBox.oExt, "position") == "absolute"){
					var pos = jpf.compat.getAbsolutePosition(this.oExt, jpf.compat.getPositionedParent(this.oExt));
					this.errBox.oExt.style.left = pos[0] + "px"; //this.oExt.offsetLeft + "px";
					this.errBox.oExt.style.top = pos[1] + "px"; //this.oExt.offsetTop + "px";
				}
				this.errBox.host = this;
			}
			this.errBox.show();
			this.focus(); //discutabel
			
			//Drawing Bug fix (ughhh) hack!
			/*if(jpf.isGecko){
				if(this.errBox.pHtmlNode.style.height == "100%")
					this.errBox.pHtmlNode.style.height = "";
				else
					this.errBox.pHtmlNode.style.height = "100%";
			}*/
		}
	}
	
	/**
	 *	@private
	 */
	this.clearError = function(value){
		if(this.__setStyleClass)
			this.__setStyleClass(this.oExt, "", [this.baseCSSname + "Error"]);
		
		if(this.errBox && this.errBox.host == this){
			this.errBox.hide();
			
			//Drawing Bug fix (ughhh) hack!
			/*if(jpf.isGecko){
				if(this.errBox.pHtmlNode.style.height == "100%")
					this.errBox.pHtmlNode.style.height = "";
				else
					this.errBox.pHtmlNode.style.height = "100%";
			}*/
		}
	}
	
	this.__addJmlDestroyer(function(){
		if(this.validgroup) this.validgroup.remove(this);
	});
	
	this.vRules = [];
	this.addValidationRule = function(rule){
		this.vRules.push(rule);
	}
	
	/**
	 *
	 * @attribute  {Boolean}  required  true  a valid value for this component is required.
	 *                                   false  default  a valid value or an empty value is accepted.
	 * @attribute  {RegExp}  validation   Regular expression which is tested against the value of this component to determine the validity of it.
	 *                          string   String containing one of the predefined validation methods (for example; DATE, EMAIL, CREDITCARD, URL).
	 *                          string   String containing javascript code which validates to true or false when executed.
	 * @attribute  {Integer}  min-value  the minimal value for which the value of this component is valid.
	 * @attribute  {Integer}  max-value  the maximum value for which the value of this component is valid.
	 * @attribute  {Integer}  min-length  the minimal length allowed for the value of this component.
	 * @attribute  {Integer}  max-length  the maximum length allowed for the value of this component.
	 * @attribute  {Boolean}  notnull  same as {@link #required} but this rule is checked realtime when the component looses the focus, instead of at specific request (for instance when leaving a form page).
	 * @attribute  {String}  check-equal   String specifying the id of the component to check if it has the same value as this component. 
	 * @attribute  {String}  invalidmsg   String specifying the message displayed when this component has an invalid value. Use a ; character to seperate the title from the message.
	 * @attribute  {String}  validgroup   String specifying the identifier for a group of items to be validated at the same time. This identifier can be new. It is inherited from a JML node upwards.
	 */
	this.__addJmlLoader(function(x){
		//this.addEventListener(this.hasFeature(__MULTISELECT__) ? "onafterselect" : "onafterchange", onafterchange);
		this.addEventListener("onbeforechange", function(){
			if(jpf.XMLDatabase.getBoundValue(this) === this.getValue()) return false;
		});

		// Submitform
		if(!this.form){
			//Set Form
			var y = this.jml;
			do{
				y = y.parentNode;
			}while(y && y.tagName && !y.tagName.match(/submitform|xforms$/) && y.parentNode && y.parentNode.nodeType != 9);
			
			if(y && y.tagName && y.tagName.match(/submitform|xforms$/)){
				if(!y.tagName.match(/submitform|xforms$/)) throw new Error(1070, jpf.formErrorString(1070, this, this.tagName, "Could not find Form element whilst trying to bind to it's Data."));
				if(!y.getAttribute("id")) throw new Error(1071, jpf.formErrorString(1071, this, this.tagName, "Found Form element but the id attribute is empty or missing."));
				
				this.form = eval(y.getAttribute("id"));
				this.form.addInput(this);
			}
		}
		
		// validgroup
		if(!this.form){
			var vgroup = x.getAttribute("validgroup") || jpf.XMLDatabase.getInheritedAttribute(x, "validgroup");
			if(vgroup){
				this.validgroup = self[vgroup] || jpf.setReference(vgroup, new jpf.ValidationGroup());
				this.validgroup.add(this);
			}
		}

		if(this.validgroup){
			this.addEventListener("onblur", function(){this.validate();})
			
			if(x.getAttribute("required") == "true"){
				//if(this.form) this.form.addRequired(this);
				this.required = true;
			}
			
			if(x.getAttribute("datatype")){
				if(this.multiselect)
					this.addValidationRule("!this.getValue() || this.XMLRoot && jpf.XSDParser.checkType('" + x.getAttribute("datatype") + "', this.getTraverseNodes())");
				else
					this.addValidationRule("!this.getValue() || this.XMLRoot && jpf.XSDParser.checkType('" + x.getAttribute("datatype") + "', this.XMLRoot) || !this.XMLRoot && jpf.XSDParser.matchType('" + x.getAttribute("datatype") + "', this.getValue())");
			}

			if(x.getAttribute("validation")){
				var validation = x.getAttribute("validation");
				if(validation.match(/^\/.*\/(?:[gim]+)?$/)) this.reValidation = eval(validation);
				
				var vRule = this.reValidation ? 
					"this.getValue().match(this.reValidation)" : //RegExp
					"(" + validation + ")"; //JavaScript
					
				this.addValidationRule("!this.getValue() || " + vRule);
			}

			if(x.getAttribute("min-value"))
				this.addValidationRule("!this.getValue() || parseInt(this.getValue()) >= " + x.getAttribute("min-value"));
			if(x.getAttribute("max-value"))
				this.addValidationRule("!this.getValue() || parseInt(this.getValue()) <= " + x.getAttribute("max-value"));
			if(x.getAttribute("max-length"))
				this.addValidationRule("!this.getValue() || this.getValue().toString().length <= " + x.getAttribute("max-length"));
			if(x.getAttribute("min-length"))
				this.addValidationRule("!this.getValue() || this.getValue().toString().length >= " + x.getAttribute("min-length"));
			if(x.getAttribute("notnull") == "true")
				this.addValidationRule("this.getValue() && this.getValue().toString().length > 0");
			//if(x.getAttribute("required") == "true")
				//this.addValidationRule("new String(this.getValue()).length != 0");
			if(x.getAttribute("check-equal"))
				this.addValidationRule("!" + x.getAttribute("check-equal") + ".isValid() || " + x.getAttribute("check-equal") + ".getValue() == this.getValue()");
				
			this.invalidmsg = x.getAttribute("invalidmsg");
			if(this.invalidmsg){
				if(this.validgroup) this.errBox = this.validgroup.getErrorBox(this);
				else{
					var o = new jpf.errorbox();
					o.pHtmlNode = this.oExt.parentNode;
					o.loadJML(x);
					this.errBox = o;
				}
				//if(this.form) this.form.registerErrorBox(this.name, o); //stupid name requirement
			}
		}
	});	
}

/**
 * Object allowing for a set of JML components to be validated.
 *
 * @classDescription		This class creates a new validation group
 * @return {ValidationGroup} Returns a new validation group
 * @type {ValidationGroup}
 * @constructor
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.9
 */
jpf.ValidationGroup = function(){
	jpf.makeClass(this);
	
	this.validateVisibleOnly = false;
	this.allowMultipleErrors = false;
	
	this.childNodes = [];
	this.add = function(o){this.childNodes.push(o);}
	this.remove = function(o){this.childNodes.remove(o);}
	
	/**
	 * @copy   JmlNode#toString
	 */
	this.toString = function(){
		return "[Javeline Validation Group]";
	}
	
	var errbox;
	/**
	 * Gets the {@link Errorbox} component used for a specified component.
	 *
	 * @param  {JmlNode}  oComponent  required  JmlNode specifying the component for which the Errorbox should be found. If none is found, an Errobox is created. Use the {@link #allowMultipleErrors} property to influence when Errorboxes are created.
	 * @return  {Errorbox}  the found or created Errorbox;
	 */
	this.getErrorBox = function(o){
		if(this.allowMultipleErrors || !errbox){
			errbox = new jpf.errorbox();
			errbox.pHtmlNode = o.oExt.parentNode;
			var cNode = o.jml.ownerDocument.createElement("Errorbox");
			errbox.loadJML(cNode);
		}
		return errbox;
	}
	
	/**
	 * Hide all Errorboxes for the components using this component as it's validation group.
	 *
	 */
	this.hideAllErrors = function(){
		for(var i=0;i<this.childNodes.length;i++){
			if(this.childNodes[i].errBox)
				this.childNodes[i].errBox.hide();
		}
	}
	
	function checkValidChildren(oParent, ignoreReq, nosetError){
		var found;
		
		//Per Element
		for(var i=0;i<oParent.childNodes.length;i++){
			var oEl = oParent.childNodes[i];

			if(!oEl) continue;
			if(
				!oEl.disabled && 
				(!this.validateVisibleOnly && oEl.visible || !oEl.oExt || oEl.oExt.offsetHeight) && 
				(
					oEl.hasFeature(__VALIDATION__) && oEl.isValid && !oEl.isValid() ||
					!ignoreReq && oEl.required && new String(oEl.getValue()).length == 0
				)
			){
				if(!nosetError){
					if(!found){
						oEl.validate(true);
						found = true;
						if(!this.allowMultipleErrors) return true; //Added (again)
					}
					else if(oEl.errBox && oEl.errBox.host == oEl) oEl.errBox.hide();
				}
				else if(!this.allowMultipleErrors) return true;
			}
			if(oEl.childNodes.length){
				found = checkValidChildren.call(this, oEl, ignoreReq, nosetError) || found;
				if(found && !this.allowMultipleErrors) return true; //Added (again)
			}
		}
		
		return found;
	}
	
	/**
	 * Checks if (part of) the set of component's registered to this component are
	 * valid. When a component is found with an invalid value the error state can
	 * be set for that component. 
	 *
	 * @param  {Boolean}  ignoreReq  optional  true  do not include required check.
	 *                                        false  default  include required check.
	 * @param  {Boolean}  nosetError  optional  true  do not set the error state of the component with an invalid value
	 *                                        false  default  set the error state of the component with an invalid value
	 * @param  {TabPage}  page  optional  the page of which the component's will be checked instead of checking them all.
	 * @return  {Boolean}  specifying wether all components have valid values
	 */
	this.isValid = function(ignoreReq, nosetError, page){
		var found = checkValidChildren.call(this, page || this, ignoreReq, nosetError);
		
		if(page){
			try{
			
			if(!eval(page.validation)){
				alert(page.invalidmsg);
				found = true;
			}
			
			}catch(e){
				throw new Error(0, jpf.formErrorString(0, this, "Validating Page", "Error in javascript validation string of page: '" + page.validation + "'", page.jml));
			}
		}
		
		//Global Rules
		//
		if(!found) found = this.dispatchEvent("onvalidation");
		
		return !found;
	}
}


/*FILEHEAD(/in/Core/Node/XForms.js)SIZE(6202)TIME(1202849967875)*/
__XFORMS__ = 1<<17;


/* Xpath extension:
	Firefox: http://mcc.id.au/xpathjs/
	IE:
	
	XSLT extension
	IE: http://msdn.microsoft.com/msdnmag/issues/02/03/xml/
*/

/**
 * Object returning an XForms Parser
 *
 * @classDescription		This class creates a new XForms parser
 * @return {XForms} Returns a new XForms parser
 * @type {XForms}
 * @constructor
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.9.8
 */
jpf.XForms = function(){
	this.__regbase = this.__regbase|__XFORMS__;
	
	function getModel(name){
		if(name){
			var model = jpf.NameServer.get("model", name);
			
			if(!model) throw new Error(0, jpf.formErrorString(0, this, "Resetting form", "Could not find model '" + name + "'"));
			
			return model;
		}
		else return this.getModel();
	}
	
	var XEvents = {
		"xforms-submit" : function(model){
			getModel.call(this, name).submit(this.tagName == "submission" ? this.name : null);
			return false;
		},
		"xforms-reset" : function(model){
			getModel.call(this, model).reset();
			return false;
		},
		"xforms-revalidate" : function(model){
			getModel.call(this, model).isValid(); 
		},
		"xforms-next" : function(){
			jpf.window.moveNext(null, this);
			return false;
		},
		"xforms-previous" : function(){
			jpf.window.moveNext(true, this);
			return false;
		},
		"xforms-focus" : function(){
			this.focus();
			return false;
		}
	}
	
	/*Notification only events
	XEvents["DOMActivate"] = 
	XEvents["xforms-value-changed"] = 
	XEvents["xforms-select"] = 
	XEvents["xforms-deselect"] = 
	XEvents["xforms-scroll-first"] = 
	XEvents["xforms-scroll-last"] = 
	XEvents["xforms-insert"] = 
	XEvents["xforms-delete"] = 
	XEvents["xforms-valid"] = 
	XEvents["xforms-invalid"] = 
	XEvents["DOMFocusIn"] = 
	XEvents["DOMFocusOut"] = 
	XEvents["xforms-readonly"] = 
	XEvents["xforms-readwrite"] = 
	XEvents["xforms-required"] = 
	XEvents["xforms-optional"] = 
	XEvents["xforms-enabled"] = 
	XEvents["xforms-disabled"] = 
	XEvents["xforms-in-range"] = XEvents["xforms-readonly"] = 
	XEvents["xforms-out-of-range"] = 
	XEvents["xforms-submit-done"] = 
	XEvents["xforms-submit-error"] = function(){}
	*/
	
	this.dispatchXFormsEvent = function(name, model, noEvent){
		if(XEvents[name] && XEvents[name].call(this, model) !== false && !noEvent) 
			this.dispatchEvent.apply(this, name);
	}
	
	function findXFormsData(xmlNode){
		if(xmlNode.getAttribute("bind")){
			return this.getModel().getBindNode(xmlNode.getAttribute("bind")).selectNodes();
		}
		else if(xmlNode.getAttribute("ref")){
			return this.getModel().data.selectSingleNode(xmlNode.getAttribute("ref"));
		}
	}
	
	this.executeXFormStack = function(actionNode){
		switch(actionNode[TAGNAME]){
			case "action":
				var nodes = actionNode.childNodes;
				for(var i=0;i<nodes.length;i++){
					this.executeXFormStack(nodes[i]);
				}
			break;
			case "dispatch":
				var el = self[actionNode.getAttribute("target")];
				el.dispatchXFormsEvent(actionNode.getAttribute("name")); //some element
			break;
			case "reset":
				this.dispatchXFormsEvent("xforms-reset", actionNode.getAttribute("model"));
			break;
			case "rebuild":
			case "recalculate":
			case "revalidate":
			case "refresh":
			case "reset":
				this.dispatchXFormsEvent("xforms-" + actionNode[TAGNAME], actionNode.getAttribute("model"), true);
			break;
			case "setfocus":
				var el = self[actionNode.getAttribute("control")];
				el.dispatchXFormsEvent("xforms-focus");
			break;
			case "load": //Is this like a link in HTML, or am I mistaking?
				var link = actionNode.getAttribute("resource"); //url assumed for now
				if(actionNode.getAttribute("show") == "new") window.open(link);
				else location.href = link;
			break;
			case "setvalue":
				var value = actionNode.getAttribute("value") ? 
					this.getModel().data.selectSingleNode(actionNode.getAttribute("value")) :
					getXmlValue(actionNode, "text()");
			
				var dataNode = findXFormsData.call(this, actionNode);
				XMLDatabase.setNodeValue(dataNode, value, true);
			break;
			case "setindex":
			
			break;
			case "send":
				var el = self[actionNode.getAttribute("submission")];
				el.dispatchXFormsEvent("xforms-submit");
			break;
			case "message":
				var message = getXmlValue(actionNode, "text()");
			
				switch(actionNode.getAttribute("level")){
					case "ephemeral":
						status = message;
					break;
					case "modeless":
						document.title = message;
					break;
					case "modal":
						alert(message);
					break;
				}
			break;
			case "insert":
				//actionNode.getAttribute("at");
				//actionNode.getAttribute("position") == "before" ? ;
				this.dispatchXFormsEvent("xforms-insert");
			break;
			case "delete":
				this.dispatchXFormsEvent("xforms-delete");
			break;
		}
	}
	
	this.parseXFormTag = function(xmlNode){
		switch(xmlNode[jpf.TAGNAME]){
			case "filename":
			
			break;
			case "mediatype":
			
			break;
			case "itemset":
			
			break;
			case "item":
				//ignore
			break;
			case "choices":
				//ignore
			break;
			case "copy":
			
			break;
			case "help":
			
			break;
			case "hint":
			
			break;
			/*	<upload ref="mail/attachment" mediatype="image/*">
				  <label>Select image:</label>
				  <filename ref="@filename" />
				  <mediatype ref="@mediatype" />
				</upload>
			*/
		}
	}
	
	this.__addJmlLoader(function(x){
		this.addEventListener(this.hasFeature(__MULTISELECT__) ? "onclick" : "onchoose", function(){
			var model = this.getModel(); 
			if(model) model.dispatchEvent("DOMActivate");
		});
		this.addEventListener(this.hasFeature(__MULTISELECT__) ? "onafterchange" : "onafterselect", function(){
			var model = this.getModel(); 
			if(model) model.dispatchEvent("xforms-value-changed")
		});
		
		if(this.hasFeature(__MULTISELECT__)){
			this.addEventListener("onafterselect", function(e){
				this.dispatchEvent(e.list.contains(e.xmlNode) ? "xforms-select" : "xforms-deselect");
			});
		}
	});
}
/*FILEHEAD(/in/Core/Application/ActionTracker.js)SIZE(15505)TIME(1203730484247)*/

/**
 * Component keeping track of all user actions that
 * are triggered in components that are registered
 * to this component. This component allows for undo &
 * redo of the specified actions, whilst being aware
 * of the datasynchronization with a backend data store.
 *
 * @classDescription		This class creates a new actiontracker
 * @return {ActionTracker} Returns a new actiontracker
 * @type {ActionTracker}
 * @constructor
 * @addnode smartbinding:actiontracker, global:actiontracker
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.8
 */
jpf.ActionTracker = function(context){
	jpf.makeClass(this);
	
	this.realtime = true;
	this.hasChanged = false;
	//this.root = (me == self.main);
	//if(!this.root) 
	
	this.getParentAT = function(){
		if(context) return context.getActionTracker(true);
		else return self.ActionTracker && self.ActionTracker != this ? self.ActionTracker : null;//me.parentWindow ? jpf.window.parentWindow.ActionTracker : 
	}
	
	this.actions = {};
	this.stackDone = new Array();
	this.stackUndone = new Array();
	this.stackRPC = new Array();
	
	/* ********************************************************************
										API
	*********************************************************************/
	
	this.define = function(action, func){
		this.actions[action] = func;
	}
	
	this.execute = function(action, args, xmlActionNode, jmlNode, selNode){
		this.hasChanged = true;
		if(this.onchange && this.onchange() === false) return;
		
		//Execute action
		var UndoObj = new jpf.UndoData(action, xmlActionNode, args, jmlNode, selNode);
		if(action)
			(typeof action == "function" ? action : this.actions[action])(UndoObj, false, this);
		
		//Add action to stack
		var id = UndoObj.id = this.stackDone.push(UndoObj)-1;
		this.lastId = id;

		//Respond
		UndoObj.saveChange(null, this);
		
		//Reset Redo Stack
		this.stackUndone.length = 0;

		//return stack id of action
		return id;
	}
	
	this.addActionGroup = function(done, rpc){
		var UndoObj = new jpf.UndoData("group", null, [jpf.copyArray(done, UndoData), jpf.copyArray(rpc, UndoData)]);
		this.stackDone.push(UndoObj);
		
		this.hasChanged = true;
		if(this.onchange) this.onchange();
	}
	
	this.purge = function(nogrouping, forcegrouping){
		var prnt = this.getParentAT();
		
		if(nogrouping && prnt){
		//if(!forcegrouping && this.parent){
			var hash = {}, ids = [];
			
			//Execute RPC calls through multicall or queued calling
			for(var i=0;i<this.stackRPC.length;i++){
				var o = this.stackRPC[i].saveChange(null, this, true);
				hash[o.uniqueId] = o;
				ids.push(this.stackRPC[i].id);
			}
			
			//Purge & Remove Multicall Force
			for(prop in hash){
				if(typeof prop == "number"){
					hash[prop].purge(receive, ids);
					hash[prop].force_multicall = false;
				}
			}
			
			//Also Execute the Socket Calls Connected to the Actions if any
			if(jpf.XMLDatabase.socket) jpf.XMLDatabase.socket.purge();
		}
		else if(prnt){
		//else if(!nogrouping){
			//Copy Stacked Actions as a single grouped action to parent ActionTracker
			prnt.addActionGroup(this.stackDone, this.stackRPC);
		}
		
		//Reset Stacks
		this.reset();
	}
	
	this.reset = function(){
		//Reset Stacks
		this.stackDone.length = 0;
		this.stackUndone.length = 0;
		this.stackRPC.length = 0;
		
		this.hasChanged = false;
		if(this.onchange) this.onchange(true);
		/* could set start of changed to x and check if different above */
	}
	
	//TODO: merge undo and redo
	this.undo = function(id, single, stackDone, stackUndone, rollBack){
		if(!stackDone) stackDone = this.stackDone;
		if(!stackUndone) stackUndone = this.stackUndone;
		
		if(!stackDone.length) return;
		
		if(single){
			var UndoObj = stackDone[id];
			if(!UndoObj) return;
			
			//Workaround for calls coming in late...
			if(id == stackDone.length-1) stackDone.length--;
			else stackDone[id] = null;
			
			//Undo Client Side Action
			if(UndoObj.action)
				(typeof UndoObj.action == "function" ? UndoObj.action : this.actions[UndoObj.action])(UndoObj, true, this);
			
			//Respond - REMOVED.. shouldn't be called during undo
			if(!rollBack) UndoObj.saveChange(true, this); // WHY NOT??? seems the right place....
			
			//Set Changed Value
			if(!stackDone.length) this.hasChanged = false; //doesn't matter for recursion (up)
			
			return UndoObj;
		}
		
		jpf.status("Executing undo");

		//Undo the last X places - where X = id;
		var i = 0;
		if(id == -1) id = stackDone.length;
		if(!id) id = 1;
		
		while(i < id && stackDone.length > 0){
			if(!stackDone[stackDone.length-1]) stackDone.length--;
			else{
				stackUndone.push(this.undo(stackDone.length-1, true, stackDone, stackUndone));
				i++;
			}
		}
		
		if(this.onchange) this.onchange(true);
	}
	
	this.redo = function(id, single, stackDone, stackUndone, rollBack){
		if(!stackDone) stackDone = this.stackDone;
		if(!stackUndone) stackUndone = this.stackUndone;
		
		if(!stackUndone.length) return;
		if(single){
			//var UndoObj = stackUndone.pop();
			//if(!UndoObj) return;
			
			var UndoObj = stackUndone[id];
			if(!UndoObj) return;
			
			//Workaround for calls coming in late... (prolly not needed for redo)
			if(id == stackUndone.length-1) stackUndone.length--;
			else stackUndone[id] = null;
			
			//Undo Client Side Action
			if(UndoObj.action) 
				(typeof UndoObj.action == "function" ? UndoObj.action : this.actions[UndoObj.action])(UndoObj, false, this);
			
			//Respond - REMOVED.. shouldn't be called during redo
			if(!rollBack) UndoObj.saveChange(false, this); // WHY NOT??? seems the right place....
			
			//this.stackDone.push(UndoObj);
			this.hasChanged = true;
			
			return UndoObj;
		}
		
		jpf.status("Executing redo");
		
		//Redo the last X places - where X = id;
		var i = 0;
		if(id == -1) id = stackUndone.length;
		if(!id) id = 1;
		
		while(i < id && stackUndone.length > 0){
			if(!stackUndone[stackUndone.length-1]) stackUndone.length--;
			else{
				stackDone.push(this.redo(stackUndone.length-1, true, stackDone, stackUndone));
				i++;
			}
		}
		
		if(this.onchange) this.onchange();
	}
	
	/* ********************************************************************
										OTHER
	*********************************************************************/
	
	this.receive = function(data, state, extra, ids){
		if(state != __HTTP_SUCCESS__){
			if(state == __HTTP_TIMEOUT__ && extra.retries < jpf.maxHttpRetries) return extra.tpModule.retry(extra.id);
			else{
				var commError = new Error(1028, jpf.formErrorString(1028, null, "ActionTracker", "Could not sent Action RPC request for control " + this.name + "[" + this.tagName + "] \n\n" + extra.message));
				if(this.dispatchEvent("onerror", jpf.extend({error : commError, state : status}, extra)) !== false)
					throw commError;
				return;
			}
		}
		
		//hack!!
		if(data && data.nodeType && data.selectSingleNode("//undo")){
			//SDU hacking
			var msg = jpf.getXmlValue(data, "//undo/reason") + "\n";
			var nodes = data.selectNodes("//undo/object");
			for(var i=0;i<nodes.length;i++){
				msg += "- " + nodes[i].getAttribute("name") + "\n";
			}
			data = msg;
		}
		else return;
		
		/*if(data){
			//Get Undo Node
			var UndoObj = this.stackDone[ids];
			var xmlActionNode = UndoObj.getActionXmlNode();
			
			//Get Result Node
			if(xmlActionNode.getAttribute("result")){
				var rNode = UndoObj.xmlNode.selectSingleNode(xmlActionNode.getAttribute("result"));

				//Attribute Node - fill
				if(rNode.nodeType == 2) rNode.nodeValue = data;
				
				//Other Node - replace
				else{
					xmlNode = jpf.getObject("XMLDOM", data).documentElement.firstChild;
					rNode.parentNode.replaceChild(xmlNode ,rNode);
				}
				
				jpf.XMLDatabase.applyChanges("synchronize", UndoObj.xmlNode);
			}
			
			return;
		}*/
		if(typeof ids == "number") return this.doError(data, ids);
		
		for(var i=0;i<ids.length;i++) this.doError(data[i], ids[i]);
	}
	
	this.doError = function(data, id){
		//Alert reason for denying access
		if(data) alert(data);
		
		//Undo failed actions
		//this.undo(id, true);
		this.undo(id, true, null, null, true);
	}
	
	/* ********************************************************************
									BUILD-IN ACTIONS
	*********************************************************************/
	
	
	this.define("setTextNode", 
		function(UndoObj, undo){
			var q = UndoObj.args;
			
			//Set Text Node
			if(!undo) jpf.XMLDatabase.setTextNode(q[0], q[1], q[2], UndoObj);
			//Undo Text Node Setting
			else jpf.XMLDatabase.setTextNode(q[0], UndoObj.oldValue, q[2]);
		}
	);
	
	this.define("setAttribute", 
		function(UndoObj, undo){
			var q = UndoObj.args;
			
			//Set Attribute
			if(!undo){
				//Set undo info
				UndoObj.name = q[1];
				UndoObj.oldValue = q[0].getAttribute(q[1]);
				
				jpf.XMLDatabase.setAttribute(q[0], q[1], q[2], q[3], UndoObj);
			}
			//Undo Attribute Setting
			else jpf.XMLDatabase.setAttribute(q[0], q[1], UndoObj.oldValue, q[3]);
		}
	);
	
	this.define("setAttributes", 
		function(UndoObj, undo){
			var prop, q = UndoObj.args;
			
			//Set Attribute
			if(!undo){
				//Set undo info
				var oldValues = {};
				for(prop in q[1]){
					oldValues[prop] = q[0].getAttribute(prop);
					q[0].setAttribute(prop, q[1][prop]);
				}
				UndoObj.oldValues = oldValues;
				
				jpf.XMLDatabase.applyChanges("attribute", q[0], UndoObj);
			}
			//Undo Attribute Setting
			else{
				for(prop in UndoObj.oldValues){
					if(!UndoObj.oldValues[prop]) q[0].removeAttribute(prop);
					else q[0].setAttribute(prop, UndoObj.oldValues[prop]);
				}
				jpf.XMLDatabase.applyChanges("attribute", q[0], UndoObj);
			}
		}
	);
	
	this.define("replaceNode", 
		function(UndoObj, undo){
			var q = UndoObj.args;
			
			//Set Attribute
			if(!undo) jpf.XMLDatabase.replaceNode(q[0], q[1], q[2], UndoObj);
			//Undo Attribute Setting
			else jpf.XMLDatabase.replaceNode(q[1], q[0], q[2]);
		}
	);
		
	this.define("addChildNode", 
		function(UndoObj, undo){
			var q = UndoObj.args;
			
			//Add Child Node
			if(!undo) jpf.XMLDatabase.addChildNode(q[0], q[1], q[2], q[3], q[4], UndoObj);
			//Remove Child Node
			else jpf.XMLDatabase.removeNode(UndoObj.addedNode);
		}
	);
	
	this.define("appendChildNode", 
		function(UndoObj, undo){
			var q = UndoObj.args;
			
			//Append Child Node
			if(!undo) jpf.XMLDatabase.appendChildNode(q[0], q[1], q[2], q[3], q[4], UndoObj);
			//Remove Child Node
			else jpf.XMLDatabase.removeNode(q[1]);
		}
	);
	
	this.define("moveNode", 
		function(UndoObj, undo){
			var q = UndoObj.args;

			//Move Node
			if(!undo) jpf.XMLDatabase.moveNode(q[0], q[1], q[2], q[3], UndoObj);
			//Move Node to previous position
			else jpf.XMLDatabase.moveNode(UndoObj.pNode, q[1], UndoObj.beforeNode, q[3]);
		}
	);
	
	this.define("removeNode", 
		function(UndoObj, undo){
			var q = UndoObj.args;

			//Remove Node
			if(!undo) jpf.XMLDatabase.removeNode(q[0], q[1], UndoObj);
			//Append Child Node
			else jpf.XMLDatabase.appendChildNode(UndoObj.pNode, UndoObj.removedNode, UndoObj.beforeNode);
		}
	);
	
	this.define("removeNodeList",
		function(UndoObj, undo){
			if(undo){
				var d = UndoObj.rData;
				for(var i=0;i<d.length;i++){
					jpf.XMLDatabase.appendChildNode(d[i].pNode, d[i].removedNode, d[i].beforeNode, UndoObj);
				}
			}
			else jpf.XMLDatabase.removeNodeList(UndoObj.args);
			
		}
	);
	
	this.define("setUndoObject", 
		function(UndoObj, undo){
			var q = UndoObj.args;
			UndoObj.xmlNode = q[0];
		}
	);
	
	this.define("group", 
		function(UndoObj, undo, at){
			if(!UndoObj.stackDone){
				var done = UndoObj.args[0];
				UndoObj.stackDone = done;
				UndoObj.stackUndone = [];
			}
			
			at[undo ? "undo" : "redo"](UndoObj.stackDone.length, false, UndoObj.stackDone, UndoObj.stackUndone);
		}
	);
	
	this.define("setValueByXpath", 
		function(UndoObj, undo){
			var q = UndoObj.args;//xmlNode, value, xpath

			//Setting NodeValue and creating the node if it doesnt exist
			if(!undo){
				if(UndoObj.newNode){
					var xmlNode = q[0].appendChild(UndoObj.newNode);
				}
				else{
					var newNodes = [];
					var xmlNode = jpf.XMLDatabase.createNodeFromXpath(q[0], q[2], newNodes);
					var node = newNodes[0] || xmlNode;
					
					UndoObj.newNode = node.nodeType == 1 ? node : null;
					if(UndoObj.newNode == q[0]) UndoObj.newNode = null;
					UndoObj.oldValue = jpf.getXmlValue(q[0], q[2]);
				}
				
				jpf.XMLDatabase.setNodeValue(xmlNode, q[1], true);
			}
			//Undo Setting NodeValue
			else{
				if(UndoObj.newNode) jpf.XMLDatabase.removeNode(UndoObj.newNode);
				else jpf.XMLDatabase.setNodeValue(q[0], UndoObj.oldValue, true);
			}
		}
	);
	
	this.define("addRemoveNodes", 
		function(UndoObj, undo){
			var q = UndoObj.args;
			
			//Set Text Node
			if(!undo){
				//Add
				for(var i=0;i<q[1].length;i++) jpf.XMLDatabase.appendChildNode(q[0], q[1][i], null, null, null, UndoObj);
				//Remove
				for(var i=0;i<q[2].length;i++) jpf.XMLDatabase.removeNode(q[2][i], null, UndoObj);
			}
			//Undo Text Node Setting
			else{
				//Add
				for(var i=0;i<q[2].length;i++) jpf.XMLDatabase.appendChildNode(q[0], q[2][i]);
				//Remove
				for(var i=0;i<q[1].length;i++) jpf.XMLDatabase.removeNode(q[1][i]);
			}
		}
	);
	
}

/**
 * @constructor
 */
jpf.UndoData = function(action, xmlActionNode, args, jmlNode, selNode){
	this.tagName = "UndoData";
	
	//Copy Constructor
	if(action && action.tagName == "UndoData"){
		this.action = action.action;
		this.xmlActionNode = action.xmlActionNode;
		this.xmlNode = action.xmlNode;
		this.args = jpf.copyArray(action.args);
		this.rdb_args = jpf.copyArray(action.rdb_args);
		this.jmlNode = jmlNode;
		this.selNode = action.selNode;
	}
	//Constructor
	else{
		this.action = action;
		this.xmlActionNode = xmlActionNode;
		this.args = args;
		this.jmlNode = jmlNode;
		
		//HACK! Please check the requirement for this and how to solve this. Goes wrong with multiselected actions!
		this.selNode = selNode || (action == "removeNode" ? args[0] : (jmlNode ? jmlNode.value : null)); 
	}
	
	this.getActionXmlNode = function(undo){
		if(!this.xmlActionNode) return false;
		if(!undo) return this.xmlActionNode;
		
		var xmlNode = $xmlns(this.xmlActionNode, "undo", jpf.ns.jpf)[0];
		if(!xmlNode) xmlNode = this.xmlActionNode;
		
		return xmlNode;
	}
	
	//PROCINSTR
	this.saveChange = function(undo, at, multicall){
		if(at && !at.realtime) return at.stackRPC.push(this);
		
		if(typeof this.action == "function") return;
		
		//Grouped undo/redo support
		if(this.action == "group"){
			var rpcNodes = this.args[1];
			for(var i=0;i<rpcNodes.length;i++) rpcNodes[i].saveChange(undo, at, multicall);
			return;
		}
		
		if(this.rdb_args){
			//Send RDB Data..
			multicall ?
				jpf.XMLDatabase.socket.sendMulti("rdb", this.rdb_args) : 
				jpf.XMLDatabase.socket.send("rdb", this.rdb_args);
		}
		
		var id = this.id, xmlActionNode = this.getActionXmlNode(undo);
		if(!xmlActionNode) return;
		
		//Process Change - Currently only 1 ActionTracker PER Form is supported - UndoData NEEDS id
		jpf.saveData(xmlActionNode.getAttribute("set"), this.selNode, 
			function(data, state, extra){
				at.receive(data, state, extra, id);
			}, multicall);
	}
}

/*FILEHEAD(/in/Core/Application/AppSettings.js)SIZE(6893)TIME(1213483123975)*/
/**
 *
 * @addnode global:appsettings
 */
jpf.appsettings = {
	tagName : "appsettings",
	
	//Defaults
	autoHideLoading : true,
	autoDisable : true,
	disableSpace : true,
	
	colsizing : true,
	colmoving : true,
	colsorting : true,
	
	loadJML : function(x){
		this.jml = x;
		
		//Set Globals
		if(!self.jpf.debug) jpf.debug = jpf.isTrue(x.getAttribute("debug"));
		if(x.getAttribute("debugtype")) jpf.debugType = x.getAttribute("debugtype");
		jpf.debugFilter = jpf.isTrue(x.getAttribute("debug-teleport")) ? "" : "!teleport";
		
		this.disableRightClick = jpf.isTrue(x.getAttribute("disable-right-click"));
		this.allowSelect = jpf.isTrue(x.getAttribute("allow-select"));
			
		this.autoDisableActions = jpf.isTrue(x.getAttribute("auto-disable-actions"));
		this.autoDisable = !jpf.isFalse(x.getAttribute("auto-disable"));
		this.disableF5 = jpf.isTrue(x.getAttribute("disable-f5"));
		this.autoHideLoading = !jpf.isFalse(x.getAttribute("auto-hide-loading"));
		
		this.disableSpace = !jpf.isFalse(x.getAttribute("disable-space"));
		this.disableBackspace = jpf.isTrue(x.getAttribute("disable-backspace"));
		
		if(jpf.hasDeskRun && this.disableF5) shell.norefresh = true;
		
		//Datagrid options
		this.colsizing = !jpf.isFalse(x.getAttribute("col-sizing"));
		this.colmoving = !jpf.isFalse(x.getAttribute("col-moving"));
		this.colsorting = !jpf.isFalse(x.getAttribute("col-sorting"));
		
		if(x.getAttribute("layout")) this.layout = x.getAttribute("layout");
		//jpf.windowManager.getForm(jmlParent.tagName == "Window" ? jmlParent.getAttribute("id") : "main").loadSettings(q);	
	}
}

/**
 * @constructor
 */
jpf.settings = function(){
	jpf.register(this, "settings", NOGUI_NODE);/** @inherits jpf.Class */
	var oSettings = this;

	/* ********************************************************************
									PROPERTIES
	*********************************************************************/
	
	this.inherit(jpf.DataBinding); /** @inherits jpf.DataBinding */

	/* ********************************************************************
									PUBLIC METHODS
	*********************************************************************/

	this.getSetting = function(name){
		return this[name];
	}
	
	this.setSetting = function(name, value){
		this.setProperty(name, value);
	}

	this.isChanged = function(name){
		if(!savePoint) return true;
		return this.getSettingsNode(savePoint, name) != this[name];
	}

	this.exportSettings = function(instruction){
		if(!this.XMLRoot) return;
		
		jpf.saveData(instruction, this.XMLRoot, 
			function(data, state, extra){
				if(state != __HTTP_SUCCESS__){
					if(state == __HTTP_TIMEOUT__ && extra.retries < jpf.maxHttpRetries) return extra.tpModule.retry(extra.id);
					else{
						var commError = new Error(0, jpf.formErrorString(0, oSettings, "Saving settings", "Error saving settings: " + extra.message));
						if(oSettings.dispatchEvent("onerror", jpf.extend({error : commError, state : status}, extra)) !== false)
							throw commError;
						return;
					}
				}
			});
		
		this.savePoint();
	}
	
	this.importSettings = function(instruction, def_instruction){
		jpf.getData(instruction, null, function(xmlData, state, extra){
			if(state != __HTTP_SUCCESS__){
				if(state == __HTTP_TIMEOUT__ && extra.retries < jpf.maxHttpRetries) return extra.tpModule.retry(extra.id);
				else{
					var commError = new Error(0, jpf.formErrorString(0, oSettings, "Loading settings", "Error loading settings: " + extra.message));
					if(oSettings.dispatchEvent("onerror", jpf.extend({error : commError, state : status}, extra)) !== false)
						throw commError;
					return;
				}
			}
			
			if(!xmlData && def_instruction) oSettings.importSettings(def_instruction);
			else oSettings.load(xmlData);
		});
	}
	
	var savePoint;
	this.savePoint = function(){
		savePoint = XMLDatabase.copyNode(this.XMLRoot);
	}
	
	//Databinding
	this.smartBinding = true;//Hack to ensure that data is loaded, event without smartbinding
	this.__load = function(XMLRoot){
		XMLDatabase.addNodeListener(XMLRoot, this);
		
		for(var prop in settings){
			this.setProperty(prop, null); //Maybe this should be !and-ed
			delete this[prop];
			delete settings[prop];
		}
		
		var nodes = this.XMLRoot.selectNodes(this.traverseRule || "node()[text()]");
		for(var i=0;i<nodes.length;i++){
			this.setProperty(
				this.applyRuleSetOnNode("name", nodes[i]) || nodes[i].tagName, 
				this.applyRuleSetOnNode("value", nodes[i]) || getXmlValue(nodes[i], "text()"));
		}
	}
	
	this.__xmlUpdate = function(action, xmlNode, listenNode){
		//Added setting
		var nodes = this.XMLRoot.selectNodes(this.traverseRule || "node()[text()]");
		for(var i=0;i<nodes.length;i++){
			var name = this.applyRuleSetOnNode("name", nodes[i]) || nodes[i].tagName;
			var value = this.applyRuleSetOnNode("value", nodes[i]) || getXmlValue(nodes[i], "text()");
			if(this[name] != value) this.setProperty(name, value);
		}
		
		//Deleted setting
		for(var prop in settings){
			if(!this.getSettingsNode(this.XMLRoot, prop)){
				this.setProperty(prop, null);
				delete this[prop];
				delete settings[prop];
			}
		}
	}
	
	this.reset = function(){
		if(!savePoint) return;
		this.load(XMLDatabase.copyNode(savePoint));
	}

	//Properties
	this.getSettingsNode = function(xmlNode, prop, create){
		if(!xmlNode) xmlNode = this.XMLRoot;
		
		var nameNode = this.getNodeFromRule("name", this.XMLRoot);
		var valueNode = this.getNodeFromRule("value", this.XMLRoot);
		nameNode = nameNode ? nameNode.getAttribute("select") : "@name";
		valueNode = valueNode ? valueNode.getAttribute("select") || "text()" : "text()";
		var traverse = this.traverseRule + "[" + nameNode + "='" + prop + "']/" + valueNode || prop + "/" + valueNode;
		
		return create ?
			jpf.XMLDatabase.createNodeFromXpath(xmlNode, traverse) :
			jpf.getXmlValue(this.xmlNode, traverse);
	}
	
	this.handlePropSet = function(prop, value, force){
		if(!force && this.XMLRoot)
			return jpf.XMLDatabase.setNodeValue(this.getSettingsNode(this.XMLRoot, prop, true), true);
		
		this[prop] = value;
		settings[prop] = value;
	}
	
	//Init
	this.loadJML = function(x){
		this.importSettings(x.getAttribute("get"), x.getAttribute("default"));
		this.exportInstruction = x.getAttribute("set");
		
		this.jml = x;
		jpf.JMLParser.parseChildren(this.jml, null, this);
		
		//Model handling in case no smartbinding is used
		var modelId = jpf.XMLDatabase.getInheritedAttribute(x, "model");

		for(var i=0;i<jpf.JMLParser.modelInit.length;i++)
			if(jpf.JMLParser.modelInit[i][0] == this) return;

		jpf.setModel(modelId, this);
	}

	//Destruction
	this.destroy = function(){
		if(this.exportInstruction)
			this.exportSettings(this.exportInstruction);
	}
}
/*FILEHEAD(/in/Core/Application/DeskRun.js)SIZE(3302)TIME(1201688465117)*/
DeskRun = {
	widgets : [],
	
	register : function(widget){
		widget.show = function(dontset){
			if(!this.posInited){
				var pos = jpf.compat.getAbsolutePosition(this.pHtmlNode);
				
				//lp.write("DT",this.name);
				//alert((pos[0] + parseInt(this.jml.getAttribute("left"))) + ":" + (pos[1] + parseInt(this.jml.getAttribute("top"))));
				//if(this.name!='sldMCamKey')
				this.oExt.moveTo(pos[0] + parseInt(this.jml.getAttribute("left"))+2, pos[1] + parseInt(this.jml.getAttribute("top"))+2);
				//if(this.name!='sldMCamKey')
				this.oExt.show();
				this.posInited = true;
				if(!dontset) this.isVisible = true;
			}
			else{
				this.oExt.show();
				if(!dontset) this.isVisible = true;
			}
		}
		
		widget.hide = function(dontset){
			this.oExt.hide();
			if(!dontset) this.isVisible = false;
		}
		
		this.widgets.push(widget);
	},
	
	hideAll : function(){
		window.external.shell.update();
		
		for(var i=0;i<this.widgets.length;i++){
			this.widgets[i].hide(true);
			window.external.shell.update();
		}
	},
	
	showAll : function(){
		window.external.shell.update();
		
		for(var i=0;i<this.widgets.length;i++){
			if(this.widgets[i].pHtmlNode.offsetHeight && this.widgets[i].isVisible) 
				this.widgets[i].show(true);
			shell.update();
		}
	},
	
	fixShow : function(){
		window.external.shell.update();
		
		for(var i=0;i<this.widgets.length;i++){
			//if(this.widgets[i].tagName == "MFSlider") alert(this.widgets[i].parentNode.tagName + ":" + this.widgets[i].parentNode.outerHTML + ":" + this.widgets[i].parentNode.offsetHeight);
			if(this.widgets[i].pHtmlNode.offsetHeight && this.widgets[i].isVisible) 
				this.widgets[i].show(true);
			else{
				this.widgets[i].hide(true);
			}
			window.external.shell.update();
		}
	}
}

/*if(jpf.hasDeskRun){
	window.onerror = function(){
		window.external.show();
	}
}*/


/*
this.doOptimize = function(left, top, width, height, right, bottom, align, no_optimize){
	//if(!self.JDepWindow) 
	return; //temporarily disabled
	
	var addParent = this.parentNode == document.body;
	if(addParent) alert(addParent);
	var left = parseInt(this.oExt.style.left) || parseInt(this.jml.getAttribute("left")) + (addParent ? parseInt(this.parentNode.style.left) : null);
	var top = parseInt(this.oExt.style.top) || parseInt(this.jml.getAttribute("top")) + (addParent ? parseInt(this.parentNode.style.top) : null);
	var width = parseInt(this.oExt.style.width) || parseInt(this.jml.getAttribute("width"));
	var height = parseInt(this.oExt.style.height) || parseInt(this.jml.getAttribute("height"));
	
	if(!left) return;

	var div = document.body.appendChild(document.createElement("div"));
	div.style.zIndex = 10000;
	div.style.border = "1px solid red";
	div.style.left = left;
	div.style.top = top;
	div.style.width = width;
	div.style.height = height;
	div.style.position = "absolute";
	
	//x.getAttribute("left"), x.getAttribute("top"), x.getAttribute("width"), x.getAttribute("height"), x.getAttribute("right"), x.getAttribute("bottom"), x.getAttribute("align"), 
	
	JDepWindow.MouseOptimize(
		parseInt(left) || 0,
		parseInt(top) || 0,
		parseInt(width) || 0,
		parseInt(height) || 0,
		no_optimize ? 1 : 0
	);
}
*/
/*FILEHEAD(/in/Core/Application/Layout.js)SIZE(35231)TIME(1213547348372)*/
/*
	align="{align:left,edge:splitter,edge-margin:10,splitter-size:3,exec:single}"
	
	align='bottom'
	align-position='0-0';
	align-edge='sizer'
	align-margin='10'
	align-sizer='3'
	width='x'
	height='y'
	min-height='x'
	min-width='y'
	
	align-exec='single'
*/


jpf.layoutServer = {
	layouts : {},
	
	addParent : function(oHtml, pMargin){
		if(!oHtml.getAttribute("id")) jpf.setUniqueHtmlId(oHtml);
		return this.layouts[oHtml.getAttribute("id")] = {
			layout : new jpf.Layout(oHtml, pMargin),
			controls : []
		}
	},
	
	
	splitters : {},
	freesplitters : [],
	vars : {},
	
	getSplitter : function(layout){
		if(!this.splitters[this.getHtmlId(layout.parentNode)])
			this.splitters[this.getHtmlId(layout.parentNode)] = [];
			
		if(this.freesplitters.length){
			var splitter = this.freesplitters.pop();
		}
		else{
			var splitter = new jpf.splitter(this.parentNode);
			splitter.loadSkin();
			splitter.draw();
		}
		
		this.splitters[this.getHtmlId(layout.parentNode)].push(splitter);
		
		return splitter;
	},
	
	clearSplitters : function(layout){
		var ar = this.splitters[this.getHtmlId(layout.parentNode)];
		if(!ar) return;
		
		for(var i=0;i<ar.length;i++){
			this.freesplitters.push(ar[i]);
			ar[i].oExt.parentNode.removeChild(ar[i].oExt);
		}
		ar.length = 0;
	},
	
	G : [],
	addGrid : function(str, pHtmlNode){
		this.G.push([str, pHtmlNode]);
	},
	activateGrid : function(){
		if(!this.G.length) return;

		//var rsz = this.G.join("\n");
		//jpf.layoutServer.setRules(document.body, "grid", rsz, true);
		//jpf.layoutServer.activateRules(document.body);
		for(var i=0;i<this.G.length;i++){
			jpf.layoutServer.setRules(this.G[i][1], "grid", this.G[i][0]);//, true);
			if(!jpf.hasSingleRszEvent) jpf.layoutServer.activateRules(this.G[i][1]);
		}
		
		if(jpf.hasSingleRszEvent) jpf.layoutServer.activateRules();
	},
	
	
	/*removeControl : function(layout, id){
		if(!layout.controls[id]) return false;
		
		layout.controls[id].parent.children.remove(layout.controls[id]);
		layout.controls[id] = null;
		
		return true;
	},
	addControl : function(layout, id, aData){
		layout.controls[id] = aData;
		aData.hid = id;
		if(aData.parent) aData.parent.children.pushUnique(aData);
		//aData.sid = aData.template.split("-")[0];
	},*/
	
	get : function(oHtml, pMargin){
		var layout = this.layouts[oHtml.getAttribute("id")];
		if(!layout) layout = this.addParent(oHtml, pMargin);
		return layout;
	},
	
	isLoadedXml : function(xmlNode){
		var nodes = xmlNode.childNodes;
		var node = xmlNode.selectSingleNode(".//node[@name]");//was node()
		var jmlNode = node ? self[node.getAttribute("name")] : null;
		if(!jmlNode) throw new Error(0, jpf.formErrorString(0, null, "Loading Alignment from XML", "Could not find JML node" + (node ? " by name '" + node.getAttribute("name") + "'" : ""), xmlNode));
		var pNode = jmlNode.oExt.parentNode;
		var pId = this.getHtmlId(pNode);
		
		return this.loadedXml[pId] == xmlNode;
	},
	
	//Jml Nodes should exist
	loadedXml : {},
	cacheXml : {},
	loadXml : function(xmlNode){
		var nodes = xmlNode.childNodes;
		var node = xmlNode.selectSingleNode(".//node[@name]");//was node()
		var jmlNode = node ? self[node.getAttribute("name")] : null;
		if(!jmlNode) throw new Error(0, jpf.formErrorString(0, null, "Loading Alignment from XML", "Could not find JML node" + (node ? " by name '" + node.getAttribute("name") + "'" : ""), xmlNode));
		var pNode = jmlNode.oExt.parentNode;
		var layout = this.get(pNode, (xmlNode.getAttribute("margin") || "").split(/,\s*/));
		var pId = this.getHtmlId(pNode);

		//Caching - still under development
		/*var xmlId = xmlNode.getAttribute(jpf.XMLDatabase.xmlIdTag);
		if(!xmlId){
			jpf.XMLDatabase.nodeConnect(jpf.XMLDatabase.getXmlDocId(xmlNode), xmlNode)
			xmlId = xmlNode.getAttribute(jpf.XMLDatabase.xmlIdTag);
		}
		
		if(this.cacheXml[xmlId]){
			var o = this.cacheXml[xmlId];
			this.metadata = o.metadata;
			this.rules[pId].layout = o.layout;
			layout.root = o.root;
			o.xmlNode.appendChild(o.root.xml);
			this.activateRules(pNode);
			this.clearSplitters(layout.layout);
			this.splitters[pId] = o.splitters.copy();
			this.freesplitters = o.freesplitters.copy();
			this.vars = jpf.extend({}, o.vars);
			for(var i=0;i<this.splitters[pId].length;i++)
				pNode.appendChild(this.splitters[pId][i].oExt);
			this.loadedXml[pId] = o.xmlNode;
			return;
		}*/
		
		this.metadata = [];

		for(var i=0;i<nodes.length;i++){
			if(nodes[i].nodeType != 1) continue;
			layout.root = this.parseXml(nodes[i], layout);
			break;
		}
		
		this.compile(pNode);
		if(jpf.JMLParser.inited) this.activateRules(pNode);
		
		this.loadedXml[pId] = xmlNode;
		
		/* caching - still under development
		this.cacheXml[xmlId] = {
			xmlNode : xmlNode,
			root : layout.root,
			layout : this.rules[pId].layout,
			metadata : this.metadata,
			splitters : this.splitters[pId].copy(),
			freesplitters : this.freesplitters.copy(),
			vars : jpf.extend({}, this.vars)
		};*/
	},
	
	/**
	 * @todo Put well defined ifdef's here
	 */
	metadata : [],
	getData : function(type, layout){
		return {
			vbox : type == "vbox",
			hbox : type == "hbox",
			node : !type.match(/^(?:hbox|vbox)$/),
			children : [],
			isRight : false, 
			isBottom : false, 
			edgeMargin : 0, 
			splitter : null,
			minwidth : 0, 
			minheight : 0, 
			weight : 1,
			pHtml : layout.parentNode,
			size : [300,200],
			position : [0,0],
			
			copy : function(){
				var copy = jpf.extend({}, this);
				if(!this.node){
					copy.children = [];
					for(var i=0;i<this.children.length;i++){
						copy.children[i] = this.children[i].copy();
						copy.children[i].parent = copy;
					}
				}
				return copy;
			},
			
			setPosition : function(x, y){
				this.oHtml.style.left = x + "px";
				this.oHtml.style.top = y + "px";
				
				this.position = [x, y];
			},
			
			setFloat : function(){
				var diff = jpf.compat.getDiff(this.oHtml);

				this.oHtml.style.width = (this.size[0]-diff[0]) + "px";
				if(this.state < 0) this.oHtml.style.height = (this.size[1]-diff[1]) + "px";

				this.prehide();
				this.hidden = 3;
				
				if(this.hid) {
					var jmlNode = jpf.lookup(this.hid);
					if(jmlNode.syncAlignment) jmlNode.syncAlignment(this);
				}
			},
			
			unfloat : function(){
				if(this.hidden != 3) return;
				this.show();
			},
			
			state : -1,
			minimize : function(height){
				if(this.state < 0){
					this.lastfheight = this.fheight;
					this.fheight = "" + height;
					this.lastsplitter = this.splitter;
					if(this.parent.vbox) this.splitter = -1;
					this.state = 1;
				}
			},
			
			restore : function(){
				if(this.state > 0){
					this.fheight = this.lastfheight;
					this.splitter = this.lastsplitter;
					this.state = -1;
				}
			},
			
			hidden : false,
			hiddenChildren : [],
			prehide : function(){
				if(this.hidden == 3){
					this.hidden = true;
					if(this.hid) jpf.lookup(this.hid).visible = false;
					if(this.oHtml) this.oHtml.style.display = "none";
					return;
				}
				
				//Record current position
				this.hidepos = {
					prev : this.parent.children[this.stackId-1],
					next : this.parent.children[this.stackId+1]
				}
				
				this.hidden = true;
				jpf.layoutServer.dlist.push(this);
				
				//Check if parent is empty
				
				for(var c=0,i=0;i<this.parent.children.length;i++){
					if(!this.parent.children[i].hidden){
						c = 1;
						break;
					}
				}
				if(!c) this.parent.prehide();
			},
			preshow : function(){
				if(!this.hidden) return;
				this.hidden = false;

				//Check if parent is shown
				if(this.parent.hidden)
					this.parent.preshow();
				
				jpf.layoutServer.dlist.push(this);
			},
			
			hide : function(){
				//Remove from parent
				var nodes = this.parent.children;
				nodes.removeIndex(this.stackId);
				for(var i=0;i<nodes.length;i++) nodes[i].stackId = i;
				
				//Add to hidden
				this.parent.hiddenChildren.push(this);
				
				if(this.hidden != 3){
					if(this.hid) jpf.lookup(this.hid).visible = false;
					if(this.oHtml) this.oHtml.style.display = "none";
				}
			},
			
			show : function(){
				//if(!this.hidden) return;

				//Check if position is still available
				var nodes = this.parent.children;
				if(this.hidepos.prev && this.hidepos.prev.parent == this.parent && !this.hidepos.prev.hidden){
					if(nodes.length < this.hidepos.prev.stackId+1) nodes.push(this);
					else nodes.insertIndex(this, this.hidepos.prev.stackId+1);
				}
				else if(this.hidepos.next && this.hidepos.next.parent == this.parent && !this.hidepos.next.hidden){
					if(this.hidepos.next.stackId == 0) nodes.unshift(this);
					else if(nodes.length < this.hidepos.next.stackId-1) nodes.push(this);
					else nodes.insertIndex(this, this.hidepos.next.stackId-1);
				}
				else if(!this.hidepos.prev){
					nodes.unshift(this);
				}
				else if(!this.hidepos.next){
					nodes.push(this);
				}
				else{
					if(this.stackId < nodes.length) nodes.insertIndex(this, this.stackId);
					else nodes.push(this);
				}
				for(var i=0;i<nodes.length;i++) if(nodes[i]) nodes[i].stackId = i;

				//Remove from hidden
				this.parent.hiddenChildren.remove(this);

				if(this.hidden != 3){
					if(this.hid) jpf.lookup(this.hid).visible = true;
					if(this.oHtml) this.oHtml.style.display = "block";
				}
				
				this.hidden = false;
				this.hidepos = null;
			}
		};
	},
	
	parseXml : function(x, layout, jmlNode, norecur){
		var aData = this.getData(x[jpf.TAGNAME], layout.layout);
		
		if(aData.node){
			if(!jmlNode){
				var jmlNode = self[x.getAttribute("name")];
				if(!jmlNode) throw new Error(0, jpf.formErrorString(0, null, "Parsing Alignment from XML", "Could not find JML node" + x.getAttribute("name"), x));
			}
			if(!jmlNode.visible) jmlNode.show(true);//jmlNode.setProperty("visible", true);//not the most optimal position
			aData.oHtml = jmlNode.oExt;
			jmlNode.aData = aData;
			
			if(jmlNode.jml.getAttribute("width")) aData.fwidth = jmlNode.jml.getAttribute("width");
			if(jmlNode.jml.getAttribute("height")) aData.fheight = jmlNode.jml.getAttribute("height");
			if(jmlNode.minwidth) aData.minwidth = jmlNode.minwidth;
			if(jmlNode.minheight) aData.minheight = jmlNode.minheight;
			
			if(!this.getHtmlId(aData.oHtml)) jpf.setUniqueHtmlId(aData.oHtml);
			aData.id = this.getHtmlId(aData.oHtml);
			if(aData.oHtml.style) aData.oHtml.style.position = "absolute";
			aData.hid = jmlNode.uniqueId;
		}
		else{
			aData.id = this.metadata.push(aData)-1;
		}
		
		if(x.getAttribute("align")) aData.template = x.getAttribute("align");
		if(x.getAttribute("lean")) aData.isBottom = x.getAttribute("lean").match(/bottom/);
		if(x.getAttribute("lean")) aData.isRight = x.getAttribute("lean").match(/right/);
		if(x.getAttribute("edge") && x.getAttribute("edge") != "splitter") aData.edgeMargin = x.getAttribute("edge");
		if(x.getAttribute("weight")) aData.weight = parseFloat(x.getAttribute("weight"));
		if(x.getAttribute("splitter") || x.getAttribute("edge") == "splitter") aData.splitter = x.getAttribute("splitter") || (x.getAttribute("edge") == "splitter" ? 5 : false);
		if(x.getAttribute("width")) aData.fwidth = x.getAttribute("width");
		if(x.getAttribute("height")) aData.fheight = x.getAttribute("height");
		if(x.getAttribute("min-width")) aData.minwidth = x.getAttribute("min-width");
		if(x.getAttribute("min-height")) aData.minheight = x.getAttribute("min-height");
		if(x.getAttribute("lastheight")) aData.lastfheight = x.getAttribute("lastheight");
		if(x.getAttribute("lastsplitter")) aData.lastsplitter = x.getAttribute("lastsplitter");
		if(x.getAttribute("hidden")) 
			aData.hidden = x.getAttribute("hidden") == 3 ? x.getAttribute("hidden") : jpf.isTrue(x.getAttribute("hidden"));
		if(x.getAttribute("state")) aData.state = x.getAttribute("state");
		if(x.getAttribute("stack")) aData.stackId = parseInt(x.getAttribute("stack"));
		if(x.getAttribute("position")) aData.position = x.getAttribute("position").split(",");
		if(x.getAttribute("size")) aData.size = x.getAttribute("size").split(",");
		
		if(aData.fwidth && aData.fwidth.indexOf("/") > -1){//match(/[\(\)\+\-=\/\*]/)){
			aData.fwidth = eval(aData.fwidth);
			if(aData.fwidth <= 1) aData.fwidth = (aData.fwidth*100) + "%";
		}
		if(aData.fheight && aData.fheight.indexOf("/") > -1){//.match(/[\(\)\+\-=\/\*]/)){
			aData.fheight = eval(aData.fheight);
			if(aData.fheight <= 1) aData.fheight = (aData.fheight*100) + "%";
		}
		
		aData.edgeMargin = Math.max(aData.splitter || 0, aData.edgeMargin || 0);
		
		if(aData.node && jmlNode.syncAlignment) jmlNode.syncAlignment(aData);
		
		if(!norecur && !aData.node){
			var nodes = x.childNodes;
			for(var last, a, i=0;i<nodes.length;i++){
				if(nodes[i].nodeType != 1) continue;
				a = this.parseXml(nodes[i], layout);
				
				if(last && last.hidden) last.hidepos.next = a;
				
				if(a.hidden){
					if(a.hid){
						var j = jpf.lookup(a.hid);
						if(a.hidden === true && j.visible){
							j.visible = false;
							a.oHtml.style.display = "none";
						}
						if(a.hidden == 3){
							var diff = jpf.compat.getDiff(a.oHtml);
							a.oHtml.style.left = a.position[0] + "px";
							a.oHtml.style.top = a.position[1] + "px";
							a.oHtml.style.width = (a.size[0]-diff[0]) + "px";
							a.oHtml.style.height = ((!this.state || this.state < 0 ? a.size[1] : a.fheight)-diff[1]) + "px";
						}
					}
					
					aData.hiddenChildren.push(a);
					a.hidepos = {prev : aData.children[aData.children.length-1]}
				}
				else{
					if(a.hid){
						var j = jpf.lookup(a.hid);
						if(!j.visible){
							j.visible = true;
							a.oHtml.style.display = "block";
						}
					}
					a.stackId = aData.children.push(a) - 1;
				}

				a.parent = aData;
				last = a;
			}
		}
		
		aData.xml = x;
		
		return aData;
	},
	
	getXml : function(pNode){
		var l = jpf.layoutServer.get(pNode);
		var xmlNode = l.root.xml ? l.root.xml.ownerDocument.createElement("layout") : jpf.XMLDatabase.getXml("<layout />");
		jpf.layoutServer.parseToXml(l.root, xmlNode);
		return xmlNode
	},
	
	saveXml : function(){
		for(var pId in this.loadedXml){
			var xmlNode = this.loadedXml[pId];
			var l = this.layouts[pId];
			var root = l.root;
			
			for(var i=xmlNode.childNodes.length-1;i>=0;i--)
				xmlNode.removeChild(xmlNode.childNodes[i]);
			
			//xmlNode.removeChild(root.xml);
			this.parseToXml(root, xmlNode);
		}
	},
	
	parseToXml : function(oItem, parentNode){
		var xmlNode = oItem.xml ? 
			oItem.xml.cloneNode(false) :
			parentNode.ownerDocument.createElement(oItem.vbox ? "vbox" : (oItem.hbox ? "hbox" : "node"));
		
		parentNode.appendChild(xmlNode);
		
		if(oItem.template) xmlNode.setAttribute("align", oItem.template);
		if(oItem.edgeMargin) xmlNode.setAttribute("margin", oItem.edgeMargin);
		if(oItem.weight) xmlNode.setAttribute("weight", oItem.weight);
		if(oItem.splitter) xmlNode.setAttribute("splitter", oItem.splitter === false ? -1 : oItem.splitter);
		if(oItem.fwidth) xmlNode.setAttribute("width", oItem.fwidth);
		if(oItem.fheight) xmlNode.setAttribute("height", oItem.fheight);
		if(oItem.minwidth) xmlNode.setAttribute("min-width", oItem.minwidth);
		if(oItem.minheight) xmlNode.setAttribute("min-height", oItem.minheight);
		if(oItem.lastfheight) xmlNode.setAttribute("lastheight", oItem.lastfheight);
		if(oItem.lastsplitter) xmlNode.setAttribute("lastsplitter", oItem.lastsplitter);
		if(oItem.hidden) xmlNode.setAttribute("hidden", oItem.hidden == 3 ? '3' : 'true');
		else if(xmlNode.getAttribute("hidden")) xmlNode.removeAttribute("hidden");
		if(oItem.stackId) xmlNode.setAttribute("stack", oItem.stackId);
		if(oItem.state > 0) xmlNode.setAttribute("state", oItem.state);
		else if(xmlNode.getAttribute("state")) xmlNode.removeAttribute("state");
		if(oItem.position) xmlNode.setAttribute("position", oItem.position.join(","));
		if(oItem.size) xmlNode.setAttribute("size", oItem.size.join(","));
		//if(oItem.isBottom || oItem.isRight) xmlNode.setAttribute("lean", oItem.minheight);
		
		function getArrayIndex(arr, obj){
			for(var i=0;i<arr.length;i++) if(arr[i].id == obj.id) return i;
			return -1;
		}
		
		var list = oItem.children.copy();
		for(var i=0;i<oItem.hiddenChildren.length;i++){
			var hidepos = oItem.hiddenChildren[i].hidepos;
			if(hidepos.prev){
				var index = getArrayIndex(list, hidepos.prev);
				if(index < 0) list.unshift(oItem.hiddenChildren[i]);
				else list.insertIndex(oItem.hiddenChildren[i], index);
			}
			else if(hidepos.next){
				var index = getArrayIndex(list, hidepos.next);
				if(index-1 < 0) list.unshift(oItem.hiddenChildren[i]);
				else list.insertIndex(oItem.hiddenChildren[i], index-1);
			}
			else{
				list.push(oItem.hiddenChildren[i]);
			}
		}
		
		for(var i=0;i<list.length;i++){
			this.parseToXml(list[i], xmlNode);
		}
	},
	
	compile : function(oHtml){
		var l = this.layouts[oHtml.getAttribute("id")];
		if(!l) return false;

		var root = l.root.copy();//is there a point to copying?
		l.layout.compile(root);
		l.layout.reset();
	},
	
	timer : null,
	qlist : [],
	dlist : [],
	queue : function(oHtml, compile){
		for(var i=0;i<this.qlist.length;i++) if(this.qlist[i][0] == oHtml) return;
		this.qlist.push([oHtml, compile]);
		if(!this.timer) this.timer = setTimeout("jpf.layoutServer.processQueue()");
	},
	
	processQueue : function(){
		this.timer = null;
		
		for(var i=0;i<this.dlist.length;i++){
			if(this.dlist[i].hidden) this.dlist[i].hide();
			else this.dlist[i].show();
		}
		
		for(var i=0;i<this.qlist.length;i++){
			if(this.qlist[i][1]) jpf.layoutServer.compile(this.qlist[i][0]);
			if(!jpf.hasSingleRszEvent) jpf.layoutServer.activateRules(this.qlist[i][0]);
		}
		
		if(jpf.hasSingleRszEvent) jpf.layoutServer.activateRules();
		this.qlist = [];
		this.dlist = [];
	},
	
	
	rules : {},
	
	getHtmlId : function(oHtml){
		//if(jpf.hasSingleRszEvent) return 1;
		//else 
			return oHtml.getAttribute("id");
	},
	
	setRules : function(oHtml, id, rules, overwrite){
		if(!this.getHtmlId(oHtml)) jpf.setUniqueHtmlId(oHtml);
		if(!this.rules[this.getHtmlId(oHtml)]) this.rules[this.getHtmlId(oHtml)] = {};
		
		var ruleset = this.rules[this.getHtmlId(oHtml)][id];
		if(!overwrite && ruleset){
			this.rules[this.getHtmlId(oHtml)][id] = rules + "\n" + ruleset;
		}
		else this.rules[this.getHtmlId(oHtml)][id] = rules;
	},
	
	getRules : function(oHtml, id){
		return id ? this.rules[this.getHtmlId(oHtml)][id] : this.rules[this.getHtmlId(oHtml)];
	},
	
	removeRule : function(oHtml, id){
		if(!this.rules[this.getHtmlId(oHtml)]) return;
		
		var ret = this.rules[this.getHtmlId(oHtml)][id] ? true : false;
		delete this.rules[this.getHtmlId(oHtml)][id];
		
		var prop;
		for(prop in this.rules[this.getHtmlId(oHtml)]){}
		if(!prop) delete this.rules[this.getHtmlId(oHtml)]
		
		return ret;
	},
	
	activateRules : function(oHtml, no_exec){
		if(!jpf.hasSingleRszEvent && !oHtml){
			var prop;
			for(prop in this.rules){
				if(document.getElementById(prop).onresize) continue;
				this.activateRules(document.getElementById(prop));
			}
			return;
		}
		
		var strRules = []
		
		if(!jpf.hasSingleRszEvent){
			var rules = this.rules[this.getHtmlId(oHtml)];
			if(!rules) return false;
			
			for(var id in rules){ //might need optimization using join()
				if(typeof rules[id] != "string") continue;
				strRules.push(rules[id]);
			}
			
			//jpf.status(strRules.join("\n"));
			var rsz = new Function(strRules.join("\n"));
			oHtml.onresize = rsz;
			if(!no_exec) rsz();
		}
		else{
			for(rule in this.rules){
				var rules = this.rules[rule];
				for(var id in rules){ //might need optimization using join()
					if(typeof rules[id] != "string") continue;
					strRules.push(rules[id]);
				}
			}
		
			//A hack.. should build a dep tree, but actually FF should just implement onresize on any HTML element.
			window.onresize = new Function(strRules.reverse().join("\n") + "\n" + strRules.join("\n"));
			if(!no_exec) window.onresize();
		}
	},
	
	forceResize : function(oHtml){
		var rsz = (!jpf.hasSingleRszEvent ? oHtml : window).onresize;
		if(rsz) rsz();
	},
	
	paused : {},
	pause : function(oHtml, replaceFunc){
		if(jpf.hasSingleRszEvent) oHtml = window;
		this.paused[this.getHtmlId(oHtml)] = oHtml.onresize;
		
		if(replaceFunc){
			oHtml.onresize = replaceFunc;
			replaceFunc();
		}
		else oHtml.onresize = null;
	},
	
	play : function(oHtml){
		if(jpf.hasSingleRszEvent) oHtml = window;
		
		var oldFunc = this.paused[this.getHtmlId(oHtml)];
		oHtml.onresize = oldFunc;
		if(oldFunc) oldFunc();
		
		this.paused[this.getHtmlId(oHtml)] = null;
	}
};



/**
 * @constructor
 */
jpf.Layout = function(parentNode, pMargin){
	var pMargin = pMargin && pMargin.length == 4 ? pMargin : [0, 0, 0, 0];
	this.pMargin = pMargin;
	this.RULES = [];
	
	this.parentNode = parentNode;
	if(!this.parentNode.getAttribute("id"))
		jpf.setUniqueHtmlId(this.parentNode);

	var knownVars = {};
	var minWidth = 0;
	var minHeight = 0;
	this.createSplitters = true;
	
	this.setMargin = function(sMargin){
		pMargin = sMargin;
	}
	
	this.reset = function(){
		this.RULES = [];
		knownVars = {};
		this.lastType = null;
		this.globalEdge = null;
		this.globalSplitter = null;
	}
	
	this.compile = function(root, noapply){
		this.addRule("var v = jpf.layoutServer.vars");
		
		this.globalSplitter = root.splitter;
		this.globalEdge = root.edgeMargin;
		
		if(this.globalSplitter || this.globalEdge)
			this.setglobals(root);
		this.preparse(root);
		this.parserules(root);
		
		if(this.createSplitters){
			jpf.layoutServer.clearSplitters(this);
			this.parsesplitters(root);
		}
		
		//Sort by checking dependency structure
		this.RULES = new DepTree().calc(this.RULES);
		
		var str = ("try{" + this.RULES.join("}catch(e){}\ntry{") + "}catch(e){}\n").replace(/([^=]+\.style[^=]+) = (.*?)\}/g, "$1 = ($2) + 'px'}");
		//var str = this.RULES.join("\n");
		str = str.replace(/q([\w|]+)\.(offset|style)/g, 'document.getElementById("q$1").$2');

		//optimization
		//if(this.parentNode != document.body)
			//"if(document.getElementById('" + this.parentNode.id + "').offsetHeight){" + str + "};";

		this.lastRoot = root;
	
		if(!noapply) jpf.layoutServer.setRules(this.parentNode, "layout", str, true);
		else return str;

		return false;
	}
	
	this.addRule = function(rule){
		this.RULES.push(rule);
	}
	
	this.setglobals = function(node){
		if(this.globalEdge && !node.edgeMargin){
			if(!node.splitter) node.splitter = this.globalSplitter;
			node.edgeMargin = Math.max(this.globalSplitter, this.globalEdge);
		}
		
		if(node.node) return;
		
		for(var i=0;i<node.children.length;i++){
			this.setglobals(node.children[i]);
		}
	}
	
	this.preparse = function(node){
		/*
			Define:
			- minwidth
			- minheight
			- calcheight
			- calcwidth
			- restspace
			- innerspace
		*/
		
		if(node.node) return;
		else{
			var type = node.vbox ? "height" : "width";
			var cmhwp = 0;
			var cmwwp = 0;
			var ctph = 0;
			//Calculate resultSpace
			node.childweight = 0;
			node.childminwidth = 0;
			node.childminheight = 0;
			var rules = ["v." + type + "_" + node.id], extra = [];
			var nodes = node.children;
			for(var i=0;i<nodes.length;i++){
				if(i < nodes.length-1) rules.push(" - " + nodes[i].edgeMargin);
				var f = nodes[i]["f" + type];
				if(f){
					//if(f.indexOf("%") > -1) ctph += parseFloat(f);
					
					extra.push(
						f.indexOf("%") > -1 ?
							" - (" + (nodes[i]["calc" + type] = "v.innerspace_" + node.id + " * " + parseFloat(f)/100) + ")" :
							" - (" + f + ")"
					);
				}
				else{
					node.childweight += nodes[i].weight;
					nodes[i]["calc" + type] = "Math." + (i%2 == 0 ? "ceil" : "floor") + "(v.restspace_" + node.id + " * (" + nodes[i].weight + "/v.weight_" + node.id + "))";
				}
				
				var g = (node.vbox ? "width" : "height");
				var v = nodes[i]["f" + g];
				if(!v) nodes[i]["calc" + g] = (node.vbox ? "v.width_" : "v.height_") + node.id;
				else nodes[i]["calc" + g] = v.indexOf("%") > -1 ? "v.innerspace_" + node.id + " * " + parseFloat(v)/100 : v
				
				if(!nodes[i].node) this.preparse(nodes[i]);
				
				if(node.vbox){
					/*if(!nodes[i].fheight){
						cmhwp = Math.max(cmhwp, Math.max(nodes[i].childminheight || 0, nodes[i].minheight || 0, 10)/nodes[i].weight);
						node.childminheight += nodes[i].edgeMargin;
					}
					else */
						node.childminheight += Math.max(nodes[i].childminheight || 0, nodes[i].minheight || 0, 10) + nodes[i].edgeMargin;
					node.childminwidth = Math.max(node.childminwidth, nodes[i].minwidth || nodes[i].childminwidth || 10);
				}
				else{
					/*if(!nodes[i].fwidth){
						cmwwp = Math.max(cmwwp, Math.max(nodes[i].childminwidth || 0, nodes[i].minwidth || 0, 10)/nodes[i].weight);
						node.childminwidth += nodes[i].edgeMargin;
					}
					else */
						node.childminwidth += Math.max(nodes[i].minwidth || 0, nodes[i].childminwidth || 0, 10) + nodes[i].edgeMargin;
					node.childminheight = Math.max(node.childminheight, nodes[i].minheight || nodes[i].childminheight || 10);
				}
			}
			
			/*if(node.vbox){
				if(cmhwp){
					if(ctph) node.childminheight += (cmhwp * node.childweight/(100-ctph))*ctph;
					node.childminheight += cmhwp * node.childweight;
				}
			}
			else{
				if(cmwwp){
					if(ctph) node.childminwidth += (cmwwp * node.childweight/(100-ctph))*ctph;
					node.childminwidth += cmwwp * node.childweight;
				}
			}*/
			
			node.innerspace = rules.join("");
			node.restspace = node.innerspace + " " + extra.join("");
			
			if(!node.parent){
				var hordiff = 0, verdiff = 0;
				if(this.parentNode.tagName.toLowerCase() != "body"){
					var diff = jpf.compat.getDiff(this.parentNode);
					var verdiff = diff[0];
					var hordiff = diff[1];
				}
				
				var strParentNodeWidth = (this.parentNode.tagName.toLowerCase() == "body" ? (jpf.isIE ? "document.documentElement['offsetWidth']" : "window.innerWidth") : "document.getElementById('" + this.parentNode.id + "').offsetWidth");
				var strParentNodeHeight = (this.parentNode.tagName.toLowerCase() == "body" ? (jpf.isIE ? "document.documentElement['offsetHeight']" : "window.innerHeight") : "document.getElementById('" + this.parentNode.id + "').offsetHeight");
				node.calcwidth = "Math.max(" + minWidth + ", " + strParentNodeWidth + " - " + (pMargin[1]) + " - " + pMargin[3] + " - " + hordiff + ")";
				node.calcheight = "Math.max(" + minHeight + ", " + strParentNodeHeight + " - " + (pMargin[2]) + " - " + pMargin[0] + " - " + verdiff + ")";
			}
		}
	}
	
	this.parserules = function(oItem){
		if(!oItem.node){
			this.addRule("v.width_" + oItem.id + " = Math.max(" + oItem.childminwidth + "," + oItem.minwidth + "," + (oItem.calcwidth || oItem.fwidth) + ")");
			this.addRule("v.height_" + oItem.id + " = Math.max(" + oItem.childminheight + "," + oItem.minheight + "," + (oItem.calcheight || oItem.fheight) + ")");
			this.addRule("v.weight_" + oItem.id + " = " + oItem.childweight);
			this.addRule("v.innerspace_" + oItem.id + " = " + oItem.innerspace);
			this.addRule("v.restspace_" + oItem.id + " = " + oItem.restspace);
			
			var aData = jpf.layoutServer.metadata[oItem.id];
			aData.calcData = oItem; oItem.original = aData;
			
			if(!oItem.parent){
				this.addRule("v.left_" + oItem.id + " = " + pMargin[0]);
				this.addRule("v.top_" + oItem.id + " = " + pMargin[3]);
				
				for(var i=0;i<oItem.children.length;i++)
					this.parserules(oItem.children[i]);
				
				return;
			}
			else{
				var vtop = ["v.top_" + oItem.id, " = "];
				var vleft = ["v.left_" + oItem.id, " = "];
			}
		}
		else{
			var vtop = [oItem.id, ".style.top = "];
			var vleft = [oItem.id, ".style.left = "];
			
			if(oItem.hid){
				var aData = jpf.lookup(oItem.hid).aData;
				aData.calcData = oItem; oItem.original = aData;
			}
			
			var oEl = oItem.oHtml;//document.getElementById(oItem.id);
			var diff = jpf.compat.getDiff(oEl);
			var verdiff = diff[1];
			var hordiff = diff[0];

			if(oItem.calcwidth)
				this.addRule(oItem.id + ".style.width = -" + hordiff + " + Math.max( " + oItem.calcwidth + ", " + oItem.minwidth + ")");
			else oEl.style.width = Math.max(0, oItem.fwidth - hordiff) + "px";
			
			if(oItem.calcheight)
				this.addRule(oItem.id + ".style.height = -" + verdiff + " + Math.max( " + oItem.calcheight + ", " + oItem.minheight + ")");
			else oEl.style.height = Math.max(0, oItem.fheight - verdiff) + "px";
		}
		
		var oLastSame = oItem.parent.children[oItem.stackId - 1];
		var oNextSame = oItem.parent.children[oItem.stackId + 1];
		
		//TOP
		if(oItem.parent.vbox){
			if(oItem.parent.isBottom){
				if(!oNextSame) vtop.push("v.top_", oItem.parent.id, " + v.height_", oItem.parent.id, " - ", oItem.id, ".offsetHeight");
				else{
					if(oNextSame.node) vtop.push(oNextSame.id, ".offsetTop - ", oNextSame.edgeMargin, " - ", oItem.id, ".offsetHeight");
					else vtop.push("v.top_" + oNextSame.id, " - ", oNextSame.edgeMargin, " - ", (oItem.node ? oItem.id + ".offsetHeight" : "v.height_" + oItem.id));
				}
			}
			else if(!oItem.stackId) vtop.push("v.top_" + oItem.parent.id);
			else if(oLastSame){
				if(oLastSame.node) vtop.push(oLastSame.id, ".offsetTop + ", oLastSame.id, ".offsetHeight + ", oLastSame.edgeMargin);
				else vtop.push("v.top_", oLastSame.id, " + v.height_", oLastSame.id, " + ", oLastSame.edgeMargin);
			}
		}
		else vtop.push("v.top_" + oItem.parent.id);

		//LEFT	
		if(oItem.parent.hbox){
			if(oItem.parent.isRight){
				if(!oNextSame) vleft.push("v.left_", oItem.parent.id, " + v.width_", oItem.parent.id, " - ", oItem.id, ".offsetWidth", null);
				else{
					if(oNextSame.node) vleft.push(oNextSame.id, ".offsetLeft - ", oNextSame.edgeMargin, " - ", oItem.id, ".offsetWidth");
					else vleft.push("v.left_" + oNextSame.id, " - ", oNextSame.edgeMargin, " - ", (oItem.node ? oItem.id + ".offsetWidth" : "v.width_" + oItem.id));
				}
			}
			else if(!oItem.stackId) vleft.push("v.left_" + oItem.parent.id);
			else if(oLastSame){
				if(oLastSame.node) vleft.push(oLastSame.id, ".offsetLeft + ", oLastSame.id, ".offsetWidth + ", oLastSame.edgeMargin);
				else vleft.push("v.left_", oLastSame.id, " + v.width_", oLastSame.id, " + ", oLastSame.edgeMargin);
			}
		}
		else vleft.push("v.left_" + oItem.parent.id);
		
		if(vleft.length > 2) this.addRule(vleft.join(""));
		if(vtop.length > 2) this.addRule(vtop.join(""));
		
		if(!oItem.node){
			for(var i=0;i<oItem.children.length;i++)
				this.parserules(oItem.children[i]);
		}
	}
	
	this.parsesplitters = function(oItem){
		if(oItem.parent && oItem.splitter > 0 && oItem.stackId != oItem.parent.children.length-1)
			jpf.layoutServer.getSplitter(this).init(oItem.splitter, oItem.hid, oItem);
		
		if(!oItem.node){
			for(var i=0;i<oItem.children.length;i++)
				this.parsesplitters(oItem.children[i]);
		}
	}
	
	function DepTree(){
		this.parselookup = {};
		this.nRules = [];
		this.doneRules = {};
	
		this.maskText = function(str, m1, m2, m3){
			return m1 + ".offset" + m2.toUpperCase();
		}
		
		this.handleVar = function(match, m1, m2, m3){
			var vname = "a" + m1.replace(/\|/g, "_") + "_style_" + m2.toLowerCase();
			return knownVars[vname] ? vname : match;
		}
		
		this.parseRule = function(rule){
			var aRule = rule.split(" = ");
			var id = aRule[0].replace(/^([_\w\d\|]+)\.style\.(\w)/, this.maskText);
			var vname = "a" + aRule[0].replace(/[\.\|]/g, "_");
			knownVars[vname] = true;
	
			var depsearch = aRule[1].split(/[ \(\)]/);// " "
			var deps = [];
			for(var i=0;i<depsearch.length;i++){
				if(depsearch[i].match(/^([_\w\d\|]+)\.offset(\w+)$/) && !depsearch[i].match(/PNODE/)){
					deps.push(depsearch[i]);
				}
			}

			if(vname.match(/width|height/i)){
				aRule[1] = aRule[1].replace(/^(\s*[\-\d]+[\s\-\+]+)/, "");
				ruleB = aRule[0] + " = " + RegExp.$1 + vname;
			}
			else ruleB = aRule[0] + " = " + vname;

			if(rule.match(/^v\./)){
				return {
					id : id,
					rule_p1 : aRule[0] + " = ",
					rule_p2 : aRule[1],
					ruleb	: null,
					deps : deps,
					processed : false
				};
			}

			return {
				id : id,
				rule_p1 : "var " + vname + " = ",
				rule_p2 : aRule[1],
				ruleb	: ruleB,
				deps : deps,
				processed : false
			};
		}
		
		this.calc = function(aRules){
			var str = "";
			for(var i=0;i<aRules.length;i++){
				if(aRules[i].match(/^var/)){
					this.nRules.push(aRules[i]);
					continue;
				}
				var o = this.parseRule(aRules[i], i);
				this.parselookup[o.id] = o;
			}

			//build referential tree (graph)
			for(prop in this.parselookup){
				if(
					typeof prop != "string" || 
					!this.parselookup[prop] || 
					typeof this.parselookup[prop] == "boolean" || 
					typeof this.parselookup[prop] == "function"
				) continue;
				
				this.processNode(this.parselookup[prop]);
			}
			
			//Walk Tree
			for(prop in this.parselookup){
				if(
					typeof prop != "string" || 
					!this.parselookup[prop] || 
					typeof this.parselookup[prop] == "boolean" || 
					typeof this.parselookup[prop] == "function"
				) continue;
				var root = this.parselookup[prop];
				//if(root.processed) continue;
				this.walkRules(root);
			}

			//Set last rules
			for(prop in this.parselookup){
				if(
					typeof prop != "string" || 
					!this.parselookup[prop] || 
					typeof this.parselookup[prop] == "boolean" || 
					typeof this.parselookup[prop] == "function" || 
					!this.parselookup[prop].ruleb
				) continue;
				
				this.nRules.push(this.parselookup[prop].ruleb);
			}

			return this.nRules;
		}
		
		this.str = "";
		this.walkRules = function(root){
			if(this.doneRules[root.id]) return;

			for(var i=0;i<root.deps.length;i++){
				if(root.deps[i] && !root.deps[i].walked && !this.doneRules[root.deps[i].id]){
					root.deps[i].walked = true;
					this.walkRules(root.deps[i]);
				}
			}
	
			this.doneRules[root.id] = true;
			this.nRules.push(root.rule_p1 + root.rule_p2.replace(/([_\w\d\|]+)\.offset(\w+)/g, this.handleVar));
		}
		
		this.processNode = function(o){
			for(var i=0;i<o.deps.length;i++){
				var l = typeof o.deps[i] == "string" ? this.parselookup[o.deps[i]] : o.deps[i];
				if(!l){
					o.deps[i] = null;
					continue;
				}

				o.deps[i] = l;//.copy();
				if(!l.processed){
					l.processed = true;
					this.processNode(l);
				}
			}
		}
	}
}
/*FILEHEAD(/in/Core/Application/Model.js)SIZE(29193)TIME(1213461485214)*/

/**
 * Class Model represents a data model which can retrieve data from a data source.
 * This data can be edited, partially loaded, extended and resetted to it's original state.
 *
 * @classDescription		This class creates a new model
 * @return {Model} Returns a new model
 * @type {Model}
 * @constructor
 * @jpfclass
 *
 * @allowchild [cdata], instance, load, submission, offline
 * @addnode smartbinding:model, global:model
 * @attribute  id  
 * @attribute  load  
 * @attribute  submission  
 * @attribute  session  
 * @attribute  offline  
 * @attribute  schema  
 * @attribute  init  
 * @attribute  saveoriginal  
 * @define instance 
 * @attribute  src  
 * @define load 
 * @attribute  get  
 * @define submission 
 * @attribute  ref  
 * @attribute  bind  
 * @attribute  action  
 * @attribute  method  
 * @attribute  set  
 * @define offline place holder element, not functional yet
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.8
 */
jpf.Model = function(data, caching){
	jpf.register(this, "model", NOGUI_NODE);/** @inherits jpf.Class */
	
	this.data = data;
	this.caching = caching;
	this.cache = {};
	
	this.saveOriginal = true;
	
	jpf.status("Creating Model");
	
	this.loadInJmlNode = function(jmlNode, xpath){
		if(this.data && xpath){
			if(!jpf.supportNamespaces && (this.data.prefix || this.data.scopeName))
				(this.data.nodeType == 9 ? this.data : this.data.ownerDocument).setProperty("SelectionNamespaces", "xmlns:" + (this.data.prefix || this.data.scopeName) + "='" + this.data.namespaceURI + "'");
			
			var xmlNode = this.data.selectSingleNode(xpath);
			if(!xmlNode) jmlNode.listenRoot = jpf.XMLDatabase.addNodeListener(this.data, jmlNode);
		}
		else xmlNode = this.data || null;
		
		jmlNode.load(xmlNode);
	}
	
	var jmlNodes = {};
	/**
	 * Registers a JmlNode to this model in order for the JmlNode to receive data 
	 * loaded in this model.
	 *
	 * @param  {JMLNode}  jmlNode  required  The JmlNode to be registered.
	 * @param  {String}  xpath   optional  String specifying an xpath query which is executed on the data of the model to select the node to be loaded in the <code>jmlNode</code>.
	 * @return  {Model}  this model
	 */
	this.register = function(jmlNode, xpath){
		if(!jmlNode) return this;
		jmlNodes[jmlNode.uniqueId] = [jmlNode, xpath];
		jmlNode.model = this;
		//if(!jmlNode.smartBinding) return this; //Setting model too soon causes object not to have XMLRoot which is incorrect
		
		if(this.connect){
			//This model is a connect proxy
			if(this.connect.type) this.connect.node.connect(jmlNode, null, this.connect.select, this.connect.type);
			else this.connect.node.connect(jmlNode, true, this.connect.select);
		}
		else{
			jmlNode.model = this;
			if(this.data) this.loadInJmlNode(jmlNode, xpath);
		}
		
		return this;
	}
	
	/**
	 * Removes a JmlNode from the group of registered JmlNodes.
	 * The JmlNode will not receive any updates from this model, however the data loaded
	 * in the JmlNode component is not unloaded.
	 *
	 * @param  {JMLNode}  jmlNode  required  The JmlNode to be unregistered.
	 */
	this.unregister = function(jmlNode){
		if(this.connect)
			this.connect.node.disconnect(jmlNode);
		
		delete jmlNodes[jmlNode.uniqueId]
	}
	
	this.getXpathByJmlNode = function(jmlNode){
		var n = jmlNodes[jmlNode.uniqueId];
		if(!n) return false;
		return n[1];	
	}
	
	/**
	 * @copy   JmlNode#setValue
	 */
	this.toString = function(){
		return this.data ? jpf.formatXML(jpf.XMLDatabase.clearConnections(this.data.cloneNode(true)).xml) : "Model has no data.";
	}
	
	/**
	 * Gets a copy of current state of the XML of this model.
	 *
	 * @return  {XMLNode}  context of this model
	 */
	this.getXml = function(){
		return this.data ? jpf.XMLDatabase.clearConnections(this.data.cloneNode(true)) : false;
	}
	
	/**
	 * Sets a value of an XMLNode based on a xpath statement executed on the data of this model.
	 * 
	 * @param  {String}  xpath  required  String specifying the xpath used to select a XMLNode.
	 * @param  {String}  value  required  String specifying the value to set.
	 * @return  {XMLNode}  the changed XMLNode
	 */
	this.setByXPath = function( xpath, value ){
		var node = this.data.selectSingleNode(xpath); if(!node)return null;
		jpf.XMLDatabase.setTextNode(node,value);
		return node;
	}
	
	/**
	 * Gets the value of an XMLNode based on a xpath statement executed on the data of this model.
	 * 
	 * @param  {String}  xpath  required  String specifying the xpath used to select a XMLNode.
	 * @return  {String}  value of the XMLNode
	 */
	this.getByXPath = function (xpath ){
		return jpf.getXmlValue(this.data, xpath );
	}
	
	/**
	 * Executes an xpath statement on the data of this model
	 * 
	 * @param  {String}  xpath   required  String specifying the xpath used to select the XMLNode(s).
	 * @param  {Boolean}  single  optional  When set to true a maximum of 1 nodes is returned.
	 * @return  {variant}  XMLNode or NodeList with the result of the selection
	 */
	this.getNodeByXPath = function(xpath, single){
		return single ? this.data.selectSingleNode(xpath) : this.data.selectNodes(xpath);
	}
	
	this.getBindNode = function(bindId){
		var bindObj = jpf.NameServer.get("bind", bindId);
		
		if(!bindObj) throw new Error(0, jpf.formErrorString(0, this, "Binding Component", "Could not find bind element with name '" + x.getAttribute("bind") + "'"));
		
		return bindObj;
	}
	
	this.isValid = function(){
		//Loop throug bind nodes and process their rules.
		for(var bindNode, i=0;i<bindValidation.length;i++){
			bindNode = bindValidation[i];
			if(!bindNode.isValid()){
				//Not valid
				
				return false;
			}
		}
		
		//Valid
		return true;
	}
	
	this.getInstanceDocument = function(instanceName){
		return this.data;
	}
	
	var XEvents = {
		"xforms-submit" : function(){
			this.submit();
			return false;
		},
		"xforms-reset" : function(model){
			this.reset();
			return false;
		},
		"xforms-revalidate" : function(model){
			this.revalidate(); 
		}
	}
	this.dispatchXFormsEvent = function(name, model, noEvent){
		if(XEvents[name] && XEvents[name].call(this, model) !== false && !noEvent) 
			this.dispatchEvent.apply(this, name);
	}
	
	this.rebuild = function(){
		
	}
	
	this.recalculate = function(){
		
	}
	
	this.revalidate = function(){
		if(this.isValid()){
			this.dispatchEvent("xforms-valid"); //Is this OK, or should this be called on a element
		}
		else{
			this.dispatchEvent("xforms-invalid"); //Is this OK, or should this be called on a element
		}
	}
	
	this.refresh = function(){
		
	}

	this.clear = function(){
		this.load(null);
	}
	
	/**
	 * Resets data in this model to the last saved point.
	 * 
	 */
	this.reset = function(){
		this.load(this.copy);
		
		this.dispatchEvent("xforms-reset");
		
		//These should do something, that is now implied
		this.dispatchEvent("xforms-recalculate");
		this.dispatchEvent("xforms-revalidate");
		this.dispatchEvent("xforms-refresh");
	}

	/**
	 * Sets a new save point based on the current state of the data in this model.
	 * 
	 */
	this.savePoint = function(){
		this.copy = this.data.cloneNode(true);
	}
	
	this.reloadJmlNode = function(uniqueId){
		if(!this.data) return;
		var xmlNode = jmlNodes[uniqueId][1] ? this.data.selectSingleNode(jmlNodes[uniqueId][1]) : this.data;
		jmlNodes[uniqueId][0].load(xmlNode);
	}
	
	/* *********** PARSE ***********/
	
	/*
		<j:model
			+ [id=""]
			+ [load="rpc:"]
			+ [submission="eval:"]
			+ [session="cookie:"]
			[offline="gears:name"]
			[schema="MySchema.xsd"]
			+ [init="false"]
			+ [save-original="boolean"]
		>
			+ <j:instance>
			+ 	<data />
			+ </j:instance>
			+ <j:instance src="" />
			+ <j:load get="" />
			+ <j:submission id="" ref="/" bind="" action="url" method="post|get|urlencoded-post" set="" />
			<j:offline [name=""] protocol="file" type="gears" />
		</j:model>
	*/
	
	var model = this;
	function cSubmission(x){
		this.tagName = "submission";
		this.name = x.getAttribute("id");
		this.parentNode = model;
		
		this.getModel = function(){return model;}
		
		jpf.makeClass(this);
		this.inherit(jpf.XForms); /** @inherits jpf.XForms */
		
		this.inherit(jpf.JmlDomAPI); /** @inherits jpf.JmlDomAPI */
	}
	function cBind(x){
		this.tagName = "bind";
		this.name = x.getAttribute("id");
		this.parentNode = this;
		this.nodeset = x.getAttribute("nodeset");
		this.type = x.getAttribute("type");
		this.jml = x;
		
		this.selectSingleNode = function(){
			return this.parentNode.data.selectSingleNode(this.nodeset);
		}
		
		this.selectNodes = function(){
			return this.parentNode.data.selectNodes(this.nodeset);
		}
		
		this.isValid = function(){
			var value, nodes = this.selectNodes();
			
			if(!typeHandlers[this.type]){
				throw new Error(0, jpf.formErrorString(0, this, "Validating based on a bind node", "Could not find type: " + this.type, x));
			}
			
			for(var i=0;i<nodes.length;i++){
				if(nodes[i].childNodes > 1) continue; //The association is ignored since the element contains child elements.
				if(!jpf.XSDParser.checkType(this.type, nodes[i])) return false;
			}
			
			return true;
		}
		
		jpf.makeClass(this);
		
		this.inherit(jpf.JmlDomAPI); /** @inherits jpf.JmlDomAPI */
	}

	var bindValidation = [], defSubmission, submissions = {}, loadProcInstr;
	this.loadJML = function(x){
		this.name = x.getAttribute("id");
		this.jml = x;
		
		//Events
		var attr = x.attributes;
		for(var i=0;i<attr.length;i++){
			if(attr[i].nodeName.substr(0,2) == "on") this.addEventListener(attr[i].nodeName, new Function(attr[i].nodeValue));
		}
		
		this.dispatchEvent("xforms-model-construct");
		 
		if(x.getAttribute("save-original") == "true") this.saveOriginal = true;
		
		//Parse submissions
		var oSub, subs = $xmlns(x, "submission", jpf.ns.jpf);
		for(var i=0;i<subs.length;i++){
			if(!subs[i].getAttribute("id")){
				if(!defSubmission) defSubmission = subs[i];
				continue;
			}
			
			submissions[subs[i].getAttribute("id")] = subs[i];
			oSub = jpf.setReference(subs[i].getAttribute("id"), new cSubmission(subs[i]));
		}
		if(!defSubmission) defSubmission = x.getAttribute("submission"); //Javeline Extension on XForms
		
		this.submitType = x.getAttribute("submittype");
		this.useComponents = x.getAttribute("useComponents");
		
		//Session support
		this.session = x.getAttribute("session");
		
		//Find load string
		var instanceNode; loadProcInstr = x.getAttribute("load") || x.getAttribute("get");
		if(!loadProcInstr){
			var prefix = jpf.findPrefix(x, jpf.ns.jpf);
			if(!jpf.supportNamespaces)
				if(prefix) (x.nodeType == 9 ? x : x.ownerDocument).setProperty("SelectionNamespaces", "xmlns:" + prefix + "='" + jpf.ns.jpf + "'");	
			if(prefix) prefix += ":";
			
			var loadNode = x.selectSingleNode(prefix + "load");//$xmlns(x, "load", jpf.ns.jpf)[0];
			if(loadNode) loadProcInstr = loadNode.getAttribute("get");
			else{
				instanceNode = $xmlns(x, "instance", jpf.ns.jpf)[0];
				if(instanceNode && instanceNode.getAttribute("src")) loadProcInstr = "url:" + instanceNode.getAttribute("src");
			}
		}
		
		//Process bind nodes
		var binds = $xmlns(x, "bind", jpf.ns.jpf);
		for(var i=0;i<binds.length;i++){
			bindValidation.push([binds[i].getAttribute("nodeset"), binds[i]]);
			if(binds[i].getAttribute("id")) jpf.NameServer.register("bind", binds[i].getAttribute("id"), new cBind(binds[i]));
			
		}
		
		//Load literal model
		if(!oSub && !loadProcInstr){
			var xmlNode = instanceNode || x;
			if(xmlNode.childNodes.length)
				this.load((xmlNode.xml || xmlNode.serialize()).replace(new RegExp("^<" + xmlNode.tagName + "[^>]*>"), "").replace(new RegExp("<\/\s*" + xmlNode.tagName + "[^>]*>$"), "").replace(/xmlns=\"[^"]*\"/g, ""));
		}
		
		//Default data for XForms models without an instance but with a submission node
		if(oSub && !this.data && !instanceNode) this.load("<xforms />");	
		
		//Load data into model if allowed
		if(!jpf.isFalse(x.getAttribute("init"))) this.init();
		
		this.dispatchEvent("xforms-model-construct-done");
		
		return this;
	}
	
	/**
	 * Changes the JmlNode that provides data to this model.
	 * Only relevant for models that are a connect proxy.
	 * A connect proxy is set up like this:
	 * <j:model connect="component_name" type="select" select="xpath" />
	 *
	 * @param  {JMLNode}  jmlNode  required  The JmlNode to be registered.
	 * @param  {String}  type   optional  select  default  sents data when a node is selected
	 *                                     choice  sents data when a node is chosen (by double clicking, or pressing enter)
	 * @param  {String}  select   optional  String specifying an xpath query which is executed on the data of the model to select the node to be loaded in the <code>jmlNode</code>.
	 */
	//Only when model is a connect proxy
	this.setConnection = function(jmlNode, type, select){
		if(!this.connect) this.connect = {};
		var oldNode = this.connect.node;
		
		this.connect.type = type;
		this.connect.node = jmlNode;
		this.connect.select = select;
		
		for(var uniqueId in jmlNodes){
			if(oldNode) oldNode.disconnect(jmlNodes[uniqueId][0]);
			this.register(jmlNodes[uniqueId][0]);
		}
	}
	
	this.init = function(){
		if(this.session){
			this.loadFrom(this.session, null, true);
		}
		else if(loadProcInstr){
			this.loadFrom(loadProcInstr);
			//loadProcInstr = null;
		}
		
		this.dispatchEvent("xforms-ready");
	}
	
	/* *********** LOADING ****************/
	
	var oModel = this; //PROCINSTR
	this.loadFrom = function(instruction, xmlContext, isSession){
		var data = instruction.split(":");
		var instrType = data.shift();
		
		//Loading data in non-literal model
		if(instrType.match(/^(?:url|url.post|rpc|call|eval|cookie|gears)$/)){
			this.dispatchEvent("onbeforecomm");

			jpf.getData(instruction, xmlContext, function(xmlData, state, extra){
				oModel.dispatchEvent("onaftercomm");
				
				if(state != __HTTP_SUCCESS__){
					if(state == __HTTP_TIMEOUT__ && extra.retries < jpf.maxHttpRetries) return extra.tpModule.retry(extra.id);
					else{
						var commError = new Error(1032, jpf.formErrorString(1032, oModel, "Loading xml data", "Could not insert data using RPC for control " + oModel.name + "[" + oModel.tagName + "] \nUrl: " + extra.url + "\nInfo: " + extra.message + "\n\n" + xmlData));
						if(oModel.dispatchEvent("onerror", jpf.extend({error : commError, state : status}, extra)) !== false)
							throw commError;
						return;
					}
				}
				
				if(isSession && !xmlData){
					if(loadProcInstr) return oModel.loadFrom(loadProcInstr);
				}
				else{
					oModel.load(xmlData);
					oModel.dispatchEvent("onreceive", {xmlNode : xmlData});
				}
			});
		}
		
		//Make connectiong with a jml element to get data streamed in from existing client side source
		else if(instrType.substr(0,1) == "#"){
			instrType = instrType.substr(1);

			try{eval(instrType).test}catch(e){
				throw new Error(1031, jpf.formErrorString(1031, null, "Model Creation", "Could not find object reference to connect databinding: '" + instrType + "'", dataNode))
			}

			this.setConnection(eval(instrType), data[0], data[1]);
			/*this.connect = {
				node : eval(instrType),
				type : data[1],
				select : data[2]
			};*/
		}
		
		return this;
	}
	
	/**
	 * Loads data in this model
	 * 
	 * @param  {XMLNode}  xmlNode  optional  The XML data node to load in this model. Null will clear the data from this model.
	 * @param  {Boolean}  nocopy  optional  When set to true the data loaded will not overwrite the reset point.
	 */
	this.load = function(xmlNode, nocopy){
		if(this.dispatchEvent("onbeforeload") === false) return false;
		
		if(typeof xmlNode == "string")
			var xmlNode = jpf.getObject("XMLDOM", xmlNode).documentElement;
		
		//FU IE
		//if(jpf.isIE) xmlNode.ownerDocument.setProperty("SelectionNamespaces", "xmlns:j='http://www.javeline.com/2001/PlatForm'");
		
		if(xmlNode){
			jpf.XMLDatabase.nodeConnect(jpf.XMLDatabase.getXmlDocId(xmlNode, this), xmlNode, null, this);
			if(!nocopy && this.saveOriginal) this.copy = xmlNode.cloneNode(true);
		}
		this.data = xmlNode;
		
		var uniqueId;
		for(uniqueId in jmlNodes){
			if(!jmlNodes[uniqueId] || !jmlNodes[uniqueId][0]) continue;

			this.loadInJmlNode(jmlNodes[uniqueId][0], jmlNodes[uniqueId][1]);
			//var xmlNode = this.data ? (jmlNodes[uniqueId][1] ? this.data.selectSingleNode(jmlNodes[uniqueId][1]) : this.data) : null;
			//jmlNodes[uniqueId][0].load(xmlNode);
		}
		
		this.dispatchEvent("onafterload");
		
		return this;
	}
	
	/* *********** INSERT ****************/
	
	//PROCINSTR
	//this.extend = function(rule, jmlNode, loadNode){
	this.insertFrom = function(instruction, xmlContext, insertPoint, jmlNode, extra_callback){
		if(!instruction) return false;
		
		this.dispatchEvent("onbeforecomm");
		
		return jpf.getData(instruction, xmlContext, function(xmlData, state, extra){
			oModel.dispatchEvent("onaftercomm");
			
			if(state != __HTTP_SUCCESS__){
				if(state == __HTTP_TIMEOUT__ && extra.retries < jpf.maxHttpRetries) return extra.tpModule.retry(extra.id);
				else{
					var commError = new Error(1032, jpf.formErrorString(1032, null, "Inserting xml data", "Could not insert data for control " + this.name + "[" + this.tagName + "] \nInstruction:" + instruction + "\nUrl: " + extra.url + "\nInfo: " + extra.message + "\n\n" + xmlData));
					if((jmlNode || oModel).dispatchEvent("onerror", jpf.extend({error : commError, state : status}, extra)) !== false)
						throw commError;
					return;
				}
			}
			
			//Checking for xpath
			if(typeof insertPoint == "string") insertPoint = oModel.data.selectSingleNode(insertPoint);
			
			if(!insertPoint) throw new Error(0, jpf.formErrorString(0, jmlNode || oModel, "Inserting data", "Could not determine insertion point for instruction: " + instruction));
			
			(jmlNode || oModel).insert(xmlData, insertPoint, jpf.isTrue(extra.userdata[1]));
			if(extra_callback) extra_callback(xmlData);
		});
	}
	
	/**
	 * Inserts data in this model as a child of the currently loaded data.
	 * 
	 * @param  {XMLNode}  XMLRoot  required  The XML data node to insert in this model. 
	 * @param  {Boolean}  parent  optional  XMLNode where the loaded data will be appended on.
	 */
	this.insert = function(XMLRoot, parentXMLNode, clearContents, jmlNode){
		if(typeof XMLRoot != "object") XMLRoot = jpf.getObject("XMLDOM", XMLRoot).documentElement;
		if(!parentXMLNode) parentXMLNode = this.data;
		
		if(clearContents){
			//clean parent
			var nodes = parentXMLNode.childNodes;
			for(var i=nodes.length-1;i>=0;i--) parentXMLNode.removeChild(nodes[i]);
		}
				
		//if(this.dispatchEvent("onbeforeinsert", parentXMLNode) === false) return false;
		
		//Integrate XMLTree with parentNode
		var newNode = jpf.XMLDatabase.integrate(XMLRoot, parentXMLNode, true);

		//Call __XMLUpdate on all listeners
		jpf.XMLDatabase.applyChanges("insert", parentXMLNode);
		
		//this.dispatchEvent("onafterinsert");
		
		return XMLRoot;
	}
	
	/* *********** SUBMISSION ****************/
	
	//Json
	//@todo rewrite this function
	this.getJsonObject = function(){
		var data = {};
		
		for(var p in this.elements){
			var name = this.elements[p].jml.getAttribute("name") || this.elements[p].name;
			if(name) data[name] = this.elements[p].getValue();
		}
		
		return data;
	}
	
	//URL encoded
	this.getCgiString = function(){
		//use components
		var uniqueId, k, sel, oJmlNode, name, value, str = [];
		
		for(uniqueId in jmlNodes){
			oJmlNode = jmlNodes[uniqueId][0];
			//if(!elements[i].active) continue;
			if(oJmlNode.disabled || !oJmlNode.change && !oJmlNode.hasFeature(__MULTISELECT__)) continue;
			if(oJmlNode.tagName == "MultiBinding") oJmlNode = oJmlNode.getHost();
			
			if(oJmlNode.multiselect){
				sel = oJmlNode.getSelection();
				for(k=0;k<sel.length;k++){
					name = oJmlNode.jml.getAttribute("name");//oJmlNode.jml.getAttribute("id")
					if(!name && oJmlNode.jml.getAttribute("ref")) name = oJmlNode.jml.getAttribute("ref").replace(/[\/\]\[@]/g, "_");
					if(!name) name = sel[k].tagName;
					if(!name.match(/\]$/)) name += "[]";
					
					value = oJmlNode.applyRuleSetOnNode("value", sel[k]) || oJmlNode.applyRuleSetOnNode("caption", sel[k]);
					if(value) str.push(name + "=" + encodeURIComponent(value));
				}
			}
			else{
				name = oJmlNode.jml.getAttribute("name") || oJmlNode.jml.getAttribute("id");
				if(!name && oJmlNode.jml.getAttribute("ref")) name = oJmlNode.jml.getAttribute("ref").replace(/[\/\]\[@]/g, "_");
				if(!name && oJmlNode.XMLRoot) name = oJmlNode.XMLRoot.tagName;
				
				if(!name) continue;
				
				value = oJmlNode.getValue();//oJmlNode.applyRuleSetOnNode(oJmlNode.mainBind, oJmlNode.XMLRoot);
				if(value) str.push(name + "=" + encodeURIComponent(value));
			}
		}
		
		return str.join("&");
	}

	/*
		<j:teleport>
			<j:RPC id="saveSettings" protocol="GEARS" type="file" />
		</j:teleport>
		
		offline="gears:name:value"
		offline:gears:name:value
		offline:cookie:name:value
		offline:air:name:value
		offline:deskrun:name:value
		offline:prism:name:value
		offline:flash:name:value
		
		URI scheme method Serialization Submission 
		http https mailto "post" application/xml HTTP POST or equivalent 
		http https file 	"get" application/x-www-form-urlencoded HTTP GET or equivalent 
		http https file 	"put" application/xml HTTP PUT or equivalent 
		http https mailto "multipart-post" multipart/related HTTP POST or equivalent 
		http https mailto "form-data-post" multipart/form-data HTTP POST or equivalent 
		http https mailto "urlencoded-post" (Deprecated) application/x-www-form-urlencoded HTTP POST or equivalent 
		(any) 				any other QNAME with no prefix N/A N/A 
		(any) 				any QNAME with a prefix implementation-defined implementation-defined 

	*/
	//PROCINSTR
	//@todo: PUT ??
	//@todo: build in instruction support
	this.submit = function(instruction, type, useComponents, xSelectSubTree){
		if(!this.isValid()){
			this.dispatchEvent("xforms-submit-error");
			this.dispatchEvent("onsubmiterror");
			return;
		}
		
		if(!instruction && !defSubmission) return false;
		if(!instruction && typeof defSubmission == "string") instruction = defSubmission;
		
		//First check if instruction is a known submission
		var sub;
		if(submissions[instruction] || !instruction && defSubmission){
			sub = submissions[instruction] || defSubmission;
			
			//<j:submission id="" ref="/" bind="" action="url" method="post|get|urlencoded-post" set="" />
			var useComponents = false;
			var type = sub.getAttribute("method").match(/^(?:urlencoded-post|get)$/) ? "native" : "xml";
			var xSelectSubTree = sub.getAttribute("ref") || "/";//Bind support will come later
			var instruction = (sub.getAttribute("method").match(/post/) ? "url.post:" : "url:") + sub.getAttribute("action");
			var file = sub.getAttribute("action");
			
			//set contenttype oRpc.contentType
		}
		else if(instruction){
			if(!type) type = this.submitType;
			if(!useComponents) useComponents = this.useComponents;
		}
		else{
			throw new Error(0, jpf.formErrorString(0, "Submitting a Model", "Could not find a submission with id '" + id + "'"));
		}
		
		//if(type == "xml" || type == "post") 
		//	throw new Error(0, jpf.formErrorString(0, this, "Submitting form", "This form has no model specified", this.jml));

		if(this.dispatchEvent("onbeforesubmit", {instruction : instruction}) === false) return false;
		
		this.dispatchEvent("xforms-submit");
		
		//this.showLoader();
		
		var model = this;
		function cbFunc(data, state, extra){
			if(state == __HTTP_TIMEOUT__ && extra.retries < jpf.maxHttpRetries) return extra.tpModule.retry(extra.id);
			else if(state != __RPC_SUCCESS__){
				model.dispatchEvent("onsubmiterror", extra);
				
				/* For an error response nothing in the document is replaced, and submit processing concludes after dispatching xforms-submit-error.*/
				model.dispatchEvent("xforms-submit-error");
			}
			else{
				model.dispatchEvent("onsubmitsuccess", jpf.extend({data : data}, extra));
				
				if(sub){
					/* For a success response including a body, when the value of the replace attribute on element submission is "all", the event xforms-submit-done is dispatched, and submit processing concludes with entire containing document being replaced with the returned body.*/
					if(sub.getAttribute("replace") == "all"){
						document.body.innerHTML = data; //Should just unload all elements and parse the new document.
						model.dispatchEvent("xforms-submit-done");
					}
					/*	For a success response including a body, when the value of the replace attribute on element submission is "none", submit processing concludes after dispatching xforms-submit-done.
						For a success response not including a body, submit processing concludes after dispatching xforms-submit-done.
					*/
					else if(sub.getAttribute("replace") == "none"){
						model.dispatchEvent("xforms-submit-done");
					}
					else{
						/* For a success response including a body of an XML media type (as defined by the content type specifiers in [RFC 3023]), when the value of the replace attribute on element submission is "instance", the response is parsed as XML. An xforms-link-exception (4.5.2 The xforms-link-exception Event) occurs if the parse fails. If the parse succeeds, then all of the internal instance data of the instance indicated by the instance attribute setting is replaced with the result. Once the XML instance data has been replaced, the rebuild, recalculate, revalidate and refresh operations are performed on the model, without dispatching events to invoke those four operations. This sequence of operations affects the deferred update behavior by clearing the deferred update flags associated with the operations performed. Submit processing then concludes after dispatching xforms-submit-done.*/
						if((extra.http.getResponseHeader("Content-Type") || "").indexOf("xml") > -1){
							if(sub.getAttribute("replace") == "instance"){
								try{
									var xml = XMLDatabase.getXml(xml);
									this.load(xml);
									model.dispatchEvent("xforms-submit-done");
								}
								catch(e){
									model.dispatchEvent("xforms-link-exception"); //Invalid XML sent
								}
							}
						}
						else{
							/* For a success response including a body of a non-XML media type (i.e. with a content type not matching any of the specifiers in [RFC 3023]), when the value of the replace attribute on element submission is "instance", nothing in the document is replaced and submit processing concludes after dispatching xforms-submit-error.*/
							if(sub.getAttribute("replace") == "instance"){
								model.dispatchEvent("xforms-submit-error");
							}
							else{
								model.dispatchEvent("xforms-submit-done");
							}
						}
					}
				}
			}
			
			//this.hideLoader();
		}
		
		if(type == "array" || type == "xml"){
			var data = type == "array"  ? this.getJsonObject() : jpf.XMLDatabase.serializeNode(this.data);
			jpf.saveData(instruction, this.data, cbFunc, null, null, [data]);
		}
		else if(type == "native"){
			var data = useComponents ? this.getCgiString() : jpf.XMLDatabase.convertXml(this.getXml(), "cgivars");
			
			if(instruction.match(/^rpc\:/)){
				rpc = rpc.split(".");
				var oRpc = self[rpc[0]];
				oRpc.callWithString(rpc[1], data, cbFunc);
				
				//Loop throught vars
				
				//Find components with the same name
				
				//Set arguments and call method
				
			}
			else{
				if(instruction.match(/^url/))
					instruction += (instruction.match(/\?/) ? "&" : "?") + data;
				
				jpf.saveData(instruction, this.data, cbFunc);
			}
		}
		
		this.dispatchEvent("onaftersubmit")
	}
	
	/* ******* DESTROY ***********/

	this.destroy = function(){
		if(this.session && this.data)
			jpf.saveData(this.session, this.getXml());
	}
}


/*FILEHEAD(/in/Core/Application/Scrollbar.js)SIZE(7055)TIME(1203730484247)*/

/**
 * @constructor
 * @private
 */
jpf.Scrollbar = function(){
	var SCROLLVALUE = 0;
	var STEPVALUE = 0.03;
	var BIGSTEPVALUE = 0.1;
	var CURVALUE = 0;
	var TIMER = null;
	var SCROLLWAIT;
	var SLIDEMAXHEIGHT;
	
	var offsetName = jpf.isIE ? "offset" : "layer";
	
	//Init Class
	var uniqueId = this.uniqueId = jpf.all.push(this) - 1;
	jpf.makeClass(this);
	
	//Init Skin
	this.inherit(jpf.Presentation); /** @inherits jpf.Presentation */
	if(this.loadSkin) this.loadSkin("default:jpf.Scrollbar");
	
	//Init DragDrop mode
	jpf.DragMode.defineMode("scrollbar" + this.uniqueId, this);
	
	//Build Skin
	this.__getNewContext("Main");
	this.oExt = jpf.XMLDatabase.htmlImport(this.__getLayoutNode("Main"), document.body);
	this.oExt.host = this;
	this.oExt.style.display = "none";
	
	var MAIN = this.oExt;
	var INDICATOR = this.__getLayoutNode("Main", "indicator", this.oExt);
	var SLIDEFAST = this.__getLayoutNode("Main", "slidefast", this.oExt);
	var BTNUP = BTN = this.__getLayoutNode("Main", "btnup", this.oExt)
	var BTNDOWN = this.__getLayoutNode("Main", "btndown", this.oExt);
	var STARTPOS = false;
	var TIMER;
	
	INDICATOR.ondragstart = function(){return false}
	
	//document.getElementById('btnup').ondblclick = 
	BTNUP.onmousedown = function(e){
		if(!e) e = event;
		this.className = "btnup btnupdown";
		clearTimeout(TIMER);
		
		CURVALUE -= STEPVALUE;
		setScroll();
		e.cancelBubble = true;
		
		TIMER = setTimeout(function(){
			TIMER = setInterval(function(){
				CURVALUE -= STEPVALUE;
				jpf.lookup(uniqueId).setScroll();
			}, 20);
		}, 300);
	}
	
	//document.getElementById('btndown').ondblclick = 
	BTNDOWN.onmousedown = function(e){
		if(!e) e = event;
		this.className = "btndown btndowndown";
		clearTimeout(TIMER);

		CURVALUE += STEPVALUE;
		setScroll();
		e.cancelBubble = true;
		
		TIMER = setTimeout(function(){
			TIMER = setInterval(function(){
				CURVALUE += STEPVALUE;
				jpf.lookup(uniqueId).setScroll();
			}, 20);
		}, 300);
	}
	
	BTNUP.onmouseout = 
	BTNUP.onmouseup = function(){
		this.className = "btnup";
		clearInterval(TIMER);
	}
	
	BTNDOWN.onmouseout = 
	BTNDOWN.onmouseup = function(){
		this.className = "btndown";
		clearInterval(TIMER);
	}
	
	INDICATOR.onmousedown = function(e){
		if(!e) e = event;
		STARTPOS = [e[offsetName + "X"], e[offsetName + "Y"] + BTN.offsetHeight];
		
		jpf.DragMode.setMode("scrollbar" + uniqueId);
		
		e.cancelBubble = true;
		return false;
	}
	
	MAIN.onmousedown = function(e){
		if(!e) e = event;
		clearInterval(TIMER);

		if(e[offsetName + "Y"] > INDICATOR.offsetTop + INDICATOR.offsetHeight){
			CURVALUE += BIGSTEPVALUE;
			setScroll();
			
			SLIDEFAST.style.display = "block";
			SLIDEFAST.style.top = (INDICATOR.offsetTop + INDICATOR.offsetHeight) + "px";
			SLIDEFAST.style.height = (MAIN.offsetHeight - SLIDEFAST.offsetTop - BTN.offsetHeight) + "px";
			
			var offset = e[offsetName + "Y"];
			TIMER = setTimeout(function(){
				TIMER = setInterval(function(){
					jpf.lookup(uniqueId).scrollDown(offset);
				}, 20);
			}, 300);
		}
		else if(e[offsetName + "Y"] < INDICATOR.offsetTop){
			CURVALUE -= BIGSTEPVALUE;
			setScroll();
			
			SLIDEFAST.style.display = "block";
			SLIDEFAST.style.top = BTN.offsetHeight + "px";
			SLIDEFAST.style.height = (INDICATOR.offsetTop - BTN.offsetHeight) + "px";
			
			var offset = e[offsetName + "Y"];
			TIMER = setTimeout(function(){
				TIMER = setInterval(function(){
					jpf.lookup(uniqueId).scrollUp(offset);
				}, 20);
			}, 300);
		}
	}
	
	MAIN.onmouseup = function(){
		clearInterval(TIMER);
		SLIDEFAST.style.display = "none";
	}
	
	this.onmousemove = function(e){
		if(!e) e = event;
		//if(e.button != 1) return this.onmouseup();
		if(!STARTPOS) return false;
		
		var next = BTN.offsetHeight + (e.clientY - STARTPOS[1] - jpf.compat.getAbsolutePosition(MAIN)[1] - BTN.offsetHeight/3);
		var min = BTN.offsetHeight;
		if(next < min) next = min;
		var max = (MAIN.offsetHeight - (BTN.offsetHeight) - INDICATOR.offsetHeight);
		if(next > max) next = max;
		//INDICATOR.style.top = next + "px"
		
		CURVALUE = (next-min) / (max - min);
		setTimeout(function(){setScroll(true);});
	}
	
	this.onmouseup = function(){
		STARTPOS = false;
		jpf.DragMode.clear();
	}
	
	var LIST, onscroll, viewheight, scrollheight;
	this.attach = function(o, v, s, scroll_func){
		LIST = o;
		onscroll = scroll_func;
		viewheight = v;
		scrollheight = s;
		
		o.parentNode.appendChild(this.oExt);
		this.oExt.style.display = "block";
		
		this.oExt.style.left = "166px";//(o.offsetLeft + o.offsetWidth) + "px";
		this.oExt.style.top = "24px";//o.offsetTop + "px";
		this.oExt.style.height = "160px";//o.offsetHeight + "px";
		
		LIST.onmousewheel = function(e){
			if(!e) e = event;
			CURVALUE += ((jpf.isOpera ? 1 : -1) * (e.wheelDelta/120) * STEPVALUE);
			setScroll(true);
		}
		
		SCROLLWAIT = 0;//(LIST.len * COLS)/2;
		SLIDEMAXHEIGHT = MAIN.offsetHeight - BTNDOWN.offsetHeight - BTNUP.offsetHeight;
		STEPVALUE = (viewheight/scrollheight)/5;
		BIGSTEPVALUE = STEPVALUE * 3;
		
		INDICATOR.style.height = Math.max(5, ((viewheight/scrollheight) * SLIDEMAXHEIGHT)) + "px";
		if(INDICATOR.offsetHeight-4 == SLIDEMAXHEIGHT) MAIN.style.display = "none";
	}
	
	function onscroll(timed, perc){
		LIST.scrollTop = (LIST.scrollHeight-LIST.offsetHeight+4) * CURVALUE;
		/*var now = new Date().getTime();
		if(timed && now - LIST.last < (timed ? SCROLLWAIT : 0)) return;
		LIST.last = now;
		
		var value = parseInt((DATA.length-LIST.len+1) * CURVALUE);
		showData(value);*/
	}
	
	var jmlNode = this;
	function setScroll(timed, no_event){
		if(CURVALUE > 1) CURVALUE = 1;
		if(CURVALUE < 0) CURVALUE = 0;
		INDICATOR.style.top = (BTN.offsetHeight + (MAIN.offsetHeight - (BTN.offsetHeight*2) - INDICATOR.offsetHeight) * CURVALUE) + "px";
		
		//status = CURVALUE;
		jmlNode.pos = CURVALUE;//(INDICATOR.offsetTop-BTNUP.offsetHeight)/(SLIDEMAXHEIGHT-INDICATOR.offsetHeight);
		if(!no_event) onscroll(timed, jmlNode.pos);
	}
	this.setScroll = setScroll;
	
	function scrollUp(v){
		if(v > INDICATOR.offsetTop) return MAIN.onmouseup();
		CURVALUE -= BIGSTEPVALUE;setScroll();
		
		SLIDEFAST.style.height = Math.max(1, INDICATOR.offsetTop - BTN.offsetHeight) + "px";
		SLIDEFAST.style.top = BTN.offsetHeight + "px";
	}
	this.scrollUp = scrollUp;
	
	function scrollDown(v){
		if(v < INDICATOR.offsetTop + INDICATOR.offsetHeight) return MAIN.onmouseup();
		CURVALUE += BIGSTEPVALUE;setScroll();
		
		SLIDEFAST.style.top = (INDICATOR.offsetTop + INDICATOR.offsetHeight) + "px";
		SLIDEFAST.style.height = Math.max(1, MAIN.offsetHeight - SLIDEFAST.offsetTop - BTN.offsetHeight) + "px";
	}
	this.scrollDown = scrollDown;
	
	this.getPosition = function(){
		return this.pos;
	}
	
	this.setPosition = function(pos, no_event){
		CURVALUE = pos;
		setScroll(null, no_event);
	}
}

/*FILEHEAD(/in/Core/Application/SmartBinding.js)SIZE(8343)TIME(1203730484247)*/

jpf.NameServer = {
	lookup : {},
	add : function(type, xmlNode){
		if(!lookup[type]) lookup[type] = [];
		return lookup[type].push(xmlNode) - 1;
	},
	register : function(type, id, xmlNode){
		if(!this.lookup[type]) this.lookup[type] = {};
		this.lookup[type][id] = xmlNode;
		
		return xmlNode;
	},
	get : function(type, id){
		return this.lookup[type] ? this.lookup[type][id] : null;
	},
	getAll : function(type){
		var name, arr = [];
		for(name in this.lookup[type]){
			arr.push(this.lookup[type][name]);
		}
		return arr;
	}
}

/**
 * Class SmartBinding represents a connection between a component and data.
 * The SmartBinding presents a way of translating data into representation and back.
 * It offers the possibility to synchronize a second data set on a remote location (server).
 * A SmartBinding also offers the ability to specify rules for drag&drop data handling.
 *
 * @classDescription		This class creates a new smartbinding
 * @return {SmartBinding} Returns a new smartbinding
 * @type {SmartBinding}
 * @constructor
 * @jpfclass
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.8
 */
jpf.SmartBinding = function(name, xmlNode){
	this.xmlbindings = null;
	this.xmlactions = null;
	this.xmldragdrop = null;
	this.bindings = null;
	this.actions = null;
	this.dragdrop = null;

	this.jmlNodes = {};
	this.modelXpath = {};
	this.name = name;

	var parts = {bindings:'loadBindings',actions:'loadActions',dragdrop:'loadDragDrop'}
	
	jpf.status(name ? "Creating SmartBinding [" + name + "]" : "Creating implicitly assigned SmartBinding");
	
	/**
	 * @private
	 */
	this.initialize = function(jmlNode, part){
		//register element
		this.jmlNodes[jmlNode.uniqueId] = jmlNode;
		
		if(part)
			return jmlNode[parts[part]](this[part], this["xml" + part]);
		
		if(jmlNode.jml && this.name) 
			jmlNode.jml.setAttribute("smartbinding", this.name);
		
		for(part in parts){
			if(typeof parts[part] != "string") continue;
			if(!this[part]) continue;

			if(!jmlNode[parts[part]]) throw new Error(1035, jpf.formErrorString(1035, jmlNode, "initialize method in SmartBindings object", "Could not find handler for '" + part + "'."));
			jmlNode[parts[part]](this[part], this["xml" + part]);
		}
		
		if(this.model)
			this.model.register(jmlNode, this.modelXpath[jmlNode.getHost ? jmlNode.getHost().uniqueId : jmlNode.uniqueId] || this.modelBaseXpath); //this is a hack.. by making MOdels with links to other models possible, this should not be needed
		else if(jmlNode.model)
			jmlNode.model.reloadJmlNode(jmlNode.uniqueId);//.load(jmlNode.model.data.selectSingleNode("Accounts/Account[1]"));
	}
	
	/**
	 * @private
	 */
	this.deinitialize = function(jmlNode){
		//unregister element
		this.jmlNodes[jmlNode.uniqueId] = null;
		delete this.jmlNodes[jmlNode.uniqueId];
		
		if(this.model)
			this.model.unregister(jmlNode);
	}
	
	/**
	 * @private
	 */
	this.addBindRule = function(xmlNode, jmlParent){
		var str = xmlNode[jpf.TAGNAME] == "ref" ? jmlParent ? jmlParent.mainBind : "value" : xmlNode.tagName;
		if(!this.bindings) this.bindings = {};
		if(!this.bindings[str]) this.bindings[str] = [xmlNode];
		else this.bindings[str].push(xmlNode);
	}
	
	/**
	 * @private
	 */
	this.addBindings = function(rules){
		this.bindings = rules;//jpf.getRules(xmlNode);
		this.xmlbindings = xmlNode;
	}
	
	/**
	 * @private
	 */
	this.addActionRule = function(xmlNode){
		var str = xmlNode[jpf.TAGNAME] == "action" ? "Change" : xmlNode.tagName;
		if(!this.actions) this.actions = {};
		if(!this.actions[str]) this.actions[str] = [xmlNode];
		else this.actions[str].push(xmlNode);
	}
	
	/**
	 * @private
	 */
	this.addActions = function(rules, xmlNode){
		this.actions = rules;//jpf.getRules(xmlNode);
		this.xmlactions = xmlNode;
	}
	
	/**
	 * @private
	 */
	this.addDropRule = 
	this.addDragRule = function(xmlNode){
		if(!this.dragdrop) this.dragdrop = {};
		if(!this.dragdrop[xmlNode[jpf.TAGNAME]]) this.dragdrop[xmlNode[jpf.TAGNAME]] = [xmlNode];
		else this.dragdrop[xmlNode[jpf.TAGNAME]].push(xmlNode);
	}
	
	/**
	 * @private
	 */
	this.addDragDrop = function(rules, xmlNode){
		this.dragdrop = rules;//jpf.getRules(xmlNode);
		this.xmldragdrop = xmlNode;
	}
	
	/**
	 * @private
	 */
	this.setModel = function(model, xpath){
		if(typeof model == "string") model = jpf.NameServer.get("model", model);
		
		this.model = jpf.NameServer.register("model", this.name, model);
		this.modelBaseXpath = xpath;
		
		for(var uniqueId in this.jmlNodes){
			this.model.unregister(this.jmlNodes[uniqueId]);
			this.model.register(jmlNode, this.modelXpath[jmlNode.getHost ? jmlNode.getHost().uniqueId : jmlNode.uniqueId] || this.modelBaseXpath); //this is a hack.. by making Models with links to other models possible, this should not be needed
			//this.jmlNodes[uniqueId].load(this.model);
		}
	}
	
	/**
	 * Loads xml data in all the components using this SmartBinding.
	 * 
	 * @param  {variant}  xmlRootNode  optional  XMLNode  XML node which is loaded in this component. 
	 *                                          String  Serialize xml which is loaded in this component.
	 *                                          Null  Giving null clears this component {@link Cache#clear}.
	 */
	this.load = function(xmlNode){
		this.setModel(new jpf.Model().load(xmlNode));
	}
	
	this.loadJML = function(xmlNode){
		this.name = xmlNode.getAttribute("id");
		this.jml = xmlNode;
		
		//Bindings
		if(xmlNode.getAttribute("bindings")){
			if(!jpf.NameServer.get("bindings", xmlNode.getAttribute("bindings")))
				throw new Error(1036, jpf.formErrorString(1036, this, "Connecting bindings", "Could not find bindings by name '" + xmlNode.getAttribute("bindings") + "'"));
			
			var cNode = jpf.NameServer.get("bindings", xmlNode.getAttribute("bindings"));
			this.addBindings(jpf.getRules(cNode), cNode);
		}
		
		//Actions
		if(xmlNode.getAttribute("actions")){
			if(!jpf.NameServer.get("actions", xmlNode.getAttribute("actions")))
				throw new Error(1037, jpf.formErrorString(1037, this, "Connecting bindings", "Could not find actions by name '" + xmlNode.getAttribute("actions") + "'"));
			
			var cNode = jpf.NameServer.get("actions", xmlNode.getAttribute("actions"));
			this.addActions(jpf.getRules(cNode), cNode);
		}
		
		//DragDrop
		if(xmlNode.getAttribute("dragdrop")){
			if(!jpf.NameServer.get("dragdrop", xmlNode.getAttribute("dragdrop")))
				throw new Error(1038, jpf.formErrorString(1038, this, "Connecting dragdrop", "Could not find dragdrop by name '" + xmlNode.getAttribute("dragdrop") + "'"));
			
			var cNode = jpf.NameServer.get("dragdrop", xmlNode.getAttribute("dragdrop"));
			this.addDragDrop(jpf.getRules(cNode), cNode);
		}
		
		var data_node, nodes = xmlNode.childNodes;
		for(var i=0;i<nodes.length;i++){
			if(nodes[i].nodeType != 1) continue;
	
			switch(nodes[i][jpf.TAGNAME]){
				case "model": data_node = nodes[i]; break;
				case "bindings": this.addBindings(jpf.getRules(nodes[i]), nodes[i]); break;
				case "actions": this.addActions(jpf.getRules(nodes[i]), nodes[i]); break;
				case "dragdrop": this.addDragDrop(jpf.getRules(nodes[i]), nodes[i]); break;
				case "ref": this.addBindRule(nodes[i]); break;
				case "action": this.addActionRule(nodes[i]); break;
				default:
					throw new Error(1039, jpf.formErrorString(1039, this, "setSmartBinding Method", "Could not find handler for '" + nodes[i].tagName + "' node."));
					//when an unknown found assume that this is an implicit bindings node
					//this.addBindings(jpf.getRules(xmlNode)); 
					break;
			}
		}
		
		//Set Model
		if(data_node) this.setModel(new jpf.Model().loadJML(data_node));
		else if(xmlNode.getAttribute("model")) jpf.setModel(xmlNode.getAttribute("model"), this);
	}
	
	if(xmlNode) this.loadJML(xmlNode);
}

/*FILEHEAD(/in/Core/Application/XMLDatabase.js)SIZE(34503)TIME(1203730484247)*/

/**
 * XMLDatabase object is the local storage for XML data.
 * This object routes all change requests to synchronize data with representation.
 * It also has many utility methods which makes dealing with XML a lot nicer.
 *
 * @classDescription		This class creates a new xmldatabase
 * @return {XMLDatabaseImplementation} Returns a new xmldatabase
 * @type {XMLDatabaseImplementation}
 * @constructor
 * @jpfclass
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.8
 */
jpf.XMLDatabaseImplementation = function(){
	this.xmlDocTag = "j_doc";
	this.xmlIdTag = "j_id";
	this.xmlListenTag = "j_listen";
	this.htmlIdTag = "id";
	
	var xmlDocLut = [];
	
	/* ************************************************************
							Remote SmartBindings
	*************************************************************/
	
	this.rdb = false;
	this.RDBHash = {};
	this.RDBChoices = [];
	
	/**
	 * @private
	 */
	this.loadRDB = function(x){
		this.rdb = true;
		this.socket = self[x.getAttribute("socket")];
		this.socket.onreceive = function(module, data){
			//module should be "rdb"
			jpf.XMLDatabase.receiveRDB(data);
		}

		var q = x.childNodes;
		for(var i=0;i<q.length;i++){
			if(q[i].nodeType != 1) continue;
			
			if(q[i].getAttribute("select")) 
				this.RDBChoices.push(q[i].getAttribute("select"), q[i].getAttribute("unique"));
			else this.RDBHash[q[i].tagName] = q[i].getAttribute("unique");
		}
	}
	
	/* ************************************************************
							Lookup
	*************************************************************/
	
	/**
	 * @private
	 */
	this.getElementById = function(id, doc){
		if(!doc) doc = xmlDocLut[id.split("\|")[0]];
		if(!doc) return false;
		return doc.selectSingleNode("descendant-or-self::node()[@" + this.xmlIdTag + "='" + id + "']");
	}

	/**
	 * @private
	 */
	this.getNode = function(htmlNode){
		if(!htmlNode || !htmlNode.getAttribute(this.htmlIdTag)) return false;
		return this.getElementById(htmlNode.getAttribute(this.htmlIdTag).split("\|", 2).join("|"));
	}

	/**
	 * @private
	 */
	this.getNodeById = function(id, doc){
		var q = id.split("\|");q.pop();
		return this.getElementById(q.join("|"), doc);//id.split("\|", 2).join("|")
	}

	/**
	 * @private
	 */
	this.getDocumentById = function(id){
		return xmlDocLut[id];
	}

	/**
	 * @private
	 */
	this.getDocument = function(node){
		return xmlDocLut[node.getAttribute(this.xmlIdTag).split("\|")[0]];
	}
	
	/**
	 * @private
	 */
	this.getID = function(xmlNode, o){
		return xmlNode.getAttribute(this.xmlIdTag) + "|" + o.uniqueId;
	}
	
	/**
	 * Gets the child position of the DOM node.
	 *
	 * @param  {DOMNode}  node  required  DOM node which is subject to the query.
	 * @return  {Integer}  position of DOM node within the NodeList of children of it's parent
	 */
	this.getChildNumber = function(node){
		var p = node.parentNode;
		for(var i=0;i<p.childNodes.length;i++) if(p.childNodes[i] == node) return i;
	}
	
	/**
	 * Determines wether <code>childnode</code> is a child of <code>pnode</code>.
	 *
	 * @param  {DOMNode}  pnode  required  DOM node for which is determined if <code>childnode</code> is a child.
	 * @param  {DOMNode}  childnode  required  DOM node for which is determined if <code>pnode</code> is a parent.
	 * @param  {Boolean}  orItself  optional  true   method also returns true when pnode == childnode
	 *                                       false  method only returns true when childnode is a child of pnode
	 * @return  {Integer}  position of DOM node within the NodeList of children of it's parent
	 */
	this.isChildOf = function(pnode, childnode, orItself){
		if(!pnode || !childnode) return false;
		if(orItself && pnode == childnode) return true;
		
		var nodes = pnode.getElementsByTagName("*");
		for(var i=0;i<nodes.length;i++) if(nodes[i] == childnode) return true;
		return false;
	}
	
	/**
	 * Finds HTML node used as representation by component <code>oComp</comp for an XML data node.
	 *
	 * @param  {XMLNode}  xmlNode  required  XML data node bound to a HTML node.
	 * @param  {JMLNode}  oComp  required  Component which has representation of the <code>xmlNode</code>.
	 * @return  {HTMLNode}  the found HTML node or null
	 */
	this.findHTMLNode = function(xmlNode, oComp){
		do{
			if(xmlNode.getAttribute(this.xmlIdTag)){
				return oComp.getNodeFromCache(xmlNode.getAttribute(this.xmlIdTag)+"|"+oComp.uniqueId);
			}
			if(xmlNode == oComp.XMLRoot) return null;
			xmlNode = xmlNode.parentNode;
		}while(xmlNode && xmlNode.nodeType != 9)
		
		return null;
	}
	
	/**
	 * Finds XML node used as representation by component <code>oComp</comp for an XML data node.
	 *
	 * @param  {HTMLNode}  htmlNode  required  HTML node bound to a XML node.
	 * @return  {XMLNode}  the found XML node or null
	 */
	this.findXMLNode = function(htmlNode){
		if(!htmlNode) return false;

		while(htmlNode && htmlNode.nodeType == 1 && htmlNode.tagName.toLowerCase() != "body" && !htmlNode.getAttribute("id") || htmlNode && htmlNode.nodeType == 1 && htmlNode.getAttribute(this.htmlIdTag) && htmlNode.getAttribute(this.htmlIdTag).match(/^q/)){
			if(htmlNode.host && htmlNode.host.oExt == htmlNode) return htmlNode.host.XMLRoot;
			htmlNode = htmlNode.parentNode;
		}
		if(!htmlNode || htmlNode.nodeType != 1) return false;
		
		if(htmlNode.tagName.toLowerCase() == "body") return false;

		return this.getNode(htmlNode);
	}
	
	/**
	 * @private
	 */
	this.getElement = function(parent, nr){
		var nodes = parent.childNodes;
		for(var j=0,i=0;i<nodes.length;i++){
			if(nodes[i].nodeType != 1) continue;
			if(j++ == nr) return nodes[i];
		}
	}
	
	/**
	 * @private
	 */
	this.getModel = function(name){
		return jpf.NameServer.get("model", name);
	}
	
	/**
	 * @private
	 */
	this.setModel = function(model){
		jpf.NameServer.register("model", model.data.ownerDocument.documentElement.getAttribute(this.xmlDocTag), model);
	}
	
	/**
	 * @private
	 */
	this.findModel = function(xmlNode){
		return this.getModel(xmlNode.ownerDocument.documentElement.getAttribute(this.xmlDocTag));
	}
	
	/**
	 * Creates an XML node from an string containing serialized XML.
	 *
	 * @param  {String}  strXml   required  String contining serialized XML.
	 * @param  {Boolean}  no_error  optional  When set to true no exception is thrown when invalid XML is detected.
	 * @return  {XMLNode}  the created XML node
	 */
	this.getXml = function(strXml, no_error){
		return jpf.getObject("XMLDOM", strXml, no_error).documentElement;
	}

	/* ************************************************************
							Data-Binding - ADMIN
	*************************************************************/
	this.nodeCount = {};

	/**
	 * @private 
	 */
	this.nodeConnect = function(documentId, xmlNode, htmlNode, o){
		if(!this.nodeCount[documentId]) this.nodeCount[documentId] = 0;

		var xmlID = xmlNode.getAttribute(this.xmlIdTag) || documentId + "|" + ++this.nodeCount[documentId];
		xmlNode.setAttribute(this.xmlIdTag, xmlID);
		if(!o) return xmlID;
		
		var htmlID = xmlID + "|" + o.uniqueId;
		if(htmlNode) htmlNode.setAttribute(this.htmlIdTag, htmlID);

		return htmlID;
	}

	/**
	 * @private 
	 */
	this.addNodeListener = function(xmlNode, o){
		if(!o.__xmlUpdate) throw new Error(1040, jpf.formErrorString(1040, null, "Adding Node listener", "Cannot attach this listener because it doesn't support the correct interface (__xmlUpdate)."));

		var listen = xmlNode.getAttribute(this.xmlListenTag);
		var nodes = (listen ? listen.split(";") : []);
		
		if(!nodes.contains(o.uniqueId)) nodes.push(o.uniqueId);
		xmlNode.setAttribute(this.xmlListenTag, nodes.join(";"));
		
		return xmlNode;
	}
	
	/**
	 * @todo  Use this function when a component really unbinds from a 
	 *        piece of data and does not uses it for caching
	 */
	this.removeNodeListener = function(xmlNode, o){
		var listen = xmlNode.getAttribute(this.xmlListenTag);
		var nodes = (listen ? listen.split(";") : []);
		
		for(var newnodes=[],i=0;i<nodes.length;i++){
			if(nodes[i] != o.uniqueId) newnodes.push(nodes[i]);
		}

		xmlNode.setAttribute(this.xmlListenTag, newnodes.join(";"));
		
		return xmlNode;
	}

	/**
	 * Integrates nodes as children beneath a parentnode 
	 * (optionally including attributes)
	 *
	 * @param  {XMLNode}  xmlNode  required  XMLNode specifying the data to integrate.
	 * @param  {XMLNode}  parent  required  XMLNode specifying the point of integration.
	 * @param  {Boolean}  copyAttributes  optional  When set to true the attributes of <code>xmlNode</code> are copied as well.
	 * @return  {XMLNode}  the created XML node
	 */
	this.integrate = function(XMLRoot, parentNode, copyAttributes){
		if(typeof parentNode != "object") parentNode = getElementById(parentNode);
		
		if(parentNode.ownerDocument.importNode)
			for(var i=XMLRoot.childNodes.length-1;i>=0;i--) parentNode.insertBefore(parentNode.ownerDocument.importNode(XMLRoot.childNodes[i], true), parentNode.firstChild);
		else for(var i=XMLRoot.childNodes.length-1;i>=0;i--) parentNode.insertBefore(XMLRoot.childNodes[i], parentNode.firstChild);
		
		if(copyAttributes){
			var attr = XMLRoot.attributes;
			for(var i=0;i<attr.length;i++) if(attr[i].nodeName != this.xmlIdTag) parentNode.setAttribute(attr[i].nodeName, attr[i].nodeValue);
		}
		
		return parentNode;
	}

	/**
	 * @private 
	 * @description  Integrates current XMLDatabase with parent XMLDatabase
	 *	
	 *	- assuming transparency of XMLDOM elements cross windows
	 *	  with no performence loss.
	 */
	this.synchronize = function(){
		this.forkRoot.parentNode.replaceChild(this.root, this.forkRoot);
		this.parent.applyChanges("synchronize", this.root);
	}
	
	this.copyNode = function(xmlNode){
		return this.clearConnections(xmlNode.cloneNode(true));
	}

	/* ************************************************************
							Data-Binding - EXEC
	*************************************************************/
	
	this.setNodeValue = function(xmlNode, nodeValue, applyChanges){
		if(xmlNode.nodeType == 1){
			if(!xmlNode.firstChild) xmlNode.appendChild(xmlNode.ownerDocument.createTextNode("-"));
			xmlNode.firstChild.nodeValue = jpf.isNot(nodeValue) ? "" : nodeValue;
			
			if(applyChanges) jpf.XMLDatabase.applyChanges("synchronize", xmlNode);
		}
		else{
			xmlNode.nodeValue = jpf.isNot(nodeValue) ? "" : nodeValue;
			if(applyChanges) jpf.XMLDatabase.applyChanges("synchronize", xmlNode.parentNode || xmlNode.selectSingleNode(".."));
		}
	}
	
	this.getNodeValue = function(xmlNode){
		if(!xmlNode) return "";
		return xmlNode.nodeType == 1 ? (!xmlNode.firstChild ? "" : xmlNode.firstChild.nodeValue) : xmlNode.nodeValue;
	}
	
	/* ******** GETINHERITEDATTRIBUTE ***********
		Returns inherited connect id if any

		INTERFACE:
		this.getInheritedAttribute(XMLNode);
	****************************/
	this.getInheritedAttribute = function(x, attr, func){
		var result, y = x;
		while(y && y.nodeType != 11 && y.nodeType != 9 && !(result = attr && y.getAttribute(attr) || func && func(y))){
			y = y.parentNode;
		}
		
		if(!result && attr && jpf.appsettings.jml) 
			result = jpf.appsettings.jml.getAttribute(attr);
		return result;
	}
	
	/* ******** SETTEXTNODE ***********
		Set nodeValue of Text Node. If Node doesn't exist it is created.
		Optionally xpath statement is executed to identify textnode.
		
		INTERFACE:
		this.setTextNode(pnode, value, [xpath]);
	****************************/	
	this.setTextNode = function(pnode, value, xpath, UndoObj){
		if(xpath){
			var tNode = pnode.selectSingleNode(xpath);
			if(!tNode) return;
			pnode = tNode.nodeType == 1 ? tNode : null;
		}
		if(pnode || !tNode){
			if(!pnode.firstChild) var tNode = pnode.appendChild(pnode.ownerDocument.createTextNode(""));//createCDATASection
			else var tNode = pnode.firstChild;
		}
		
		//Action Tracker Support
		if(UndoObj) UndoObj.oldValue = tNode.nodeValue;
		
		//Apply Changes
		tNode.nodeValue = value;
		
		this.applyChanges("text", tNode.parentNode, UndoObj);
		
		this.applyRDB("setTextNode", pnode, value, xpath, UndoObj);
	}

	/* ******** SETATTRIBUTE ***********
		Sets attribute of node.
		Optionally xpath statement is executed to identify attribute node
		
		INTERFACE:
		this.setAttribute(xmlNode, name, value, [xpath]);
	****************************/
	this.setAttribute = function(xmlNode, name, value, xpath, UndoObj){
		//if(xmlNode.nodeType != 1) xmlNode.nodeValue = value;
		
		//Apply Changes
		(xpath ? xmlNode.selectSingleNode(xpath) : xmlNode).setAttribute(name, value);
		this.applyChanges("attribute", xmlNode, UndoObj);
		
		this.applyRDB("setAttribute", xmlNode, name, value, xpath, UndoObj);
	}
	
	/* ******** REMOVEATTRIBUTE ***********
		Removes attribute of node.
		Optionally xpath statement is executed to identify attribute node
		
		INTERFACE:
		this.removeAttribute(xmlNode, name, [xpath]);
	****************************/
	this.removeAttribute = function(xmlNode, name, xpath, UndoObj){
		//if(xmlNode.nodeType != 1) xmlNode.nodeValue = value;
		
		//Action Tracker Support
		if(UndoObj) UndoObj.name = name;

		//Apply Changes
		(xpath ? xmlNode.selectSingleNode(xpath) : xmlNode).removeAttribute(name);
		this.applyChanges("attribute", xmlNode, UndoObj);
		
		this.applyRDB("removeAttribute", xmlNode, name, xpath, UndoObj);
	}
	
	/* ******** REPLACENODE ***********
		Replace one node with another
		Optionally xpath statement is executed to identify attribute node
		
		INTERFACE:
		this.replaceNode(oldNode, newNode, [xpath]);
	****************************/
	this.replaceNode = function(oldNode, newNode, xpath, UndoObj){
		//if(xmlNode.nodeType != 1) xmlNode.nodeValue = value;
		
		//Apply Changes
		if(xpath) oldNode = oldNode.selectSingleNode(xpath);
		
		//Action Tracker Support
		if(UndoObj) UndoObj.oldNode = oldNode;
		
		oldNode.parentNode.replaceChild(newNode, oldNode);
		this.copyConnections(oldNode, newNode);
		
		this.applyChanges("replacechild", newNode, UndoObj);
		
		this.applyRDB("replaceChild", oldNode, newNode, xpath, UndoObj);
	}

	/* ******** ADDCHILDNODE ***********
		Creates a new node under pnode before beforeNode or as last node.
		Optionally xpath statement is executed to identify parentNode node
		
		INTERFACE:
		this.addChildNode(pnode, tagName, attr, [afterNode], [xpath]);
	****************************/
	this.addChildNode = function(pnode, tagName, attr, beforeNode, xpath, UndoObj){
		//Create New Node
		var xmlNode = pnode.insertBefore(pnode.ownerDocument.createElement(tagName), beforeNode);

		//Set Attributes
		for(var i=0;i<attr.length;i++) xmlNode.setAttribute(attr[i][0], attr[i][1]);
		
		//Action Tracker Support
		if(UndoObj) UndoObj.addedNode = xmlNode;
		
		this.applyChanges("add", xmlNode, UndoObj);
		
		this.applyRDB("addChildNode", pnode, tagName, attr, beforeNode, xpath, UndoObj);
		
		return xmlNode;
	}

	/* ******** APPENDCHILDNODE ***********
		Appends xmlNode to pnode and before beforeNode or as last node
		Optionally set bool unique to make sure node is unique under parent
		Optionally xpath statement is executed to identify parentNode node
		
		INTERFACE:
		this.appendChildNode(pnode, xmlNode, [afterNode], [unique], [xpath]);
	****************************/
	this.appendChildNode = function(pnode, xmlNode, beforeNode, unique, xpath, UndoObj){
		if(unique && pnode.selectSingleNode(xmlNode.tagName)) return false;
		
		if(UndoObj) this.clearConnections(xmlNode);
		
		//Add xmlNode to parent pnode or one selected by xpath statement
		(xpath ? pnode.selectSingleNode(xpath) : pnode).insertBefore(xmlNode, beforeNode);
		
		//detect if xmlNode should be removed somewhere else
		//- [17-2-2004] changed pnode (2nd arg applychange) into xmlNode

		this.applyChanges("add", xmlNode, UndoObj);
		
		this.applyRDB("appendChildNode", pnode, xmlNode.xml, beforeNode, unique, xpath, UndoObj);
		
		return xmlNode;
	}
	
	this.copyConnections = function(fromNode, toNode){
		//This should copy recursive
		try{
			toNode.setAttribute(this.xmlListenTag, fromNode.getAttribute(this.xmlListenTag));
			toNode.setAttribute(this.xmlIdTag, fromNode.getAttribute(this.xmlIdTag));
		}catch(e){}
	}
	
	this.clearConnections = function(xmlNode){
		try{
			var nodes = xmlNode.selectNodes("descendant-or-self::node()[@" + this.xmlListenTag + "]");
			for(var i=nodes.length-1;i>=0;i--) nodes[i].removeAttributeNode(nodes[i].getAttributeNode(this.xmlListenTag));
			var nodes = xmlNode.selectNodes("descendant-or-self::node()[@" + this.xmlIdTag + "]");
			for(var i=nodes.length-1;i>=0;i--) nodes[i].removeAttributeNode(nodes[i].getAttributeNode(this.xmlIdTag));
			var nodes = xmlNode.selectNodes("descendant-or-self::node()[@" + this.xmlDocTag + "]");
			for(var i=nodes.length-1;i>=0;i--) nodes[i].removeAttributeNode(nodes[i].getAttributeNode(this.xmlDocTag));
			var nodes = xmlNode.selectNodes("descendant-or-self::node()[@j_loaded]");
			for(var i=nodes.length-1;i>=0;i--) nodes[i].removeAttributeNode(nodes[i].getAttributeNode("j_loaded"));
			//var nodes = xmlNode.selectNodes("descendant-or-self::node()[@j_selection]");
			//for(var i=nodes.length-1;i>=0;i--) nodes[i].removeAttributeNode(nodes[i].getAttributeNode("j_selection"));
		}catch(e){}
		
		return xmlNode;
	}
	
	this.serializeNode = function(xmlNode){
		return this.clearConnections(xmlNode.cloneNode(true)).xml;
	}
	
	/* ******** MOVENODE ***********
		Moves xmlNode to pnode and before beforeNode or as last node
		
		INTERFACE:
		this.moveNode(pnode, xmlNode, [beforeNode], [xpath]);
	****************************/
	this.moveNode = function(pnode, xmlNode, beforeNode, xpath, UndoObj){
		//Action Tracker Support
		if(!UndoObj) UndoObj = {};
		UndoObj.pNode = xmlNode.parentNode;
		UndoObj.beforeNode = xmlNode.nextSibling;
		UndoObj.toPnode = (xpath ? pnode.selectSingleNode(xpath) : pnode);

		this.applyChanges("move-away", xmlNode, UndoObj);
		
		//Set new id if the node change document (for safari this should be fixed)
		if(!jpf.isSafari && jpf.XMLDatabase.getXmlDocId(xmlNode) != jpf.XMLDatabase.getXmlDocId(pnode)){
			xmlNode.removeAttributeNode(xmlNode.getAttributeNode(this.xmlIdTag));
			this.nodeConnect(jpf.XMLDatabase.getXmlDocId(pnode), xmlNode);
		}

		if(jpf.isSafari && pnode.ownerDocument != xmlNode.ownerDocument) xmlNode = pnode.ownerDocument.importNode(xmlNode, true); //Safari issue not auto importing nodes
		UndoObj.toPnode.insertBefore(xmlNode, beforeNode);
		this.applyChanges("move", xmlNode, UndoObj);
		
		this.applyRDB("moveNode", pnode, xmlNode, beforeNode, xpath, UndoObj);
	}

	/* ******** REMOVENODE ***********
		Removes xmlNode from xmlTree
		Optional xpath statement identifies xmlNode
		
		INTERFACE:
		this.removeNode(xmlNode, [xpath]);
	****************************/
	this.removeNode = function(xmlNode, xpath, UndoObj){
		if(xpath) xmlNode = xmlNode.selectSingleNode(xpath);
		
		//ActionTracker Support
		if(UndoObj){
			UndoObj.pNode = xmlNode.parentNode;
			UndoObj.removedNode = xmlNode;
			UndoObj.beforeNode = xmlNode.nextSibling;
		}
		
		//Apply Changes
		this.applyChanges("remove", xmlNode, UndoObj);
		var p = xmlNode.parentNode; p.removeChild(xmlNode);
		this.applyChanges("redo-remove", xmlNode, null, p);//UndoObj
		
		this.applyRDB("removeNode", xmlNode, xpath, UndoObj);
	}

	/* ******** REMOVENODELIST ***********
		Removes xmlNodeList from xmlTree
		
		INTERFACE:
		this.removeNodeList(xmlNodeList);
	************************************/
	this.removeNodeList = function(xmlNodeList, UndoObj){
		//if(xpath) xmlNode = xmlNode.selectSingleNode(xpath);
		
		for(var rData=[],i=0;i<xmlNodeList.length;i++){ //This can be optimized by looping nearer to xmlUpdate
			//ActionTracker Support
			if(UndoObj){
				rData.push({
					pNode : xmlNodeList[i].parentNode,
					removedNode : xmlNodeList[i],
					beforeNode : xmlNodeList[i].nextSibling
				});
			}
			
			//Apply Changes
			this.applyChanges("remove", xmlNodeList[i], UndoObj);
			var p = xmlNodeList[i].parentNode; p.removeChild(xmlNodeList[i]);
			this.applyChanges("redo-remove", xmlNodeList[i], null, p);//UndoObj
		}
		if(UndoObj) UndoObj.removeList = rData;
		
		this.applyRDB("removeNodeList", xmlNodeList, null, UndoObj);
	}
	
	/* ************************************************************
						Data-Binding: Applying Changes
	*************************************************************/
	
	/* ******** APPLYCHANGES  ***********
		Looks for listeners and execute their __xmlUpdate methods
		
		INTERFACE:
		this.applyChanges(xmlNode);
	****************************/
	this.applyChanges = function(action, xmlNode, UndoObj, nextloop){
		//Set Variables
		var oParent = nextloop, loopNode = (xmlNode.nodeType == 1 ? xmlNode : xmlNode.parentNode), hash = {};

		while(loopNode && loopNode.nodeType != 9){
			//Get List of Node listeners ID's
			var listen = loopNode.getAttribute(this.xmlListenTag);

			if(listen){
				var ids = listen.split(";");

				//Loop through ID List and call for xmlUpdate
				for(var i=0;i<ids.length;i++){
					if(hash[ids[i]]) continue; hash[ids[i]] = true;

					//Only Local Objects [LATER: or those of parentWindows]
					var o = jpf.localLookup(ids[i]);
					if(o){
						//Check if component is just waiting for data to become available
						if(o.listenRoot){
							var model = o.getModel();
							
							if(!model) throw new Error(0, jpf.formErrorString(this, "Notifying Component of data change", "Component without a model is listening for changes", this.jml));
							
							var xpath = model.getXpathByJmlNode(o);
							var XMLRoot = xpath ? model.data.selectSingleNode(xpath) : model.data;
							if(XMLRoot){
								jpf.XMLDatabase.removeNodeListener(o.listenRoot, o);
								o.listenRoot = null;
								o.load(XMLRoot);
							}
							continue;
						}
						
						//Update xml data
						o.__xmlUpdate(action, xmlNode, loopNode, UndoObj, oParent);
					}
				}
			}
			
			//Go one level up
			loopNode = loopNode.parentNode || nextloop;
			if(loopNode == nextloop) nextloop = null;
		}
		
		if(UndoObj) UndoObj.xmlNode = xmlNode;
		//if(UndoObj) alert(UndoObj.xmlNode.xml);
	}
	
	this.notifyListeners = function(xmlNode){
		//This should be done recursive
		var listen = xmlNode.getAttribute(jpf.XMLDatabase.xmlListenTag);
		if(listen){
			listen = listen.split(";");
			for(var j=0;j<listen.length;j++){
				jpf.lookup(listen[j]).__xmlUpdate("synchronize", xmlNode, xmlNode);
				//load(xmlNode);
			}
		}
	}

	/* ******** APPLYRDB  ***********
		Sents Message through socket to tell remote databound listeners
		that data has been changed
		
		INTERFACE:
		this.applyRDB([...], [UndoObj]);
	****************************/
	this.applyRDB = function(){
		//To optimize below line can move upwards | Disable if receiving RDB Message
		if(!this.rdb || this.rcvrdb) return false;
		
		var UndoObj, args = [], q = arguments;
		for(var i=0;i<q.length;i++){
			if(q[i] && q[i].tagName == "UndoData") UndoObj = q[i];
			else args.push(q[i] && q[i].nodeType ? this.serializeXmlToXpath(q[i]) : q[i]);
		}

		//ActionTracker Support
		if(UndoObj) UndoObj.rdb_args = args;
		//Or sent Socket call
		else this.socket.send("rdb", args);
	}

	/* ******** RECEIVERDB ***********
		Receive RDB Message for data it has in cache
		
		INTERFACE:
		this.receiveRDB(data);
	****************************/
	this.receiveRDB = function(q){
		var xmlNode = this.unSerializeXmlToXpath(q[1]);
		if(!xmlNode) return;
		
		this.rcvrdb = true;
		switch(q[0]){
			case "setTextNode": this.setTextNode(xmlNode, q[2], q[3]);break;
			case "setAttribute": this.setAttribute(xmlNode, q[2], q[3], q[4]);break;
			case "addChildNode": this.addChildNode(xmlNode, q[2], q[3], this.unSerializeXmlToXpath(q[4]), q[5]);break;
			case "appendChildNode": 
				var beforeNode = (q[3] ? this.unSerializeXmlToXpath(q[3]) : null);
				this.appendChildNode(xmlNode, this.clearConnections(q[2]), beforeNode, q[4], q[5]);
			break;
			case "moveNode": 
				var beforeNode = (q[3] ? this.unSerializeXmlToXpath(q[3]) : null);
				var sNode = this.unSerializeXmlToXpath(q[2]);
				this.appendChildNode(xmlNode, sNode, beforeNode, q[4], q[5]);
			break;
			case "removeNode": this.removeNode(xmlNode, q[2]);break;
		}
		this.rcvrdb = false;
	}

	/* ******** UNBIND ***********
		Unbind all Javeline Elements from a certain Form
		
		INTERFACE:
		this.unbind(frm);
	****************************/
	this.unbind = function(frm){
		//Loop through objects of local jpf
		for(var lookup={},i=0;i<frm.jpf.local.length;i++)
			if(frm.jpf.local[i].unloadBindings)
				lookup[frm.jpf.local[i].unloadBindings()] = true;

		//Remove Listen Nodes
		for(var k=0;k<xmlDocLut.length;k++){
			if(!xmlDocLut[k]) continue;
			
			var Nodes = xmlDocLut[k].selectNodes("//self::node()[@" + this.xmlListenTag + "]");
	
			//Loop through Nodes and rebuild listen array
			for(var i=0;i<Nodes.length;i++){
				var listen = Nodes[i].getAttribute(this.xmlListenTag).split(";");
				for(var nListen=[],j=0;j<listen.length;j++)
					if(!lookup[listen[j]]) nListen.push(listen[j]);
	
				//Optimization??
				if(nListen.length != listen.length)
					Nodes[i].setAttribute(this.xmlListenTag, nListen.join(";"));
			}
		}
	}
	
	/* ************************************************************
							Skin-Binding - EXEC
	*************************************************************/
	
	//Currently only supports a single node
	this.selectNodes = function(sExpr, contextNode){
		if(jpf.hasXPathHtmlSupport || !contextNode.style) return contextNode.selectNodes(sExpr); //IE55
		//if(contextNode.ownerDocument != document) return contextNode.selectNodes(sExpr);
		
		return jpf.XPath.selectNodes(sExpr, contextNode)
	}
	
	this.selectSingleNode = function(sExpr, contextNode){
		if(jpf.hasXPathHtmlSupport || !contextNode.style) return contextNode.selectSingleNode(sExpr); //IE55
		//if(contextNode.ownerDocument != document) return contextNode.selectSingleNode(sExpr);
		
		var nodeList = this.selectNodes(sExpr + (jpf.isIE ? "" : "[1]"), contextNode ? contextNode : null);
		return nodeList.length > 0 ? nodeList[0] : null;
	}

	/* ************************************************************
							General XML Handling
	*************************************************************/
	
	//for RDB: xmlNode --> Xpath statement
	this.serializeXmlToXpath = function(xmlNode){
		var def = this.RDBHash[xmlNode.tagName];
		if(def){
			//unique should not have ' in it... -- can be fixed...
			var unique = xmlNode.selectSingleNode(def).nodeValue;
			return "//" + xmlNode.tagName + "[" + def + "='" + unique + "']";
		}

		for(var i=0;i<this.RDBChoices.length;i++){
			if(xmlNode.selectSingleNode(this.RDBChoices[i][0])){
				var unique = xmlNode.selectSingleNode(this.RDBChoices[i][1]).nodeValue;
				return "//" + this.RDBChoices[i][0] + "[" + this.RDBChoices[i][1] + "='" + unique + "']";
			}
		}

		//THIS SHOULD BE THE COMPLETE PATH
		return "//" + xmlNode.parentNode.tagName + "/" + xmlNode.tagName + "[" + (this.getChildNumber(xmlNode)+1) + "]";
	}

	//for RDB: Xpath statement --> xmlNode
	this.unSerializeXmlToXpath = function(str){
		for(var xmlNode=null,i=0;i<xmlDocLut.length;i++)
			if(xmlNode = xmlDocLut[i].selectSingleNode(str)) return xmlNode;
		
		return false;
	}
	
	this.createNodeFromXpath = function(contextNode, xPath, addedNodes){
		var xmlNode, foundpath = "", paths = xPath.split("/");
		if(xmlNode = contextNode.selectSingleNode(xPath)) return xmlNode;
		
		for(var addedNode,isAdding=false,i=0;i<paths.length-1;i++){
			if(!isAdding && contextNode.selectSingleNode(foundpath + (i != 0 ? "/" : "") + paths[i])){
				foundpath += (i != 0 ? "/" : "") + paths[i];
				continue;
			}
			
			if(paths[i].match(/\@|\[.*\]|\(.*\)/)) throw new Error(1041, jpf.formErrorString(1041, this, "Select via xPath", "Could not use xPath to create xmlNode: " + xPath));
			if(paths[i].match(/\/\//)) throw new Error(1041, jpf.formErrorString(1041, this, "Select via xPath", "Could not use xPath to create xmlNode: " + xPath));
			
			isAdding = true;
			addedNode = contextNode.selectSingleNode(foundpath).appendChild(contextNode.ownerDocument.createElement(paths[i]));
			if(addedNodes) addedNodes.push(addedNode);
			foundpath += paths[i] + "/";
		}
		if(!foundpath) foundpath = ".";
		
		var lastpath = paths[paths.length-1];
		if(lastpath.match(/^\@(.*)$/)){
			var attrNode = contextNode.ownerDocument.createAttribute(RegExp.$1);
			contextNode.selectSingleNode(foundpath).setAttributeNode(attrNode);
			return attrNode;
		}
		else if(lastpath.trim() == "text()") return contextNode.selectSingleNode(foundpath).appendChild(contextNode.ownerDocument.createTextNode(""));
		else return contextNode.selectSingleNode(foundpath).appendChild(contextNode.ownerDocument.createElement(lastpath));
	}

	this.getXmlDocId = function(xmlNode, model){
		var docId = (xmlNode.ownerDocument.documentElement || xmlNode).getAttribute(this.xmlDocTag) || xmlDocLut.indexOf(xmlNode.ownerDocument);
		if(docId && docId > -1) return docId;
		
		docId = xmlDocLut.push(xmlNode.ownerDocument.documentElement || xmlNode.ownerDocument || xmlNode)-1;
		if(xmlNode.ownerDocument.documentElement) xmlNode.ownerDocument.documentElement.setAttribute(this.xmlDocTag, docId);
		if(model) jpf.NameServer.register("model", docId, model);

		return xmlDocLut.length-1;
	}
	
	this.getBindXmlNode = function(xmlRootNode){
		if(typeof xmlRootNode != "object") xmlRootNode = jpf.getObject("XMLDOM", xmlRootNode);
		if(xmlRootNode.nodeType == 9) xmlRootNode = xmlRootNode.documentElement;
		if(xmlRootNode.nodeType == 3 || xmlRootNode.nodeType == 4) xmlRootNode = xmlRootNode.parentNode;
		if(xmlRootNode.nodeType == 2) xmlRootNode = xmlRootNode.selectSingleNode("..");
		
		return xmlRootNode;
	}
	
	this.convertMethods = {
		/**
		 * Gets a JSON object containing all the name/value pairs of the components using this component as it's validation group.
		 *
		 * @return  {Object}  the created JSON object
		 */
		"json" : function (xml){
			var result = {}, filled = false, nodes = xml.childNodes;
			for(var i=0;i<nodes.length;i++){
				if(nodes[i].nodeType != 1) continue;
				var name = nodes[i].tagName;
				filled = true;
				
				//array
				var sameNodes = xml.selectNodes(x);
				if(sameNodes.length > 1){
					var z = [];
					for(var j=0;j<sameNodes.length;j++){
						z.push(this.json(sameNodes[j], result));
					}
					result[name] = z;
				}
				
				//single value
				else result[name] = this.json(sameNodes[j], result);
			}
			
			return filled ? result : jpf.getXmlValue(xml, "text()");
		},
		
		"cgivars" : function(xml, basename){
			var str = [], filled = false, nodes = xml.childNodes;
			for(var i=0;i<nodes.length;i++){
				if(nodes[i].nodeType != 1) continue;
				var name = nodes[i].tagName;
				filled = true;
				
				//array
				var sameNodes = xml.selectNodes(name);
				if(sameNodes.length > 1){
					for(var j=0;j<sameNodes.length;j++){
						str.push(this.cgivars(sameNodes[j], (basename ? basename + "." : "") + name + "[" + j + "]"));
					}
				}
				
				//single value
				else str.push(this.cgivars(nodes[i], (basename ? basename + "." : "") + name));
			}
			
			return filled ? str.join("&") : (basename || "") + "=" + encodeURIComponent(jpf.getXmlValue(xml, "text()"));
		}
	};
	
	this.convertXml = function(xml, to){
		return this.convertMethods[to](xml);
	}
	
	this.getTextNode = function(x){
		for(var i=0;i<x.childNodes.length;i++){
			if(x.childNodes[i].nodeType == 3 || x.childNodes[i].nodeType == 4)
				return x.childNodes[i];
		}
		return false;
	}
	
	this.getAllNodesBefore = function(pNode, xpath, xmlNode, func){
		var nodes = jpf.XMLDatabase.selectNodes(xpath, pNode);
		for(var found=false,result=[],i=nodes.length-1;i>=0;i--){
			if(!found && nodes[i] == xmlNode){
				found = true;
				continue;
			}
			if(!found) continue;
			result.push(nodes[i]);
			if(func) func(nodes[i]);
		}
		return result;
	}
	
	this.getAllNodesAfter = function(pNode, xpath, xmlNode, func){
		var nodes = jpf.XMLDatabase.selectNodes(xpath, pNode);
		for(var found=false,result=[],i=0;i<nodes.length;i++){
			if(!found && nodes[i] == xmlNode){
				found = true;
				continue;
			}
			if(!found) continue;
			result.push(nodes[i]);
			if(func) func(nodes[i]);
		}
		return result;
	}
	
	this.clearBoundValue = function(jmlNode, xmlRoot, applyChanges){
		if(!xmlRoot && !jmlNode.XMLRoot) return;
		
		var xmlNode = (jmlNode.nodeType == GUI_NODE) ?
			xmlRoot.selectSingleNode(jmlNode.getAttribute("ref")) :
			jmlNode.getNodeFromRule("value", jmlNode.XMLRoot);
		
		if(xmlNode) this.setNodeValue(xmlNode, "", applyChanges);
	}
	
	this.getBoundValue = function(jmlNode, xmlRoot, applyChanges){
		if(!xmlRoot && !jmlNode.XMLRoot) return "";
		
		var xmlNode = (jmlNode.nodeType == 1) ?
			xmlRoot.selectSingleNode(jmlNode.getAttribute("ref")) :
			jmlNode.getNodeFromRule("value", jmlNode.XMLRoot);
		
		return xmlNode ? this.getNodeValue(xmlNode) : "";
	}
	
	this.getArrayFromNodelist = function(nodelist){
		for(var nodes=[],j=0;j<nodelist.length;j++) nodes.push(nodelist[j]);
		return nodes;
	}
}

jpf.Init.run('XMLDatabaseImplementation');

/*FILEHEAD(/in/Core/Application/XSDImplementation.js)SIZE(13191)TIME(1203730484247)*/
//Non validating parser

/**
 * Object returning an implementation of an XSD parser.
 *
 * @classDescription		This class creates a new XSD parser
 * @return {XSDImplementation} Returns a new XSD parser
 * @type {XSDImplementation}
 * @constructor
 * @parser
 *
 * @allownode simpleType, complexType
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.8
 */
jpf.XSDImplementation = function(){
	var typeHandlers = {
		//XSD datetypes [L10n potential]
		"xsd:dateTime" : function(value){
			value = value.replace(/-/g, "/");
	
			value.match(/^(\d{2})\/(\d{2})\/(\d{4}) (\d{2}):(\d{2}):(\d{2})$/);
			if(!RegExp.$3 || RegExp.$3.length < 4) return false;
		
			var dt = new Date(value);
			if(dt.getFullYear() != parseFloat(RegExp.$3)) return false;
			if(dt.getMonth() != parseFloat(RegExp.$2)-1) return false;
			if(dt.getDate() != parseFloat(RegExp.$1)) return false;
			if(dt.getHours() != parseFloat(RegExp.$4)) return false;
			if(dt.getMinutes() != parseFloat(RegExp.$5)) return false;
			if(dt.getSeconds() != parseFloat(RegExp.$5)) return false;
			
			return true;
		},
		"xsd:time" : function(value){
			value.match(/^(\d{2}):(\d{2}):(\d{2})$/);
		
			var dt = new Date(value);
			if(dt.getHours() != parseFloat(RegExp.$1)) return false;
			if(dt.getMinutes() != parseFloat(RegExp.$2)) return false;
			if(dt.getSeconds() != parseFloat(RegExp.$3)) return false;
			
			return true;
		},
		"xsd:date" : function(value){
			value = value.replace(/-/g, "/");
			value.match(/^(\d{2})\/(\d{2})\/(\d{4})$/);
			if(!RegExp.$3 || RegExp.$3.length < 4) return false;
		
			var dt = new Date(value);
			if(dt.getFullYear() != parseFloat(RegExp.$3)) return false;
			if(dt.getMonth() != parseFloat(RegExp.$2)-1) return false;
			if(dt.getDate() != parseFloat(RegExp.$1)) return false;
			
			return true;
		},
		"xsd:gYearMonth" : function(value){
			value = value.replace(/-/g, "/");
			value.match(/^\/?(\d{4})(?:\d\d)?\/(\d{2})(?:\w|[\+\-]\d{2}:\d{2})?$/);
			if(!RegExp.$1 || RegExp.$1.length < 4) return false;
		
			var dt = new Date(value);
			if(dt.getFullYear() != parseFloat(RegExp.$)) return false;
			if(dt.getMonth() != parseFloat(RegExp.$2)-1) return false;
			
			return true;
		},
		"xsd:gYear" : function(value){
			value.match(/^\/?(\d{4})(?:\d\d)?(?:\w|[\+\-]\d{2}:\d{2})?$/);
			if(!RegExp.$1 || RegExp.$1.length < 4) return false;
		
			var dt = new Date(value);
			if(dt.getFullYear() != parseFloat(RegExp.$1)) return false;
			
			return true;
		},
		"xsd:gMonthDay" : function(value){
			value = value.replace(/-/g, "/");
			value.match(/^\/\/(\d{2})\/(\d{2})(?:\w|[\+\-]\d{2}:\d{2})?$/);
		
			var dt = new Date(value);
			if(dt.getMonth() != parseFloat(RegExp.$1)-1) return false;
			if(dt.getDate() != parseFloat(RegExp.$2)) return false;
			
			return true;
		},
		"xsd:gDay" : function(value){
			value = value.replace(/-/g, "/");
			value.match(/^\/{3}(\d{2})(?:\w|[\+\-]\d{2}:\d{2})?$/);
		
			var dt = new Date(value);
			if(dt.getDate() != parseFloat(RegExp.$1)) return false;
			
			return true;
		},
		"xsd:gMonth" : function(value){
			value = value.replace(/-/g, "/");
			value.match(/^\/{2}(\d{2})(?:\w|[\+\-]\d{2}:\d{2})?$/);
		
			var dt = new Date(value);
			if(dt.getMonth() != parseFloat(RegExp.$1)-1) return false;
			
			return true;
		},
		
		//XSD datetypes
		"xsd:string" : function(value){return typeof value == "string"},
		"xsd:boolean" : function(value){return /^(true|false)$/i.test(value)},
		"xsd:base64Binary" : function(value){return true;},
		"xsd:hexBinary" : function(value){return /^(?:0x|x|#)?[A-F0-9]{0,8}$/i.test(value)},
		"xsd:float" : function(value){return parseFloat(value) == value},
		"xsd:decimal" : function(value){return /^[0-9\.\-,]+$/.test(value)},
		"xsd:double" : function(value){return parseFloat(value) == value},
		"xsd:anyURI" : function(value){return /^(?:\w+:\/\/)?(?:(?:[\w\-]+\.)+(?:[a-z]+)|(?:(?:1?\d?\d?|2[0-4]9|25[0-5])\.){3}(?:1?\d\d|2[0-4]9|25[0-5]))(?:\:\d+)?(?:\/([^\s\\\%]+|%[\da-f]{2})*)?$/i.test(value)},
		"xsd:QName" : function(value){return true;},
		"xsd:normalizedString" : function(value){return true;},
		"xsd:token" : function(value){return true;},
		"xsd:language" : function(value){return true;},
		"xsd:Name" : function(value){return true;},
		"xsd:NCName" : function(value){return true;},
		"xsd:ID" : function(value){return true;},
		"xsd:IDREF" : function(value){return true;},
		"xsd:IDREFS" : function(value){return true;},
		"xsd:NMTOKEN" : function(value){return true;},
		"xsd:NMTOKENS" : function(value){return true;},
		"xsd:integer" : function(value){return parseInt(value) == value},
		"xsd:nonPositiveInteger" : function(value){return parseInt(value) == value && value <= 0},
		"xsd:negativeInteger" : function(value){return parseInt(value) == value && value < 0},
		"xsd:long" : function(value){return parseInt(value) == value && value >= -2147483648 && value <= 2147483647},
		"xsd:int" : function(value){return parseInt(value) == value},
		"xsd:short" : function(value){return parseInt(value) == value && value >= -32768 && value <= 32767},
		"xsd:byte" : function(value){return parseInt(value) == value && value >= -128 && value <= 127},
		"xsd:nonNegativeInteger" : function(value){return parseInt(value) == value && value >= 0},
		"xsd:unsignedLong" : function(value){return parseInt(value) == value && value >= 0 && value <= 4294967295},
		"xsd:unsignedInt" : function(value){return parseInt(value) == value && value >= 0},
		"xsd:unsignedShort" : function(value){return parseInt(value) == value && value >= 0 && value <= 65535},
		"xsd:unsignedByte" : function(value){return parseInt(value) == value && value >= 0 && value <= 255},
		"xsd:positiveInteger" : function(value){return parseInt(value) == value && value > 0},
		
		//XForms datatypes
		"xforms:listItem" : function(value){return true;},
		"xforms:listItems" : function(value){return true;},
		"xforms:dayTimeDuration" : function(value){return true;},
		"xforms:yearMonthDuration" : function(value){return true;},
		
		//Javeline PlatForm datatypes
		"jpf:email" : function(value){return /^[A-Z0-9\.\_\%\-]+@(?:[A-Z0-9\-]+\.)+[A-Z]{2,4}$/i.test(value)},
		"jpf:creditcard" : function(value){
			value = value.replace(/ /g, "");
			value = value.pad(21, "0", PAD_LEFT);
			for(var total=0,r,i=value.length;i>=0;i--){
				r = value.substr(i, 1)*(i%2+1);
				total += r > 9 ? r-9 : r;
			}
			return total%10 === 0;
		},
		"jpf:expdate" : function(value){
			value = value.replace(/-/g, "/");
			value = value.split("/");//.match(/(\d{2})\/(\d{2})/);
		
			var dt = new Date(value[0] + "/01/" + value[1]);
			//if(fulldate && dt.getFullYear() != parseFloat(value[1])) return false;
			if(dt.getYear() != parseFloat(value[1])) return false;//!fulldate && 
			if(dt.getMonth() != parseFloat(value[0])-1) return false;
			
			return true;	
		},
		"jpf:wechars" : function(value){return /^[0-9A-Za-z\xC0-\xCF\xD1-\xD6\xD8-\xDD\xDF-\xF6\xF8-\xFF -\.',]+$/.test(value)},
		"jpf:phonenumber" : function(value){return /^[\d\+\- \(\)]+$/.test(value)},
		"jpf:faxnumber" : function(value){return /^[\d\+\- \(\)]+$/.test(value)},
		"jpf:mobile" : function(value){return /^[\d\+\- \(\)]+$/.test(value)}
	};
	
	var custumTypeHandlers = {};

	this.parse = function(xmlNode){
		if(xmlNode[jpf.TAGNAME] == "complextype") this.parseComplexType(xmlNode);
		else if(xmlNode[jpf.TAGNAME] == "simpletype") this.parseSimpleType(xmlNode);
		else{
			var nodes = $xmlns(xmlNode, "complextype", jpf.ns.xsd);
			for(var i=0;i<nodes.length;i++) this.parseComplexType(nodes[i]);
			
			var nodes = $xmlns(xmlNode, "simpletype", jpf.ns.xsd);
			for(var i=0;i<nodes.length;i++) this.parseSimpleType(nodes[i]);
		}
	}
	
	this.getValue = function (xmlNode){
		return xmlNode.nodeType == 1 ? jpf.getXmlValue(xmlNode, "text()") : xmlNode.nodeValue;
	}
	
	this.matchType = function(value, type){
		//check if type is type
		if(typeHandlers[type]) return typeHandlers[type](value);
		return true;
	}

	this.parseComplexType = function(xmlNode){
		var func;
		
		custumTypeHandlers[xmlNode.getAttribute("name")] = func;
	}
	
	/* ***************** SIMPLE TYPES *******************/

	/*
		enumeration 	Defines a list of acceptable values 
		fractionDigits Specifies the maximum number of decimal places allowed. Must be equal to or greater than zero 
		length 			Specifies the exact number of characters or list items allowed. Must be equal to or greater than zero 
		maxExclusive 	Specifies the upper bounds for numeric values (the value must be less than this value) 
		maxInclusive 	Specifies the upper bounds for numeric values (the value must be less than or equal to this value) 
		maxLength 		Specifies the maximum number of characters or list items allowed. Must be equal to or greater than zero 
		minExclusive 	Specifies the lower bounds for numeric values (the value must be greater than this value) 
		minInclusive 	Specifies the lower bounds for numeric values (the value must be greater than or equal to this value) 
		minLength 		Specifies the minimum number of characters or list items allowed. Must be equal to or greater than zero 
		pattern 			Defines the exact sequence of characters that are acceptable  
		totalDigits 	Specifies the exact number of digits allowed. Must be greater than zero 
	*/
	var simpleTypeHandler = {
		//Direct childnodes
		"restriction" : function(xmlNode, func){
			func.push("if(!jpf.XSDParser.matchType(value, '" + xmlNode.getAttribute("base") + "')) return false;");

			var nodes = xmlNode.childNodes;
			for(var i=0;i<nodes.length;i++){
				if(simpleTypeHandler[nodes[i][jpf.TAGNAME]])
					simpleTypeHandler[nodes[i][jpf.TAGNAME]](nodes[i], func);
			}
		},
		
		"list" : function(xmlNode, func){
			
		},
		
		"union" : function(xmlNode, func){
			
		},
		
		//Subnodes
		//These should also allow for dates
		"mininclusive" : function(xmlNode, func){
			func.push("if(parseFloat(value) < " + xmlNode.getAttribute("value") + ") return false;");
		},
		"maxinclusive" : function(xmlNode, func){
			func.push("if(parseFloat(value) > " + xmlNode.getAttribute("value") + ") return false;");
		},
		"minexclusive" : function(xmlNode, func){
			func.push("if(parseFloat(value) => " + xmlNode.getAttribute("value") + ") return false;");
		},
		"maxexclusive" : function(xmlNode, func){
			func.push("if(parseFloat(value) =< " + xmlNode.getAttribute("value") + ") return false;");
		},
		//This should also check for list items
		"maxlength" : function(xmlNode, func){
			func.push("if(value.length > " + xmlNode.getAttribute("value") + ") return false;");
		},
		//This should also check for list items
		"minlength" : function(xmlNode, func){
			func.push("if(value.length < " + xmlNode.getAttribute("value") + ") return false;");
		},
		//This should also check for list items
		"length" : function(xmlNode, func){
			func.push("if(value.length != " + xmlNode.getAttribute("value") + ") return false;");
		},
		"fractiondigits" : function(xmlNode, func){ 
			func.push("if(parseFloat(value) == value && value.split('.')[1].length != " + xmlNode.getAttribute("value") + ") return false;");
		}, 
		"totaldigits" : function(xmlNode, func){
			func.push("if(new String(parseFloat(value)).length == " + xmlNode.getAttribute("value") + ") return false;");
		},
		"pattern" : function(xmlNode, func){
			func.push("if(!/^" + xmlNode.getAttribute("value").replace(/(\/|\^|\$)/g, "\\$1") + "$/.test(value)) return false;");
		},
		"enumeration" : function(xmlNode, func){
			if(func.enum_done) return;
			var enum_nodes = $xmlns(xmlNode.parentNode, "enumeration", jpf.ns.xsd);
			func.enum_done = true;
			for(var re=[],k=0;k<enum_nodes.length;k++) re.push(enum_nodes[k].getAttribute("value"));
			func.push("if(!/^(?:" + re.join("|") + ")$/.test(value)) return false;");
		},
		"maxscale" : function(xmlNode, func){
		//http://www.w3.org/TR/2006/WD-xmlschema11-2-20060217/datatypes.html#element-maxScale
			
		},
		"minscale" : function(xmlNode, func){
		//http://www.w3.org/TR/2006/WD-xmlschema11-2-20060217/datatypes.html#element-minScale
			
		}
	}

	this.parseSimpleType = function(xmlNode){
		var func = [];
		func.push("var value = jpf.XSDParser.getValue(xmlNode);");

		var nodes = xmlNode.childNodes;
		for(var i=0;i<nodes.length;i++){
			if(simpleTypeHandler[nodes[i][jpf.TAGNAME]])
				simpleTypeHandler[nodes[i][jpf.TAGNAME]](nodes[i], func);
		}

		func.push("return true;");
		custumTypeHandlers[xmlNode.getAttribute("name")] = new Function('xmlNode', func.join("\n"));
	}

	this.checkType = function(type, xmlNode){
		if(typeHandlers[type]){
			var value = this.getValue(xmlNode);
			return typeHandlers[type](value);
		}
		else if(custumTypeHandlers[type]){
			return custumTypeHandlers[type](xmlNode);
		}
		else{

		}
	}
}

jpf.XSDParser = new jpf.XSDImplementation();
/*FILEHEAD(/in/Core/Crypt/base64.js)SIZE(1203)TIME(1154551076863)*/

/*FILEHEAD(/in/Core/Crypt/blowfish.js)SIZE(22124)TIME(1203730484247)*/

/*FILEHEAD(/in/Core/Crypt/md4.js)SIZE(7274)TIME(1154551076863)*/

/*FILEHEAD(/in/Core/Crypt/md5.js)SIZE(8861)TIME(1154551076863)*/

/*FILEHEAD(/in/Core/Crypt/sha1.js)SIZE(5788)TIME(1154551076863)*/

/*FILEHEAD(/in/TelePort/DeskRun.js)SIZE(6805)TIME(1203730484247)*/

/*FILEHEAD(/in/TelePort/http.js)SIZE(15216)TIME(1213478355856)*/

/**
 * Object allowing for easy non-prototol-specific data 
 * communication from within the browser. (Ajax)
 *
 * @classDescription		This class creates a new Http object
 * @return {Http} Returns a new Http object
 * @type {Http}
 * @constructor
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.4
 */
jpf.http = function(){
	this.queue = [null];
	this.callbacks = {};
	this.cache = {};
	this.timeout = 10000; //default 10 seconds
	if(!this.uniqueId) this.uniqueId = jpf.all.push(this) - 1;
	
	// Register Communication Module
	jpf.Teleport.register(this);
	
	if(!this.toString){
		this.toString = function(){
			return "[Javeline TelePort Component : (HTTP)]";
		}
	}
	
	
	this.loadCache = function(name){
			var strResult = this.get(CWD + name + ".txt");
			
		jpf.status("[HTTP] Loading HTTP Cache", "steleport");
		
		if(!strResult) return false;

		eval("var data = " + strResult);
		this.cache = data.params;
		
		return true;
	}

	this.getXml = function(url, receive, async, userdata, nocache){
		return this.get(url, receive, !!async, userdata, nocache, "", true);
	}

	this.getString = function(url, receive, async, userdata, nocache){
		return this.get(url, receive, !!async, userdata, nocache, "");
	}

	this.get = function(url, receive, async, userdata, nocache, data, useXML, id, autoroute, useXSLT, caching){
		var tpModule = this;
		
		if(data){
			this.protocol = "POST";
			this.contentType = "application/x-www-form-urlencoded";
		}

		if(async === undefined) async = true;
		if(jpf.isOpera) async = true; //opera doesnt support sync calls
		
		if(jpf.isSafari) url = jpf.html_entity_decode(url);
		
		if(jpf.isNot(id)){
			//Caching
			if(this.cache[url] && this.cache[url][data]){
				 var http = {
				 	responseText : this.cache[url][data],
				 	responseXML : {},
				 	status : 200,
				 	isCaching : true
				 }
			}
			else
				var http = jpf.getObject("HTTP");
			
			id = this.queue.push([http, receive, null, null, userdata, null, [url, async, data, nocache, useXSLT, caching], useXML, 0])-1;
			
			if(http.isCaching){
				if(async) return setTimeout("jpf.lookup(" + this.uniqueId + ").receive(" + id + ");", 50);//Math.round(Math.random()*200));
				else return this.receive(id);
			}
		}
		else{
			var http = this.queue[id][0];
			if(http.isCaching) http = jpf.getObject("HTTP");
			else 
				http.abort();
		}

		if(async){
			if(jpf.hasReadyStateBug){
				this.queue[id][3] = new Date();
				this.queue[id][2] = function(){
					var dt = new Date(new Date().getTime() - tpModule.queue[id][3].getTime());
					var diff = parseInt(dt.getSeconds()*1000 + dt.getMilliseconds());
					if(diff > tpModule.timeout){
						tpModule.dotimeout(id); 
						return
					};
					
					if(tpModule.queue[id][0].readyState == 4){
						tpModule.queue[id][0].onreadystatechange = function(){};
						tpModule.receive(id);
					}
				};
				this.queue[id][5] = setInterval(function(){tpModule.queue[id][2]()}, 20);
			}
			else{
				http.onreadystatechange = function(){
					if(!tpModule.queue[id] || http.readyState != 4) return;
					tpModule.receive(id);
				}
			}
		}

		if(!autoroute) autoroute = this.shouldAutoroute;
		if(this.autoroute && jpf.isOpera) autoroute = true; //Bug in opera
		var srv = autoroute ? this.routeServer : url;

		jpf.debugMsg("<strong>Making request[" + id + "] to " + url + (autoroute ? "<br /><span style='color:green'>[via: " + srv + (nocache ? (srv.match(/(\.asp|\.aspx|\.ashx)$/) ? "/" : (srv.match(/\?/) ? "&" : "?")) + Math.random() : "") + "]</span>" : "") + "</strong> with data:<br />" + new String(data && data.xml ? data.xml : data).replace(/\&/g, "&amp;").replace(/</g, "&lt;") + "<hr />", "teleport");
		
		jpf.status("[HTTP] Making request[" + id + "] url: " + url, "teleport");

		try{
			//if(srv.match(/(\.asp|\.aspx|\.ashx)$/)) nocache = false;
			http.open(this.protocol || "GET", srv + (nocache ? (srv.match(/\?/) ? "&" : "?") + Math.random() : ""), async);
			
			//OPERA ERROR's here... on retry
			http.setRequestHeader("User-Agent", "Javeline TelePort 1.0.0");
			http.setRequestHeader("Content-type", this.contentType || (this.useXML || useXML ? "text/xml" : "text/plain"));
			
			if(autoroute){
				http.setRequestHeader("X-Route-Request", url);
				http.setRequestHeader("X-Proxy-Request", url);
				http.setRequestHeader("X-Compress-Response", "gzip");
			}
		}catch(e){
			var useOtherXH = false;
			
			if(self.XMLHttpRequestUnSafe){
				try{
					http = new XMLHttpRequestUnSafe();
					http.onreadystatechange = function(){
						if(!tpModule.queue[id] || http.readyState != 4) return;
						tpModule.receive(id);
					}
					http.open(this.protocol || "GET", srv + (nocache ? (srv.match(/\?/) ? "&" : "?") + Math.random() : ""), async);
					this.queue[id][0] = http;
					async = true; //force async
					useOtherXH = true;
				}
				catch(e){}
			}
			
			// Retry request by routing it
			if(!useOtherXH && this.autoroute && !autoroute){
				if(!jpf.isNot(id)){
					clearInterval(this.queue[id][5]);
					//this.queue[id] = null;
				}
				this.shouldAutoroute = true;
				return this.get(url, receive, async, userdata, nocache, data, useXML, id, true, useXSLT);
			}
			
			if(!useOtherXH){
				//Routing didn't work either... Throwing error
				var noClear = receive ? receive(null, __RPC_ERROR__, {
					userdata : userdata,
					http : http,
					url : url,
					tpModule : this,
					id : id,
					message : "Permission denied accessing remote resource: " + url
				}) : false;
				if(!noClear) this.clearQueueItem(id);
				
				return;
			}
		}

		if(this.__HeaderHook) this.__HeaderHook(http);

			http.send(data);

		if(!async) return this.receive(id);
	}

	this.receive = function(id){
		if(!this.queue[id]) return false;

		clearInterval(this.queue[id][5]);

		var data, message;
		var http = this.queue[id][0];

		// Test if HTTP object is ready
		try{if(http.status){}}catch(e){return setTimeout('jpf.lookup(' + this.uniqueId + ').receive(' + id + ')', 10);}

		var callback = this.queue[id][1];
		var useXML = this.queue[id][7];
		var userdata = this.queue[id][4];
		var retries = this.queue[id][8];
		
		var a = this.queue[id][6];
		var from_url = a[0];
		var useXSLT = a[4];
		
		jpf.debugMsg("<strong>Receiving [" + id + "]" + (http.isCaching ? "[<span style='color:orange'>cached</span>]" : "") + " from " + from_url + "<br /></strong>" + http.responseText.replace(/\&/g, "&amp;").replace(/\</g, "&lt;").replace(/\n/g, "<br />") + "<hr />", "teleport");
		
		jpf.status("[HTTP] Receiving [" + id + "]" + (http.isCaching ? "[caching]" : "") + " from " + from_url, "teleport");

		try{
			var msg = "";

			// Check HTTP Status
			if(http.status != 200 && http.status != 0){
				if(this.isRPC && this.checkPermissions && this.checkPermissions(message, {id:id, http:http, tpModule:this, retries:retries}) === true) return;
				throw new Error(0, "HTTP error [" + id + "]:" + http.status + "\n" + http.responseText);
			}

			// Check for XML Errors
			if(useXML || this.useXML){
				if(http.responseText.replace(/^[\s\n\r]+|[\s\n\r]+$/g, "") == "") throw new Error("Empty Document");
				
				msg = "Received invalid XML\n\n";
				//var lines = http.responseText.split("\n");
				//if(lines[22] && lines[22].match(/Cafco /)) lines[22] = "";
				//lines.join("\n")
				var xmlDoc = http.responseXML && http.responseXML.documentElement ? jpf.xmlParseError(http.responseXML) : jpf.getObject("XMLDOM", http.responseText);
				if(!jpf.supportNamespaces) xmlDoc.setProperty("SelectionLanguage", "XPath");
				var xmlNode = xmlDoc.documentElement;
			}

			// Get content
			var data = useXML || this.useXML ? xmlNode : http.responseText;

			// Check RPC specific Error messages
			if(this.isRPC){
				msg = "RPC result did not validate: ";
				message = this.checkErrors(data, http, {id:id, http:http, tpModule:this});
				if(this.checkPermissions && this.checkPermissions(message, {id:id, http:http, tpModule:this, retries:retries}) === true) return;
				data = this.unserialize(message);
			}
			
			//Use XSLT to transform xml node if needed
			if(useXML && useXSLT){
				var xmlNode = data;
				this.getXml(useXSLT, function(data, state, extra){
					if(state != __HTTP_SUCCESS__){
						if(state == __HTTP_TIMEOUT__ && extra.retries < jpf.maxHttpRetries) return extra.tpModule.retry(extra.id);
						else{
							extra.userdata.message = "Could not load XSLT from external resource :\n\n" + extra.message;
							extra.userdata.callback(data, state, extra.userdata);
						}
					}

					var result = xmlNode.transformNode(data);
					
					var noClear = extra.userdata.callback ? extra.userdata.callback([result, xmlNode], __RPC_SUCCESS__, extra.userdata) : false;
					if(!noClear) extra.tpModule.queue[id] = null;
				}, true, {
					callback : callback,
					userdata : userdata,
					http : http,
					url : from_url,
					tpModule : this,
					id : id,
					retries : retries
				});
				
				return;
			}
		}
		catch(e){
			// Send callback error state
			var noClear = callback ? callback(data, __RPC_ERROR__, {
				userdata : userdata,
				http : http,
				url : from_url,
				tpModule : this,
				id : id,
				message : msg + e.message,
				retries : retries
			}) : false;
			if(!noClear){
				http.abort();
				this.clearQueueItem(id);
			}

			return;
		}
		
		//Caching
		if(a[5]){
			if(!this.cache[from_url]) this.cache[from_url] = {};
			this.cache[from_url][a[2]] = http.responseText;
		}

		var noClear = callback ? callback(data, __RPC_SUCCESS__, {
			userdata : userdata,
			http : http,
			url : from_url,
			tpModule : this,
			id : id,
			retries : retries
		}) : false;
		if(!noClear) this.clearQueueItem(id);

		return data;
	}

	this.dotimeout = function(id){
		if(!this.queue[id]) return false;

		clearInterval(this.queue[id][5]);
		var http = this.queue[id][0];

		// Test if HTTP object is ready
		try{if(http.status){}}catch(e){return setTimeout('HTTP.dotimeout(' + id + ')', 10);}

		var callback = this.queue[id][1];
		var useXML = this.queue[id][7];
		var userdata = this.queue[id][4];

		http.abort();

		jpf.debugMsg("<strong>HTTP Timeout [" + id + "]<br /></strong><hr />", "teleport");
		
		jpf.status("[HTTP] Timeout [" + id + "]", "teleport");

		var noClear = callback ? callback(null, __RPC_TIMEOUT__, {
			userdata : userdata,
			http : http,
			url : this.queue[id][6][0],
			tpModule : this,
			id : id,
			message : "HTTP Call timed out",
			retries : this.queue[id][8]
		}) : false;
		if(!noClear) this.clearQueueItem(id);
	}
	
	this.clearQueueItem = function(id){
		if(!this.queue[id]) return false;
		
		if(jpf.hasReadyStateBug) clearInterval(this.queue[id][5]);
		jpf.releaseHTTP(this.queue[id][0]);
		this.queue[id] = null;
		delete this.queue[id];
		
		return true;
	}

	this.retry = function(id){
		if(!this.queue[id]) return false;

		clearInterval(this.queue[id][5]);
		var q = this.queue[id];
		var a = q[6];

		jpf.debugMsg("<strong>Retrying request...<br /></strong><hr />", "teleport");
		
		jpf.status("[HTTP] Retrying request [" + id + "]", "teleport");

		q[8]++;
		this.get(a[0], q[1], a[1], q[4], a[3], a[2], q[7], id, null, null, a[5]);
		
		return true;
	}

	this.cancel = function(id){
		if(id === null) id = this.queue.length-1;
		if(!this.queue[id]) return false;
		
		//this.queue[id][0].abort();
		this.clearQueueItem(id);
	}

	if(!this.load){
		this.load = function(x){
			var receive = x.getAttribute("receive");
			
			for(var i=0;i<x.childNodes.length;i++){
				if(x.childNodes[i].nodeType != 1) continue;
				
				var useXML = x.childNodes[i].getAttribute("type") == "XML";
				var url = x.childNodes[i].getAttribute("url");
				var receive = x.childNodes[i].getAttribute("receive") || receive;
				var async = x.childNodes[i].getAttribute("async") != "false";
				
				this[x.childNodes[i].getAttribute("name")] = function(data, userdata){
					return this.get(url, self[receive], async, userdata, false, data, useXML);
				}
			}
		}
		
		this.instantiate = function(x){
			var url = x.getAttribute("src");
			var useXSLT = x.getAttribute("xslt");
			var async = x.getAttribute("async") != "false";

			this.getURL = function(data, userdata){
				return this.get(url, this.callbacks.getURL, async, userdata, false, data, true, null, null, useXSLT);
			}
			
			var name = "http" + Math.round(Math.random()*100000);
			jpf.setReference(name, this);
			
			return name + ".getURL()";
		}
		
		this.call = function(method, args){
			this[method].call(this, args);
		}
	}
}

//Init.addConditional(function(){jpf.Comm.register("http", "variables", HTTP);}, null, ['Kernel']);
jpf.Init.run('HTTP');
/*FILEHEAD(/in/TelePort/iframe.js)SIZE(3146)TIME(1203730484247)*/
jpf.Init.run('XMLDatabaseImplementation');
/*FILEHEAD(/in/TelePort/poll.js)SIZE(3521)TIME(1203730484247)*/

/*FILEHEAD(/in/TelePort/RPC/get.js)SIZE(4469)TIME(1213483123975)*/

/**
 * Implementation of the HTTP GET protocol (CGI).
 *
 * @classDescription		This class creates a new HTTP GET TelePort module.
 * @return {Get} Returns a new HTTP GET TelePort module.
 * @type {Get}
 * @constructor
 * 
 * @addenum rpc[@protocol]:get
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.4
 */
jpf.get = function(){
	this.supportMulticall = false;
	this.protocol = "GET";
	this.vartype = "cgi";
	this.isXML = true;
	this.namedArguments = true;

	// Register Communication Module
	jpf.Teleport.register(this);

	// Stand Alone
	if(!this.uniqueId){
		jpf.makeClass(this);
		this.inherit(jpf.BaseComm); /** @inherits jpf.BaseComm */
		this.inherit(jpf.http); /** @inherits jpf.http */
		this.inherit(jpf.rpc); /** @inherits jpf.rpc */
	}

	this.unserialize = function(str){
		return str;
	}

	this.getSingleCall = function(name, args, obj){
		//var args2={};for(var i = 0;i<args.length;i++)args2[args[i][0]]=args[i][1];
		obj.push(args);
	}
	
	// Create message to send
	this.serialize = function(functionName, args){
		if(justUseUrl){
			this.URL = this.urls[functionName];
			return "";
		}
		
		var vars = [];

		function recur(o,stack){
			if(jpf.isArray(o)){
				for(var j=0;j<o.length;j++) recur(o[j],stack+"%5B"+j+"%5D");
			}
			else if(typeof o == "object"){
				for(prop in o){
					
					if(typeof o[prop] == "function") continue;
					recur(o[prop],stack+"%5B" + encodeURIComponent(prop) + "%5D");	
				}
			}
			else vars.push(stack+"="+o);
		};

		if(this.multicall){
			vars.push("func="+this.mcallname);
			for(var i=0; i < args[0].length; i++ )
				recur( args[0][i], "f%5B"+i+"%5D" );
		}
		else{
			for(prop in args){
				
				recur(args[prop], prop);
			}
		}
				
		if(!this.BaseURL) this.BaseURL = this.URL;
		var nUrl = this.urls[functionName] ? this.urls[functionName] : this.BaseURL;
		this.URL = nUrl + (vars.length ? (nUrl.match(/\?/) ? "&" : "?") + vars.join("&") : "");

		return "";
	}

	// Check Received Data for errors
	this.checkErrors = function(data, http){
		return data;
	}

	this.__load = function(x){
		if(x.getAttribute("method-name")){
			var mName = x.getAttribute("method-name");
			var nodes = x.childNodes;

			for(var i=0;i<nodes.length;i++){
				var y = nodes[i];
				var v = y.insertBefore(x.ownerDocument.createElement("variable"), y.firstChild);
				v.setAttribute("name", mName);
				v.setAttribute("value", y.getAttribute("name"));
			}
		}
	}
	
	/**
	 * Submit a form with ajax (GET)
	 *
	 * @param form	 form
	 * @param function callback  Called when http result is received
	 */
   this.submitForm = function(form, callback){
		if(!this['postform']) this.addMethod('postform', callback);
		
		var args = [];       
		for (var i=0; i<form.elements.length; i++) {
		   if (!form.elements[i].name) continue;
		   if (form.elements[i].tagname = 'input' && (form.elements[i].type == 'checkbox' || form.elements[i].type == 'radio') && !form.elements[i].checked) continue;
		  
		   if (form.elements[i].tagname = 'select' && form.elements[i].multiple) {
		       for (j=0; j<form.elements[i].options.length; j++) {
		           if (form.elements[i].options[j].selected) 
		           	args.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].options[j].value));
		       }
		   }
		   else{
		       args.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value));
		   }
		}
		
		var loc = (form.action || location.href);
		this.urls['postform'] = loc + (loc.indexOf("?") > -1 ? "&" : "?") + args.join("&");
		this['postform'].call(this);
		
		return false;
   }
    
   var justUseUrl;
   this.callWithString = function(func, str, callback){
    	this.setCallback(func, callback)
    	var original_url = this.urls[func];
    	
    	justUseUrl = true;
    	this.urls[func] = this.urls[func] + (this.urls[func].indexOf("?") > -1 ? "&" : "?") + str;
    	this[func].call(this);
    	
    	justUseUrl = false;
    	this.urls[func] = original_url;
   }
}

/*FILEHEAD(/in/TelePort/RPC/header.js)SIZE(1572)TIME(1203730484247)*/

/**
 * @constructor
 */
jpf.header = function(){
	this.supportMulticall = false;
	this.protocol = "GET";
	this.vartype = "header";
	this.isXML = true;
	this.namedArguments = true;

	// Register Communication Module
	jpf.Teleport.register(this);

	// Stand Alone
	if(!this.uniqueId){
		jpf.makeClass(this);
		this.inherit(jpf.BaseComm); /** @inherits jpf.BaseComm */
		this.inherit(jpf.http); /** @inherits jpf.http */
		this.inherit(jpf.rpc); /** @inherits jpf.rpc */
	}

	this.unserialize = function(str){
		return str;
	}

	// Create message to send
	this.serialize = function(functionName, args){
		for(var hFunc=[],i=0;i<args.length;i++){
	   	if(!args[i][0] || !args[i][1]) continue;

			jpf.debugMsg("<strong>" + args[i][0] + ":</strong> " + args[i][1] + "<br />", "teleport");

   		http.setRequestHeader(args[i][0], args[i][1]);
	   }
	   
	   this.__HeaderHook = new Function('http', hFunc.join("\n"));

		return "";
	}

	// Check Received Data for errors
	this.checkErrors = function(data, http){
		return data;
	}

	this.__load = function(x){
		if(x.getAttribute("method-name")){
			var mName = x.getAttribute("method-name");
			var nodes = x.childNodes;

			for(var i=0;i<nodes.length;i++){
				var y = nodes[i];
				var v = y.insertBefore(x.ownerDocument.createElement("variable"), y.firstChild);
				v.setAttribute("name", mName);
				v.setAttribute("value", y.getAttribute("name"));
			}
		}
	}
}

/*FILEHEAD(/in/TelePort/RPC/jphp.js)SIZE(3149)TIME(1203730484247)*/

/**
 * @constructor
 */
jpf.jphp = function(){
	this.supportMulticall = true;
	this.multicall = false;
	this.mcallname = "multicall";
	this.protocol = "POST";
	this.useXML = true;
	this.namedArguments = false;

	// Register Communication Module
	jpf.Teleport.register(this);

	// Stand Alone
	if(!this.uniqueId){
		jpf.makeClass(this);
		this.inherit(jpf.BaseComm); /** @inherits jpf.BaseComm */
		this.inherit(jpf.http); /** @inherits jpf.http */
		this.inherit(jpf.rpc); /** @inherits jpf.rpc */
	}

	// Serialize Objects
	var serialize = {
		host : this,
		
		object : function(ob){
			var ob = ob.valueOf();

			var length = 0, x = "";
			for(prop in ob){
				if(typeof this[prop] != "function"){
					length++;
					//WEIRD FUCKED UP INTERNET EXPLORER BUG
					var r = prop;
					x += this.host.doSerialize(r) + ";" + this.host.doSerialize(ob[r]) + (typeof ob[r] == "object" || typeof ob[r] == "array" ? "" : ";");
				}
			}

			if(ob.className) return "O:" + ob.className.length + ":\"" + ob.className + "\":" + length + ":{" + x.substr(0, x.length) + "}";
			return "a:" + length + ":{" + x.substr(0, x.length) + "}";
		},

		string : function(str){
			var str = str.replace(/[\r]/g, "");
			str = str.replace(/\]\]/g, "\]-\]-\]").replace(/\]\]/g, "\]-\]-\]");
			return "s:" + str.length + ":\"" + str + "\"";
		},

		number : function(nr){
			if(nr == parseInt(nr))
				return "i:" + nr;
			else if(nr == parseFloat(nr))
				return "d:" + nr;
			else
				return this["boolean"](false);
		},

		"boolean" : function(b){
			return "b:" + (b == true ? 1 : 0);
		},

		array : function(ar){
			var x = "a:" + ar.length + ":{";
			for(var i=0;i<ar.length;i++)
				x += "i:" + i + ";" + this.host.doSerialize(ar[i]) + (i < ar.length && typeof ar[i] != "object" && typeof ar[i] != "array" ? ";" : "");

			return x + "}";
		}
	}

	this.unserialize = function(str){
		return eval(str.replace(/\|-\|-\|/g, "]]").replace(/\|\|\|/g, "\\n"));
	}

	this.doSerialize = function(args){
		if(typeof args == "function"){
			throw new Error(0, "Cannot Parse functions");
		}
		else if(jpf.isNot(args))
			return serialize["boolean"](false);

		return serialize[args.dataType || "object"](args);
	}

	// Create message to send
	this.serialize = function(functionName, args){
  		//Construct the XML-RPC message
  		var message = "<?xml version='1.0' encoding='UTF-16'?><run m='" + functionName + "'><![CDATA[";
  		//for(i=0;i<args.length;i++){
  			message += this.doSerialize(args);
  		//}

  		return message + "]]></run>";
  	}

	// Check Received Data for errors
	this.checkErrors = function(data, http){
   	//handle method result
      if(data && data.tagName == "data"){
      	data = data.firstChild.nodeValue;

			//error handling
			if(data && data[0] == "error") throw new Error(10, data[1]);
		}
		else throw new Error(1083, jpf.formErrorString(1083, null, "Checking for errors", "Malformed RPC Message: Parse Error\n\n:'" + http.responseText + "'"));

		return data;
	}
}

/*FILEHEAD(/in/TelePort/RPC/jsonrpc.js)SIZE(2967)TIME(1213478355856)*/

// Serialize Objects
jpf.JSONSerialize = {
	object : function(o){
		var str = [];
		for(var prop in o){
			str.push('"' + prop.replace(/(["\\])/g, '\\$1') + '": ' + jpf.serialize(o[prop]));
		}

		return "{" + str.join(", ") + "}";
	},

	string : function(s){
		s = '"' + s.replace(/(["\\])/g, '\\$1') + '"';
		return s.replace(/(\n)/g, "\\n").replace(/\r/g, "");
	},

	number : function(i){
		return i.toString();
	},

	"boolean" : function(b){
		return b.toString();
	},

	date : function(d){
		var padd = function(s, p){
			s=p+s;
			return s.substring(s.length - p.length);
		};
		var y = padd(d.getUTCFullYear(), "0000");
		var m = padd(d.getUTCMonth() + 1, "00");
		var d = padd(d.getUTCDate(), "00");
		var h = padd(d.getUTCHours(), "00");
		var min = padd(d.getUTCMinutes(), "00");
		var s = padd(d.getUTCSeconds(), "00");

		var isodate = y +  m  + d + "T" + h +  ":" + min + ":" + s;

		return '{"jsonclass":["sys.ISODate", ["' + isodate + '"]]}';
	},

	array : function(a){
		for(var q=[],i=0;i<a.length;i++)
			q.push(jpf.serialize(a[i]));

		return "[" + q.join(", ") + "]";
	}
}

/**
 * @todo allow for XML serialization
 */
jpf.serialize = function(args){
	if(typeof args == "function" || jpf.isNot(args))
		return "null";
	return jpf.JSONSerialize[args.dataType || "object"](args);
}

/**
 * Implementation of the JSON-RPC protocol.
 *
 * @classDescription		This class creates a new JSON-RPC TelePort module.
 * @return {JsonRpc} Returns a new JSON-RPC TelePort module.
 * @type {JsonRpc}
 * @constructor
 *
 * @addenum rpc[@protocol]:jsonrpc
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.4
 */
jpf.jsonrpc = function(){
	this.supportMulticall = false;
	this.multicall = false;

	this.protocol = "POST";
	this.useXML = false;
	this.id = 0;
	this.namedArguments = false;

	// Register Communication Module
	jpf.Teleport.register(this);


	// Stand Alone
	if(!this.uniqueId){
		jpf.makeClass(this);
		this.inherit(jpf.BaseComm); /** @inherits jpf.BaseComm */
		this.inherit(jpf.http); /** @inherits jpf.http */
		this.inherit(jpf.rpc); /** @inherits jpf.rpc */
	}
	
	this.getSingleCall = function(name, args, obj){
		obj.push({method: name, params: args});
	}

	// Create message to send
	this.serialize = function(functionName, args){
		this.fName = functionName;
		this.id++;

  		//Construct the XML-RPC message
  		var message = '{"method":"' + functionName + '","params":' + jpf.serialize(args) + ',"id":' + this.id + '}';
  		return message;
  	}

  	this.__HeaderHook = function(http){
  		http.setRequestHeader('X-JSON-RPC', this.fName);
  	}

	this.unserialize = function(str){
		var obj = eval('obj=' + str);
		return obj.result;
	}

	// Check Received Data for errors
	this.checkErrors = function(data, http){
		return data;
	}
}

/*FILEHEAD(/in/TelePort/RPC/jsop.js)SIZE(1696)TIME(1203730484247)*/

/**
 * @constructor
 */
jpf.jsop = function(){
	this.supportMulticall = false;
	this.multicall = false;
	this.mcallname = "system.multicall";
	this.protocol = "POST";
	this.useXML = false;
	this.id = 0;
	this.namedArguments = true;

	// Register Communication Module
	jpf.Teleport.register(this);

	// Stand Alone
	if(!this.uniqueId){
		jpf.makeClass(this);
		this.inherit(jpf.BaseComm); /** @inherits jpf.BaseComm */
		this.inherit(jpf.http); /** @inherits jpf.http */
		this.inherit(jpf.rpc); /** @inherits jpf.rpc */
	}
	
	this.getSingleCall = function(name, args, obj){
		var o = {};
		o[name] = args;//vars;
		obj.push(o);
	}

	// Create message to send
	this.serialize = function(functionName, args){
		this.fName = functionName;
		this.id++;
		
		//Construct the XML-RPC message
		if(this.multicall){
			return jpf.serialize(args[0]);
		}
		else{
			var o = {};
			o[functionName] = args;
			return jpf.serialize(o);
		}
  	}

  	this.__HeaderHook = function(http){
  		http.setRequestHeader('Accept', 'text/javascript, text/html, application/xml, text/xml, */*');
  		http.setRequestHeader('x-requested-with', 'XMLHttpRequest');
  		http.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
  		//http.setRequestHeader('X-JSON-RPC', this.fName);
  	}

	this.unserialize = function(str){
		return str;
		var obj = eval('obj=' + str);
		return obj.result;
	}

	// Check Received Data for errors
	// Check Received Data for errors
	this.checkErrors = function(data, http, extra){
		return jpf.XMLDatabase.getXml(data, true);
	}
}

/*FILEHEAD(/in/TelePort/RPC/post.js)SIZE(4122)TIME(1203730484247)*/

/**
 * Implementation of the HTTP POST protocol (CGI).
 *
 * @classDescription		This class creates a new HTTP POST TelePort module.
 * @return {Post} Returns a new HTTP POST TelePort module.
 * @type {Post}
 * @constructor
 *
 * @addenum rpc[@protocol]:post
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.4
 */
jpf.post = function(){
	this.supportMulticall = true;
	this.mcallname = "multicall";
	this.multicall = false;
	this.protocol = "POST";
	this.vartype = "cgi";
	this.isXML = true;
	this.namedArguments = true;
	this.contentType = "application/x-www-form-urlencoded";

	// Register Communication Module
	jpf.Teleport.register(this);

	// Stand Alone
	if(!this.uniqueId){
		jpf.makeClass(this);
		this.inherit(jpf.BaseComm); /** @inherits jpf.BaseComm */
		this.inherit(jpf.http); /** @inherits jpf.http */
		this.inherit(jpf.rpc); /** @inherits jpf.rpc */
	}

	this.unserialize = function(str){
		return str;
	}
	
	this.__HeaderHook = function(http){
	}
	
	this.getSingleCall = function(name, args, obj){
		//var args2={};for(var i = 0;i<args.length;i++)args2[args[i][0]]=args[i][1];
		obj.push(args);
	}
	
	// Create message to send
	this.serialize = function(functionName, args){
		//functionName == 'postform' && 
		if(postVars){
			var v = postVars; postVars = null;
			this.URL = this.urls[functionName];
			return v;
		}
		
		var vars = [];

		function recur(o,stack){
			if(jpf.isArray(o)){
				for(var j=0;j<o.length;j++) recur(o[j],stack+"%5B"+j+"%5D");
			}
			else if(typeof o == "object"){
				for(prop in o){
					if(typeof o[prop] == "function") continue;
					recur(o[prop],stack+"%5B" + encodeURIComponent(prop) + "%5D");	
				}
			}
			else vars.push(stack+"="+o);
		};

		if(this.multicall){
			vars.push("func="+this.mcallname);
			for(var i=0; i < args[0].length; i++ )
				recur( args[0][i], "f%5B"+i+"%5D" );
		}
		else{
			for(prop in args)
				recur(args[prop], prop);
		}
				
		if( !this.BaseURL ) this.BaseURL = this.URL;
		this.URL = this.urls[functionName] ? this.urls[functionName] : this.BaseURL;

		return vars.join("&");
	}

	// Check Received Data for errors
	this.checkErrors = function(data, http){
		return data;
	}

	/**
	 * @define rpc
	 * @attribute method-name 
	 */
	this.__load = function(x){
		if(x.getAttribute("method-name")){
			var mName = x.getAttribute("method-name");
			var nodes = x.childNodes;

			for(var i=0;i<nodes.length;i++){
				if(nodes[i].nodeType != 1) continue;
				var y = nodes[i];
				var v = y.insertBefore(x.ownerDocument.createElement("variable"), y.firstChild);
				v.setAttribute("name", mName);
				v.setAttribute("value", y.getAttribute("name"));
			}
		}
	}
	
	/**
	 * Submit a form with ajax (POST)
	 *
	 * @param form	 form
	 * @param function callback  Called when http result is received
	 */
	var postVars;
	this.submitForm = function(form, callback){
		if(!this['postform']) this.addMethod('postform', callback);

		var args = [];
		for (var i=0; i<form.elements.length; i++) {
			if (!form.elements[i].name) continue;
			if (form.elements[i].tagName = 'input' && (form.elements[i].type == 'checkbox' || form.elements[i].type == 'radio') && !form.elements[i].checked) continue;
			
			if (form.elements[i].tagName = 'select' && form.elements[i].multiple) {
				for (j=0; j<form.elements[i].options.length; j++) {
					if (form.elements[i].options[j].selected) 
						args.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].options[j].value));
				}
			}
			else {
				args.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value));
			}
		}
		
		this.urls['postform'] = form.action || location.href;
		postVars = args.join("&");
		this['postform'].call(this);
		
		return false;
	}
	
   this.callWithString = function(func, str, callback){
		//this.urls[func] = url;
		this.setCallback(func, callback)
		postVars = str;
		this[func].call(this);
   }
}

/*FILEHEAD(/in/TelePort/RPC/soap.js)SIZE(7418)TIME(1205790104099)*/

/**
 * Implementation of the SOAP RPC protocol.
 *
 * @classDescription		This class creates a new SOAP TelePort module.
 * @return {Soap} Returns a new SOAP TelePort module.
 * @type {Soap}
 * @constructor
 *
 * @addenum rpc[@protocol]:soap
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.4
 */
jpf.soap = function(){
	this.supportMulticall = false;
	this.protocol = "POST";
	this.useXML = true;

	this.nsName = "m";
	this.nsURL = "http://www.javeline.org";
	
	this.namedArguments = true;

	// Register Communication Module
	jpf.Teleport.register(this);

	// Stand Alone
	if(!this.uniqueId){
		jpf.makeClass(this);
		this.inherit(jpf.BaseComm); /** @inherits jpf.BaseComm */
		this.inherit(jpf.http); /** @inherits jpf.http */
		this.inherit(jpf.rpc); /** @inherits jpf.rpc */
	}

	// Serialize Objects
	var serialize = {
		host : this,

		object : function(o){
			var wo = o;//.valueOf();

			for(prop in wo){
				if(typeof wo[prop] != "function" && prop != "type"){
					retstr += this.host.doSerialize(wo[prop], prop);
				}
			}

			return retstr;
		},

		string : function(s){
			return s.replace(/\]\]/g, "] ]");//"<![CDATA[" + s.replace(/\]\]/g, "] ]") + "]]>";
		},

		number : function(i){
			return i;
		},

		"boolean" : function(b){
			return b == true ? 1 : 0;
		},

		date : function(d){
			//Could build in possibilities to express dates
			//in weeks or other iso8601 possibillities
			//hmmmm ????
			//19980717T14:08:55
			return doYear(d.getUTCYear()) + doZero(d.getMonth()) + doZero(d.getUTCDate()) + "T" + doZero(d.getHours()) + ":" + doZero(d.getMinutes()) + ":" + doZero(d.getSeconds());

			function doZero(nr) {
				nr = String("0" + nr);
				return nr.substr(nr.length-2, 2);
			}

			function doYear(year) {
				if(year > 9999 || year < 0)
					XMLRPC.handleError(new Error("Unsupported year: " + year));

				year = String("0000" + year)
				return year.substr(year.length-4, 4);
			}
		},

		array : function(a){
			var retstr = "";
			for(var i=0;i<a.length;i++)
				retstr += this.host.doSerialize(a[i], "item");

			return retstr;
		}
	}

	this.doSerialize = function(args, name){
		var c = name ? args : args[1];
		var name = name ? name : args[0];

		if(typeof c == "function") throw new Error(0, "Cannot Parse functions");

		if(c === false)
			return '<' + name + ' xsi:null="1"/>';
		else
			return '<' + name + ' ' + this.getXSIType(c) + '>' + serialize[c.dataType || "object"](c) + '</' + name + '>';
	}

	// get xsi:type
	this.getXSIType = function(c){
		if(!c.dataType) return '';
		else if(c.dataType == "array")
			return 'xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="xsd:ur-type[' + c.length + ']"';
		else if(c.dataType == "number")
			return 'xsi:type="' + (parseInt(c) == c ? "xsd:int" : "xsd:float") + '"';
		else if(c.dataType == "data")
			return 'xsi:type="xsd:timeInstant"';
		else
			return 'xsi:type="xsd:' + c.dataType + '"';
	}

	// Create message to send
	this.serialize = function(functionName, args){
  		//Construct the SOAP message

  		var message = '<?xml version="1.0"?>' +
		'<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/1999/XMLSchema" xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance">' +
		'<SOAP-ENV:Body>' +
		'<' + this.nsName + ':' + functionName + ' xmlns:' + this.nsName + '="' + this.nsURL + '">'

   	for(var i=0;i<args.length;i++){
   		message += this.doSerialize(args[i]);
		}

		message += '</' + this.nsName + ':' + functionName + '></SOAP-ENV:Body></SOAP-ENV:Envelope>';

  		return message;
  	}

  	this.__HeaderHook = function(http){
  		http.setRequestHeader('SOAPAction', '"' + this.URL.replace(/http:\/\/.*\/([^\/]*)$/, "$1") + '"');
  	}

	this.unserialize = function(data){
		return data;
		var ret, i;

		//xsi:type
		var type = data.getAttribute("xsi:type");
		switch(type){
			case "xsd:string":
				return (data.firstChild) ? new String(data.firstChild.nodeValue) : "";
			break;
			case "xsd:int":
			case "xsd:double":
			case "xsd:float":
				return (data.firstChild) ? new Number(data.firstChild.nodeValue) : 0;
			break;
			case "xsd:timeInstant":
				/*
				Have to read the spec to be able to completely
				parse all the possibilities in iso8601
				07-17-1998 14:08:55
				19980717T14:08:55
				*/

				var sn = jpf.dateSeparator;

				if(/^(\d{4})(\d{2})(\d{2})T(\d{2}):(\d{2}):(\d{2})/.test(data.firstChild.nodeValue)){;//data.text)){
	      		return new Date(RegExp.$2 + sn + RegExp.$3 + sn +
	      							RegExp.$1 + " " + RegExp.$4 + ":" +
	      							RegExp.$5 + ":" + RegExp.$6);
	      	}
	    		else{
	    			return new Date();
	    		}

			break;
			case "xsd:boolean":
				return Boolean(isNaN(parseInt(data.firstChild.nodeValue)) ? (data.firstChild.nodeValue == "true") : parseInt(data.firstChild.nodeValue))

			break;
			case "SOAP-ENC:base64":
				return jpf.decodeBase64(data.firstChild.nodeValue);
			break;
			case "SOAP-ENC:Array":
				var nodes = data.childNodes;

				ret = new Array();
				for(var i=0;i<nodes.length;i++){
					if(nodes[i].nodeType != 1) continue;
     				ret.push(this.unserialize(nodes[i]));
     			}

				return ret;

			break;
			default:
				//Custom Type
				if(type && !self[type]) throw new Error(1084, jpf.formErrorString(1084, null, "SOAP", "Invalid Object Specified in SOAP message: " + type));

				var nodes = data.childNodes;
				var o = type ? new self[type] : {};

				ret = new Array();
				for(var i=0;i<nodes.length;i++){
					if(nodes[i].nodeType != 1) continue;
     				ret[nodes[i].tagName] = this.unserialize(nodes[i]);
     			}

				return ret;
			break;
		}
	}

	// Check Received Data for errors
	this.checkErrors = function(data, http){
		/*var fault = data.selectSingleNode("Fault");
		if(fault){
			var nr = fault.selectSingleNode("faultcode/text()").nodeValue;
			var msg = "\n" + fault.selectSingleNode("faultstring/text()").nodeValue;
			throw new Error(nr, msg);
		}

		else if(data.getElementsByTagName("Errors")){
			var fault = data.getElementsByTagName("Errors")[0];
			var nr = fault.selectSingleNode("node()/node()/text()").nodeValue;
			var msg = "\n" + fault.selectSingleNode("node()/node()[2]/text()").nodeValue;
			throw new Error(nr, msg);
		}*/

		// IE Hack
		if(!jpf.supportNamespaces)
			data.ownerDocument.setProperty("SelectionNamespaces", "xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xds='http://www.w3.org/2001/XMLSchema' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'");

		rvalue = data.getElementsByTagName("SOAP-ENV:Body")[0];///node()/node()[2]
		if(!rvalue && data.getElementsByTagNameNS) rvalue = data.getElementsByTagNameNS("http://schemas.xmlsoap.org/soap/envelope/", "Body")[0]

		return rvalue;
	}

	/**
	 * @define rpc
	 * @attribute ns-name 
	 * @attribute ns-url 
	 */
	this.__load = function(x){
		if(x.getAttribute("ns-name")) this.nsName = x.getAttribute("ns-name");
		if(x.getAttribute("ns-url")) this.nsURL = x.getAttribute("ns-url");
	}
}

/*FILEHEAD(/in/TelePort/RPC/xmlp.js)SIZE(1754)TIME(1203730484247)*/

/**
 * @constructor
 */
jpf.xmlp = function(){
	this.supportMulticall = false;
	this.multicall = false;
	this.mcallname = "system.multicall";
	this.protocol = "POST";
	this.useXML = false;
	this.id = 0;
	this.namedArguments = false;

	// Register Communication Module
	jpf.Teleport.register(this);

	// Stand Alone
	if(!this.uniqueId){
		jpf.makeClass(this);
		this.inherit(jpf.BaseComm); /** @inherits jpf.BaseComm */
		this.inherit(jpf.http); /** @inherits jpf.http */
		this.inherit(jpf.rpc); /** @inherits jpf.rpc */
	}
	
	this.getSingleCall = function(name, args, obj){
		obj.push("<" + name + ">" + (args[0] ? (typeof args[0] == "string" ? args[0] : args[0].xml.replace(/^<[^>]*>/,"").replace(/<[^>]*>$/,"")) : "") + "</" + name + ">");
		return obj;
	}

	// Create message to send
	this.serialize = function(functionName, args){
		this.fName = functionName;
		this.id++;
		
		//Construct the XML-RPC message
		if(this.multicall){
			return "<Nbd>" + args[0].join("") + "</Nbd>";
		}
		else{
			return "<Nbd>" + this.getSingleCall(functionName, args, [])[0] + "</Nbd>";
		}
  	}

  	this.__HeaderHook = function(http){
  		http.setRequestHeader('Accept', 'text/javascript, text/html, application/xml, text/xml, */*');
  		http.setRequestHeader('x-requested-with', 'XMLHttpRequest');
  		http.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
  		//http.setRequestHeader('X-JSON-RPC', this.fName);
  	}

	this.unserialize = function(str){
		return str;
	}

	// Check Received Data for errors
	this.checkErrors = function(data, http, extra){
		return jpf.XMLDatabase.getXml(data, true);
	}
}

/*FILEHEAD(/in/TelePort/RPC/xmlrpc.js)SIZE(7254)TIME(1205790104099)*/

/**
 * Implementation of the XML-RPC protocol.
 *
 * @classDescription		This class creates a new XML-RPC TelePort module.
 * @return {XmlRpc} Returns a new XML-RPC TelePort module.
 * @type {XmlRpc}
 * @constructor
 *
 * @addenum rpc[@protocol]:xmlrpc
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.4
 */
jpf.xmlrpc = function(){
	this.supportMulticall = true;
	this.multicall = false;
	this.mcallname = "system.multicall";
	this.protocol = "POST";
	this.useXML = true;
	
	this.namedArguments = false;

	// Register Communication Module
	jpf.Teleport.register(this);

	// Stand Alone
	if(!this.uniqueId){
		jpf.makeClass(this);
		this.inherit(jpf.BaseComm); /** @inherits jpf.BaseComm */
		this.inherit(jpf.http); /** @inherits jpf.http */
		this.inherit(jpf.rpc); /** @inherits jpf.rpc */
	}

	// Serialize Objects
	var serialize = {
		host : this,

		object : function(o){
			var wo = o;//.valueOf();

			retstr = "<struct>";

			for(prop in wo){
				if(typeof wo[prop] != "function" && prop != "type"){
					retstr += "<member><name>" + prop + "</name><value>" + this.host.doSerialize(wo[prop]) + "</value></member>";
				}
			}
			retstr += "</struct>";

			return retstr;
		},

		string : function(s){
			//<![CDATA[***your text here***]]>
			//return "<string><![CDATA[" + s.replace(/\]\]\>/g, "").replace(/\<\!\[\CDATA\[/g, "") + "]]></string>";//.replace(/</g, "&lt;").replace(/&/g, "&amp;")
			return "<string><![CDATA[" + s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;") + "]]></string>";
			//var str = "<string>" + s.replace(/\&/g, "&amp;").replace(/\</g, "&lt;").replace(/\>/g, "&gt;") + "</string>";//.replace(/</g, "&lt;").replace(/&/g, "&amp;")
			return str;
		},

		number : function(i){
			if(i == parseInt(i)){
				return "<int>" + i + "</int>";
			}
			else if(i == parseFloat(i)){
				return "<double>" + i + "</double>";
			}
			else{
				return this["boolean"](false);
			}
		},

		"boolean" : function(b){
			if(b == true) return "<boolean>1</boolean>";
			else return "<boolean>0</boolean>";
		},

		date : function(d){
			//Could build in possibilities to express dates
			//in weeks or other iso8601 possibillities
			//hmmmm ????
			//19980717T14:08:55
			return "<dateTime.iso8601>" + doYear(d.getUTCYear()) + doZero(d.getMonth()) + doZero(d.getUTCDate()) + "T" + doZero(d.getHours()) + ":" + doZero(d.getMinutes()) + ":" + doZero(d.getSeconds()) + "</dateTime.iso8601>";

			function doZero(nr) {
				nr = String("0" + nr);
				return nr.substr(nr.length-2, 2);
			}

			function doYear(year) {
				if(year > 9999 || year < 0)
					XMLRPC.handleError(new Error(1085, jpf.formErrorString(1085, null, "XMLRPC serialization", "Unsupported year: " + year)));

				year = String("0000" + year)
				return year.substr(year.length-4, 4);
			}
		},

		array : function(a){
			var retstr = "<array><data>";
			for(var i=0;i<a.length;i++){
				retstr += "<value>";
				retstr += this.host.doSerialize(a[i])
				retstr += "</value>";
			}
			return retstr + "</data></array>";
		}
	}

	this.getSingleCall = function(name, args, obj){
		obj.push({m: name, p: args});
	}

	this.doSerialize = function(args){
		if(typeof args == "function"){
			throw new Error(1086, jpf.formErrorString(1086, null, "XMLRPC serialization", "Cannot Parse functions"));
		}
		else if(jpf.isNot(args))
			return serialize["boolean"](false);

		return serialize[args.dataType || "object"](args);
	}

	// Create message to send
	this.serialize = function(functionName, args){
  		//Construct the XML-RPC message
		var message = '<?xml version="1.0" encoding=\"UTF-8\"?><methodCall><methodName>' + functionName + '</methodName><params>';
   		for(var i=0;i<args.length;i++){
   			message += '<param><value>' + this.doSerialize(args[i]) + '</value></param>';
		}
		message += '</params></methodCall>';

  		return message;
  	}

	this.unserialize = function(data){
		var ret, i;

		switch(data.tagName){
			case "string":
				if(jpf.isGecko){
					data = (new XMLSerializer()).serializeToString(data);
					data = data.replace(/^\<string\>/,'');
					data = data.replace(/\<\/string\>$/,'');
					data = data.replace(/\&lt;/g, "<");
					data = data.replace(/\&gt;/g, ">");

					return data;
				}

				return (data.firstChild) ? data.firstChild.nodeValue : "";
				break;
			case "int":
			case "i4":
			case "double":
				return (data.firstChild) ? new Number(data.firstChild.nodeValue) : 0;
				break;
			case "dateTime.iso8601":
				/*
				Have to read the spec to be able to completely
				parse all the possibilities in iso8601
				07-17-1998 14:08:55
				19980717T14:08:55
				*/

				var sn = jpf.dateSeparator;

				if(/^(\d{4})(\d{2})(\d{2})T(\d{2}):(\d{2}):(\d{2})/.test(data.firstChild.nodeValue)){;//data.text)){
	      		return new Date(RegExp.$2 + sn + RegExp.$3 + sn +
	      							RegExp.$1 + " " + RegExp.$4 + ":" +
	      							RegExp.$5 + ":" + RegExp.$6);
	      	}
	    		else{
	    			return new Date();
	    		}

				break;
			case "array":
				data = jpf.compat.getNode(data, [0]);

				if(data && data.tagName == "data"){
					ret = new Array();

					var i = 0;
					while(child = jpf.compat.getNode(data, [i++])){
      				ret.push(this.unserialize(child));
					}

					return ret;
				}
				else{
					this.handleError(new Error(1087, jpf.formErrorString(1087, null, "", "Malformed XMLRPC Message")));
					return false;
				}
				break;
			case "struct":
				ret = {};

				var i = 0;
				while(child = jpf.compat.getNode(data, [i++])){
					if(child.tagName == "member"){
						ret[jpf.compat.getNode(child, [0]).firstChild.nodeValue] = this.unserialize(jpf.compat.getNode(child, [1]));
					}
					else{
						this.handleError(new Error(1087, jpf.formErrorString(1087, null, "", "Malformed XMLRPC Message2")));
						return false;
					}
				}

				return ret;
				break;
			case "boolean":
				return Boolean(isNaN(parseInt(data.firstChild.nodeValue)) ? (data.firstChild.nodeValue == "true") : parseInt(data.firstChild.nodeValue))

				break;
			case "base64":
				return jpf.decodeBase64(data.firstChild.nodeValue);
				break;
			case "value":
				child = jpf.compat.getNode(data, [0]);
				return (!child) ? ((data.firstChild) ? new String(data.firstChild.nodeValue) : "") : this.unserialize(child);

				break;
			default:
				throw new Error(1088, jpf.formErrorString(1088, null, "", "Malformed XMLRPC Message: " + data.tagName));
				return false;
				break;
		}
	}

	// Check Received Data for errors
	this.checkErrors = function(data, http){
		if(jpf.compat.getNode(data, [0]).tagName == "fault"){
			if(!jpf.isSafari){
				var nr = data.selectSingleNode("//member[name/text()='faultCode']/value/int/text()").nodeValue;
				var msg = "\n" + data.selectSingleNode("//member[name/text()='faultString']/value/string/text()").nodeValue;
			}else{nr = msg = ""}

			throw new Error(nr, msg);
		}

		data = jpf.compat.getNode(data, [0,0,0]);

		return data;
	}
}

/*FILEHEAD(/in/TelePort/rpc.js)SIZE(9105)TIME(1203730484247)*/

/**
 * Baseclass for any RPC protocol. Modules are available for
 * SOAP, XML-RPC, JSON-RPC and several proprietary protocols.
 *
 * @classDescription		This class creates a new Rpc object
 * @return {Rpc} Returns a new Rpc object
 * @type {Rpc}
 * @constructor
 * @baseclass
 *
 * @author      Ruben Daniels
 * @version     %I%, %G%
 * @since       0.4
 */
jpf.rpc = function(){
	if(!this.supportMulticall) this.multicall = false;

	this.stack = {};
	this.globals = [];
	this.names = {};
	this.urls = {};

	this.isRPC = true;
	this.useHTTP = true;
	this.TelePortModule = true;

	this.routeServer = jpf.host + "/cgi-bin/rpcproxy.cgi";
	this.autoroute = false;

	this.namedArguments = false;
	this.tagName = "RPC";

	/* ADD METHODS */

	this.addMethod = function(name, receive, names, async, vexport, is_global, global_name, global_lookup, caching){
		if(is_global) this.callbacks[name] = new Function('data', 'status', 'extra', 'jpf.lookup(' + this.uniqueId + ').setGlobalVar("' + global_name + '"' + ', data, extra.http, "' + global_lookup + '", "' + receive + '", extra, status)');
		else if(receive) this.callbacks[name] = receive;

		this.setName(name, names);
		if(vexport) this.vexport = vexport;
		this[name] = new Function('return this.call("' + name + '"' + ', this.fArgs(arguments, this.names["' + name + '"], ' + (this.vartype != "cgi" && this.vexport == "cgi") + '));');
		this[name].async = async;
		this[name].caching = caching;

		return true;
	}

	this.setName = function(name, names){
		this.names[name] = names;
	}

	this.setCallback = function(name, func){
		this.callbacks[name] = func;
	}

	this.fArgs = function(a, nodes, no_globals){
		var args = this.namedArguments ? {} : [];
		if(!no_globals) for(var i=0;i<this.globals.length;i++) args[this.globals[i][0]] = this.globals[i][1];
		
		if(this.namedArguments){
			if(!nodes || nodes && !nodes.length) return args;
			//throw new Error(0, jpf.formErrorString(0, this, "Calling RPC method", "Cannot set argument(s) which are not defined"));
			
			for(var value, j=0,i=0;i<nodes.length;i++){
				// Determine value
				var name = nodes[i].getAttribute("name");
				if(nodes[i].getAttribute("value")) value = nodes[i].getAttribute("value");
				else if(nodes[i].getAttribute("method")) value = self[nodes[i].getAttribute("method")](args);
				else{
					//Fugly Rik Hack				
					if ( a.length==1 && typeof a[0]=='object' && !jpf.isNull(a[0])){
					    //typeof(a[0][name]) != "undefined";
						value = a[0][name];
					}else{
						value = a[j];
						j++;
					}
					if(jpf.isNot(value)) value = nodes[i].getAttribute("default");
				}

				//Encode string optionally
				value = nodes[i].getAttribute("encoded") == "true" ? encodeURIComponent(value) : value;

				//Set arguments
				this.namedArguments ? (args[name] = value) : (args.push(value)); //isn't this only called for namedArguments = true (should)
			}
		}
		else
			for(var i=0;i<a.length;i++) args.push(a[i]);
		
		return args;
	}

	/* GLOBALS */

	this.setGlobalVar = function(name, data, http, lookup, receive, extra, status){
		if(status != __RPC_SUCCESS__){
			jpf.debugMsg("Could not get Global Variable<br />", "teleport");

			if(receive) self[receive](data, status, extra);
			return;
		}

		if(this.vartype == "header" && lookup && http) data = http.getResponseHeader(lookup);
		if(lookup.split("\:", 2)[0] == "xpath"){

			try{
				var doc = jpf.getObject("XMLDOM", data).documentElement;
			}
			catch(e){
				throw new Error(1083, jpf.formErrorString(1083, null, "Receiving global", "Returned value is not XML (for global variable lookup with name '" + name + "')"));
			}

			var data = jpf.getXmlValue(doc, lookup.split("\:", 2)[1]);
		}

		for(var found=false,i=0;i<this.globals.length;i++){
			if(this.globals[i][0] == name){
				this.globals[i][1] = data;
				found = true;
			}
		}
		if(!found) this.globals.push([name, data]);

		if(receive) self[receive](data, __RPC_SUCCESS__, extra);
	}

	/* CALL */

	this.call = function(name, args){
		if(this.workOffline) return;
		
		if(this.oncall) this.oncall(name, args);

		var receive = typeof this.callbacks[name] == "string" ? self[this.callbacks[name]] : this.callbacks[name];
		if(!receive) receive = function(){}
		//if(!receive){throw new Error(1602, "---- Javeline Error ----\nProcess :  RPC Send\nMessage : Callback method is not declared: '" + this.callbacks[name] + "'")}

		// Set up multicall
		if(this.multicall){
			if(!this.stack[this.URL]) this.stack[this.URL] = this.getMulticallObject ? this.getMulticallObject() : new Array();
			//this.stack[this.URL].push();
			this.getSingleCall(name, args, this.stack[this.URL])
			return true;
		}

		// Get Data
		var data = this.serialize(name, args); //function of module

		// Sent the request
		var info = this.get(this.URL, receive, this[name].async, this[name].userdata, true, data, false, null, null, null, this[name].caching);

		return info;
	}

	/* PURGE MULTICALL */

	this.purge = function(receive, userdata, async, extradata){
		if(!this.stack[this.URL] || !this.stack[this.URL].length) throw new Error(0, jpf.formErrorString(0, null, "Executing a multicall", "No RPC calls where executed before calling purge()."));
		
		// Get Data
		var data = this.serialize("multicall", [this.stack[this.URL]]); //function of module
		
		var url = this.URL;
		if(extradata){
			for(var vars=[],i=0;i<extradata.length;i++){
				vars.push(encodeURIComponent(extradata[i][0]) + "=" + encodeURIComponent(extradata[i][1] || ""))
			}
			url = url + (url.match(/\?/) ? "&" : "?") + vars.join("&");
		}

		info = this.get(url, receive, async, userdata, true, data, false);
		this.stack[this.URL] = this.getMulticallObject ? this.getMulticallObject() : [];

		//return info[1];
	}

	this.revert = function(modConst){
		this.stack[modConst.URL] = this.getMulticallObject ? this.getMulticallObject() : [];
	}
	
	this.getStackLength = function(){
		return this.stack[this.URL] ? this.stack[this.URL].length : 0;
	}

	/**
	 * Load XML Definitions
	 *
	 * @allowchild  method
	 * @attribute {String} url 
	 * @attribute {String} url-eval 
	 * @attribute {String} protocol 
	 * @attribute {Boolean} multicall 
	 * @attribute {Integer} timeout 
	 * @attribute {Boolean} autoroute 
	 * @attribute {Boolean} offline 
	 * @attribute {Boolean} async 
	 * @attribute {String} export 
	 * @attribute {String} type 
	 * @attribute {String} variable 
	 * @attribute {String} lookup 
	 * @attribute {Boolean} caching 
	 * @define method  
	 * @allowchild  variable
	 * @attribute name  
	 * @attribute url  
	 * @attribute receive  
	 * @define variable  
	 * @attribute name  
	 * @attribute value  
	 * @attribute default  
	 */
	this.load = function(x){
		this.jml = x;
		this.timeout = parseInt(x.getAttribute("timeout")) || this.timeout;
		this.URL = x.getAttribute("urleval") ? eval(x.getAttribute("urleval")) : x.getAttribute("url");
		if(this.URL) this.server = this.URL.replace(/^(.*\/\/[^\/]*)\/.*$/, "$1") + "/";
		this.multicall = x.getAttribute("multicall") == "true";
		this.autoroute = x.getAttribute("autoroute") == "true";
		this.workOffline = x.getAttribute("offline") == "true";

		if(this.__load) this.__load(x);

		var q = x.childNodes;
		for(var url, i=0;i<q.length;i++){
			if(q[i].nodeType != 1) continue;

			if(q[i].tagName == "global"){
				this.globals.push([q[i].getAttribute("name"), q[i].getAttribute("value")]);
				continue;
			}

			//var nodes = $xmlns(q[i], "variable", jpf.ns.jpf);
			var nodes = q[i].getElementsByTagName("*");

			url = q[i].getAttribute("urleval") ? eval(q[i].getAttribute("urleval")) : q[i].getAttribute("url");
			if(url) this.urls[q[i].getAttribute("name")] = url;

			//Add Method
			this.addMethod(
				q[i].getAttribute("name"),
				q[i].getAttribute("receive") || x.getAttribute("receive"),
				nodes,
				(q[i].getAttribute("async") == "false" ? false : true),
				q[i].getAttribute("export"),
				q[i].getAttribute("type") == "global",
				q[i].getAttribute("variable"),
				q[i].getAttribute("lookup"),
				q[i].getAttribute("caching") == "true"
			);
		}
	}
	
	/**
	 * Post a form with ajax
 	 *
 	 * @param form     form
 	 * @param function callback  Called when http result is received
	this.submitForm = function(form, callback, callName) {
		this.addMethod('postform', callback);
		this.urls['postform'] = form.action;

		var args = [];
		for (var i=0; i < form.elements.length; i++) {
			var name = form.elements[i].name.split("[");
			for(var j=0;j<name.length;j++){
				//Hmm problem with sequence of names... have to get that from the variable sequence...
			}
			args[] = form.elements[i].value;  
		}
		
		this['postform'].apply(this, args);
	}*/
}
/*FILEHEAD(/in/TelePort/socket.js)SIZE(3579)TIME(1203730484247)*/

//Depends on implementation of Javeline HTTP Socket on Server Side
/**
 * @constructor
 */
jpf.socket = function(){
	this.uniqueId = jpf.all.push(this) - 1;
	this.server = null;
	this.timeout = 10000;
	
	this.TelePortModule = true;
	
	/* ************************************************************
				Receiving - Permanent Connection (HTTP-PUSH)
	*************************************************************/
	this.init = function(){
		this.iframe = document.createElement("IFRAME");
		document.body.appendChild(this.iframe);
		this.iframe.style.position = "absolute";

		//if(!jpf.isIE) jpf.importClass(MozillaCompat, true, this.iframe.contentWindow);
		
		/*if(self.jpf.debug){
			this.iframe.style.left = "0px";
			this.iframe.style.top = "0px";
			this.iframe.style.zIndex = 100;
		}
		else */
		this.iframe.style.display = "none";
		this.timer = setInterval("var o = jpf.lookup(" + this.uniqueId + ");if(o.iframe.contentWindow.document.readyState == 'complete') o.reconnect()", 1000);
		
		this.inited = true;
	}

	this.socketConnect = function(vars){
		if(!this.inited) this.init();
		
		if(!vars) vars = [["date", new Date().getTime()]];
		else vars.push(["date", new Date().getTime()]);

		for(var str="",i=0;i<vars.length;i++)
			vars[i] = vars[i][0] + "=" + escape(vars[i][1])

		this.iframe.src = this.server + "?connection_id=" + this.uniqueId + "&" + vars.join("&");
		return this;
	}

	this.reconnect = function(){
		this.iframe.contentWindow.location.reload();
	}

	this.socketDisconnect = function(){
		clearInterval(this.timer);
		this.iframe.src = "blank.html";this.iframe.src = "blank.html";
	}

	this.setConnectionId = function(listenId){
		this.connectionId = listenId;
	}

	this.receive = function(module, strdata){
		jpf.debugMsg("<strong>HTTP Socket RCV: [" + module + "] - " + strdata.replace(/</g, "&lt;") + "</strong><hr />", "teleport");

		if(module == "LISTENER_ID") this.listenerId = strdata;
		else{
			var o = eval(strdata.replace(/\]-\]-\]/g, "]]").replace(/\|\|\|/g, "\\n"));
			//if(this.onreceive) this.onreceive(module, o);
			if(this.onreceive) self[this.onreceive](module, o);
		}
	}

	/* ************************************************************
						Forward Communication (RPC)
	*************************************************************/

	this.send = function(module, data){
		jpf.debugMsg("<strong>HTTP Socket SND: [" + module + "] - " + data.toString().replace(/</g, "&lt;") + "</strong><hr />", "teleport");

		this.forward.send(this.connectionId, module, data);
	}

	this.purge = function(){
		this.forward.purge();
	}

	this.load = function(x){
		this.server = x.getAttribute("url-eval") ? eval(x.getAttribute("url-eval")) : x.getAttribute("url");
		
		var fName = x.getAttribute("f-type") || "JPHP";
		
		this.forward = new self[fName]();
		this.forward.addMethod("send", null, null, true)
		
		this.forward.timeout = parseInt(x.getAttribute("timeout")) || this.timeout;
		this.forward.URL = this.server;
		this.forward.server = this.server.replace(/^(.*\/\/[^\/]*)\/.*$/, "$1") + "/";
		if(x.getAttribute("var-type")) this.forward.vartype = x.getAttribute("var-type");
		this.forward.multicall = x.getAttribute("multicall") == "true";
		
		if(x.getAttribute("mode") != "manual") this.socketConnect();
		if(x.getAttribute("receive")) this.onreceive = x.getAttribute("receive");
	}
}

/*FILEHEAD(/in/jpack_end.js)SIZE(120)TIME(1201688465117)*/
if(document.body) jpf.Init.run('BODY');
else window.onload = function(){jpf.Init.run('BODY');}

//Start
jpf.start();
/*FILEHEAD(/temp/jfw_debug.map)SIZE(0)TIME(1213547412584)*/

/*FILEHEAD(/cwd/jfwsym.txt)SIZE(0)TIME(0)*/
