/**
 *# runOnLoad.js
 */
/*
 * runOnLoad.js: portable registration for onload event handlers.
 *
 * This module defines a single runOnLoad() function for portably registering
 * function that can be safely invoked only when the document is fully loaded
 * and the DOM is available.
 *
 * Functions registered with runOnLoad() will not be passed any arguments when
 * invoked. They will not be invoked as a method of any meaningful object, and
 * the this keyword should not be used. Functions registered with runOnLoad()
 * will be invoked in the order in which they were registered, There is no way
 * to deregister a function once it has been passed to runOnLoad().
 *
 * In old browsers that do not support addEventListner() or attachEvent(),
 * this function relies on the DOM Level 0 window.onload property and will not
 * work correctly when used in documents that set the onload attribute of
 * their <body> or <frameset> tags.
 */
function runOnLoad(f) {
	if		(runOnLoad.loaded) f();		// If already loaded, just invoke f() now.
	else	runOnLoad.funcs.push(f);	// Otherwise, store it for later.
}

runOnLoad.funcs		= [];		// The array of functions to call when the document loads.
runOnLoad.loaded	= false;	// The functions have not been run yet.

// Run all registered functions in the order in which they were registered.
// It is safe to call runOnLoad.run() more than once: invocations after the
// first do nothing. It is safe for an initialization function to call
// runOnLoad() to register another function.
runOnLoad.run = function() {
	if (runOnLoad.loaded) return;		// If we've already run, do nothing.
	
	for(var i = 0; i < runOnLoad.funcs.length; i++) {
		try			{ runOnLoad.funcs[i](); }
		catch(e)	{ /* An exception in one function shouldn't stop the rest. */ }
	}
	
	runOnLoad.loaded = true;	// Remember that we've already run once.
	delete runOnLoad.funcs;		// But don't remember the functions themselves.
	delete runOnLoad.run;		// And forget about this functions too!
};

// Register runOnLoad.run() as the onload event handler for the window
if			(window.addEventListener)	window.addEventListener("load", runOnLoad.run, false);
else if		(window.attachEvent)		window.attachEvent("onload", runOnLoad.run);
else									window.onload = runOnLoad.run;


/**
 *# XML.js
 */
if (XML == undefined) var XML = {};
/**
 * Create a new Document object. If no arguments are specified,
 * the document wil be empty, If a root tag is specified, the document
 * will contain that single root tag. If the root tag has a namespace
 * prefix, the second argument must specify the URL that identifies the
 * namespace.
 */
XML.newDocument = function(rootTagName, namespaceURL) {
	if (!rootTagName)	rootTagName		= "";
	if (!namespaceURL)	namespaceURL	= "";
	
	if (document.implementation && document.implementation.createDocument) {
		// This is the W3C standard way to do it
		return document.implementation.createDocument(namespaceURL, rootTagName, null);
	} else {	// This is the IE way to do it
		// Create an empty document as an ActiveX object
		// If there is not root element, this is all we have to do
		var doc = new ActiveXObject("MSXML2.DOMDocument");
		
		// If there is a root tag, initialize the document
		if (rootTagName) {
			// Look for a namespace prefix
			var prefix = "";
			var tagname = rootTagName;
			var p = rootTagName.indexOf(':');
			if (p != -1) {
				prefix	= rootTagName.substring(0, p);
				tagname	= rootTagName.substring(p+1);
			}
			
			// If we have a namespace, we must have a namespace prefix
			// If we don't have a namespaced, we discard any prefix
			if (namespaceURL) {
				if (!prefix) prefix = "a0";	// What Firefox uses
			}
			else prefix = "";
			
			// Create the root element (with optional namespace) as a
			// string of text
			var text = "<" + (prefix?(prefix+":"):"") + tagname + (namespaceURL?(" xmlns:" + prefix + '="' + namespaceURL + '"'):"") + "/>";
			// And parse that text into the empty document
			doc.loadXML(text);
		}
		return doc;
	}
};

/**
 * Parse the XML document contained in the string argument and return
 * a Document object that represents it.
 */
XML.parse = function(text) {
	if (typeof DOMParser != "undefined") {
		// Mozilla, Firefox, and related browsers
		return (new DOMParser()).parseFromString(text, "application/xml");
	} else if (typeof ActiveXObject != "undefined") {
		// Internet Explorer.
		var doc = XML.newDocument();	// Create an empty document
		doc.loadXML(text);				// Parse text into it
		return doc;						// Return it
	} else {
		// As a last resort, try loading the document from a data: URL
		// This si supposed to work in Safari.
		var url = "data:text/xml;character=utf-8," + encodeURIComponent(text);
		var request = new XMLHttpRequest();
		request.open("GET", url, false);
		request.send(null);
		return request.responseXML;
	}
}


