// Tabby is a creation of Jenna "Blueberry" Fox! Who releases it as public domain
// as of the 9th of July, 2007. More info and up to date downloads and demo's at:
// http://creativepony.com/journal/scripts/tabby/

// Basic version of Tabby which works off local data
var Tabby = new Class({
	options: {
		tabsElement: '.tabs', // css expression to find tabs
		contentElement: '.initial-data', // css expression to find place to insert data
		data: {} // the data itself for each tab as link id + html content pairs
	},
	
	tabBuffer: {},
	
	// creates a new Tabby :)
	initialize: function(container, options) {
		this.container = $(container);
		this.setOptions(options);
		this.tabsElement = this.container.getElement(this.options.tabsElement);
		this.contentElement = this.container.getElement(this.options.contentElement);
		
		// set up tabs to actually work
		this.tabsElement.getChildren().each(function (child) {
			child.addEvent('click', function(event) {
				this.display(child.id);
			}.bindWithEvent(this));
			
			// put a hand cursor up so people know its clickable
			child.setStyle('cursor', 'pointer');
			
			// stop link from firing if it was where the click happened
			child.getElement('a').addEvent('click', function(event) {
				event.preventDefault();
			}.bindWithEvent());
		}.bind(this));
	},
	
	// display specified tab by id
	display: function(tabID) {
		this.tabBuffer[this.getSelected().id] = this.contentElement;
		var previousButton = this.getSelected();
		var previousBody = this.contentElement;
		
		if ($defined(this.tabBuffer[tabID]) == false) {
			if ($type(this.options.data[tabID]) == 'string') {
				this.tabBuffer[tabID] = this.contentElement.clone(false);
				this.tabBuffer[tabID].setHTML(this.options.data[tabID]);
			} else {
				this.tabBuffer[tabID] = this.options.data[tabID];
			}
		}
		
		this.tabBuffer[tabID].setStyle('visibility', 'hidden');
		this.contentElement = this.contentElement.replaceWith(this.tabBuffer[tabID]);
		
		// change which tab is selected in the dom
		this.tabsElement.getElement('.selected').removeClass('selected');
		$(tabID).addClass('selected');
		
		// fire off onChanged event
		this.fireEvent('onChanged', [this, this.getSelected(), this.contentElement, previousButton, previousBody]);
		this.contentElement.setStyle('visibility', 'visible');
	},
	
	// returns currently selected tab id
	getSelected: function() {
		return this.tabsElement.getElement('.selected');
	}
});

Tabby.implement(new Events, new Options);


// Remote version of Tabby which loads over Ajax
Tabby.Remote = Tabby.extend({
	initialize: function(container, options) {
		this.options.urls = {};
		this.parent.apply(this, arguments);
	},
	
	display: function(tabID) {
		if (tabID == this.getSelected().id) return;
		
		if ($defined(this.options.data[tabID]) || $defined(this.tabBuffer[tabID])) {
			this.fireEvent('onLoading');
			this.parent(tabID);
			this.fireEvent('onLoaded');
		} else {
			// if already trying to load something, stop it
			if ($defined(this.ajax) && this.ajax.running) { this.ajax.cancel(); }
			
			// fire event for animations and such
			this.fireEvent('onLoading');
			
			// load tab remotely
			this.ajax = new Ajax(this.options.urls[tabID], {
				method: 'get',
				onComplete: function () {
					this.options.data[tabID] = this.ajax.response.text;
					this.display(tabID);
					this.fireEvent('onLoaded');
				}.bind(this)
			}).request();
		}
	},
	
	clearCache: function() {
		this.options.data = {};
		this.tabBuffers = {};
	}
});

/* usage for within actual page:
window.addEvent('load', function() {
	// here's how you’d do this with ajax calls and tabby, note the use of Tabby.Remote
	var demo = new Tabby.Remote('demo', {
		urls: {
			'poniestab': 'ponies.txt',
			'ministab': 'minis.txt'
		}
	});
	
	// same thing without ajax and tabs content in the script
	// these strings could be dom elements instead:
	var demo = new Tabby('demo', {
		data: {
			'poniestab': 'Small horse, officially any horse under 14.2 hands (58 in./145 cm) high. Most ponies are of Celtic origin. They are noted for their extreme hardiness and gentle natures. Some ponies are only 26 in. (65 cm) high. See Shetland pony; Welsh pony.',
			'ministab': 'Found all over the world and come in various colors and coat patterns. The designation of miniature horse is determined by the height of the animal, which, depending on the particular registry involved, is usually less than 34-38 inches (82-91 cm) as measured at the withers.'
		}
	})
	
	// even elements already somewhere else in the page. This is the recomended
	// way to use Tabby. We’ve used css in this demo to hide the elements inside #hidden-tabby-data
	var demo = new Tabby('demo', {
		data: {
			'poniestab': $('ponies-tab-content'),
			'ministab': $('minis-tab-content')
		}
	})
})
*/
