﻿//------------------------------------------------------
// Page:					Republicast3.js
// Author:				John Bradnam
// Created:				070812 JLB
// Copyright:			Republicorp P/L
// Purpose:				Republicast3 engine
// History:
//------------------------------------------------------

var objRepublicast = null;

//------------------------------------------------------
// public entry points
//------------------------------------------------------

function RepublicastOnLoad(intTop, intBottom, intLeft, intRight) {
	if (objRepublicast == null) {
		if (typeof(intTop) == "undefined")
			objRepublicast = new clsRepublicast(Margin.top, Margin.bottom, Margin.left, Margin.right);
		else
			objRepublicast = new clsRepublicast(intTop, intBottom, intLeft, intRight);
	}
} //RepublicastOnLoad

function RepublicastIsReady() {
	return objRepublicast.initialised;
} //RepublicastIsReady

function RepublicastShow() {
	objRepublicast.resizecustomfront();
} //RepublicastShow

function RepublicastFirst() {
	objRepublicast.first();
} //RepublicastFirst

function RepublicastPrevious() {
	objRepublicast.prev();
} //RepublicastPrevious

function RepublicastGoTo(intPage, strSearchTerm) {
	objRepublicast.show(intPage, strSearchTerm);
} //RepublicastGoTo

function RepublicastGoUrl(strUrl) {
	return true;
} //RepublicastGoUrl

function RepublicastNext() {
	objRepublicast.next();
} //RepublicastNext

function RepublicastLast() {
	objRepublicast.last();
} //RepublicastLast

function RepublicastAddEventHandler(strEventName, strCallBack) {
	eval("objRepublicast." + strEventName + " = '" + strCallBack + "';");
} //RepublicastAddEvent

function RepublicastRemoveEventHandler(strEventName) {
	eval("objRepublicast." + strEventName + " = null;");
} //RepublicastRemoveEventHandler

function RepublicastFireEvent(strEventName) {
	eval("objRepublicast." + strEventName.substr(2) + "();");
} //RepublicastFireEvent

function RepublicastCustomView(strCustomPageId)
{
	objRepublicast.customview(strCustomPageId);
} //RepublicastCustomView

function RepublicastGetPhysicalPage(intPage) {
	return (typeof(intPage) == "undefined") ? objRepublicast.page : intPage;
} //RepublicastGetPhysicalPage

function RepublicastGetLogicalPage(intPage) {
	return objRepublicast.getlogical(RepublicastGetPhysicalPage(intPage));
} //RepublicastGetLogicalPage

function RepublicastGetLogicalLeftPage() {
	return objRepublicast.getlogical(objRepublicast.page);
} //RepublicastGetLogicalLeftPage

function RepublicastGetLogicalRightPage() {
	return objRepublicast.getlogical((objRepublicast.mode == 2) ? objRepublicast.fixed : objRepublicast.page);
} //RepublicastGetLogicalRightPage

function RepublicastGetPhysicalLeftPage() {
	return objRepublicast.page;
} //RepublicastGetPhysicalLeftPage

function RepublicastGetPhysicalRightPage() {
	var intPage = (objRepublicast.mode == 2) ? objRepublicast.fixed : objRepublicast.page;
	if (intPage > Config.pages)
		intPage = 0;
	return intPage;
} //RepublicastGetPhysicalRightPage

function RepublicastLogicalToPhysical(strPage) {
	var objRoman = new clsRoman();
	return objRoman.getphysical(strPage);
} //RepublicastLogicalToPhysical

//------------------------------------------------------
// Republicast class
//------------------------------------------------------