/**
 *# DOM.js
 */
/**
 * make(tagname, attribute, children):
 *   create an HTML element with specified tagname, attributes, and children.
 *
 * The attributes argument is a Javascript object: the names and values of its
 * properties are taken as the names and values of the attributes to set.
 * If attributes is null, and children is an array or a string, the attributes
 * can be omitted altogether and the children passed as the second argument.
 *
 * The children argument is normally an array of children to be added to the 
 * created element. If there are no children, this argument can be omitted. If
 * there is only a single child, it can be passed directly instead of being
 * enclosed in an array. (But if the child is not a string and no attributes
 * are specified, an array must be used.)
 *
 * Example: make("p", ["This is a ", make("b", "bold"), " word."]);
 */
function make(tagname, attributes, children) {
	
	// If we were invoked with two arguments, the attributes argument is
	// an array or string; it should really be the children arguments.
	if (arguments.length == 2 && (attributes instanceof Array || typeof attributes == "string")) {
		children = attributes;
		attributes = null;
	}
	
	// Create the element.
	var e = document.createElement(tagname);
	
	// Set attributes.
	if (attributes) {
		for(var name in attributes) {
			if (name == "className")	e.className = attributes[name];
			else						e.setAttribute(name, attributes[name]);
		}
	}
	
	// Add children, if any were specified.
	if (children != null) {
		if (children instanceof Array) {	// If it really is an array
			for(var i = 0; i < children.length; i++) {	// Loop through children
				var child = children[i];
				if (typeof child == "string") child = document.createTextNode(child);	// Handle text nodes.
				e.appendChild(child);	// Assume anything else is a Node.
			}
		}
		else if (typeof children == "string") e.appendChild(document.createTextNode(children));	// Handle single text child.
		else e.appendChild(children);	// Handle any other single child.
	}
	
	// Finally, return the element.
	return e;
}

/**
 * maker(tag): return a function that calls maeke() for the specified tag.
 *
 * Example: var table = maker("table"), tr = maker("tr"), td = maker("td");
 */
function maker(tag) {
	return function(attrs, kids) {
		if (arguments.length == 1)	return make(tag, attrs);
		else						return make(tag, attrs, kids);
	}
}

/**
 * removeAllChildren(element): remove all children of the specified element.
 */
function removeAllChildren(element) {
	while (element.firstChild) element.removeChild(element.firstChild);
}


/**
 *# CSSClass.js
 */
/**
 * CSSClass.js: Utilities for manipulating the CSS class of an HTML element.
 *
 * This module defines a single global symbol named CSSClass. This object
 * contains utility functions for working with the class attribute (className
 * property) of HTML elements. All functions take two arguments: the element
 * e being tested or manipulated and the CSS class c that is to be tested,
 * added, or removed. If element e is a string, it is taken as an element
 * id and passed to document.getElementById().
 */
var CSSClass = {};	// Create our namespace object.

// Rerturn true if element e is a member of the class c; false otherwise.
CSSClass.is = function(e, c) {
	if (typeof e == "string") e = document.getElementById(e);	// element id.
	
	// Before doing a regexp search, optimize for a couple of common cases.
	var classes = e.className;
	if (!classes) return false;		// Not a member of any classes.
	if (classes == c) return true;	// Member of just this one class.
	
	// Otherwise, use a regular expression to search for c as a word by itself
	// \b in a regular expression requires a match at a word boundary.
	return e.className.search("\\b" + c + "\\b") != -1;
};

// Add class c to the className of element e if it is not already there.
CSSClass.add = function(e, c) {
	if (typeof e == "string") e = document.getElementById(e);	// element id.
	
	if (CSSClass.is(e,c)) return;	// If already a member, do nothing.
	if (e.className) c = " " + c;	// Whitespace separetor, if needed.
	e.className += c;				// Append the new class to the end.
};

// Remove all occurrences (if any) of class c from the className of element e
CSSClass.remove = function(e, c) {
	if (typeof e == "string") e = document.getElementById(e);	// element id.
	
	// Search the className for all occurrencew of c and replace with "".
	// \s* matches any number of whitespace characters.
	// "g" makes the regular expression match any number of occurrences.
	e.className = e.className.replace(new RegExp("\\b" + c + "\\b\\s*", "g"), "");
};


