/*
Script: 	PaneOpener.js
			A MooTools Plugin to integrate panel opening/closing (extending/retracting) (requires MooTools 1.1)

License:
			MIT-style license.
*/ 

/*
Class: PaneOpener
		Works with Mootools 1.2 in compatibility mode (works with 1.11 if you switch the 
		.removeEvents line to the one underneath)

Syntax:
 >new PaneOpener( togglerSelector, paneSelector[, options] );

Arguments:
	togglerSelector 	- (string) The togglers whose onclick will open their respective panes.  Elements selected via $(togglerSelector)
	paneSelector 		- (string) Similar but for the pane that will open
	options 				- (string, optional) Fx.Base options plus...
	
	options (continued):
		isAccordian - (bool) True, makes 
	
Events:
	onOpen - (function) Event called when toggler is clicked and pane is closed (hidden)
		Signaure:
			>onOpen( toggler, pane )
	
		Arguments:
			toggler 	- (string) Selector for elements to be used as togglers (on click) for their next occurring pane
			pane 		- (string) Selector for elements that will be the panes to hide/show

	onClose 			- (function) Event called when toggler is clicked and pane is open (showing)
		Arguments:
			toggler 	- (string) Selector for elements to be used as togglers (on click) for their next occurring pane
			pane 		- (string) Selector for elements that will be the panes to hide/show

	onAfterOpen 	- (function) Event called when after opening tween
		Arguments:
			toggler 	- (string) Selector for elements to be used as togglers (on click) for their next occurring pane
			pane 		- (string) Selector for elements that will be the panes to hide/show

	onAfterClose 	- (function) Event called when after closing tween
		Arguments:
			toggler 	- (string) Selector for elements to be used as togglers (on click) for their next occurring pane
			pane 		- (string) Selector for elements that will be the panes to hide/show


Properties:
	_togglers - (array, private) Array of all togglers.  Note
	_tgl_tstate - (bool, private) Not a class prop but is added to the toggler elements indicating open/close state (close = false)
	_tgl_isAnim - (bool, private) Not a class prop but is added to the toggler elements indicating whether animation is in progress
	_tgl_tgl_pane - (element)	Not a class prop but is added to the toggler elements.  References the element who the toggler shows/hides.
	closeAll			


Example[s]:

Note:
	Click events are disabled while animation is occurring to prevent unsynchronisation of event firing.  (needs refining)
	All panes start closed.
	There should be an equal amount of togglers and panes.
	Theres a slight glitch in IE due to a stray height that creaps on after close.  The method used in accordian works fine so this 
	should be rewritten to work similarly

Version History:
1.01	- Wrapped click event in try...catch to prevent garbage collection error in FF
*/
var PaneOpener = new Class({
	_togglers: new Array(),			// Keep track so we can closeAll when accordian effect desired
	_isAnim : false,					// Latch to disable click events whil animation running
	
	initialize: function ( togglerSel, paneSel, options ){
		var toggle, pane, fx;
		var classRef = this;

		// Get the toggle links and their respective panes
		var toggleLinks = $$( togglerSel );
		var togglePanes = $$( paneSel );

		// Loop through and set up Fx's
		for ( var i=0; i<toggleLinks.length; i++ ) {
	
			// They should have the same length
			if (!$defined( toggleLinks[i] ) || !$defined( togglePanes[i] ))
				continue;
			
			toggle = toggleLinks[i];
			pane = togglePanes[i];
	
			toggle._tgl_pane = pane;		// reference for onToggled event
			
			// default to toggled off
			toggle._tgl_tstate = false;

			// Clean up options
			var fxOptions = new Object();
			for (var j in options) {
				if (j != 'onAfterOpen' && j != 'onAfterClose' && j != 'onOpen' && j != 'onClose' && j != 'isAccordian') 
					fxOptions[j] = options[j];
			}

			// Hide panels by default	
			toggle._fx = new Fx.Slide( pane, fxOptions );
			toggle._fx.hide();
			
			// Add to the class var
			this._togglers[this._togglers.length] = toggle;
	
			// Assign click event to toggler
			toggle.addEvent( 'click', function () { 
				// Bug in Moo GC cases errors so wrap in a try... (see hack below)															
				try {												
					var toggler = this;
					var pane = this._tgl_pane;
					
					
					// Check animation flag and return if set...
					//if ($defined( this._tgl_isAnim ) && this._tgl_isAnim)
					if (classRef._isAnim)	
						return;
					
					// Clear all onComplete events
					//this._fx.removeEvents('onComplete');			// doesnt work!! in 1.11
					delete (this._fx.$events['onComplete']);	// hack
								
					// Choose event functions depending on whether we are currently open or closed				
					// true = open, ie closing
					if (this._tgl_tstate) {
					
						// EVENT: onClose()
						if ($defined ( options.onClose ) )
							options.onClose( toggler, pane);
						
						// EVENT: onComplete()
						if ($defined ( options.onAfterClose )) {
							this._fx.addEvent( 'onComplete', function () {
								options.onAfterClose( toggler, pane );
							});
						}
										
					}
					
					// false = close, ie opening
					else {
					
						// EVENT: onOpen()
						if ($defined ( options.onOpen ) )
							options.onOpen( toggler, pane);
						
						// EVENT: onAfterOpen()
						if ($defined ( options.onAfterOpen )) {
							this._fx.addEvent( 'onComplete', function () {
								options.onAfterOpen( toggler, pane );
							});
						}
					
					}
						
					// Set the is animating flag and set oncomplete event to clear it
					this._tgl_isAnim = true;
					//TODO: classRef._isAnim = true;
					
					this._fx.addEvent( 'onComplete', function () {
						//TODO: classRef._isAnim = false;
						toggler._tgl_isAnim = false;														 
					});
						
						
					// Do the toggle and change the state
					this._fx.toggle(); 
					this._tgl_tstate = !this._tgl_tstate;
					
					// Accordian style?
					if ($defined( options.isAccordian ) && options.isAccordian) {
						classRef.closeAll();			
					}
				} catch (e) {};
			});
		}
	},
	
	
	/*
	Property: 	closeAll()
					Fires click event for all open panes' togglers, thereby closing them.  Used for accordian effect
	*/
	closeAll: function () {
		var toggler;
		
		// Close all unclosed panes by firing toggler click event
		for (var i in this._togglers) {
			toggler = this._togglers[i];
			
			if (toggler._tgl_tstate && !toggler._tgl_isAnim) {			// TRUE = OPEN
				toggler.fireEvent( 'click' );
			}
		}
	}
	
	/*
	Property:	setAnimLatch()
					Sets the animation latch to true disabling PaneOpener click events...
	
	setAnimLatch: function () {
		this._isAnim = true;	
	},
*/
	/*
	Property:	clearAnimLatch()
					Clears the animation latch reenabling PaneOpener click events...
	
	clearAnimLatch: function () {
		this._isAnim = false;	
	}
*/
});