function clsRepublicast(intTop, intBottom, intLeft, intRight) {
	//properties
	this.top = intTop;
	this.bottom = intBottom;
	this.left = intLeft;
	this.right = intRight;
	this.screenw = 0;
	this.screenh = 0;
	this.count = ((Config.pages % 2) == 0) ? Config.pages + 2 : Config.pages + 1;
	this.total = Config.pages + 2;
	this.pages = null;
	this.zoom = 0;
	this.width = 0;
	this.height = 0;
	this.page = 0;
	this.fixed = 1;
	this.mode = 2;
	this.speed = 80;
	this.div = null;
	this.front = null;
	this.back = null;
	this.drag = null;
	this.full = null;
	this.turnleft = null;
	this.turnright = null;
	this.waitleft = null;
	this.waitright = null;
	this.find = null;
	this.onpagechange = null;
	this.onengineresize = null;
	this.onresize = null;
	this.onready = null;
	this.ignore = false;
	this.initialised = false;
	
	//constructor	
	this.constructor = function () {
		this.div = document.getElementById("republicast");
		this.div.style.display = "none";
		this.div.onselectstart = function(objEvent) { objRepublicast.selectstart(objEvent); };
		this.front = document.getElementById("front");
		this.back = document.getElementById("back");
		this.front.onresize = function () { objRepublicast.resizecustomfront(); };
		this.back.onresize = function () { objRepublicast.resizecustomback(); };
		this.turnleft = new clsTurn(this, this.page, this.mode, true);
		this.turnleft.div.onmouseover = function () { objRepublicast.turnleft.mouseover(); };
		this.turnleft.div.onmouseout = function () { objRepublicast.turnleft.mouseout(); };
		this.turnleft.div.onclick = function () { objRepublicast.prev(); };
		this.turnright = new clsTurn(this, this.page + 1, this.mode, false);
		this.turnright.div.onmouseover = function () { objRepublicast.turnright.mouseover(); };
		this.turnright.div.onmouseout = function () { objRepublicast.turnright.mouseout(); };
		this.turnright.div.onclick = function () { objRepublicast.next(); };
		this.waitleft = new clsWait(this, true);
		this.waitright = new clsWait(this, false);
		window.onresize = function() { objRepublicast.resize(); };
		window.setTimeout("objRepublicast.resizeinit()",100);
	} //constructor
	
	//get the current page object
	this.getpage = function(intPage) {
		return this.pages[intPage];
	} //getpage
	
	//notify viewer of page change
	this.pagechange = function () {
		if (this.onpagechange != null) {
			var strText = "";
			if (this.mode < 2)
				strText = this.getlogical(this.page);
			else if (this.page == 0)
				strText = this.getlogical(1);
			else if (this.page >= Config.pages)
				strText = this.getlogical(this.page);
			else
				strText = this.getlogical(this.page) + " - " + this.getlogical(this.fixed);
			strText = strText + " of " + (Config.pages - Config.pageoffset);
			eval(this.onpagechange + "(this, '" + strText + "');");
		}
	} //pagechange
	
	//load the page
	this.loadpage = function(intPage) {
		var objPage = null;
		if (intPage < this.total) {
		  objPage = this.getpage(intPage);
		  if (objPage == null) {
				objPage = new clsPage(this, intPage, this.zoom, this.mode);
				this.pages[intPage] = objPage;
				if (objPage.page.tagName == "IMG") {
					objPage.page.onmousedown = function(objEvent) { objRepublicast.dragstart(intPage, objEvent); };
					objPage.page.onclick = function(objEvent) { objRepublicast.zoomin(intPage, objEvent); };
					objPage.full.onmousedown = function(objEvent) { objRepublicast.dragstart(intPage, objEvent); };
					objPage.full.onclick = function(objEvent) { objRepublicast.zoomout( objEvent); };
				}
			}
		}
		return objPage;
	} //loadpage
	
	//remove unused pages
	this.remove = function(blnAll) {
		var objImg = GetFirstChild(this.div);
		var objNext = null;
		var intPage = 0;
		while (objImg != null) {
			objNext = GetNextSibling(objImg);
			intPage = parseInt(objImg.getAttribute("page"));
			if ((!blnAll) && (intPage == this.page)) {
				if (objImg.tagName == "ADDRESS") {
					if (this.find == null) {
						objImg.style.display = "none";
						this.div.removeChild(objImg);
					}
				}
				else if (objImg.tagName != "A") {
					if (this.mode == 0)
						objImg.style.left = this.width + "px";
					else
						objImg.style.left = "0px";
					objImg.style.width = this.width + "px";
				}
			}
			else if ((!blnAll) && (intPage == this.fixed)) {
				if (objImg.tagName == "ADDRESS") {
					if (this.find == null) {
						objImg.style.display = "none";
						this.div.removeChild(objImg);
					}
				}
				else if (objImg.tagName != "A") {
					if (this.mode == 0)
						objImg.style.left = "0px";
					else
						objImg.style.left = this.width + "px";
					objImg.style.width = this.width + "px";
				}
			}
			else if (objImg.tagName == "DIV") {
				if ((objImg != this.turnleft.div) && (objImg != this.turnright.div)) {
					objImg.style.display = "none";
					document.body.appendChild(objImg);
				}
			}
			else if (objImg.tagName != "TABLE") {
				try { objImg.style.display = "none"; } catch(e) {}
				this.div.removeChild(objImg);
			}
			objImg = objNext;
		}
	} //remove
	
	//called to put show/hide links on page
	this.showlinks = function(blnShow) {
		var strDisplay = blnShow ? "block" : "none";
		var objImg = GetFirstChild(this.div);
		while (objImg != null) {
			if ((objImg.tagName == "A") || (objImg.tagName == "ADDRESS"))
				objImg.style.display = strDisplay;
			objImg = GetNextSibling(objImg);
		}
	} //showlinks
	
	//previous page
	this.prev = function() {
		var intFrom = this.page;
		var intLeft = (this.mode == 0) ? this.width : 0;
		if (this.previnit()) {
			this.showlinks(false);
			this.turnleft.show(false);
			this.animate(intFrom, intLeft, this.width, this.speed, -this.speed, 0);
		}
	} //prev
	
	//previous page initialise
	this.previnit = function() {
		var blnResult = true;
		if ((this.mode != 2) && (this.page > 1))
			this.page = this.page - 1;
		else if ((this.mode == 2) && (this.page > 0)) {
			this.page = this.page - 2;
			this.fixed = this.page + 1;
		}
		else
			blnResult = false;
		if (blnResult) {
			this.render(this.page, 1);
			if (this.mode == 2)
				this.render(this.fixed, 1);
		}
		return blnResult;
	} //previnit
	
	//next page
	this.next = function() {
		var intFrom = (this.mode == 2) ? this.page + 1 : this.page;
		var intLeft = (this.mode == 1) ? 0 : this.width;
		if (this.nextinit()) {
			this.showlinks(false);
			this.turnright.show(false);
			this.animate(intFrom, intLeft, this.width, 0, -this.speed, 0);
		}
	} //next
	
	//next page initialise
	this.nextinit = function() {
		var blnResult = false;
		if ((this.page + 2) < this.count) {
			this.page = this.page + 1;
			if (this.mode == 2) {
				this.page = this.page + 1;
				this.fixed = this.page + 1;
			}
			this.render(this.page, 2);
			if (this.mode == 2)
				this.render(this.fixed, 2);
			blnResult = true;
		}
		return blnResult;
	} //nextinit

	//show first page
	this.first = function(intPage) {
		this.show(1);
	} //first
	
	//show last page
	this.last = function(intPage) {
		this.show(Config.pages);
	} //last
	
	//show specific page
	this.show = function(intPage, strSearchTerm) {
		if (this.initialised) {
			var blnRender = false;
			intPage = parseInt(intPage);
			if ((intPage > 0) && (intPage <= Config.pages)) {
				if (this.mode == 2) {
					var intLeft = intPage & 0x0fffe;
					if ((intLeft + 2) > this.count)
						intLeft = this.count - 2;
					if (this.full != null)
						this.zoomout(null);
					if (this.page != intLeft) {
						this.page = intLeft;
						this.fixed = this.page + 1;
						this.turnleft.setpage(this.page);
						this.turnright.setpage(this.fixed);
						blnRender = (this.pages != null);
					}
				}
				else {
					if (intPage == this.count)
						intLeft = this.count - 1;
					if (this.full != null)
						this.zoomout(null);
					if (this.page != intPage) {
						this.page = intPage;
						this.turnleft.setpage(this.page);
						this.turnright.setpage(this.page);
						blnRender = (this.pages != null);
					}
				}
				if (blnRender) {
					this.find = null;
					this.render(this.page);
					if (this.mode == 2)
						this.render(this.fixed);
					this.remove(false);
					this.pagechange();
				}
				if ((this.pages != null) && (typeof(strSearchTerm) != "undefined") && (strSearchTerm != null) && (strSearchTerm != this.find)) {
					this.find = null;			
					this.remove(false);
					this.find = strSearchTerm;
					this.getpage(this.page).loadresults();
					this.getpage(this.fixed).loadresults();
				}
			}
		}
	} //show
	
	//show custom panel
	this.customview = function(strPageId) {
		var blnChange = false;
		var objDiv = document.getElementById((strPageId == "page_book") ? "page_front" : strPageId);
		if (objDiv != null) {
			var objPar = objDiv.parentNode.parentNode;
			if ((strPageId == "page_front") || (strPageId == "page_back") || (strPageId == "page_book")) {
				this.front.className = "coverleft";
				this.back.className = "coverright";
				this.switchcustom(this.front, "page_front");
				this.switchcustom(this.back, "page_back");
				if (strPageId == "page_front") {
					this.page = 0;
					this.fixed = 1;
				}
				else if (strPageId == "page_back") {
					this.page = Config.pages;
					this.fixed = this.page + 1;
				}
				else {
					this.page = this.page & 0x0fffe;
					this.fixed = this.page + 1;
				}
				this.mode = 2;
				blnChange = true;
			}
			else if (objPar == this.front) {
				this.front.className = "customleft";
				this.switchcustom(this.front, objDiv);
				this.switchcustom(this.back, "page_back");
				if (this.mode != 0) {
					this.fixed = 0;
					this.page = ((this.mode == 1) || ((this.page + 2) == this.count)) ? this.page : this.page + 1;
					this.mode = 0;
				}
				blnChange = true;
			}
			else if (objPar == this.back) {
				this.back.className = "customright";
				this.switchcustom(this.front, "page_front");
				this.switchcustom(this.back, objDiv);
				if (this.mode != 1) {
					this.fixed = this.total - 1;
					this.page = (this.page == 0) ? 1 : this.page;
					this.mode = 1;
				}
				blnChange = true;
			}
			if (blnChange) {
				this.find = null;
				this.remove(true);
				this.pages = new Array(this.count);
				this.waitleft.position(this.mode);
				this.waitright.position(this.mode);
				this.turnleft.position(this.mode);
				this.turnright.position(this.mode);
				this.render(this.page);
				this.render(this.fixed);
				this.turnleft.setpage(this.page);
				if (this.mode == 2)
					this.turnright.setpage(this.fixed);
				else
					this.turnright.setpage(this.page);
				this.resizecustomfront();
				this.resizecustomback();
				this.pagechange();
			}
		}
	} //customview
	
	//switch in custom panel
	this.switchcustom = function(objPar, objPag) {
		var objDiv = null;
		if (typeof(objPag) == "string")
			objPag = document.getElementById(objPag);
		objDiv = GetFirstChild(GetFirstChild(objPar));
		while (objDiv != null) {
			objDiv.style.display = (objDiv == objPag) ? "" : "none";
			objDiv = GetNextSibling(objDiv);
		}
	} //switchcustom
	
	//resize front panels
	this.resizecustomfront = function() {
		this.resizecustom(this.front);
	} //resizecustomfront
	
	//resize back panels
	this.resizecustomback = function() {
		this.resizecustom(this.back);
	} //resizecustomback
	
	//resizecustom
	this.resizecustom = function(objPar) {
		var objBdr = GetFirstChild(objPar);
		var objPag = null;
		var objBdy = null;
		var intTop = 0;
		var strWidth = 0;
		var objDiv = GetFirstChild(objBdr);
		while (objDiv != null) {
			if (objDiv.offsetWidth != 0) {
				objBdr.style.width = (this.width - 2) + "px";
				objBdr.style.height = this.height + "px";
				strWidth = (this.width - (objDiv.offsetLeft << 1)) + "px";
				intTop = objDiv.offsetTop;
				objPag = GetFirstChild(objDiv);
				intTop += objPag.offsetHeight;
				objPag.style.width = strWidth;
				objBdy = GetNextSibling(objPag);
				objBdy.style.width = strWidth;
				objPag = GetNextSibling(objBdy);
				intTop += objPag.offsetHeight;
				objPag.style.width = strWidth;
				var intBottom = objDiv.offsetTop;
				try { intBottom = document.defaultView.getComputedStyle(objDiv, '').getPropertyValue("margin-bottom"); }
				catch (e) { intBottom = ((objDiv.currentStyle != null) && (objDiv.currentStyle.marginBottom != "auto")) ? objDiv.currentStyle.marginBottom : objDiv.offsetTop; }
				intTop += parseInt(intBottom);
				objBdy.style.height = (this.height - intTop) + "px";
			}
			objDiv = GetNextSibling(objDiv);
		}
	} //resizecustom
	
	//render the page
	this.render = function(intPage, intMode) {
		if (typeof(intMode) == "undefined")
			intMode = 0;
		var objPage = this.loadpage(intPage);
		this.loadpage(intPage + 1);
		this.loadpage(intPage + 2);
		objPage.page.style.display = "";
		switch (intMode) {
			case 1: //prev
				if (this.mode != 2) {
					if (((intPage == this.fixed) && (this.mode == 0)) || ((intPage != this.fixed) && (this.mode == 1)))
						objPage.page.style.left = "0px";
					else
						objPage.page.style.left = this.width + "px";
					objPage.page.style.width = this.width + "px";
					this.div.insertBefore(objPage.page, this.div.firstChild);
					this.div.insertBefore(this.waitright.tbl, this.div.firstChild);
					this.div.insertBefore(this.waitleft.tbl, this.div.firstChild);
				}
				else if ((intPage % 2) == 0) {
					objPage.page.style.width = this.width + "px";
					objPage.page.style.left = "0px";
					this.div.insertBefore(objPage.page, this.div.firstChild);
					this.div.insertBefore(this.waitright.tbl, this.div.firstChild);
					this.div.insertBefore(this.waitleft.tbl, this.div.firstChild);
				}
				else {
					objPage.page.style.width = "0px";
					objPage.page.style.left = this.width + "px";
					this.div.appendChild(objPage.page);
				}
				break;
				
			case 2: //next
				if (this.mode != 2) {
					if (((intPage == this.fixed) && (this.mode == 0)) || ((intPage != this.fixed) && (this.mode == 1)))
						objPage.page.style.left = "0px";
					else
						objPage.page.style.left = this.width + "px";
					objPage.page.style.width = this.width + "px";
					this.div.insertBefore(objPage.page, this.div.firstChild);
					this.div.insertBefore(this.waitright.tbl, this.div.firstChild);
					this.div.insertBefore(this.waitleft.tbl, this.div.firstChild);
				}
				else if ((intPage % 2) == 0) {
					objPage.page.style.width = "0px";
					objPage.page.style.left = this.width + "px";
					this.div.appendChild(objPage.page);
				}
				else {
					objPage.page.style.width = this.width + "px";
					objPage.page.style.left = this.width + "px";
					this.div.insertBefore(objPage.page, this.div.firstChild);
					this.div.insertBefore(this.waitright.tbl, this.div.firstChild);
					this.div.insertBefore(this.waitleft.tbl, this.div.firstChild);
				}
				break;
				
			default:
				this.div.appendChild(objPage.page);
				objPage.renderlinks(this.div, false);
				break;
		}
		objPage.calcRect();
	} //render
	
	//animate page
	this.animate = function(intPage, intLeft, intWidth, intLeftDelta, intWidthDelta, intMode) {
		var blnDone = false;
		if (((intMode == 0) && (intWidth != 0)) || ((intMode == 1) && (intWidth < this.width))) {
			intLeft = intLeft + intLeftDelta;
			intWidth = intWidth + intWidthDelta;
			intLeft = (intLeft < 0) ? 0 : intLeft;
			intWidth = (intWidth < 0) ? 0 : (intWidth > this.width) ? this.width : intWidth;
		}
		else {
			intMode = intMode + 1;
			if ((intMode == 2) || (this.mode != 2)) {
				blnDone = true;
				this.remove(false);
				if (this.mode == 2) {
					this.getpage(this.page).renderlinks(this.div, false);
					this.getpage(this.fixed).renderlinks(this.div, false);
					this.turnleft.setpage(this.page);
					this.turnright.setpage(this.fixed);
				}
				else {
					this.getpage(this.page).renderlinks(this.div, false);
					this.turnleft.setpage(this.page);
					this.turnright.setpage(this.page);
				}
				this.find = null;
				this.pagechange();
			}
			else if (intLeftDelta == 0) {
				//next
				intPage = intPage + 1;
				intLeft = this.width;
				intWidth = 0;
				intLeftDelta = -this.speed;
				intWidthDelta = this.speed;
			}
			else {
				//prev
				intPage = intPage - 1;
				intLeft = this.width;
				intWidth = 0;
				intLeftDelta = 0;
				intWidthDelta = this.speed;
			}
		}
		if (!blnDone) {
			var objPage = this.getpage(intPage);
			objPage.page.style.left = intLeft + "px";
			objPage.page.style.width = intWidth + "px";
			window.setTimeout("objRepublicast.animate(" + intPage + "," + intLeft + "," + intWidth + "," + intLeftDelta + "," + intWidthDelta + "," + intMode + ")",10);
		}
	} //animate

	//ready event
	this.ready = function () {
		if (this.onready != null)
			eval(this.onready + "(this);");
	} //this.ready

	//resizeinit
	this.resizeinit = function () {
		this.resize();
		this.initialised = true;
		this.ready();
		this.resizecustomfront();
		this.resizecustomback();
	} //resizeinit
	
	//resize the engine
	this.resize = function () {
		if ((document.documentElement) && (document.documentElement.clientHeight)) {
			this.screenw = document.documentElement.clientWidth;
			this.screenh = document.documentElement.clientHeight;
		}
		else if (document.body) {
			this.screenw = document.body.clientWidth;
			this.screenh = document.body.clientHeight
		}
		intWidth = this.screenw - this.left - this.right;
		intHeight = this.screenh - this.top - this.bottom;
		var intZoom = this.zoom;
		this.zoom = 1;
		for (intIndex = Config.sizes.length - 2; intIndex > 0; intIndex--) {
			if (((Config.sizes[intIndex].width << 1) <= intWidth) && (Config.sizes[intIndex].height <= intHeight)) {
				this.zoom = intIndex;
				break;
			}
		} //for
		if (this.zoom != intZoom) {
			this.remove(true);
			this.pages = new Array(this.count);
			this.width = Config.sizes[this.zoom].width;
			this.height = Config.sizes[this.zoom].height;
			this.font = Config.sizes[this.zoom].size;
			this.div.style.width = (this.width << 1) + "px";
			this.div.style.height = this.height + "px";
			this.waitleft.position(this.mode);
			this.waitright.position(this.mode);
			this.turnleft.position(this.mode);
			this.turnright.position(this.mode);
			document.body.style.fontSize = this.font;
			this.render(this.page);
			this.render(this.fixed);
			if (this.find != null) {
				this.getpage(this.page).loadresults();
				this.getpage(this.fixed).loadresults();
			}
			this.resizecustomfront();
			this.resizecustomback();
			if (this.onengineresize != null)
				eval(this.onengineresize + "(this, this.width * 2, this.height);");
		}
		if (this.full)
			this.full.resize();
		if (this.onresize != null)
			eval(this.onresize + "();");
		this.div.style.display = "";
		if (this.div.offsetHeight == 0)
			setTimeout("objRepublicast.resize()",500);
	} //resize
	
	//select start
	this.selectstart = function(objEvent) {
		if (objEvent == null)
			objEvent = event;
		var blnAllow = ((objEvent != null) && (objEvent.srcElement != null) && (objEvent.srcElement.tagName == "INPUT"));
		if (objEvent != null)
			objEvent.returnValue = blnAllow;
		return blnAllow;
	} //selectstart

	//drag start
	this.dragstart = function(intPage, objEvent) {
		if (objEvent == null)
			objEvent = event;
		if (this.full != null)
			this.full.drag(objEvent.clientX, objEvent.clientY);
		else
			this.drag = new clsDrag(this, this.mode, this.getpage(intPage), objEvent.clientX, objEvent.clientY);
		document.onmousemove = function(objEvent) { objRepublicast.dragmove(objEvent); }
		document.onmouseup = function(objEvent) { objRepublicast.dragend(objEvent); }
		document.body.onselectstart = function() { return false; };
		try { document.body.setCapture(true); } catch(e) {}
		objEvent.cancelBubble = true;
		objEvent.returnValue = false;
		try { objEvent.preventDefault(); } catch(e) {}
		return false;
	} //dragstart

	this.dragmove = function(objEvent)	{
		if (objEvent == null)
			objEvent = event;
		if (this.full != null)
			this.full.move(objEvent.clientX, objEvent.clientY);
		else if (this.drag != null)
			this.drag.move(objEvent.clientX, objEvent.clientY);
	} //dragmove
	
	this.dragend = function(objEvent)	{
		if (objEvent == null)
			objEvent = event;
		try {	document.body.releaseCapture(true); } catch(e) {};
		document.body.style.cursor = "";
		if (this.full != null)
			this.full.drop(objEvent.clientX, objEvent.clientY);
		else if (this.drag != null) {
			this.ignore = ((this.drag.drop(objEvent.clientX, objEvent.clientY)) && (objEvent.preventDefault));
			this.drag = null;
		}
		document.onmousemove = null;
		document.onmouseup = null;
		document.body.onselectstart = null;
		return false;
	} //dragend

	//click
	this.click = function(objAdr, objEvent) {
		if (this.full != null)
			this.zoomout(objEvent);
		else if (typeof(objAdr) == "object")
			this.zoomin(parseInt(objAdr.getAttribute("page")), objEvent);
	} //click

	//zoom in
	this.zoomin = function(intPage, objEvent) {
		if (objEvent == null)
			objEvent = event;
		if ((this.full == null) && (!this.ignore)) {
			this.showlinks(false);
			this.full = new clsFull(this, this.mode, intPage, objEvent.clientX, objEvent.clientY);
		}
		this.ignore = false;
	} //zoomin
	
	//zoom out
	this.zoomout = function(objEvent) {
		if (objEvent == null)
			objEvent = event;
		if (this.full != null) {
			if (this.full.postdrag)
				this.full.postdrag = false;
			else {
				this.full = this.full.dispose();
				this.showlinks(true);
			}
		}
	} //zoomout
	
	//linksloaded
	this.linksloaded = function(objAjax) {
		objAjax.page.linksloaded();
	} //linksloaded

	//resuktsloaded
	this.resultsloaded = function(objAjax) {
		objAjax.page.resultsloaded();
	} //resultsloaded

	//get logical page number	
	this.getlogical = function(intPage) {
		var objRoman = new clsRoman();
		return objRoman.getlogical(intPage);
	} //getlogical
	
	//initialisation
	this.constructor();
	
} //clsRepublicast

