var objAttachToContainer = null;	// HTML element that the paginator will be attached (usually a DIV).
var objBook = null;					// Paginator book object.
var strID = '';						// Container element id.
var intCurPageNum = 1;				// The current page number.
var intPrevPageNum = 0;				// The Previous page number.		
var isPaginationOn = true;			// Checks if pagination is on off.
    
/* A page object stores information about "page" divs and the anchors on the "page" divs.
   strPageID: The ID of the page being created. */
function ClsPage(strPageID) {
  var aryBookmarks = new Array();	// Array of bookmark anchors on this page.
  
  /* Add a bookmark to this page object. 
	 strBookmarkID: Bookmark anchor ID. */
  this.AddBookmark = function AddBookmark(strBookmarkID) { aryBookmarks.push(strBookmarkID); }
  /* Get the page ID. */
  this.GetPageID = function GetPageID() { return strPageID; }  
  /* Get all the bookmarks IDs in an array. */
  this.GetAllBookmarks = function GetAllBookmarks() { return aryBookmarks; }
  /* Get the number of bookmarks on this page. */
  this.GetNumBookmarks = function GetNumBookmarks() { return aryBookmarks.length; }  
  /* Checks if a particular bookmark exists on this page.
	 strBookmarkID: Bookmark anchor ID. */
  this.IsBookmarkOnPage = function IsBookmarkOnPage(strBookmarkID) {
	for(var i = 0; i < aryBookmarks.length; i++) {
	  if(aryBookmarks[i] == strBookmarkID)
		return true;
	}
	return false;		
  }  
}

/* A book object holds a collection of page objects.*/
function ClsBook() {
  var aryObjPages = new Array();	// Array of ClsPage objects;

  /* Add a page to this book object. 
	 strPageID: The ID of the page to add to this book object. */
  this.AddPage = function AddPage(strPageID) { aryObjPages.push(new ClsPage(strPageID)); }
  /* Get a single page based on page index. 
	 intIndex: The index number of the page to get. */
  this.GetPageByIndex = function GetPageByIndex(intIndex) {
	if(aryObjPages.length != 0 && intIndex >= 0 && intIndex < aryObjPages.length)
	  return aryObjPages[intIndex];
	else
	  return false;	  
  }
  /* Get a single page based on the page ID. 
	 strPageID: The ID of the page to get. */
  this.GetPageByID = function GetPageByID (strPageID) {
	for(var i = 0; i < aryObjPages.length; i++) {
	  if(aryObjPages[i].GetPageID() == strPageID)
		return aryObjPages[i];
	}
	return false;
  }
  /* Get the last page in the book. */
  this.GetLastPage = function GetLastPage() {
	if(aryObjPages.length > 0)
	  return aryObjPages[(aryObjPages.length - 1)]; 
	else
	  return false;
  }
  /* Get all the pages in this book object. */
  this.GetAllPages = function GetAllPages() { return aryObjPages; }
  /* Get the number pages in this book object. */
  this.GetNumPages = function GetNumPages() { return aryObjPages.length; }
  /* Check if a bookmark exists in this book. */
  this.IsBookmarkInBook = function IsBookmarkInBook(strBookmarkID) {  
	for(var i = 0; i < aryObjPages.length; i++) {
	  if(aryObjPages[i].IsBookmarkOnPage(strBookmarkID))
		return (i + 1);
	}
	return false;
  }
}

