/* 
filename: window.js																				   
written by: Mac Davis																			   
usage: 
var winObj = jsWindow(title, content, id, posX, posY, width, height, resizeOn, buttonsOn,  modal);

Parameters:
Name		Type 			Description
----------- --------------- ----------------------------------------------------------------------
title		text			text that will appear in the title bar.
content		object or text	The content(s) of the window.
posX		integer			X position of the window on the screen.
posY		integer 		Y position of the window on the screen.
width		integer			Width of the window in pixels.
height		integer			height of the window in pixels.
resizeOn	boolean			toggles resizable status of the window
buttonsOn	boolean			toggles close and min/max buttons in upper right corner of the window.
modal		boolean			toggles whether other windows can be activated on top of the window.

Methods:
close Ex. winObj.close();	Closes the calling window and removes if from the DOM.
focus Ex. windObj.focus();	Sets the calling window to the active window.

Exposed elements via class name's and ID's:

Classes -- Affects all window objects:
	.winContainer	Window object class name.
	.winBorder		Window border class name.
	.winTitle		Title bar object class name.
	.winContent		Window content object class name.

ID's -- Affects individual windows, where [id] is the id paramter passed to the function
	#[id]Container	Window object ID.
	#[id]Border		Window border ID.
	#[id]Title		Title bar object ID.
	#[id]Content	Window content object ID.	   
*/	

var $jsWindows = new Array();
var topIndex = 100; 
var currentWindow = false;

//jsWindow constructer.
function jsWindow(title, content, id, posX, posY, width, height, resizeOn, buttonsOn, modal)
{
	for (var i=0; i < $jsWindows.length; i++)
	{
		if ($jsWindows[i].id == id)
		{
			return false;
		}
	}
	
	
	if (currentWindow != false)
	{  
		if (currentWindow.parentObj.modal == true)
		{
			return false;
		}
	}
	
	winObj = new $jsWindow(title, content, id, posX, posY, width, height, resizeOn, buttonsOn, modal);
	return winObj;
} 

/*******************************************************************************************************/
/* 									  Window handler object											   */
/*******************************************************************************************************/

function activeWindow(event)
{
	var evt = new eventObj(event);
	if (evt.source.parentWindow)
	{
		var node = evt.source.parentWindow.parentObj;
	}
	else
	{
		return true;
	}
		
	if(currentWindow.id != node.container.id)
	{
 		if (currentWindow == false || currentWindow.parentObj.modal != true)
		{
			currentWindow = $(node.container.id);
			for(var i=0; i<$jsWindows.length; i++)
			{ 
				if ($jsWindows[i].id != node.container.id)
				{
					$jsWindows[i].titleBox.style.backgroundColor = "gray";
					$jsWindows[i].container.style.cursor = "";
					$jsWindows[i].container.resizable = false;
					var thisID = $jsWindows[i].id;
					disableElements("select", $(thisID));
					disableElements("button", $(thisID));
					disableElements("input", $(thisID));				
				}
				else
				{ 
					node.ifrmBlocker.style.zIndex = topIndex++;
					node.container.style.zIndex = topIndex++;
					node.titleBox.style.backgroundColor = node.titleBox.oldBackgroundColor;
					node.container.resizable = true; 
					var thisID = $jsWindows[i].id;
					enableElements("select", $(thisID));
					enableElements("button", $(thisID));
					enableElements("input", $(thisID));
				}
			}
		}
	}
	evt.consume();
}

/*******************************************************************************************************/
/* 									Window resizing functions										   */
/*******************************************************************************************************/

//Change cursor on window edges to indicate resize direction.
function resizeCursor(event)
{ 
	var position = "";
	var evt = new eventObj(event);
	var node = evt.source;
	
	//Okay, I borrowed this idea from brainjar.com
	//This defines the resize area on the window border.
	if (node.className == "winContainer")
	{ 
		if (node.parentWindow.parentObj.resizeOn == false)
		{
			return true;
		}
		
		if (currentWindow.id != node.id || node.resizable == false)
		{
			node.style.cursor = "";
			return false;
		}

		if (evt.y < node.offsetTop+15 && evt.y > node.offsetTop-15)
		{
			position += "n";
		}
		else if (evt.y < node.offsetTop+node.offsetHeight+15 && evt.y > node.offsetTop+node.offsetHeight-15)
		{
			position += "s";
		}
	
		if (evt.x < node.offsetLeft+15 && evt.x > node.offsetLeft-15)
		{
			position += "w";
		}
		else if (evt.x < node.offsetLeft+node.offsetWidth+15 && evt.x > node.offsetLeft+node.offsetWidth-15)
		{
			position += "e";
		}	
		node.style.cursor = position + "-resize";
		node.resizePos = position;
	}	 
}