//------------------------------------------------------
// ajax class
//------------------------------------------------------

function clsAjax(objPage, blnAsync, funResponse) {
	this.ajax = null;
	this.page = objPage;
	this.async = blnAsync;
	this.onready = null;
	this.onerror = null;
	this.response = "";
	this.error = "";
	this.waitresponse = false;
	this.onresponse = (typeof(funResponse) == "function") ? funResponse : null;

	//constructor	
	this.constructor = function() {
		if (navigator.userAgent.indexOf("Opera") != -1)
			;
		else if (navigator.userAgent.indexOf("MSIE") != -1) {
			var strName = "Msxml2.XMLHTTP";
			if (navigator.appVersion.indexOf("MSIE 5.5") >= 0) {
				strName = "Microsoft.XMLHTTP";
			}
			try {
				this.ajax = new ActiveXObject(strName);
				if (this.async) {
					if (this.onresponse == null)
						eval( "this.onresponse = function () { RepublicastLoaded(" + this.page.num + "); };");
					this.ajax.onreadystatechange = this.onresponse;
				}
			}
			catch (e) {
				this.ajax = null;
			}
		}
		else if (navigator.userAgent.indexOf("Mozilla") != -1) {
			this.ajax = new XMLHttpRequest();
			if (this.async) {
				if (this.onresponse == null)
					eval( "this.onresponse = function () { RepublicastLoaded(" + this.page.num + "); };");
				this.ajax.onload = this.onresponse;
				this.ajax.onerror = this.onresponse;
			}
		}
	} //constructor
	
	this.ready = function () {
		if (this.ajax.readyState == 4) {
			this.waitresponse = false;
			if (this.ajax.status == 200) {
				this.response = this.ajax.responseText;
				if (this.onready != null)
					eval(this.onready + "(this);");
			}
			else {
				this.error = this.ajax.statusText;
				if (this.onerror != null)
					eval(this.onerror + "(this);");
			}
		}
	} //ready
	
	//get
	this.get = function(strUrl) {
		this.response = "";
		this.error = "";
		if (this.ajax != null) {
			this.waitresponse = this.async;
			this.ajax.open("GET", strUrl, this.async);
			this.ajax.send("");
			if (!this.async)
				this.response = this.ajax.responseText;
		}
		return this.response;
	} //get
	
	//post
	this.post = function(strUrl, strData) {
		this.response = "";
		this.error = "";
		if (this.ajax != null) {
			this.waitresponse = this.async;
			this.ajax.open("POST",strUrl, false);
			this.ajax.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8");
			this.ajax.send(strData);
			if (!this.async)
				this.response = this.ajax.responseText;
		}
		return this.response;
	} //post

	//initialise
	this.constructor();
	
} //clsAJax

