/*
 * Miscellaneous {
 */

/* Allow a number of functions to be called when <body> is loaded. */
var onBodyLoadFuncs = new Array();
function addOnBodyLoadFunc(f)
{
    onBodyLoadFuncs[onBodyLoadFuncs.length] = f;
}
function callOnBodyLoadFuncs()
{
    for (var i = 0; i < onBodyLoadFuncs.length; ++i)
	onBodyLoadFuncs[i]();
}

function mtlib_leftPadStr(str, length, padC)
{
    str = new String(str); /* convert to string. */
    var s = '';
    length -= str.length;
    for (; length > 0; --length)
	s = s.concat(padC);
    return s.concat(str);
}
/* Help show or hide a block of text (see booking page for example). */
function mtlib_showHide(prefix, action)
{
    function setIfFound(which, value)
    {
	var elem = document.getElementById(prefix + which);
	if (elem)
	    elem.style.display = value;
    }
    if (action == 'show') {
	setIfFound('show', 'none');
	setIfFound('hide', 'inline');
	setIfFound('body', 'block');
    } else if (action == 'hide') {
	setIfFound('show', 'inline');
	setIfFound('hide', 'none');
	setIfFound('body', 'none');
    } else {
	alert("Internal error: mtlib_showHide: unknown action ["
	    + action + "]");
    }
    return false;
}


/*
 * } Miscellaneous
 */


/*
 * Email address hiding {
 */
/* Convert to: <a href="user@domainQualifiers" attribs>text</a>
 * If text is empty, user@domain is used instead.
 */
function mailLink(tag, domain, user, qualifiers, attribs, text)
{
    mailLinkStart(tag, domain, user, qualifiers, attribs);
    if (text == '')
	document.write(user + '@' + domain);
    else
	document.write(text);
    mailLinkEnd(tag);
}
function mailLinkStart(tag, domain, user, qualifiers, attribs)
{
    document.write("<" + tag + " hr" + 'ef="mai' + "lto:" + user
	+ "@" + domain + qualifiers + '" ' + attribs + ' >');
}
function mailLinkEnd(tag)
{
    document.write('<\/' + tag + '>');
}
/*
 * } Email address hiding
 */

/*
 * DOM stuff {
 */

function mtlib_findElementsByTagAndName(tagName, name)
{
    var elements = document.getElementsByName(name);
    // Hack for ie: doesn't find elements that are not supposed to have names
    if (elements.length == 0) {
	var el;
	var tagEls = document.getElementsByTagName(tagName);
	elements = new Array();
	for (var i = 0; i < tagEls.length; ++i) {
	    el = tagEls[i];
	    if (el.name == name)
		elements[elements.length] = el;
	}
    }
    return elements;
}

function mtlib_removeIdsFromTree(parent)
{
    parent.removeAttribute("id");
    for (var i = 0; i < parent.childNodes.length; ++i)
	mtlib_removeIdsFromTree(parent.childNodes[i]);
}

function mtlib_findTreeElementsByTagAndName(parent, tagName, name,
    alertIfNotUnique)
{
    var matches = new Array();
    var el;
    var tagEls = parent.getElementsByTagName(tagName);
    for (var i = 0; i < tagEls.length; ++i) {
	el = tagEls[i];
	// if (el.name == name)
	if (el.getAttribute("name") == name)
	    matches[matches.length] = el;
    }
    if (alertIfNotUnique && matches.length != 1)
	alert("internal error: failed to find one <" + tagName
	    + "> named (" + name + ")");
    return matches;
}

/* From http://www.quirksmode.org/js/findpos.html */
function mtlib_getHTMLElementPosition(obj)
{
    var curleft = curtop = 0;
    if (obj.offsetParent) {
	curleft = obj.offsetLeft
	curtop = obj.offsetTop
	while ((obj = obj.offsetParent) != null) {
	    curleft += obj.offsetLeft
	    curtop += obj.offsetTop
	}
    }
    return [curleft, curtop];
}

/*
 * } DOM stuff
 */


/*
 * Event stuff {
 */

/* based on code from
 * http://evolt.org/article/Mission_Impossible_mouse_position/17/23335/index.html
 */
function mtlib_getEventDocXY( e, ei )
{
    var docX, docY;
    if (!e)
	e = window.event;
    if (typeof(e.pageX) == 'number') {
	docX = e.pageX;
	docY = e.pageY;
    } else {
	docX = e.clientX;
	docY = e.clientY;
	/* IE6 (and others?) set documentElement.scrollTop but not (always?)
	 * body.scrollTop (and Left) - but which exist with value 0.
	 */
	if (document.documentElement
	    && typeof (document.documentElement.scrollTop) == 'number')
	{
	    docX += document.documentElement.scrollLeft;
	    docY += document.documentElement.scrollTop;
	} else {
	    docX += document.body.scrollLeft;
	    docY += document.body.scrollTop;
	}
    }
    ei.docX = docX;
    ei.docY = docY;
}

function mtlib_preventDefaultEvent(eventInfo)
{
    if (eventInfo.isIE) {
	eventInfo.event.cancelBubble = true;
	eventInfo.event.returnValue = false;
    } else {
	eventInfo.event.preventDefault();
    }
}

