﻿
/**
  * MSML.Flipbook 
  * 
  * @description
  * Microsoft Live Messenger Portal flipbook funtionalities.
  * Modified 1-2-3 guide
  * 
  * @copyright       Neue Digitale / Razorfish 
  * @author          martin.krause@neue-digitale.de
  * @version         1.5
  *
  * @revision        $Revision$
  * @lastmodified    $Date$
  *
  * @jslint          2009-03-23
  *
  */


KIM.flipbook = {
	
	__version: 1.5, // class version 
	__class: 'KIM.flipbook', // class name
	 
	// set default options
	_oDefaults: {
		sSelectorVertical : '.flipbook_vertical dt',
		sSelectorOneTwoThree : '.flipBook ',
		_aStates: ['none','one','two','three','four','five'],
		_aDistances :['-=638px','+=638px']
 
	},
	
 
	
	_oAnimations : {}, // number of running animations
	// store state and action in relation to animation id in case of multiple 1-2-3 elements on one page 
	_oState: {},  //'none', // possible values : none, one, one-two, two, three, four, five
	_oAction: {}, //'', // possible values: none, one, two, three, four, five key: animationId
	 
	/**
	 * Setup
	 * @param {String} [sTitle], title
	 * @return {Void}
	 */
	_setUp: function (oOptions) {
		var _scope = KIM.flipbook;
		// merge options and defaults
		_scope._oOpt = jQuery.extend({},_scope._oDefaults, oOptions);
		_scope._oDefaults = null;
 
		
		// add events to all 1-2-3-flipbook sensitive areas (<h3>), passing neccesary options
		jQuery(_scope._oOpt.sSelectorOneTwoThree+' .one h3')
			.unbind('click.KIMflipbook')
			.bind('click.KIMflipbook',{'sType':'flipbook', 'sAction' : 'one'},KIM.flipbook.click);
		jQuery(_scope._oOpt.sSelectorOneTwoThree+' .two h3')
			.unbind('click.KIMflipbook')
			.bind('click.KIMflipbook',{'sType':'flipbook', 'sAction' : 'two'},KIM.flipbook.click);
		jQuery(_scope._oOpt.sSelectorOneTwoThree+' .three h3')
			.unbind('click.KIMflipbook')
			.bind('click.KIMflipbook',{'sType':'flipbook', 'sAction' : 'three'},KIM.flipbook.click);
		jQuery(_scope._oOpt.sSelectorOneTwoThree+' .four h3')
			.unbind('click.KIMflipbook')
			.bind('click.KIMflipbook',{'sType':'flipbook', 'sAction' : 'four'},KIM.flipbook.click);
		jQuery(_scope._oOpt.sSelectorOneTwoThree+' .five h3')
			.unbind('click.KIMflipbook')
			.bind('click.KIMflipbook',{'sType':'flipbook', 'sAction' : 'five'},KIM.flipbook.click);
			
	},
	
	/**
	 * onClick Callback
	 * @param {Event} event
	 * @return {Boolean}
	 */
	click:function (event) {
		
		var _$elParent = null;
		
		// get element
		var _$element = jQuery(this);
				
		// switch action
		switch(event.data.sType) {
 
		
			case 'flipbook':
				// get wrapper, necessary for multiple flipbooks on one page
				_$elParent = _$element.parents('div.flipBook').eq(0);
				KIM.flipbook._doClickOneTwoThree(_$element,_$elParent,event.data.sAction);
				if (typeof window.trackingFire === 'function' ) {window.trackingFire(_$elParent.attr('id').split('_cl')[1]+_$element.attr('id').split('_cl')[1]);}
			break;
		}
	
		return false;
	},
	
 

	/**
	 * Handles click type: "1-2-3"
	 * @param {jQueryElement} $element
	 * @private
	 * @return {Bool}
	 */
	_doClickOneTwoThree: function ($element,_$elParent,sAction) {
		
		// force id 
		var _sAnimationId = _$elParent.WLMidentify().attr('id');
		// exit on active element of running animation

		if ( KIM.DOM.getUnique(_sAnimationId) ) {
			return false;
		}
		// set Running flag
		KIM.DOM.setUnique(_sAnimationId);
		var _scope = KIM.flipbook;
		
		// cache current action, key: animationId
		_scope._oAction[_sAnimationId] = sAction;
		
		// set default value if necessary
		if ( typeof(_scope._oState[_sAnimationId]) == 'undefined') {_scope._oState[_sAnimationId] = 'none'; }
		
		
		var _$elements = _$elParent.find('.item');
 

		// clicked on element ...
		switch (sAction){
		
			case 'one':
			
				// slide left
				if (_scope._oState[_sAnimationId] === 'none') {
					// toggle element "one"
					_scope._animateOneTwoThree( _$elements.eq(0), _scope._oOpt._aDistances[0], _sAnimationId);
					// toggle state
					_scope._oState[_sAnimationId] = 'one';
					return true;
				}
				
				// slide right
				if (_scope._oState[_sAnimationId] === 'one') {
					// toggle element "one"
					_scope._animateOneTwoThree(_$elements.eq(0),_scope._oOpt._aDistances[1], _sAnimationId);
					// toggle state
					_scope._oState[_sAnimationId] = 'none';
					return true;
				}
				
				if (_scope._oState[_sAnimationId] === 'two') {
					// toggle elements one and two
					_scope._animateOneTwoThree(_$elements.slice(0,2),_scope._oOpt._aDistances[1], _sAnimationId);
					// toggle state
					_scope._oState[_sAnimationId] = 'none';
					return true;
				}
				
				if (_scope._oState[_sAnimationId] === 'three') {
					// toggle elements one, two and three
					_scope._animateOneTwoThree(_$elements.slice(0,3),_scope._oOpt._aDistances[1], _sAnimationId);
					// toggle state
					_scope._oState[_sAnimationId] = 'none';
					return true;
				}
				
				if (_scope._oState[_sAnimationId] === 'four') {
					// toggle elements one, two, three and four 
					_scope._animateOneTwoThree(_$elements.slice(0,4),_scope._oOpt._aDistances[1], _sAnimationId);
					// toggle state
					_scope._oState[_sAnimationId] = 'none';
					return true;
				}

				
				if (_scope._oState[_sAnimationId] === 'five') {
					// toggle elements one, two, three and four 
					_scope._animateOneTwoThree(_$elements.slice(0,4),_scope._oOpt._aDistances[1], _sAnimationId);
					// toggle state
					_scope._oState[_sAnimationId] = 'none';
				}
				
			break;
		
			case 'two':
				
				// slide left
				if (_scope._oState[_sAnimationId] === 'none') {
					// toggle element "one"
					_scope._animateOneTwoThree(_$elements.eq(0), _scope._oOpt._aDistances[0], _sAnimationId);
					// toggle state
					_scope._oState[_sAnimationId] = 'one';
					return true;
				}
				
				if (_scope._oState[_sAnimationId] === 'one') {
					// toggle element "two"
					_scope._animateOneTwoThree(_$elements.eq(1), _scope._oOpt._aDistances[0], _sAnimationId);
					// toggle state
					_scope._oState[_sAnimationId] = 'two';
					return true;
				}
				
				// slide rigth
				if (_scope._oState[_sAnimationId] === 'two') {
					// toggle element "two"
					_scope._animateOneTwoThree(_$elements.eq(1),_scope._oOpt._aDistances[1], _sAnimationId);
					// toggle state
					_scope._oState[_sAnimationId] = 'one';
					return true;
				}
				
				if (_scope._oState[_sAnimationId] === 'three') {
					// toggle elements two and three
					_scope._animateOneTwoThree(_$elements.slice(1,3),_scope._oOpt._aDistances[1], _sAnimationId);
					// toggle state
					_scope._oState[_sAnimationId] = 'one';
					return true;
				}
				
				if (_scope._oState[_sAnimationId] === 'four') {
					// toggle elemens two, three and four
					_scope._animateOneTwoThree(_$elements.slice(1,4),_scope._oOpt._aDistances[1], _sAnimationId);
					// toggle state
					_scope._oState[_sAnimationId] = 'one';
					return true;
				}

				
				if (_scope._oState[_sAnimationId] === 'five') {
					// toggle elemens two, three and four
					_scope._animateOneTwoThree(_$elements.slice(1,4),_scope._oOpt._aDistances[1], _sAnimationId);
					// toggle state
					_scope._oState[_sAnimationId] = 'one';
				}
			break;
		
			case 'three':
	 
				// slide left
				if (_scope._oState[_sAnimationId] === 'none') {
					// toggle elements one and two
					_scope._animateOneTwoThree(_$elements.slice(0,2), _scope._oOpt._aDistances[0], _sAnimationId);
					// toggle state
					_scope._oState[_sAnimationId] = 'two';
					return true;
				}
				
				if (_scope._oState[_sAnimationId] === 'one') {
					// toggle element two
					_scope._animateOneTwoThree(_$elements.eq(1), _scope._oOpt._aDistances[0], _sAnimationId);
					// toggle state
					_scope._oState[_sAnimationId] = 'two';
					return true;
				}
				
				if (_scope._oState[_sAnimationId] === 'two') {
					// toggle element three
					_scope._animateOneTwoThree(_$elements.eq(2), _scope._oOpt._aDistances[0], _sAnimationId);
					// toggle state
					_scope._oState[_sAnimationId] = 'three';
					return true;
				}
				
				
				// slide right 
				if (_scope._oState[_sAnimationId] === 'three') {
					// toggle elemen three
					_scope._animateOneTwoThree(_$elements.eq(2),_scope._oOpt._aDistances[1], _sAnimationId);
					// toggle state
					_scope._oState[_sAnimationId] = 'two';
					return true;
				}
				
				if (_scope._oState[_sAnimationId] === 'four') {
					// toggle elemens three and four
					_scope._animateOneTwoThree(_$elements.slice(2,4),_scope._oOpt._aDistances[1], _sAnimationId);
					// toggle state
					_scope._oState[_sAnimationId] = 'two';
					return true;
				}

				
				if (_scope._oState[_sAnimationId] === 'five') {
					// toggle elemens three and four
					_scope._animateOneTwoThree(_$elements.slice(2,4),_scope._oOpt._aDistances[1], _sAnimationId);
					// toggle state
					_scope._oState[_sAnimationId] = 'two';

				}
				break;
 
			case 'four':
				
				// slide left
				if (_scope._oState[_sAnimationId] === 'none') {
					// toggle elements one, two tand three
					_scope._animateOneTwoThree(_$elements.slice(0,3), _scope._oOpt._aDistances[0], _sAnimationId);
					// toggle state
					_scope._oState[_sAnimationId] = 'three';
					return true;
				}
				
				if (_scope._oState[_sAnimationId] === 'one') {
					// toggle elements two and three
					_scope._animateOneTwoThree(_$elements.slice(1,3), _scope._oOpt._aDistances[0], _sAnimationId);
					// toggle state
					_scope._oState[_sAnimationId] = 'three';
					return true;
				}
				
				if (_scope._oState[_sAnimationId] === 'two') {
					// toggle element three
					_scope._animateOneTwoThree(_$elements.eq(2), _scope._oOpt._aDistances[0], _sAnimationId);
					// toggle state
					_scope._oState[_sAnimationId] = 'three';
					return true;
				}
				
				if (_scope._oState[_sAnimationId] === 'three') {
					// toggle element four
					_scope._animateOneTwoThree(_$elements.eq(3), _scope._oOpt._aDistances[0], _sAnimationId);
					// toggle state
					_scope._oState[_sAnimationId] = 'four';
					return true;
				}
				
				// slide right
				if (_scope._oState[_sAnimationId] === 'four') {
					// toggle element four
					_scope._animateOneTwoThree(_$elements.eq(3),_scope._oOpt._aDistances[1], _sAnimationId);
					// toggle state
					_scope._oState[_sAnimationId] = 'three';
					return true;
				}

				
				if (_scope._oState[_sAnimationId] === 'five') {
					// toggle element four
					_scope._animateOneTwoThree(_$elements.eq(3),_scope._oOpt._aDistances[1], _sAnimationId);
					// toggle state
					_scope._oState[_sAnimationId] = 'three';
					return true;
				}
				
			break;
			case 'five':
				
				// slide left
				if (_scope._oState[_sAnimationId] === 'none') {
					// toggle elements one, two, three, four
					_scope._animateOneTwoThree(_$elements.slice(0,4), _scope._oOpt._aDistances[0], _sAnimationId);
					// toggle state
					_scope._oState[_sAnimationId] = 'four';
					return true;
				}
				
				if (_scope._oState[_sAnimationId] === 'one') {
					// toggle elements two, three and four
					_scope._animateOneTwoThree(_$elements.slice(1,4), _scope._oOpt._aDistances[0], _sAnimationId);
					// toggle state
					_scope._oState[_sAnimationId] = 'four';
					return true;
				}
				
				if (_scope._oState[_sAnimationId] === 'two') {
					// toggle elements three and four 
					_scope._animateOneTwoThree(_$elements.slice(2,4), _scope._oOpt._aDistances[0], _sAnimationId);
					// toggle state
					_scope._oState[_sAnimationId] = 'four';
					return true;
				}
				
				if (_scope._oState[_sAnimationId] === 'three') {
					// toggle element three
					_scope._animateOneTwoThree(_$elements.eq(3), _scope._oOpt._aDistances[0], _sAnimationId);
					// toggle state
					_scope._oState[_sAnimationId] = 'four';
					return true;
				}
				
				// slide right 
				if (_scope._oState[_sAnimationId] === 'four') {
					// toggle elements one, two, three and four 
					_scope._animateOneTwoThree(_$elements.slice(0,4),_scope._oOpt._aDistances[1], _sAnimationId);
					// toggle state
					_scope._oState[_sAnimationId] = 'none';
					return true;
				}

			break;
		}
		
		// failed sliding, remove running flag 
		KIM.DOM.unsetUnique(_sAnimationId);
		// exit
		return false;
		
	},
	
	/**
	 * Toggle element for animation "1-2-3"
	 * @param {jQuery-Element} $element to toggle
	 * @param {String} sAction marker
	 * @param {string} sAnimationId animation id aka running flag
	 */
	_animateOneTwoThree: function ($elements,_sLeft,sAnimationId) {
 
		var _scope = KIM.flipbook;
 		// create temporary wrapper element forcing smooth animations
		$elements
			.wrapAll(jQuery('<div class="" id="animationWrapper" style="position: relative; height: 456px;">'));
			
		// run animation on temporary wrapper
		jQuery('#'+sAnimationId)
			.addClass('animation');
			
		jQuery('#animationWrapper')
			.css('zIndex',($elements.eq(0).css('zIndex')))
			.addClass('animation')
			.animate(
				{
					left: _sLeft
				},
				{
					step: function(now, fx){
						// force integer
						fx.elem.style.left = Math.round(now)+fx.unit;
					},
					complete: function(){
						
						// force position on animated elements if the wrapper element ain't there
						if ( _sLeft.split('=')[0] == '-') {
							var _iLeft = -1* parseInt(_sLeft.split('=')[1]);
						} else {
							var _iLeft = parseInt(_sLeft.split('=')[1]);
						}
						$elements.each(function () {
							jQuery(this).css('left', ( parseInt(jQuery(this).css('left'))+ _iLeft) )
						})
						// remove wrapper element
			 			jQuery('#animationWrapper').replaceWith(
							$elements
						);
						// run oncomplete function
						KIM.flipbook.onComplete(sAnimationId,'flipBook');
					}
				}
			);
	},

 	 
	
	/**
	 * Animation onComplete callback
	 * @param {String} sAnimationId aka running flag
	 * @param {String} sType void || flipBook
	 * @return {void}
	 */
	onComplete : function (sAnimationId) {

		// clear states
		var _aStates = KIM.flipbook._oOpt._aStates;
		for (var _sState in _aStates) {
			jQuery('#'+sAnimationId).removeClass('state-'+_aStates[_sState])
		};
		
		// add current state class
		jQuery('#'+sAnimationId)
			.addClass('state-'+KIM.flipbook._oState[sAnimationId]);
		
		// remove animation classes
		jQuery(KIM.flipbook._oOpt.sSelectorOneTwoThree +' .animation')
			.removeClass('animation');
		jQuery(KIM.flipbook._oOpt.sSelectorOneTwoThree)
			.removeClass('animation');
		
		// remove flag
		KIM.DOM.unsetUnique(sAnimationId);

	},
	
	 /**
	 * Constructor
	 * @param {Object} [oOptions]
	 * @constructor
	 */
	initialize: function (oOptions) {
		// fake singleton
		if (this._oOpt) {
			return this;
		}
		// setup 
		this._setUp(oOptions);
		// fake singleton
		return this;
	}
};

// initialize onDOMReady
jQuery(function() {
	KIM.flipbook.initialize();
});
