/**
 * SiteHandler.js - Standardized page handler for all Kensit site pages.
 * 
 * @author			Lorne Nicol, Kensit Technologies
 * @sdoc				SiteHandler.sdoc
 * @namespace		myLibrary.myNamespace
 * @version			1.0.0
 */
var	bBrowserIE = (navigator.appName.indexOf("Microsoft") !== -1);
var	bBrowserV401 = (document.URL);
var objHeader, nHdrStartLoc, sCurrPageType;
var sFrameMode = '', sHTML = '', sMailTo, sRootFolder;
var sMenuOffID;

var myPage = new DynPage();
var myFiles = new Files(myPage);

/** @id Browser
 * Browser* - Browser-dependent equivalent DOM values.
 */

/*
 * DocH - height of object document.
 */
function BrowserDocH(oDoc) {
	if (bBrowserIE) {
		return oDoc.documentElement.scrollHeight;
	}
	else {
		return oDoc.documentElement.offsetHeight;
	}
}

/*
 * DocTop - Vertical position of object in window.
 */
function BrowserDocTop(obj) {
	if (bBrowserIE) {
		return obj.offsetTop;
	}
	else {
		return obj.offsetTop;
	}
}

/*
 * ScrollY - Vertical scrolling location on page.
 */
function BrowserScrollY(sNewPos) {
	if (sNewPos) {
		document.documentElement.scrollTop = sNewPos;
	}
	else {
		if (bBrowserIE) {
			if (bBrowserV401) {
				return document.documentElement.scrollTop;
			}
			else {
				return document.body.scrollTop;
			}
		}
		else {
			return window.pageYOffset;
		}
	}
}

/*
 * OnloadSet - Changes the onload event handler.
 */
function BrowserOnloadSet(obj,fpFunc) {
	if (bBrowserIE) {
		obj.attachEvent('onload',fpFunc);
	}
	else {
		obj.onload = fpFunc;
	}
}

/*
 * WndwH - Vertical size of browser window.
 */
function BrowserWndwH() {
	if (bBrowserIE) {
		if (bBrowserV401) {
			return document.documentElement.clientHeight;
		}
		else {
			return document.body.clientHeight;
		}
	}
	else {
		return window.innerHeight;
	}
}

/*
  BuildFooter - Write standard page-end HTML for all pages.
    This is coupled with SetupPage which creates the page-start HTML.
    Done:
      Close PageData,PageLeft divisions (started by SetupPage).
      Build PageXtra division.
      Build PageFoot division. 
*/
function BuildFooter(sW3CStd) {
var objLeft, sHTMLType='';
	if (!StringHas(sCurrPageType,'NoLeft')) {
		StringHTML('</div></div>');
	}
	if(!StringHas(sCurrPageType,'NoXtra')) {
		StringHTML('<div id="PageXtra" class="PageXtra">');
		StringHTML(HTMLPageXtra());
		StringHTML('</div>');
	}
  StringHTML('</div>');
	if (!StringHas(sCurrPageType,'NoLeft')) {
		if (StringHas(sCurrPageType,'NoXtra')) {
			objLeft = document.getElementById('PageLeft');
			objLeft.style.width = '100%';
		}
	}
	StringHTML('<div class="PageFoot"><hr>');
	if (sW3CStd) {
		if (StringHas(sW3CStd,'HTML4.01')) {
			sHTMLType = 'HTML4.01';
		}
		if (StringHas(sW3CStd,'XHTML1.0')) {
			sHTMLType = 'XHTML1.0';
		}
		if (sHTMLType !== '') {
			StringHTML(
			 '<a href="http://validator.w3.org/check/referer" target=External>' +
			 '<img class="W3CStd" src="' + myPage.root + 'Common/W3C_Valid' + sHTMLType + '.gif" ' +
			 ' alt="Valid ' + sHTMLType + '!  Click and validate that this page conforms ' +
			 'to the W3C standard."/></a>'
			 );
		}
		if (StringHas(sW3CStd,'CSS')) {
			StringHTML(
			 '<a href="http://jigsaw.w3.org/css-validator/" target=External>' +
			 '<img class="W3CStd" src="' + sRootFolder + 'Common/W3C_ValidCSS.gif" ' +
			 ' alt="Valid CSS!  Click and validate that this page conforms ' +
			 'to the W3C standard."/></a>'
			 );
		}
	}
	StringHTML(
	 '<span style="text-align: right; float: right">' +
	 'Last updated: ' + document.lastModified +
	 '</span></div>'
	 ,'Go');
}

