//
// Copyright 2006-2008, Digital Recorders
//

//<![CDATA[

String.prototype.trim = function() {
        return this.replace(/^\s+|\s+$/g,"");
}

String.prototype.equalsIgnoreCase = function(str) {
	if (exists(str))
		return this.toLowerCase() === str.toLowerCase();
	else
		false;
}

String.prototype.compareToIgnoreCase = function(str) {
	
	if (!exists(str))
		return 1;

  var s1 = this.toLowerCase(), s2 = str.toLowerCase();
  
  if (s1 < s2)
	return -1;
  else if (s1 > s2)
	return 1;
  else
	return 0;
}

String.prototype.count = function(separator) {
	return (this.length - this.replace(new RegExp(separator,"g"), '').length) / separator.length;
}

if (!Array.indexOf && !Array.prototype.indexOf) {
	Array.prototype.indexOf = function (obj) {
		for (var i=0; i<this.length; i++) {
			if (this[i] == obj)
				return i;
		}

		return -1;
	}	
}

//******************************************************************************
// Constants
var   QUADRANT_HEIGHT_BUFFER = 7;  // Value to be taken off of the quadrant size calculated.

//**********************************************************************************************************************************************************************************
// ATTRIBUTES
var        browserTimeWindows  = null;            // Empty reference to object array mapping Route IDs to their current Time Regimes.
var          otviaTimeWindows  = null;            // Object array mapping Route IDs to their current Time Regimes.
var        routesSelectedList  = [];
var 	selectedRouteLogNums   = [];
var 	suppressedRouteLogNums = [];
var                xmlMenuDoc  = new Object();    // Empty object reference to hold XML file contents defining the Route List Sub-Menus (if there are any).
var              menusByRoute  = [];         	// Empty array reference to hold XML file contents from each "route" element.
var               menusByMenu  = [];         	// Empty array reference to hold XML file contents from a "menu" child element of a given "route" element.
var               menusByItem  = [];         	// Empty array reference to hold XML file contents from a "menu-item" child element of a given "menu" element.
var        otviaServletStatus  = "RESTART";
var      browserServletStatus  = "OK";
var         otviaServletCycle  = 0;
var        statusErrorMessage  = "OTvia reports the connection to the data server has been interrupted.  This is usually temporary.  ";
           statusErrorMessage += "OTvia is attempting to reconnect, which takes about a minute.  The browser display should update automatically once reconnected.  ";
           statusErrorMessage += "You may wait, or sign off and come back later. ";
var       regimeChangeMessage  = "A Transit Service change has occurred due to the current Date/Time.  Certain Routes and/or Timetables have been adjusted accordingly.  \n";
          regimeChangeMessage += "YOU SHOULD DE-SELECT AND THEN RE-SELECT ANY ROUTES YOU HAVE CHOSEN TO DISPLAY, FOR THESE CHANGES TO TAKE EFFECT.";
var                       map  = null;            // Google Map
var					mapCenter;
var			currentCenterOfMap;
var                     isIE6  = false;           // IE6 flag
var          IEMapWidthFactor  = 328;             // Value in pixels of amount of screen width used by the other GUI elements. *
var         IEMapHeightFactor  = 156;             // Value in pixels of amount of screen height used by the other GUI elements. *
var   IERouteListHeightFactor  = 177;             // Value in pixels of amount of screen height used by the other GUI elements. *
var           IEMapLeftOffset  = 42;              // Value in pixels of amount of screen width used by other GUI elements TO THE LEFT OF THE MAP BODY ONLY.
var                 mapIsWide  = false;           // Flag indicating whether or not user has expanded the width of the map over the Route List panel.
var         serverTimeTimerID  = 0;               // the timer ID for the Time event
var             statusTimeout  = 60000;           // timeout for status query
var              alertTimeout  = 30000;           // timeout for Alert query
var             routeIDString  = "";              // keep the route id string globally
var         routeIDListString  = "";              // keep the list of route id string globally for seleting all routes
var stringRoutesToBeSuppressed = "";
var      cookieAlertTagString  = "OTvia2.Alert";  // Name prefix for Alert Cookies, to facilitate their programmatic identification.
var            alertFlowState  = undefined;       // The current state of the Alert Flow Interaction screen.
var              isPageLoading = false;
var lastVehicleHttpRequestTime = 0;
var lastShelterHttpRequestTime = 0;
var             stopSearchFlag = false;
var                  imagepath = "images";
var             imageExtension = ".png";
var				emptyOverlay;						// Empty GMap overlay to xform LatLng to px
var						mapType = null;
var 				currentZoom = null;
var				activeShelterId = 0;
var						kmlLayer = null;
var				isRouteChecked = false;
var 			arrayOfKMLLayers = [];
var				currentServerTime = null;
var			isMinorSheltersMode = false;
var	otviaLabelDeltaMinutesUpdates = [];
    			                    

//**********************************************************************************************************************************************************************************
// ARRAYS

var vehicleArray            = [];
var shelterArray            = [];
var sortedShelterArray		= []; // shelter array sorted by shelter name
var shelterGroupArray       = [];
var arrayOfShelterGroupArray = [];
var shelterSearchListArray  = [];
var selectedRouteIDs		= []; // used only in IE
var poolOfAvailableShelters	= [];
var availableMarkers = [];
var availableLabels = [];

//**********************************************************************************************************************************************************************************
// OBJECTS
//

//
// Vehicle Object
//
function Vehicle(vehicleID)
{
    this.vehicleID        = vehicleID;
    this.visualOrder      = 4;

    this.filtered         = false;
    
    //
    // Updates for label refactoring code
    //
    this.marker           = null;
    this.quadrant         = 0;
    this.label            = null;
    this.labelID          = "labelVehicle" + vehicleID;
    this.labelClassName   = "labelVehicleTooltip";
    this.labelOffset      = null;
    this.labelText        = null;

    //
    // Location for label per object.
    //
    this.quadOffset1      = new google.maps.Size(-319,-21);
    this.quadOffset2      = new google.maps.Size(11,-21);
    this.quadOffset3      = new google.maps.Size(11, -80);
    this.quadOffset4      = new google.maps.Size(-319,-80);
    
    // Difference between anchored center of marker and where the GxLabel
    // will display.
    this.labelHeightOffset = 8;
}

//
// Shelter Object
//

Shelter.onTopZIndex = 3;

function Shelter(shelterID,shelterName)
{
    this.shelterID        = shelterID;
    this.visualOrder      = 1;
    
    this.shelterName      = shelterName;
    
    this.grouped          = false;
    this.minor			  = false;
    
    this.xScreen          = 0;
    this.yScreen          = 0;
    
    //
    // Updates for label refactoring code
    //
    this.marker           = null;
    this.quadrant         = 0;
    this.label            = null;
    this.labelID          = "labelShelter" + shelterID;
    this.labelClassName   = "labelShelterTooltip";
    this.minorLabelClassName = "labelShelterMinorTooltip";
    this.labelOffset      = null;
    this.labelText        = null;
    this.newText          = null;

    //
    // Location for label per object.
    //
    this.quadOffset1      = new google.maps.Size(-381,-34);
    this.quadOffset2      = new google.maps.Size(9,-34);
    this.quadOffset3      = new google.maps.Size(9, -77);
    this.quadOffset4      = new google.maps.Size(-381,-77);

    // Difference between center of marker and center of label
    // will display.
    this.labelHeightOffset = 14;

    this.parent           = null;
    
    this.lat              = 0;
    this.lon              = 0;
    
    this.routeIDs = [];
}

Shelter.prototype.ensureLabel = function() {
	if (!this.marker) {
		// no marker...just set marker/label and hide them 
		this.setVisible(true);
		this.marker.setVisible(false);
		this.label.hide();
	}
}

Shelter.prototype.setVisible = function(show) {
	
	if (show) {
		if (this.marker) {
			this.marker.setPosition(this.position);
			this.marker.setIcon(this.minor ? minorShelterIcon : shelterIcon);
			this.marker.setVisible(true);
			this.label.setAnchor(this.position);
			//this.label.shelterID = this.shelterID;
			itemLabelUpdate(this, this.labelText, this.minor ? this.minorLabelClassName : this.labelClassName);
		} else {
			// attach marker & label
			this.marker = availableMarkers.pop();
			if (!this.marker) {
			    var m = new google.maps.Marker(
	    	    {position: this.position,
	    	    map: map,
	    	    icon: (this.minor ? minorShelterIcon : shelterIcon),
	    	    flat: true,
	    	    zIndex: this.visualOrder});
	    	
	    	    //assign the new marker
	    	    this.marker = m;
	    	
	    	    this.marker.setMap(map);
	    	    m = null;
	    		// create shelter label
	    	    itemLabelController(this, this.labelText, this.position, false, this.minor ? this.minorLabelClassName : this.labelClassName);
			} else {
				this.marker.setPosition(this.position);
				this.marker.setVisible(true);
				this.marker.setIcon(this.minor ? minorShelterIcon : shelterIcon);
				this.label = availableLabels.pop();
				this.label.setAnchor(this.position);
				//this.label.shelterID = this.shelterID;
				itemLabelUpdate(this, this.labelText, this.minor ? this.minorLabelClassName : this.labelClassName);
			}
		}		
	} else {
		if (this.marker) {
			// detach marker & label from this shelter
			this.marker.setVisible(false);
			this.label.hide();
			
			availableMarkers.push(this.marker);
			availableLabels.push(this.label);
			
			this.marker = null;
			this.label = null;
		}
	}
	
}

Shelter.prototype.labelClosed = function() {
	jsShelterLabelController(this.shelterID, false, true);

	// hide marker if necessary
	if (this.marker && this.marker.getZIndex() == Shelter.onTopZIndex) {
		this.marker.setZIndex(this.visualOrder);
		this.marker.setVisible(false);		
	}
}

Shelter.prototype.updateShelterGroupIconAndStickLabel = function() {

	var currentShelterGroup = this.parent;
    if (currentShelterGroup) {

    	// we are in a group...now check if group has an active label

	    if (currentShelterGroup.isShelterLabelActive) {
	    	var activeShelter = shelterArray[currentShelterGroup.activeShelterLabelID];
	    	if (activeShelter && activeShelter.label) {
	    		// found the active label .. close it by calling close icon handler
	    		activeShelter.label.mClose()();
	    	}
	    }
	    // show the Shelter label and stick it and update shelter group icon
	    jsShelterLabelController(this.shelterID, true, true);	    
    } else {
    	// we're solo...simply stick the label
    	if (this.label)
    		this.label.stickIt();
    }
    
}


//
// Shelter Search List item
//
function ShelterSearchListItem(id, name)
{
    this.id               = id;
    this.name             = name;
}

//
// Shelter Group Object
//
function ShelterGroup() {
    this.visualOrder        = 2;
    this.shelters           = [];    
    //
    // Updates for label refactoring code
    //
    this.marker             = null;
    this.quadrant           = 0;
    this.label              = null;
    this.labelID            = null;
    this.labelClassName     = "labelShelterGroupTooltip";
    this.minorLabelClassName = "labelShelterGroupMinorTooltip";
    this.labelText          = null;
    
    //
    // Location for label per object.
    //
    this.quadOffset2        = new google.maps.Size(-216,-34);
    this.quadOffset1        = new google.maps.Size(9,-36);
    this.quadOffset4        = new google.maps.Size(9, -77);
    this.quadOffset3        = new google.maps.Size(-216,-77);

    // Difference between anchored center of marker and where the GxLabel
    // will display.
    this.labelHeightOffset = 14;

    this.isShelterLabelActive = false;
    this.activeShelterLabelID = null;
}

ShelterGroup.prototype.isMinor = function () {
	for (var i=0; this.shelters && i<this.shelters.length; i++) {
		if (this.shelters[i] && !this.shelters[i].minor)
			return false;		
	}
	
	return true;
}



//
// This is used to hold onto the Route listings of an agency. There is also
// the flag embeded that tells this interface if the route is visible or
// not. As this is toggled the value here is updated.
//
var routeArray          = [];

//
// RouteLayer Object
//
function RouteLayer(routeID)
{
    this.routeID = routeID;    
    this.polyLines = [];
}

var jsRouteLayers       = [];

//
// Vehicle Icon
//
var vehicleIcon              =  "images/vehicle_icon.png";

//
// Shelter Icon
//
var shelterIcon              = "images/shelter_icon.png";
var minorShelterIcon         = "images/minor_shelter_icon.png";

//
// Shelter Group Icon
//
var shelterGroupIcon         = "images/multi_shelter_icon.png";
var minorShelterGroupIcon    = "images/minor_multi_shelter_icon.png";

//**********************************************************************************************************************************************************************************
// FUNCTIONS

//..................................................................................................................................................................................
// addMapRouteLayers - Adds the current jsRouteLayers to the
//                     map. This was implemented to help with 
//                     the asynchronous call to updateRouteLayer above.
function addMapRouteLayers(routeID)
{
	// due to the delay between click on checkbox and actual receipt of route layer data
	// we have to check if the route is still selected
	var hideIt = !document.getElementById(routeID).checked;
    for (var z = 0 ; z < jsRouteLayers[routeID].polyLines.length; ++z) 
    {
        jsRouteLayers[routeID].polyLines[z].setMap(map);
        if (hideIt)
        	jsRouteLayers[routeID].polyLines[z].setOptions({strokeOpacity:0});
    }
}

function showMapRouteLayers(routeID)
{
    for (var z = 0 ; z < jsRouteLayers[routeID].polyLines.length; ++z) 
    {
        jsRouteLayers[routeID].polyLines[z].setOptions({strokeOpacity:1});
    }
}

