/**
 * $Id::                                                                       $
 * 
 * Tab Control creates tabs for defined contents.
 *
 * ChangeLog:
 * v1.0, 2008-08-06, JeanV:
 *   - Initial release
 *
 * v1.1, 2008-11-04, JeanV:
 *   - fixed a bug in constructor that would emerge when optional 
 *     parameter 'initialTab' was passed
 * 
 * @copyright 2008 Phase 4
 * @version 1.1
 * @link $URL::                                                                $
 * @author $Author::                                                           $
 * @package Phase4
 * @subpackage Control 
 */

/*
 * Register the classes into subpackage Control
 */
Phase4.registerClasses('Control', new Array('Tab'));

/**
 * Options:
 * 
 * Name				| Type		| Description
 * ------------------------------------------------------------------------------------------------
 * behaviour		| String	| Defines whether the panes shall be shown on 'click' (default) or 'mouseover'
 * initialTab		| String	| The id of the tab that will be selected on initialization (defaults to first tab)
 * onChange			| Callback	| Fired when ever the tab is changed. Passes the currently visible pane as only argument
 * panes			| Array		| The (ids of the) panes in the correct order. If missing will use css-rule div#pane<N> within element
 * selectedClass	| String	| The css-class that will be assigned to the selected tab (defaults to empty string)
 * tabs				| Array		| The (ids of the) tabs in the correct order. If missing will use css-rule div#tab<N> within element
 */
Phase4.Control.Tab.prototype = {
	/**
	 * Constructor
	 * 
	 * @param {Element,String} element The element that will be used as container for the tab-control
	 * @param {Object} [options] The options as seen above
	 */
	initialize: function(element, options) {
		var tabcontrol = this;
		
		//init datamembers
		this.element = $(element);
		this.options = options || {};
		this.panes = new Array();
		this.tabs = new Array();
		
		//grab optional datamembers or default them
		this.behaviour = this.options.behaviour || 'click';
		this.initialTab = $(this.options.initialTab) || '';
		this.onChange = this.options.onChange || function(pane) { return; };
		this.selectedClass = this.options.selectedClass || '';
		
		//init tabs and panes
		this._initTabs();
		this._initPanes();
		
		//redefault initial tab if needed and have it displayed
		if (!this.initialTab) {
			this.initialTab = this.tabs[0];
		}
		this.selectTab(null, this.initialTab);
	},
	
	/**
	 * Destructor
	 */
	dispose: function() {},
	
	/*
	 * Private methods
	 */
	
	/**
	 * Grabs the panes
	 */
	_initPanes: function() {
		var panes = this.options.panes || this.element.select('div').findAll(function(s) { return (s.id && s.id.search(/^pane(\d+)$/)==0); });
		
		//iterate through panes adding them to our panes-datamember
		panes.each(function(s) {
			this.panes.push($(s));
		}, this);
	},
	
	/**
	 * Grabs the tabs and installs listeners
	 */
	_initTabs: function() {
		var tabs = this.options.tabs || this.element.select('div').findAll(function(s) {  return (s.id && s.id.search(/^tab(\d+)$/)==0); });
		
		//iterate through tabs adding them to our tabs-datamember and setting up listeners
		tabs.each(function(s, n) {
			var elem = $(s);
			
			elem.observe(this.behaviour, this.selectTab.bindAsEventListener(this, elem));	//might not work!!
			this.tabs.push(elem);
			
		}, this);
	},
	
	/*
	 * Public methods
	 */
	
	/**
	 * Will select specified tab and show its associated pane. 
	 * 
	 * @param {Event} evt The event that fired this function (can be null if used from external script)
	 * @param {Element} tab The tab for which a pane shall be shown
	 */
	selectTab: function(evt, tab) {
		var currentPane;
		
		//iterate through tabs, showing/hiding the associated panes
		this.tabs.each(function(s, n) {
			if (s.id==tab.id) {
				s.addClassName(this.selectedClass);
				this.panes[n].show();
				currentPane = this.panes[n];
			} else {
				s.removeClassName(this.selectedClass);
				this.panes[n].hide();
			}
		}, this);
		
		//finally, we call the onChange-callback
		this.onChange(currentPane);
	}
};