function mtlib_getEventInfo(eArg)
{
    var e = eArg;
    if (!e)
	e = window.event;
    var t;
    if (e.target)
	t = e.target;
    else if (e.srcElement)
	t = e.srcElement;
    /* IE 7.0 sometimes says "nodeType is null or not an object"
     * (not sure why it isn't "t" or why the nodeType property would
     * be missing).
     */
    if (typeof t != "undefined" && t != null
	    && typeof t.nodeType != "undefined" && t.nodeType != null
	    && t.nodeType == 3) // defeat Safari bug
	t = t.parentNode;
    var ei = new Object();
    ei.event = e;
    ei.target = t;
    // IE does not have the event.preventDefault() method
    ei.isIE = e.preventDefault ? 0 : 1;
    mtlib_getEventDocXY(eArg, ei);

    return ei;
}

/* event.modifiers: 1:alt, 2:ctrl, 4:shift, ?:meta;
 * metaKey also set when 3rd mouse button pressed.
 */
function mtlib_isShiftKeyDown(eventInfo)
{
    return (eventInfo.event.shiftKey
	|| (eventInfo.event.modifiers & 4)) ? 1 : 0;
}

function mtlib_isCtrlKeyDown(eventInfo)
{
    if (navigator.platform.indexOf("Mac") >= 0)
	return (eventInfo.event.ctrlKey
	    || eventInfo.event.metaKey) ? 1 : 0;
    else
	return (eventInfo.event.ctrlKey
	    || (eventInfo.event.modifiers & 2)) ? 1 : 0;
}

function mtlib_centerWindowOnClickAttributes(eventInfo, wWidth, wHeight)
{
    var attr = "width=" + wWidth + ",height=" + wHeight
	+ ",left=" + (eventInfo.event.screenX - wWidth / 2)
	+ ",top=" + (eventInfo.event.screenY - wHeight / 2)
	;
    return attr;
}

function mtlib_buttonDoubleClickDetect(button)
{
    /* Double click detection/avoidance. */
    var nowMS = new Date().getTime();
    if (typeof button.lastClickTime != "undefined"
	    && nowMS - button.lastClickTime < 1 * 1000)
	return true;
    button.lastClickTime = nowMS;
    return false;
}

/*
 * } Event stuff
 */

/*
 * Date stuff {
 */
var mtlib_daysInMonth_m = [31,28,31,30,31,30,31,31,30,31,30,31];
/* year is yyyy, month is 0..11. */
function mtlib_daysInMonth(year, month) {
    var nDays = mtlib_daysInMonth_m[month];
    if (month != 2)
	return nDays;
    if (year % 4 != 0 || (year % 100 == 0 && year % 400 != 0))
	return nDays;
    return nDays - 1;
}

function mtlib_secondsToHHMMFormat(secs, zeroPadHours, showSecs)
{
    var hh = 0;
    var mm = 0;
    var ss = '';
    var sign = '';
    if (secs < 0) {
	sign = '-';
	secs = -secs;
    }
    hh = (secs / (60 * 60)) | 0;
    if (hh < 10 && zeroPadHours)
	hh = '0' + hh;
    mm = secs % (60 * 60);
    mm = (mm / 60) | 0;
    if (mm < 10)
	mm = '0' + mm;
    if (showSecs) {
	ss = secs % 60;
	if (ss < 10)
	    ss = '0' + ss;
	ss = ':' + ss;
    }
    return sign + hh + ':' + mm + ss;
}

/*
 * } Date stuff
 */

/* Check if a popup window was successfully opened.
 * wObj is the return value from window.open(),
 * wName (if not null) is used to check that the value of wObj.name
 *     is correct,
 * blockedFunc is a function to call with the results of the check - it
 *     is passed three arguments: a boolean value indicating success/failure,
 *     a string indicating what test failed, and the window object.
 *     The function is likely to be called after checkForPopupBlocker()
 *     returns.
 * Returns: nothing.
 */
function mtlib_checkForPopupBlocker(wObj, wName, blockedFunc)
{
    if (wObj == null) {
	blockedFunc(true, "window object null", wObj);
    } else {
	/* Done after a while as some popup blockers allow the window
	 * to be created but close it very quickly.
	 */
	setTimeout(function() {
	    var failedTest = null;
	    if (typeof wObj.parent == 'undefined') {
		failedTest = "window parent is undefined";
	    } else {
		try {
		    var name = wObj.name;
		    if (wName != null
			&& (name == null || name != wName))
		    {
			if (name == null)
			    failedTest = "name attribute is null";
			else if (name != wName)
			    failedTest = "name attribute is incorrect - expected [" + wName + "], found[" + name + "]";
		    } else if (wObj.closed) {
			failedTest = "window is closed";
		    }
		} catch (ex) {
		    failedTest = "exception checking name/closed attributes\n("
			+ ex + ")";
		}
	    }
	    if (failedTest == null)
		blockedFunc(false, "-", wObj);
	    else
		blockedFunc(true, failedTest, wObj);
	}, 500);
    }
}
