//<![CDATA[

 

/**

 * @class MavDialog

 * @abstract MooTools class for customized dialog window boxes

 * @version 0.1.1

 *

 * @license MIT-style license

 * @author Dustin C Hansen <dustin [at] maveno.us>

 * @copyright Copyright (c) 2008 [Dustin Hansen](http://maveno.us, http://fuzecore.com).

 */



var MavDialog = new Class({

	Implements: [Options, Events],

	Binds: ['clickClose', 'show'],

	options: {

		'autoShow': true,

		'buttons': null,

		'cancel': null,

		'cancelAutoClose': true,

		'cancelClass': 'cancel-button',

		'cancelImageClass': 'dialog-image-button',

		'cancelText': 'Cancel',

		'cancelDestroy': true,

		'callback': null,

		'center': true,

		'clickCloses': false,

		'defaultButtons': true,

		'dialogClass': 'mav-dialog',

		'draggable': false,

		'fxOptions': {},

		'footer': null,

		'footerClass': 'mav-dialog-footer',

		'force': false,

		'height': 'auto',

		'loadingMessage': 'loading...',

		'message': null,

		'messageAreaClass': 'mav-dialog-message',

		'messageBoxClass': 'mid-float-box',

		'noTitleClass': 'mav-no-title',

		'noFooterClass': 'mav-no-footer',

		'ok': null,

		'okAutoClose': true,

		'okClass': 'ok-button',

		'okImageClass': 'dialog-image-button',

		'okText': 'OK',

		'okDestroy': true,

		'parent': null,

		'requestQuery': '',

		'shadeClass': 'mavdialog-shade',

		'styles': {},

		'title': null,

		'titleBarClass': 'mav-dialog-title',

		'titleClose': true,

		'titleCloseClass': 'mav-icon-button md-closer',

		'titleCloseTitle': 'Close Dialog',

		'titleTextClass': 'md-title-text',

		'url': null,

		'useFx': true,

		'width': '400'

/*		,'onComplete': $empty(),

		'onClose': $empty(),

		'onHide': $empty(),

		'onRequest': $empty(),

		'onShow': $empty()*/

	},



	/*'delayedShow': false,

	'dialog': null,

	'drag': null,

	'footer': null,

	'fx': null,

	'grabbed': null,

	'grabbedHide': null,

	'message': null,

	'parent': null,

	'request': null,

	'tabIdx': 0,

	'titlebar': null,*/



	initialize: function(_opts) {

		this.setOptions(_opts);

		var dialogNum = Math.ceil(Math.random() * 10000);

		this.dialogId = 'mavd' + dialogNum + '_dialog';



		if ($(this.dialogId + '_dialog')) { return null; }



		this.request = new Request({

			'url': '',

			'onSuccess': this.urlRequest.bind(this),

			'onFailure': this.errorMessage.bind(this)

		});



		this.tabidx = dialogNum;

		this.parent = $((this.options.parent || document.body));



		this.generate();

	},

	

	destruct: function() {



	},

	

	generate: function() {

		var dialog_styles = $merge({'display':'none', 'width':this.options.width.toInt()+'px'}, this.options.styles);



		this.dialog = new Element('div', {

			'id': this.dialogId, 

			'class': this.options.dialogClass,

			'opacity': (this.options.useFx ? 0 : 1),

			'styles': dialog_styles

		}).inject(this.parent);



		this.fx = this.options.useFx ? new Fx.Tween(this.dialog, $merge({

			'duration': '300'

		}, this.options.fxOptions)) : null;



		// dialog box sections and borders

		var db_message = new Element('div', {

			'class': this.options.messageBoxClass

		}).inject(this.dialog);

		

		// dialog box title

		if (this.options.title !== false) {

			this.titlebar = new Element('div', {

				'id': this.dialogId + '_title',

				'class': this.options.titleBarClass

			}).inject(db_message);



			new Element('span', {'class':this.options.titleTextClass, 'html': this.options.title}).inject(this.titlebar);



			if (this.options.titleClose != false) {

				new Element('span', {

					'id':this.dialogId + '_closer',

					'class': this.options.titleCloseClass,

					'title': this.options.titleCloseTitle

				}).inject(this.titlebar).addEvent('click', this.close.bind(this));

			}

		}





		// dialog box message

		this.message = new Element('div', {

			'id': this.dialogId + '_message', 

			'class': this.options.messageAreaClass + (this.options.title === false ? ' ' + this.options.noTitleClass : '') + (this.options.footer === false ? ' ' + this.options.noFooterClass : '')

		}).inject(db_message).setStyle('height', (this.options.height=='auto'?'auto':this.options.height.toInt()+'px'));



		if ($defined(this.options.url)) {

			this.request.options.url = this.options.url;

			this.request.send((this.options.requestQuery || ''));

			this.setMessage(this.options.loadingMessage);



			if (this.options.autoShow) { this.delayedShow = true; }

		} else if ($defined(this.options.message)){ this.setMessage(this.options.message); }





		// dialog footer

		if (this.options.footer !== false) {

			this.footer = new Element('div', {

				'id': this.dialogId + '_footer',

				'class': this.options.footerClass

			}).inject(db_message);



			new Element('div', {'class': 'foot-wrap'}).inject(this.footer);

			new Element('div', {'class': 'clear'}).inject(this.footer);



			if ($type(this.options.buttons) == 'array') {

				for(var i=0; i<this.options.buttons.length; i++) {

					(this.injectButton(this.options.buttons[i])).inject(this.footer.firstChild, 'top');

				}

			}



			// TODO: this could be much cleaner, yes?

			// default ok button

			if (this.options.ok !== false && this.options.defaultButtons !== false) {

				(this.injectButton({

					'text': this.options.okText,

					'class': this.options.okClass,

					'imageClass': this.options.okImageClass,

					'action': ($type(this.options.ok) == 'function' ? this.options.ok : null),

					'autoClose': this.options.okAutoClose

				})).inject(this.footer.firstChild, 'top');

			}

			// default cancel button

			if (this.options.cancel !== false && this.options.defaultButtons !== false) {

				(this.injectButton({

					'text': this.options.cancelText,

					'class': this.options.cancelClass,

					'imageClass': this.options.cancelImageClass,

					'action': ($type(this.options.cancel) == 'function' ? this.options.cancel : null),

					'autoClose': this.options.cancelAutoClose

				})).inject(this.footer.firstChild, 'top');

			}

		}



		// set dialog to draggable

		if (this.options.draggable && this.titlebar) {

			this.drag = new Drag.Move(this.dialog, {handle: this.titlebar});

		}



		if (this.options.clickCloses || ((this.options.title == false || this.options.titleClose == false) && (this.options.footer == false))) {

			$(document.body).addEvent('mousedown', this.clickClose);

		}



		// set the tab index for the dialog. Needs to be set so buttons tab correctly.

		this.setTabindex();

		this.fireEvent('complete');



		// execute onComplete function, if present.

		if (this.options.autoShow && !this.request.running) { this.show(); }

	},



	// TODO: is this the best way to handle this? probably not.

	buttonOptions: {

		'text': '',

		'position': 'right',

		'imageClass': 'image-button',

		'class': '',

		'action': $empty(),

		'autoClose': true,

		'tabindex': null

	},



	injectButton: function(_opts) {

		var opts = $merge(this.buttonOptions, _opts);

		var bid = this.dialogId + '_btn_' + (opts.text || Math.ceil(Math.random() * 10000)).replace(/\W/g, '').toLowerCase();

		var button = new Element('div', {

			'class': 'go' + opts['position'] + ' ' + opts['imageClass'] + ' ' + opts['class']

		});



		var b_link = new Element('a', { 'id': bid, 'href': 'javascript:void(0)', 'html': opts.text }).inject(button);

		if ($defined(opts.tabindex)) { b_link.set('tabindex', opts.tabindex); }

		if ($type(opts.action) == 'function') { button.addEvent('click', opts.action.bind(this)); }

		if (opts.autoClose) { button.addEvent('click', this.close.bind(this)); }



		return button;

	},



	setMessage: function(_message) {

		var message = ($type(_message) == 'function' ? _message() : _message);



		if ($type(message) == 'element') {

			this.grabbed = message.getParent();

			if (this.grabbed != null) {

				this.grabbedHide = (message.hasClass('none') ? {'class':'none'} : (message.getStyle('display') == 'none' ? {'style':'display:none'} : {}));

				if ($defined(this.grabbedHide['class'])) { message.removeClass('none'); }

				else if ($defined(this.grabbedHide['style'])) { message.setStyle('display', ''); }

				this.message.grab(message);

			} else {

				message.inject(this.message);

			}

		} else {

			this.message.set('html', message);

		}

		

		if (this.delayedShow) { 

			this.delayedShow = false;

			this.show();

		}

	},

	

	// TODO: To be used by improper HTMLElement or URL request...

	errorMessage: function(_error) {

		

	},



	// TODO: verify that all elements that take tabindex have been included.

	setTabindex: function() {

		var tabbed = ['a','select','input','textarea','button','label'];

		this.tabidx = this.tabidx.toInt();



		$(this.dialogId + '_message').getElements('*').each(function(_elem, _idx) {

			if (tabbed.contains(_elem.get('tag')) && _elem.get('tabindex') != -1) {

				_elem.set('tabindex', (++this.tabidx));

			}

		}, this);

		

		if ($(this.dialogId + '_footer')) {

			var footer_links = $(this.dialogId + '_footer').getElements('*');

			(footer_links.reverse()).each(function(_elem, _idx) {

				if (tabbed.contains(_elem.get('tag')) && _elem.get('tabindex') != -1) {

					_elem.set('tabindex', (++this.tabidx));

				}

			}, this);

		}

	},



	urlRequest: function(_response) {

		this.setMessage(_response);

		this.fireEvent('request');

	},



	toggleShade: function(_show) {

		if (!$('mavdialog_shade')) { new Element('div', {'id':'mavdialog_shade', 'class':this.options.shadeClass, 'opacity':'0.5'}).inject(document.body); }

		$('mavdialog_shade').setStyle('display', (_show === true ? 'block' : 'none'));

	},



	show: function() {

		if (this.options.force) {

			var shade_requests = ($(document.body).retrieve('shade_requets') || 0).toInt();

			$(document.body).store('shade_requests', (++shade_requests));

			this.toggleShade(this.options.force);

		}



		this.dialog.setStyle('display', '');

		if (this.options.center !== false) { this.screen_center(); }

		this.fireEvent('show');



		if (this.options.useFx) {

			this.fx.start('opacity', 0, 1);

		}

	},



	hide: function() {

		this.dialog.setStyle('display', 'none');

		this.fireEvent('hide');

	},



	clickClose: function(e) {

		var is_dialog = false;

		$(e.target).getParents('div').each(function(_elem) {

			if (!is_dialog && $(_elem).get('id') == this.dialogId) {

				is_dialog = true;

			}

		}, this);



		if (!is_dialog) { this.close(); }

	},



	close: function() {

		if (this.options.useFx) {

			this.fx.start('opacity', 1, 0).chain(this.finishClose.bind(this));

		} else { this.finishClose(); }

	},



	finishClose: function() {

		if ($(this.dialog)) {

			if (this.options.force) {

				var shade_requests = ($(document.body).retrieve('shade_requests')).toInt();

				$(document.body).store('shade_requests', (--shade_requests));

			}



			if ($defined(this.grabbed)) {

				if ($defined(this.grabbedHide['class'])) { this.message.firstChild.addClass('none'); }

				else if ($defined(this.grabbedHide['style'])) { this.message.firstChild.setStyle('display', 'none'); }

				this.grabbed.grab(this.message.firstChild);

			}



			this.dialog.dispose();

			if (this.options.force && shade_requests == 0) { this.toggleShade(); }



			this.fireEvent('close');

			

			this.destruct();

			$(document.body).removeEvent('mousedown', this.clickClose);

		}		

	},



	screen_center: function() {

		this.dialog.position('center', (this.parent || null));

	}

});