/*
 * BuildPageFrame - Write HTML that creates an iframe on the page.
 */
function BuildPageFrame(sHTMLPage, sFrameNm) {
	StringHTML(
	 '<iframe id="' + sFrameNm + 'Frame" name="' + sFrameNm + 'Target' + '"' +
	 ' class="PageFrame" frameborder="0" scrolling="no"' +
	 ' src="' + sHTMLPage + '"' +
	 ' onload="ResizeFrame(' + "'" + sFrameNm + "Frame')");
	StringHTML('"></iframe>','Go');
}

/*
 * BuildSideMenu - Build the common side menu items.
 */
function BuildSideMenu() {
	StringHTML(HTMLMenu('Website Addenda',
	 HTMLMenuLink('What&#39;s New','WhatsNew.htm') +
	 HTMLMenuLink('Sitemap','javascript: myPage.SetUnderConstruction(\'PageContent\');') +
	 HTMLMenuLink('Website History','WebsiteHistory.htm') +
	 HTMLMenuLink('Website Design',sRootFolder + 'AboutThisWebsite.htm',
	  'Learn about how this website was constructed ' +
	  'and the standards it follows')
	 ));
}

/*
 * BuildUCBlock - Write HTML for embedding an Under Construction block.
 */
function BuildUCBlock(nBlockType) {
	switch (nBlockType) {
		case 2: {
			sHTML = '<img src="' + sRootFolder + 'Common/UCSign.gif" ' +
			 'alt="This area is still under construction">';
		}
		break;
		
		default: {
			sHTML = '<div class=PageConstruction>' +
			 '<img src="' + sRootFolder + 'Common/UCBanner.gif" ' +
			 'style="width: 100%">' +
			 '<img src="' + sRootFolder + 'Common/UCFallingIcon.gif" ' +
			 'style="float: left">' +
			 '<img src="' + sRootFolder + 'Common/UCFallingIcon.gif" ' +
			 'style="float: right">' +
			 '<br><br>This content of this page is still under construction.&nbsp;' +
			 'Incomplete parts are denoted with a construction sign image.&nbsp;' +
			 '<br><br>' +
			 "Feel free to nag the site's Webmaster if you wish to see the page's completion.&nbsp;" +
			 '</div><br>';
		}
		break;
	}
	document.write(sHTML);
}

/*
 * CounterHTML - Put BraveNet counter on page.
 */
function CounterHTML(nCtrID) {
	document.write(HTMLCounter(nCtrID))
}

/*
 * DynPage* - Page Handler object for dynamic content management.
 */
function DynPage() {
	this.IsIE = (navigator.appName.indexOf("Microsoft") !== -1);
	this.IsLocal = (location.protocol == 'file:')
	this.obj = new Array();
	this.root = '';
	this.xmlhttp = new Array();
	this.xmlobj = new Array();
}

DynPage.prototype.Obj = function (sIDName) {
	for (var i = 0;i < this.obj.length; i++) {
		if (this.obj[i].id == sIDName) break;
	}
	if (i == this.obj.length) {
		this.obj.push(document.getElementById(sIDName));
	}
	return this.obj[i]
}

DynPage.prototype.SetHistoryData = function (sLoc,n) {
	var j,sFolder,sName;
	this.HistoryList = (this.HistoryList)?this.HistoryList:myFiles.GetHistory(sLoc);
	var iCnt = (n)?n:this.HistoryList.length;
	for (var i = 0; i < iCnt; i++) {
		this.SetSnippet('D'+i,this.root + this.HistoryList[i]);
	}		
}