/**
 *# Geo.js
 */
var RPD = Math.PI/180;	// Radian per Degree
var RADIUS	= 6378.7;	// Radius of the earth

function radian(d) {
	return parseFloat(RPD)*parseFloat(d);
}

function distance(lat_f, lng_f, lat_t, lng_t) {
	// If theta>1 then acos returns NaN.
	var theta = Math.min((Math.sin(radian(lat_f)) * Math.sin(radian(lat_t)) + Math.cos(radian(lat_f)) * Math.cos(radian(lat_t)) * Math.cos(radian(parseFloat(lng_t)-parseFloat(lng_f)))), 1);
	return parseFloat(RADIUS) * Math.acos(parseFloat(theta));
}

function timeDifference(t_f, t_t) {
	var p = /^(\d{4})[^\d]+(\d{2})[^\d]+(\d{2})[^\d]+(\d{2})[^\d]+(\d{2})[^\d]+(\d{2})/;
	var t_fs = t_f.match(p);
	var m_f = Date.UTC(t_fs[1], (t_fs[2]-1), t_fs[3], t_fs[4], t_fs[5], t_fs[6]);
	var t_ts = t_t.match(p);
	var m_t = Date.UTC(t_ts[1], (t_ts[2]-1), t_ts[3], t_ts[4], t_ts[5], t_ts[6]);

	return (m_t - m_f) * 0.001;
}


/**
 *# Graphics.js
 */
/**
 * addRollover(img, rolloverURL):
 *   add a rollover effect to the specified image, by adding event
 *   handlers to switch the image to the specified URL while the mouse
 *   is over the image.
 *
 * This method sets onmouseover and onmouseout event-handler properties
 * of the specified image, overwriting and discardingany handlers 
 * previously set on those properties.
 */
function addRollover(img, rolloverURL) {
	var baseURL = img.src;
	(new Image()).src = rolloverURL;
	img.onmouseover	= function() { img.src = rolloverURL; }
	img.onmouseout	= function() { img.src = baseURL; }
}

/**
 * initRollovers():
 *   find all <img> and <input type="image"> tags in the document that
 *   have a "rollover" attribute on them.
 *
 * Use the value of this attribute as the URL of an image to be displayed
 * when the mouse passes over the image and set appropriate event handlers
 * to create the rollover effect.
 *
 * HTML example:
 * <img src="normalImage.gif" rollover="rolloverImage.gif" />
 * <input name="submit" type="image" src="normalImage.gif" rollover="rolloverImage.gif" />
 * * "rollover" is a NON-STANDARD attribute.
 */
function initRollovers() {
	var images = document.getElementsByTagName("img");
	for (var i = 0; i < images.length; i++) {
		var image = images[i];
		var rolloverURL = image.getAttribute("rollover");
		if (rolloverURL) addRollover(image, rolloverURL);
	}
	var inputs = document.getElementsByTagName("input");
	for (var i = 0; i < inputs.length; i++) {
		var input = inputs[i];
		if (input.getAttribute("type") == "image") {
			var rolloverURL = input.getAttribute("rollover");
			if (rolloverURL) addRollover(input, rolloverURL);
		}
	}
}

// Ensure that initRollovers() method is invoked when the document has loaded.
//runOnLoad(initRollovers);

/**
 * Enable and Disable buttons
 */
function enableImageButton(img, baseURL, rolloverURL, eventHandler) {
	img.src = baseURL;
	img.onmouseover	= function() { img.src = rolloverURL; };
	img.onmouseout	= function() { img.src = baseURL; };
	img.onclick		= eventHandler;
	img.style.cursor = "pointer";
}

function disableImageButton(img, baseURL) {
	img.src = baseURL;
	img.onmouseover	= null;
	img.onmouseout	= null;
	img.onclick		= null;
	img.style.cursor = "auto";
}


/**
 *# There is no independent file for this DateTime object and its methods.
 */
if (DateTime == undefined) var DateTime = {};

/**
 * This method set date to 0:00 of the date
 */
/*
DateTime.setMidnight = function(date) {
	return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0, 0);
};
*/

/**
 * This method formats Date object to "YYYY-MM-DD"
 */
DateTime.formatDate = function(date) {
	return date.getFullYear()+'-'+d2((parseInt(date.getMonth())+1))+'-'+d2(date.getDate());
};

