var TIM_LIB_INCLUDED = true;
var WEB_ROOT = "";

var domSupport = (document.getElementById && document.getElementsByTagName && document.hasChildNodes);

var is_ie6 = (
	window.external &&
	typeof window.XMLHttpRequest == "undefined"
);

/****************************************
// General-purpose DOM utility functions
****************************************/
// When downloading data to populate a SELECT, it is often helpful to show a message
// in the SELECT and disable it.
// This function removes all children from the select s and adds a new option with the value 0
// and with the contents of message, and further disables the select
function makeSelectDisplayMessage(s, message) {
	while(s.hasChildNodes()) s.removeChild(s.firstChild);
	addNewOptionToSelect(s, 0, message);
	s.disabled = true;
}

function addNewOptionToSelect(s, val, label) {
	var newOpt = document.createElement("OPTION");
	newOpt.value = val;
	newOpt.appendChild(document.createTextNode(label));
	s.appendChild(newOpt);
}
// Gets the value of the currently-selected OPTION in the SELECT s
function getSelectedOptionValueOfSelect(s) {
	var val = null;
	if (s.selectedIndex >= 0) {
		var activeOption = s.options.item(s.selectedIndex);
		val = activeOption.value;
	}
	return val;
}

// For the given select, finds option val and makes it the currently selected  option
// Opposite of getSelectedOptionOfSelect
function makeThisValueSelected(select, val) {
	var i = getIndexOfOptionWithValue(select, val);
	if (i >= 0) {
		select.selectedIndex = i;
	}
}

// Returns the index of the OPTION element in the passed-in SELECT that has
// the value of "val". This can be used to select it or to get the name corresponding
// to the value, etc.
function getIndexOfOptionWithValue(select, val) {
	for (var i = 0; i < select.options.length; i++) {
		if (select.options[i].value == val) return i;
	}
	return -1;
}

/*
	Written by Jonathan Snook, http://www.snook.ca/jonathan
	Add-ons by Robert Nyman, http://www.robertnyman.com
	
	Some Ways To Call It

	To get all A elements in the document with a “info-links” class.
	getElementsByClassName(document, "a", "info-links");
	
	To get all DIV elements within the element named “container”, with a “col” class.
	getElementsByClassName(document.getElementById("container"), "div", "col");
	
	To get all elements within in the document with a “click-me” class.
	getElementsByClassName(document, "*", "click-me");
	
	The first line in the function is to cover-up for a flaw in IE 5 where one can’t use the wildcard selector * to get all elements.
*/
function getElementsByClassName(oElm, strTagName, strClassName){
	var arrElements = (strTagName == "*" && oElm.all)? oElm.all : oElm.getElementsByTagName(strTagName);
	var arrReturnElements = new Array();
	strClassName = strClassName.replace(/\-/g, "\\-");
	var oRegExp = new RegExp("(^|\\s)" + strClassName + "(\\s|$)");
	var oElement;
	for(var i=0; i<arrElements.length; i++){
		oElement = arrElements[i];
		if(oRegExp.test(oElement.className)){
			arrReturnElements.push(oElement);
		}
	}
	return (arrReturnElements)
}

// Removes all child nodes from a DOM element
// Arg: elm		- the node from which all children should be removed
function removeAllChildrenFrom(elm) {
	// This is one way to remove all children from a node
	// box is an object refrence to an element with children
	while (elm.firstChild) 
	 {
	    elm.removeChild(elm.firstChild);
	 }
}

// Returns a number 0+ that identifies the index into the
// list of TDs for that row
function getCellNumberFor(cell) {
	var allCells = cell.parentNode.getElementsByTagName("TD");
	for (var i = 0; i < allCells.length; i++) {
		if (allCells[i] == cell) return i;
	}
	return null; // bad news
}

function getRowNumberFor(cell) {
	var allRows = cell.parentNode.parentNode.getElementsByTagName("TR");
	for (var i = 0; i < allRows.length; i++) {
		if (cell.parentNode == allRows[i]) return i;
	}
	return null;
}

function getEventMouseCoords(e) {
	var posx = 0;
	var posy = 0;
	if (!e) var e = window.event;
	if (e.pageX || e.pageY) {
		posx = e.pageX;
		posy = e.pageY;
	}
	else if (e.clientX || e.clientY) {
		posx = e.clientX + document.body.scrollLeft
			+ document.documentElement.scrollLeft;
		posy = e.clientY + document.body.scrollTop
			+ document.documentElement.scrollTop;
	}
	// posx and posy contain the mouse position relative to the document
	// Do something with this information
	
	return {x: posx, y: posy};
}