DynPage.prototype.SetHistoryIDs = function (sLoc) {
	this.HistoryList = (this.HistoryList)?this.HistoryList:myFiles.GetHistory(sLoc);
	var sHTML = '<ul>';
	for (var i = 0; i < this.HistoryList.length; i++) {
		sHTML = sHTML + '<li id="D' + i + '"></li>';
	}
	document.write(sHTML + '</ul>');
}

DynPage.prototype.SetSnippet = function (sID,sLoc) {
	if (sID=='document') {
		myFiles.Read(sLoc, document);
	}
	else {
		myFiles.Read(sLoc, this.Obj(sID));
	}
}

DynPage.prototype.SetUnderConstruction = function (sID) {
	this.SetSnippet(sID,'Snippets/UnderConstruction.htm');
}

/*
 * HTML* - Return snippets of HTML to be written to document.
 */

/*
 *   Counter - Extracted HTML for BraveNet counter.
 */
function HTMLCounter(nCtrID) {
   return '<script language="JavaScript"' +
    ' type="text/javascript"' +
    ' src="http://pub21.bravenet.com/counter/code.php?id=' +
    nCtrID + '&amp;usernum=1747027887&amp;cpv=2"></script>'
}

/** @id Files */
function Files(objPage) {
	this.file = new Array();
	this.page = objPage;
	//IE won't do local files (access denied)
	this.xmlok = !(this.page.IsIE && this.page.IsLocal);
	//Split value changes if local or on site
	this.splitstr = (this.page.IsLocal)?'\r\n':'\n';
}

Files.prototype.Data = function(sLoc) {
	var x = this.Read(sLoc);
	return this.file[x].data;
}

Files.prototype.Dir = function(sStr) {
	var aDir = new Array();
	if (!this.dirlist) {
		var x = this.Read(this.page.root + '_dir.txt');
		this.dirlist = this.file[x].data.split(this.splitstr);
		this.dirlist.pop();
	}
	for (var i = 0; i < this.dirlist.length; i++) {
		if (this.dirlist[i].indexOf(sStr) > -1) {
			aDir.push(this.dirlist[i]);
		}
	}
	return aDir;
}

Files.prototype.GetHistory = function(sLoc) {
	var sURLs = new Array(), sDates = new Array(), sDate, j,x;
	var aDir = this.Dir('Snippets/History_');
	for (var i = 0; i < aDir.length; i++) {
		if (aDir[i].substr(0,9)=='Snippets/' ||
		 aDir[i].substr(0,sLoc.length+1)==sLoc + '/') {
			x = aDir[i].indexOf('Snippets/History_') + 17;
			sDate = aDir[i].substr(x,10);
			for (j = 0; j < sDates.length;j++) {
				if (sDate > sDates[j] ||
				    (sDate == sDates[j] && x > 17)) {
					break;
				}
			}
			x = sURLs.splice(j,0,aDir[i]);
			x = sDates.splice(j,0,sDate);
		}
	}
	return sURLs;
}

/*
 * Read - Object for a file read request (using XMLhttp).
 */