//Capture the resize event.
function resizeDrag(event)
{
	var evt = new eventObj(event);
	var node = evt.source;	
	
	if (node.resizable == false)
	{
		activeWindow(event);
		return true;
	}
	//create variables for all window objects, and original window dimensions.
	
	if (node.parentObj)
	{ 
		var node = node.parentObj;
		
		if (node.resizeOn == false)
		{
			return true;
		}
		
		node.container.sizeArea = node.container.resizePos;
		
		node.container.ogWidth = parseInt(node.container.style.width);
		node.container.ogHeight = parseInt(node.container.style.height);
		node.container.ogLeft = parseInt(node.container.style.left);
		node.container.ogTop = parseInt(node.container.style.top);
		
		node.borderBox.ogWidth = parseInt(node.borderBox.style.width);
		node.borderBox.ogHeight = parseInt(node.borderBox.style.height);
		
		node.titleBox.ogWidth = parseInt(node.titleBox.style.width);
		
		node.contentBox.ogWidth = parseInt(node.contentBox.style.width);
		node.contentBox.ogHeight = parseInt(node.contentBox.style.height);
		
		winX = evt.x;
		winY = evt.y;
	
		addEvent(document, "mousemove", resizeMove, false);
		addEvent(document, "mouseup", resizeRelease, false);
	}
}

//This function does the window resizing.
function resizeMove(event)
{
	var evt = new eventObj(event);
	var node = currentWindow.parentWindow.parentObj;
		
	prevTop = node.container.style.top;
	prevLeft = node.container.style.left;
	resizeChar1 = false;
	resizeChar0 = node.container.sizeArea.substring(0,1);
	
	if (node.container.resizePos.length > 1)
	{
		resizeChar1 = node.container.sizeArea.substring(1,2);
	} 
	
	moveY = winY-evt.y;
	moveX = winX-evt.x;
	
	//Set resizing limits.
	if (node.container.ogHeight+moveY < parseInt(node.container.minHeight) && resizeChar0 == "n")
	{
		moveY = parseInt(node.container.minHeight)-node.container.ogHeight;
	}
	if (node.container.ogHeight-moveY < parseInt(node.container.minHeight) && resizeChar0 == "s")
	{
		moveY = node.container.ogHeight-parseInt(node.container.minHeight);
	}
	if (node.container.ogWidth-moveX < parseInt(node.container.minWidth) && (resizeChar0 == "e" || resizeChar1 == "e"))
	{
		moveX = node.container.ogWidth-parseInt(node.container.minWidth);
	}
	if (node.container.ogWidth+moveX < parseInt(node.container.minWidth) && (resizeChar0 == "w" || resizeChar1 == "w"))
	{
	 	moveX = parseInt(node.container.minWidth)-node.container.ogWidth;
	}
	
	//Determine resize area, and resize the window accordingly.
	if (resizeChar0 == "s")
	{	
		node.container.style.height = node.container.ogHeight-moveY + "px";
		node.borderBox.style.height = node.borderBox.ogHeight-moveY + "px";
		node.contentBox.style.height = node.contentBox.ogHeight-moveY + "px";
		node.ifrmBlocker.style.height = parseInt(node.container.offsetHeight) + "px";
	}
	
	if (resizeChar0 == "n")
	{
		node.container.style.top = node.container.ogTop-moveY + "px";
		node.container.style.height = node.container.ogHeight+moveY + "px";	
		node.borderBox.style.height = node.borderBox.ogHeight+moveY + "px";
		node.contentBox.style.height = node.contentBox.ogHeight+moveY + "px";
		node.ifrmBlocker.style.top = parseInt(node.container.offsetTop) + "px";
		node.ifrmBlocker.style.height = parseInt(node.container.offsetHeight) + "px";
	}
			
	if (resizeChar0 == "e" || resizeChar1 == "e")
	{
		node.container.style.width = node.container.ogWidth-moveX + "px";
		node.borderBox.style.width = node.borderBox.ogWidth-moveX + "px";
		node.contentBox.style.width = node.contentBox.ogWidth-moveX + "px";
		node.titleBox.style.width = node.titleBox.ogWidth-moveX + "px";	  
		node.ifrmBlocker.style.width = parseInt(node.container.offsetWidth) + "px";
	}
	
	if (resizeChar0 == "w" || resizeChar1 == "w")
	{
		node.container.style.left = node.container.ogLeft-moveX + "px";
		node.container.style.width = node.container.ogWidth+moveX + "px";
		node.borderBox.style.width = node.borderBox.ogWidth+moveX + "px";
		node.contentBox.style.width = node.contentBox.ogWidth+moveX + "px";
		node.titleBox.style.width = node.titleBox.ogWidth+moveX + "px";	   
		node.ifrmBlocker.style.left = parseInt(node.container.offsetLeft) + "px";
		node.ifrmBlocker.style.width = parseInt(node.container.offsetWidth) + "px";
	} 
	
	evt.consume;
}