//..................................................................................................................................................................................
// getJSONStatus - Verifies the operating status of the servlet environment, and responds accordingly.
function getJSONStatus(data, responseCode)
{
    //set the timer
    setTimeout(updateStatus, statusTimeout);
    
    if (responseCode == "success")
    {
        var json = eval('(' + data + ')');
        if(otviaTimeWindows == null)
        {
            otviaTimeWindows = [];
        }
        otviaTimeWindows = json.StatusFlags.OTviaTimeWindows;
        otviaServletStatus = json.StatusFlags.OTviaServletStatus;

        // Currently only two status states -- "OK" and "ERROR"; may eventually need to expand this as a switch statement.
        if (otviaServletStatus != browserServletStatus) 
        {
            // Simple counter of Servlet refresh events; accessible through a JavaScript debugger such as FireBug or Drosera.
            otviaServletCycle++;
            browserServletStatus = otviaServletStatus;
            
            // Transitioning from OK status to RESTART status.
            if (otviaServletStatus == "RESTART") 
            {
                document.getElementById("otviaDRAVLServerStatus").style.display = ("block");
                document.getElementById("otviaDRAVLServerStatusMsg").style.display  = ("block");
                jQuery(".user-links-div").hide();
            }
            // Must be transitioning from RESTART status to OK status.
            else
            {
                document.getElementById("otviaDRAVLServerStatus").style.display = ("none");
                document.getElementById("otviaDRAVLServerStatusMsg").style.display  = ("none");
                jQuery(".user-links-div").show();
            }
        }
        
        //  Force initialization of browserTimeWindows on first status update.  Take no other action.
     
        if (browserTimeWindows != null && browserTimeWindows.length == otviaTimeWindows.length)
        {
            for (var k in otviaTimeWindows)
            {
                if (otviaTimeWindows[k].RouteTimeWindow != browserTimeWindows[k].RouteTimeWindow )
                {
                	if (!suppressRouteID(otviaTimeWindows[k].RouteID)) {

                		if (kmlURLPrefix) {
                			// remove all kmlLayers that contain this routeID
                			for (var x in arrayOfKMLLayers) {
                				if ((x+"").indexOf(otviaTimeWindows[k].RouteID) != -1) {
                					GLog.write("getJSONStatus() ... KML layer removed for "+x);
                					arrayOfKMLLayers[x] = null;
                				}
                			}                			
                		} else {
                			jsRouteLayers[otviaTimeWindows[k].RouteID].polylines = [];                			
                		}
                		
                		// if this route is currently showing then redisplay it
                		if (document.getElementById(otviaTimeWindows[k].RouteID).checked) {
                			routeCheckBoxClicked(otviaTimeWindows[k].RouteID);
                		}
                    }
                }
            }
        }
        // Initialize or update browserTimeWindows[].  This object array mirrors the most recently received version of otviaTimeWindows[].
        if(browserTimeWindows == null)
        {
            browserTimeWindows = [];
        }
        //        browserTimeWindows = otviaTimeWindows.slice(0);
        for (var k in otviaTimeWindows)
        {
            browserTimeWindows[k] = otviaTimeWindows[k];
        }
    }
}

function getJSONAlerts(data, responseCode)
{    
    if (responseCode == "success") {
        var json = eval('(' + data + ')');
        
        if (json && json.Alerts) {
        	for (i=0; i<json.Alerts.length; i++) {
        		if (json.Alerts[i] != undefined)
        			alert(json.Alerts[i].msg);
                        
                    //
                    // Reload the Alerts Drawer with current data.
                    //
                    getEditAlerts();
        	}
        }
    }
}

//..................................................................................................................................................................................
// getJSONTime - Gets the current Day of Week, Date, and Time from the OTvia server.
function getJSONTime(data, responseCode)
{    
    if (responseCode == "success") {
        var json = eval('(' + data + ')');
        
        currentServerTime = json.OTviaServerTime;
        
        var oDOW = currentServerTime.dow;
        var oTime = currentServerTime.time + " " + agencyTimeLabel;
        var oDate = currentServerTime.date;
        
        jQuery("#oDOW").html(oDOW);
        jQuery("#oDate").html(oDate);
        jQuery("#oTime").html(oTime);
        
        // update dM in OtviaLabels
        for (var i in otviaLabelDeltaMinutesUpdates) {
        	if (otviaLabelDeltaMinutesUpdates[i])
        		otviaLabelDeltaMinutesUpdates[i]();
        }        
    }
}

//
// Function to sort the routeArray via the name of the route
//
function routeArraySort(a, b) {
  function chunkify(t) {
    var tz = [], x = 0, y = -1, n = 0, i, j;

    while (i = (j = t.charAt(x++)).charCodeAt(0)) {
      var m = (i == 46 || (i >=48 && i <= 57));
      if (m !== n) {
        tz[++y] = "";
        n = m;
      }
      tz[y] += j;
    }
    return tz;
  }

  var aa = chunkify(a.Route.Name);
  var bb = chunkify(b.Route.Name);

  for (x = 0; aa[x] && bb[x]; x++) {
    if (aa[x] !== bb[x]) {
      var c = Number(aa[x]), d = Number(bb[x]);
      if (c == aa[x] && d == bb[x]) {
        return c - d;
      } else return (aa[x] > bb[x]) ? 1 : -1;
    }
  }
  return aa.length - bb.length;
}

//..................................................................................................................................................................................
// getJSONRoute - Generates the HTML code for displaying/hiding the Route
//                layers for a given agency.
function getJSONRoute(data, responseCode)
{
    var routeBodyContent = "";

    if (responseCode == "success")
    {
        var json = eval('(' + data + ')');
        routeIDString = "";  // global string to list the active routes.
        stringRoutesToBeSuppressed = "";
        routeArray = json.RouteArray;
        
        // if we did not get any routes then..wait for a few seconds and retry
        // Otvia may not have completed the database query to get all the routes
        if (routeArray.length <= 0) {
        	setTimeout("updateRoute()", 5000);
        	return;
        }

        routeArray = fixRouteArray(routeArray);
        
        //
        // Here we'll sort the array by name and display this way.
        //
        routeArray.sort(routeArraySort);
        
        if (routeView) {
//        	areAllRoutesSelected = true;

        	// if in a route view then discard routes not in the view
	        var tmpRouteArray = [];
	
	        for (var x = 0 ; x < routeArray.length; ++x) {
	        	
	        	var route = routeArray[x].Route;	        
		        
		        if (route) {
		        	if (routeView.logNums.indexOf(route.LogNum) != -1) {
		        		tmpRouteArray.push(routeArray[x]);
		        		continue;
		        	}
		        }
	        }
	        
	        routeArray = tmpRouteArray;
        }
        

        //
        // NOTE: Adding Prototype Iterator loop
        //
        zIndex = 1000;
        routeBodyContent += "<ul>";
        for (var x = 0 ; x < routeArray.length; ++x)
        {
            //
            // XXX: BIG NOTE HERE!!!!!
            //
            // Objects being pushed up into the JavaScript code here are case sensitive.
            // If you type in the wrong value of the variable, the JavaScript interpretor
            // will allow this and simply create the new attribute of the object and
            // not what you're looking for.
            //
            // REMEMBER THIS!!!!
            //
            var route = routeArray[x].Route;
                        
            //
            // The route is good now lets pull in the data to generate
            // the route list.
            //
            // Note introduction and use of zIndex and zIndex2 below.
            //   Every element must be given an appropriately sequenced z-index value to make IE6 & 7 mimic standards-based behavior.
            if (route)
            {
                routeBodyContent += "<div class='routeListItem' style='z-index:" + zIndex + "'>";
                routeBodyContent += "<li style='z-index:" + zIndex + "'>";
                routeBodyContent += "<div class='routeCheckbox' style='z-index:" + zIndex + "'><input type='checkbox' id='"+ route.RouteID +"' value='" + route.RouteID + "'";
                routeBodyContent += "     onClick='routeCheckBoxClicked(" + route.RouteID + ");'";
                
                if (routeView) {
                	//routeBodyContent += " checked='true'";                	
                }
                                
                routeBodyContent += "></div>";
                routeBodyContent += "<div class='routeColor' style='z-index:" + zIndex + "; background-color: #" + route.ColorRoute + ";'></div>";
                routeBodyContent += "<div class='routeDesc' style='z-index:" + zIndex + "'>";
                routeBodyContent += "<div class='routeName' id='label" + zIndex + "' style='z-index:" + zIndex + "'>" + route.Name + "</div>";
                var zIndex2 = zIndex + 1000;  // Raise zIndex for the sub-menu panel.  Note carefully how zIndex and zIndex2 are used in the next two lines.
                if (haveRouteMenus)
                {
                    for (var a = 0; a < menusByRoute.length; a++)
                    {
                    	var nameElem = menusByRoute[a].getElementsByTagName("name")[0];
                    	var routeIdElem = menusByRoute[a].getElementsByTagName("routeID")[0];
                        nameIndex = a;
                        if ((nameElem && nameElem.childNodes[0].nodeValue.toLowerCase() == route.Name.toLowerCase()) ||
                        		(routeIdElem && routeIdElem.childNodes[0].nodeValue == route.LogNum.toString()))
                        {
                            routeBodyContent += "<div class='routeExpander' style='z-index:" + zIndex + "'";
                            routeBodyContent += "     onmouseover='showRouteSubMenu(" + zIndex2 + ")'; onmouseout='hideRouteSubMenu(" + zIndex2 + ")';";
                            routeBodyContent += ">";
                            routeBodyContent += "<img src='images/menu_selector_normal.gif' id='icon" + zIndex2 + "' />";
                            routeBodyContent += getOptionsList(nameIndex, zIndex2);
                            routeBodyContent += "</div>";  // End class routeExpander.
                            break;
                        }
                    }
                }
                routeBodyContent += "</div>";  // End class routeDesc
                routeBodyContent += "</li>";
                routeBodyContent += "</div>";  // End class routeListItem.
                routeBodyContent += "<div class='clear'></div>";
                zIndex -= 10;
                
                //
                // Update/Create the entry for this route in the Route Layer
                // array.
                //
                jsRouteLayers[route.RouteID] = new RouteLayer(route.RouteID);                
            }
        }
        routeBodyContent += "<div>&nbsp;</div><div>&nbsp;</div><div>&nbsp;</div><div>&nbsp;</div><div>&nbsp;</div>";  // Provide spacer at bottom so that final Route submenus will show in a space that the user can scroll into view.
        routeBodyContent += "</ul>";
    }
        
    //
    // Once the routeBodyContent has been update, we now need to update
    // the document with its new value.
    //
    jQuery("div#routes").html(routeBodyContent);

    //
    // Make sure the Accordion re-sizes properly upon route list population
    resizeAccordion();
    
    updateRouteIDString();
    routeIDListString = routeIDString;
    
    getEditAlerts();
    
    setTimeout(showVehiclesFirst, 100);
    //updateVehicle(); // show all vehicles first
    
    // after 1 secs show all shelters
    //setTimeout(executeThisFuncLater(jQuery.get, "packet/json/shelter", createSheltersFromJSON), 1000);
    
    if (selectAllRoutesCheckBoxActive)
    {
        if (areAllRoutesSelected){
            document.getElementById("allRoutesCB").checked = true;
            onClickAllRoutes(true);
            GLog.write("**************** all routes selected ******************");
        } else {
        	// bug in FF - after page reload this checkbox remains checked
        	document.getElementById("allRoutesCB").checked = false;        	
        }
    }
}

function showVehiclesFirst() {
	var data = jQuery.ajax({
        url: "packet/json/vehicle?routes=" + getRouteIDsForHTTPRequest() + "&lastVehicleHttpRequestTime=" + lastVehicleHttpRequestTime + "&forceUpdate=true",
        async: false
    }).responseText;

	getJSONVehicle(data, "success");
	
	setTimeout(executeThisFuncLater(jQuery.get, "packet/json/allshelters", createSheltersFromJSON), 100);
}

function showRouteLayers() {
	GLog.write("...in showRouteLayers()");
    for (var r = 0 ; r < routeArray.length ; r++)
    {
        toggleRouteLayer(routeArray[r].Route.RouteID, true, true);
    }
    
    if (!allStopsShowing)
    	showSelectedRoutes();
}

//..................................................................................................................................................................................
function getJSONRouteLayer(data, statusText)
{
	// GLog.write("########### getJSONRouteLayer "+statusText);
    if (statusText == "success")
    {
        var json = eval('(' + data + ')');
        var routeLayerArray = json.RouteLayerArray;
        
        for (var x = 0 ; x < routeLayerArray.length; ++x)
        {
            var routeLayer = routeLayerArray[x].RouteLayer;
            
            if (!routeLayer) {
                continue;
            }
            
            var polyLines = [];
            
            for (var y = 0 ; y < routeLayer.LayerArray.length; ++y)
            {
                var layer = routeLayer.LayerArray[y].Layer;
                
                if (!layer) {
                    continue;
                }
                
                var vertCount = 0;
                var verticies = [];
                
                for (var z = 0 ; z < layer.CoordArray.length; ++z)
                {
                    var coordinate = layer.CoordArray[z].Coordinate;
                    
                    if (!coordinate) {
                        continue;
                    }
                
                    //
                    // Create Polyline for Google Maps.
                    //
                    verticies[vertCount++] = new google.maps.LatLng(coordinate.Latitude / 100000, -coordinate.Longitude / 100000);
                }
                var varPolyLine = new google.maps.Polyline({map:map,path:verticies,strokeColor:"#" + routeLayer.ColorRoute,strokeOpacity:1});
                polyLines[polyLines.length] = varPolyLine;
            }
            jsRouteLayers[routeLayer.RouteID].polyLines = polyLines;
            
            //
            // This is the initial call to update the Route Layer's being displayed
            // on the map.
            //
            addMapRouteLayers(routeLayer.RouteID);
        }
    }
}

function updateRouteIDString()
{
    routeIDString = "";
    selectedRouteLogNums = [];
    isRouteChecked = false;
    for (var x = 0 ; x < routeArray.length ; ++x)
    {
        if (document.getElementById(routeArray[x].Route.RouteID).checked) {
            if (routeIDString == "")
            {
                routeIDString += routeArray[x].Route.RouteID;                
            }
            else
            {
                routeIDString += "," + routeArray[x].Route.RouteID;                
            }
            
            selectedRouteLogNums.push(routeArray[x].Route.LogNum);
            isRouteChecked = true;
        }
    }

    if (routeIDString.length == 0)  // Zero length indicates that no Routes are selected (the default), but we still must discriminate against unregistered buses.
    {
        for (var x = 0 ; x < routeArray.length ; ++x)
        {
            if (routeIDString == "")
            {
                routeIDString += routeArray[x].Route.RouteID;                
            }
            else
            {
                routeIDString += "," + routeArray[x].Route.RouteID;                
            }
            
            selectedRouteLogNums.push(routeArray[x].Route.LogNum);
        }
        
        selectedRouteLogNums = selectedRouteLogNums.concat(suppressedRouteLogNums);
    }
    
    // GLog.write("selected routes = "+selectedRouteLogNums);
}
//
// Shelters
// 