function RepublicastLoaded(intPage) {
	try {
		var objPage = objRepublicast.getpage(intPage);
		if ((objPage.ajaxlink != null) && (objPage.ajaxlink.waitresponse))
			objPage.ajaxlink.ready();
		if ((objPage.ajaxresult != null) && (objPage.ajaxresult.waitresponse))
			objPage.ajaxresult.ready();
	}
	catch(e) {
		window.setTimeout("RepublicastLoaded(" + intPage + ")",1);
	}
} //RepublicastLoaded

//------------------------------------------------------
// clsXmlDoc class
//------------------------------------------------------

function clsXmlDoc(strXml) {
	this.xml = null;
	this.loaded = false;
	this.parser = null;
	this.doc = null;

	this.constructor = function(strXml) {
		if (window.ActiveXObject) {
			this.doc = new ActiveXObject("Microsoft.XMLDOM");
			if (this.doc != null) { 
				this.doc.async = "false";
				if (typeof(strXml) != "undefined")
					this.doc.loadXML(strXml);
				this.loaded = true;
			}
		}
		else {
			this.xml = document.implementation.createDocument("", "", null);
			if (this.xml != null) {
				this.xml.async = "false";
				this.parser = new DOMParser();
				if (this.parser != null) {
					if (typeof(strXml) != "undefined")
						this.doc = this.parser.parseFromString(strXml, "text/xml");
					this.loaded = true;
				}
			}
		}
	} //constructor

	this.getElementsByTagName = function(strTag) {
		return (this.doc != null) ? this.doc.getElementsByTagName(strTag) : null;
	} //getElementsByTagName

	this.getAttributeCount = function(objNode) {
		return parseInt(objNode.attributes.length);
	} //getAttribute
		
	this.getAttribute = function(objNode, intIndex) {
		return objNode.attributes[intIndex];
	} //getAttribute
		
	this.getAttributeValue = function(objAttribute) {
		return objAttribute.value;
	} //getAttributeValue
		
	this.getAttributeName = function(objAttribute) {
		return (this.parser == null) ? objAttribute.baseName : objAttribute.name;
	} //getAttributeName
		
	this.getInnerText = function(objNode) {
		return (this.parser == null) ? objNode.text : objNode.childNodes[0].nodeValue;
	} //getInnerText

	this.constructor(strXml);
} //clsXmlDoc

//------------------------------------------------------
// Page class
//------------------------------------------------------

