/** A pluggable paging/navigation object
 * 
 * @author Erick S <esatire at gmail dot com>
 * @version 1.2 28/12/2007 - Added options for double navbars, and jumpTo points
 */

/** The semi-abstract class constructor
 * 
 * The DOM should contain 2 objects for this:
 * 1) A container for content with some id with id + _container
 * 2) A container for the pages navigator with id + _pagenavigator
 * For example a DIV with id "shmulik_container" and another DIV with id "shmulik_pagenavigator"
 * 
 * @param elementIdPrefix{string} As explained above
 * @param numPerPage{int} how many items are in each page
 * @param pageSpan{int} optional - how many page links will be created
 */
function PageNavigator(elementIdPrefix, numPerPage, pageSpan)
{
	// since it's meant to be used as a parent a lot,
	// It will only be inited if containerId was entered
	if (elementIdPrefix)
	{
		this.container = document.getElementById(elementIdPrefix + "_container");
		this.pageNavigator = document.getElementById(elementIdPrefix + "_pagenavigator");
		this.secondNavigator = null; // Some elements have a navigator on top and on bottom
		var myself = this;
		this.numItems = 0; // Could be useful for derived classes
		this.curPage = -1;
		this.totalPages = 0;
		this.lastClicked = null; // Saves the last clicked paging link (For display purposes)
		/** Element - If set - after each page request we will scroll to this */
		this.jumpElement = null; 
		if (numPerPage) this.numPerPage = numPerPage;
		this.pageSpan = (pageSpan) ? pageSpan : 3;
		this.request = null; // For ajax. Init through child constructor.
		this.serverScript = null;
		// Classes for the links - modify as you see fit
		this.linkClass = 'navBarLink';
		this.activeClass = 'navBarActive';
		this.extraClass = 'navBarExtra'; // Used for outmost arrows
		this.linkSeperator = ''; // What to put between links in the pager

		// pluggable methods
		this.onPageRequest = function(){};
		this.onLink = function()
		{
			if (myself.request.InProgress()) return false;
			if (myself.lastClicked != null)
				myself.lastClicked.style.borderStyle = 'solid';

			this.style.borderStyle = 'inset';
			myself.lastClicked = this;
			myself.requestPage(parseInt(this.id));
		}
	}
}
/** Called on page set - feel free to overrid when needed */
PageNavigator.prototype.boundCheck = function(pageNum)
{
	if (pageNum < 0 || pageNum >= this.totalPages) return false;
	return true;
}
PageNavigator.prototype.setPage = function(pageNum)
{
	// keep pagenum within upper boundary
	this.curPage = (pageNum >= this.totalPages) ? this.totalPages - 1 : pageNum;
	this.createPagingLinks();
}
/** When sending the ajax request */
PageNavigator.prototype.requestPage = function(pageNum)
{
	pageNum = parseInt(pageNum);
	if (isNaN(pageNum)) pageNum = 1;
	if (this.boundCheck(pageNum)) this.onPageRequest(pageNum);
}
PageNavigator.prototype.nextPage = function()
{
	this.requestPage(this.curPage+1);
}
PageNavigator.prototype.nextPage = function()
{
	this.requestPage(this.curPage+1);
}
PageNavigator.prototype.setNumItems = function(numItems)
{
	this.numItems = numItems;
	this.totalPages = Math.ceil(numItems/this.numPerPage);
	if (this.totalPages == 0) this.totalPages = 1;
}
/** Creates the actual links in the pagenavigator DOM element */
PageNavigator.prototype.createPagingLinks = function()
{
	if (this.totalPages <= 1)
	{
		this.pageNavigator.innerHTML = '';
		if (this.secondNavigator) this.secondNavigator.innerHTML = '';
		return;
	}

	var navigatorHTML = new Array();
	var iStart,iEnd;
	if (this.curPage <= this.pageSpan)
	{
		iStart = 0;
		iEnd   = this.pageSpan*2;
	}
	else if (this.curPage > (this.totalPages-1)-this.pageSpan)
	{
		iStart = this.totalPages - 1 - this.pageSpan*2;
		iEnd   = this.totalPages;
	}
	else
	{
		iStart = this.curPage-this.pageSpan;
		iEnd   = this.curPage+this.pageSpan;
	}
	// out of bounds fix
	if (iEnd > (this.totalPages-1)) iEnd = (this.totalPages-1);
	if (iStart < 0) iStart = 0;
	
	if (iStart > 0)
		navigatorHTML.push("<td class='"+this.extraClass+"' id='0' title='עמוד ראשון'>&laquo;</td>");

	if (this.curPage > 0)
		navigatorHTML.push("<td class='"+this.linkClass+"' id='"+(this.curPage-1)+"' title='הקודם'>&lt;</td>");

	for (var i=iStart; i<=iEnd;i++)
	{
		if (i != this.curPage)
		{
			navigatorHTML.push("<td class='"+this.linkClass+"' id='"+i+"'>" + (i+1) + "</td>");
		}
		else
		{ // it has a span so we can give it a different style than the '...' parts 
			navigatorHTML.push("<td class='"+this.activeClass+"'>"+(i+1)+"</td>");
		}
	}
	
	if (this.curPage < this.totalPages-1)
		navigatorHTML.push("<td class='"+this.linkClass+"' id='"+(this.curPage+1)+"' title='הבא'>&gt;</td>");		

	if (iEnd < (this.totalPages-1))
		navigatorHTML.push("<td class='"+this.extraClass+"' id='"+(this.totalPages-1)+"' title='עמוד אחרון'>&raquo;</td>");
		
	this.pageNavigator.innerHTML=	'<table cellspacing="4" cellpadding="0" border="0" class="stdNavBar">'+
											navigatorHTML.join(this.linkSeperator)+'</tr></table>';
	navigatorHTML = null;
	
	// work on the links
	var links = this.pageNavigator.getElementsByTagName('td');
	for (var i=0;i<links.length;i++)
	{
		if (links[i].className != this.activeClass) links[i].onclick = this.onLink;
	}
	if (this.secondNavigator)
	{
		this.secondNavigator.innerHTML = this.pageNavigator.innerHTML;
		links = this.secondNavigator.getElementsByTagName('td');
		for (var i=0;i<links.length;i++)
		{
			if (links[i].className != this.activeClass) links[i].onclick = this.onLink;
		}
	}
}
/** Basic functionality for request results - when the responseText is the block's HTML */
PageNavigator.prototype.onRequestResult = function(responseText,pageNum,count_id)
{
	this.container.innerHTML = responseText;
	var count;
	try
	{
		var element = document.getElementById(count_id);
		if (!element) throw Error();
		count = parseInt(element.innerHTML);
		if (isNaN(count)) throw Error();
	}
	catch (ex)
	{
		count = 0;
	}
	this.setNumItems(count);
	this.setPage(pageNum);
	if (this.jumpElement) this.jumpElement.scrollIntoView();
}