//..................................................................................................................................................................................
function getJSONShelter(data, responseCode)
{   
    //
    // Added for performance benchmarking 03182009
    //
    // var startDate = new Date();
    // var startTime = startDate.getTime();

    // GLog.write("Shelter process starting: " + startDate);
    //
    // Till here - Added for performance benchmarking 03182009
    
    if (responseCode != "success")
    {
        // There is a problem here. This javascript will wait
        // until the problem is cleared up to try again.
        return;
    }
    else
    {
    	// GLog.write("in getJSONShelter at "+(new Date()));
        
        var json=null;
        //eval the json string
        var startTime = new Date().getTime();
                
        try {
        	json = eval('(' + data + ')');
        	if (!(json instanceof Object) || !(json.ShelterArray instanceof Array) || json.lastUpdateTime == undefined
        			|| json.lastUpdateTime == null)
        		return; // invalid response object received
        } catch (ex) {
        	return;
        }
        //GLog.write("jsonShelter eval took : "+(new Date().getTime() - startTime));

        var jsonShelterArray = json.ShelterArray;
        lastShelterHttpRequestTime = json.lastUpdateTime;

        //parse the JSON string
        startTime = new Date().getTime();

        var createdShelters = false;
        var jsonShelterArrayLength = jsonShelterArray.length;
        for (var x = 0 ; x < jsonShelterArrayLength ; ++x)
        {
            var shelter = jsonShelterArray[x].Shelter;
            
            // Is shelter null for some reason?
            if (shelter)
            {
                // Does the shelter have a valide Lat/Lng? 
                if ((shelter.Latitude != 0) && (shelter.Longitude != 0))
                {
                    //get the shelter
                    var shelterObj = shelterArray[shelter.ShelterId];
                    
                    //check if already have one
                    if (!shelterObj)
                    {
                    	GLog.write("NOT found shelterId : "+shelter.ShelterId+" creating object");
                    	shelterObj = createShelterObjectFromJSON(shelter);
                    	createdShelters = true;
                    }
                    if(shelter.update)
                    {
                    	shelterObj.newText = shelter.WebLabel;
                    	// update only if label text has changed
                    	if (shelterObj.newText && shelterObj.labelText != shelterObj.newText) {
                        	shelterObj.labelText = shelterObj.newText;
                        	itemLabelUpdate(shelterObj, shelterObj.labelText);
                    	}
                    	shelterObj.predictionTimes = shelter.PredictionTimes;
                    }
                    else
                    {
                    	shelterObj.newText = null;                    	
                    }
                }
            }
        }
        
        if (createdShelters) {
        	showSelectedRoutes(true);
        }
        
        // GLog.write(" processing jsonArray took : "+(new Date().getTime() - startTime));

        //
        // Now that the label is active. We'll check to see if the alert icon stays.
        //
        // NOTE: This can be used to pull the code form the Shelter object to keep
        //       the information clean at that level.
        //
        if (!isAlertDrawerActive)
        {
            jQuery(".alertIcon").html("");
        }        
        }
}

function createShelterObjectFromJSON(shelter) {
	var createdShelter = false;
	var shelterObj = poolOfAvailableShelters.pop();
	
    //make a new shelter obj if not in pool
	if (!shelterObj) {
		createdShelter = true;
	    shelterObj = new Shelter(shelter.ShelterId, shelter.ShelterName);
	} else {
		shelterObj.shelterID = shelter.ShelterId;
		shelterObj.shelterName = shelter.ShelterName;		
	}

    //set the info
    shelterArray[shelter.ShelterId] = shelterObj;
    shelterObj.lat = shelter.Latitude;
    shelterObj.lon = shelter.Longitude;
    shelterObj.routeIDs = shelter.routeIDs;
    shelterObj.minor = shelter.minor;
    
    if (shelter.update) {
        shelterObj.labelText = shelter.WebLabel;
        shelterObj.predictionTimes = shelter.PredictionTimes;
    } else {
        shelterObj.labelText = "";
        shelterObj.predictionTimes = {};    	
    }

    // get shelter position
    var point = new google.maps.LatLng(shelterObj.lat/100000.0, -shelterObj.lon/100000.0);
    
    shelterObj.position = point;
/*
    if (createdShelter) {
	    // create Marker for shelter
	    var marker = new google.maps.Marker(
	    {position: point,
	    map: map,
	    icon: (shelterObj.minor ? minorShelterIcon : shelterIcon),
	    flat: true,
	    //shadow: shelterIconshadow,
	    zIndex: shelterObj.visualOrder});
	
	    //assign the new marker
	    shelterObj.marker = marker;
	
	    shelterObj.marker.setMap(map);
	    marker = null;
		// create shelter label
	    itemLabelController(shelterObj, shelterObj.labelText, point, false, shelterObj.minor ? shelterObj.minorLabelClassName : shelterObj.labelClassName);
    } else {
    	shelterObj.marker.setIcon(shelterObj.minor ? minorShelterIcon : shelterIcon);
    	shelterObj.marker.setPosition(point);
    	shelterObj.marker.setVisible(true);
    	shelterObj.label.setAnchor(point);
    	itemLabelUpdate(shelterObj, shelterObj.labelText, shelterObj.minor ? shelterObj.minorLabelClassName : shelterObj.labelClassName);    	
    }
*/
	var screenPoint = emptyOverlay.getProjection().fromLatLngToContainerPixel(shelterObj.position);
	shelterObj.xScreen = screenPoint.x;
	shelterObj.yScreen = screenPoint.y;
    
    return shelterObj;	
}

function createSheltersFromJSON(data, responseCode) {
	
	if (responseCode == "success") {
        var json=null;
        //eval the json string
                
        try {
        	json = eval('(' + data + ')');
        	if ((json instanceof Object) && (json.ShelterArray instanceof Array)) {
                var jsonShelterArray = json.ShelterArray;
                
                setTimeout(executeThisFuncLater(create100Shelters, jsonShelterArray, 0), 5);        		
        	} else {
        		// try again
        		GLog.write("******************** eval of JSON string failed in createSheltersFromJSON ******************");
        		jQuery.get("packet/json/shelter", createSheltersFromJSON);        		
        	}
        } catch (ex) {
    		// try again
    		GLog.write("******************** Exception in createSheltersFromJSON ******************");
    		jQuery.get("packet/json/shelter", createSheltersFromJSON);
        }		
	} else {
		// try again
		GLog.write("******************** NON success response recd by createSheltersFromJSON ******************");
		jQuery.get("packet/json/shelter", createSheltersFromJSON);
	}	
}

function create100Shelters(jsonShelterArray, beginIndex) {
	var numSheltersToProcess = 100, n=0;
	//var lengthToUse = beginIndex+100 >= jsonShelterArray.length ? jsonShelterArray.length : beginIndex+100;
	var x;
    for (x = beginIndex; x < jsonShelterArray.length && n < numSheltersToProcess; x++)
    {
        var shelter = jsonShelterArray[x].Shelter;
        
        // Is shelter null for some reason?
        if (shelter)
        {
        	n++;
            // Does the shelter have a valide Lat/Lng? 
            if ((shelter.Latitude != 0) && (shelter.Longitude != 0))
            {
                //make a new shelter obj
                var shelterObj = createShelterObjectFromJSON(shelter);
            }
        }
    }
    
    if (x < jsonShelterArray.length) {
    	setTimeout(executeThisFuncLater(create100Shelters, jsonShelterArray, x), 5);
    } else {

    	arrayOfShelterGroupArray[map.getZoom()] = [];

    	showSelectedRoutes(true);
    	
    	/*
    	// processed all shelters ... create the groups
        sortedShelterArray = [].concat(shelterArray);
        
        // sort shelters by name
        sortedShelterArray.sort(compareShelters);
        
        createShelterGroups();
        
        //
        // Update the list of shelters for use with the Search drawer
        //
        // NOTE: isSearchDrawerActive is defined in index.jsp
        //
        if (isSearchDrawerActive) {
            refreshSearchList(shelterArray);
        }
        */
    	
    	// if in a route view show route layers
    	/*
    	if (routeView) {
    		for (var i=0; i<routeArray.length; i++) {
    			if (routeArray[i] && routeArray[i].Route) {
    				routeCheckBoxClicked(routeArray[i].Route.RouteID);
    			}
    		}
    	}
    	*/
        
        // start the data flowing
        setInterval(executeThisFuncLater(updateVehicle, null), 1000);
        setInterval(executeThisFuncLater(updateShelter, null), 5000);    	
    }	
}

function createOrPositionShelterGroupMarkers() {
    for(var x=0;x<shelterGroupArray.length;x++)
    {
        //get the shelter group
        var shelterGroup = shelterGroupArray[x];
        
        //check the shelter group
        if (shelterGroup)
        {
            //check the number of item in the grouping
            if(shelterGroup.shelters.length > 1)
            {
                //get the first shelter
                var shelter1 = shelterGroup.shelters[0];

                //check the shelter
                if (shelter1)
                {
                	if (shelterGroup.marker) {
    	            	// position shelterGroup marker and show it                		
    	            	shelterGroup.marker.setIcon(shelterGroup.isMinor() ? minorShelterGroupIcon : shelterGroupIcon);
    	            	shelterGroup.marker.setPosition(shelter1.position);
    	            	shelterGroup.marker.setVisible(true);                		
                	} else {
	                    // create marker
	                    var marker = new google.maps.Marker(
	                    {position: shelter1.position,
	                    map: map,
	                    icon: shelterGroup.isMinor() ? minorShelterGroupIcon : shelterGroupIcon,
	                    flat: true,
	                    zIndex: shelterGroup.visualOrder});
	
	                    //add marker to group
	                    shelterGroup.marker = marker;
	                    shelterGroup.marker.setMap(map);
                	}
                }
                
                // Label
                //
                // Create the label assignment for the shelterGroup and activate
                //
                shelterGroup.labelText = getGroupShelterList(shelterGroup);
                //GLog.write(".........................itemLabelController() called from procesShelterGroup()......");
                itemLabelController(shelterGroup, shelterGroup.labelText, shelterGroup.marker.getPosition(), false, shelterGroup.isMinor() ? shelterGroup.minorLabelClassName : shelterGroup.labelClassName);
                
                // hide markers of shelters and set their label anchor to shelterGroup
                for (var i=0; i < shelterGroup.shelters.length; i++) {
                	if (shelterGroup.shelters[i].marker)
                		shelterGroup.shelters[i].marker.setVisible(false);
                	
                	if (shelterGroup.shelters[i].label)
                		shelterGroup.shelters[i].label.setAnchor(shelterGroup.marker.getPosition());
                }
            }
            else
            {
                //shelterGroup with 1 shelter...ungroup the shelter
                if(shelterGroup.shelters[0])
                {
                    //set the shelter grouping to false
                    shelterGroup.shelters[0].grouped = false;
                    shelterGroup.shelters[0].parent  = null;
                    
                    // show shelter marker
                    shelterGroup.shelters[0].setVisible(true);
                    //shelterGroup.shelters[0].label.setAnchor(shelterGroup.shelters[0].position);
                }
                // empty out shelters for this group and hide its marker & label if they exist
                shelterGroup.shelters = [];
                if (shelterGroup.marker)
                	shelterGroup.marker.setVisible(false);
                if (shelterGroup.label)
                	shelterGroup.label.hide();
            }
        }
    }	
}

function newShelterAndGroup(shelter, shelterGroup) {
    //set group flag
    shelter.grouped = true;
    shelter.parent  = shelterGroup;

    //
    // Query the label associated with the shelter being added to the group
    // to see if its been stuck to the map.
    //
    if (shelter.label)
    {
        //
        // We found a shelter with an active label for this group.
        // We'll now assign this label as the active label for this group.
        //
        if (shelter.label.isClicked && shelter.label.isStatic)
        {
            shelterGroup.isShelterLabelActive = true;
            shelterGroup.activeShelterLabelID = shelter.shelterID;
            shelterGroup.labelID = "labelShelterGroup" + shelter.shelterID;
        }
    }
                        
    //add the shelter to the shelter group
    shelterGroup.shelters.push(shelter);
}

function addShelterToGroup(shelter, localShelterGroupArray)
{
    //parse the shelter groups
    for(var x=0;x<localShelterGroupArray.length;x++)
    {
        //get the shelter group
        var shelterGroup = localShelterGroupArray[x];
        
        //check the shelter group
        if(shelterGroup)
        {
            //parse the shelters
            if(shelterGroup.shelters.length > 0)
            {
                //get the shelter
                var shelter_check = shelterGroup.shelters[0];
                
                //check the shelter check
                if(shelter_check)
                {
                    //get the point from the
                    //var point_group = shelter_check.marker.getPoint();
            
                    //get the screen coordinates for group
                    //var screen_group_point = map.fromLatLngToContainerPixel(point_group);
            
                    //do a check to see if I belong to this group
                    var threshold = 35;
                    if(shelter.xScreen > shelter_check.xScreen - threshold && shelter.xScreen < shelter_check.xScreen + threshold &&
                        shelter.yScreen > shelter_check.yScreen - threshold && shelter.yScreen < shelter_check.yScreen + threshold)   
                    {
                    	//GLog.write(shelter.xScreen+", "+shelter.yScreen+" added "+shelter.shelterName + " to GROUP "+shelter_check.shelterName+" "+shelter_check.xScreen+", "+shelter_check.yScreen);
                        //add the shelter to this group
                        shelterGroup.shelters.push(shelter);

                        //set group flag
                        shelter.grouped = true;
                        shelter.parent  = shelterGroup;

                        //
                        // Assign the first label found to the ShelterGroup.
                        //
                        if (!shelterGroup.isShelterLabelActive)
                        {
                            //
                            // Query the label associated with the shelter being added to the group
                            // to see if its been stuck to the map.
                            //
                            if (shelter.label)
                            {
                                //
                                // We found a shelter with an active label for this group.
                                // We'll now assign this label as the active label for this group.
                                //
                                if (shelter.label.isClicked && shelter.label.isStatic)
                                {
                                    shelterGroup.isShelterLabelActive = true;
                                    shelterGroup.activeShelterLabelID = shelter.shelterID;
                                    shelterGroup.labelID = "labelShelterGroup" + shelter.shelterID;
                                }
                            }
                        }
                        else
                        {
                            //
                            // Query the label associated with the shelter being added to the group
                            // to see if its been stuck to the map.
                            //
                            if (shelter.label)
                            {
                                //
                                // We found a shelter with an active label for this group.
                                // We have found that another label is active turn this one off.
                                //
                                if (shelter.label.isClicked && shelter.label.isStatic)
                                {
                                    if (shelterGroup.activeShelterLabelID != shelter.shelterID)
                                    {
                                        shelter.label.hide();
                                    }
                                }
                            }
                        }
                        
                        return shelterGroup;
                    }
                }
            }
        }
    }
    
    return null; // indicating that the input shelter could not be grouped     
}

function zoomChanged() {	
	var tmpArray = arrayOfShelterGroupArray[map.getZoom()];
	
	if (!tmpArray) {
		arrayOfShelterGroupArray[map.getZoom()] = [];
	}

	setScreenCoordinatesForShelters();

	setTimeout(executeThisFuncLater(showSelectedRoutes), 100);
}

function setScreenCoordinatesForShelters() {
	for (var i=0; i<shelterArray.length; i++) {
		var shelter = shelterArray[i];
		if (shelter) {
        	// get screen coordinates for current zoom level
            var screenPoint = emptyOverlay.getProjection().fromLatLngToContainerPixel(shelter.position);
            shelter.xScreen = screenPoint.x;
            shelter.yScreen = screenPoint.y;
		}
	}
	
}