/**
 * This method formats Date object to "YYYY-MM-DD HH:MM:SS"
 */
DateTime.formatDateTime = function(date) {
	return date.getFullYear()+'-'+d2((parseInt(date.getMonth())+1))+'-'+d2(date.getDate())+' '+d2(date.getHours())+':'+d2(date.getMinutes())+':'+d2(date.getSeconds());
};

/**
 * This method formats second to "HH:MM:SS"
 */
DateTime.formatTimeSec = function(sec) {
	sec = Math.round(sec);
	var s = sec % 60;
	var m = Math.floor(sec / 60);
	if (m < 60)		return d2(m) + ':' + d2(s);
	else			return d2(Math.floor(m / 60)) + ':' + d2(m % 60) + ':' + d2(s);
};


/**
 *# There is no independent file for these functions.
 */
/**
 * This function appneds '0' at the top of a digit as follows:
 * e.g. 0 -> '00', 1 -> '01', ..., 9 -> '09', 10 -> '10', ...
 */
function d2(n) { return ((n<10) ? "0" : "") + n.toString(); }


/**
 *# There is no independent file for this FormE object and its methods.
 */
if (FormE == undefined) var FormE = {};

/**
 * Replacement for getElementsByName
 * * getElementsByName does not work in IE.
 */
FormE.getElementsByNameIE = function(tag, name) {
	var tags = document.getElementsByTagName(tag);
	var names = [];
	for(var i = 0; i < tags.length; i++) { if(tags[i].getAttribute("name") == name) names.push(tags[i]); }
	return names;
};

/**
 * Create <input type="radio" /> with its name, value, and id specified.
 * If checked is set to true, its defaultChecked property is set.
 * Please note that this method sets onclick event handler
 * because in IE radio buttons created through DOM API are not able to be set!
 * This method more useful when you want to manipulate radio button directly,
 * for example, checking its status (checked or not).
 */
FormE.createRadio = function(name, value, id, checked) {
	var r = document.createElement("input");
	r.setAttribute("type", "radio");
	r.setAttribute("name", name);
	r.setAttribute("value", value);
	r.setAttribute("id", id);
	if (checked && (checked == true)) r.defaultChecked = true;
	r.onclick = function() {
		var rs = FormE.getElementsByNameIE("input", this.name);
		for(var i = 0; i < rs.length; i++) rs[i].checked = false;
		this.checked = true;
	};
	return r;
};

/**
 * Create <label> with its label specified and encapsulate the specified element e and associate with it.
 */
FormE.createLabel = function(e, label) {
	var l = document.createElement("label");
	l.setAttribute("htmlFor", e.id);
	l.appendChild(e);
	l.appendChild(document.createTextNode(label));
	return l;
};

/**
 * Create a pair of radio button and the associated label.
 */
FormE.createLabelRadio = function(name, value, id, label, checked) {
	var r = document.createElement("input");
	r.setAttribute("type", "radio");
	r.setAttribute("name", name);
	r.setAttribute("value", value);
	r.setAttribute("id", id);
	if (checked && (checked == true)) r.defaultChecked = true;
	r.onclick = function() {
		var rs = FormE.getElementsByNameIE("input", this.name);
		for(var i = 0; i < rs.length; i++) rs[i].checked = false;
		this.checked = true;
	};
	var l = document.createElement("label");
	l.setAttribute("htmlFor", id);
	l.appendChild(r);
	l.appendChild(document.createTextNode(label));
	return l;
};

/**
 * Create <input type="checkbox" /> with its name, value, and id specified.
 * If checked is set to true, its defaultChecked property is set.
 */
FormE.createCheckbox = function(name, value, id, checked) {
	var c = document.createElement("input");
	c.setAttribute("type", "checkbox");
	c.setAttribute("name", name);
	c.setAttribute("value", value);
	c.setAttribute("id", id);
	if (checked && (checked == true)) c.defaultChecked = true;
	return c;
};

FormE.createLabelCheckbox = function(name, value, id, label, checked) {
	var c = document.createElement("input");
	c.setAttribute("type", "checkbox");
	c.setAttribute("name", name);
	c.setAttribute("value", value);
	c.setAttribute("id", id);
	if (checked && (checked == true)) c.defaultChecked = true;
	var l = document.createElement("label");
	l.setAttribute("htmlFor", id);
	l.appendChild(c);
	l.appendChild(document.createTextNode(label));
	return l;
};