//Release resize event listeners when user releases the mouse button.
function resizeRelease()
{	
	removeEvent(document, "mousemove", resizeMove, false);
	removeEvent(document, "mouseup", resizeRelease, false);
}

/*******************************************************************************************************/
/* 								Window drag and drop functions										   */
/*******************************************************************************************************/
 
function winDragPress(event) 
{
	var evt = new eventObj(event);
	var node = evt.source.parentWindow.parentObj;
	
	if (currentWindow == false || (node.id != currentWindow.id && currentWindow.parentObj.modal == false))
	{
		activeWindow(event);
	}
	else if (node.id != currentWindow.id && currentWindow.parentObj.modal == true)
	{
		return false;
	}
	
	node.container.ogX = parseInt(node.container.offsetLeft);
	node.container.ogY = parseInt(node.container.offsetTop);
	
	winX = evt.x;
	winY = evt.y;
	
	addEvent(document,"mousemove",winDragMove,false);
	addEvent(document,"mouseup",winDragRelease,false);
}

function winDragMove(event)
{
	var evt = new eventObj(event);
	var node = currentWindow.parentWindow.parentObj; 
	node.container.style.left = node.container.ogX+(evt.x-winX) + "px";
	node.ifrmBlocker.style.left = node.container.ogX+(evt.x-winX) + "px";
	node.container.style.top = node.container.ogY+(evt.y-winY) + "px";	 
	node.ifrmBlocker.style.top = node.container.ogY+(evt.y-winY) + "px";
	
	evt.consume(); 
}

function winDragRelease()
{
	 removeEvent(document, "mousemove", winDragMove, false);
	 removeEvent(document, "mouseup", winDragRelease, false);
}

/********************************************************************************************************/
/*								Main Window Functions and Methods										*/
/********************************************************************************************************/