function adjustMarkerLabelOffsets() {
	for (var i=0; i < shelterGroupArray.length; i++) {
		var sg = shelterGroupArray[i];
		if (sg)
			adjustItemLabelOffset(sg);
	}
	
	// GLog.write("$$$$$$$$$$$$ adjustMarkerLabelOffsets() finished shelterGroups");
	
	for (i=0; i<shelterArray.length; i++) {
		var shelter = shelterArray[i];
		if (shelter) {
			adjustItemLabelOffset(shelter);
		}
	}
	
	// GLog.write("$$$$$$$$$$$$ adjustMarkerLabelOffsets() finished shelters");

	for (i=0; i<vehicleArray.length; i++) {
		var vehicle = vehicleArray[i];
		if (vehicle) {
			adjustItemLabelOffset(vehicle);
		}
	}
	
	// GLog.write("$$$$$$$$$$$$ adjustMarkerLabelOffsets() finished vehicles");
}

function jsShelterLabelController(shelterID, preview, clicked)
{
	//GLog.write("entered jsShelterLabelController args: "+shelterID+" "+preview+" "+clicked);
	
	if (!shelterID)
		return;		// no shelterID ... bail
	
    var shelterObj = shelterArray[shelterID];
    
    if (!shelterObj)
    	return; // no shelter ... bail

    //
    // Get our parent
    //
    var currentShelterGroup = shelterObj.parent;
    
    if (!currentShelterGroup)
    	return; // no shelterGroup ... nothing to do...bail 
    
    //GLog.write("got groupObj for shelterId = "+shelterID);
    
    //check if preview
    if(preview == true)
    {
        //parse the shelter groups
        for(var x=0;x<currentShelterGroup.shelters.length;x++)
        {
            //check this is the shelter id
            if(currentShelterGroup.shelters[x].shelterId != shelterID)
            {
            	/*
                if(!currentShelterGroup.shelters[x].label.isClicked)
                {
                	// GLog.write("call setStatic ############## 1");
                    currentShelterGroup.shelters[x].label.setStatic(false);
                }
                */
            }
        }
    }
    
    //
    // Determine if we have an active label.
    //
    if (currentShelterGroup.isShelterLabelActive) {
    	//GLog.write("Group has shelter active");
        if (currentShelterGroup.activeShelterLabelID == shelterID) {
        	//GLog.write(shelterID+ " active in Group");
            //
            // If the label was active and we receive the click event
            // turn off the label.
            //
            if (clicked) {
                currentShelterGroup.isShelterLabelActive = false;
                currentShelterGroup.activeShelterLabelID = null;
                currentShelterGroup.labelID = null;
                //shelterObj.label.hide();
                shelterObj.setVisible(false);

                //GLog.write("shelter label closed");
                
	            currentShelterGroup.labelText = getGroupShelterList(currentShelterGroup);
	            itemLabelUpdate(currentShelterGroup, currentShelterGroup.labelText);
            }
        }
    } else {
        //
        // User has initiated a sticky label.
        //
        if (clicked) {
        	shelterObj.ensureLabel();//setVisible(true);
            itemLabelController(shelterObj, shelterObj.labelText, currentShelterGroup.marker.getPosition(), clicked, shelterObj.minor ? shelterObj.minorLabelClassName : shelterObj.labelClassName);
            currentShelterGroup.isShelterLabelActive = true;
            currentShelterGroup.activeShelterLabelID = shelterID;
            currentShelterGroup.labelID = "labelShelterGroup"+shelterID;
            
            //GLog.write("shelter label open and stuck");
        
            currentShelterGroup.labelText = getGroupShelterList(currentShelterGroup);
            itemLabelUpdate(currentShelterGroup, currentShelterGroup.labelText); 
        } else {
            //
            // Just browsing.
            //
            if (preview) {
            	shelterObj.ensureLabel(); //setVisible(true);
                itemLabelController(shelterObj, shelterObj.labelText, currentShelterGroup.marker.getPosition(), clicked, shelterObj.minor ? shelterObj.minorLabelClassName : shelterObj.labelClassName);
                //GLog.write("call setStatic ############## 2");
                shelterObj.label.setStatic(true);
            } else {
                itemLabelController(shelterObj, shelterObj.labelText, currentShelterGroup.marker.getPosition(), clicked, shelterObj.minor ? shelterObj.minorLabelClassName : shelterObj.labelClassName);
                //GLog.write("call setStatic ############## 3");
                shelterObj.label.setStatic(false);
                shelterObj.setVisible(false);
            }
        }
    }
}

function adjustItemLabelOffset(item) {
	// sanity check -- if no item/label then quit
	if (!item || !item.label)
		return;

    // Variables
    var updatedQuadrant;
    var hasNewQuadrant = false;

    var currentMapCenterLat;
    var currentMapCenterLng;
    
    try {
        currentMapCenterLat = map.getCenter().lat();
        currentMapCenterLng = map.getCenter().lng();
        
        if (item.label.getAnchor().lng() <= currentMapCenterLng) {
            if (item.label.getAnchor().lat() <= currentMapCenterLat) {
                if (item.quadrant == 3) {
                    hasNewQuadrant    = false;
                } else {
                    updatedQuadrant    = 3;
                    hasNewQuadrant    = true;
                }
            } else {
                if (item.quadrant == 2) {
                    hasNewQuadrant    = false;
                } else {
                    updatedQuadrant    = 2;
                    hasNewQuadrant    = true;
                }
            }
        } else {
            if (item.label.getAnchor().lat() <= currentMapCenterLat) {
                if (item.quadrant == 4) {
                    hasNewQuadrant    = false;
                } else {
                    updatedQuadrant    = 4;
                    hasNewQuadrant    = true;
                }
            } else {
                if (item.quadrant == 1) {
                    hasNewQuadrant    = false;
                } else {
                    updatedQuadrant    = 1;
                    hasNewQuadrant    = true;
                }
            }
        }
    } catch (exception) {
        // Do nothing.
    }
    
    if (hasNewQuadrant) {
        item.quadrant = updatedQuadrant;
    }
    
    //
    // thomasp - Update the offset now that we have a label and can access
    //           its height.
    //
    var heightNotSet=false;
    switch(item.quadrant) {
        case 1:
            item.labelOffset = item.quadOffset1;
            break;
        case 2:
            item.labelOffset = item.quadOffset2;
            break;
        case 3:
            item.labelOffset = new google.maps.Size(item.quadOffset3.width, -(item.label.height + item.labelHeightOffset));
            if (item.label.height == 0)
            	heightNotSet=true;            	
            break;
        case 4:
            item.labelOffset = new google.maps.Size(item.quadOffset4.width, -(item.label.height + item.labelHeightOffset));
            if (item.label.height == 0)
            	heightNotSet=true;            	
            break;
    }
    
    // if (item.shelterName)
    	// GLog.write("########"+" shelter "+ item.shelterName+" label offset is "+item.labelOffset.width+" , "+item.labelOffset.height);
    item.label.setOffset(item.labelOffset);    
}

function itemLabelUpdate(item, labelText, cssClassName) {
    if (item.label) {
    	item.label.opts.item = item;
        item.label.setContent(labelText);
        adjustItemLabelOffset(item);
        
        if (cssClassName) {
        	item.label.className = cssClassName;

            if (item.label.container) {
            	item.label.container.className = cssClassName;
            }
        }
    }
}

function itemLabelController(item, labelText, point, menuActivated, cssClassName) {
	var labelDisplay = undefined;
    //
    // Now updated the label given the information gathered.
    //
    if (!item.label) {
        //create the item label
        item.label = new OtviaLabel(labelText, {className: (cssClassName ? cssClassName : item.labelClassName), marker: item.marker, isStatic: false, map : map, item : item});
                
        // Add item to the map.
        // map.addOverlay(item.label);
    } else {
    	if (cssClassName)
    		item.label.className = cssClassName;
    	if (item.label.container) {
    		if (cssClassName)
    			item.label.container.className = cssClassName;
	    	//get the label display
	    	labelDisplay = item.label.container.style.display;
    	}
    }
    
    //check the label display for change
    if(item.label.content != labelText) {
        //set the label contents
        item.label.setContent(labelText);
    }

    //set the label anchor
    item.label.setAnchor(point);
            
    //adjust the label offset
    // GLog.write("<<<<<<<<<<<<<<<<<<<<<<<<adjustItemLabelOffset() called from itemLabelController()<<<<<");
    adjustItemLabelOffset(item);
            
    if (menuActivated)
    	item.label.stickIt();
    else if (labelDisplay == "")
        item.label.show();	// label style set to display show the label
}

function setVehicleIconDirectionImage(currentDirection) {
    if (currentDirection > 337.50 && currentDirection <= 22.50)
    {
        vehicleIcon            = imagepath + "/vehicle-direction-000"+imageExtension;
    }
    else if (currentDirection > 22.50 && currentDirection <= 67.50)
    {
        vehicleIcon            = imagepath + "/vehicle-direction-045"+imageExtension;
    }
    else if (currentDirection > 67.50 && currentDirection <= 112.50)
    {
        vehicleIcon            = imagepath + "/vehicle-direction-090"+imageExtension;
    }
    else if (currentDirection > 112.50 && currentDirection <= 157.50)
    {
        vehicleIcon            = imagepath + "/vehicle-direction-135"+imageExtension;
    }
    else if (currentDirection > 157.50 && currentDirection <= 202.50)
    {
        vehicleIcon            = imagepath + "/vehicle-direction-180"+imageExtension;
    }
    else if (currentDirection > 202.50 && currentDirection <= 247.50)
    {
        vehicleIcon            = imagepath + "/vehicle-direction-225"+imageExtension;
    }
    else if (currentDirection > 247.50 && currentDirection <= 292.50)
    {
        vehicleIcon            = imagepath + "/vehicle-direction-270"+imageExtension;
    }
    else if (currentDirection > 292.50 && currentDirection <= 337.50)
    {
        vehicleIcon            = imagepath + "/vehicle-direction-315"+imageExtension;
    } else {
    	// default of "000"
        vehicleIcon            = imagepath + "/vehicle-direction-000"+imageExtension;
    }
}

function getJSONVehicle(data, responseCode) {
    
    if (responseCode != "success") {
        // There is a problem here. This javascript will wait
        // until the problem is cleared up to try again.
        return;
    }
    else if (data == "") {
        // There is a problem here. This javascript will wait
        // until the problem is cleared up to try again.
        return;
    } else {
    
        // var startDate = new Date();
        // var startTime = startDate.getTime();

        // GLog.write("getJSONVehicle() starting: " + startDate);
    
    	var json=null;
        //turn the http data into json object
        try {
        	json = eval('(' + data + ')');
        	if (!(json instanceof Object) || !(json.VehicleArray instanceof Array) || json.lastUpdateTime == undefined
        			|| json.lastUpdateTime == null)
        		return; // invalid response object received
        } catch (ex) {
        	return;
        }
        var jsonVehicleArray = json.VehicleArray;
        lastVehicleHttpRequestTime = json.lastUpdateTime;
        
        //parse the vehicle array
        for (var x = 0 ; x < jsonVehicleArray.length; ++x) {
            //get the vehicle from vehicle array
            var vehicle = jsonVehicleArray[x].vehicle;

            //
            // Check for a null vehicle and a vehicle that has an id of -1.
            // The vehicles are stored in the array based on vehicle id. If we
            // recieve a vehicle id of -1 this will cause the vehicle icon to
            // 'ghost' or leave a trail.
            //

            //
            // XXX - thomasp : oos here has been put in for Lincoln
            //
            if (vehicle && vehicle.id != -1 && !vehicle.oos) {
                //check the vehicle update
                if(vehicle.update == false) {
                    //
                    // Set the filtered flag to active to see which vehicles/lables
                    // to remove from the map.
                    //
                    if (vehicleArray[vehicle.id]) {
                        vehicleArray[vehicle.id].filtered = true;
                        
                        // lawrencel - next line not necessary in a properly functioning system
                        // since I am debugging vehicles not appearing when it switches routes by programmaitcally
                        // changing its routeID in server I have to set the routeID under all conditions
                        vehicleArray[vehicle.id].routeID = vehicle.routeID;
                    }
                } else {
                    //check the cvlocaltion info
                    if (vehicle.CVLocation) {
                        if ((vehicle.CVLocation.latitude != 0) && (vehicle.CVLocation.longitude != 0)) {
                            if (!vehicleArray[vehicle.id]) {
                                vehicleArray[vehicle.id] = new Vehicle(vehicle.id);                                
                            }
                            
                            // must always set routeID since vehicle may have switched routes
                            vehicleArray[vehicle.id].routeID = vehicle.routeID;                            

                            //make the point
                            var point = new google.maps.LatLng(vehicle.CVLocation.latitude/100000.0, vehicle.CVLocation.longitude/100000.0);
                            // Dhanya - Directional Arrow under Vehicle Icon
                            var currentDirection = vehicle.CVLocation.angle;
                            if (isDirectionalArrowActive){
                            	setVehicleIconDirectionImage(currentDirection);
                            }
                                  
                            //
                            // thomasp - Updated code to use Vehicle objects defined
                            //           here and pull them from the vehicleArray
                            //
                            // NOTE: There might be problem here with the interaction
                            //       between the code here and the Google Maps. The
                            //       updated items might not refresh correctly
                            //       and be constantly created. I'll test this
                            //       once vehicle are reporting with valid routes.
                            //
                            if (!vehicleArray[vehicle.id].marker) {
                                //make the marker
                                var marker = new google.maps.Marker(//point, {icon: vehicleIcon, zIndexProcess: zOrder});
                                {position: point,
                                map: map,
                                icon: vehicleIcon,
                                //shadow: vehicleIconshadow,
                                flat:true,
                                zIndex: vehicleArray[vehicle.id].visualOrder});
                            	
                                vehicleArray[vehicle.id].marker = marker;
                                //vehicleArray[vehicle.id].marker.visualOrder = vehicleArray[vehicle.id].visualOrder;
                                //map.addOverlay(vehicleArray[vehicle.id].marker);
                                // vehicleArray[vehicle.id].marker.setMap(map);
                            } else {
                                vehicleArray[vehicle.id].marker.setPosition(point);
                                vehicleArray[vehicle.id].marker.setIcon(vehicleIcon);
                            }

                            // Label            
                            var ttTitle = vehicle.WebLabel;
                            vehicleArray[vehicle.id].labelText = vehicle.WebLabel;
                            vehicleArray[vehicle.id].predictionTimes = vehicle.PredictionTimes;

                            // LLR - debug wrong direction arrow on vehicle
                            /*
                            var strIdx = vehicle.WebLabel.indexOf("</div>");
                            if (strIdx != -1) {
                            	vehicleArray[vehicle.id].labelText = vehicle.WebLabel.substring(0, strIdx)+ " "+vehicle.id+" "+vehicle.CVLocation.angle+" "+vehicle.WebLabel.substr(strIdx);
                            }
                            */
                            
                            //
                            // Function to control an items label.
                            // 
                            itemLabelController(vehicleArray[vehicle.id], vehicleArray[vehicle.id].labelText, point, false);

                            //
                            // Set the filtered flag to active to see which vehicles/lables
                            // to remove from the map.
                            //
                            vehicleArray[vehicle.id].filtered = true;
                        }
                    }
                }
            }
        }
        
        //
        // Start filtering vehicles that do not have the filtered flag
        //
        for (var x = 0 ; x < vehicleArray.length ; ++x) {
            if (vehicleArray[x]) {
                if (vehicleArray[x].filtered == false) {
                    vehicleArray[x].label.hide();
                    // map.removeOverlay(vehicleArray[x].marker);
                    vehicleArray[x].marker.setVisible(false);//setMap(null);
                    // updatedVehicleArray[x] = undefined;
                    //vehicleArray[x] = null;
                } else {
                    vehicleArray[x].filtered = false;
                    if (selectedRouteLogNums.indexOf(vehicleArray[x].routeID) != -1) {
                    	if (!vehicleArray[x].marker.getVisible()) { // setVisible only if not showing otherwise we get flashing vehicle icons
                    		vehicleArray[x].marker.setVisible(true);
                    	}
                    } else {
                    	vehicleArray[x].marker.setVisible(false);                    	
                    }
                }
            }
        }

        //
        // Now set the vehicleArray to the newly updated updatedVehicleArray
        //
        // NOTE: Need to ensure in all cases here that the array manipulation is
        //       not causing any memory leaks or problems.
        //
        // vehicleArray = updatedVehicleArray;
        
        vehicle     = null;
        json        = null;


	    // var endDate = new Date();
	    // var endTime = endDate.getTime();

	    // GLog.write("getJSONVehicle() ending: " + endDate);
	    // GLog.write("getJSONVehicle() time: " + (endTime-startTime));

    }
}