function clsPage(objEngine, intPage, intZoom, intMode) {
	//properties
	this.engine = objEngine;
	this.page = null;
	this.thumb = null;
	this.full = null;
	this.links = null;
	this.results = null;
	this.zoom = intZoom;
	this.mode = intMode;
	this.num = intPage;
	this.width = Config.sizes[intZoom].width;
	this.height = Config.sizes[intZoom].height;
	this.dx = Config.sizes[intZoom].dx;
	this.dy = Config.sizes[intZoom].dy;
	this.fwidth = Config.sizes[Config.sizes.length - 1].width;
	this.fheight = Config.sizes[Config.sizes.length - 1].height;
	this.fdx = Config.sizes[Config.sizes.length - 1].dx;
	this.fdy = Config.sizes[Config.sizes.length - 1].dy;
	this.twidth = Config.sizes[0].width;
	this.theight = Config.sizes[0].height;
	this.factor = this.height / this.fheight;
	this.rect = new clsRect();
	this.ajaxlink = null;
	this.ajaxresult = null;

	//constructor	
	this.constructor = function () {
		if (this.num == 0) {
			this.page = document.getElementById("front");
			this.page.style.width = Config.sizes[intZoom].width + "px";
			this.page.style.height = Config.sizes[intZoom].height + "px";
			this.page.style.left = ((intPage % 2) == 0) ? "0px" : Config.sizes[intZoom].width + "px";
			this.page.style.top = "0px";
			this.page.style.cursor = "default";
			this.page.style.display = "none";
		}
		else if (this.num > Config.pages) {
			this.page = document.getElementById("back");
			this.page.style.width = Config.sizes[intZoom].width + "px";
			this.page.style.height = Config.sizes[intZoom].height + "px";
			this.page.style.left = ((intPage % 2) == 0) ? "0px" : Config.sizes[intZoom].width + "px";
			this.page.style.top = "0px";
			this.page.style.cursor = "default";
			this.page.style.display = "none";
		}
		else {
			this.page = this.addimage(intPage, this.zoom, this.mode, "pagecursor");
			this.thumb = this.addimage(intPage, 0, 2, "thumbcursor");
			this.full = this.addimage(intPage, Config.sizes.length - 1, 2, "fullcursor");
			this.loadlinks();
		}
		this.page.setAttribute("page", intPage);
	} //constructor
	
	//add a image tag for the current zoom factor
	this.addimage = function(intPage, intZoom, intMode, strClass) {
		var objImg = null;
		objImg = document.createElement("img");
		objImg.src = "../../Engine/Page.aspx?c=" + Config.id + "&p=" + intPage + "&z=" + intZoom;
		objImg.width = Config.sizes[intZoom].width;
		objImg.height = Config.sizes[intZoom].height;
		objImg.className = strClass;
		objImg.style.position = "absolute";
		objImg.style.left = ((intMode == 1) || ((intMode == 2) && ((intPage % 2) == 0))) ? "0px" : Config.sizes[intZoom].width + "px";
		objImg.style.top = "0px";
		objImg.style.display = "none";
		//objImg.style.zIndex = 2;
		return objImg;
	} //addimage
	
	//get page rectangle
	this.calcRect = function() {
		this.rect.top = 0;
		this.rect.left = ((intMode == 1) || ((intMode == 2) && ((intPage % 2) == 0))) ? 0 : this.width;
		this.rect.left += 2;
		oPar = this.page.parentNode;
		while ((oPar != null) && (oPar != document.body)) {
			if ((oPar.tagName == "DIV") && (oPar.style.position == "relative")) {
				this.rect.left = this.rect.left + oPar.offsetLeft;
				this.rect.top = this.rect.top + oPar.offsetTop;
			}
			oPar = oPar.parentNode;
		}
		this.rect.bottom = this.rect.top + this.height;
		this.rect.right = this.rect.left + this.width;
	} //calcRect
	
	//load links for page
	this.loadlinks = function() {
		if ((this.links == null) && (this.num > 0) && (this.num <= Config.pages)) {
			this.ajaxlink = new clsAjax(this, true);
			this.ajaxlink.onready = "objRepublicast.linksloaded";
			this.ajaxlink.get("../../Engine/Links.aspx?c=" + Config.id + "&p=" + this.num + "&z=" + this.factor);
		}
	} //loadlinks
	
	//called when links have loaded
	this.linksloaded = function() {
		if (this.ajaxlink.response != "") {
			var objXmlDoc = new clsXmlDoc(this.ajaxlink.response);
			if (objXmlDoc.loaded) {
				var aTagLink = objXmlDoc.getElementsByTagName("link");
				var intCount = parseInt(aTagLink.length);
				this.links = new Array(intCount);
				for (var intIndex = 0; intIndex < intCount; intIndex++) {
					var objLink = aTagLink[intIndex];
					var intLinkCount = objXmlDoc.getAttributeCount(objLink);
					var objItem = new clsLink();
					for (var intAttribute = 0; intAttribute < intLinkCount; intAttribute++) {
						var objAttribute = objXmlDoc.getAttribute(objLink, intAttribute);
						var strValue = objXmlDoc.getAttributeValue(objAttribute);
						switch (objXmlDoc.getAttributeName(objAttribute)) {
							case "left": objItem.rect.left = parseInt(strValue); break;
							case "top": objItem.rect.top = parseInt(strValue); break;
							case "right": objItem.rect.right = parseInt(strValue); break;
							case "bottom": objItem.rect.bottom = parseInt(strValue); break;
							case "page": objItem.page = parseInt(strValue); break;
							case "url": objItem.url = strValue; break;
						} //switch
					}
					this.links[intIndex] = objItem;
				}
				if ((this.engine.page == this.num) || (this.engine.fixed == this.num))
					this.renderlinks(this.engine.div, false);
			}
		}
		this.ajaxlink = null;
	} //linksloaded
	
	//called to put links on page
	this.renderlinks = function(objParent, blnFull) {
		if (this.links != null) {
			var intX = (blnFull) ? this.fdx : this.dx;
			var intY = (blnFull) ? this.fdy : this.dy;
			var intW = (blnFull) ? this.fwidth : this.width;
			var intH = (blnFull) ? this.fheight : this.height;
			var blnLeft = false;
			if (blnFull)
				blnLeft = ((this.mode != 2) || ((this.num % 2) == 0) || (this.num == 1));
			else
				blnLeft = ((this.mode == 1) || ((this.mode == 2) && ((this.num % 2) == 0)));
			var intOffset = (blnLeft) ? 0 : (blnFull) ? this.fwidth : this.width;
			var fltScaleX = (intW + intX) / this.fwidth;
			var fltScaleY = (intH + intY) / this.fheight;
			var intCount = this.links.length;
			for (intIndex = 0; intIndex < intCount; intIndex++) {
				var objLink = this.links[intIndex];
				var intLeft = Math.floor(objLink.rect.left * fltScaleX) + intOffset;
				var intTop = Math.floor(objLink.rect.top * fltScaleY);
				var intRight = Math.floor(objLink.rect.right * fltScaleX) + intOffset;
				var intBottom = Math.floor(objLink.rect.bottom * fltScaleY);
				var objAnc = document.createElement("A");
				objAnc.style.display = "block";
				objAnc.style.cursor = "pointer";
				objAnc.style.position = "absolute";
				objAnc.style.zIndex = 3;
				objAnc.style.left = intLeft + "px";
				objAnc.style.top = intTop + "px";
				objAnc.style.width = (intRight - intLeft) + "px";
				objAnc.style.height = (intBottom - intTop) + "px";
				objAnc.style.backgroundImage = "url(../../Engine/Link.gif)";
				objAnc.style.fontSize = "1px";
				objAnc.className = "link";
				objAnc.setAttribute("page", this.num);
				if (objLink.url == "") {
					eval("objAnc.onclick = function() { RepublicastGoTo(" + objLink.page + "); return false; }");
					objAnc.href = "Page." + this.engine.getlogical(objLink.page);
					objAnc.title = "Goto page " + this.engine.getlogical(objLink.page);
				}
				else if (objLink.url.substr(0,7) == "mailto:") {
					//eval("objAnc.onclick = function() { return RepublicastGoUrl('" + objLink.url + "'); }");
					objAnc.href = objLink.url;
					objAnc.title = "Send email to " + objLink.url.substr(7);
				}
				else {
					//eval("objAnc.onclick = function() { return RepublicastGoUrl('" + objLink.url + "'); }");
					objAnc.href = objLink.url;
					objAnc.target = "_blank";
					objAnc.title = "View " + objLink.url;
				}
				objParent.appendChild(objAnc);
			} //for;
		}
	} //renderlinks

	//load results for page
	this.loadresults = function() {
		if ((this.num > 0) && (this.num <= Config.pages)) {
			this.ajaxresult = new clsAjax(this, true);
			this.ajaxresult.onready = "objRepublicast.resultsloaded";
			this.ajaxresult.get("../../Engine/Results.aspx?c=" + Config.id + "&p=" + this.num + "&f=" + encodeURI(this.engine.find));
		}
	} //loadreults
	
	//called when results have loaded
	this.resultsloaded = function() {
		if (this.ajaxresult.response != "") {
			var objXmlDoc = new clsXmlDoc(this.ajaxresult.response);
			if (objXmlDoc.loaded) {
				var aTagIndex = objXmlDoc.getElementsByTagName("index");
				var intCount = parseInt(aTagIndex.length);
				this.results = new Array(intCount);
				for (var intIndex = 0; intIndex < intCount; intIndex++) {
					var objIndex = aTagIndex[intIndex];
					var intResultCount = objXmlDoc.getAttributeCount(objIndex);
					var objItem = new clsRect();
					for (var intAttribute = 0; intAttribute < intResultCount; intAttribute++) {
						var objAttribute = objXmlDoc.getAttribute(objIndex, intAttribute);
						var strValue = objXmlDoc.getAttributeValue(objAttribute);
						switch (objXmlDoc.getAttributeName(objAttribute)) {
							case "left": objItem.left = parseInt(strValue); break;
							case "top": objItem.top = parseInt(strValue); break;
							case "right": objItem.right = parseInt(strValue); break;
							case "bottom": objItem.bottom = parseInt(strValue); break;
						} //switch
					}
					this.results[intIndex] = objItem;
				}
				if ((this.engine.page == this.num) || (this.engine.fixed == this.num))
					this.renderresults(this.engine.div, false);
			}
		}
		this.ajaxresult = null;
	} //resultsloaded
	
	//called to put results on page
	this.renderresults = function(objParent, blnFull) {
		if ((this.results != null) && (this.engine.find != null)) {
			var intX = (blnFull) ? this.fdx : this.dx;
			var intY = (blnFull) ? this.fdy : this.dy;
			var intW = (blnFull) ? this.fwidth : this.width;
			var intH = (blnFull) ? this.fheight : this.height;
			var blnLeft = (((this.mode == 0) && (blnFull)) || (this.mode == 1) || ((this.mode == 2) && ((this.num % 2) == 0)));
			var intOffset = (blnLeft) ? 0 : (blnFull) ? this.fwidth : this.width;
			var fltScaleX = (intW + intX) / this.fwidth;
			var fltScaleY = (intH + intY) / this.fheight;
			var intCount = this.results.length;
			for (intIndex = 0; intIndex < intCount; intIndex++) {
				var objIndex = this.results[intIndex];
				var intLeft = Math.floor(objIndex.left * fltScaleX) + intOffset;
				var intTop = Math.floor(objIndex.top * fltScaleY);
				var intRight = Math.floor(objIndex.right * fltScaleX) + intOffset;
				var intBottom = Math.floor(objIndex.bottom * fltScaleY);
				var objAdr = document.createElement("ADDRESS");
				objAdr.style.display = "block";
				objAdr.style.position = "absolute";
				objAdr.style.zIndex = 2;
				objAdr.style.left = intLeft + "px";
				objAdr.style.top = intTop + "px";
				objAdr.style.width = (intRight - intLeft) + "px";
				objAdr.style.height = (intBottom - intTop) + "px";
				objAdr.style.fontSize = "1px";
				objAdr.className = "result " + ((blnFull) ? "fullcursor" : "pagecursor");
				objAdr.onclick = (document.all) ? null : function(objEvent) { objRepublicast.click(this, objEvent); };
				objAdr.setAttribute("page", this.num);
				objParent.appendChild(objAdr);
			} //for;
		}
	} //renderresults
	
	//Initialise
	this.constructor();
} //clsPage