//Creates all window objects and adds it to the DOM tree.
function $jsWindow(title, content, id, posX, posY, width, height, resizeOn, buttonsOn, modal)
{
	this.title = title;
	this.content = content;
	this.id = id;
	this.x = posX;
	this.y = posY;
	this.resizePos = "";
	this.resizeOn = resizeOn;
	this.buttonsOn = buttonsOn;
	this.modal = modal;
	
	//Create four window objects, container, border, title, and content.
	this.ifrmBlocker = document.createElement("iframe");
	this.container = document.createElement("div");
	this.borderBox = document.createElement("div");
	this.titleBox = document.createElement("div");
	this.titleText = document.createElement("span");
	this.buttonBox = document.createElement("div");
	if (this.buttonsOn == true)
	{
		this.minIcon = minIconObj(this);
		this.closeIcon = closeIconObj(this); 
	}
	this.contentBox = document.createElement("div");
	
	//Intialize the window container object.
	this.container.parentObj = this;
	this.container.parentWindow = this.container;
	this.container.id = this.id; 
	this.container.className = "winContainer";
	this.container.defHeight = height;
	this.container.defWidth = width;
	this.container.minHeight = "50px";
	this.container.minWidth = "75px";
	this.container.resizable = true;
	
	//These must not be changed, or the window formatting will break during resize.
	this.container.style.position = "absolute";
	this.container.style.top = this.y + "px";
	this.container.style.left = this.x + "px";
	this.container.style.padding = "2px"; 
	this.container.onmousemove = resizeCursor;
	this.container.onmousedown = resizeDrag;
	this.container.onclick = activeWindow;
	
	//Initialize the window border object.
	this.borderBox.parentWindow = this.container;
	this.borderBox.id = this.id + "Border";
	this.borderBox.className = "winBorder";
	this.borderBox.style.overflow = "hidden";
	this.borderBox.style.cursor = "default";
	
	//Initialize the window title object
	this.titleBox.parentWindow = this.container;
	this.titleBox.id = this.id + "Title";
	this.titleBox.className = "winTitle";
	this.titleBox.oldBackgroundColor = this.titleBox.style.backgroundColor;
	this.titleBox.style.overflow = "hidden";
	this.titleBox.style.whiteSpace = "nowrap";
	this.titleBox.onmousedown = winDragPress;
	
	this.titleText.parentWindow = this.container;
	this.titleText.innerHTML = this.title;
	 
	//Initialize the min/max/close button container.
	this.buttonBox.parentWindow = this.container;
	this.buttonBox.id = this.id + "Buttons";
	this.buttonBox.style.position = "absolute";
	
	//Initialize the window content object.
	this.contentBox.parentWindow = this.container;
	this.contentBox.style.overflow = "auto";
	this.contentBox.id = this.id + "Content";
	this.contentBox.className = "winContent";
	this.contentBox.style.visibility = "visible";
	this.contentBox.style.height = "100%";
	this.contentBox.onclick = activeWindow; 	
	

	//Populate the content.
	if (typeof content == "string")
	{
		textContent = document.createElement("div")
		textContent.innerHTML = content;
		textContent.onclick = activeWindow;
		textContent.parentWindow = this.container;
		this.contentBox.appendChild(textContent);
	}
	else
	{
		textContent = content.cloneNode(true);
		textContent.style.position = "";
		textContent.onclick = activeWindow;
		textContent.parentWindow = this.container;
		textContent.style.visibility = "visible";
		this.contentBox.appendChild(textContent);
	}
	
	//Build the window and insert it into the DOM tree.
	if (this.buttonsOn == true)
	{
		this.buttonBox.appendChild(this.minIcon);
		this.buttonBox.appendChild(this.closeIcon);
	}
	this.titleBox.appendChild(this.buttonBox);
	this.titleBox.appendChild(this.titleText);	
	this.borderBox.appendChild(this.titleBox);
	this.borderBox.appendChild(this.contentBox);
	this.container.appendChild(this.borderBox);
	document.body.appendChild(this.container); 
	document.body.appendChild(this.ifrmBlocker);
	
	//Add window to the window object array, and make it the active window.
	$jsWindows.push(this);	
	this.focus();
	
	//Repositioning errant elements
	this.vertPad = parseInt(this.container.offsetHeight)-parseInt(this.container.clientHeight);
	this.horzPad = parseInt(this.container.offsetWidth)-parseInt(this.container.clientWidth);
	
	this.container.style.width = width + "px";
	this.container.style.height = height + "px";
	this.borderBox.style.width = width + "px";
	this.borderBox.style.height = height + "px";
	
	this.titleBox.style.width = parseInt(this.titleBox.offsetWidth) + "px";
	this.titleBox.style.height = parseInt(this.titleBox.offsetHeight) + "px";
	
	this.contentBox.style.width = parseInt(this.contentBox.offsetWidth) + "px";
	this.contentBox.style.height = parseInt(this.contentBox.offsetHeight) + "px";
	
	if (this.buttonsOn == true)
	{
		this.buttonBox.style.height = parseInt(this.closeIcon.offsetHeight) + "px";
	}
	
	this.borderBox.style.height = parseInt(this.container.clientHeight)-this.vertPad + "px";
	if (this.buttonsOn == true)
	{
		this.buttonBox.style.right = parseInt(this.borderBox.offsetLeft)+parseInt(this.titleBox.offsetLeft) + "px";
		this.buttonBox.style.top = parseInt(this.borderBox.offsetTop)+parseInt(this.titleBox.offsetTop) + "px";
	}
	this.contentBox.style.height = parseInt(this.borderBox.offsetHeight, 10)-parseInt(this.titleBox.offsetHeight, 10) + "px";	
	this.titleBox.style.width = parseInt(this.contentBox.offsetWidth) + "px";
	
	this.ifrmBlocker.style.position = "absolute";
	this.ifrmBlocker.setAttribute("src", "javascript:false");
	this.ifrmBlocker.setAttribute("frameBorder", "0");
	this.ifrmBlocker.style.top = parseInt(this.container.offsetTop) + "px";
	this.ifrmBlocker.style.left = parseInt(this.container.offsetLeft) + "px";
	this.ifrmBlocker.style.width = parseInt(this.container.offsetWidth) + "px";
	this.ifrmBlocker.style.height = parseInt(this.container.offsetHeight) + "px";
	this.ifrmBlocker.style.zIndex = topIndex++;
	this.container.style.zIndex = topIndex++;
	this.ifrmBlocker.style.filter="alpha(style=0,opacity=0)";
}