Files.prototype.Read = function(sLoc,fASyncCallback) {
	for (var i = 0; i < this.file.length; i++) {
		if (this.file[i].loc == sLoc) {
			break;
		}
	}
	if (i == this.file.length) {
		this.file.push(new Object());
		this.file[i].loc = sLoc;
		var sType = 'None';
		if (window.XMLHttpRequest && this.xmlok) {
			// code for IE7, Mozilla, Safari, etc.
			this.xmlhttp=new XMLHttpRequest();
			sType = 'XMLHttpRequest';
		}
		else {
			if (window.ActiveXObject) {
				//code for IE (before 7, or local)
				try {this.xmlhttp = new ActiveXObject('Msxml2.XMLHTTP');}
				catch (e) {
					try {this.xmlhttp = new ActiveXObject('Microsoft.XMLHTTP');}
					catch (E) {
					}
				}
				if (this.xmlhttp) {
					sType = 'ActiveX';
				}
			}
		}
		if (sType !== 'None') {
			if (fASyncCallback) {
				this.xmlhttp.onreadystatechange = ReadCallback;
				this.xmlhttp.open('GET', sLoc, true);
				this.file[i].xmlhttp = this.xmlhttp;
				this.file[i].action = fASyncCallback;
			}
			else {
				this.xmlhttp.open('GET', sLoc, false);
			}
			if (sType == 'XMLHttpRequest') {
				if (fASyncCallback) {
					this.file[i].xmlhttp.send(null);
				}
				else {
					this.xmlhttp.send(null);
				}
			}
			else {
				if (fASyncCallback) {
					this.file[i].xmlhttp.send();
				}
				else {
					this.xmlhttp.send();
				}
			}
			if (!fASyncCallback) {
				this.file[i].data = this.xmlhttp.responseText;
			}
		}
		else {
			alert('Unable to read site file:' + sLoc);
		}
	}
	else {
		if (fASyncCallback) {
			fASyncCallback(this.file[i].data);
		}
	}
	return i;
}

function ReadCallback() {
	for (var i = 0; i < myFiles.file.length; i++) {
		if (myFiles.file[i].xmlhttp) {
			if (myFiles.file[i].xmlhttp.readyState==4) {
				myFiles.file[i].data = myFiles.file[i].xmlhttp.responseText;
				delete myFiles.file[i].xmlhttp;
				switch (typeof(myFiles.file[i].action)) {
					case 'object':
						if (myFiles.file[i].action === document) {
							document.write(myFiles.file[i].data);
						}
						else {
							myFiles.file[i].action.innerHTML = myFiles.file[i].data;
						}
						break;
					case 'function':
						myFiles.file[i].action(myFiles.file[i].data);
						break;
					default:
						break;
				}
			}
		}
	}	
}

/*
 *   EmailBox - Email me block.
*/
function HTMLEmailBox(sEmailID, sEmailText) {
	return HTMLInfoBox('Contact',
	 '<div class="EmailBox">' +
	 HTMLMailTo(sEmailID, sEmailText, 'EmailBox',
	 '<img src="' + sRootFolder + 'Common/MailboxAnimated.gif" align=center border=0'
	 + ' alt="Click to start your default email program and open a new email letter">')) + 
	 '</div>'
}

function HTMLMailTo(sEMailID, sPageText, sClass, sPagePrefix) {
	var sMailTo
	sMailTo = '<a'
	if (sClass) {
		sMailTo = sMailTo + ' class="' + sClass + '"'
	}
	sMailTo = sMailTo +
	 ' title="Click here to start your default email program and open a new email letter"' +
	 ' href="mailto:';
	if (sEMailID=='Personal') {
		sMailTo = sMailTo + 'Lorne Nicol'
	}
	else {
		sMailTo = sMailTo + sEMailID;
	}
	sMailTo = sMailTo + '<&#108&#111&#114&#110&#105&#99' +
	 '&#64&#116&#101&#108&#117&#115.&#110&#101&#116>">';
	if (sPagePrefix) {
		sMailTo = sMailTo + sPagePrefix;
	}
	sMailTo = sMailTo + sPageText + '</a>';
	return sMailTo
}

function HTMLIFrameBox(sName, sHdg, nH, sSrc) {
	return HTMLInfoBox(sHdg,
	 '<iframe id="' + sName +'" name="' + sName +'"' +
	 ' frameborder=0 src="' + sSrc + '"' +
	 ' style="height:' + nH + '; width: 100%; margin: 0px"></iframe>'
	 );
}

function HTMLHeaderMenu() {
	return '***No HTMLHeaderMenu defined***'
}

function HTMLInfoBox(sHdg, sDtl) {
	return '<div class="InfoBox"><div class="InfoHdg">' +
	 sHdg + '</div><div class="InfoDtl">' +
	 sDtl + '</div></div>'
}

function HTMLMenu(sHdg, sMenuItems) {
	return HTMLInfoBox(sHdg,
	 '<ul class="Menu">' + sMenuItems + '</ul>')
}
/*
 * 
 */
