/*	Script: Waiter.js
		Adds a semi-transparent overlay over a dom element with a spinnin ajax icon.

		Author:
		Aaron Newton - aaron [dot] newton [at] cnet [dot] com

		Class: Waiter
		Adds a semi-transparent overlay over a dom element with a spinnin ajax icon.

		Arguments:
		target - (dom element or id) the dom element to overlay; defaults to document.body
		options - (object) a key/value set of options

		Options:
		baseHref - (string) url prefix for the img src (see below); defaults to
				'http://www.cnet.com/html/rb/assets/global/waiter/'
		img - (object) options for the image (see below)
		imgPosition - (object) options passed to <Element.setPosition> for the image; relativeTo is set to the target above automatically.
		layer - (object) options for the overlay layer (see below)
		fxOptions - (object) options passed to the effects used to transition the overlay and the image opacity

		img options:
		Properties passed to the element instantiation.
		(start code)
		//default values
		img: {
			src: 'waiter.gif',
			id: 'waitingImg',
			styles: {
				position: 'absolute',
				width: 24,
				height: 24,
				display: 'none',
				opacity: 0,
				zIndex: 999
			}
		}
		(end)

		layer options:
		Properties passed to the element instantiation.
		(start code)
		//default values
		layer:{
			id: 'waitingDiv',
			background: '#fff',
			opacity: 0.8
		}
		(end)


*/
var Waiter = new Class({
	options: {
		baseHref: '',
		img: {
			src: 'waiter.gif',
			id: 'waitingImg',
			styles: {
				position: 'absolute',
				width: 24,
				height: 24,
				display: 'none',
				opacity: 0,
				zIndex: 999
			}
		},
		imgPosition: {},
		layer:{
			id: 'waitingDiv',
			background: '#fff',
			opacity: 0.9
		},
		fxOptions: {}
	},
	initialize: function(target, options){
		this.target = $(target||document.body);
		this.setOptions(options);
		this.waiterImg = $(this.options.img.id) || new Element('img', $merge(this.options.img, {
			src: this.options.baseHref + this.options.img.src
		})).injectInside(document.body);
		this.waiterDiv = $(this.options.layer.id) || new Element('div', {
			id: this.options.layer.id,
			styles: {
				width: 0,
				height: 0,
				position: 'absolute',
				zIndex: 998,
				display: 'none',
				opacity: 0,
				backgroundColor: this.options.layer.background
			}
		}).injectInside(document.body);
		this.waiterFx = this.waiterFx || new Fx.Elements($$(this.waiterImg, this.waiterDiv), this.options.fxOptions);
	},
/*	Property: toggle
		Toggles the waiter over the specified element. If the waiter is currently showing over the specified element, it will hide. Otherwise it will
	*/
	toggle: function(element, show) {
		if (this.inTransit) {
			this.chain(this.toggle.bind(this, [element, show]));
			return this;
		}
		//the element or the default
		element = $(element) || $(this.active) || $(this.target);
		if (!$(element)) return this;
		if (this.active && element != this.active) return this.stop().chain(this.start.bind(this, element));
		//if it's not active or show is explicit
		//or show is not explicitly set to false
		//start the effect
		if((!this.active || show) && show !== false) this.start(element);
		//else if it's active and show isn't explicitly set to true
		//stop the effect
		else if(this.active && !show) this.stop();
		return this;
	},
	start: function(element){
		if (this.inTransit) {
			this.chain(this.start.bind(this, element));
			return this;
		}
		this.inTransit = true;
		element = $(element) || $(this.target);
		var start = function() {
			dbug.log(element);
			var dim = element.getComputedSize();
			dbug.log(element, dim);
			this.active = element;
			this.waiterImg.setPosition($merge(this.options.imgPosition, {
				relativeTo: element
			})).show();
			this.waiterDiv.setStyles({
				width: dim.totalWidth,
				height: dim.totalHeight,
				display: 'block'
			}).setPosition({
				relativeTo: element,
				position: 'upperLeft'
			});
			this.waiterFx.start({
				0: { opacity:[1] },
				1: { opacity:[this.options.layer.opacity]}
			}).chain(function(){
				this.inTransit = false;
				this.fireEvent('onShow', element);
				this.callChain();
			}.bind(this));
		}.bind(this);

		if (this.active && this.active != element) this.stop(start);
		else start();

		return this;
	},
	stop: function(callback){
		if (this.inTransit) {
			this.chain(this.stop.bind(this, callback));
			return this;
		}
		if (!this.active) return this;
		this.inTransit = true;
		//fade the waiter out
		this.waiterFx.start({
			0: { opacity:[0]},
			1: { opacity:[0]}
		}).chain(function(){
			this.inTransit = false;
			this.active = null;
			this.waiterDiv.hide();
			this.waiterImg.hide();
			this.fireEvent('onHide', this.active);
			this.callChain();
			if ($type(callback) == "function") callback.attempt();
		}.bind(this));
		return this;
	}
});
Waiter.implement(new Options, new Events, new Chain);

/*	Class: Ajax
		Extends functionality from <Waiter> into <Ajax>.

		Additional Options:
		useWaiter - (boolean) if true will automatically apply a <Waiter> to the update target; defaults to false. Note: if you do not specify a value for update option this is ignored.
		waiterOptions - (object) options value passed on to <Waiter> class.
	*/
if (typeof Ajax != "undefined") {
	var Ajax = Ajax.extend({
		options: {
			useWaiter: false,
			waiterOptions: {}
		},
		initialize: function(url, options){
			this.parent(url, options);
			if (this.options.useWaiter && this.options.update) {
				this.waiter = new Waiter(this.options.update, this.options.waiterOptions);
				this.addEvent('onComplete', this.waiter.stop.bind(this.waiter));
				this.addEvent('onFailure', this.waiter.stop.bind(this.waiter));
			}
		},
		request: function(data) {
			if (this.waiter) this.waiter.start().chain(this.parent.bind(this, data));
			else this.parent(data);
			return this;
		}
	});
}


/* do not edit below this line */
/* Section: Change Log

$Source: /cvs/main/flatfile/html/rb/js/global/cnet.global.framework/common/js.widgets/Waiter.js,v $
$Log: Waiter.js,v $
Revision 1.5  2008/01/12 01:48:53  newtona
fixing some of the date math methods
added some error checking to Waiter and fixed a bug with the ajax integration

Revision 1.4  2008/01/07 22:25:44  newtona
Waiter.js: syntax error fixed

Revision 1.3  2008/01/07 22:23:29  newtona
tweaking Waiter syntax

Revision 1.2  2008/01/07 22:12:18  newtona
Waiter.js: integrated with Ajax

Revision 1.1  2008/01/04 00:49:06  newtona
date.picker: rewrote class to make use of new native date.js
date.picker.plus: allows for time and date range options
stickyWin.default.layout now has a handle option
stickyWinFx now uses the handle reference in stickyWin.default.layout by default
fixed some Fx.Sort array link issues
added datepicker assets to setAssetHref
Waiter.js: new class
OverText.js: new class
Native: date and date.extras - extends the native Date object greatly
updated make mootools 1.11 redball.common.full.js.bat to include new files
fixed a few syntax issues (semi colons) with previous commits


*/