//Internal close window function.
function closeWindow(event)
{	  
	var evt = new eventObj(event);
	var node = evt.source.parentWindow.parentObj;
	
	if (node.id != currentWindow.id && currentWindow.parentObj.modal == true)
	{
		return false;
	}

	node.close();
}

//This is the focus method, to set the active window.
$jsWindow.prototype.focus = function()
{
	if (document.fireEvent)
	{
		this.container.fireEvent("onclick");
	}
	else
	{	  
		msgEvent = document.createEvent("MouseEvents");
		msgEvent.initMouseEvent("click",true,true,document.defaultView,1,0,0,0,0,false,false,false,false,0,null);
		this.container.dispatchEvent(msgEvent); 
	}
}

//This is the close method to close a window.
$jsWindow.prototype.close = function()
{
	var node = this.container;
	var frm = this.ifrmBlocker;

	for (var i=0; i<$jsWindows.length; i++)
	{
		var winObj = $jsWindows.shift();
		if (winObj.id == node.id)
		{ 	
			//do nothing;
		}
		else
		{
			$jsWindows.push(winObj);
		}
	}
	node.parentNode.removeChild(node);
	frm.parentNode.removeChild(frm);
	currentWindow = false; 
	
	var nextWindow = getTopWindow();
	if (nextWindow)
	{
		nextWindow.focus();
	}
}

//These functions create the min/max/close button objects.
function minIconObj(node)
{
	var newElm = document.createElement("img");
	newElm.defsrc = "images/min_icon.gif";
	newElm.clicksrc = "images/min_icon_click.gif";
	newElm.src = newElm.defsrc;
	newElm.parentWindow = node.container;
	newElm.onmousedown = clickDown;
	newElm.onmouseup = clickUp;
	newElm.onclick = minimize;
	return newElm;
}

function maxIconObj(node)
{
	var newElm = document.createElement("img");
	newElm.defsrc = "images/max_icon.gif";	
	newElm.clicksrc = "images/max_icon_click.gif";
	newElm.src = newElm.defsrc;
	newElm.parentWindow = node.container;
	newElm.onmousedown = clickDown;
	newElm.onmouseup = clickUp;
	newElm.onclick = maximize;
	return newElm; 	
}	

function closeIconObj(node)
{ 
	var newElm = document.createElement("img");
	newElm.defsrc = "images/close_icon.gif";
	newElm.clicksrc = "images/close_icon_click.gif";
	newElm.src = newElm.defsrc;
	newElm.parentWindow = node.container;
	newElm.onmousedown = clickDown;
	newElm.onmouseup = clickUp;
	newElm.onclick = closeWindow; 
	return newElm;	
}

