// JavaScript Document
//
//			wmView.js						View capabilities
//
//											Version 2
//
//											Includes book class for a set of "panes" of information
//											Simplified Panel class to: 
//											- change hide function to delete
//											- remove menu option
//											Explain class
//
//											tooltTip function
//
toolTip = function (e) {
	e = e || window.event;
	if (window.innerWidth) {
		var x = e.clientX + window.pageXOffset;
		var y = e.clientY + window.pageYOffset;
	} else if (document.documentElement.clientWidth) {
		var x = e.clientX + document.documentElement.scrollLeft;
		var y = e.clientY + document.documentElement.scrollTop;
	} else if (document.body.clientWidth) {
		var x = e.clientX + document.body.scrollLeft;
		var y = e.clientY + document.body.scrollTop;
	} else {
		throw new Error ("ToolTip: Unsupported browser");
	}
	if (e.currentTarget) {
		var target = e.currentTarget;
	} else if (e.srcElement) {
		var target = e.srcElement;
	}
	var text = target.getAttribute ("tooltip");
	if (!text) return;
	x += 5;						//	x Offset from mouse for tooltip
	y += 5;						//	y Offset from mouse for tooltip
//
//									Build doc elements
//
	var frame = document.createElement("div");
	frame.className = "tipFrame";
	frame.style.left = x + "px";
	frame.style.top = y + "px";
	frame.style.visibility = "hidden";
	document.body.appendChild(frame);
//									Set content	
	var content = document.createElement("div");
	content.className = "tipContent";
	content.style.top = "0px";
	content.style.left = "0px";
	content.innerHTML = text;
	frame.appendChild(content);
//									Set shadow
	var shadow = document.createElement("div");
	shadow.className = "tipShadow";
	frame.appendChild(shadow);
	shadow.style.height = content.offsetHeight + "px";
//									Display
	var timer = window.setTimeout (show, 100);
//									Remove when mouse leaves tool
	if (target.addEventListener) {
		target.addEventListener("mouseout", mouseout, false);
	} else if (target.attachEvent) {
		target.attachEvent ( "onmouseout", mouseout);
	} else {
		target.onmouseout = mouseout;
		}
	function show () {
		frame.style.visibility = "visible";
		timer = window.setTimeout (hide, 1400);
	}
	function hide () {
		frame.style.visibility = "hidden";
	}
	function mouseout () {
		window.clearTimeout(timer);
		document.body.removeChild(frame);
		if (target.removeEventListener) {
			target.removeEventListener ("mouseout", mouseout, false);
		} else if (target.detachEvent) {
			target.detachEvent ("onmouseout", mouseout);
		} else {
			target.mouseout = null;
		}
	}
	
}
//
//													Animantion Function
//
//													Basic function to animate CSS styles
//
//													element - an HTML element to be animated
//													time - time for which animation is to run
//													animation - an object containing a set of functions
//													to be applied to style attributes.
//													Each function is called with parameters:
//														f - current frame
//														t - current total interval
//													finish - a function to call when animation is complete.
//														element - the element animated is passed to finish.
//
function animateStyle (element, time, animation, finish) {
	var f = 0;
	var deltaT = 0;
	var saveCursor = element.style[cursor];
	var intId = setInterval(displayFrame, 30);
	element.style[cursor] = "wait";
	return;
//													Nested function performs animation
	function displayFrame () {
//													Check for completion
		if (deltaT > time) {							// complete
			clearInterval (intId);
			element.style[cursor] = saveCursor;
			if (finish) finish (element);			//	call end function if specified
			return;
		}
//													Animate style
		for (var prop in animation) {
			try {
				element.style[prop] = animation[prop] (f, deltaT);
			} catch (e) {}
		}
//													increment for next call
		f++;
		deltaT = deltaT + 30;
	}
}
		
	
function Panel (title, opts) {
//
//													Store params
//
	this.panelTitle = title;
	this.divBase = title.replace(/\s/g, '_');
	this.params = {};
	if (opts) {
		for (opt in opts) {
			this.params[opt] = opts[opt];
		}
	}
//
//													Set defaults
//
	this.params.width = this.params.width || 300;
	this.params.height = this.params.height || 400;
//
//													Set up container
//
	this.panel = document.createElement("div");
	this.panel.id = this.divBase + "_Panel";
	this.panel.style.width = (this.params.width + 15) + "px";
	this.panel.style.height = (this.params.height + 15) + "px";
	this.panel.style.left = (this.params.left || 120) + "px";
	this.panel.style.top = (this.params.top || 120) + "px";
	this.panel.style.position = "absolute";
	this.panel.style.visibility = "hidden";
//
//													Set shadow
//
	this.shadow = document.createElement("div");
	this.shadow.className = "panelShadow";
	this.shadow.style.width = this.params.width + "px";
	this.shadow.style.height = this.params.height + "px";
	this.panel.appendChild(this.shadow);
//
//													Set Frame
//
	this.frame = document.createElement("div");
	this.frame.className = "panelFrame";
	this.frame.style.width = this.params.width + "px";
	this.frame.style.height = this.params.height + "px";
//
//													Set Header
//
	this.header = document.createElement("div");
	this.header.className = "panelTitle";
	this.header.style.width = (this.params.width - 10) +"px";
	this.header.onmousedown = this.drag;
	this.actInd = document.createElement("div");	//	Active Icon
	this.actInd.className = "panelIcon";
	this.actInd.style.left = "5px";
	this.actInd.innerHTML = '<img src="Assets/Light.gif" />';
	this.actInd.id = this.divBase + "_Act";
	this.header.appendChild(this.actInd);
	this.caption = document.createElement("div");
	this.caption.className = "panelCaption";		// Panel caption
	this.caption.innerHTML = this.panelTitle;
	this.header.appendChild(this.caption);
	this.closer = document.createElement("div");	// Panel remove icon
	this.closer.className = "panelIcon";
	this.closer.style.left = (this.params.width - 23) + "px";
	this.closer.innerHTML = '<img src="Assets/Hide.gif" />';
	this.closer.onclick = this.hide;
	this.closer.id = this.divBase + "_Hide"
	this.header.appendChild(this.closer);
	this.frame.appendChild(this.header);
//
//													Set Content
//
	this.content = document.createElement("div");
	this.content.id = this.divBase + "_Content";
	this.content.className = "panelContent";
	this.content.style.width = (this.params.width - 10) + "px";
	this.content.style.height = (this.params.height - 35) + "px";
//
//													Append to document
//
	this.frame.appendChild(this.content);
	this.panel.appendChild(this.frame);
	document.body.appendChild(this.panel);
}
Panel.prototype.setXY = function (x, y) {
//
//													Set (x,y) for panel
//
	this.panel.style.left = x + "px";
	this.panel.style.top = y + "px";
}
Panel.prototype.load = function (content, label) {
	if ((typeof content != "string") && (content.nodeName != "DIV")) {
		throw new Error ("Panel: Invalid parameter to .load method <content>: " +content);
	}
	if ((label) && (typeof label != "string")) {
		throw new Error ("Panel: Invalid parameter to .load method <label>: " + label);
	}
	if (label) {
		this.caption.innerHTML = this.panelTitle + ": " + label;
	}
	if (typeof content == "string") {
		this.content.innerHTML = content;
	} else {
		this.content.appendChild(content);
	}
	return;
}
Panel.prototype.show = function (state) {
//
//													Show panel if state true, else hide it
//
	if (state == null) state = true;
	if (state) {
		this.panel.style.visibility = "visible";
		this.content.style.visibility = "inherit";
		return;
	} else {
		this.panel.style.visibility = "hidden";
	}
	return;
}
Panel.prototype.clear = function () {
	document.body.removeChild(this.panel);
}
Panel.prototype.status = function (phase) {
	if (phase == 0) {
		this.actInd.innerHTML = '<img src="Assets/Light.gif" />';
		return;
	}
	if (phase < 3) {
		this.actInd.innerHTML = '<img src="Assets/GreenLight.gif" />';
	} else {
		this.actInd.innerHTML = '<img src="Assets/RedLight.gif" />';
	}
	return;
}
//
//													Panel event handling functions
//
//													NOTE
//													Event handlers cannot use "this" variables of
//													the Panel object, as "this" is set to the target
//													of the interupt.
//
Panel.prototype.hide = function (ev) {
	ev = ev || window.event;
	if (window.event) {
		var self = ev.srcElement;
	} else {
		var self = ev.target;
	}
	var parent = self.parentNode;
	var endBase = parent.id.lastIndexOf ("_Hide");
	var divBase = parent.id.substring(0,endBase);
	var panelDiv = document.getElementById (divBase + "_Panel");
	var contentDiv = document.getElementById (divBase + "_Content");
	contentDiv.style.visibility = "hidden";
	panelDiv.style.visibility = "hidden";
}
Panel.prototype.drag = function (e) {
	e = e || window.event;
	var startX = e.clientX;
	var startY = e.clientY;
	if (window.event) {
		var self = e.srcElement;
	} else {
		var self = e.target;
	}
	while (self.parentNode != document.body) {
		self = self.parentNode;
	}
	var origX = self.offsetLeft;
	var origY = self.offsetTop;
	var deltaX = startX - origX;
	var deltaY = startY - origY;
	if (document.addEventListener) {
		document.addEventListener ("mousemove", moveHandler, true);
		document.addEventListener ("mouseup", upHandler, true);
	} else if (document.attachEvent) {
		self.setCapture();
		self.attachEvent ("onmousemove", moveHandler);
		self.attachEvent ("onmouseup", upHandler);
		self.attachEvent ("onlosecapture", upHandler);
	} else {
		var oldMove = document.onmousemove;
		var oldUp = document.onmouseup;
		document.onmousemove = moveHandler;
		document.onmouseup = upHandler;
	}
	if (e.stopPropagation) {
		e.stopPropagation();
	} else {
		e.cancelBubble = true;
	}
	if (e.preventDefault) {
		e.preventDefault();
	} else {
		e.returnValue = false;
	}
	function moveHandler (ev) {
		ev = ev || window.event;
		self.style.left = (ev.clientX - deltaX) + "px";
		self.style.top = (ev.clientY - deltaY) + "px";
		if (ev.stopPropagation) {
			ev.stopPropagation();
		} else {
			ev.cancelBubble = true;
		}
	}
	function upHandler (ev) {
		ev = ev || window.event;
		if (document.removeEventListener) {
			document.removeEventListener ("mousemove", moveHandler, true);
			document.removeEventListener ("mouseup", upHandler, true);
		} else if (document.detachEvent) {
			self.detachEvent ("onlosecapture", upHandler);
			self.detachEvent ("onmouseup", upHandler);
			self.detachEvent ("onmousemove", moveHandler);
			self.releaseCapture();
		} else {
			document.onmouseup = oldUp;
			document.onmousemove = oldMove;
		}
		if (ev.stopPropagation) {
			ev.stopPropagation();
		} else {
			ev.cancelBubble = true;
		}
	}
}
function Book (displayDiv, bookName) {
//
//												Book class
//
//												This class manages a set of pages (called panes to
//												avoid confusion with webpages). Panes are loaded using
//												the .load method changed with the .show method.
//												The .hide method hides the book.
//												A .setOptions method is provided to allow other style 
//												parameters
//												of the display div to be changed.
//
//												displayDiv - a div to contain the set of panes
//												(book pages).
//
//												bookName - a string to be used as the root for all
//												pane divs created in this book. This must be
//												valid for use in the div id field
//
	if (displayDiv.nodeName != "DIV") {
		throw new Error ("Book: Invalid parameter <displayDiv>: " + displayDiv);
	}
	if (typeof bookName != "string") {
		throw new Error ("Book: Invalid parameter <bookName>: " + bookName);
	}
	this.viewDiv = displayDiv;					// save display div for book
	this.bookIdBase = bookName + "_C";			// save pane div prefix
	this.baseDiv = document.createElement("div");
	this.baseDiv.id = this.bookIdBase + "0";
	this.baseDiv.style.left = "0px";
	this.baseDiv.style.top = "0px";
	this.baseDiv.style.width = this.viewDiv.style.width;
	this.baseDiv.style.height = this.viewDiv.style.height;
	this.baseDiv.style.backgroundColor = this.viewDiv.style.backgroundColor;
	this.baseDiv.style.visibility = "hidden";
	this.viewDiv.appendChild (this.baseDiv);
	this.currentDivIndex = 0;					// No div is currently visible
	this.count = 1;								// initialize number of panes in set
}
Book.prototype.setOptions = function (params) {
//
//												params must be a javascript object containing valid
//												style settings for a div element.
//
	if (params != Object) {
		throw new Error ("Book: Invalid parameters for setOptions <options>: " + options);
	}
	for (var opt in params) {
		this.viewDiv.style[opt] = params[opt];
	}
}
Book.prototype.load = function (content) {
	var paneDiv = document.createElement ("div");
	paneDiv.id = this.bookIdBase + this.count;
	paneDiv.style.visibility = "hidden";
	paneDiv.style.position = "absolute";
	paneDiv.style.top = "0px";
	paneDiv.style.left = "0px";
	if (typeof content == "string") {
		paneDiv.innerHTML = content;
	} else {
		paneDiv.appendChild (content);
	}
	
	this.viewDiv.appendChild (paneDiv);
	return this.count++;
}
Book.prototype.show = function (index) {
//
//													Set pane to show
//
	var i = index || this.currentDivIndex;			// default to current page
	if ((i < 0) || (i > (this.count - 1))) {
			throw new Error ("Book: requested out of range :" + i + "max: " + this.count);
	}
	var currentDiv = document.getElementById (this.bookIdBase + this.currentDivIndex);
	var nextDiv = document.getElementById (this.bookIdBase + i);
	nextDiv.style.width = this.viewDiv.offsetWidth + "px";
	nextDiv.style.height = this.viewDiv.offsetHeight + "px";
	nextDiv.style.overflow = "auto";
	if (i == this.currentDivIndex) return;
	turnPane (this.viewDiv, currentDiv, nextDiv);
	this.currentDivIndex = i;
	return;
}
Book.prototype.hide = function () {
//
//													Hide current visible pane
//
	if (this.currentDivIndex != 0) {
		var currentDiv = document.getElementById (this.pDivBase + this.currentDivIndex);
		var nextDiv = this.baseDiv;
		turnPane (this.viewDiv, currentDiv, nextDiv);
	}
	this.viewDiv.style.visibility = "hidden";		// Hide display div
	this.currentDivIndex = 0;						// No div is showing 
}
//
//													Turn pane code
//
function turnPane(viewDiv, current, next) {
	var wW = viewDiv.offsetWidth;
	var y = viewDiv.offsetHeight;
	var deltaX = (wW / 20).toFixed(0);
	var i = 19;
	var intTime = setInterval(paneTurn, 50);
	return;
	function paneTurn () {
		var x = wW - (i * deltaX);
		next.style.clip = "rect(0px, " + x + "px, " + "auto, 0px)";
		current.style.clip = "rect(0px, " + wW + "px, " + "auto, " + x + "px)"; 
		next.style.visibility = "visible";
		if (i > 0) {
			i--;
			} else {
			clearInterval (intTime);			
			current.style.visibility = "hidden";
			current.style.clip = "rect(auto, auto, auto, auto)";
			}
		return;
	}
}
function Command (commandId, opts) {
//
//														Store default options
//
	this.option = {};
	this.option.width =160;
	this.option.left = 10;
	this.option.top = 10;
	this.option.height = 25;
//
//														Overide defaults with opts
//
	if (opts) {
		for (opt in opts) {
			this.option[opt] = opts[opt];
		}
	}
//														Debug
	this.cmdDiv = document.getElementById (commandId);
	this.menuDiv = document.createElement("div");
	this.menuDiv.className = "cmdMenu";
	this.menuDiv.style.position = "absolute";
	this.menuDiv.style.width = (this.option.width +8) + "px";
	this.menuDiv.style.height = "8px";
	this.menuDiv.style.top = this.option.top + "px";
	this.menuDiv.style.left = this.option.left + "px";
	this.menuDiv.id = this.cmdDiv.id + "_Menu";
	this.menuDiv.style.visibility = "hidden";
//
//														Build Shadow Div
//
	this.menuShadow = document.createElement("div");
	this.menuShadow.id = this.cmdDiv.id + "_MenuShadow";
	this.menuShadow.className = "cmdMenuShadow";
	this.menuShadow.style.width = this.option.width + "px";
	this.menuShadow.style.top = "10px";
	this.menuShadow.style.left = "10px";
//
//														Build Menu Frame
//
	this.menuFrame = document.createElement("div");
	this.menuFrame.className = "cmdMenuFrame";
	this.menuFrame.id = this.cmdDiv.id + "_MenuFrame";
	this.menuFrame.style.top = "0px";
	this.menuFrame.style.left = "0px";
	this.menuFrame.style.width = this.option.width + "px";
//
//														Initialize menu area
//
	this.menuHeight = 0;
	this.menuCount = 0;
	this.menuDiv.appendChild(this.menuFrame);
	this.menuDiv.appendChild(this.menuShadow);
	this.cmdDiv.appendChild (this.menuDiv);
	this.cmdDiv.onclick = this.showMenu;
}
Command.prototype.addMenuItem = function (label, action) {	
//
//														Add to menu
//
	var	menuItem = document.createElement ("div");
	menuItem.id = this.cmdDiv.id + "_M" + this.menuCount;
	menuItem.className = "cmdMenuItem";
	menuItem.style.width = this.option.width + "px";
	if (this.menuCount > 0) {
		var prevItemId = this.cmdDiv.id + "_M" + (this.menuCount - 1);
		var prevItem = document.getElementById (prevItemId);
		prevItem.style.borderBottom = "3px outset #FFFF99";
		this.menuHeight = this.menuHeight + 3;
		menuItem.style.borderTop = "3px outset #FFFF99";
	}
	menuItem.style.top = this.menuHeight + "px";
	menuItem.style.backgroundColor = "#ffffcc";
	menuItem.innerHTML = label;
	menuItem.onclick = this.menuAction;
	menuItem.setAttribute ("menuItemAction", action);
	this.menuHeight = this.menuHeight + 25;
	this.menuDiv.style.height = (this.menuHeight)  + "px";	
	this.menuFrame.style.height = (this.menuHeight) + "px";
	this.menuShadow.style.height = (this.menuHeight) + "px";
	this.menuFrame.appendChild (menuItem);
	return this.menuCount++;
}
Command.prototype.showMenu = function (ev) {
	ev = ev || window.event;
	if (window.event) {
		var self = ev.srcElement;
	} else {
		var self = ev.target;
	}
	var menuDiv = document.getElementById (self.id + "_Menu");
	menuDiv.style.visibility = "visible";
	var timer = window.setTimeout(hide, 5000);
	function hide () {
		menuDiv.style.visibility = "hidden";
	}
}
Command.prototype.menuAction = function (ev) {
	ev = ev || window.event;
	if (window.event) {
		var self = ev.srcElement;
		window.event.cancelBubble = true;
	} else {
		var self = ev.target;
		ev.stopPropagation();
	}
	var label = self.innerHTML;
	var action = self.getAttribute ("menuItemAction");
	eval(action + "('" + label + "');");
	var menuDivId = self.id.substring(0, self.id.lastIndexOf("_")) + "_Menu";
	var menuDiv = document.getElementById(menuDivId);
	menuDiv.style.visibility = "hidden";
}
//
//										Validation Functions
//
//											Designed to work with forms
//
//											id - document node to contain error message
//											value - string to check
//											spString - valid specical characters
//
//											formError - displays error & increments
//											wm.errorCount
//
//											clearError - clears message if any and
//											decrements wm.errorCount.
//
function checkFieldAlpha (id, value, spString, blankOK) {
//
//										pass in:
//											id - the node for an error message
//											value - a String value to check
//											spString - a String of valid specials
//
	if ((((blankOK) && (blankOK != true)) || (!blankOK)) &&
		(value.length < 1)) {
		formError (id, "Field must not be blank");
	}
	for (var i=0; i < value.length; i++) {
		var charA = value.charAt(i);
		if ((charA >= "a") && (charA <= "z")) continue;
		if ((charA >= "A") && (charA <= "Z")) continue;
		if (spString != null) {
			var ix = spString.indexOf (charA);
		} else {
			var ix = -1;
		}
		if (ix > -1) continue;
		formError (id, "Character: " + charA + " is not allowed in this field");
		return false;
	}
	return true;
}
function checkFieldAlphaNum (id, value, spString, blankOK) {
//
//										pass in:
//											id - the node for an error message
//											value - a String value to check
//											spString - a String of valid specials
//
	if ((((blankOK) && (blankOK != true)) || (!blankOK)) &&
		(value.length < 1)) {
		formError (id, "Field must not be blank");
	}
	for (var i=0; i < value.length; i++) {
		var charA = value.charAt(i);
		if ((charA >= "a") && (charA <= "z")) continue;
		if ((charA >= "A") && (charA <= "Z")) continue;
		if ((charA >= "0") && (charA <= "9")) continue;
		if (spString != null) {
			var ix = spString.indexOf (charA);
		} else {
			var ix = -1;
		}
		if (ix > -1) continue;
		formError (id, "Character: " + charA + " is not allowed in this field");
		return false;
	}
	return true;
}
function checkFieldNum (id, value, spString, blankOK) {
//
//											Field must be numeric
//
	if ((((blankOK) && (blankOK != true)) || (!blankOK)) &&
		(value.length < 1)) {
		formError (id, "Field must not be blank");
	}
	for (var i=0; i < value.length; i++) {
		var charA = value.charAt(i);
		if ((charA >= "0") && (charA <= "9")) continue;
		if (spString != null) {
			var ix = spString.indexOf (charA);
		} else {
			var ix = -1;
		}
		if (ix > -1) continue;
		formError (id, "Character: " + charA + " is not allowed in this field");
		return false;
	}
	return true;	
}
function checkFieldMail (id, eMail) {
//
//										pass in:
//											id - the node for an error message
//											eMail - a String value to check
//
	if (eMail.length < 1) {
		formError (id, "Field must not be blank");
	}
//										Check name part of e-mail address
	var i = 0;							// set iterator
	for (i; i < eMail.length; i++) {
		var charA = eMail.charAt(i);
		if ((charA >= "a") && (charA <= "z")) continue;
		if ((charA >= "A") && (charA <= "Z")) continue;
		if ((charA >= "0") && (charA <= "9")) continue;
		if (charA == "." || charA == "-" || charA == "_") continue;
		if (charA == "@") break;
		formError (id, "Character: " + charA + " is not allowed in this field");
		return false;
	}
//										Ends with the @ sign
	if (charA != "@") {
		formError (id, "Must contain an @ character");
		return false;
	}
//										Check domain part of e-mail
	if (i++ >= eMail.length) {
		formError (id, "Domain not specified");
		return false;
	}
	for (i; i < eMail.length; i++) {
		charA = eMail.charAt(i);
		if ((charA >= "a") && (charA <= "z")) continue;
		if ((charA >= "A") && (charA <= "Z")) continue;
		if ((charA >= "0") && (charA <= "9")) continue;
		if (charA == "-") continue;
		if (charA == ".") break;
		formError (id, "Character: " + charA + " is not allowed in domain");
		return false;
	}
	if (charA != ".") {
		formError (id, "Invalid domain format");
		return false;
	}
	if (i++ >= eMail.length) {
		formError (id, "Invalid domain format");
		return false;
	}
	for (i; i < eMail.length; i++) {
		charA = eMail.charAt(i);
		if ((charA >= "a") && (charA <= "z")) continue;
		if ((charA >= "A") && (charA <= "Z")) continue;
		if (charA == ".") continue;
		formError (id, "Invalid character (" + charA + ") in domain");
		return false;
	}
	if (charA == ".") {
		formError (id, "Domain cannot end with a period");
		return false;
	}
	return true;
}
function clearError (id) {
	var errorId = id + "err";
	var error = document.getElementById(errorId);
	if (error) {
		var parent = error.parentNode;
		parent.removeChild(error);
		wm.errorCount--;
	}
}
function formError (id, message) {
	var label = document.getElementById(id);
	var errorId = id + "err";
	var errorMessage = '<div class="formError" id="' + errorId +
		'" >' + message + '</div>';
	var content = label.innerHTML;
	content = content + errorMessage;
	label.innerHTML = content;
	wm.errorCount++;
}