// Finds and returns the coordinates of the argument obj
function findPosX(obj)
{
  var curleft = 0;
  if(obj.offsetParent)
      while(1) 
      {
        curleft += obj.offsetLeft;
        if(!obj.offsetParent)
          break;
        obj = obj.offsetParent;
      }
  else if(obj.x)
      curleft += obj.x;
  return curleft;
}

function findPosY(obj)
{
  var curtop = 0;
  if(obj.offsetParent)
      while(1)
      {
        curtop += obj.offsetTop;
        if(!obj.offsetParent)
          break;
        obj = obj.offsetParent;
      }
  else if(obj.y)
      curtop += obj.y;
  return curtop;
}

function getViewportDimensions() {
	var viewportwidth;
	 var viewportheight;

	 // the more standards compliant browsers (mozilla/netscape/opera/IE7) use window.innerWidth and window.innerHeight

	 if (typeof window.innerWidth != 'undefined')
	 {
	      viewportwidth = window.innerWidth,
	      viewportheight = window.innerHeight
	 }

	// IE6 in standards compliant mode (i.e. with a valid doctype as the first line in the document)

	 else if (typeof document.documentElement != 'undefined'
	     && typeof document.documentElement.clientWidth !=
	     'undefined' && document.documentElement.clientWidth != 0)
	 {
	       viewportwidth = document.documentElement.clientWidth,
	       viewportheight = document.documentElement.clientHeight
	 }

	 // older versions of IE

	 else
	 {
	       viewportwidth = document.getElementsByTagName('body')[0].clientWidth,
	       viewportheight = document.getElementsByTagName('body')[0].clientHeight
	 }
	return {width: viewportwidth, height: viewportheight};
}

//
// suppressSpecialKeys
//
// Designed to be an event handler; returns false if a special key is pressed
// Remember to use onkeypress for Firefox to ensure that the event is suppressed
// onkeyup/down won't work
//
function suppressSpecialKeys(e) {
    var targ; // the INPUT that was downed
	if (!e) var e = window.event;
	
	switch(e.keyCode) {
		case 13: // enter
		case 37: // left
		case 38: // up
		case 39: // right
		case 40: // down
			return false;
		default:
			return true;
	}
}

//
// suppressSubmitKeys
//
// Designed to be an event handler; returns false if a key is pressed that would submit a form
// Remember to use onkeypress for Firefox to ensure that the event is suppressed
// onkeyup/down won't work
//
function suppressSubmitKeys(e) {
	var targ; // the INPUT that was downed
	if (!e) var e = window.event;
	
	switch(e.keyCode) {
		case 13: // enter
			return false;
		default:
			return true;
	}
}

//
// Gets the correct object to do AJAX requests with; or returns false if we can't
//
function getReq() {
	var req;
	
	if (window.XMLHttpRequest) {
		try {
			req = new XMLHttpRequest();
		}
		catch(e) {
			req = false;
		}
	}
	else if (window.ActiveXObject) {
		try {
			req = new ActiveXObject("Msxml2.XMLHTTP");
		}
		catch(e) {
			try {
				req = new ActiveXObject("Microsoft.XMLHTTP");
			}
			catch(e) {
				req = false;
			}
		}
	}
	return req;
}

//
// From http://www.codeproject.com/KB/scripting/dateformat.aspx
//	Date formatting function; adds on to the Date global object
//
// Format string matches ColdFusions format method (except n is used for minutes)
//


// a global month names array

var gsMonthNames = new Array(
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December'
);
// a global day names array

var gsDayNames = new Array(
'Sunday',
'Monday',
'Tuesday',
'Wednesday',
'Thursday',
'Friday',
'Saturday'
);
// the date format prototype

