//Ajax Pagination Script- Author: Dynamic Drive (http://www.dynamicdrive.com)
//** Created Sept 14th, 07'
//** Updated Oct 31st, 07'- Fixed bug when book only contains 1 page
//** Updated Aug 9th 08'- Upgraded to v1.2:
			//1) Adds ability to limit the range of the visible pagination links shown for a book with many pages
			//2) Adds Session only persistence to persist the last page user viewed when navigating away then returning to the webpage containing the script.
			//3) Modified Ajax request function in IE7 to use ActiveXObject object, so script can be tested offline

//** Updated Oct 21st 08'- Upgraded to v1.2.1: Fixed bug with no content showing when there's only one page
//** Updated Dec 1st 08'- v1.2.2: Fixed bug in FF when only one page in book

var ajaxpageclass=new Object()
ajaxpageclass.loadstatustext="Requesting content, please wait..." // HTML to show while requested page is being fetched:
ajaxpageclass.ajaxbustcache=false // Bust cache when fetching pages?
ajaxpageclass.paginatepersist=false //enable persistence of last viewed pagination link (so reloading page doesn't reset page to 1)?
ajaxpageclass.pagerange=4 // Limit page links displayed to a specific number (useful if you have many pages in your book)?
ajaxpageclass.ellipse="..." // Ellipse text (no HTML allowed)

/////////////// No need to edit beyond here /////////////////////////

ajaxpageclass.connect=function(pageurl, divId){
	var page_request = false
	var bustcacheparameter=""
	if (window.XMLHttpRequest && !document.all) // if Mozilla, Safari etc (skip IE7, as object is buggy in that browser)
		page_request = new XMLHttpRequest()
	else if (window.ActiveXObject){ // if IE6 or below
		try {
		page_request = new ActiveXObject("Msxml2.XMLHTTP")
		} 
		catch (e){
			try{
			page_request = new ActiveXObject("Microsoft.XMLHTTP")
			}
			catch (e){}
		}
	}
	else
		return false
	document.getElementById(divId).innerHTML=this.loadstatustext //Display "fetching page message"
	page_request.onreadystatechange=function(){ajaxpageclass.loadpage(page_request, divId)}
	if (this.ajaxbustcache) //if bust caching of external page
		bustcacheparameter=(pageurl.indexOf("?")!=-1)? "&"+new Date().getTime() : "?"+new Date().getTime()
	page_request.open('GET', pageurl+bustcacheparameter, true)
	page_request.send(null)
}

ajaxpageclass.loadpage=function(page_request, divId){
	if (page_request.readyState == 4 && (page_request.status==200 || window.location.href.indexOf("http")==-1)){
		document.getElementById(divId).innerHTML=page_request.responseText;
		if(window.scrollTo){
			scrollTo(0, 0);
		}
	}
}

ajaxpageclass.getCookie=function(Name){ 
	var re=new RegExp(Name+"=[^;]+", "i"); //construct RE to search for target name/value pair
	if (document.cookie.match(re)) //if cookie found
		return document.cookie.match(re)[0].split("=")[1] //return its value
	return null
}

ajaxpageclass.setCookie=function(name, value){
	document.cookie = name+"="+value
}

ajaxpageclass.getInitialPage=function(divId, pageinfo){
	var persistedpage=this.getCookie(divId)
	var selectedpage=(this.paginatepersist && this.getCookie(divId)!=null)? parseInt(this.getCookie(divId)) : pageinfo.selectedpage
	return (selectedpage>pageinfo.pages.length-1)? 0 : selectedpage //check that selectedpage isn't out of range
}

