	////////////////////////////////////////////////////////////////////////////////////////////////////
	// Helper
	////////////////////////////////////////////////////////////////////////////////////////////////////
	function puTrim(s)
	{
		s = s.replace(/^\s*/,'').replace(/\s*$/, '');
		return s;
	}
	
	function puCheckURI(uri)
	{
		if(!uri || uri.length <= 0)
			return "";
		
		/*aURI = uri.split("http://");
		if(!aURI[1])
			return "http://" + aURI[0];*/
		
		return uri;
	}
	
	function puGetWindowObject(obj) 
	{
		if(typeof(obj) == "object")
		{
			while(obj.parentNode.tagName != null && obj.tagName != "TABLE")
				obj = obj.parentNode;
		}
		else if(typeof(obj) == "string")
			obj = document.getElementById(obj);
			
		return obj;
	}
	
	function puGetStylePath()
	{
		var obj = document.getElementById("pudhtmlStyle");
		if(!obj)
			return null;
			
		return obj.href.substr(0, obj.href.lastIndexOf("/") +1);
	}
	
	function puGetBrowserName()
	{
		var nav = navigator.userAgent;
		if(nav.indexOf("Netscape") >= 0)
			return "Netscape";
		else if(nav.indexOf("Firefox") >= 0)
			return "Mozilla Firefox";
		else if(nav.indexOf("Opera") >= 0)
			return "Opera";
		else if(nav.indexOf("MSIE") >= 0)
			return "Microsoft Internet Explorer";
		else if(nav.indexOf("Konqueror") >= 0)
			return "Konqueror";
		else if(nav.indexOf("Mozilla") >= 0)
			return "Mozilla";
		else
			return null;
	}
	
	function puLoadBrowserStyle(path)
	{
		var obj = document.getElementById("pudhtmlStyle");
		if(!obj)
			return null;
		
		var newStyle = obj.href.substr(0, obj.href.lastIndexOf("/pudhtml.css"));
		newStyle = newStyle.substr(0, newStyle.lastIndexOf("/"));
			
		var name = puGetBrowserName();
		if(name == "Microsoft Internet Explorer")
			obj.href = newStyle + "/ie/pudhtml.css";
		else if(name == "Mozilla")
			obj.href = newStyle + "/mozilla/pudhtml.css";
		else if(name == "Netscape")
			obj.href = newStyle + "/netscape/pudhtml.css";
		else if(name == "Mozilla Firefox")
			obj.href = newStyle + "/firefox/pudhtml.css";
		else if(name == "Opera")
			obj.href = newStyle + "/opera/pudhtml.css";
		else if(name == "Konqueror")
			obj.href = newStyle + "/konqueror/pudhtml.css";
	}
	
	function puResizeMaximized()
	{
		for(var name in puw)
		{
			if(puw[name].isMaximized)
			{
				puw[name].isMaximized = false;
				puWindowMax(name);
			}
		}
	}
	
	////////////////////////////////////////////////////////////////////////////////////////////////////
	// Objects
	////////////////////////////////////////////////////////////////////////////////////////////////////
	function PUWindow(uri, name, params, mode)
	{
		this.uri = puCheckURI(uri);
		this.name = name;
		this.left = 50;
		this.top = 50;
		this.width = 400;
		this.height = 300;
		this.scrollbars = "auto";
		this.titlebar = true;
		this.location = false;
		this.resizable = true;
		this.status = false;
		
		this.titleText = uri;
		this.statusText = "";
		this.draggingActive = false;
		this.isMaximized = false;
		this.isMinimized = false;
		
		this.mode = (mode) ? mode : "dhtml";
		
		if(params)
		{
			// split argument into an array
			var args = new Array();
			params = params.split(",");
			for(var i=0; i<params.length; i++)
			{
				var assign = params[i].split("=");
				if(assign.length == 2)
					args[puTrim(assign[0])] = puTrim(assign[1]);
			}
			
			// check if this object alreay exists copy all argument into this object
			if(puw[name])
			{
				var o = puw[name];
				this.uri = o.uri;
				this.name = o.name;
				this.left = o.left;
				this.top = o.top;
				this.width = o.width;
				this.height = o.height;
				this.scrollbars = o.scrollbars;
				this.titlebar = o.titlebar;
				this.location = o.location;
				this.resizable = o.resizable;
				this.status = o.status;
				this.title = o.title;
				
				this.titleText = o.titleText;
				this.statusText = o.statusText;
				this.draggingActive = o.draggingActive;
				this.isMaximized = o.isMaximized;
				this.isMinimized = o.isMinimized;
			}
			
			// set available arguments into this object
			if(args["left"])
				this.left = args["left"];
			if(args["top"])
				this.top = args["top"];
			if(args["width"])
				this.width = args["width"];
			if(args["height"])
				this.height = args["height"];
			if(args["scrollbars"])
				this.scrollbars = args["scrollbars"];

			if(args["titlebar"] == "yes")
				this.titlebar = true;
			else if(args["titlebar"] == "no")
				this.titlebar = false;
				
			if(args["location"] == "yes")
				this.location = true;
			else if(args["location"] == "no")
				this.location = false;
				
			if(args["resizable"] == "yes")
				this.resizable = true;
			else if(args["resizable"] == "no")
				this.resizable = false;
				
			if(args["status"] == "yes")
				this.status = true;
			else if(args["status"] == "no")
				this.status = false;
			
			if(args["title"] && args["title"].length > 0)
				this.title = args["title"];
			else
				this.title = null;
			
			this.min = function() {puWindowMin(this.name);};
			this.max = function() {puWindowMax(this.name);};
			this.hide = function() {puWindowHide(this.name);};
			this.show = function() {puWindowShow(this.name);};
			this.close = function() {puWindowClose(this.name);};
			this.focus = function() {puFocus(this.name);};
			this.blur = function() {puBlur(this.name);};
			this.moveBy = function(x, y) {puWindowMoveBy(this.name, x, y);};
			this.moveTo = function(x, y) {puWindowMoveTo(this.name, x, y);};
			this.resizeBy = function(x, y) {puWindowResizeBy(this.name, x, y);};
			this.resizeTo = function(x, y) {puWindowResizeTo(this.name, x, y);};
			this.setTitle = function(title) {puSetTitle(this.name, title);};
			this.setLocation = function(uri) {puSetLocation(this.name, uri);};
			this.setStatus = function(status) {puSetStatus(this.name, status);};
		}
	}
	
	function TaskBar()
	{
		this.taskNumber = 0;
		this.taskTable = document.getElementById("puTaskBar");
		this.taskRow = document.getElementById("puTaskRow");
		this.taskClone = document.getElementById("puTask").cloneNode(true);
		
		
		this.taskRow.removeChild(document.getElementById("puTask"));
	}
	
	////////////////////////////////////////////////////////////////////////////////////////////////////
	// Globals
	////////////////////////////////////////////////////////////////////////////////////////////////////
	var puIE = (navigator.appName=="Microsoft Internet Explorer")?true:false;
	var puw = new Array();
	var puActiveWindowObj = null;
	var puTaskBar = null;
	var puZIndex = 0;
	
	////////////////////////////////////////////////////////////////////////////////////////////////////
	// Window Functions
	////////////////////////////////////////////////////////////////////////////////////////////////////
	function puFocus(obj)
	{
		obj = puGetWindowObject(obj);
		obj.style.zIndex = ++puZIndex;
		
		puActiveWindowObj = obj;
		puActiveWindowObj.ondragstart = new Function("return false");
	}
	
	function puBlur(obj)
	{
		puWindowMin(obj);
	}
	
	function puWindowMoveBy(obj, x, y)
	{
		obj = puGetWindowObject(obj);
		puw[obj.id].left = parseInt(puw[obj.id].left) +x;
		puw[obj.id].top = parseInt(puw[obj.id].top) +y;
		obj.style.left = puw[obj.id].left;
		obj.style.top = puw[obj.id].top;
	}
	
	function puWindowMoveTo(obj, x, y)
	{
		obj = puGetWindowObject(obj);
		puw[obj.id].left = x;
		puw[obj.id].top = y;
		obj.style.left = puw[obj.id].left;
		obj.style.top = puw[obj.id].top;
	}
	
	function puWindowResizeBy(obj, x, y)
	{
		obj = puGetWindowObject(obj);
		if(!puw[obj.id].resizable)
			return;

		puw[obj.id].width = parseInt(puw[obj.id].left) +x;
		puw[obj.id].height = parseInt(puw[obj.id].top) +y;
		obj.style.width = puw[obj.id].width;
		obj.style.height = puw[obj.id].height;
		
		puSetTitle(obj.id);
		puSetStatus(obj.id);
	}
	
	function puWindowResizeTo(obj, x, y)
	{
		obj = puGetWindowObject(obj);
		if(!puw[obj.id].resizable)
			return;

		puw[obj.id].width = x;
		puw[obj.id].height = y;
		obj.style.width = puw[obj.id].width;
		obj.style.height = puw[obj.id].height;
		
		puSetTitle(obj.id);
		puSetStatus(obj.id);
	}
	
	function puWindowHide(obj)
	{
		puGetWindowObject(obj).style.visibility = "hidden";
	}
	
	function puWindowShow(obj)
	{
		puGetWindowObject(obj).style.visibility = "visible";
	}
	
	function puWindowMin(obj)
	{
		obj = puGetWindowObject(obj);
		if(!puw[obj.id].isMinimized)
			puAddTaskToTaskBar(obj);
	}
	
	function puWindowMax(obj)
	{
		obj = puGetWindowObject(obj);
		if(!puw[obj.id].resizable)
			return;
		
		if(!puw[obj.id].isMaximized)
		{
			obj.style.left = 0;
			obj.style.top = 0;
			if(puIE)
			{
				obj.style.width = document.body.clientWidth;
				obj.style.height = document.body.clientHeight;
			}
			else
			{
				obj.style.width = innerWidth;
				obj.style.height = innerHeight;
			}
			puw[obj.id].isMaximized = true;
			var img = document.getElementById(obj.id +"maximg");
			img.src = img.src.replace("maximize.", "restore.");
		}
		else
		{
			obj.style.width = puw[obj.id].width;
			obj.style.height = puw[obj.id].height;
			obj.style.left = puw[obj.id].left;
			obj.style.top = puw[obj.id].top;
			
			puw[obj.id].isMaximized = false;
			var img = document.getElementById(obj.id +"maximg");
			img.src = img.src.replace("restore.", "maximize.");
		}
		
		puSetTitle(obj.id);
		puSetStatus(obj.id);
	}
	
	function puWindowClose(obj)
	{
		obj = puGetWindowObject(obj);
		parentObj = obj.parentNode;
		if(parentObj)
			parentObj.removeChild(obj);
		else
			obj.style.visibility = "hidden";
	}
	
	function puWindowOpen(uri, name, params, mode)
	{
		// Load browser specified look & feel
		puLoadBrowserStyle();
		
		// try to open a default window-Popup, otherwise fallback to DHTML-Popup
		var oDefaultWin = null;
		if((mode == "window" || mode == "both") && puGetBrowserName() != "Opera")	// Opera terminates script if you open try to open a popup-window and Opera-Popup-Blocker is toggled. Dirty workaround: Open only DHTML-Popup without a check for popup-blocker.
		{
			if((oDefaultWin = window.open(uri, name, params)))
				return oDefaultWin;
		}
		
		// create taskbar if not available
		if(puTaskBar == null)
		{
			puCreateTaskBar();
			puTaskBar = new TaskBar();
	
			// adding event listener		
			document.onmousemove = puDragWindow;
			window.onresize = puResizeMaximized;
			//window.onscroll = puScrollWindow;
		}
	
		// if name is not set, create a random name
		if(!name)
			name = "puWindow" + Math.random();
			
		// create a new PUWindow-object
		puw[name] = new PUWindow(uri, name, params, mode);
		var o = puw[name];
		
		// remove old window with the same name if available
		var winObj = document.getElementById(o.name);
		if(winObj)
			winObj.parentNode.removeChild(winObj);
			
		var path = puGetStylePath();
		document.open();
	   	document.write('<table id="' +o.name +'" style="left:' +o.left +'px; top:' +o.top +'px; width:' +o.width +'px; height:' +o.height +'px; position:absolute; z-index:0;" class="window" border="0" cellspacing="0" cellpadding="0" onmousedown="puFocus(this)">');
		
		if(o.titlebar)
		{
			document.write('<tr align="left" valign="middle" class="titleBar" style="cursor:default;" onselectstart="return false;">');
				document.write('<td ondblclick="puWindowClose(this)" style="padding-left:2px;"><img src="' +path +'icon_window.gif" border="0"></td>');
				document.write('<td width="100%" style="padding-left:4px;" id="' +o.name +'title" ondblclick="puWindowMax(this)" onmousedown="puDragStart(this)" onmouseup="puDragStop(this)">Popup by Click Around</td>');
				document.write('<td style="padding-right:1px;"><button onfocus="this.blur()" onclick="puWindowMin(this)" class="titleBarButtons"><img src="' +path +'button_minimize.gif"></button></td>');
				document.write('<td style="padding-right:1px;"><button id="' +o.name +'maxbutton" onfocus="this.blur()" onclick="puWindowMax(this)" class="titleBarButtons"><img id="' +o.name +'maximg" src="' +path +'button_maximize.gif"></button></td>');
				document.write('<td style="padding-right:1px;"><button onfocus="this.blur()" onclick="puWindowClose(this)" class="titleBarButtons"><img src="' +path +'button_close.gif"></button></td>');
			document.write('</tr>');
		}
		
		if(o.location)
		{
			document.write('<tr valign="middle" class="locationBar">');
				document.write('<td style="padding-left:2px; padding-right:4px;">');
					document.write('<img src="' +path +'icon_uri.gif" border="0">');
				document.write('</td>');
				document.write('<td colspan="4" height="1">');
					document.write('<form onsubmit="puSetLocation(this); return false;" style="margin:0px; padding:0px;">');
					document.write('<input id="' +o.name +'location" value="' +o.uri +'" type="text" style="width:100%;" class="locationTextField">');
					document.write('</form>');
				document.write('</td>');
			document.write('</tr>');
		}
			
			document.write('<tr>');
				document.write('<td colspan="5" width="100%">');
					document.write('<iframe id="' +o.name +'uri" name="' +o.name +'uri" src="' +o.uri +'" scrolling="' +o.scrollbars +'" frameborder="0" width="100%" height="100%" class="content"></iframe>');
				document.write('</td>');
			document.write('</tr>');
			
		if(o.status)
		{
			document.write('<tr valign="middle" class="statusBar" onselectstart="return false;">');
				document.write('<td style="padding-left:2px; padding-right:4px; padding-top:2px; padding-bottom:2px;">');
					document.write('<img src="' +path +'icon_status.gif" border="0">');
				document.write('</td>');
				document.write('<td id="' +o.name +'status" colspan="4" height="1" width="100%">');
					document.write('&nbsp;');
				document.write('</td>');
			document.write('</tr>');
		}
			
		document.write('</table>');
		document.close();

		// check if window can be resizable
		if(o.titlebar)
		{	
			var obj = document.getElementById(name +"maxbutton");
			obj.disabled = !puw[name].resizable;
		}
		
		// set window title
		puSetTitle(o.name, o.uri);
		
		return o;
	}

	function puSetTitle(windowName, data)
	{
		var titleObj = document.getElementById(windowName +"title");
		if(!titleObj)
			return;
			
		var winObj = puw[windowName];
		if(data)
			winObj.titleText = data + " - " +puGetBrowserName();
		
		if(winObj.title)
			winObj.titleText = winObj.title;
			
			
		titleObj.firstChild.data = "";
		var w = titleObj.offsetHeight;
		for(var i=0; i<winObj.titleText.length; i++)
		{
			titleObj.firstChild.data += winObj.titleText.charAt(i);
			if(titleObj.offsetHeight > w)
			{
				var title = titleObj.firstChild.data;
				titleObj.firstChild.data = title.substr(0, i-6) +" . . .";
				break;
			}
		}
	}
	
	function puSetStatus(windowName, data)
	{
		var statusObj = document.getElementById(windowName +"status");
		if(!statusObj)
			return;
			
		var winObj = puw[windowName];
		if(data)
			winObj.statusText = data;

		statusObj.firstChild.data = "";
		var w = statusObj.offsetHeight;
		for(var i=0; i<winObj.statusText.length; i++)
		{
			statusObj.firstChild.data += winObj.statusText.charAt(i);
			if(statusObj.offsetHeight > w)
			{
				var status = statusObj.firstChild.data;
				statusObj.firstChild.data = winObj.statusText.substr(0, i-6) +" . . .";
				break;
			}
		}
	}
	
	function puSetLocation(obj, uri)
	{
		obj = puGetWindowObject(obj);

		var locationObj = document.getElementById(obj.id +"location");
		if(locationObj)
		{
			if(uri)
				locationObj.value = puCheckURI(uri);
				
			document.getElementById(obj.id +"uri").src = locationObj.value;
			puSetTitle(obj.id, locationObj.value);
		}
		else if(uri)
		{
			document.getElementById(obj.id +"uri").src = puCheckURI(uri);
			puSetTitle(obj.id, uri);
		}
	}
	
	////////////////////////////////////////////////////////////////////////////////////////////////////
	// Drag Functions
	////////////////////////////////////////////////////////////////////////////////////////////////////
	function puDragStart(obj)
	{
		obj = puGetWindowObject(obj);
		puActiveWindowObj = obj;
		puActiveWindowObj.draggingActive = true;
		
		puY = puPosY - parseInt(obj.style.top);
		puX = puPosX - parseInt(obj.style.left);
	}
	
	function puDragStop(obj)
	{
		if(puActiveWindowObj)
			puActiveWindowObj.draggingActive = false;
	}
	
	function puDragWindow(e)
	{
		puPosX = puIE?event.clientX:e.clientX;
		puPosY = puIE?event.clientY:e.clientY;
		if(puActiveWindowObj && puActiveWindowObj.draggingActive && !puw[puActiveWindowObj.id].isMaximized)
		{
			puw[puActiveWindowObj.id].top = puPosY - puY;
			puw[puActiveWindowObj.id].left = puPosX - puX;
			puActiveWindowObj.style.top = puw[puActiveWindowObj.id].top;
			puActiveWindowObj.style.left = puw[puActiveWindowObj.id].left;
		}
	}
	
	
	////////////////////////////////////////////////////////////////////////////////////////////////////
	// Scroll Functions
	////////////////////////////////////////////////////////////////////////////////////////////////////
	function puScrollWindow()
	{
		/*puPosX = puIE?event.clientX:e.clientX;
		puPosY = puIE?event.clientY:e.clientY;
		if(puActiveWindowObj && puActiveWindowObj.draggingActive && !puw[puActiveWindowObj.id].isMaximized)
		{
			puw[puActiveWindowObj.id].top = puPosY - puY;
			puw[puActiveWindowObj.id].left = puPosX - puX;
			puActiveWindowObj.style.top = puw[puActiveWindowObj.id].top;
			puActiveWindowObj.style.left = puw[puActiveWindowObj.id].left;
		}*/
		
		//alert(puw);
		//oTable.style.top = document.body.scrollTop + posY;
		//window.status = blaxx++;
	}
	
	
	////////////////////////////////////////////////////////////////////////////////////////////////////
	// Taskbar Functions
	////////////////////////////////////////////////////////////////////////////////////////////////////
	function puCreateTaskBar()
	{
	   document.write('<table id="puTaskBar" style="left:0px; bottom:10px; width:1px; position:absolute; z-index:10000; visibility:hidden;" border="0" cellspacing="0" cellpadding="2">');
			document.write('<tr>');
				document.write('<td class="taskBar">');
				   	document.write('<table border="0" cellpadding="0" cellspacing="0">');
					document.write('<tr id="puTaskRow" align="left" valign="middle">');
						document.write('<td id="puTask" onclick="puRemoveTaskFromTaskBar(this)"><nobr><button id="puTaskButton" onfocus="this.blur()" class="taskBarButtons">&nbsp;</button></nobr></td>');
					document.write('</tr>');
				document.write('</table>');
				document.write('</td>');
			document.write('</tr>');
		document.write('</table>');
	}
	
	function puAddTaskToTaskBar(obj)
	{
		obj.style.visibility = "hidden";
		puw[obj.id].isMinimized = true;
		
		puTaskBar.taskRow.appendChild(puTaskBar.taskClone.cloneNode(true));
		puTaskBar.taskNumber++;
		if(puTaskBar.taskNumber > 0)
			puTaskBar.taskTable.style.visibility = "visible";
		
		var taskObj = document.getElementById("puTask");
		var buttonObj = document.getElementById("puTaskButton");
		
		var title = document.getElementById(obj.id +"title").firstChild.data;
		if(title.length > 7)
			title = title.substr(0, 7) +"...";
		buttonObj.firstChild.data = title;
		
		taskObj.id = obj.id + "task";
		buttonObj.id = obj.id + "taskbutton";
	}
	
	function puRemoveTaskFromTaskBar(obj)
	{
		var winId = obj.id.substring(0, obj.id.length-4);
		var winObj = document.getElementById(winId);
		
		winObj.style.visibility = "visible";
		puw[winObj.id].isMinimized = false;
		puFocus(winObj);
		
		puTaskBar.taskRow.removeChild(obj);
		puTaskBar.taskNumber--;
		if(puTaskBar.taskNumber <= 0)
			puTaskBar.taskTable.style.visibility = "hidden";
	}