function HTMLMenuLink(sLabel, sHref, sTitleText, sLIData) {
	return '<li'
	 + ((sLIData)?
	  ' onmouseover="MenuItemOn(&#39;' + sLabel + '&#39;)"'
	  + ' onmouseout="sMenuOffID=&#39;' + sLabel + '&#39;"'
	  + ' onclick="MenuToggle(&#39;' + sLabel + '&#39;)"'
	 	:'')
	 + '>'
	 + '<a'
	 + ' href="' + sHref + '"'
	 + ' title="' + ((sTitleText)?sTitleText:'Click to view') + '"'
	 + ((sHref.substr(0,5) === 'http:')?' target="External"':'')
	 + '>' + sLabel + '</a>'
	 + ((sLIData)?sLIData:'')
	 + '</li>';
}

function HTMLPageHead() {
	return '***No PageHead Defined***'
}

function HTMLPageInfo() {
	return ''
}

function HTMLPageXtra() {
	return ''
}

function HTMLSideMenu() {
	return ''
}

function HTMLSubMenu(sLabel,sHref,sTitle,sSubMenu) {
	return HTMLMenuLink(sLabel,sHref,sTitle,
	 '<ul id="' + sLabel + '" class="SubMenu"'
	  + ' onmouseover="sMenuOffID=&#39;&#39;"'
	  + ' onmouseout="MenuItemOff(&#39;' + sLabel + '&#39;)"'
	  + '>'
	 + sSubMenu + '</ul>');
}

/*
 * InsertMailTo - Write HTML for mail-to anchor.
 */
function InsertMailTo(sEmailID, sEmailTxt, sEmailClass, sEmailPrefix) {
	document.write(HTMLMailTo(sEmailID, sEmailTxt, sEmailClass, sEmailPrefix))
}

function MenuItemOff(sID) {
var oItem;
	oItem = document.getElementById(sID);
	oItem.style.display = 'none';
}

function MenuItemOn(sID) {
var oItem;

	oItem = document.getElementById(sID);
	oItem.style.left = oItem.parentNode.offsetLeft + 'px';
	oItem.style.marginTop = oItem.parentNode.offsetHeight + 'px';
	oItem.style.top = oItem.parentNode.offsetTop + 'px';
	oItem.style.display = 'block';
	if (sMenuOffID !== '') {
		if (sMenuOffID !== sID) {
			MenuItemOff(sMenuOffID);
		}
		sMenuOffID = '';
	}
}

function MenuToggle(sID) {
var oItem;

	oItem = document.getElementById(sID);
	if (oItem.style.display=='block') {
		MenuItemOff(sID);
	}
	else {
		MenuItemOn(sID);
	}
}
/*
 * PlaceHeader - Repositions header to its standard location.
 */
function PlaceHeader() {
	var nYOffset
	nYOffset = BrowserScrollY()
	if (nYOffset < nHdrStartLoc) {
		nYOffset = nHdrStartLoc
	}
	if (nYOffset != objHeader.offsetTop) {
		objHeader.style.top = nYOffset + 'px'
	}
	if (sMenuOffID !== '') {
		MenuItemOff(sMenuOffID);
		sMenuOffID = '';
	}
}

/*
 * ResizeFrame - Resize iframe object based on parameters.
 *   Parms: sMode - Null/missing - detect size of content document, changing height.
 *          Window - change height to fill remaining window area, less nAdjH.
 *          Image - change height/width to actual size of content image.
 *          nAdjH - Reduction in height to allow margin at bottom.
 */
