/*
	$Id: dialog.js 68 2009-05-12 10:06:35Z root $ [load:2]
	$HeadURL: file:///usr/home/svn/cms/scripts/dialog.js $
	(C) Copyright 2006-2009 Fellownet / Third Floor Design.
	All rights reserved.
*/

Dialog = Class.create();

Dialog.zindex = 100;
Dialog.dialogs = new Array();

Dialog.addMethods( {
	initialize: function(options_) {
		this.options = $H( {
			width:600,
			padding:0,
			method:'get',
			modal:false,
			effect:false,
			duration:0.3,
			offset:0,
			close:false,

			onOpen:function() {},
			onShow:function() {},
			onHide:function() {},
			onClose:function() {},
			onClick:function() {},
			onDrag:function() {}
		} ).update(options_);

		this.visible = false;
		this.observers = new Array();

		if (typeof(this.options.get('source')) == 'string') {
			new Ajax.Request(this.options.get('source'), {
				method:this.options.get('method'),
				parameters:this.options.get('parameters'),
				onComplete:function(req_) {
					if (req_.headerJSON) this.options.update(req_.headerJSON);
					this.options.set('content', req_.responseText);
					this.continue_initialize();
				}.bind(this)
			} );
		} else this.continue_initialize();
	},
	
	continue_initialize: function() {
		this.div_container = new Element('div', { 'class':'dialog' } ).setStyle( { 'top':'-9999px', 'left':'-9999px', 'width':this.options.get('width') + 'px' } );
		this.div_container.dialog = this;
		document.getElementsByTagName('body').item(0).appendChild(this.div_container);
		this.div_container.appendChild(this.div_outer = new Element('div', { 'class':'outer' } ));
		if (typeof(this.options.get('title')) != 'undefined') {
			this.div_outer.appendChild(this.div_header = new Element('div', { 'class':'header' } ));
			if (this.options.get('close')) {
				this.div_header.appendChild(this.img_close = new Element('img', { 'src':'images/dialog/close.gif' } ));
				this.img_close.observe('click', function() {
					if (typeof(this.options.get('onClick')) == 'function') this.options.get('onClick')(this.options.get('close'), this);
				}.bind(this));
			}
			this.div_header.appendChild(this.h1_header = new Element('h1').update(this.options.get('title')));
			if (typeof(this.options.get('subtitle')) == 'string' && this.options.get('subtitle').length > 0) {
				this.h1_header.insert( { bottom:this.span_header = new Element('span', { 'class':'subtitle' } ).update(this.options.get('subtitle')) } );
			}
		}
		this.div_outer.appendChild(this.div_content = new Element('div', { 'class':'content' } ));
		if (this.options.get('padding') > 0) this.div_content.setStyle( { 'padding':this.options.get('padding') + 'px' } );

		this.buttons = new Array();
		if (typeof(this.options.get('buttons')) != 'undefined') {
			this.div_outer.appendChild(this.div_buttons = new Element('div', { 'class':'buttons' } ));
			var buttondefs = this.options.get('buttons').split(/\s*[,|]\s*/i);
			buttondefs.unshift(buttondefs.pop());
			var spacer = false;
			buttondefs.each( function(buttondef_) {
				if (buttondef_ == '-') {
					spacer = true;
					return;
				}

				var button = new Element('button');
				if (buttondef_.indexOf('#') > -1) {
					buttondef_ = buttondef_.split('#');
					button.action = buttondef_[0];
					button.update(buttondef_[1]);
				} else button.update(button.action = buttondef_);

				if (spacer) {
					spacer = false;
					button.style.marginLeft = '10px';
				}

				this.div_buttons.appendChild(button);

				if (this.buttons.length == 0) button.addClassName('right');
				this.buttons.push(button);
			}.bind(this));

			if (typeof(this.options.get('onClick')) == 'function') this.div_buttons.observe('click', function(event_) {
				var element = event_.element();
				if (
					element.tagName.toLowerCase() == 'button' &&
					element.action
				) this.options.get('onClick')(element.action, this);
			}.bindAsEventListener(this));
		}
		if (this.buttons.length > 0) this.buttons.push(this.buttons.shift());

		this.div_container.insert( { bottom:this.div_disable = new Element('div', { 'class':'disabled' } ).hide() } );
	
		if (this.h1_header && typeof(Draggable) != 'undefined') {
			this.h1_header.addClassName('draggable');
			new Draggable(this.div_container, {
				handle:this.h1_header,
				starteffect:false,
				endeffect:false,
				zindex:9999,
				onEnd:function() {
					if (typeof(this.options.get('onDrag')) == 'function') this.options.get('onDrag')(this);
				}.bind(this)
			} );
		}

		if (typeof(this.options.get('content')) == 'string') this.div_content.update(this.options.get('content'));
		if (typeof(this.options.get('onOpen')) == 'function') this.options.get('onOpen')(this);

		if (window.console) window.console.log("[Dialog] with id " + this.div_container.identify() + " created");
	},
	show: function() {
		if (
			this.visible ||
			typeof(document.body) == 'undefined' ||
			typeof($(document.body).getWidth) != 'function'
		) return;

		if (typeof(Dialog.div_modal) == 'undefined') {
			Dialog.div_modal = new Element('div', { 'class':'modal' } ).hide();
			$(document.body).insert( { bottom:Dialog.div_modal } );
			Dialog.div_modal.observe('click', function() {
				Dialog.onTop(true);
			} );
		}

		this.visible = true;
		Dialog.dialogs.push(this);

		var offset = document.viewport.getScrollOffsets();
		var size = document.viewport.getDimensions();
		var top = Math.max(0, Math.ceil(offset.top + (size.height / 2) - (this.div_container.getHeight() / 2))) + this.options.get('offset');
		var left = Math.max(0, Math.ceil(offset.left + (size.width / 2) - (this.div_container.getWidth() / 2))) + this.options.get('offset');

		if (this.options.get('duration') == 0) this.options.set('effect', false);

		if (this.options.get('modal')) {
			var size = document.viewport.getDimensions();
			Dialog.div_modal.setStyle( {
				width:$(document.body).getWidth() + 'px',
				height:Math.max($(document.body).getHeight(), size.height) + 'px',
				zIndex:++Dialog.zindex
			} ).setOpacity(0.6).show();
		}

		if (this.options.get('effect')) this.div_container.hide();
		this.div_container.setStyle( {
			position:'absolute',
			left:left + 'px',
			top:top + 'px',
			zIndex:++Dialog.zindex
		} );
		if (this.options.get('effect')) {
			this.div_container.blindDown( { duration:this.options.get('duration'), afterFinish: function() {
				if (typeof(this.options.get('onShow')) == 'function') this.options.get('onShow')(this);
			}.bind(this) } );
		} else {
			if (typeof(this.options.get('onShow')) == 'function') this.options.get('onShow')(this);
		}
		return this;
	},
	center: function() {
		var offset = document.viewport.getScrollOffsets();
		var size = document.viewport.getDimensions();
		var top = Math.max(0, Math.ceil(offset.top + (size.height / 2) - (this.div_container.getHeight() / 2))) + this.options.get('offset');
		var left = Math.max(0, Math.ceil(offset.left + (size.width / 2) - (this.div_container.getWidth() / 2))) + this.options.get('offset');
		this.div_container.setStyle( {
			left:left + 'px',
			top:top + 'px'
		} );
	},
	hide: function() {
		if (! this.visible) return;
		this.visible = false;
		Dialog.dialogs = Dialog.dialogs.without(this);

		var dlg_modal = false;
		Dialog.dialogs.each( function(dialog_) {
			if (dialog_.options.get('modal')) dlg_modal = dialog_;
		} );

		var do_hide = function() {
			this.div_container.setStyle( {
				position:'absolute',
				left:'-9999px',
				top:'-9999px'
			} ).show();

			if (dlg_modal) {
				Dialog.div_modal.style.zIndex = parseInt(dlg_modal.div_container.getStyle('zIndex')) - 1;
			} else Dialog.div_modal.hide();

			if (typeof(this.options.get('onHide')) == 'function') this.options.get('onHide')(this);
		}.bind(this);

		if (this.options.get('effect')) {
			this.div_container.blindUp( {
				duration:this.options.get('duration'),
				afterFinish:do_hide
			} );			
		} else do_hide();

		return this;
	},
	close: function() {
		this.observers.each( function(observer_) {
			Event.stopObserving(document, observer_.eventname, observer_.event);
		} );
		var onHide = this.options.get('onHide');
		this.options.set('onHide', function(dialog_) {
			onHide(dialog_);
			this.div_container.remove();
			this.show = this.hide = this.close = this.enable = this.disable = undefined;
			if (typeof(this.options.get('onClose')) == 'function') this.options.get('onClose')(this);
		}.bind(this));
		this.hide();
		return this;
	},
	disable: function() {
		var dimensions = this.div_container.getDimensions();
		this.div_disable.setStyle( {
			width:dimensions.width + 'px',
			height:dimensions.height + 'px'
		} ).show();
		this.div_container.select('button').each( function(button_) {
			button_.disabled_state = button_.disabled;
			button_.addClassName('disabled');
			button_.disabled = true;
		} );
		if (this.img_close) this.img_close.hide();
	},
	enable: function() {
		this.div_disable.hide();
		this.div_container.select('button').each( function(button_) {
			if (! button_.disabled_state) {
				button_.removeClassName('disabled');
				button_.disabled = false;
			}
		} );
		if (this.img_close) this.img_close.show();
	},
	flash: function() {
		if (this.__flashBusy) return;
		this.__flashBusy = true;

//		new Effect.Shake(this.div_container, { duration:0.5 } );
		setTimeout( function() {
			this.__flashBusy = false;
		}.bind(this), 750);
	},
	element: function() {
		return this.div_container;
	},
	observe: function(eventname_, function_) {
		var observer;
		document.observe(eventname_, observer = function(event_) {
			if (
				this == Dialog.onTop() &&
				! this.div_disable.visible()
			) function_(event_);
		}.bind(this));
		this.observers.push( { eventname:eventname_,event:observer } );
	}
} );