// this method creates the maps and sets up map listeners
function load() {

    //
    // Check the browser
    //
	if (!disableBrowserCheck)
		checkDownloadFirefox();
	else
		jQuery("#browserCheckDialog").dialog("destroy");
    //
    // Set flag to notify the alert subsystem the page has been reloaded.
    //
    isPageLoading = true;
    
    //
    // Initialize jQuery - Accordion styles for OTvia
    //
    jQuery(".ui-accordion").bind("accordionchange", function(event, ui) {
        // jQuery(".dr-drawer").css("overflow", "auto");
        getEditAlerts();
    });
   
    //
    // Corner intialization
    //
    jQuery("div#otviaTime").corner("3px");
    jQuery("div.user-links-div").corner("3px");
    jQuery("div.user-id-div").corner("3px");
    
    //
    // Handle resize issues associated with IE6 only.  Deal with this first, so IE6 initializes correctly, too.
    //
    // Detect IE6.  If using IE6 then reset CSS .width and .height from "auto" to calculated numeric values.
    var IEversion = 0;
    if (navigator.appVersion.indexOf("MSIE") != -1)
    {
        var verstrings = navigator.appVersion.split("MSIE");
        IEversion = verstrings[1];
        if (IEversion.charAt(1) == "6")  // Note using index of 1, as char at 0 should be a space.
        {
            isIE6 = true;
            if ((document.body.clientWidth - IEMapWidthFactor - 56) > 0)
            {
            document.getElementById("mapPanel").style.width  = ((document.body.clientWidth  - IEMapWidthFactor) + "px");
            document.getElementById("mapPanel").style.height = ((document.body.clientHeight - IEMapHeightFactor + 28) + "px");
            document.getElementById("dr-utility-drawers").style.height = ((document.body.clientHeight - IEMapHeightFactor + 28) + "px");
            document.getElementById("mE_D4").style.height = ((document.body.clientHeight - IEMapHeightFactor) + "px");
            document.getElementById("mE_D5").style.height = ((document.body.clientHeight - IEMapHeightFactor) + "px");
            document.getElementById("mE_D8").style.height = ((document.body.clientHeight - IEMapHeightFactor)/2 + "px");
            document.getElementById("mE_D9").style.height = ((document.body.clientHeight - IEMapHeightFactor)/2 + "px");
            document.getElementById("map").style.width  = ((document.body.clientWidth  - IEMapWidthFactor - 56) + "px");
            document.getElementById("map").style.height = ((document.body.clientHeight - IEMapHeightFactor) + "px");
            document.getElementById("mapTop").style.width  = ((document.body.clientWidth  - IEMapWidthFactor - 56) + "px");
            document.getElementById("mapTR").style.left  = ((document.body.clientWidth  - IEMapWidthFactor - 14) + "px");
            document.getElementById("mapRight").style.left  = ((document.body.clientWidth  - IEMapWidthFactor - 14) + "px");
            document.getElementById("mapRight").style.height = ((document.body.clientHeight - IEMapHeightFactor) + "px");
            document.getElementById("mapBR").style.left  = ((document.body.clientWidth  - IEMapWidthFactor - 14) + "px");
            document.getElementById("mapBR").style.top = ((document.body.clientHeight - IEMapHeightFactor + 13) + "px");
            document.getElementById("mapLeft").style.height = ((document.body.clientHeight - IEMapHeightFactor) + "px");
            document.getElementById("mapBL").style.top = ((document.body.clientHeight - IEMapHeightFactor + 13) + "px");
            document.getElementById("mapBottom").style.top = ((document.body.clientHeight - IEMapHeightFactor + 13) + "px");
            document.getElementById("mapBottom").style.width  = ((document.body.clientWidth  - IEMapWidthFactor - 56) + "px");
            document.getElementById("otviaDRAVLServerStatus").style.width  = ((document.body.clientWidth - 28) + "px");
            document.getElementById("otviaDRAVLServerStatus").style.height = ((document.body.clientHeight - IEMapHeightFactor + 28) + "px");
            document.getElementById("otviaDRAVLServerStatus").style.right  = ("auto");
            document.getElementById("otviaDRAVLServerStatus").style.bottom = ("auto");
            }
        }
    }
    
    // Create the Google Map.
	 var myLatlng = new google.maps.LatLng(mapCenterLat, mapCenterLong);
	 var myOptions = {
	      zoom: 12,
	      minZoom : minMapZoom,
	      maxZoom : maxMapZoom,
	      center: myLatlng,
	      mapTypeId: google.maps.MapTypeId.ROADMAP,
	      keyboardShortcuts:true
	 }
	 map = new google.maps.Map(document.getElementById("map"), myOptions);
	 
//	 // if in a predefined view zoom in closer
//	 if (routeView)
//		 map.setZoom(map.getZoom()+2);
		 
	 
	emptyOverlay = new google.maps.OverlayView();
	emptyOverlay.draw = function() {};
	emptyOverlay.setMap(map);
	currentZoom = map.getZoom();
	 
    
    mapCenter = myLatlng;
    currentCenterOfMap = mapCenter;

    // Local Search
    
    //
    // thomasp - Removed experimental search feature.
    // var localSearchOptions = { suppressInitialResultSelection : true };
    // map.addControl(new google.maps.LocalSearch(localSearchOptions));

    // add zoom listener
    google.maps.event.addListener(map, "zoom_changed", function() {
    	// max/min checks are needed if zoom bar limits could not be set
	    if (map.getZoom() > maxMapZoom) {
	    	return;
	    }

	    if (map.getZoom() < minMapZoom) {
	    	return;
	    }
	    
		if (currentZoom && map.getZoom() == currentZoom) {
			return; 	// no real change in zoom....nothing to do
		}
		
		currentZoom = map.getZoom();
	    
	    // hide all shelters/groups
	    for (var i=0; i<shelterArray.length; i++) {
	    	if (shelterArray[i] && shelterArray[i].marker)
	    		shelterArray[i].marker.setVisible(false);
	    }

	    for (i=0; i<shelterGroupArray.length; i++) {
	    	if (shelterGroupArray[i] && shelterGroupArray[i].marker)
	    		shelterGroupArray[i].marker.setVisible(false);
	    }
	    
        setTimeout(zoomChanged, 200);
    });
           
    // when map center changes then labels have to display in the new positions
    google.maps.event.addListener(map, "center_changed", function() {

    	// if new center is more 25 miles from agency center then revert to last valid center
    	if (google.maps.geometry.spherical.computeDistanceBetween(map.getCenter(), mapCenter) > maxPanDistance) {
    		map.setCenter(currentCenterOfMap);
    	} else {
    		currentCenterOfMap = map.getCenter();

    		// adjust offsets of markers
        	adjustMarkerLabelOffsets();
        	
        	// set screen coordinates
        	setScreenCoordinatesForShelters();        
    	}    	
    });

    // when map type changes then zoom bar limits have to be set
    google.maps.event.addListener(map, "maptypeid_changed", function() {
    	//setZoombarLimits();
    });
    
    // Local Search
    //
    // thomasp - Removed experimental search feature.
    //
    // google.maps.Search.setOnLoadCallback(load);

    //
    // Load the Route List Sub-Menu definitions for the current Agency, if they exist.
    //
    if (haveRouteMenus)
    {
        readMenusXMLFile();
    }

    //
    // Update the Route list
    //
    // NOTE: Code change here we'll have to decide on what intiates the
    //       visual page components then being as sequence to setTimeout
    //       calls to ensure the rest of the page is loaded.
    //
    updateRoute();
 
    // 
    // Set the interval timer, for the continuous, periodic check on the status of the servlet environment, including any changes in the Time Regimes for the Routes.
    updateStatus();
    
    //
    // Server Time
    //
    updateServerTime();
    serverTimeTimerID = setInterval(updateServerTime, 30000);
    
    //
    // Initiate the update for user alerts.
    //
    
    updateAlerts(cookieAlertTagString);

    //
    // Call to reset the alert information page.
    //
    getEditAlerts();
    
    // to fix size problem in IE6
    if (isIE6)
        resize();
    
    isPageLoading = false;
}

//..................................................................................................................................................................................
function purge(d) {
	if (d) {
    var a = d.attributes, i, l, n;
    if (a) {
    	l = a.length;
    	for (i=0; i<l; i++) {
    		if (a[i]) {
    		var name = a[i].name;
    		if (name && typeof d[name] === 'function') {
    			d[name] = null;
    		}
    		}
    	}
    }

    a = d.childNodes;
    if (a) {
        l = a.length;
        for (i = 0; i < l; i++) {
            purge(a[i]);
        }
    }
	}
}

//..................................................................................................................................................................................
function resize() {
    // First, handle resizing issues for IE6.
    if (isIE6)
    {
        if (mapIsWide)
        {        	
            document.getElementById("mapPanel").style.width  = ((document.body.clientWidth - 28) + "px");
            document.getElementById("map").style.width  = ((document.body.clientWidth  - 84) + "px");
            document.getElementById("mapTop").style.width  = ((document.body.clientWidth  - 84) + "px");
            document.getElementById("mapBottom").style.width  = ((document.body.clientWidth  - 84) + "px");
            document.getElementById("mapTR").style.left  = ((document.body.clientWidth - IEMapLeftOffset) + "px");
            document.getElementById("mapRight").style.left  = ((document.body.clientWidth - IEMapLeftOffset) + "px");
            document.getElementById("mapBR").style.left  = ((document.body.clientWidth - IEMapLeftOffset) + "px");
        }
        else
        {        	
            if ((document.body.clientWidth - IEMapWidthFactor - 56) > 0)
            {
            document.getElementById("mapPanel").style.width  = ((document.body.clientWidth - IEMapWidthFactor) + "px");
            document.getElementById("map").style.width  = ((document.body.clientWidth - IEMapWidthFactor - 56) + "px");
            document.getElementById("mapTop").style.width  = ((document.body.clientWidth - IEMapWidthFactor - 56) + "px");
            document.getElementById("mapBottom").style.width  = ((document.body.clientWidth - IEMapWidthFactor - 56) + "px");
            document.getElementById("mapTR").style.left  = ((document.body.clientWidth  - IEMapWidthFactor - 14) + "px");
            document.getElementById("mapRight").style.left  = ((document.body.clientWidth  - IEMapWidthFactor - 14) + "px");
            document.getElementById("mapBR").style.left  = ((document.body.clientWidth  - IEMapWidthFactor - 14) + "px");
            }
        }

        document.getElementById("mapPanel").style.height = ((document.body.clientHeight - IEMapHeightFactor + 28) + "px");
        document.getElementById("dr-utility-drawers").style.height = ((document.body.clientHeight - IEMapHeightFactor + 28) + "px");
        document.getElementById("mE_D4").style.height = ((document.body.clientHeight - IEMapHeightFactor) + "px");
        document.getElementById("mE_D5").style.height = ((document.body.clientHeight - IEMapHeightFactor) + "px");
        document.getElementById("mE_D8").style.height = ((document.body.clientHeight - IEMapHeightFactor)/2 + "px");
        document.getElementById("mE_D9").style.height = ((document.body.clientHeight - IEMapHeightFactor)/2 + "px");
        document.getElementById("map").style.height = ((document.body.clientHeight - IEMapHeightFactor) + "px");
        // document.getElementById("routes").style.height = ((document.body.clientHeight - IERouteListHeightFactor) + "px");
        document.getElementById("mapRight").style.height = ((document.body.clientHeight - IEMapHeightFactor) + "px");
        document.getElementById("mapBR").style.top = ((document.body.clientHeight - IEMapHeightFactor + 13) + "px");
        document.getElementById("mapLeft").style.height = ((document.body.clientHeight - IEMapHeightFactor) + "px");
        document.getElementById("mapBL").style.top = ((document.body.clientHeight - IEMapHeightFactor + 13) + "px");
        document.getElementById("mapBottom").style.top = ((document.body.clientHeight - IEMapHeightFactor + 13) + "px");
        document.getElementById("otviaDRAVLServerStatus").style.width  = ((document.body.clientWidth - 28) + "px");
        document.getElementById("otviaDRAVLServerStatus").style.height = ((document.body.clientHeight - IEMapHeightFactor + 28) + "px");
        document.getElementById("otviaDRAVLServerStatus").style.right  = ("auto");
        document.getElementById("otviaDRAVLServerStatus").style.bottom = ("auto");

        //added to set the customer logo at the center of the screen on load as well as resize (for IE6 ONLY)
        // *** 502 = (left:342px + right:160px) (From dr.css #agencyLogo style attributes)
        document.getElementById("img").style.marginLeft = (((document.body.clientWidth-(502))-document.getElementById("img").width)/2);     
    }
    else //if NOT IE6..
    {
        document.getElementById("otviaDRAVLServerStatus").style.right  = ("14px");
        document.getElementById("otviaDRAVLServerStatus").style.bottom = ("28px");
        document.getElementById("otviaDRAVLServerStatus").style.width  = ("auto");
        document.getElementById("otviaDRAVLServerStatus").style.height = ("auto");
    }

    // To resize the accordion correctly on browser resize
    resizeAccordion();

// _______________ alerts section (keeping if further debugging is required)__________________

//            alert("maxHeight: " + maxHeight);
//            alert("drawerCount: " + drawerCount);
//            alert("padding: " + padding);
//
//            alert(".dr-drawer " + jQuery(".dr-drawer").height());
//
//            alert("#routes " + jQuery("#routes").height());
//
//            alert("dr-utility-drawers " + document.getElementById("dr-utility-drawers").style.height);
    //
//            alert(document.getElementById("routes").style.height);

//            alert((document.getElementById("dr-utility-drawers").style.height) - paddingIE6);
    //
//________________________              till here                         ____________________

    google.maps.event.trigger(map, 'resize');
    //var centerReference = map.getCenter();
    //map.checkResize();
    //map.setCenter(centerReference);    
}