ajaxpageclass.createBook=function(pageinfo, divId, paginateIds){ //MAIN CONSTRUCTOR FUNCTION
	this.pageinfo=pageinfo //store object containing URLs of pages to fetch, selected page number etc
	this.divId=divId
	this.paginateIds=paginateIds //array of ids corresponding to the pagination DIVs defined for this pageinstance
	//NOTE: this.paginateInfo stores references to various components of each pagination DIV defined for this pageinstance
	//NOTE: Eg: divs[0] = 1st paginate div, pagelinks[0][0] = 1st page link within 1st paginate DIV, prevlink[0] = previous link within paginate DIV etc
	this.paginateInfo={divs:[], pagelinks:[[]], prevlink:[], nextlink:[], previouspage:null, previousrange:[null,null], leftellipse:[], rightellipse:[]}
	this.dopagerange=false
	this.pagerangestyle=''
	this.ellipse='<span style="display:none">'+ajaxpageclass.ellipse+'</span>' //construct HTML for ellipse
	var initialpage=ajaxpageclass.getInitialPage(divId, pageinfo)
	this.buildpagination(initialpage)
	this.selectpage(initialpage)
}

ajaxpageclass.createBook.prototype={

	buildpagination:function(selectedpage){ //build pagination links based on length of this.pageinfo.pages[]
		this.dopagerange=(this.pageinfo.pages.length>ajaxpageclass.pagerange) //Bool: enable limitpagerange if pagerange value is less than total pages available
		this.pagerangestyle=this.dopagerange? 'style="display:none"' : '' //if limitpagerange enabled, hide pagination links when building them
		this.paginateInfo.previousrange=null //Set previousrange[start, finish] to null to start
		if (this.pageinfo.pages.length<=1){ //no 0 or just 1 page
			document.getElementById(this.paginateIds[0]).innerHTML=(this.pageinfo.pages.length==1)? "" : ""
			return
		}
		else{ //construct paginate interface
			var paginateHTML='<div class="pagination"><ul>\n'
			paginateHTML+='<li><a href="#previous" rel="'+(selectedpage-1)+'">«</a></li>\n' //previous link HTML
			for (var i=0; i<this.pageinfo.pages.length; i++){
				var ellipses={left: (i==0? this.ellipse : ''), right: (i==this.pageinfo.pages.length-1? this.ellipse : '')} //if this is 1st or last page link, add ellipse next to them, hidden by default
				paginateHTML+='<li>'+ellipses.right+'<a href="#page'+(i+1)+'" rel="'+i+'" '+this.pagerangestyle+'>'+(i+1)+'</a>'+ellipses.left+'</li>\n'
			}
			paginateHTML+='<li><a href="#next" rel="'+(selectedpage+1)+'">next »</a></li>\n' //next link HTML
			paginateHTML+='</ul></div>'
		}// end construction
		this.paginateInfo.previouspage=selectedpage //remember last viewed page
		for (var i=0; i<this.paginateIds.length; i++){ //loop through # of pagination DIVs specified
			var paginatediv=document.getElementById(this.paginateIds[i]) //reference pagination DIV
			this.paginateInfo.divs[i]=paginatediv //store ref to this paginate DIV
			paginatediv.innerHTML=paginateHTML
			var paginatelinks=paginatediv.getElementsByTagName("a")
			var ellipsespans=paginatediv.getElementsByTagName("span")
			this.paginateInfo.prevlink[i]=paginatelinks[0]
			if (paginatelinks.length>0)
				this.paginateInfo.nextlink[i]=paginatelinks[paginatelinks.length-1]
			this.paginateInfo.leftellipse[i]=ellipsespans[0]
			this.paginateInfo.rightellipse[i]=ellipsespans[1]
			this.paginateInfo.pagelinks[i]=[] //array to store the page links of pagination DIV
			for (var p=1; p<paginatelinks.length-1; p++){
				this.paginateInfo.pagelinks[i][p-1]=paginatelinks[p]
			}
			var pageinstance=this
			paginatediv.onclick=function(e){
				var targetobj=window.event? window.event.srcElement : e.target
				if (targetobj.tagName=="A" && targetobj.getAttribute("rel")!=""){
					if (!/disabled/i.test(targetobj.className)){ //if this pagination link isn't disabled (CSS classname "disabled")
						pageinstance.selectpage(parseInt(targetobj.getAttribute("rel")))
					}
				}
				return false
			}
		}
	},

	selectpage:function(selectedpage){
		//replace URL's root domain with dynamic root domain (with or without "www"), for ajax security sake:
		if (this.pageinfo.pages.length>0){
			var ajaxfriendlyurl=this.pageinfo.pages[selectedpage].replace(/^http:\/\/[^\/]+\//i, "http://"+window.location.hostname+"/")
			ajaxpageclass.connect(ajaxfriendlyurl, this.divId) //fetch requested page and display it inside DIV
		}
		if (this.pageinfo.pages.length<=1) //if this book only contains only 1 page (or 0)
			return //stop here
		var paginateInfo=this.paginateInfo
		for (var i=0; i<paginateInfo.divs.length; i++){ //loop through # of pagination DIVs specified
			//var paginatediv=document.getElementById(this.paginateIds[i])
			paginateInfo.prevlink[i].className=(selectedpage==0)? "prevnext disabled" : "prevnext" //if current page is 1st page, disable "prev" button
			paginateInfo.prevlink[i].setAttribute("rel", selectedpage-1) //update rel attr of "prev" button with page # to go to when clicked on
			paginateInfo.nextlink[i].className=(selectedpage==this.pageinfo.pages.length-1)? "prevnext disabled" : "prevnext"
			paginateInfo.nextlink[i].setAttribute("rel", selectedpage+1)
			paginateInfo.pagelinks[i][paginateInfo.previouspage].className="" //deselect last clicked on pagination link (previous)
			paginateInfo.pagelinks[i][selectedpage].className="currentpage" //select current pagination link
		}
		paginateInfo.previouspage=selectedpage //Update last viewed page info
		ajaxpageclass.setCookie(this.divId, selectedpage)
		this.limitpagerange(selectedpage) //limit range of page links displayed (if applicable)
	},

	limitpagerange:function(selectedpage){
		//reminder: selectedpage count starts at 0 (0=1st page)
		var paginateInfo=this.paginateInfo
		if (this.dopagerange){
			var visiblelinks=ajaxpageclass.pagerange-1 //# of visible page links other than currently selected link
			var visibleleftlinks=Math.floor(visiblelinks/2) //calculate # of visible links to the left of the selected page
			var visiblerightlinks=visibleleftlinks+(visiblelinks%2==1? 1 : 0) //calculate # of visible links to the right of the selected page
			if (selectedpage<visibleleftlinks){ //if not enough room to the left to accomodate all visible left links
				var overage=visibleleftlinks-selectedpage
				visibleleftlinks-=overage //remove overage links from visible left links
				visiblerightlinks+=overage //add overage links to the visible right links
			}
			else if ((this.pageinfo.pages.length-selectedpage-1)<visiblerightlinks){ //else if not enough room to the left to accomodate all visible right links
				var overage=visiblerightlinks-(this.pageinfo.pages.length-selectedpage-1)
				visiblerightlinks-=overage //remove overage links from visible right links
				visibleleftlinks+=overage //add overage links to the visible left links
			}
			var currentrange=[selectedpage-visibleleftlinks, selectedpage+visiblerightlinks] //calculate indices of visible pages to show: [startindex, endindex]
			var previousrange=paginateInfo.previousrange //retrieve previous page range
			for (var i=0; i<paginateInfo.divs.length; i++){ //loop through paginate divs
				if (previousrange){ //if previous range is available (not null)
					for (var p=previousrange[0]; p<=previousrange[1]; p++){ //hide all page links
						paginateInfo.pagelinks[i][p].style.display="none"
					}
				}
				for (var p=currentrange[0]; p<=currentrange[1]; p++){ //reveal all active page links
					paginateInfo.pagelinks[i][p].style.display="inline"
				}
				paginateInfo.pagelinks[i][0].style.display="inline" //always show 1st page link
				paginateInfo.pagelinks[i][this.pageinfo.pages.length-1].style.display="inline" //always show last page link
				paginateInfo.leftellipse[i].style.display=(currentrange[0]>1)? "inline" : "none" //if starting page is page3 or higher, show ellipse to page1
				paginateInfo.rightellipse[i].style.display=(currentrange[1]<this.pageinfo.pages.length-2)? "inline" : "none" //if end page is 2 pages before last page or less, show ellipse to last page
			}
		}
			paginateInfo.previousrange=currentrange
	},

	refresh:function(pageinfo){
	this.pageinfo=pageinfo
	var initialpage=ajaxpageclass.getInitialPage(this.divId, pageinfo)
	this.buildpagination(initialpage)
	this.selectpage(initialpage)
	}
}
// URL: www.freecontactform.com
// Version: FreeContactForm Lite V1.0
// Copyright (c) 2009 Stuart Cochrane <stuartc1@gmail.com>
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
function has_id(id){try{var tmp=document.getElementById(id).value;}catch(e){return false;}
return true;}
function has_name(nm){try{var tmp=cfrm.nm.type;}catch(e){return false;}
return true;}
function $$(id){if(!has_id(id)&&!has_name(id)){alert("Field "+id+" does not exist!\n Form validation configuration error.");return false;}
if(has_id(id)){return document.getElementById(id).value;}else{return;}}
function $val(id){return document.getElementById(id);}
function trim(id){$val(id).value=$val(id).value.replace(/^\s+/,'').replace(/\s+$/,'');}
var required={field:[],add:function(name,type,mess){this.field[this.field.length]=[name,type,mess];},out:function(){return this.field;},clear:function(){this.field=[];}};var validate={check:function(cform){var error_message='Please fix the following errors:\n\n';var mess_part='';var to_focus='';var tmp=true;for(var i=0;i<required.field.length;i++){if(this.checkit(required.field[i][0],required.field[i][1],cform)){}else{error_message=error_message+required.field[i][2]+'  is invalid\n';if(has_id(required.field[i][0])&&to_focus.length===0){to_focus=required.field[i][0];}
tmp=false;}}
if(!tmp){alert(error_message);}
if(to_focus.length>0){document.getElementById(to_focus).focus();}
return tmp;},checkit:function(cvalue,ctype,cform){if(ctype=="NOT_EMPTY"){if(this.trim($$(cvalue)).length<1){return false;}else{return true;}}else if(ctype=="EMAIL"){exp=/^[a-zA-Z0-9._%-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/;if($$(cvalue).match(exp)==null){return false;}else{return true;}}},trim:function(s){if(s.length>0){return s.replace(/^\s+/,'').replace(/\s+$/,'');}else{return s;}}};
//Drop Down/ Overlapping Content: http://www.dynamicdrive.com
//**Updated: Dec 19th, 07': Added ability to dynamically populate a Drop Down content using an external file (Ajax feature)
//**Updated: Feb 29th, 08':
				//1) Added ability to reveal drop down content via "click" of anchor link (instead of default "mouseover")
				//2) Added ability to disable drop down content from auto hiding when mouse rolls out of it
				//3) Added hidediv(id) public function to directly hide drop down div dynamically

//**Updated: Sept 11th, 08': Fixed bug whereby drop down content isn't revealed onClick of anchor in Safari/ Google Chrome

var dropdowncontent={
	disableanchorlink: true, //when user clicks on anchor link, should link itself be disabled (always true if "revealbehavior" above set to "click")
 hidedivmouseout: [true, 200], //Set hiding behavior within Drop Down DIV itself: [hide_div_onmouseover?, miliseconds_before_hiding]
	ajaxloadingmsg: "Loading content. Please wait...", //HTML to show while ajax page is being feched, if applicable
	ajaxbustcache: true, //Bust cache when fetching Ajax pages?

	getposOffset:function(what, offsettype){
		return (what.offsetParent)? what[offsettype]+this.getposOffset(what.offsetParent, offsettype) : what[offsettype]
	},

	isContained:function(m, e){
		var e=window.event || e
		var c=e.relatedTarget || ((e.type=="mouseover")? e.fromElement : e.toElement)
		while (c && c!=m)try {c=c.parentNode} catch(e){c=m}
		if (c==m)
			return true
		else
			return false
	},

	show:function(anchorobj, subobj, e){
		if (!this.isContained(anchorobj, e) || (e && e.type=="click")){
			var e=window.event || e
			if (e.type=="click" && subobj.style.visibility=="visible"){
				subobj.style.visibility="hidden"
				return
			}
			var horizontaloffset=(subobj.dropposition[0]=="left")? -(subobj.offsetWidth-anchorobj.offsetWidth) : 0 //calculate user added horizontal offset
			var verticaloffset=(subobj.dropposition[1]=="top")? -subobj.offsetHeight : anchorobj.offsetHeight //calculate user added vertical offset
			subobj.style.left=this.getposOffset(anchorobj, "offsetLeft") + horizontaloffset + "px"
			subobj.style.top=this.getposOffset(anchorobj, "offsetTop")+verticaloffset+"px"
			subobj.style.clip=(subobj.dropposition[1]=="top")? "rect(auto auto auto 0)" : "rect(0 auto 0 0)" //hide drop down box initially via clipping
			subobj.style.visibility="visible"
			subobj.startTime=new Date().getTime()
			subobj.contentheight=parseInt(subobj.offsetHeight)
			if (typeof window["hidetimer_"+subobj.id]!="undefined") //clear timer that hides drop down box?
				clearTimeout(window["hidetimer_"+subobj.id])
			this.slideengine(subobj, (subobj.dropposition[1]=="top")? "up" : "down")
		}
	},

	curveincrement:function(percent){
		return (1-Math.cos(percent*Math.PI)) / 2 //return cos curve based value from a percentage input
	},

	slideengine:function(obj, direction){
		var elapsed=new Date().getTime()-obj.startTime //get time animation has run
		if (elapsed<obj.glidetime){ //if time run is less than specified length
			var distancepercent=(direction=="down")? this.curveincrement(elapsed/obj.glidetime) : 1-this.curveincrement(elapsed/obj.glidetime)
			var currentclip=(distancepercent*obj.contentheight)+"px"
			obj.style.clip=(direction=="down")? "rect(0 auto "+currentclip+" 0)" : "rect("+currentclip+" auto auto 0)"
			window["glidetimer_"+obj.id]=setTimeout(function(){dropdowncontent.slideengine(obj, direction)}, 10)
		}
		else{ //if animation finished
			obj.style.clip="rect(0 auto auto 0)"
		}
	},

	hide:function(activeobj, subobj, e){
		if (!dropdowncontent.isContained(activeobj, e)){
			window["hidetimer_"+subobj.id]=setTimeout(function(){
				subobj.style.visibility="hidden"
				subobj.style.left=subobj.style.top=0
				clearTimeout(window["glidetimer_"+subobj.id])
			}, dropdowncontent.hidedivmouseout[1])
		}
	},

	hidediv:function(subobjid){
		document.getElementById(subobjid).style.visibility="hidden"
	},

	ajaxconnect:function(pageurl, divId){
		var page_request = false
		var bustcacheparameter=""
		if (window.XMLHttpRequest) // if Mozilla, IE7, Safari etc
			page_request = new XMLHttpRequest()
		else if (window.ActiveXObject){ // if IE6 or below
			try {
			page_request = new ActiveXObject("Msxml2.XMLHTTP")
			} 
			catch (e){
				try{
				page_request = new ActiveXObject("Microsoft.XMLHTTP")
				}
				catch (e){}
			}
		}
		else
			return false
		document.getElementById(divId).innerHTML=this.ajaxloadingmsg //Display "fetching page message"
		page_request.onreadystatechange=function(){dropdowncontent.loadpage(page_request, divId)}
		if (this.ajaxbustcache) //if bust caching of external page
			bustcacheparameter=(pageurl.indexOf("?")!=-1)? "&"+new Date().getTime() : "?"+new Date().getTime()
		page_request.open('GET', pageurl+bustcacheparameter, true)
		page_request.send(null)
	},

	loadpage:function(page_request, divId){
		if (page_request.readyState == 4 && (page_request.status==200 || window.location.href.indexOf("http")==-1)){
			document.getElementById(divId).innerHTML=page_request.responseText
		}
	},

 init:function(anchorid, pos, glidetime, revealbehavior){
		var anchorobj=document.getElementById(anchorid)
		var subobj=document.getElementById(anchorobj.getAttribute("rel"))
		var subobjsource=anchorobj.getAttribute("rev")
		if (subobjsource!=null && subobjsource!="")
			this.ajaxconnect(subobjsource, anchorobj.getAttribute("rel"))
		subobj.dropposition=pos.split("-")
		subobj.glidetime=glidetime || 1000
		subobj.style.left=subobj.style.top=0
		if (typeof revealbehavior=="undefined" || revealbehavior=="mouseover"){
			anchorobj.onmouseover=function(e){dropdowncontent.show(this, subobj, e)}
			anchorobj.onmouseout=function(e){dropdowncontent.hide(subobj, subobj, e)}
			if (this.disableanchorlink) anchorobj.onclick=function(){return false}
		}
		else
			anchorobj.onclick=function(e){dropdowncontent.show(this, subobj, e); return false}
		if (this.hidedivmouseout[0]==true) //hide drop down DIV when mouse rolls out of it?
			subobj.onmouseout=function(e){dropdowncontent.hide(this, subobj, e)}
	}
}





var mmOpenContainer = null;
var mmOpenMenus = null;
var mmHideMenuTimer = null;

function MM_menuStartTimeout(hideTimeout) {
	mmHideMenuTimer = setTimeout("MM_menuHideMenus()", hideTimeout);	
}

function MM_menuHideMenus() {
	MM_menuResetTimeout();
	if(mmOpenContainer) {
		var c = document.getElementById(mmOpenContainer);
		c.style.visibility = "inherit";
		mmOpenContainer = null;
	}
	if( mmOpenMenus ) {
		for(var i = 0; i < mmOpenMenus.length ; i++) {
			var m = document.getElementById(mmOpenMenus[i]);
			m.style.visibility = "hidden";			
		}
		mmOpenMenus = null;
	}
}

function MM_menuHideSubmenus(menuName) {
	if( mmOpenMenus ) {
		var h = false;
		var c = 0;
		for(var i = 0; i < mmOpenMenus.length ; i++) {
			if( h ) {
				var m = document.getElementById(mmOpenMenus[i]);
				m.style.visibility = "hidden";
			} else if( mmOpenMenus[i] == menuName ) {
				h = true;
			} else {
				c++;
			}
		}
		mmOpenMenus.length = c+1;
	}
}

function MM_menuOverMenuItem(menuName, subMenuSuffix) {
	MM_menuResetTimeout();
	MM_menuHideSubmenus(menuName);
	if( subMenuSuffix ) {
		var subMenuName = "" + menuName + "_" + subMenuSuffix;
		MM_menuShowSubMenu(subMenuName);
	}
}

function MM_menuShowSubMenu(subMenuName) {
	MM_menuResetTimeout();
	var e = document.getElementById(subMenuName);
	e.style.visibility = "inherit";
	if( !mmOpenMenus ) {
		mmOpenMenus = new Array;
	}
	mmOpenMenus[mmOpenMenus.length] = "" + subMenuName;
}

function MM_menuResetTimeout() {
	if (mmHideMenuTimer) clearTimeout(mmHideMenuTimer);
	mmHideMenuTimer = null;
}

function MM_menuShowMenu(containName, menuName, xOffset, yOffset, triggerName) {
	MM_menuHideMenus();
	MM_menuResetTimeout();
	MM_menuShowMenuContainer(containName, xOffset, yOffset, triggerName);
	MM_menuShowSubMenu(menuName);
}

function MM_menuShowMenuContainer(containName, x, y, triggerName) {	
	var c = document.getElementById(containName);
	var s = c.style;
	s.visibility = "inherit";
	
	mmOpenContainer = "" + containName;
}