/*
 *******************************************************************
 *******************************************************************

	Content Scroller Javascript Module
	Nicholas Ortenzio

	Requires : Prototype and Scriptaculous

 *******************************************************************
 *******************************************************************
 */

var contentScroller = Class.create({

	/*
	 ***************************************
	 * CONSTRUCTOR
	 ***************************************
	 */
	
	initialize : function(scrollerModule) {
		this.scrollerModule = scrollerModule;
		scrollerModule.scrollerModule = this;
		
		this.setOptions();
		this.setDomElements();
		
		// no elements in scroller
		if (this.panels.length == 0) { this.disableNav(); return; }
		
		this.setProperties();
		this.setNavStates();
		this.setToc();
		this.setEvents();
		this.setAutoScrolling();

		var initialPage = Math.max(Math.floor((this.options.defaultPanel-1)/this.options.scroll),0);
		if ( this.initialPage > 0) {this.navigate(initialPage); }
		this.updateToc(initialPage);
	},

	/*
	 ***************************************
	 * INITIALIZATION METHODS
	 ***************************************
	 */

	setOptions : function() {
		this.options = {
			prevSelector : '',
			nextSelector : '',
			tocSelector : '',

			viewportSelector : '.scroller_viewport',
			holderSelector : '.scroller_items',
			panelSelector : '.scroller_item',

			panelHoverClass : 'highlighted',
			activeTocClass : 'active',
		    enabledNavClass : 'enabled',
			disabledNavClass : 'disabled',
			hoverNavClass : 'hover',
			
			navEnabled : true,
			scroll : 1,
			wrap : false,
			effect : 'sinoidal',
			duration : 1.0,
			autoScroll : false,
			defaultPanel : 1
		};

		for (var x in this.options) {
			this.options[x] = this.scrollerModule.readAttribute(x) || this.options[x];
		}

		this.options.scroll = parseInt(this.options.scroll);
		this.options.autoScroll = parseFloat(this.options.autoScroll);
		this.options.duration = parseFloat(this.options.duration);
		this.options.defaultPanel = parseInt(this.options.defaultPanel);
	
		this.options.navEnabled = (this.options.navEnabled.toString()=="false")?false:true;
		this.options.wrap = (this.options.wrap.toString()=="true");
		this.options.effect = Effect.Transitions[this.options.effect];
		this.navTo = this.navigate;
	},

	setDomElements : function() {
		this.dots = [];
		this.viewport = this.scrollerModule.select(this.options.viewportSelector)[0];
		this.holder = this.scrollerModule.select(this.options.holderSelector)[0];

		this.toc = (this.options.tocSelector) ? this.scrollerModule.select(this.options.tocSelector)[0] : null;
		this.panels = this.scrollerModule.select(this.options.panelSelector);
		this.prevNavs = this.scrollerModule.select(this.options.prevSelector);
		this.nextNavs = this.scrollerModule.select(this.options.nextSelector);
	},

	setProperties : function() {
		this.panelWidth = this.getWidthPlusMargin(this.panels[0]);
		this.viewportWidth = this.viewport.getWidth();
		this.disableScrolling = (this.holder.getWidth() <= this.viewport.getWidth());
		
		this.currentPanel = 0;
		this.visiblePanels = Math.floor(this.viewportWidth/this.panelWidth);

		this.options.scroll = Math.min(this.options.scroll, this.visiblePanels);
		this.maxIndex = this.panels.length - this.visiblePanels;
		this.totalPages = Math.ceil((this.panels.length-this.visiblePanels)/this.options.scroll) + 1;
	},

	setNavStates : function() {
		if (this.maxIndex <= 0) {
			this.options.autoScroll = false;
			this.options.navEnabled = false;
			this.prevNavs.each(function(n) {
				n.addClassName(this.options.disabledNavClass);
			}.bind(this));
			this.nextNavs.each(function(n) {
				n.addClassName(this.options.disabledNavClass);
			}.bind(this))
		} else if (this.options.wrap) {
			this.prevNavs.each(function(n) {
				n.addClassName(this.options.enabledNavClass);
			}.bind(this));
			this.nextNavs.each(function(n) {
				n.addClassName(this.options.enabledNavClass);
			}.bind(this))
		} else {
			this.prevNavs.each(function(n) {
				n.addClassName(this.options.disabledNavClass);
			}.bind(this));
		}
	},

	setToc : function() {
		if (this.totalPages<2) { this.toc = false; }
		if (!this.toc) return;
		for (var x=0; x<this.totalPages; ++x) {
			this.dots.push(document.createElement('span'));
			this.dots[x].innerHTML = '&nbsp;';
			this.toc.insert(this.dots[x]);
			
			var s = Math.min(x*this.options.scroll, this.maxIndex);
			if(this.options.navEnabled){$(this.dots[x]).observe('click', this.activate.bind(this,s))}
		}
	},

	setEvents : function() {

		if (this.options.navEnabled) {
			this.prevNavs.each(function(n){
				n.observe('click', this.navigate.bind(this, -1));
				n.observe('mouseover', function(){n.addClassName(this.options.hoverNavClass)}.bind(this));
				n.observe('mouseout',  function(){n.removeClassName(this.options.hoverNavClass)}.bind(this));
			}.bind(this));

			this.nextNavs.each(function(n){
				n.observe('click', this.navigate.bind(this, 1));
				n.observe('mouseover', function(){n.addClassName(this.options.hoverNavClass)}.bind(this));
				n.observe('mouseout',  function(){n.removeClassName(this.options.hoverNavClass)}.bind(this));
			}.bind(this));
		} else { 
			this.disableNav();
		}

		this.panels.each(function(n){
			n.observe('mouseover', function(){n.addClassName(this.options.panelHoverClass)}.bind(this));
			n.observe('mouseout', function(){n.removeClassName(this.options.panelHoverClass)}.bind(this));
		}.bind(this));
	},

	disableNav : function() {
		this.prevNavs.each(function(n){n.addClassName(this.options.disabledNavClass)}.bind(this));
		this.nextNavs.each(function(n){n.addClassName(this.options.disabledNavClass)}.bind(this));	
	},
	
	setAutoScrolling : function() {
		if (!this.options.autoScroll) return;
		if (this.autoTimer) this.autoTimer.stop();
		this.autoTimer = new PeriodicalExecuter(this.onAutoScroll.bind(this), this.options.autoScroll);
	},

	onAutoScroll : function() {
		this.navigate(1);
	},

	/*
	 ***************************************
	 * 
	 ***************************************
	 */

	getWidthPlusMargin : function(t){
		var w = t.getWidth();
		var l = t.getStyle('marginLeft');
		var r = t.getStyle('marginRight');

		if (l.indexOf('%')>-1) {
			l = $(t.parentElement).getWidth() * parseInt(l,10) / 100;
		} else {
			l = parseInt(l,10) || 0;
		}

		if (r.indexOf('%')>-1) {
			r = $(t.parentElement).getWidth() * parseInt(r,10) / 100;
		} else {
			r = parseInt(r,10) || 0;
		}

		return w + l + r;
	},

	navigate : function(dir) {
		var index = this.currentPanel + (dir * this.options.scroll);
		
		if (!this.options.wrap){
			if (index < 0) {
				index = 0;
			} else if (index > this.maxIndex) {
				index = this.maxIndex;
			}
		} else {
			if (index < 0) {
				if (this.currentPanel > 0) {
					index = 0;
				} else {
					index = this.maxIndex;
				}
			} else if (index > this.maxIndex) {
				if (this.currentPanel < this.maxIndex) {
					index = this.maxIndex;
				} else {
					index = 0;
				}
			}
		}
	
    if (this.panels.length <= this.visiblePanels) { return; }
	if (this.disableScrolling) { return; }
		this.activate(index);
	},

	updateToc : function(panel) {
		if (!this.toc) return;
		var alpha = Math.ceil(this.currentPanel/this.options.scroll)
		var omega = Math.ceil(panel/this.options.scroll)

		if (!this.dots[alpha] || !this.dots[omega]) return;

		$(this.dots[alpha]).removeClassName(this.options.activeTocClass);
		$(this.dots[omega]).addClassName(this.options.activeTocClass);
	},

	updateNavElements : function(panel) {
		if (this.options.wrap) return;

		this.prevNavs.each(function(n){
			if (panel == 0) {
				n.addClassName(this.options.disabledNavClass);
				n.removeClassName(this.options.enabledNavClass);
			} else {
				n.addClassName(this.options.enabledNavClass);
				n.removeClassName(this.options.disabledNavClass);
			}
		}.bind(this));

		this.nextNavs.each(function(n){
			if (panel >= this.maxIndex) {
				n.addClassName(this.options.disabledNavClass);
				n.removeClassName(this.options.enabledNavClass);
			} else {
				n.addClassName(this.options.enabledNavClass);
				n.removeClassName(this.options.disabledNavClass);
			}
		}.bind(this));

	},

	beforeAnimate : function(panel) {
		this.isAnimating = true;
		this.updateNavElements(panel);
		this.updateToc(panel);
	},

	afterAnimate : function(panel) {
		this.isAnimating = false;
		this.currentPanel = panel;
	},

	activate : function(panel) {
		this.setAutoScrolling();
		if (this.isAnimating) return;
		var left = this.panelWidth * panel * -1;	

		new Effect.Move(this.holder, { 
			x: left,
			mode: 'absolute', 
			queue : 'end',
			transition: this.options.effect,
			duration : this.options.duration,
			beforeStart : this.beforeAnimate.bind(this,panel),
			afterFinish : this.afterAnimate.bind(this,panel)
		});
	}
});

//document.observe("dom:loaded", function() {$$('.scrollerModule').each(function(i){new contentScroller(i)})});

NBAUtil.Events.addDomLoadedHandler(function() { $$('.scrollerModule').each(function(i) { new contentScroller(i); }); });