// added to resize the accordion correctly on browser resize as well as load..
function resizeAccordion()
{
    var drawerCount = jQuery(".dr-drawer").length;
    var padding     = (drawerCount * 28) + ((drawerCount - 1) * 3);
    var maxHeight;

    if (isIE6)
    {
        //Always parse to an integer (from pixels) to avoid invalid object exceptions later
        // JQuery somehow does not seems to be giving correct values in IE6)
        maxHeight = parseInt(document.getElementById("dr-utility-drawers").style.height);
    }
    else // Resize the accordion (ALL non-IE6 browsers)
    {     
        maxHeight   = jQuery("#drawers").parent().height();
    }

    jQuery(".dr-drawer").height(maxHeight - padding + 5);
    //
    // Update the route drawer's size upon creation
    //
    // NOTE: The 35 is the number of pixels of the routeTop element
    //       from index.jsp
    //
    jQuery("#routes").height(maxHeight - padding - 35);
}

function routeCheckBoxClicked(routeID) {
	GLog.write("....in routeCheckBoxClicked() for "+routeID);
	
	if (kmlURLPrefix)
		handleRouteClickViaKMLLayer(routeID);
	else
		handleRouteClickViaPolylines(routeID);
}

function handleRouteClickViaPolylines(routeID) {
	if (limitSelectedRoutesInIE(routeID)) {
		allStopsShowing = false;
		toggleRouteLayer(routeID,true);
	}	
}

function limitSelectedRoutesInIE(routeID) {
	var result = true;
	if (Browser.isIE()) {
		if (document.getElementById(routeID).checked) {
			
			if (selectedRouteIDs.length == 10) {
				// if this routeID not in list then turn off the checkbox
				if (selectedRouteIDs.indexOf(routeID) == -1) {
					result = false;
					document.getElementById(routeID).checked = false;
					showIEWarning();
				}
			} else {
				if (selectedRouteIDs.indexOf(routeID) == -1) {
					selectedRouteIDs.push(routeID);
				}
			}
			
		}
	}

	return result;
}

function handleRouteClickViaKMLLayer(routeID) {
	if (routeID) {
		allStopsShowing = false;
		toggleRouteLayer(routeID,true);
	}

	// if there is a KML layer in use ... hide it
	if (kmlLayer) {
		try {
			kmlLayer.layer.setMap(null);			
		} catch (e) {
			// bad KML layer...
			GLog.write("bad KML layer for "+kmlLayer.routeIDString);
			// arrayOfKMLLayers[kmlLayer.routeIDString] = null;			
		}		
		kmlLayer = null;
	}

	// if any route checked then update KML i.e. route layer	
	if (isRouteChecked) {
		// see if we already have this KML layer
		if (arrayOfKMLLayers[routeIDString]) {
			kmlLayer = arrayOfKMLLayers[routeIDString];
			kmlLayer.layer.setMap(map);			
		} else {
			createKMLLayer();			
		}
	}	
}

function createKMLLayer() {
	GLog.write("########### getting KML for "+routeIDString);
	
	// hack for IE
	var cz = null;
	/*
	if (Browser.isIE()) {
		cz = map.getZoom();
		
		if (cz > minMapZoom) {
			map.setZoom(cz-1);
		} else {
			map.setZoom(cz+1);
		}
	}
	*/
	
	var routeKey = jQuery.ajax({
        url: 'kml/shortenURL',
        async: false,
        type: 'POST',
        data: {routes : routeIDString}
    }).responseText;
	
	var layer = new google.maps.KmlLayer(kmlURLPrefix+'/kml/routeKey?'+ routeKey,
		    {suppressInfoWindows: true, preserveViewport:true});
	
	layer.setMap(map);
	
	var idx = routeIDString;
	
	kmlLayer = {layer : layer, routeIDString : idx};
	
	arrayOfKMLLayers[idx] = kmlLayer;
	
	// wait for no more than 20 secs for this KML layer to be loaded
	var timeOutID = setTimeout(executeThisFuncLater(removeBadKMLLayer, idx, cz), 20000);
	
	/*
	google.maps.event.addListener(layer, "metadata_changed", function () {
		alert("metadata_changed for "+routeIDString);
	}); */
	google.maps.event.addListener(layer, "metadata_changed", function () {
		GLog.write("KML Layer metadata_changed for "+idx);
		clearTimeout(timeOutID);
		google.maps.event.clearInstanceListeners(arrayOfKMLLayers[idx].layer);
		
		// go back to original zoom
		if (cz)
			map.setZoom(cz);
	});
	
}


function removeBadKMLLayer(idx, cz) {
	var badLayer = arrayOfKMLLayers[idx];
	
	if (kmlLayer == badLayer)
		kmlLayer = null;
	
	google.maps.event.clearInstanceListeners(badLayer.layer);
	
	try {
		badLayer.layer.setMap(null);		
	} catch (e) {
		GLog.write("Exception in removeBadKMLLayer() for "+idx);
	}
	
	delete badLayer.layer; 
	
	arrayOfKMLLayers[idx] = null;
	
	// restore zoom
	if (cz)
		map.setZoom(cz);
	
	GLog.write("KML layer removed "+idx);
}

//..................................................................................................................................................................................
function toggleRouteLayer(routeID,isRouteClicked, noUpdate)
{
	GLog.write("........in toggleRouteLayer()");
 
    //update the route string
    updateRouteIDString();
    //Suresh - on click on select all routes start
    if (selectAllRoutesCheckBoxActive)
    {
        updateSelectAllCheckBox();
    }
    
    //Suresh - on click on select all routes end

    //
    // REMOVED - Code here should fire in updateDataNow() method.
    //
    
    // update the shelter list
    /*
    if (isSearchDrawerActive)
    {
        refreshSearchList(shelterArray);
    }
    */

    //restart the updates with new filtering
    if (!noUpdate) {
    	showSelectedRoutes(); 
    	//setTimeout(executeThisFuncLater(showHideRouteLayers, routeID), 700); // "showHideRouteLayers("+routeID+")", 1000); // let the vehicles & shelters show before showing the slow polylines
    } // else {
    	showHideRouteLayers(routeID);    	
    //}
    
    // GLog.write("toggleRouteLayer completed for routeID : "+routeID);

}

function executeThisFuncLater(func, arg1, arg2, arg3, arg4, arg5) {
	return function() {
		func(arg1, arg2, arg3, arg4, arg5);
	}
}

function showHideRouteLayers(routeID) {
    for (var x = 0 ; x < routeArray.length; ++x)
        {
            if (routeArray[x].Route)
            {
                if (routeID == routeArray[x].Route.RouteID) {
                	//GLog.write("------------- Route "+routeID+" "+document.getElementById(routeID).checked);

                    if (!document.getElementById(routeID).checked) {
                    	if (!kmlURLPrefix) {
	                        for (var z = 0 ; z < jsRouteLayers[routeID].polyLines.length; ++z) {
	                        	jsRouteLayers[routeID].polyLines[z].setOptions({strokeOpacity:0});
	                            //GLog.write("hid overlay route "+routeID+" polyline "+z);
	                        }
                    	}
                        var index = routesSelectedList.indexOf(routeID);
                        routesSelectedList.splice(index,1);
                    }
                    else {
                        //
                        // Update the Route Layer for the current Route
                        //
                        //GLog.write("<<<<<< in route checked true for "+routeID);
                    	if (!kmlURLPrefix) {
	                        if (jsRouteLayers[routeID].polyLines.length == 0) {
	                        	//GLog.write(routeID + " about to call updateRouteLayer");
	                            updateRouteLayer(routeID);
	                        }
	                        else {
	                            showMapRouteLayers(routeID);
	                        }
                    	}
                        routesSelectedList.push(routeID);
                    }
                    break; // found and processed the input routeID
                }
            }
        }	
}

//..................................................................................................................................................................................
function toggleMapWidth()
{
    if (mapIsWide) 
    {
        top.document.getElementById('dr-utility-drawers').style.display = 'block';
        top.document.getElementById('mapPanel').style.left = '300px';
        top.document.getElementById('mapTL').style.left = '28px';
        top.document.getElementById('mapTop').style.left = '42px';
        top.document.getElementById('mapLeft').style.left = '28px';
        top.document.getElementById('mapBL').style.left = '28px';
        top.document.getElementById('mapBottom').style.left = '42px';
        top.document.getElementById('map').style.left = '42px';
        top.document.getElementById('mE_D2').style.display = 'none';
        top.document.getElementById('mE_D3').style.display = 'none';
        top.document.getElementById('mE_D4').style.display = 'none';
        top.document.getElementById('mE_D5').style.display = 'none';
        top.document.getElementById('mE_D6').style.display = 'none';
        top.document.getElementById('mE_D7').style.display = 'none';
        jQuery("#mE_D8_H1").html("E<br />x<br />p<br />a<br />n<br />d<br />&nbsp;");
        top.document.getElementById('mE_D9_Img').src = 'images/map_wider.gif';
        jQuery("#mE_D9_H1").html("<br />&nbsp;<br />M<br />a<br />p<br>");
        if (isIE6)
        {
            document.getElementById("mapPanel").style.width  = ((document.body.clientWidth - IEMapWidthFactor) + "px");
            document.getElementById("map").style.width  = ((document.body.clientWidth - IEMapWidthFactor - 56) + "px");
            document.getElementById("mapTop").style.width  = ((document.body.clientWidth - IEMapWidthFactor - 56) + "px");
            document.getElementById("mapBottom").style.width  = ((document.body.clientWidth - IEMapWidthFactor - 56) + "px");
            document.getElementById("mapTR").style.left  = ((document.body.clientWidth  - IEMapWidthFactor - 14) + "px");
            document.getElementById("mapRight").style.left  = ((document.body.clientWidth  - IEMapWidthFactor - 14) + "px");
            document.getElementById("mapBR").style.left  = ((document.body.clientWidth  - IEMapWidthFactor - 14) + "px");
        }
        mapIsWide = false;
    }
    else
    {
        top.document.getElementById('dr-utility-drawers').style.display = 'none';
        top.document.getElementById('mapPanel').style.left = '0px';
        top.document.getElementById('mapTL').style.left = '35px';
        top.document.getElementById('mapTop').style.left = '49px';
        top.document.getElementById('mapLeft').style.left = '35px';
        top.document.getElementById('mapBL').style.left = '35px';
        top.document.getElementById('mapBottom').style.left = '49px';
        top.document.getElementById('map').style.left = '49px';
        top.document.getElementById('mE_D2').style.display = 'block';
        top.document.getElementById('mE_D3').style.display = 'block';
        top.document.getElementById('mE_D4').style.display = 'block';
        top.document.getElementById('mE_D5').style.display = 'block';
        top.document.getElementById('mE_D6').style.display = 'block';
        top.document.getElementById('mE_D7').style.display = 'block';
        jQuery("#mE_D8_H1").html("S<br />h<br />o<br />w<br />&nbsp;")
        top.document.getElementById('mE_D8_H1').style.display = 'block';
        top.document.getElementById('mE_D9_Img').src = 'images/map_narrower.gif';
        jQuery("#mE_D9_H1").html("<br />&nbsp;<br />T<br />o<br />o<br />l<br />s<br>")
        top.document.getElementById('mE_D9_H1').style.display = 'block';
        if (isIE6)
        {
            document.getElementById("mapPanel").style.width  = ((document.body.clientWidth - 28) + "px");
            document.getElementById("map").style.width  = ((document.body.clientWidth  - 84) + "px");
            document.getElementById("mapTop").style.width  = ((document.body.clientWidth  - 84) + "px");
            document.getElementById("mapBottom").style.width  = ((document.body.clientWidth  - 84) + "px");
            document.getElementById("mapTR").style.left  = ((document.body.clientWidth - IEMapLeftOffset) + "px");
            document.getElementById("mapRight").style.left  = ((document.body.clientWidth - IEMapLeftOffset) + "px");
            document.getElementById("mapBR").style.left  = ((document.body.clientWidth - IEMapLeftOffset) + "px");
        }
        mapIsWide = true;
    }
    
    google.maps.event.trigger(map, 'resize');
    
    //
    // thomasp - Fixes map updates on width toggle.
    //
    //var centerReference = map.getCenter();
    //map.checkResize();
    //map.setCenter(centerReference);
}

//..................................................................................................................................................................................
// Generalized function, for constructing Route List sub-menus based on information from a locality-specific .xml configuration file.
function getOptionsList(a_index,z_index2)
{
    var z_index2_li = z_index2;
    z_index2++;
    var optionsList = "<ul id='submenu" + z_index2_li + "' style='z-index:" + z_index2 + ";'>";
    z_index2++;
    menusByMenu = menusByRoute[a_index].getElementsByTagName("r_menu");  // Only one menu per route, so loop not required to proceed, but menusByMenu[0] must be explicitly indexed.
    menusByItem = menusByMenu[0].getElementsByTagName("r_menu_item");
    // Parse the menu_items and load the label and link into an anchor element for each menu_item.
    for (var c =0; c < menusByItem.length; c++)
    {
        var url = menusByItem[c].getElementsByTagName("m_link")[0].childNodes[0].nodeValue;
        var label = menusByItem[c].getElementsByTagName("m_label")[0].childNodes[0].nodeValue;
        optionsList += "<li style='z-index:" + z_index2 + ";'>";
        optionsList += "<div style='z-index:" + z_index2 + "; color:#000000; cursor:pointer; cursor:hand; text-align: center' onclick='displayMenu(\"" + url + "\")'>";
        optionsList += label;
        optionsList += "</div>";
        optionsList += "</li>";
    }
    optionsList += "</ul>";
    return optionsList;
}

