/*
	$Id: dialog.class.js,v 1.10 2006/10/21 12:37:03 bob Exp $
	(C) Copyright 2006 Fellownet.
	All rights reserved.

	Usefull urls:
	- http://www.sergiopereira.com/articles/prototype.js.html
	- http://blogs.ebusiness-apps.com/jordan/pages/Prototype%20Library%20Info.htm
	- http://www.gotapi.com/index.html
	- http://tagsoup.com/-dev/null-/css/fixed/
*/

var dialog = Class.create();

var __dialogs = new Array();
var __zIndex = 9999;

dialog.prototype = {
	initialize: function(options_) {
		this.options = {
			width:300,
			name:'Untitled',
			title:false,
			content:'Content',
			buttons:'',
			buttons_disabled:'',
			button_default:false,
			button_cancel:false,
			source:'',
			method:'get',
			parameters:'',
			modal:false,
			standalone:false,
			tag:false,
			sound:false,
			callback:function(button_, dialog_) { dialog_.close(); }
		}
		Object.extend(this.options, options_ || {} );

		var self = this;

		if (__dialogs.length > 0) {
			var hasVisibles = __dialogs.any( function(dialog_) {
				return ! dialog_.options['standalone'] && dialog_.visible();
			} );
			if (hasVisibles && this.options['modal']) {
				this.show = this.hide = this.enable = this.disable = function() { /* disable these dialog functions */ }
				return;
			} else this.id = __dialogs.last().id + 10;
		} else {
			this.bodyoverlay = document.createElement('div');
			this.bodyoverlay.style.display = 'none';
			this.bodyoverlay.setAttribute('id', 'dialogoverlay');
			Element.addClassName(this.bodyoverlay, 'dialogfaded');

			document.getElementsByTagName('body').item(0).appendChild(this.bodyoverlay);

			this.id = 100;
			Event.observe(document, 'keypress', this.onkeypress.bindAsEventListener(this), true);
		}

		this.div_container = document.createElement('div');
		this.div_container.setAttribute('id', 'div_container_' + this.id);
		this.div_container.className = 'dialog';
		this.div_container.style.visibility = 'hidden';

		if (
			typeof(window.__ie) == 'number' &&
			window.__ie <= 6
		) {
			this.iframe = document.createElement('iframe');
			this.iframe.className = 'hidden';
			this.iframe.setAttribute('src', '/blank.app');
			this.div_container.appendChild(this.iframe);
		}

		this.div_outer = document.createElement('div');
		this.div_outer.className = 'outer';
		this.div_container.appendChild(this.div_outer);

		this.div_overlay = document.createElement('div');
		Element.addClassName(this.div_overlay, 'overlay');
		Element.addClassName(this.div_overlay, 'dialogfaded');
		this.div_overlay.style.display = 'none';
		this.div_container.appendChild(this.div_overlay);


		this.div_inner = document.createElement('div');
		this.div_inner.className = 'inner';
		this.div_outer.appendChild(this.div_inner);

		if (this.options['title']) {
			this.div_header = document.createElement('div');
			this.div_header.className = 'header';
			this.div_header.innerHTML = this.options['title'];
			this.div_inner.appendChild(this.div_header);
		}

		this.div_content = document.createElement('div');
		this.div_content.setAttribute('id', 'div_content_' + this.id);
		this.div_content.className = 'content';
		this.div_inner.appendChild(this.div_content);

		this.buttons = new Array();
		var disabled = $A(this.options['buttons_disabled'].split(/\s*[,|]\s*/i));
		if (! /^\s*$/i.test(this.options['buttons'])) {
			this.div_buttons = document.createElement('div');
			this.div_buttons.className = 'buttons';

			var buttondefs = this.options['buttons'].split(/\s*[,|]\s*/i);
			buttondefs.each( function(buttondef_) {
				var input_button = document.createElement('button');
				input_button.setAttribute('caption', buttondef_);
				input_button.innerHTML = buttondef_;
				input_button.onclick = function() {
					self.options.callback(buttondef_, self);
				};
				if (self.buttons.length == 0) Element.addClassName(input_button, 'mostleft');

				if (
					self.options['button_default'] &&
					self.options['button_default'] == buttondef_
				) Element.addClassName(input_button, 'default');

				if (disabled.indexOf(buttondef_) > -1) {
					input_button.disabled = true;
					Element.addClassName(input_button, 'disabled');
					input_button.setAttribute('enabled', false);
				} else input_button.setAttribute('enabled', true);

				self.div_buttons.appendChild(input_button);
				self.buttons.push(input_button);
			} );
			this.div_inner.appendChild(this.div_buttons);
		}

		 __dialogs.push(this);
	},

	onkeypress: function(e_) {
		var top = dialog.onTop();
		if (top) switch(e_.keyCode) {
			case Event.KEY_RETURN:
				if (top.options['button_default']) {
					top.options['callback'](top.options['button_default'], top);
				}
				return false;
			break;
			case Event.KEY_ESC:
				if (top.options['button_cancel']) {
					top.options['callback'](top.options['button_cancel'], top);
				}
				return false;
			break;
			default:
				return true;
			break;
		}
	},

	hide: function(onComplete_) {
		if (Element.visible('div_container_' + this.id)) {
			this.__toggle(onComplete_);
		}
	},

	show: function(onComplete_) {
		if (/^\s*$/i.test(this.div_content.innerHTML)) {
			var self = this;
			var setBoundaries = function() {
				self.div_container.style.width = self.options['width'] + 'px';
				self.div_outer.style.width = (self.options['width'] - 40) + 'px';
				self.div_inner.style.width = (self.options['width'] - 40) + 'px';
				self.div_content.style.width = (self.options['width'] - 40) + 'px';
				if (self.div_buttons) self.div_buttons.style.width = (self.options['width'] - 40) + 'px';
				if (self.div_header) self.div_header.style.width = (self.options['width'] - 50) + 'px';

				self.options['height'] = Element.getHeight(self.div_container);

				self.div_overlay.style.width = (self.options['width'] - 28) + 'px';
				self.div_overlay.style.height = (self.options['height']) + 'px';

				if (
					typeof(window.__ie) == 'number' &&
					window.__ie <= 6
				) {
					self.iframe.style.width = (self.options['width']) + 'px';
					self.iframe.style.height = (self.options['height']) + 'px';
					var onScroll = window.onscroll;
					window.onscroll = function() {
						if (self && self.center) self.center();
						if (onScroll) onScroll();
					}
					var onResize = window.onresize;
					window.onresize = function() {
						if (self && self.center) self.center();
						if (onResize) onResize();
					}
					self.center();
				} else {
					self.div_container.style.left = '50%';
					self.div_container.style.top = '48%';
					self.div_container.style.marginLeft = '-' + Math.ceil(self.options['width'] / 2) + 'px';
					self.div_container.style.marginTop = '-' + Math.ceil(self.options['height'] / 2) + 'px';
				}

				self.div_container.style.display = 'none';
				self.div_container.style.visibility = 'visible';
				self.__toggle(onComplete_);
			}

			document.getElementsByTagName('body').item(0).appendChild(this.div_container);

			if (! /^\s*$/i.test(this.options['source'])) {
				new Ajax.Updater( {
					success:this.div_content
				}, this.options['source'], {
					method:this.options['method'],
					parameters:this.options['parameters'],
					evalScripts:true,
					onComplete:setBoundaries
				} );
			} else {
			
				if ( typeof( this.options['content'] ) == 'string' ) {

					this.div_content.innerHTML = this.options['content'];
					Element.addClassName(this.div_content, 'margin');
					setBoundaries();
				} else {
					$( this.div_content ).insert( { top:this.options['content'] } );
					this.options['content'].removeClassName( 'offscreen' );
					Element.addClassName(this.div_content, 'margin');
					setBoundaries();
				}
				
			}
		} else {
			if (! Element.visible('div_container_' + this.id)) {
				this.__toggle(onComplete_);
			}
		}
	},

	close: function(onComplete_) {
		this.disable();
		var self = this;
		this.hide( function() {
			self.destroy();
			if (onComplete_) onComplete_();
		} );
	},

	destroy: function() {
		__dialogs = __dialogs.without(this);
		document.getElementsByTagName('body').item(0).removeChild(this.div_container);
		this.show = this.hide = this.enable = this.disable = this.center = function() {}
	},

	refresh: function(onComplete_) {
		if (! /^\s*$/i.test(this.options['source'])) {
			new Ajax.Updater( {
				success:this.div_content
			}, this.options['source'] + '?rn=' + Math.random(), {
				method:this.options['method'],
				parameters:this.options['parameters'],
				evalScripts:true,
				onComplete:function() {
					if (onComplete_) onComplete_();
				}
			} );
		}
	},

	disable: function() { this.enable(false); },
	enable: function(enable_) {
		if (enable_ == undefined) enable_ = true;
		var self = this;
		this.buttons.each( function(button_) {
			self.enableButton(button_, enable_, true);
		} );
	},

	disableButton: function(button_) { this.enableButton(button_, false); },
	enableButton: function(button_, enable_, __internal_) {
		if (enable_ == undefined) enable_ = true;
		if (__internal_ == undefined) __internal_ = false;
		if (! $(button_)) {
			this.buttons.each( function(dlgbutton_) {
				if (dlgbutton_.getAttribute('caption') == button_) {
					button_ = dlgbutton_;
				}
			} );
		}
		if (__internal_ && enable_) {
			enable_ = button_.getAttribute('enabled');
		}

		Element.addClassName(button_, enable_ ? 'enabled' : 'disabled');
		Element.removeClassName(button_, enable_ ? 'disabled' : 'enabled');
		if (! __internal_) button_.setAttribute('enabled', enable_);
		button_.disabled = (! enable_);
	},

	getName: function() { return this.options['name']; },
	setName: function(name_) { this.options['name'] = name_; },
	getTag: function() { return this.options['tag']; },
	setTag: function(tag_) { this.options['tag'] = tag_; },

	setTitle: function(title_) {
		if (this.div_header) this.div_header.innerHTML = title_;
	},

	__moveToTop:function() {
		this.div_container.style.zIndex = __zIndex++;
	},

	__toggle:function(onComplete_) {
		var self = this;
		var onShow = function() {
			try {

			} catch(e_) {}
			self.appear();
			self.buttons.each( function(button_) {
				if (button_.getAttribute('caption') == self.options['button_default']) {
					try {
						button_.focus();
					} catch(err_) {}
				}
			} );
		}
		var onHide = function() {
			self.appear();
			var dlg = dialog.onTop();
			if (dlg) {
				dlg.appear();
			} else $('dialogoverlay').hide();
		}
		this.__moveToTop();

		if (Element.visible('div_container_' + self.id) == false) {
			__dialogs.each( function(dialog_) {
				if (dialog_ != __dialogs.last()) {
					dialog_.fade();
				}
			} );
			$('dialogoverlay').show();
			if (
				typeof(window.__ie) == 'number' &&
				window.__ie <= 6
			) $('dialogoverlay').style.height = document.body.offsetHeight + 'px';
		}

		Element.toggle('div_container_' + this.id);
		if (Element.visible('div_container_' + this.id)) {
			onShow();
		} else onHide();
		if (onComplete_) onComplete_();
	},
	fade: function() {
		this.div_overlay.style.display = 'block';
	},
	appear: function() {
		this.div_overlay.style.display = 'none';
	},
	visible: function() {
		try {
			return Element.visible('div_container_' + this.id);
		} catch(err_) {
			return false;
		}
	},

	center: function() {
		var my_width  = 0;
		var my_height = 0;
		if (typeof(window.innerWidth) == 'number') {
			my_width = window.innerWidth;
			my_height = window.innerHeight;
		} else if (document.documentElement && (document.documentElement.clientWidth || document.documentElement.clientHeight)) {
			my_width  = document.documentElement.clientWidth;
			my_height = document.documentElement.clientHeight;
		} else if (document.body && (document.body.clientWidth || document.body.clientHeight)) {
			my_width  = document.body.clientWidth;
			my_height = document.body.clientHeight;
		}
		var scrollY = 0;
		if (document.documentElement && document.documentElement.scrollTop) {
			scrollY = document.documentElement.scrollTop;
		} else if (document.body && document.body.scrollTop) {
			scrollY = document.body.scrollTop;
		} else if (window.pageYOffset) {
			scrollY = window.pageYOffset;
		} else if (window.scrollY) {
			scrollY = window.scrollY;
		}
		var dimensions = Element.getDimensions(this.div_container);
		var setX = (my_width - dimensions.width) / 2;
		var setY = (my_height - dimensions.height) / 2 + scrollY;
		setX = (setX < 0) ? 0 : setX;
		setY = (setY < 0 ) ? 0 : setY;

		this.div_container.style.left = setX + "px";
		this.div_container.style.top  = setY + "px";
	}

}

dialog.open = function(options_, onComplete_) {
	var dlg = new dialog(options_);
	if (typeof(onComplete_) == 'function') {
		dlg.show(onComplete_(dlg));
	} else dlg.show();
	return dlg;
}

dialog.onTop = function() {
	var visibles = __dialogs.findAll( function(el_) {
		return el_.visible() && ! el_.options['standalone'];
	} );
	if (visibles.length > 0) {
		var dialog = visibles.last();
		return dialog;
	} else return false;
}
