/* DDDialog Routines (non-modal asynchronous dialog box)
 *
 * Copyright 2010 Disk Depot
 */

var	DDDIALOG_TYPE_ALERT = 1,
	DDDIALOG_TYPE_CONFIRM = 2,
	DDDIALOG_TYPE_PROMPT = 3;

/* 
 * type			One of the defined DDDIALOG_TYPE_* types above
 * titleStr		Title of box
 * bodyStr		Body text in box
 * initDialogStr	Initial contents of dialog box (if applicable, otherwise param ignored)
 * callBack		Callback method that takes two params (callBackData, result); called if "OK" clicked. (If null, no callback made)
 * callBackData		Any arbitrary object (including arrays, etc.) that contains predefined data we wish to pass to callback. Can be null.
 */
function DDDialog(type, titleStr, bodyStr, initDialogStr, callBack, callBackData, okText, cancelText)
{
	var	thisDDDialog = this;				/* Required for click-handling closure functions */

	/* Assign methods */
	this.display = dddialog_display;
	this.isDisplayed = dddialog_isDisplayed;
	this.callBack = callBack;
	this.callBackData = callBackData;
	this.okClickHandler = dddialog_okClickHandler;
	this.cancelClickHandler = dddialog_cancelClickHandler;
	this.textKeyHandler = dddialog_textKeyHandler;
	this.okText = okText ? okText : "OK";
	this.cancelText = cancelText ? cancelText : "Cancel";

	/* Assign/create properties */
	this.id = dddialog_idCount++;
	this.show = false;
	this.titleStr = titleStr;
	this.bodyStr = bodyStr;
	this.initDialogStr = initDialogStr;

	/* Checks and filters */
	if ((type != DDDIALOG_TYPE_ALERT) && (type != DDDIALOG_TYPE_CONFIRM) && (type != DDDIALOG_TYPE_PROMPT)) {
		throw "Unknown DDDIALOG_* dialog type ('type' parameter)";
	}
	this.bodyStr = this.bodyStr.replace(/</g, "&lt;");
	this.bodyStr = this.bodyStr.replace(/>/g, "&gt;");
	this.bodyStr = this.bodyStr.replace(/>/g, "&gt;");
	this.bodyStr = this.bodyStr.replace(/\n/g, "<br />");
	this.bodyStr = this.bodyStr.substring(0, 500);

	/* Initialise */
	this.html = dddialog_generateHTML(type, this.id, this.titleStr, this.bodyStr, this.initDialogStr, this.okText, this.cancelText); 
	dddialog_addHTML(this.html);
	this.promptElm = document.getElementById('dddialog_prompt_' + this.id);
	this.shadowElm = document.getElementById('dddialog_shadow_img_' + this.id);
	this.okElm = document.getElementById('dddialog_ok_' + this.id);
	this.cancelElm = document.getElementById('dddialog_cancel_' + this.id);
	this.textElm = document.getElementById('dddialog_text_' + this.id);
	if (this.textElm) {
		this.textElm.value = initDialogStr;
	}

	/* Add click handlers - note use of closures with "thisDDDialog" */
	this.okElm.onclick = function () { thisDDDialog.okClickHandler(); }
	if (this.cancelElm) {
		this.cancelElm.onclick = function () { thisDDDialog.cancelClickHandler(); }
	}
	if (this.textElm) {
		this.textElm.onkeydown = function () {
								var	passedEvent = arguments[0] ? arguments[0] : event;
								thisDDDialog.textKeyHandler(passedEvent);
							}
	}
}

function dddialog_display(wantShow)
{
	/* Check lock */
	if ((dddialog_activeDialog !== null) && wantShow) {
		throw "Cannot display two or more DDDialog boxes at the same time";
	}
 
	var	thisDDDialog = this;	/* (for closures) */
	this.show = wantShow;

	this.promptElm.style.display = wantShow ? 'block' : 'none';
	this.shadowElm.style.display = (window.XMLHttpRequest && wantShow) ? 'block' : 'none';
	/* Note; XMLHttpRequest is quick-'n'-lousy way to see if (not) running IE6 (no variable PNG transparency support) */ 

	if (wantShow) {
		var	width = this.promptElm.clientWidth;
		var	height = this.promptElm.clientHeight;

		var	top = (screen.height / 4) - (this.promptElm.offsetHeight / 2);
			left = ((screen.width - 25) / 2) - (this.promptElm.offsetWidth / 2);

		this.promptElm.style.left = left;
		this.promptElm.style.top = top;

		if (window.XMLHttpRequest) {
			this.shadowElm.style.display = 'block';
			this.shadowElm.style.top = top;
			this.shadowElm.style.left = left;
			
			this.shadowElm.style.width = 1.1 * width + 'px';
			this.shadowElm.style.height = 1.35 * height + 'px';
		}

		if (this.textElm) {
			this.textElm.focus();
			this.textElm.onblur = function () {
					//thisDDDialog.textElm.select();		// Doesn't work directly w/ Firefox
					dddialog_flashElm(this.id, "red", 3, false);
					//thisDDDialog.textElm.focus();			// Doesn't work w/ Firefox
					setTimeout("document.getElementById('" + this.id + "').select();", 100);
				};
			this.textElm.value = this.initDialogStr;
		}

		dddialog_activeDialog = this;	
	} else {
		if (this.textElm) {
			this.textElm.onblur = null;
		}

		dddialog_activeDialog = null;	/* Other dialogs can now be shown */
	}
}