//..................................................................................................................................................................................
function hideRouteSubMenu(zid)
{
    var menu_id = "submenu" + zid;
    var icon_id = "icon" + zid;
    var label_id = "label" + (zid - 1000);  // Note reduction of zIndex2 to value of zIndex.
    top.document.getElementById(menu_id).style.display = 'none';
    top.document.getElementById(icon_id).src = 'images/menu_selector_normal.gif';
    top.document.getElementById(label_id).style.color = 'black';
}

//..................................................................................................................................................................................
function showRouteSubMenu(zid)
{
    var menu_id = "submenu" + zid;
    var icon_id = "icon" + zid;
    var label_id = "label" + (zid - 1000);  // Note reduction of zIndex2 to value of zIndex.
    top.document.getElementById(menu_id).style.display = 'block';
    top.document.getElementById(icon_id).src = 'images/menu_selector_active.gif';
    top.document.getElementById(label_id).style.color = '#ff0000';
}

//..................................................................................................................................................................................
// Construct Group Shelter List menu based on information in the Shelter Group object.
function getGroupShelterList(groupObj)
{
    var groupShelterList  = "";
    groupShelterList += "<div class=\""+(groupObj.isMinor() ? "labelMinorShelterGroupInstructions" : "labelShelterGroupInstructions")+"\">\n";
    groupShelterList += "  <h1 class=\""+(groupObj.isMinor() ? "labelMinorShelterGroupInstructions_H1" : "labelShelterGroupInstructions_H1")+"\" >Multi-Stop Icon<br />Select A Stop Below:</h1>\n";
    groupShelterList += "</div>\n";
    groupShelterList += "<div class=\"LabelShelterGroupStopsList\">\n";

    //
    // Check to see if the group has been pulled apart and reset the items.
    //
    var foundShelter = false;
    if (groupObj.isShelterLabelActive)
    {        	
	    for (var c = 0; c < groupObj.shelters.length; c++)
	    {
	            if (groupObj.activeShelterLabelID == groupObj.shelters[c].shelterID)
	            {
	                foundShelter = true;
	                break;
	            }
	    }
    }
    
    if (!foundShelter)
    {
        groupObj.isShelterLabelActive = false;
        groupObj.activeShelterLabelID = null;
        groupObj.activeShelterDOMId = null;
    }
    
    // Parse the Shelter Grouping for included Shelters/Stops and load the label and link into an anchor element for each Shelter.
    for (var i = 0; i < groupObj.shelters.length; i++)
    {
        //
        // Determine if the group has an active label. If so change its onmouseover color.
        //
        var labelColor = "#000000";
        var mouseColor = "#0000ff";
        var className = "";
        var foundActiveShelter=false;
        if (groupObj.isShelterLabelActive)
        {
            if (groupObj.activeShelterLabelID == groupObj.shelters[i].shelterID)
            {
                labelColor = "#0000ff";
                mouseColor = "#0000ff";
                foundActiveShelter = true;                
            }
            else
            {
                labelColor = "#CCCCCC";
                mouseColor = "#CCCCCC";
            }
        }
        else
        {
            labelColor = "#000000";
            mouseColor = "#0000ff";
        }
        
        if ((i % 2) != 0)
        {
            className = groupObj.shelters[i].minor ? "labelShelterGroupMinorStopRowEven" : "labelShelterGroupStopRowEven";
        }
        else
        {
            className = groupObj.shelters[i].minor ? "labelShelterGroupMinorStopRowOdd" : "labelShelterGroupStopRowOdd";
        }
        
        groupShelterList += "<div ";
        if (foundActiveShelter) {
        	groupObj.activeShelterDOMId = "activeShelterId"+ activeShelterId++;
        	groupShelterList += " id=\""+ groupObj.activeShelterDOMId +"\" ";
        	GLog.write("activeShelterId"+ activeShelterId);
        }
        groupShelterList += " style=\"color:" + labelColor + "\" class=\""+className+"\">";
        
        groupShelterList += "<a style=\"color:" + labelColor + ";\"";
        groupShelterList += "   onmouseover=\"this.style.color='" + mouseColor + "'; jsShelterLabelController(" + groupObj.shelters[i].shelterID + ", " + true + ", " + false;
        groupShelterList += ");\" onmouseout=\"this.style.color='" + labelColor + "'; jsShelterLabelController(" + groupObj.shelters[i].shelterID + ", " + false + ", " + false;
        groupShelterList += ");\" onclick=\"jsShelterLabelController(" + groupObj.shelters[i].shelterID + ", " + true + ", " + true + ");\"";
        groupShelterList += ">";
        groupShelterList += groupObj.shelters[i].shelterName;
        groupShelterList += "</a>";
        groupShelterList += "</div>";
    }
    groupShelterList += "</div>";
    groupShelterList += "<div class=\"labelCloseIcon\"></div>";
    
    // GLog.write(groupShelterList);
    
    return groupShelterList;
}

//..................................................................................................................................................................................
function unload() {

    //
    // Google mape unload function.
    //
    //google.maps.Unload();
    
	//if (!Browser.isIE() || (Browser.isIE() && Browser.version() != 8))
		purge(document);
}

function refreshSearchList(tShelterArray)
{
    //
    // Stop search selected.
    //
    if (stopSearchFlag) {
        jQuery("#routeSearchSelection").focus();
    }

    //
    // Look to see if the shelter array has changed. If so update it.
    //
    //if (shelterSearchListArray.length == 0)
    {
        shelterSearchListArray = [];
        var listIndex = 0;
        for (seCounter = 0 ; seCounter < tShelterArray.length ; seCounter++)
        {
            //
            // Pull a Shelter and get its name and id
            //
            var tShelter = tShelterArray[seCounter];

            if (!tShelter)
            {
                continue;
            }

            //
            // Store this information in a Map for use in our completion list.
            //
            var tssListItem = new ShelterSearchListItem(tShelter.shelterID, tShelter.shelterName);
            shelterSearchListArray[listIndex++] = tssListItem;
        }

        //
        // Now sort the array alphabetically
        //
        shelterSearchListArray.sort(shelterSort);

        htmlString = "<input id='routeSearchSelection' type='text'/>";
        jQuery("#search").html(htmlString);

        jQuery("#routeSearchSelection").autocomplete(shelterSearchListArray, {
            minChars: 3,
            max: listIndex,
            top: 7,
            left: 0,
            width: 292,
            mustMatch: false,
            scroll: true,
            scrollHeight: 140,
            autoFill: false,
            matchContains: true,
            selectFirst: true,
            formatItem: acFormatItem
        }).result(acResult);

        jQuery("#routeSearchSelection").focus();
   }
}

function acFormatItem(row, position, count, search)
{
    return row.name;
}

function acResult(event, item) {
    var tShelter = shelterArray[item.id];

    if (tShelter) {

    	if (!isMinorSheltersMode && tShelter.minor) {
    		// minor stop and not showing them
    		// so show label and bring marker to top
    		tShelter.setVisible(true);
    		tShelter.marker.setZIndex(Shelter.onTopZIndex);
    	} else {
        	if (!tShelter.marker) {
        		// shelter not showing but we just need to stick label...so hide marker
        		tShelter.setVisible(true);
        		tShelter.marker.setVisible(false);
        	}
    	}

        //adjust the label offset
        adjustItemLabelOffset(tShelter);

        tShelter.updateShelterGroupIconAndStickLabel();
    }

    if (tShelter && tShelter.position)
    	map.panTo(tShelter.position);
}

function shelterSort(a,b) {
    var x = a.name;
    var y = b.name;

    return ((x < y) ? -1 : ((x > y) ? 1 : 0));
}

function setSearch(val){
    stopSearchFlag = val;
    if (val) {
    	setTimeout(executeThisFuncLater(focusSearchBox), 100);
    }    	
}

function focusSearchBox() {
	jQuery("#routeSearchSelection").focus();
}

//..................................................................................................................................................................................
// updateRoute - Updates route lists and check boxes.
function updateRoute()
{
    jQuery.get("packet/json/route", getJSONRoute);
}

//..................................................................................................................................................................................
// updateRouteLayer - Updates the route layers on the
//                    map. Also used for vehicle/stop
//                    filtering if one of these is active.

var numRouteLayersQueue = 0;

function updateRouteLayer(routeID) {

	var timeOut = 100; // 100 msec for non-IE	
	
	if (!Browser.isIE()) {
		setTimeout(executeThisFuncLater(jQuery.get, "packet/json/routelayer?"+routeID, getJSONRouteLayer), timeOut);
	} else {
		// on IE we wait for 3 secs before getting the next route layer
		GLog.write("router layers queue size = " + numRouteLayersQueue);
		setTimeout(executeThisFuncLater(jQuery.get, "packet/json/routelayer?"+routeID, getJSONRouteLayer), 3000*numRouteLayersQueue);
		numRouteLayersQueue++;
		setTimeout(decrementRouteLayersQueue, numRouteLayersQueue*3000);
		
	}
}

function decrementRouteLayersQueue() {
	numRouteLayersQueue--;
}

//..................................................................................................................................................................................
// updateVehicleMarker - Updates vehicles markers on the map.
function updateVehicle(routeID) {
	 //+ "&forceUpdate=true"
    if (!routeID) {
        jQuery.get("packet/json/vehicle?routes=" + getRouteIDsForHTTPRequest() + "&lastVehicleHttpRequestTime=" + lastVehicleHttpRequestTime, getJSONVehicle);
    } else {
        jQuery.get("packet/json/vehicle?routes=" + routeID + "&lastVehicleHttpRequestTime=" + lastVehicleHttpRequestTime, getJSONVehicle);
    }
}

//..................................................................................................................................................................................
// updateShelterMarker - Updates Shelter markers on the map.
function updateShelter(routeID) {
	//  + "&forceUpdate=true"
    if (!routeID) {
        jQuery.get("packet/json/shelter?routes=" + getRouteIDsForHTTPRequest() + "&lastShelterHttpRequestTime=" + lastShelterHttpRequestTime, getJSONShelter);
    } else {
        jQuery.get("packet/json/shelter?routes=" + routeID + "&lastShelterHttpRequestTime=" + lastShelterHttpRequestTime, getJSONShelter);
    }
}
//..................................................................................................................................................................................
// updateStatus - Updates contents of various status indicators of the servlet environment.
function updateStatus()
{
    jQuery.get("packet/json/status", getJSONStatus);
}

//..................................................................................................................................................................................
// updateServerTime - Updates contents of server time for display.
function updateServerTime() {
    jQuery.get("packet/json/time", getJSONTime);
}

//..................................................................................................................................................................................
// doCookiesExistWithPrefix - checks to see if cookies exist with names beginning with given prefix
//
function doCookiesExistWithPrefix(prefix)
{
	var result=false;
    
	var  allCookies = document.cookie;
	var re = /\s*;\s*/;
	var cookieArray = allCookies.split(re);	
	var reNameValue = /\s*=\s*/;
	
	for (i=0; i<cookieArray.length; i++) {
		// each element should be a name=value pair
		var e = cookieArray[i];
		
		var pair = e.split(reNameValue);		
		if (pair.length >= 2) {
			if (pair[0].trim().indexOf(prefix) == 0) {
				result=true;
				break;
            }
        }
    }

	return result;
}

function createCookie(name,value,days){	
	var expires = "";
    if (days) {
        var date = new Date();
        date.setTime(date.getTime()+(days*24*60*60*1000));
        expires = "; expires="+date.toGMTString();
    }
    document.cookie = name+"="+value+expires+"; path=/";
}

//
// updateAlerts - Updates the browser with the various alerts the user may have configured.
//
function updateAlerts(cookieAlertTag)
{
	/*
	if (!Browser.isIE()) {
		// browser is not IE ... send request only if Alert cookies exist
	    if (doCookiesExistWithPrefix(cookieAlertTag)) {
	        jQuery.get("packet/json/alerts", getJSONAlerts);
	    }
	} else {
	*/
		// IE has 4K limit on total cookie size per domain for document.cookie to function correctly
		// even though the cookies may actually exist. work around it by always sending request
	
		//
		// to handle server side persistent alerts...we have to always make the request..irrespective of presence/absense of cookies
		//
		jQuery.get("packet/json/alerts", getJSONAlerts);
	//}

    //set the timer
    setTimeout("updateAlerts(\"" + cookieAlertTag + "\")", alertTimeout);    
}

//..................................................................................................................................................................................
// readMenusXMLFile - Reads the sub-menu information from the corresponding .xml file..
function readMenusXMLFile() {
	jQuery.ajax(
			{
				async : false,
				url : "xml/routeMenus",
				dataType : "xml",
				error : function () {
			        haveRouteMenus = false;
			        alert("ERROR : Could not load route sub-menus");				
				},
				success : function (data) {
					menusByRoute = data.getElementsByTagName("route");
				}
			}
	);
}

function latLngToDivPixel(point)
{
    var t = this;
    
    return t.map.fromLatLngToDivPixel(point);
}

function latLngToPixel(point)
{
    var t = this;
    
    return t.map.fromLatLngToContainerPixel(point);
}

//
// zOrder : Function used to alter the zOrder of the elements on the Google
//          map.
//
function zOrder(marker,b)
{
    return -marker.visualOrder*1000000;
}

function zOrderVisible(visibleMarker,b)
{
    return -visibleMarker.visualOrder*1000000;
}

function launchURL(url)
{    
    //
    // Check to see if the map has been expanded.
    //
    if (mapIsWide)
    {
        toggleMapWidth();
    }
    
    //
    // Check state of alert screen interaction.
    //
    queryAlertFlowState();
    
    switch (alertFlowState)
    {
        case "CREATE":
            if (confirm("You are already creating another Alert would you like to continue?"))
            {
            	setSearch(false);
                jQuery("#drawers").accordion("activate", "#alert-drawer");
                setTimeout("displayAlertsDrawer(\""+url+"\")", 1000);
                // jQuery("#alerts").attr("src", url);
            }
            break;
        case "EDIT":
            if (confirm("You are already editing another Alert would you like to continue?"))
            {
            	setSearch(false);
                jQuery("#drawers").accordion("activate", "#alert-drawer");
                setTimeout("displayAlertsDrawer(\""+url+"\")", 1000);
                // jQuery("#alerts").attr("src", url);
            }
            break;
        default:
        	setSearch(false);
            jQuery("#drawers").accordion("activate", "#alert-drawer");
            setTimeout("displayAlertsDrawer(\""+url+"\")", 1000);
            // jQuery("#alerts").attr("src", url);
            break;
    }
}

function displayAlertsDrawer(url) {
	jQuery("#alerts").attr("src", url);	
}

function displayMenu(url)
{
    window.open(url);
    return false;
}