function ResizeFrame(sFrameID, sMode, nAdjH) {
	var obj, nAdj;
	obj = document.getElementById(sFrameID);
	if (obj) {
		if (sMode) {
			nAdj = (nAdjH)?nAdjH:BrowserDocTop(obj)
			if (sMode == 'Window') {
				obj.style.height = (BrowserWndwH() - nAdj) + 'px'
			}
			else {
				if (sMode=='Page') {
					obj.style.height = (obj.scrollHeight +
					 (BrowserWndwH() - BrowserDocH(document)) - 5) + 'px'
				}
			}
		}
		else {
			obj.height = BrowserDocH(obj.contentWindow.document);
			if (BrowserScrollY() > BrowserDocTop(obj)) {
				BrowserScrollY(BrowserDocTop(obj))
			}
		}
		if (window.frameElement !== null) {
			parent.ResizeFrame(window.frameElement.id);
		}
	}
	else {
		alert('Page error, FrameID: ' + sFrameID + ' does not exist.');
	}
}

/*
 * SetOnload - Sets onload handler for an object and
 *   calls it for the first time.
 */
function SetOnload(sID, fpHandler) {
	var obj;
	obj = document.getElementById(sID);
	BrowserOnloadSet(obj,fpHandler);
	fpHandler();
}

/*
 * SetupCounter - Inserts InfoBox for BraveNet counter.
 */
function SetupCounter() {
	var sCtr
	if (document.getElementById('PageCounter')) {
		sCtr = document.getElementById('PageCounter').innerHTML
		while (StringHas(sCtr.toLowerCase(),'</script>')) {
			n = sCtr.toLowerCase().indexOf('</script>') + 9
			sCtr = sCtr.substr(n)
		}
		StringHTML(HTMLInfoBox('Obligatory Counter',
		 '<p class="Counter">Visitors since 29-Nov-2004</p>' +
		 sCtr),'Go')
	}
}

/*
 * SetupHeader - Sets up for floating header menu.
 */
function SetupHeader() {
	objHeader = document.getElementById('Header');
	nHdrStartLoc = objHeader.offsetTop;
	window.setInterval("PlaceHeader()", 100);
	sMenuOffID = '';
	SetupOnLoaded();
}

/*
 *	SetupOnLoaded - Executed as final step on every page (at end of standard onload). 
 *		NOTE: This function is overridden wherever desired to do any post load processing.
 */
function SetupOnLoaded() {
}

/*
 * SetupPage - Puts out starting HTML for every page.
 */
function SetupPage(sRootLoc, sPageType) {
	sRootFolder = (sRootLoc)?sRootLoc:'';
	myPage.root = sRootFolder;
	sCurrPageType = (sPageType)?sPageType:'Default';

	StringHTML('<div class="PageHead">','New')
	StringHTML(HTMLPageHead())
	StringHTML('</div>')

	StringHTML('<div id="Header"><ul class="HeaderMenu">')
	StringHTML(HTMLMenuLink('Home','index.htm',
	 'Return to this page&#39;s starting location'))
	StringHTML(HTMLHeaderMenu())
	StringHTML('</ul></div>')

	StringHTML('<div class="PageBody">',"Go")
	if (!StringHas(sCurrPageType,'NoLeft')) {
	  StringHTML('<div id="PageLeft" class="PageLeft">')
	  if (!StringHas(sCurrPageType,'NoInfo')) {
	    StringHTML('<div id="PageInfo" class="PageInfo">')
			StringHTML(HTMLPageInfo())
	    if (!StringHas(sCurrPageType,'NoMenu')) {
	      BuildSideMenu()
			}
			if (!StringHas(sCurrPageType,'NoCounter')) {
			  SetupCounter()
			}
			StringHTML('</div>')
		}
		StringHTML('<div id= "PageContent" class="PageData">')
	}
	StringHTML('','Go')
}

/*
 * StringHas - Checks string for value.
 */
function StringHas(sStr, sOpt) {
	return sStr.indexOf(sOpt)!=-1
}

/*
 * StringHTML - Manage HTML strings (building, writing).
*/
function StringHTML(sValue, sAction) {
	sHTML = sHTML + sValue
	if (sAction) {
		switch (sAction) {
			case "New":
				sHTML = sValue;
				break;
			case "Go":
				document.write(sHTML);
				sHTML='';
				break;
			default:
				alert('Error: Unknown StringHTML action');
				break;
		}
	}
}