Date.prototype.format = function(f)
{
    if (!this.valueOf())
        return 'Invalid Date';

    var d = this;

    return f.replace(/(yyyy|mmmm|mmm|mm|m|dddd|ddd|dd|d|hh|h|nn|ss|a\/p|tt|t)/gi,
        function($1)
        {
            switch ($1.toLowerCase())
            {
            case 'yyyy': return d.getFullYear();
            case 'mmmm': return gsMonthNames[d.getMonth()];
            case 'mmm':  return gsMonthNames[d.getMonth()].substr(0, 3);
            case 'mm':   return zf(d.getMonth() + 1, 2);
            case 'm':    return (d.getMonth() + 1);
            case 'dddd': return gsDayNames[d.getDay()];
            case 'ddd':  return gsDayNames[d.getDay()].substr(0, 3);
            case 'dd':   return zf(d.getDate(),2);
			case 'd':    return d.getDate();
			case 'h':
            case 'hh':
			             var h = d.getHours();
			             if (/(tt|t)/i.test(f)) {
							if(h > 12) {
				               h = h % 12;
							}
							else if (h == 0) {
								h = 12;
							}
			             }
			             return zf(h, $1.length);
            case 'nn':   return zf(d.getMinutes(),2);
            case 'ss':   return zf(d.getSeconds(),2);
            case 't':
            case 'a/p':  return d.getHours() < 12 ? 'A' : 'P';
            case 'tt':   return d.getHours() < 12 ? 'AM' : 'PM';
            }
        }
    );
}

//
// Pads zeroes to the front of Number n until total length is digits
//
// zf(34, 5) returns "00034"
//
function zf(n, digits) {
	var str = Number(n)+"";
	var zeroesNeeded = digits - str.length;
	if (zeroesNeeded <= 0) {
		return str;
	}
	else {
		for (i = 0; i < zeroesNeeded; i++) {
			str = "0"+str;
		}
	}
	return str;
}

//
// Returns true if argument str is a valid time
//
// 24-hour format available, but only if AM/PM not specified
//
// Returns a boolean: true if string is a valid time, or false if not
//
function validateTimeString(str) {
	execArr = /^ *([012]?[0-9]):[0-5][0-9](:[0-5][0-9])?( +(AM|PM))? *$/i.exec(str);
	
	if (execArr && execArr.length > 0) {
		// array element will be null/undefined if not matched at all
		if (execArr[4] && execArr[4].length > 0) {
			// AM/PM specified; make sure hours are ≤ 12
			if (execArr[1] > 12) {
				return false;
			}
			else {
				return true;
			}
		}
		else if (execArr[1] < 24){
			return true;
		}
		else {
			return false;
		}
	}
	else {
		return false;
	}
}

//
// convert a string to lowercase with 1st letter capitalised
//
function ucFirst(s)
{
	var c = s.charAt(0);

	if (parseInt(s.length)==1){
		return c.toUpperCase();
	}
	else
	{
		return c.toUpperCase() + s.slice(1).toLowerCase();
	}
}

/*
 * OrdinalNumberFormat()
 *
 * Formats a given number with an ordinal suffix (e.g. 1 -> 1st, 2 -> 2nd)
 */
function OrdinalNumberFormat(n) {
	var suffix = "th";
	switch(n % 10) {
		case 3:
			suffix = "rd";
			break;
		case 2:
			suffix = "nd";
			break;
		case 1:
			suffix = "st";
			break;
		default:
			suffix = "th";
	}
	return n + suffix;
}

/*
 * ImperialDistanceBetween()
 *
 * Finds the distance in miles between two points on earth using the Haversine formula
 */
function ImperialDistanceBetween(lat1, lng1, lat2, lng2) {
		// From http://www.faqs.org/faqs/geography/infosystems-faq/
		// Using formula R (in km) = 6378 - 21 * sin(lat)
		// lat = 37
		var R =  3963.0 // miles
		
		var dlon = (lng2 - lng1)*(Math.PI/180);
		var dlat = (lat2 - lat1)*(Math.PI/180);
		var l2rads = lat2*(Math.PI/180);
		var l1rads = lat1*(Math.PI/180);
		
		// from http://www.faqs.org/faqs/geography/infosystems-faq/ (haversine formula)
		var a = Math.pow(Math.sin(dlat/2),2) + Math.cos(l1rads) * Math.cos(l2rads) * Math.pow(Math.sin(dlon/2),2);
		var c = 2 * Math.asin(Math.min(1,Math.sqrt(a)));
		var d = R*c;
		
		return d;
}

/*************************************

				MAPS SUPPORT FUNCTIONS

**************************************/

function getLocationIcon(color) {
	// Create our "tiny" marker icon
	var icon = new google.maps.Icon(G_DEFAULT_ICON);
	icon.image = getLocationImage(color);
	//icon.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png";
	//icon.iconSize = new google.maps.Size(12, 20);
	//icon.shadowSize = new google.maps.Size(22, 20);
	//icon.iconAnchor = new google.maps.Point(6, 20);
	//icon.infoWindowAnchor = new google.maps.Point(5, 1);
	
	return icon;
}

function getLocationImage(color) {
	return WEB_ROOT+"/images/marker_"+color+".png";
}