Dialog.open = function(options_) {
	var options = $H(options_);
	var onOpen = options.get('onOpen');
	options.set('onOpen', function(dialog_) {
		if (typeof(onOpen) == 'function') onOpen(dialog_);
		dialog_.show();
	} );
	var dialog = new Dialog(options);
	return dialog;
}

Dialog.onTop = function(flash_) {
	if (Dialog.dialogs.length > 0) {
		var dialog = Dialog.dialogs[Dialog.dialogs.length - 1];
		if (flash_) dialog.flash();
		return dialog;
	} else return false;
}

Event.observe(window, 'resize', function(event_) {
	var size = document.viewport.getDimensions();
	if (Dialog.div_modal) Dialog.div_modal.setStyle( {
		width:$(document.body).getWidth() + 'px',
		height:Math.max($(document.body).getHeight(), size.height) + 'px'
	} );
} );

document.observe('keydown', function(event_) {
	var el = event_.element();
	var dialog = Dialog.onTop();

	switch(event_.keyCode) {
		case 119:
		case 87:
			if (dialog && (event_.ctrlKey || event_.metaKey)) {
				dialog.close();
				event_.stop();
			}
			break;
		case 27:
			if (dialog) {
				dialog.close();
				event_.stop();
			}
			break;
	}
} );
