var Dashtabs = Class.create({
	beforeTab:  Prototype.emptyFunction,			// action to occur prior to switching from one tab to another
	afterTab:   Prototype.emptyFunction,			// action to occur after switching from one tab to another
	paneClass:  "pane",								// the class for the pane element
	tabClass:   "tab",								// the class for the tab elements
	tabOnClass: "on",								// the class added to tabs when clicked

	tabContainer: null,								// the container element for the tabs
	tabPane: null,									// the container element for the pane's content
	tab: null,										// a reference to the tab that was clicked
	
	// this class forces very little structure on the visitor.  as long as there is a tab container with children 
	// containing the class this.tabClass.  there must also be a container element with the class this.paneClass
	// that is either a sibling to the tab container or it is an uncle of the tab container.  beyond that, the
	// rest is up to the user.  my suggestion is this:
	
	/************** TABBED PANE STRUCTURE EXEMPLAR:
	
		<ul id="tab_container">
			<li class="tab"><a href="...">A</a></li>
			<li class="tab"><a href="...">B</a></li>
			.
			.
			.
			<li class="tab"><a href="...">Z</a></li>
		</ul>
		<div class="pane"></div>
		
	*/	
	
	initialize: function(element, opts) {
		if(opts) for(option in opts) this[option] = opts[option];		// apply user options to the object
		this.tabContainer = $(element);									// store a local referenc to the tabContainer

		// the tabPane must be a sibling of the container or an uncle thereof.  the first line below checks for the
		// sibling option, the second for the uncle-relationship.
		
		this.tabPane = this.tabContainer.next("." + this.paneClass);
		if(!this.tabPane) this.tabPane = this.tabContainer.up().next("." + this.paneClass);
		if(!this.tabPane) throw "Unable to discover pane element from provided tab container.";
		
		// finally, when a tab is clicked, we'll call the showTab method of this object.  note that this function
		// is bound to the object itself.
		
		this.tabContainer.observe("click", this.showTab.bind(this));
	},
	
	showTab: function(event) {
		event.stop();							// avoid executing any "normal" events when a tab is clicked
		this.tab = $(event.target);				// this is the specific tab that was clicked
		
		// for the purpose of allowing progressive enhancement, if the tab element is an <a> element, we'll use
		// it's parent with the tabClass instead of itself for the process below.  if we can't find such an element
		// then we'll throw an exception and return.
		
		if(this.tab.tagName == "A") this.tab = this.tab.up("." + this.tabClass);
		if(!this.tab) throw "Can't find parent of anchor having the class '" + this.tabClass + "'";
		
		if(this.tab.hasClassName(this.tabClass) && !this.tab.hasClassName(this.tabOnClass)) {
			// if the element that was clicked has the appropriate tabClass and it's not the tab that's already
			// on, then we'll want to handle a tab click.  first we call the beforeTab method of this object. this
			// method can return boolean false if there's a reason to avoid changing the tabbed pane's state.  then,
			// we'll add the tabOnClass to this tab and remove it from its siblings.  finally, we'll call the afterTab
			// method.  note that both action methods are bound to this object.  that means the tab with the tabOnClass
			// will be different in the before action from the one in the after action.
			
			if(typeof(this.beforeTab)=="function" && this.beforeTab.call(this)===false) return;
			this.tab.addClassName(this.tabOnClass).siblings().invoke("removeClassName", this.tabOnClass);
			if(typeof(this.afterTab)=="function") this.afterTab.call(this);
		}
	}
});

document.fire("dashtabs:loaded");