//Button animations
function clickDown(event)
{
	var evt = new eventObj(event);
	var node = evt.source;
	
	//var imagePath = node.src;
	//var imageName = imagePath.split(".");
	//node.src = imageName[0] + "_click.gif";
	node.src= node.clicksrc;
}

function clickUp(event)
{
	var evt = new eventObj(event);
	var node = evt.source;
	//var imagePath = node.src;
	//var splitStart = imagePath.indexOf("_click", 0);
	//var prefix = imagePath.slice(0,splitStart); 
	//node.src = prefix + ".gif";
	node.src = node.defsrc;
}

//Minimize Window Function.
function minimize(event)
{
	var evt = new eventObj(event);
	var node = evt.source.parentWindow.parentObj;
	
	if (node.id != currentWindow.id && currentWindow.parentObj.modal == true)
	{
		return false;
	}
	
	node.maxIcon = maxIconObj(node);
	
	node.maximizeSizeX = parseInt(node.borderBox.offsetWidth);
	node.minimizeSizeX = parseInt(node.contentBox.offsetWidth)+(75-parseInt(node.contentBox.offsetWidth));
	node.maximizeSizeY = parseInt(node.borderBox.offsetHeight);

	node.container.style.width = node.minimizeSizeX + "px";	
	node.titleBox.style.width = node.minimizeSizeX + "px";
	node.borderBox.style.width = node.minimizeSizeX + "px";
	node.ifrmBlocker.style.width = parseInt(node.container.offsetWidth) + "px";
	node.container.style.height = parseInt(node.titleBox.offsetHeight) + "px";
	node.borderBox.style.height = parseInt(node.titleBox.offsetHeight) + "px";
	node.contentBox.defHeight = parseInt(node.contentBox.offsetHeight) + "px";
	node.ifrmBlocker.style.height = parseInt(node.container.offsetHeight) + "px"; 
	node.contentBox.style.height = "0px";
	node.container.resizable = false;
	node.buttonBox.replaceChild(node.maxIcon, node.minIcon); 
	
	evt.consume();
}

//Maximize Window Function.
function maximize(event)
{
	var	evt = new eventObj(event);
	var node = evt.source.parentWindow.parentObj;
	
	if (node.id != currentWindow.id && currentWindow.parentObj.modal == true)
	{
		return false;
	}
	 
	node.minIcon = minIconObj(node);
	
	node.container.style.width = node.maximizeSizeX + "px";
	node.titleBox.style.width = node.maximizeSizeX + "px";
	node.borderBox.style.width = node.maximizeSizeX + "px";
	node.contentBox.style.width = node.maximizeSizeX + "px";
	node.ifrmBlocker.style.width = parseInt(node.container.offsetWidth) + "px";
	node.container.style.height = node.maximizeSizeY + "px";
	node.borderBox.style.height = node.maximizeSizeY + "px";	
	node.contentBox.style.height = parseInt(node.contentBox.defHeight) + "px";
	node.ifrmBlocker.style.height = parseInt(node.container.offsetHeight) + "px";
	node.container.resizable = true;
	node.buttonBox.replaceChild(node.minIcon, node.maxIcon);
	
	evt.consume();
}

//These functions disable, or enable elements.  To be used on inactive windows only.
function disableElements(tagname, node)
{
	var tagElements = node.getElementsByTagName(tagname);
	if (tagElements.length > 0)
	{
		for (var i=0; i<tagElements.length; i++)
		{
			tagElements[i].disabled = "disabled";
		}
	}
}

function enableElements(tagname, node)
{
	var tagElements = node.getElementsByTagName(tagname);
	if (tagElements.length > 0)
	{
		for (var i=0; i<tagElements.length; i++)
		{
			tagElements[i].disabled = false;
		}
	}
} 

//This function is used to get the most recent active window.
function getTopWindow()
{
	var maxIndex = 0;
	var topWindow = false;
	
	for (var i=0; i<$jsWindows.length; i++)
	{ 
		if ($jsWindows[i].container.style.zIndex > maxIndex)
		{
			maxIndex = $jsWindows[i].container.style.zIndex;
			topWindow = $jsWindows[i];
		}
	}
	return topWindow;
}