﻿/**
 * @author POP webdev [tw+cn]
 * @classDescription Project-specific class to manage an expanding effect of a list of promos.
 * @return {Object}	Returns an new instance.
 * This class depends on Prototype v1.6 and Scriptaculous effects.
 */
var PromoExpando = Class.create ({
	initialize: function(elPromoList, options)
	{
		this.options = Object.extend({
			expandedStyle: {width: '370px'}, 
			contractedStyle: {width: '183px'},
			contractedBGImageClassName: 'pe_bg_contracted'
		}, options || {});

		this.promoList = $(elPromoList);
		if(!this.promoList){return;} // element check
		
		this.promoListID = this.promoList.identify();

		this.promos = this.promoList.select('li');
		this.promos.each(function(promo){
			// get the original calculated width
			promo._originalWidth = promo.getWidth() -1;//  -1 = prototype/scriptaculous adds 1px border to elements calculated width, need to subtract -1px)
		});

		this._activeIndex = -1;

		// Attach an event handler to the ul
				
		this.promoList.observe('mouseover', this.__ListOver.bindAsEventListener(this));
		this.promoList.observe('mouseout', this.__ListOut.bindAsEventListener(this));

		// create selector/style pair objects to pass to transform
		var oContractLi = {};
		oContractLi['ul#' + this.promoListID + ' li:not([class~=selected])'] = this.options.contractedStyle;
		var oContractBG = {};
		oContractBG['ul#' + this.promoListID + ' li:not([class~=selected]) div.' + this.options.contractedBGImageClassName] = 'opacity: .4';
		var oExpandLi = {};
		oExpandLi['ul#' + this.promoListID + ' li.selected'] = this.options.expandedStyle;
		var oExpandBG = {};
		oExpandBG['ul#' + this.promoListID + ' li.selected div.' + this.options.contractedBGImageClassName] = 'opacity: 1.0';

		this.fxScopeID = 'scope_' + this.promoListID;
		var boundFxCancel = this._cancelEfxInQueue.bind(this);
	
		
		// store transformations (multiple effects in parallel than can be played)
		this.transformation = new Effect.Transform(
			[
				oContractLi,
				oContractBG,
				oExpandLi,
				oExpandBG
			], {
					queue: {position:'front', scope: this.fxScopeID, limit: 1}, 
					duration: 0.35, 
					transition: Effect.Transitions.sinoidal,
					beforeStart: boundFxCancel
				}
		);
		
		var oResetLi = {};
		oResetLi['ul#' + this.promoListID + ' li'] = this.options.contractedStyle; // this width will be overwritten with it's unique slot width before effect setup
		var oResetBG = {};
		oResetBG['ul#' + this.promoListID + ' li div.' + this.options.contractedBGImageClassName] = 'opacity: .4';
		
		this.resetTansformation = new Effect.Transform(
			[	
				oResetLi,
				oResetBG
			], { 
					duration: 0.3,
					queue: {position:'end', scope: this.fxScopeID, limit:2},
					beforeSetup:function(fxInstance){
						fxInstance.effects.each(function(fx){
							// overwrite contracted width with original width for li elements
							if(fx.element._originalWidth){
								fx.style.set('width', fx.element._originalWidth + 'px');
								//console.log(fx.style.get('width'));							
							}
						});
					}
				}
		);

		// set initial state
		this.resetPromos();
		
		// set initial promo to expand - BF
		if (this.options.initialExpandedPromo) {
			this.promos[this.options.initialExpandedPromo].addClassName("selected");
			this.expandPromo(this.options.initialExpandedPromo);
		}
	},

	__ListOver: function(e){
		var element = Event.findElement(e, 'li');
		if(element){
			var promoIndex = this.promos.indexOf(element);
			this._activeIndex = promoIndex;
			
			// add/remove selected class
			for(var i=0, len = this.promos.length; i < len; i++){
				var idx = this.promos.indexOf(this.promos[i]);
				(idx > -1 && idx == promoIndex) ? this.promos[i].addClassName('selected'): this.promos[i].removeClassName('selected');
			}
			
			this.expandPromo(promoIndex);
		}
	},

	__ListOut: function(e){
		this._activeIndex = -1;
		this.resetPromos.bind(this).delay(.1);

		// remove selected class name - added 12/8 BF
		this.promos.each(function(each) {
			each.removeClassName('selected');
		});
	},

	expandPromo: function(index){
		// console.log('expanding');
		this.transformation.play();
	},

	resetPromos: function(){
		if(this._activeIndex != -1){return;}

		//console.log('resetting');
		this.resetTansformation.play();
	},
	
	_cancelEfxInQueue: function(fxInstance){
		Effect.Queues.get(this.fxScopeID).invoke('cancel');
	}

});
