
function paginatorInit(pageName)
{
    if (pageName == 'artisans')
    {
        new Paginator('page', 20000).paginateArtisans();
    } else {
        new Paginator('page', 1300).paginate();
    }
}

function Paginator(name, maxHeight) //constructor
{
	this._name = name;
	this._maxHeight = maxHeight;
}

Paginator.prototype =
{
	_maxHeight: 0,
	_pages: new Array(),
	
	paginate: function()
	{
        if (document.getElementById(this._name+1))
        {
            this._pages[0] = document.getElementById(this._name+1);
            if (this._pages[0].offsetHeight >= this._maxHeight)
            {
                this._moveElements();
                this._makePageNav();
                this._linkAnchors();
                this._matchHeights();
            }
        }
    },

    paginateArtisans: function()
	{
        if (document.getElementById(this._name+1))
        {
            this._pages[0] = document.getElementById(this._name+1);
            if (this._pages[0].offsetHeight >= this._maxHeight)
            {
                this._moveElementsArtisans();
                this._makePageNav();
                this._linkAnchors();
                this._matchHeights();
            }
        }
    },

    //////////////////////////////
	//	PRIVATE BUILDER METHODS	//
	//////////////////////////////
	
	_moveElements: function() // moves all elements positioned below the page breaks to new page
	{
		var node = this._pages[0].firstChild;
		while(node)
		{
			if (node.nodeType == 1 | 8) // only element or comment nodes
			{
				if (node.offsetTop+node.offsetHeight>=this._maxHeight | node.nodeValue == 'pageBreak') // if element intersects page break
				{
					var newPage = this._newPage();
					var header = document.getElementById('header').cloneNode(true);
					newPage.appendChild(header);
					var nextSiblings = this._nextSiblings(node);
					for (var a=0; a<nextSiblings.length; a++) newPage.appendChild(nextSiblings[a]);
				}
			}
			node = node.nextSibling;
		}
	},

    _moveElementsArtisans: function()
	{
		var node = this._pages[0].firstChild;
		var count = 0;
		var newPage, header, nextSiblings;

		while(node)
		{
			if (node.nodeType == 1 | 8) // only element or comment nodes
			{
				if (node.name && node.name == 'newArtisan' && count == 1)
				{
					newPage = this._newPage();
					header = document.getElementById('header').cloneNode(true);
					newPage.appendChild(header);
					nextSiblings = this._nextSiblings(node);
					for (var a=0; a<nextSiblings.length; a++) newPage.appendChild(nextSiblings[a]);
					count = 0;
				}
				else
				{
					count++;
				}
			}
			node = node.nextSibling;
		}
	},

    _makePageNav: function()
	{
		var pages = this._getPages();
		var obj = this; // reference to current instance of Paginator object so methods can be accessed within page link event handler scope
		var pageNav, pageLink;
		
		if (pages.length == 1) return;
		
		for (var a=0; a<pages.length; a++) // create one nav per page
		{
			pageNav = document.createElement('div');
			pageNav.className = 'pageNav';
			pageNav.innerHTML = 'Page ';
			
			for (var b=0; b<pages.length; b++) // create a link to each page in the nav currently being assembled
			{
				if (a!=b) // only create a link if the target is not the current page
				{
					pageLink = document.createElement('a');
					pageLink.href = '#';
					pageLink.innerHTML = b+1;
					pageLink.onclick = function()
					{
						var p = this.innerHTML;
						obj._getParentPage(this).style.visibility = 'hidden';
						document.getElementById(obj._name+p).style.visibility = 'visible';
					}
				}
				else //make current page link inactive
				{
					pageLink = document.createElement('a');
					pageLink.innerHTML = b+1;
					pageLink.style.border = 'none';
				}
				pageNav.appendChild(pageLink);
			}
			pages[a].appendChild(pageNav);
		}
	},
	
	_linkAnchors: function()
	{
		var links = document.getElementsByTagName('a');
		var areas = document.getElementsByTagName('area');
		var allLinks = new Array();
		var obj = this; // reference to current instance of Paginator object so methods can be accessed within anchor link event handler scope
		var anchorName, anchorEl;
		
		for (var i=0; i<links.length; i++) allLinks.push(links[i]); // Grr, can't concat a NodeList!
		for (var i=0; i<areas.length; i++) allLinks.push(areas[i]);
		
		for (var i=0; i<allLinks.length; i++)
		{
			if (allLinks[i].href.match(/#\w+/))
			{
				allLinks[i].onclick = function() // this == event target
				{
					anchorName = this.href.match(/#(\w+)/)[1];
					anchorEl = document.getElementById(anchorName);
					obj._getParentPage(this).style.visibility = 'hidden';
					obj._getParentPage(anchorEl).style.visibility = 'visible';
				}
			}
		}
		
	},
	
	_matchHeights: function()
	{
		var pages = this._getPages();
		var highest = 0;
		for (var a=0; a<pages.length; a++)
		{
			if (pages[a].offsetHeight > highest) highest = pages[a].offsetHeight
		}
		pages[0].style.height = highest+'px';
		if (document.getElementById('leftColumn')) document.getElementById('leftColumn').style.height = highest+100+'px';
	},
	
	//////////////////////////////
	//	PRIVATE HELPER METHODS	//
	//////////////////////////////
	
	_newPage: function()
	{
		var proto = this._pages[0];
		var result = document.createElement('div');
			result.id = this._name+(this._pages.length+1);
			result.className = 'wrapper';
			result.style.width = proto.offsetWidth+'px';
			result.style.position = 'absolute';
			result.style.top = proto.offsetTop + 'px';
			//result.style.left = proto.offsetLeft-5+'px';
			result.style.visibility = 'hidden';
		proto.parentNode.appendChild(result);
		this._pages.push(result);
		return result;
	},
	
	_nextSiblings: function(el) // returns array of argument node and all following siblings
	{
		var node = el;
		var result = new Array();
		do
		{
			if (node.nodeType == 1 | 8) result.push(node); // only accept element or comment nodes
		}	while (node = node.nextSibling);
		return result;
	},
	
	_getPages: function()
	{
		var result = new Array();
		for (var i=1; document.getElementById(this._name+i); i++)
		{
			result.push(document.getElementById(this._name+i));
		}
		return result;
	},
	
	_getParentPage: function(el)
	{
		var regExp = new RegExp(this._name);
		while(el.parentNode)
		{
			if (el.parentNode.id && regExp.test(el.parentNode.id))
			{
				return el.parentNode;
			}
			el = el.parentNode;
		}
	}
}