
/*===============================================================================
	AJAXPager.js
	John Larson
	6/24/08
	
	Component for managing history of a collection of swappable sections
	within a single div as a series of parameterizable pages.
	
	Example:
	<div id="myPageRegion">
	  <div id="page1">
	    ... link to page 2 ...
	  </div>
	  <div id="page2">
	    ... link to page 3 ...
	  </div>
	  <div id="page3">
	    ... link to page 1 ...
	    ... link to page 2 ...
	  </div>
	</div>
	
	var myAJAXPager = new AJAXPager('myPageRegion');
	
	Dependencies:
		HistoryManager.js
	
===============================================================================*/


var AJAXPager = new Class({
	
	Implements: [Options, Events],
	
	options: {
		initiallyVisiblePage:			null,
		historyKey:						null,
		autoCachePages:					true,
		skipAllAJAX:					false,
		AJAXLoadInitialPage:			false,
		AJAXExemptPageIDSet:			[],
		pageTransitionCallback:			$empty,
		manageHistory:					true,
		showAJAXLoadMessage:			true
	},
	
	initialize: function(pageContainer, AJAXURL, options){
		
		this.setOptions(options);
		
		this.AJAXURL = AJAXURL;
		if(!this.options.skipAllAJAX  &&  AJAXURL.indexOf('[pageID]') == -1)
			throw('Insertible [pageID] missing from provided AJAXURL.');
		
		
		this.pageContainer = $(pageContainer);
		var pageSet = this.pageContainer.getChildren();
		if(pageSet.length == 0)
			throw('No section divs in pageContainer passed to AJAXPager constructor.');
	//	dbug.log(pageSet);
		
		this.currentPage = this.options.initiallyVisiblePage  ||  pageSet[0];
		var me = this;
	//	dbug.log(this.currentPage);
		// Hide all of the ones that are not visible:
		pageSet.each(function(thePage) {
			thePage.setStyle('display', thePage == me.currentPage ? 'block' : 'none');
			thePage.loadedQueryString = null; // query string of the page instance already loaded
			thePage.subPagerSet = [];
		});
		
		this.pageSet = pageSet;
		
		AJAXPager.instanceCount++;
		
		this.currentlyInTransition = false;
		
		if(this.options.manageHistory) {
			this.historyKey = this.options.historyKey  ||  'Page' + AJAXPager.instanceCount;
			this.history = HistoryManager.register(
				this.historyKey,
				[this.currentPage.id],
				
				// onMatch, callback when the state changed (here, values[0] === pageHashLink):
				function(values) {
					dbug.nog('onMatch: ' + values[0]);
					this._doPageTransition(values[0]);
				}.bind(this),
				
				// onGenerate: generates a hash segment for this Pager (values[0] === pageHashLink)
				function(values) {
					return this.historyKey + '(' + values[0] + ')';
				}.bind(this),
				
				// regexp: extracts precisely what is generated by onGenerate from the big hash
				this.historyKey + '\\(([^\\).]+)\\)',
				{skipDefaultMatch: true }
			);
		}
		
		if(this.options.AJAXLoadInitialPage) {
			dbug.nog('AJAXPager::must load ' + this.currentPage.id);
			this._doPageTransition(this.currentPage.id);
		}
	},
	
	destroy: function() {
		if(this.options.manageHistory)
			this.history.unregister();
	},
	
	setAlternateOnLoadUpdateSection: function(thePage, theUpdateSection) {
		$(thePage).updateSection = theUpdateSection;
	},
	
	
	goToPage: function(pageHashLink, skipAJAXLoad) {
		
		if(pageHashLink == this.pageHashLink) { // already here!
			dbug.nog('would go to ' + pageHashLink + ', but already here!');
			return;
		}
		if(this.currentlyInTransition)
			return;
		this.currentlyInTransition = true;
		
		dbug.nog('###setValue(' + pageHashLink + ')!!');
		if(this.options.manageHistory)
			this.history.setValue(0, pageHashLink);
		
		this._doPageTransition(pageHashLink, skipAJAXLoad);
	},
	
	_doPageTransition: function(pageHashLink, skipAJAXLoad) {
		
		if(pageHashLink == this.pageHashLink) { // already here!
		//	dbug.log('would go to ' + pageHashLink + ', but already here!');
			return;
		}
		
		var pageHashSet = pageHashLink.split('?');
		var pageID = pageHashSet[0];
	//	dbug.log('>>>_doPageTransition(' + pageHashLink + ')');
		var pageQueryString = pageHashSet.length == 1 ? '_zero=0' : pageHashSet[1];
		
		this.pageHashLink = pageHashLink;
		
		var oldPage = this.currentPage;
		var newPage = $(pageID);
		if(!newPage) { // just like broken [pageHash]Link!  Default to first page we DO have.
			newPage = this.pageSet[0];
			pageID = newPage.id;
		}
		
		// Since we're navigating away from the old page, all of it's sub-pager's must go:
		oldPage.subPagerSet.each(function(theSubPager) {
			theSubPager.destroy();
		});
		oldPage.subPagerSet = []; // clear all
		
		if(skipAJAXLoad  ||  this.options.skipAllAJAX  ||
		   this.options.AJAXExemptPageIDSet.contains(pageID)  ||
		   (this.options.autoCachePages  &&  newPage.loadedQueryString == pageQueryString)) {
			// no need to do an AJAX load, just show it:
		//	dbug.log('no need to load ' + pageHashLink);
			this._swapVisiblePage(newPage);
		}
		else {
		//	dbug.log('AJAX load ' + pageHashLink);
			// will load via AJAX and then swap to:
			var me = this;
			if(this.options.showAJAXLoadMessage) showLoad();
			new Request.HTML({ url: this.AJAXURL.replace('[pageID]', pageID),
				method: 'post',
				data: pageQueryString,
				update: newPage.updateSection  ||  newPage,
				evalScripts: true,
				onComplete: function() {
					if(me.options.showAJAXLoadMessage) hideLoad();
					me._swapVisiblePage(newPage);
				}
			}).send();
		}
		
		this.options.pageTransitionCallback(pageHashLink);
	},
	
	getCurrentPageHashLink: function() {
		return this.pageHashLink;
	},
	
	addSubPager: function(whichPage, subAJAXPager) {
		
		whichPage = $(whichPage);
		if(!this.pageSet.contains(whichPage))
			throw('Invalid call to addSubPager: ' + whichPage + ' does not belong to this pager.');
		whichPage.subPagerSet.push(subAJAXPager);
		
	},
	
	removeSubPager: function(whichPage, subAJAXPager) {
		whichPage.subPagerSet.erase(subAJAXPager);
	},
	
	_swapVisiblePage: function(newPage) {
		
		var oldPage = this.currentPage;
		
		if(newPage.style.display == 'none') { // only swap if not already swapped!
			x = newPage;
			var me = this
			var oldPageFx = oldPage.get('tween');
			var newPageFx = newPage.get('tween');
			oldPageFx.start('opacity', 1, 0).chain(function() {
				newPage.style.visibility = 'hidden';
				oldPage.style.display = 'none';
				newPage.style.display = '';
				newPageFx.start('opacity', 0, 1);
				me.currentlyInTransition = false;
			});
			
			this.currentPage = newPage;
		}
		else
			this.currentlyInTransition = false;
	}
	
});

AJAXPager.instanceCount = 0;