/* Creates a book object based on the current Web page. */
function CreateBook(objNode, objBook, strPageIdentifier) {
  var objChildrenNodes;		// Child nodes of parent node.

  // Check if the DOM element is actually a node.
  if(objNode.nodeType == Node.ELEMENT_NODE) {
	// Ensure that the node has a tag name.
	if(!IsUndefined(objNode.tagName)) {
	  /* Check if the tag name is DIV and if it has a class name equal to 
		 the strPageIdentifier parameter value. */
	  if((objNode.tagName).toLowerCase() == "div" && objNode.className == strPageIdentifier) {
		/* Check if the node has an id or a name attribute and that the value of that 
		   attribute is not empty, otherwise create an id for this tag */
		if(!IsUndefined(objNode.id) && objNode.id != "")
		  strPageID = objNode.id;
		else if(!IsUndefined(objNode.name) && objNode.name != "") {
		  strPageID = objNode.name;
		  objNode.id = objNode.name;
		}
		else
		  objNode.id = strPageIdentifier + (objBook.GetNumPages() + 1);

		objBook.AddPage(objNode.id);
	  }
	  
	  /* Check if there are any pages in the book then check for
		 internal links in this DIV. */
	  if(objBook.GetNumPages() > 0 && IsAnchor(objNode))
		(objBook.GetLastPage()).AddBookmark(objNode.id);
	}
  }
  
  // Get all the child nodes of the current node if there are any.
  objChildrenNodes = objNode.childNodes;

  // Recurssively loop through the child nodes.
  for(var i = 0; i < objChildrenNodes.length; i++)
	CreateBook(objChildrenNodes[i], objBook, strPageIdentifier);
  
  return objBook;
}

/* Finds the Y coordinate for the specified object. */
function FindYPos(objElement) {
  var intPosition = 0;	// The position of the element in question.
  
  // Check the element's parent position.
  if(objElement.offsetParent) {
	while(objElement.offsetParent) {
	  intPosition += objElement.offsetTop
	  objElement = objElement.offsetParent;
	}
  }
  else if(objElement.y)
	intPosition += objElement.y;
  else
	;

  return intPosition;
}

/* Scrolls the window to the specified X and Y coordinates. */
function ScrollToPosition(intXPos, intYPos) {
  window.scrollTo(intXPos, intYPos);
}

/* Generates the pagination HTML code. */
function GenerateNavHTML(strNavID) {
  var strNavHTML = '';	// HTML code for the paginator script.

  // Make sure the book has pages and the content DIV exists.
  if(objBook.GetNumPages() > 0 && objAttachToContainer != null) {		
	strNavHTML = strNavHTML + '<a href="javascript:void(0);" onclick="ShowPage(\'prev\', 0);" id="' + strNavID + '_prev">&#8249;&nbsp;</a>&nbsp;'
	  
	// Generate the page navigation links.
	for(var i = 0; i < objBook.GetNumPages(); i++)
	  strNavHTML  = strNavHTML  + '<a href="javascript:void(0);" onclick="ShowPage(' + (i + 1) + ', 0);" id="' + strNavID + '_' + (i + 1) + '">' + (i + 1) + "</a>&nbsp;";

	strNavHTML = strNavHTML + '<a href="javascript:void(0);" onclick="ShowPage(\'next\', 0);" id="' + strNavID + '_next">&nbsp;&#8250;</a>&nbsp;';	
  }
  
  return strNavHTML;
}

function PrintPages(printAll) {
  if(printAll) {
	ShowPage('off', 0);
	print();
  }
  else
	print();  
}


function HandleInternalLinkClick(objEvent, objElement) {
  var strBookmarkID = (objElement.hash).substring(1);
  var intPageNum = objBook.IsBookmarkInBook(strBookmarkID);

  if(intPageNum)
	this.ShowPage(intPageNum);
}