//------------------------------------------------------
// link class
//------------------------------------------------------

function clsLink() {
	this.rect = new clsRect();
	this.page = 0;
	this.url = "";
} //clsLink

//------------------------------------------------------
// Drag class
//------------------------------------------------------

function clsDrag(objEngine, intMode, objPage, intStartX, intStartY) {
	//properties
	this.engine = objEngine;
	this.mode = intMode;
	this.page = objPage;
	this.startx = intStartX;
	this.starty = intStartY;
	this.dragx = intStartX;
	this.dragy = intStartY;
	this.lastgoodx = intStartX;
	this.left = this.page.page.offsetLeft;
	this.top = this.page.page.offsetTop;
	this.box = this.page.rect;
	this.hittest = new clsRect(this.box);
	this.half = this.page.width >> 1;
	this.movex = 0;
	this.enabled = true;
	this.dragpage = null;
	this.dragleft = false;
	
	//constructor
	this.constructor = function() {
		if (this.mode == 2)
			this.dragleft = ((this.page.num % 2) != 0);
		else {
			var objRight = new clsRect(this.box);
			objRight.left += this.half;
			this.dragleft = (objRight.inRect(this.dragx, this.dragy));
			if (this.dragleft)
				this.hittest.left += this.half;
			else
				this.hittest.right -= this.half;
		}
	} //constructor
	
	//move while drag
	this.move = function(intClientX, intClientY) {
		this.dragx = intClientX;
		this.dragy = intClientY;
		if ((this.enabled) && (this.hittest.inRect(this.dragx, this.dragy))) {
			if (this.dragpage != null) {
				var intWidth = 0;
				var intLeft = 0;
				if (this.dragleft) {
					intWidth = Math.floor((this.dragx - this.box.left) * this.movex);
					intLeft = (this.mode == 1) ? 0 : this.page.width;
				}
				else {
					intWidth = Math.floor((this.box.right - this.dragx) * this.movex);
					intLeft = (this.page.width - intWidth) + ((this.mode == 0) ? this.page.width : 0);
				}
				intLeft = (intLeft < 0) ? 0 : intLeft;
				intWidth = (intWidth < 0) ? 0 : (intWidth > this.page.width) ? this.page.width : intWidth;
				this.dragpage.page.style.left = intLeft + "px";
				this.dragpage.page.style.width = intWidth + "px";
				this.lastgoodx = intClientX;
			}
			else if ((this.dragleft) && ((this.startx - this.dragx) > 5)) {
				var intFrom = this.page.num;
				if (this.engine.nextinit()) {
					this.engine.showlinks(false);
					document.body.style.cursor = "w-resize";
					this.movex = this.page.width / (this.startx - this.box.left);
					this.dragpage = this.engine.getpage(intFrom);
					this.move(intClientX, intClientY);
				}
			}
			else if ((!this.dragleft) && ((this.dragx - this.startx) > 5)) {
				var intFrom = this.page.num;
				if (this.engine.previnit()) {
					this.engine.showlinks(false);
					document.body.style.cursor = "e-resize";
					this.movex = this.page.width / (this.box.right - this.startx);
					this.dragpage = this.engine.getpage(intFrom);
					this.move(intClientX, intClientY);
				}
			}
		}
		else if (this.dragpage != null) {
			var intWidth = 0;
			if (this.dragleft)
				intWidth = Math.floor((this.dragx - this.box.left) * this.movex);
			else
				intWidth = Math.floor((this.box.right - this.dragx) * this.movex);
			if (((this.mode == 2) && (intWidth < 0)) || ((this.mode != 2) && (intWidth < this.half)))
				this.drop(this.dragx, this.dragy);
		}
	} //move
	
	//drop
	this.drop = function(intClientX, intClientY) {
		var blnDrop = false;
		this.dragx = intClientX;
		this.dragy = intClientY;
		if (this.dragpage != null) {
			var intWidth = 0;
			var intLeft = 0;
			if (this.dragleft) {
				intWidth = Math.floor((this.dragx - this.box.left) * this.movex);
				if (((this.mode == 2) && (intWidth > 0)) || ((this.mode != 2) && (intWidth > this.half))) {
					this.engine.remove(false);
					this.engine.show(this.dragpage.num, this.engine.find);
					this.engine.showlinks(true);
				}
				else {
					intWidth = Math.floor((this.lastgoodx - this.box.left) * this.movex);
					intLeft = ((this.mode == 1) ? 0 : this.page.width);
					this.engine.animate(this.dragpage.num, intLeft, intWidth, 0, -this.engine.speed, 0);
				}
			}
			else {
				intWidth = Math.floor((this.box.right - this.dragx) * this.movex);
				intLeft = this.page.width - intWidth;
				if (((this.mode == 2) && (intWidth > 0)) || ((this.mode != 2) && (intWidth > this.half))) {
					this.engine.remove(false);
					this.engine.show(this.dragpage.num, this.engine.find);
					this.engine.showlinks(true);
				}
				else {
					intWidth = Math.floor((this.box.right - this.lastgoodx) * this.movex);
					intLeft = this.page.width - intWidth + ((this.mode == 0) ? this.page.width : 0);
					this.engine.animate(this.dragpage.num, intLeft, intWidth, this.engine.speed, -this.engine.speed, 0);
				}
			}
			this.dragpage = null;
			this.enabled = false;
			blnDrop = true;
		}
		return blnDrop;
	} //drop
	
	//initialise object
	this.constructor();
	
} //clsDrag