MavDialog.Confirm = new Class({

	Extends: MavDialog,



	initialize: function(_opts) {

		var opts = $merge(_opts, {

			'cancel':false,

			'titleClose':false,

			'message': this.buildMessage.bind(this, _opts.message),

			'ok': this.closeAction.bind(this, true),

			'cancel': this.closeAction.bind(this, false)

		});

		this.parent(opts);

	},

	

	buildMessage: function(_msg) {

		var message_box = new Element('div');

		new Element('div', {'class':'mav-icon-button confirm-icon goleft'}).inject(message_box);

		new Element('div', {'class':'mav-alert-msg goleft', 'html': _msg}).inject(message_box);

		new Element('div', {'class':'clear'}).inject(message_box);

		

		return message_box;

	},

	

	closeAction: function(_confirmed) {

		this.close();



		if (this.options.useFx && $defined(this.options.callback)) {

			// bah.

			this.fx.start('opacity', 1, 0).chain(this.finishClose.bind(this)).chain(this.options.callback(_confirmed));

		} else {

			this.finishClose();

			if ($defined(this.options.callback) && $type(this.options.callback) == 'function') {

				this.options.callback(_confirmed);

			}

		}

	}

});



MavDialog.Prompt = new Class({

	Extends: MavDialog,



	initialize: function(_opts) {

		var opts = $merge(_opts, {

			'cancel':false,

			'titleClose':false,

			'message': this.buildMessage.bind(this, _opts.message),

			'ok': this.closeAction.bind(this),

			'cancel': this.closeAction.bind(this, false),

			'onComplete': function() {

				var text_elem = this.dialogId + '_prompted';

				window.setTimeout(function() { $(text_elem).focus(); }, 310);

			}

		});

		this.parent(opts);

	},



	buildMessage: function(_msg) {

		var message_box = new Element('div');

		new Element('div', {'class':'mav-icon-button prompt-icon goleft'}).inject(message_box);

		var msg_display = new Element('div', {'class':'mav-alert-msg goleft'}).inject(message_box);



		new Element('div', {'html': _msg}).inject(msg_display);

		new Element('input', {

			'id': this.dialogId + '_prompted',

			'type':'text', 

			'class': 'mav-prompt-input'

		}).inject(msg_display);



		new Element('div', {'class':'clear'}).inject(message_box);



		return message_box;

	},

	

	closeAction: function(_canceled) {

		this.close();

		

		var prompt_value = (_canceled === false ? null : $(this.dialogId + '_prompted').get('value'));

		if (this.options.useFx && $defined(this.options.callback)) {

			// bah.

			this.fx.start('opacity', 1, 0).chain(this.finishClose.bind(this)).chain(this.options.callback(prompt_value));

		} else {

			this.finishClose();

			if ($defined(this.options.callback) && $type(this.options.callback) == 'function') {

				this.options.callback(prompt_value);

			}

		}

	}

});