/* Show the appropriate page. */
function ShowPage(intPageID, intYScroll) {
  var objLink;						// Link object.
  var objPrevLink;					// "Previous" link object.
  var objNextLink;					// "Next" link object. 
  var isPageVisible = false;		// Determines if a page is visible or not.
  var strPageDisPropVal = 'none';
  var strPNavDisPropVal = 'visible';
	
  if(isNumber(intCurPageNum))
	intPrevPageNum = intCurPageNum;

  if(isNumber(intPageID)) {	
	intCurPageNum = intPageID;
  }
  else if(intPageID == 'next') {	
	if((intCurPageNum + 1) > objBook.GetNumPages())
	  intCurPageNum = objBook.GetNumPages();
	else
	  intCurPageNum = intCurPageNum + 1;  
  }
  else if(intPageID == 'prev') {
	if((intCurPageNum - 1) < 1)
	  intCurPageNum = 1;
	else
	  intCurPageNum = intCurPageNum - 1;
  }
  else {
	if(intPageID == 'off' && isPaginationOn) {
	  isPageVisible = true;
	  strPNavDisPropVal = 'hidden';
	  isPaginationOn = false;
	}
	else if(intPageID == 'on' && !isPaginationOn) {
	  isPageVisible = false;
	  strPNavDisPropVal = 'visible';
	  isPaginationOn = true;
	}
	else
	  ;
  }
 
  if((intPrevPageNum > 0 && intPrevPageNum <= objBook.GetNumPages()) && (intCurPageNum > 0 && intCurPageNum <= objBook.GetNumPages())) {
	togglePageVis(intPrevPageNum, false);
	if(MM_findObj(strID + "_" + intPrevPageNum))
	  MM_findObj(strID + "_" + intPrevPageNum).style.background = "#eee";
	togglePageVis(intCurPageNum, true);
	if(MM_findObj(strID + "_" + intCurPageNum))
	  MM_findObj(strID + "_" + intCurPageNum).style.background = "#ff6";		
  }
   
  //ScrollToPosition(0, intYScroll);
  if(!document.location.hash)
	ScrollToPosition(0, 0);
}

/* Toggle the visibility of the speficied page. */
function togglePageVis(intPageNum, isVisible) {
  if(isVisible)
	MM_findObj(objBook.GetPageByIndex((intPageNum - 1)).GetPageID()).style.display = "block";
  else
	MM_findObj(objBook.GetPageByIndex((intPageNum - 1)).GetPageID()).style.display = "none";
}

/* Initialize the paginator object. */
function InitPaginator(strContainerID, strPageIdentifier) {
  var intYScroll = 0;

  // Find the object with the id specified by the strContainerID parameter.
  objAttachToContainer = MM_findObj(strContainerID);
  // Create a book object by locating all HTML elements with the id spedicifed by the strPageIdentifier parameter.
  objBook = CreateBook(document, (new ClsBook), strPageIdentifier);
  // Set the container id.
  strID = strContainerID;

  // If the container object was found generate the page navigation HTML code and place the code within the container.
  if(objAttachToContainer)
	objAttachToContainer.innerHTML =  objAttachToContainer.innerHTML + GenerateNavHTML(strContainerID);

  /* Loop through the hashed links in this document and associate the onclick event of 
	 internal links found in this book with the HandleInternalLinkClick function. */
  for(var i = 0; i < document.links.length; i++) {
	if(document.links[i].hash) {
	  document.links[i].onclick = associateObjWithEvent(this, "HandleInternalLinkClick");
	}
  }

  /* If there is a hash (#) symbol in the URL check if the bookmark ID exists
	 in this book. If the bookmark exists set the current page number to the
	 page where the bookmark was found. */
/*  if(document.location.hash) {
	strBookmarkID = (document.location.hash).substring(1);

	if(objBook.IsBookmarkInBook(strBookmarkID)) {
	  intCurPageNum = objBook.IsBookmarkInBook(strBookmarkID);
	  intYScroll = FindYPos(MM_findObj(strBookmarkID));
	  window.status = document.location.hash + ": " + intYScroll;
	}
	else
	  window.location.href = window.location.href;
  }*/
  
  if(objBook.GetNumPages() > 0) {
  /* If there is a hash (#) symbol in the URL check if the bookmark ID exists
	 in this book. If the bookmark exists set the current page number to the
	 page where the bookmark was found. */
	if(document.location.hash) {
	  strBookmarkID = (document.location.hash).substring(1);

	  if(objBook.IsBookmarkInBook(strBookmarkID)) {
		intCurPageNum = objBook.IsBookmarkInBook(strBookmarkID);
		intYScroll = FindYPos(MM_findObj(strBookmarkID));
		//window.status = document.location.hash + ": " + intYScroll;
	  }
	}
  	
	// Hide all the pages.
  	for(var i = 1; i < (objBook.GetNumPages() + 1); i++)
	  togglePageVis(i, false);
	 
	// Show the current page (the first page).
	ShowPage(intCurPageNum, intYScroll);
  }
}

window.onload = function () {
  InitPaginator("paginator_pagenums", "paginator_page");
}