//------------------------------------------------------
// Full class
//------------------------------------------------------

function clsFull(objEngine, intMode, intPage, intStartX, intStartY) {
	this.engine = objEngine;
	this.mode = intMode;
	this.leftpage = null;
	this.rightpage = null;
	this.num = intPage;
	this.startx = intStartX;
	this.starty = intStartY;
	this.dragx = 0;
	this.dragy = 0;
	this.left = 0;
	this.top = 0;
	this.div = null;
	this.page = null;
	this.width = 0;
	this.height = 0;
	this.pwidth = 0;
	this.pheight = 0;
	this.swidth = 0;
	this.sheight = 0;
	this.leftnum = 0;
	this.rightnum = Config.pages + 1;
	this.postdrag = false;
	this.leftpage = null;
	this.rightpage = null;
	
	this.constructor = function () {
		var objPage = this.engine.getpage(this.num);
		if (this.mode == 0)
			this.rightnum = intPage;
		else if (this.mode == 1)
			this.leftnum = intPage;
		else if ((this.num % 2) == 0) {
			this.leftnum = intPage;
			this.rightnum = intPage + 1;
		}
		else {
			this.leftnum = intPage - 1;
			this.rightnum = intPage;
		}
		if (this.leftnum != 0) {
			this.leftpage = this.engine.getpage(this.leftnum);
			this.width += this.leftpage.fwidth;
			this.height = this.leftpage.fheight;
			this.pwidth += this.leftpage.width;
			this.pheight = this.leftpage.height;
			this.leftpage.full.style.left = "0px";
		}
		if (this.rightnum <= Config.pages) { 
			this.rightpage = this.engine.getpage(this.rightnum);
			this.width += this.rightpage.fwidth;
			this.height = this.rightpage.fheight;
			this.pwidth += this.rightpage.width;
			this.pheight = this.rightpage.height;
			if (this.leftpage != null)
				this.rightpage.full.style.left = this.rightpage.fwidth + "px";
			else {
				this.rightpage.full.style.left = "0px";
				this.rightpage.calcRect();
			}
		}
		this.swidth = this.engine.screenw;
		this.sheight = this.engine.screenh;
		this.div = document.createElement("DIV");
		this.div.style.position = "absolute";
		this.div.style.left = "0px";
		this.div.style.top = "0px";
		this.div.style.width = this.swidth + "px";
		this.div.style.height = this.sheight + "px";
		this.div.style.overflow = "hidden";
		this.div.style.zIndex = 9;
		this.div.style.backgroundColor = "white";
		this.div.style.cursor = "default";
		this.div.style.display = "none";
		this.page = document.createElement("DIV");
		this.page.style.position = "absolute";
		this.page.style.width = this.width + "px";
		this.page.style.height = this.height + "px";
		this.page.style.cursor = "move";
		if (this.leftpage != null) {
			this.leftpage.full.style.display = "block";
			this.page.appendChild(this.leftpage.full);
			this.leftpage.renderlinks(this.page, true);
			this.leftpage.renderresults(this.page, true);
			this.leftpage.calcRect();
		}
		if (this.rightpage != null) {
			this.rightpage.full.style.display = "block";
			this.page.appendChild(this.rightpage.full);
			this.rightpage.renderlinks(this.page, true);
			this.rightpage.renderresults(this.page, true);
			this.rightpage.calcRect();
		}
		var objBox = this.getpageoffset();
		this.left = this.startx - Math.floor(((this.startx - objBox.left) * this.width) / this.pwidth);
		this.top = this.starty - Math.floor(((this.starty - objBox.top) * this.height) / this.pheight);
		this.resize();
		this.div.appendChild(this.page);
		document.body.insertBefore(this.div, document.body.firstChild);
		this.div.style.display = "";
	} //constructor
	
	//remove the full size page
	this.dispose = function() {
		document.body.removeChild(this.div);
		return null;
	} //dispose
	
	//get divisional page offset
	this.getpageoffset = function() {
		var objRect = new clsRect();
		if (this.leftpage == null) {
			objRect.left = this.rightpage.rect.left;
			objRect.top = this.rightpage.rect.top;
		}
		else {
			objRect.left = this.leftpage.rect.left;
			objRect.top = this.leftpage.rect.top;
		}
		return objRect;
	} //getpageoffset
	
	//drag start
	this.drag = function(intClientX, intClientY) {
		this.startx = intClientX;
		this.starty = intClientY;
		document.body.style.cursor = "move";
	} //drag

	this.move = function(intClientX, intClientY) {
		this.dragx = intClientX;
		this.dragy = intClientY;
		var intX = this.startx - this.dragx;
		var intY = this.starty - this.dragy;
		if ((intX != 0) || (intY != 0)) {
			this.left = this.left - intX;
			this.top = this.top - intY;
			this.resize();
			this.startx = this.dragx;
			this.starty = this.dragy;
			this.postdrag = true;
		}
	} //move
	
	this.drop = function(intClientX, intClientY) {
		this.move(intClientX, intClientY);
	} //drop
	
	//resize
	this.resize = function() {
		if ((this.swidth != this.engine.screenw) || (this.sheight != this.engine.screenh)) {
			this.swidth = this.engine.screenw;
			this.sheight = this.engine.screenh;
			this.div.style.width = this.swidth + "px";
			this.div.style.height = this.sheight + "px";
		}
		if (this.width < this.engine.screenw)
			this.left = (this.engine.screenw - this.width) >> 1;
		else
			this.left = (this.left > 0) ? 0 : ((this.left + this.width) < this.engine.screenw) ? this.engine.screenw - this.width : this.left;
		if (this.height < this.engine.screenh)
			this.top = (this.engine.screenh - this.height) >> 1;
		else
			this.top = (this.top > 0) ? 0 : ((this.top + this.height) < this.engine.screenh) ? this.engine.screenh - this.height : this.top;
		this.page.style.left = this.left + "px";
		this.page.style.top = this.top + "px";
	} //resize
	
	//initialise
	this.constructor();
} //clsFull

//------------------------------------------------------
// Turn class
//------------------------------------------------------