MavDialog.Alert = new Class({

	Extends: MavDialog,



	initialize: function(_opts) {

		var opts = $merge(_opts, {

			'cancel':false,

			'titleClose':false,

			'message': this.buildMessage.bind(this, _opts.message)

		});

		this.parent(opts);

	},



	buildMessage: function(_msg) {

		var message_box = new Element('div');

		new Element('div', {'class':'mav-icon-button alert-icon goleft'}).inject(message_box);

		new Element('div', {'class':'mav-alert-msg goleft', 'html': _msg}).inject(message_box);

		new Element('div', {'class':'clear'}).inject(message_box);

		

		return message_box;

	}

});





MavDialog.MediaBox = new Class({

	Extends: MavDialog,	

	mOptions: {

		'autoShow': true,

		'footerClass': 'media-footer',

		'defaultButtons': false,

		'title': false,

		'force': true,

		'messageBoxClass':'',

		'dialogClass': 'mav-dialog-media',

		'noTitleClass':'',

		'noFooterClass':'',

		'titleClose':false,

		'clickCloses': true,

		'media': '',

		'buttons': [{

			'text': 'Close',

			'class': 'media-close-button close-icon'

		}]

	},

	mediaFormats: [/\.jpe?g$/i, /\.gif$/i, /\.png$/i],



	initialize: function(_opts) {

		this.mOptions = $merge(this.mOptions, _opts);

		this.mOptions['message'] = new Element('img').inject(document.body);



		if ($defined(this.mOptions.media)) {

			this.mOptions['message'].set('src', this.mOptions.media).addEvent('load', this.finishInit.bind(this));

		}

	},



	finishInit: function() {

		var iSize = this.mOptions['message'].getSize();

		this.mOptions['width'] = (iSize.x + 26) + 'px';

		this.mOptions['height'] = (iSize.y) + 'px';

		this.mOptions['message'].addClass('none');



		this.setOptions(this.mOptions);

		var dialogNum = Math.ceil(Math.random() * 10000);

		this.dialogId = 'mavd' + dialogNum + '_dialog';



		this.request = {'running':false};

		if ($(this.dialogId + '_dialog')) { return null; }



		this.tabidx = dialogNum;

		this.parent = $((this.options.parent || document.body));



		this.generate();

	}

});

// shortcut method

var MavMediaBox = function(_media) { new MavDialog.MediaBox({'media': _media}); };





//]]>