function queryAlertFlowState()
{
    //
    // NOTE: This call is made asynchronously to prevent the Javascript from
    //       moving to far ahead in the logic calling this function before
    //       it returns.
    //
    var json = eval('(' + jQuery.ajax({
        url: "alert/getWindowState.htm",
        async: false
    }).responseText + ')');
    alertFlowState = json.Response.state;
}

function getEditAlerts()
{
    //
    // Here we'll update the Alert drawer as well with the edit page
    //
    queryAlertFlowState();
    
    if (alertFlowState == "NONE" || isPageLoading) {
        jQuery("#alerts").attr("src", "alert/editAlertsPage.htm");
    }
        
}

function updateSelectAllCheckBox(){
    var ii;
    var routeIDArray = routeIDListString.split(",");
    var routeArrayLength = routeIDArray.length;
    var numberOfRoutesChecked = 0;

    for(ii = 0;ii < routeArrayLength; ii++){
        if(document.getElementById(routeIDArray[ii]).checked){
            numberOfRoutesChecked++;
        }        
    }
    if(numberOfRoutesChecked == routeArrayLength){
        document.getElementById("allRoutesCB").checked = true;
    }else{
        document.getElementById("allRoutesCB").checked = false;
    }
}

var allStopsShowing = true;
function onClickAllRoutes(isChecked){
    var toogleRouteId = routeIDListString;
    if(toogleRouteId != ""){
        var separator = ",";
        var routeIdArray = toogleRouteId.split(separator);
	var routeCount = routeIdArray.length;
        var i = 0;
        var routeId;
	for (i = 0; i < routeCount; i++) {
            routeId = routeIdArray[i];
            if(isChecked){
                document.getElementById(routeId).checked = true;
            }else{
                document.getElementById(routeId).checked = false;
            }            
    }
            showRouteLayers();
    }
    allStopsShowing = true;

    if (kmlURLPrefix) {
    	handleRouteClickViaKMLLayer(null);
    }

    // GLog.write("onClickAllRoutes() completed for " +isChecked);
    
    return true;
}

function suppressRoute(thisRoute) {
	var result = false;
	
	for (i=0; i<routesToBeSuppressedInMenu.length; i++) {
		if (thisRoute.LogNum == routesToBeSuppressedInMenu[i]) {
			result = true;
			break;
		}
	}
	
	return result;
}

function suppressRouteID(routeID) {
	var result = false;
	
	var rIDs = stringRoutesToBeSuppressed.split(",");
	var id = ""+routeID;
	for (i=0; i<rIDs.length; i++) {
		if (id == rIDs[i]) {
			result = true;
			break;
		}
	}
	
	return result;
}

function getRouteIDsForHTTPRequest() {
	// if any routes are filtered then tracking only vehicles are not to be shown
	var result = routesSelectedList.length > 0 ? "" : stringRoutesToBeSuppressed;
	
	if (result.length > 0)
		result = result + "," + routeIDString;
	else
		result = routeIDString;
		
	return result;
}

// remove routes that will be suppressed from the menu on left
// add their routeID to the global string

function fixRouteArray(ra) {

	var result=[], j=0;
	for (var i=0; i<ra.length; i++) {
		if (suppressRoute(ra[i].Route)) {
			if (stringRoutesToBeSuppressed.length <=0)
				stringRoutesToBeSuppressed = "" + ra[i].Route.RouteID;
			else
				stringRoutesToBeSuppressed += "," + ra[i].Route.RouteID;
			suppressedRouteLogNums.push(ra[i].Route.LogNum);
		} else {
			result[j++] = ra[i];
		}
	}

	return result;
}

function exists(obj) {
	  if (obj)
		return true;
		
	  return false;	
}

function compareShelters(o1, o2) {
	var s1 = "", s2 = "";

	if (exists(o1))
		s1 = o1.shelterName;

	if (exists(o2))
		s2 = o2.shelterName;

	if (s1 == "") {
		if (s2 != "")
			return 1;
		else
			return 0;
	} else {
		if (s2 == "")
			return -1;
	}

	var result=0;
	
    // match a sequence of characters that are not digits or a sequence of digits
    var pat1 = new RegExp("(([^\\d]+)|(\\d+))", "g"), pat2 = new RegExp("(([^\\d]+)|(\\d+))", "g");

    var array1, array2;
    
    while (true) {
    	if ((array1 = pat1.exec(s1)) != null) {
    		if ((array2 = pat2.exec(s2)) != null) {
    			// both exist get to work
				
    			var $2letters = array2[2], $1letters = array1[2];
    			var $1digits = array1[3], $2digits = array2[3];
    			
				// alert(s1+" "+$1letters + " " + $1digits + " " + s2 + " " + $2letters + " " + $2digits);
				
    			if (exists($1letters) && exists($2letters)) {
    				if ($1letters.equalsIgnoreCase($2letters)) {
    					// same sequence of letters...compare digits if both exist
						result = compareDigits($1digits, $2digits);
						if (result != 0)
							break;		        					
    				} else {
    					result = $1letters.compareToIgnoreCase($2letters);
    					break;
    				}
    			} else if (exists($1letters)) {
					result = 1;
					break;		        				
    			} else if (exists($2letters)) {
    				result = -1;
    				break;
    			} else {
    				// no letters in s1 or s2
					result = compareDigits($1digits, $2digits);
					if (result != 0)
						break;		        					
    			}		        			
    		} else {
    			// s1 exists but not s2
    			result = 1;
    			break;
    		}
    	} else if ((array2 = pat2.exec(s2)) != null) {
    		// s2 exists but not s1
    		result = -1;
    		break;        		
    	} else {
    		// neither exists...bail
    		break;
    	}        	
    }
    
    return result;
}

function compareDigits(d1, d2) {
	var result;
	
	if (exists(d1) && exists(d2)) {
		if (!d1.equalsIgnoreCase(d2)) {
			var i1 = parseInt(d1, 10), i2 = parseInt(d2, 10);
			if (i1 == i2) {
				result = d1.compareToIgnoreCase(d2);
			} else {
				if (i1 < i2)
					result = -1;
				else
					result = 1;
			}
		} else {
			result = 0;
		}			
	} else if (exists(d1))
		result = 1;
	else if (exists(d2))
		result = -1;
	else
		result = 0; // both d1 & d2 are null

	return result;		
}

//
//	showSelectedRoutes() can be called either due to a true route selection change or when shelters are added in getJSONShelter() 	
//	in the first case the 2nd arg (addedShelters) is false and true for the 2nd case
//
var showSelectedRoutes = (function () {
	var secondPartOfFunction = function (addedShelters) {
		// if shelter has a selected route -- show its marker o.w. hide it
		var localShelterGroupArray = [], searchableShelters = [];
		var allRoutesShelterGroups = arrayOfShelterGroupArray[map.getZoom()];
		var addedShelterGroups = false;
		
		if (!allRoutesShelterGroups)
			return; // if no shelter groups at this zoom level ... bail

		isMinorSheltersMode = numRoutesForMinorStops == 0 || selectedRouteLogNums.length <= numRoutesForMinorStops;

		if (!addedShelters) {
		} else {
		    sortedShelterArray = [].concat(shelterArray);
		    // sort shelters by name
		    sortedShelterArray.sort(compareShelters);
		}
		
		for (var i=0; i<sortedShelterArray.length; i++) {
			var shelter = sortedShelterArray[i];
			if (shelter) {
					var visible = false;
					var isShelterStuck = false;

					for (var j=0; j<shelter.routeIDs.length; j++) {
						if (selectedRouteLogNums.indexOf(shelter.routeIDs[j]) != -1) {
							// if shelter is on selected route(s) then it is searchable regardless of its visibility
							searchableShelters.push(shelter);
							isShelterStuck = shelter.label && shelter.label.isClicked;
							if (shelter.minor) {
								if (isMinorSheltersMode)
									visible = true;
							} else {
								//GLog.write("matched route => "+shelter.routeIDs[j]);
								visible = true;
							}
							break;								
						}
					}
					
					shelter.setVisible(false);

					if (isShelterStuck) {
						shelter.setVisible(true);
						shelter.label.stickIt();
						
						if (!isMinorSheltersMode && shelter.minor) {
							// if stuck label is minor and we are not showing minor stops then we
							// to show stop icon by bringing its marker to the top of zOrder
							shelter.marker.setZIndex(Shelter.onTopZIndex);
						}
					}

					if (visible) {
						//shelter.setVisible(true);// if label is stuck then it will continue to show...no need to do anything
						if (addShelterToGroup(shelter, localShelterGroupArray) == null) {
						
							var shelterGroup = null;
							// first get unused shelterGroup
							for (j=0; j < allRoutesShelterGroups.length; j++) {
								if (localShelterGroupArray.indexOf(allRoutesShelterGroups[j]) == -1) {
									shelterGroup = allRoutesShelterGroups[j];
									break;
								}
							}
							
							if (shelterGroup) {
								// prep this shelterGroup for reuse
								shelterGroup.isShelterLabelActive = false;
								shelterGroup.activeShelterLabelID = null;
								shelterGroup.labelID = null;
								shelterGroup.shelters = [];
								newShelterAndGroup(shelter, shelterGroup);
								localShelterGroupArray.push(shelterGroup);
								
							} else {
								// could not get existing shelterGroup...is this an error?
								//GLog.write("could not find shelterGroup in showSelectedRoutes()");
					            // create new shelterGroup and add this shelter to it..
					            shelterGroup = new ShelterGroup();
					            newShelterAndGroup(shelter, shelterGroup);

					            //add to the group array
					            localShelterGroupArray.push(shelterGroup);
					            addedShelterGroups = true;
							}
						}
					} else {
						// shelter not visible...hence not grouped so no parent
						shelter.parent = null;
						shelter.grouped = false;
						//shelter.setVisible(false);
						//shelter.label.hide(); // in case it is stuck
					}
			}
		}
				
		// gather stuck group labels
		var stuckGroupLabels = [];
		for (var i=0; i<shelterGroupArray.length; i++) {
			var sg = shelterGroupArray[i];
			if (sg && sg.label && sg.label.isClicked) {
				stuckGroupLabels.push(sg.shelters[0]);
			}
		}

		// hide current shelter groups
		for (i=0; i<shelterGroupArray.length; i++) {
			var sg = shelterGroupArray[i];
			if (sg) {
				if (sg.marker)
					sg.marker.setVisible(false);
				
				if (sg.label)
					sg.label.hide();
			}
		}
			
		shelterGroupArray = localShelterGroupArray;
		
		if (addedShelterGroups) {
			arrayOfShelterGroupArray[map.getZoom()] = shelterGroupArray;
		}
		
		createOrPositionShelterGroupMarkers();
		
		// re-stick stuck group labels if appropriate
		for (var i=0; stuckGroupLabels && i < stuckGroupLabels.length; i++) {
			for (var j=0; j<shelterGroupArray.length; j++) {
				var sg = shelterGroupArray[j];
				if (sg) {
					if (sg.shelters.indexOf(stuckGroupLabels[i]) != -1) {
						sg.label.stickIt();
						break;
					}
				}
			}
		}
		
        //
        // Update the list of shelters for use with the Search drawer
        //
        // NOTE: isSearchDrawerActive is defined in index.jsp
        //
        if (isSearchDrawerActive) {
        	refreshSearchList(searchableShelters);
        }

		// get data for shelters on selected routes only if we did not just get the shelter data
        // "addedShelters" flag being true means shelters were just received and created hence no need to get them again 
        if (!addedShelters)
        	setTimeout(executeThisFuncLater(jQuery.get, "packet/json/shelter?routes=" + getRouteIDsForHTTPRequest() + "&lastShelterHttpRequestTime=" + 0 + "&forceUpdate=true", getJSONShelter), 10);

        // update vehicles
        setTimeout(executeThisFuncLater(jQuery.get, "packet/json/vehicle?routes=" + getRouteIDsForHTTPRequest() + "&lastVehicleHttpRequestTime=" + 0 + "&forceUpdate=true", getJSONVehicle), 10);

		adjustMarkerLabelOffsets();		
	};
	
	return function (addedShelters) {

		// show/hide vehicle markers based on selected routes -- this is causing vehicles to flash/flicker 
		// NOOOO!!! this will controlled entirely in getJSONVehicle() per current selected routes
		/*
	    for (var x = 0 ; x < vehicleArray.length ; ++x)
	    {
	    	var vehicle = vehicleArray[x]; 
	        if (vehicle) {
	        	if (selectedRouteLogNums.indexOf(vehicle.routeID) != -1) {
	        		vehicle.marker.setVisible(true);
	        	} else {
	        		vehicle.marker.setVisible(false);
	        		vehicle.label.hide();
	        	}
	        }
	    }
	    */
	    
	    // setTimeout(executeThisFuncLater(secondPartOfFunction, stuckGroupLabels), 100);
		secondPartOfFunction(addedShelters);
	};
	
})(); 

function setZoombarLimits() {
	 mapType = map.mapTypes[map.getMapTypeId()];
	 if (mapType) {
		 mapType.maxZoom = maxMapZoom;
		 mapType.minZoom = minMapZoom;
		 map.setZoom(map.getZoom());
		 GLog.write("&&&&&&&&&&&&&&&&&& GOT mapType !!!!!!!!!!!!!!!!");
	 } else
		 GLog.write("did not get mapType in setZoombarLimits()");
}

function checkDownloadFirefox(){
    if (!Browser.isFireFox()  && !Browser.isChrome() && !Browser.isSafari() && !Browser.isOpera()) {
        if (!doCookiesExistWithPrefix("doNotRemindCheckBoxStatus")) {
        	jQuery("#browserCheckDialog").dialog("open");
        } else
        	jQuery("#browserCheckDialog").dialog("destroy");
    } else
    	jQuery("#browserCheckDialog").dialog("destroy");
}

function dismissBrowserCheckDialog(){
	if (jQuery("#cbFireFoxDownload").is(':checked')) {
        var date = new Date();
        date.setTime(date.getTime()+(10000*24*60*60*1000));
		createCookie("doNotRemindCheckBoxStatus", "CHECKED", 10000);		
	}
	jQuery("#browserCheckDialog").dialog("destroy");
}

function showIEWarning(){
    if (!doCookiesExistWithPrefix("noIEWarning")) {
    	jQuery("#ieWarningDialog").dialog("open");
    }
}

function dismissIEWarning(){
	if (jQuery("#cbIEWarning").is(':checked')) {
        var date = new Date();
        date.setTime(date.getTime()+(10000*24*60*60*1000));
		createCookie("noIEWarning", "CHECKED", 10000);
		
		// no longer need the dialog
		jQuery("#ieWarningDialog").dialog("destroy");
	} else
		jQuery("#ieWarningDialog").dialog("close");
}

//]]>