function clsTurn(objEngine, intPage, intMode, blnLeft) {
	this.engine = objEngine;
	this.page = 0;
	this.mode = intMode;
	this.left = blnLeft;
	this.name = (this.left) ? "left" : "right";
	this.event = "objRepublicast.turn" + this.name + ".animate()";
	this.rect = new clsRect();
	this.width = 37;
	this.height = 37;
	this.frames = 6;
	this.frame = 0;
	this.direction = 1;
	this.div = null;
	
	//constructor
	this.constructor = function (intPage) {
		if (intMode != 2)
			intPage = intPage - 1;
		var objDiv = document.createElement("DIV");
		objDiv.style.position = "absolute";
		objDiv.style.width = this.width + "px";
		objDiv.style.height = this.height + "px";
		objDiv.style.overflow = "hidden";
		objDiv.style.zIndex = 4;
		objDiv.style.cursor = "pointer";
		objDiv.style.backgroundImage = "url(../../Engine/turn_" + this.name + ".gif)";
		objDiv.style.backgroundRepeat = "no-repeat";
		objDiv.style.backgroundPositionX = "0px";
		objDiv.style.backgroundPositionY = "0px";
		if (this.left)
			objDiv.title = "Click to view\nprevious page";
		else
			objDiv.title = "Click to view\nnext page";
		this.div = this.engine.div.appendChild(objDiv);
		this.setpage(intPage);
	} //constructor

	//set page		
	this.setpage = function(intPage) {
		this.page = intPage;
		this.show(true);
	} //setpage
	
	//position
	this.position = function(intMode) {
		this.mode = intMode;
		this.rect.bottom = this.engine.height;
		this.rect.top = this.rect.bottom - this.height;
		switch (this.mode) {
			case 0: this.rect.left = (this.left) ? this.engine.width : (this.engine.width << 1) - this.width; break;
			case 1: this.rect.left = (this.left) ? 0 : this.engine.width - this.width; break;
			case 2: this.rect.left = (this.left) ? 0 : (this.engine.width << 1) - this.width; break;
		}
		this.rect.right = this.rect.left + this.width;
		this.div.style.left = this.rect.left + "px";
		this.div.style.top = this.rect.top + "px";
	} //position

	//show	
	this.show = function(blnShow) {
		var intFront = ((this.mode == 2) || (!this.left)) ? 1 : 2;
		var intBack = ((this.mode == 2) || (this.left)) ? Config.pages : Config.pages - 1;
		this.div.style.display = ((!blnShow) || (this.page < intFront) || (this.page > intBack)) ? "none" : "";
	} //show
	
	//mouseover
	this.mouseover = function() {
		this.direction = 1;
		window.setTimeout(this.event,1);
	} //mouseover
	
	//mouseout
	this.mouseout = function() {
		this.direction = -1;
		window.setTimeout(this.event,1);
	} //mouseover
	//mouseout

	//animate	
	this.animate = function() {
		if (((this.frame != 0) && (this.direction == -1)) || ((this.frame < this.frames) && (this.direction == 1))) {
			this.frame = this.frame + this.direction;
			this.div.style.backgroundPosition = (-(this.frame - 1) * this.width) + "px 0px";
			window.setTimeout(this.event,(this.direction == 1) ? 1 : 50);
		}
	} //animate
	
	this.mousedown = function(intClientX, intClientY) {
		if (this.rect.inRect(intClientX, intClientY))
			this.div.style.display = "hidden";
	} //mousedown
	
	this.constructor(intPage);
} //clsTurn
	
//------------------------------------------------------
// Wait class
//------------------------------------------------------

function clsWait(objEngine, blnLeft) {
	this.engine = objEngine;
	this.left = blnLeft;
	this.tbl = null;
	
	//constructor
	this.constructor = function() {
		var objDiv = document.createElement("DIV");
		objDiv.innerHTML = "<table class=\"wait_page\"><tr><td><table><tr><td><img src=\"../../Engine/Wait.gif\" /></td><td>Loading ...</td></tr></table></td></tr></table>";
		this.tbl = this.engine.div.appendChild(objDiv.firstChild);
	} //constructor

	//position
	this.position = function(intMode) {
		this.tbl.style.width = this.engine.width + "px";
		this.tbl.style.height = this.engine.height + "px";
		this.tbl.style.left = (((!this.left) && (intMode==2)) ? this.engine.width : 0) + "px";
		this.tbl.style.top = "0px";
	} //position

	this.constructor();
} //clsWait
	
//------------------------------------------------------
// rectangle class
//------------------------------------------------------

function clsRect(objRect) {
	this.top = 0;
	this.left = 0;
	this.bottom = 0;
	this.right = 0;
	
	this.constructor = function(objRect) {
		if ((typeof(objRect) == "object") && (objRect != null)) {
			this.top = objRect.top;
			this.left = objRect.left;
			this.bottom = objRect.bottom;
			this.right = objRect.right;
		}
	} //constructor
	
	this.inRect = function(intX, intY) {
		return ((intX >= this.left) && (intX < this.right) && (intY >= this.top) && (intY < this.bottom));
	} //inRect
	
	this.constructor(objRect);
} //clsRect

//------------------------------------------------------
// roman class
//------------------------------------------------------

function clsRoman() {
	this.digits = new Array(9);

	//class constructor	
	this.constructor = function() {
		this.digits[0] = ["M","C","X","I"];
		this.digits[1] = ["MM","CC","XX","II"];
		this.digits[2] = ["MMM","CCC","XXX","III"];
		this.digits[3] = [null,"CD","XL","IV"];
		this.digits[4] = [null,"D","L","V"];
		this.digits[5] = [null,"DC","LX","VI"];
		this.digits[6] = [null,"DCC","LXX","VII"];
		this.digits[7] = [null,"DCCC","LXXX","VIII"];
		this.digits[8] = [null,"CM","XC","IX"];
	} //constructor
	
	//convert to roman numerial
	this.toRoman = function(intValue) {
		var strResult = "";
		if (intValue < 10000) {
			for (var intIndex = 0; intIndex < 4; intIndex++) {
				var intPower = Math.floor(Math.pow(10, 3 - intIndex));
				var intDigit = Math.floor(intValue / intPower);
				intValue -= intDigit * intPower;
				if (intDigit > 0)
					strResult += this.digits[intDigit - 1][intIndex];
			}
		}
		return strResult;
	} //toRoman

	//convert from roman numerial
	this.fromRoman = function(strValue) {
		var strRoman = strValue.toUpperCase();
		var strDigit = "";
		var intResult = 0;
		var intPos = 0;
		for (var intPower = 0; intPower < 4; intPower++) {
			for (var intDigit = 8; intDigit >= 0; intDigit--) {
				strDigit = this.digits[intDigit][intPower];
				if ((strDigit != null) && (strRoman.indexOf(strDigit, intPos) == intPos)) {
					intResult = intResult + Math.floor(Math.pow(10, 3 - intPower)) * (intDigit + 1);
					intPos = intPos + strDigit.length;
					break;
				}
			} //for
			if (intPos == strRoman.length)
				break;
		} //for
		if (intPos != strRoman.length)
			intResult = 0;
		return intResult;
	} //fromRoman

	//test if numeric	
	this.isNumeric = function(strValue) {
		return ((!isNaN(parseInt(strValue))) && (parseInt(strValue) == strValue))
	} //isNumeric
	
	//convert logical to physical number
	this.getphysical = function(strPage) {
		var intPage = 0;
		if (this.isNumeric(strPage)) {
			intPage = parseInt(strPage) + Config.pageoffset;
			if ((intPage > Config.pages) || (intPage <= Config.pageoffset))
				intPage = 0;
		}			
		else {
			intPage = this.fromRoman(strPage);
			if (intPage > Config.pageoffset)
				intPage = 0;
		}
		return intPage;
	} //getPhysical
	
	//covert physical to logical number
	this.getlogical = function(intPage) {
		var strPage = intPage - Config.pageoffset;
		if ((intPage > Config.pages) || (intPage <= 0))
			strPage = "";
		else if (strPage <= 0) {
			var objRoman = new clsRoman();
			strPage = objRoman.toRoman(intPage).toLowerCase();
		}
		return strPage;
	} //getlogical
	
	this.constructor();
} //clsRoman

//------------------------------------------------------
// cross browser support
//------------------------------------------------------

function GetFirstChild(objObject)
{
	objObject = objObject.firstChild;
	if ((objObject != null) && (objObject.nodeType == 3))
		objObject = GetNextSibling(objObject);
	return objObject;
} //GetFirstChild
		
function GetNextSibling(objObject)
{
	objObject = objObject.nextSibling;
	while ((objObject != null) && (objObject.nodeType == 3))
		objObject = objObject.nextSibling;
	return objObject;
} //GetNextSibling
		
function GetPreviousSibling(objObject)
{
	objObject = objObject.previousSibling;
	while ((objObject != null) && (objObject.nodeType == 3))
		objObject = objObject.previousSibling;
	return objObject;
} //GetPreviousSibling
	
