/****
**
*	Name:		ModalDialog
*	Purpose:	Implements a modal dialog that is cross-browser compatible.
**
****/

if(typeof(window.ModalDialog) == 'undefined') {
	// Setup the window's dialog variable
	window.dialog = null;
	window.nextModalDialogIndex = 0;


	/***
	**
	*	Name:		[Constructor]
	*	Purpose:	Initialize the object.
	**
	***/

	window.ModalDialog = function()
	{
		window.dialog = this;

		this.caption = null;
		this.onHide = null;
		this.hiddenSelects = new Array();
		this.returnValue = null;
		this.xmlHttp = null;

		this.actions = new Array();
		this.onActionHandlers = new Array();
		this.onCloseHandlers = new Array();

		// Setup the IFRAME
		var iframe = document.createElement('iframe');
		iframe.name = "ModalDialogFrame" + (window.nextModalDialogIndex++);
		iframe.src = window.rootUrl + 'dialogs';
		iframe.style.backgroundColor = 'transparent';
		iframe.style.border = 'none';
		iframe.style.position = 'fixed';
		iframe.style.left = '0';
		iframe.style.top = '0';
		iframe.style.right = '0';
		iframe.style.bottom = '0';
		iframe.style.width = '100%';
		iframe.style.height = '100%';
		iframe.style.visibility = 'hidden';
		iframe.style.zIndex = 1000;
		if(iframe.allowTransparency != undefined) iframe.allowTransparency = true;
		this.iframe = document.body.appendChild(iframe);
	}


	/*
	*	Name:		appendChild
	*	Purpose:	Add a child to the dialog box.
	*/

	ModalDialog.prototype.appendChild = function(oChild)
	{
		return this.contentDiv.appendChild(oChild);
	}


	/*
	*	Name:		clearActions
	*	Purpose:	Remove all actions from the dialog.
	*/

	ModalDialog.prototype.clearActions = function()
	{
		this.actions = new Array();

		var doc = this.getDocument();
		var actions = doc.getElementById('dialogButtons');
		if(actions != null) {
			while(actions.firstChild) actions.removeChild(actions.firstChild);
		}
	}


	/*
	*	Name:		close
	*	Purpose:	Close the dialog.
	*/

	ModalDialog.prototype.close = function()
	{
		// Hide the dialog
		var iframe = this.iframe;
		if(iframe != null) {
			iframe.style.display = 'none';
		}

		// Reload the blank dialog
		var doc = this.getDocument();
		doc.location.replace(window.rootUrl + 'dialogs');

		// Catch the onHide property
		if(typeof(this.onHide) != 'undefined' && this.onHide != null) {
			this.onClose(this.onHide);
			this.onHide = null;
		}

		// Notify handlers registered with this object
		for(var i = 0; i < this.onCloseHandlers.length; i++) {
			// Call the handler
			var func = this.onCloseHandlers[i];
			if(typeof(func) == 'string') {
				var retVal = eval(func);
			} else {
				var retVal = func(this);
			}

			// Cancel close on a return value of FALSE
			if(retVal === false) {
				return false;
			}
		}

		// Show hidden select boxes
		if(this.hiddenSelects.length) {
			for(var i = 0; i < this.hiddenSelects.length; i++) {
				var select = this.hiddenSelects[i];
				select.style.visibility = select.oldStyleVisibility;
			}
		}

		// Clear the window's dialog variable
		if(window.dialog === this) {
			window.dialog = null;
		}
	}
	ModalDialog.prototype.hide = ModalDialog.prototype.close;


	/*
	*	Name:		displayAction
	*	Purpose:	Display an action for the dialog.
	*/

	ModalDialog.prototype.displayAction = function(name, label)
	{
		if(typeof(this.actions) == 'undefined') this.actions = new Array();
		this.actions[this.actions.length] = {name:name, label:label};

		var doc = this.getDocument();
		var actions = doc.getElementById('dialogButtons');
		if(actions != null) {
			var button = doc.createElement('input');
			button.type = 'button';
			button.className = 'button';
			button.value = label;
			button.setAttribute('actionName', name);
			button.onclick = function() { window.dialog.performAction(this.getAttribute('actionName')); }
			actions.appendChild(button);
		}
	}


	/*
	*	Name:		displayElement
	*	Purpose:	Display an element as the dialog content.
	*/

	ModalDialog.prototype.displayElement = function(elem)
	{
		this.displayedElement = elem;
	}


	/*
	*	Name:		getActions
	*	Purpose:	Retrieve an array of objects the describe actions that can be performed.
	*/

	ModalDialog.prototype.getActions = function()
	{
		return this.actions;
	}


	/*
	*	Name:		getDocument
	*	Purpose:	Retrieve the document within the dialog.
	*/

	ModalDialog.prototype.getDocument = function()
	{
		var iframe = this.iframe;
		return iframe.contentWindow.document;
	}


	/*
	*	Name:		getForm
	*	Purpose:	Get the form for the dialog.
	*/

	ModalDialog.prototype.getForm = function()
	{
		// Get the dialog document
		var doc = this.getDocument();

		// Search for a FORM element
		var form = null;
		if(doc.evaluate != undefined) {
			var forms = doc.evaluate('//form', doc, null, XPathResult.ANY_u_TYPE, null);
			var thisForm = forms.iterateNext();
			if(thisForm) form = thisForm;
		} else if(doc.getElementsByTagName != undefined) {
			var forms = doc.getElementsByTagName('form');
			if(forms.length > 0) form = forms.item(0);
		}

		// Create a form element when one does not exist
		if(form == null) {
			form = doc.createElement('form');
			form.method = 'POST';
			form.enctype = 'multipart/form-data';
			form.encoding = 'multipart/form-data';
			form.acceptCharset = 'UTF-8';
			var contents = doc.getElementById('dialogContent');
			while(contents.childNodes.length) {
				form.appendChild(contents.childNodes[0]);
			}
			form = contents.appendChild(form);
		}

		return form;
	}


	/*
	*	Name:		getReturnValue / setReturnValue
	*	Purpose:	Retrieve or set the return value for the dialog.
	*/

	ModalDialog.prototype.getReturnValue = function() { return this.returnValue; }
	ModalDialog.prototype.setReturnValue = function(value) { this.returnValue = value; }


	/*
	*	Name:		getWindow
	*	Purpose:	Retrieve the window within the dialog.
	*/

	ModalDialog.prototype.getWindow = function()
	{
		var iframe = this.iframe;
		return iframe.contentWindow;
	}


	/*
	*	Name:		includeScript
	*	Purpose:	Include a script in the dialog.
	*/

	ModalDialog.prototype.includeScript = function(path)
	{
		// Check if the script has already been included
		var window = this.getWindow();
		window.includeOnce(path);
	}


	/*
	*	Name:		load
	*	Purpose:	Load the contents of the dialog.
	*/

	ModalDialog.prototype.load = function(vWhat, sMethod, sArgs)
	{
		if(typeof(sMethod) == 'undefined') sMethod = null;
		if(typeof(sArgs) == 'undefined') sArgs = null;

		// Get the IFRAME's document
		var doc = this.getDocument();

		// Determine the URL to load
		if(typeof(vWhat) == 'string') {
			var src = vWhat;
			vWhat = null;
		} else {
			var src = null;
		}

		// Add the root url
		if(src != null && src.substring(0, 1) != '/') {
			if(typeof(window.rootUrl) == 'undefined') {
				var rootUrl = '/';
			} else {
				var rootUrl = window.rootUrl;
			}
			if(src.substring(0, 7) != 'http://' && src.substring(0, 8) != 'https://') {
				src = rootUrl + src;
			}
		}
		

		// Handle the root url
		if(sMethod == null && src != null) {
			// Load the initial document contents
			doc.location.replace(src);
			this.contentNode = vWhat;
		} else if(sMethod != null) {
			// Get the document from which to create the form and the element to append it to
			var iframe = this.iframe;
			if(frames[iframe.name] == null) {
				var formDocument = doc;
				var formParent = doc;
				var useTarget = false;
			} else {
				var formDocument = document;
				var formParent = document.body;
				var useTarget = true;
			}

			// Setup a form for sending the arguments
			var form = formDocument.createElement('form');
			form.style.display = 'none';
			form.method = sMethod;
			form.action = src;
			if(useTarget) {
				form.target = iframe.name;
			}
			
			// Add the arguments as hidden inputs
			var args = sArgs.split('&');
			for(var i = 0; i < args.length; i++) {
				var parts = args[i].split('=');
				var name = unescape(parts[0]);
				var value = unescape(parts[1]);
				var input = formDocument.createElement('input');
				input.type = 'hidden';
				input.name = name;
				input.value = value;
				form.appendChild(input);
			}

			// Submit the form
			formParent.appendChild(form);
			form.submit();
			if(useTarget) {
				formParent.removeChild(form, true);
			}
		} else {
			this.contentNode = vWhat;
		}
	}


	/*
	*	Name:		loadXMLHttpRequest
	*	Purpose:	Load content from the provided XMLHttpRequest object.
	*/

	ModalDialog.prototype.loadXMLHttpRequest = function(xmlHttp)
	{
		this.xmlHttp = xmlHttp;
	}


	/*
	*	Name:		onAction
	*	Purpose:	Register a handler for action notification.
	*/

	ModalDialog.prototype.onAction = function(handler)
	{
		this.onActionHandlers[this.onActionHandlers.length] = handler;
	}


	/*
	*	Name:		onClose
	*	Purpose:	Register a handler for close notification.
	*/

	ModalDialog.prototype.onClose = function(handler)
	{
		this.onCloseHandlers[this.onCloseHandlers.length] = handler;
	}


	/*
	*	Name:		performAction
	*	Purpose:	Perform the requested action.
	*/

	ModalDialog.prototype.performAction = function(actionName)
	{
		// Search the dialog content for a handler
		var dialogWin = this.getWindow();
		if(typeof(dialogWin.onPerformAction) != 'undefined') {
			var retVal = dialogWin.onPerformAction(actionName);
			if(retVal === false) {
				return false;
			}
		}
		if(typeof(dialogWin.onDialogAction) != 'undefined') {
			var retVal = dialogWin.onDialogAction(actionName);
			if(retVal === false) {
				return false;
			}
		}

		// Notify any handlers
		for(var i = 0; i < this.onActionHandlers.length; i++) {
			var func = this.onActionHandlers[i];

			// Call the handler
			var retVal = func(this, actionName);

			// Cancel the action on a FALSE return value
			if(retVal === false) {
				return false;
			} 
		}

		// Get the form for the dialog
		var form = this.getForm();

		// Determine if the form is using the change dispatcher
		var elem = form.elements['ChangeDispatcher'];
		if(elem != null) {
			var inputName = "_mountPath_[dialogAction]";
		} else {
			var inputName = "dialogAction";
		}

		// Add the input specifying the action
		var input = form.ownerDocument.createElement('input');
		input.type = 'hidden';
		input.name = inputName;
		input.value = actionName;
		form.appendChild(input);

		// Submit the form
		form.submit();

		return true;
	}


	/*
	*	Name:		resize
	*	Purpose:	Automatically resize the dialog window.
	*/

	ModalDialog.prototype.resize = function()
	{
		var iframe = this.iframe;
		iframe.contentWindow.resizeDialog();
	}


	/*
	*	Name:		setTitle
	*	Purpose:	Set the title for the dialog.
	*/

	ModalDialog.prototype.setTitle = function(value)
	{
		// Store the title
		this.caption = value;
		
		// Attempt to change the title now
		var doc = this.getDocument();
		if(doc != null) {
			var titleNode = doc.getElementById('dialogTitle');
			if(titleNode != null) {
				while(titleNode.firstChild) titleNode.removeChild(titleNode.firstChild);
				titleNode.appendChild(doc.createTextNode(value));
			}
		}
	}


	/***
	**
	*	Name:		show
	*	Purpose:	Display the modal dialog.
	**
	***/

	ModalDialog.prototype.show = function()
	{
		// Hide any other dialog
		if(window.dialog != null && window.dialog !== this) {
			window.dialog.close();
		}

		window.dialog = this;

		// Make sure the dialog is loaded
		var doc = this.getDocument();

		// Load contents for the document
		if(this.xmlHttp != null) {
			// Make sure the document is loaded
			if(this.xmlHttp.readyState != 4) {
				window.setTimeout('window.dialog.show();', 500);
				return;
			}

			// Check the response code
			switch(this.xmlHttp.status) {
				case 200:
					// Good to go
					break;

				case 403:
					alert("You are not authorized to perform this action.");
					return false;

				case 404:
					alert("Unable to load the requested dialog.");
					return false;
			}

			var doc = this.xmlHttp.responseXML;
			this.contentNode = doc.documentElement;

			// Evaluate JavaScript
			var win = this.getWindow();
			if(typeof(doc.evaluate) != 'undefined') {
				var scripts = doc.evaluate('//node()[local-name()="script"]', this.contentNode, this.resolveNamespace, XPathResult.ANY_u_TYPE, null);
				var script = scripts.iterateNext();
				while(script) {
					for(var i = 0; i < script.childNodes.length; i++) {
						win.eval(script.childNodes[i].nodeValue);
					}
					script = scripts.iterateNext();
				}
			} else {
				var scripts = doc.getElementsByTagName('script');
			}
		}
		
		// Show this dialog
		var iframe =  this.iframe;
		if(iframe != null) {
			iframe.style.display = 'block';
			iframe.style.visibility = 'visible';
		}

		// Call the onShow method in the dialog
		var dialogWin = this.getWindow();
		if(dialogWin != null && typeof(dialogWin.onShow) != 'undefined') {
			dialogWin.onShow(this);
		}

		// Call the onShow method in this object
		if(typeof(this.onShow) != 'undefined') {
			this.onShow();
		}

		// Hide select boxes in browsers that support getElementsByTagName
		/*
		if(document.getElementsByTagName != undefined) {
			this.hiddenSelects = new Array();
			var selects = document.getElementsByTagName('select');
			for(var i = 0; i < selects.length; i++) {
				var select = selects[i];
				select.oldStyleVisibility = select.style.visibility;
				select.style.visibility = 'hidden';
				this.hiddenSelects[i] = select;
			}
		}
		*/
	}
}