/* Read-only way of finding if dialog is displayed */
function dddialog_isDisplayed()
{
	return this.show;
}

function dddialog_okClickHandler()
{
	var	result = this.textElm ? this.textElm.value : null;

	this.display(false);

	if (this.callBack) {
		this.callBack(this.callBackData, result);
	}
}

function dddialog_cancelClickHandler()
{
	this.display(false);
}

function dddialog_textKeyHandler(passedEvent)
{
	if (passedEvent.keyCode == 13) {
		this.okClickHandler();
	} else if (passedEvent.keyCode == 27) {
		this.cancelClickHandler();
	}
}

/* ===================================================================== */
/* Following for internal use only - some methods intentionally "static" */

var	dddialog_idCount = 1;
var	dddialog_activeDialog = null;
	/* Lock - don't want two dialogs showing at same time - n.b. we ignore miniscule chance of a race condition(!) */

function dddialog_generateHTML(type, id, titleText, bodyText, initValue, okText, cancelText)
{
	var	result;

	result = 
			"<div style='display:none; position:absolute; top:20px; left:20px; width: 400px; border: solid 1px black; background-color:white; z-index:500;' id='dddialog_prompt_" + id + "'>" +
			"<div class='dddialog_heading'>" + titleText + "</div>" + 
			"<div class='dddialog_main'>" + bodyText + "</div>";

	if (type == DDDIALOG_TYPE_PROMPT) {
		result += "<div class='dddialog_main'>" + 
				"<center>" +
				"<input size='50' type='text' id='dddialog_text_" + id + "' " +
					" />" + 
				"</center>" +
				"</div>";
	}

	result += "<div class='dddialog_main'>" + "<center>" + 
			"<table style='width:378px;' cellpadding='0' cellspacing='0'>" +
			"<tr><td align='center'>" + 
			"<div style='width:100px;' class='dddialog_box_inactive' id='dddialog_ok_" + id + "' onmouseout='this.className=\"dddialog_box_inactive\";' onmouseover='this.className=\"dddialog_box_active\";'><span style='cursor:default;'>" + okText + "</span></div>" +
			"</td>";

	if ((type == DDDIALOG_TYPE_PROMPT) || (type == DDDIALOG_TYPE_CONFIRM)) {
		result += "<td align='center'>" + 
				"<div style='width:100px;' class='dddialog_box_inactive' id='dddialog_cancel_" + id + "' onmouseout='this.className=\"dddialog_box_inactive\";' onmouseover='this.className=\"dddialog_box_active\";'><span style='cursor:default;'>" + cancelText + "</span></div>" +
				"</td>";
	}

	result += "</tr>" +
			"</table>" +
			"</center>" +
			"</div>" +
			"</div>" +
			"<img class='dddialog_shadow_img' style='display: none; position: absolute; top: 20px; left: 20px; z-index: 499;' id='dddialog_shadow_img_" + id + "' src='http://www.diskdepot.co.uk/dddialog/shadow-557x159.png' />";

	return result;
}

/* Flash specified element as colour bgColor "times" times. Times should always be an odd number. */
function dddialog_flashElm(elmId, bgColor, times)
{
	var	elm = document.getElementById(elmId);

	var	oldBgColor = elm.style.backgroundColor;
	elm.style.backgroundColor = bgColor;

	if (times > 0) {
		var	code =	"dddialog_flashElm(" +
					"\"" + elmId + "\", " +
					"\"" + oldBgColor + "\", " +
					"\"" + (times - 1) + "\")";
		window.setTimeout(code, 180);
	}

}

function dddialog_addHTML(html)
{
	var	div = document.createElement("div");
	div.innerHTML = html;
	div.style.display = 'block';
	div.style.position = 'absolute';
	div.style.width = '700';
	div.style.top = '20';
	div.style.left = '20';

	document.body.appendChild(div);
}

