//
// 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;
}

//******************************************************************************
// 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  = Array();
var                xmlMenuDoc  = new Object();    // Empty object reference to hold XML file contents defining the Route List Sub-Menus (if there are any).
var              menusByRoute  = Array();         // Empty array reference to hold XML file contents from each "route" element.
var               menusByMenu  = Array();         // Empty array reference to hold XML file contents from a "menu" child element of a given "route" element.
var               menusByItem  = Array();         // 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                streetview  = null;            // Street View
var                  geocoder  = null;            // Geocorder
var                     isIE6  = false;           // IE6 flag
var              showAllBuses  = false;           // Temporary debugging flag; toggle by double-clicking on the OTvia Logo.  It might be useful to make this settable through web.xml.
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        bFullVehicleUpdate  = true;            // Forces the vehicles to do full update
var        forceVehicleUpdate  = false;           // Keeps the status of the forced update for other methods.
var        bFullShelterUpdate  = true;            // Forces the shelters to do full update
var        forceShelterUpdate  = false;           // Keeps the status of the forced update for other methods.
var             dataTimeoutID  = 0;               // the timer ID for an event
var         serverTimeTimerID  = 0;               // the timer ID for the Time event
var               dataTimeout  = 3000;            // the timeout for the data
var           dataFailTimeout  = 10000;           // the timeout for http failure modes
var             statusTimeout  = 60000;           // timeout for query
var              alertTimeout  = 30000;           // timeout for Alert query
var         serverTimeTimeout  = 1000;            // timeout for server time check
var             bRoutesLoaded  = false;           // the routes are loaded
var           bHTTPInProgress  = false;           // bool to let us know that an http is in progress
var             routeIDString  = "";              // keep the route id string globally
var         routeIDListString  = "";              // keep the list of route id string globally for seleting all routes
var      cookieAlertTagString  = "OTvia2.Alert";  // Name prefix for Alert Cookies, to facilitate their programmatic identification.
var            bProcessGroups  = true;            // process the groups
var            alertFlowState  = undefined;       // The current state of the Alert Flow Interaction screen.
var            launchURLStatus = false;
var              isPageLoading = false;
var lastVehicleHttpRequestTime = 0;
var lastShelterHttpRequestTime = 0;
var lastOutOfServiceVehicleHttpRequestTime = 0;
var                  imagepath = "images";
var             imageExtension = ".png";

var             stopSearchFlag = false;

//**********************************************************************************************************************************************************************************
// ARRAYS
// Arrays used to mirror vehicles and their labels.
// This is used to keep track of the google.maps.Marker objects
// used to track objects on the GMap2.
//
var vehicleMarkers      = new Array();
var vehicleLabels       = new Array();

var vehicleArray            = new Array();
var outOfServicevehicleArray = new Array();
var shelterArray            = new Array();
var shelterGroupArray       = new Array();

var shelterSearchListArray  = new Array();
var vehicleSearchListArray  = new Array();


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

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

    this.filtered         = false;
    
    //
    // Updates for label refactoring code
    //
    this.visibleMarker    = null;
    this.marker           = null;
    this.directionalIcon  = null;
    this.directionalIconVisualOrder = 1;
    
    this.quadrant         = 0;
    this.vehicleIDLabel   = null;
    this.vehicleIDLabelVisualOrder   = 4;
    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,-11);
    this.quadOffset2      = new google.maps.Size(11,-11);
    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 = 0;
}

//
// Shelter Object
//
function Shelter(shelterID,shelterName)
{
    this.shelterID        = shelterID;
    this.visualOrder      = 3;
    
    this.shelterName      = shelterName;
    
    this.filtered         = false;
    this.grouped          = false;
    
    this.stops            = [];
    this.activeStopPatNum = null;

    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.labelOffset      = null;
    this.labelText        = null;
    this.groupedLabelText = null;
    this.newText          = null;

    this.infoWindowHTML   = null;
    this.labelVisible     = false;

    //
    // Location for label per object.
    //
    this.quadOffset1      = new google.maps.Size(-(330+(shelterIconWidth/2)+4),-shelterIconAnchorOffset);
    this.quadOffset2      = new google.maps.Size((shelterIconWidth/2),-shelterIconAnchorOffset);
    this.quadOffset3      = new google.maps.Size((shelterIconWidth/2), -(shelterIconHeight/2)); // 77
    this.quadOffset4      = new google.maps.Size(-(330+(shelterIconWidth/2)+4),-(shelterIconHeight/2)); // 77

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

    this.gEventHandle     = null;
    
    this.isLabelActive    = false;
    
    this.parent           = null;
    
    this.lat              = 0;
    this.lon              = 0;
}

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

//
// Vehicle Search List item
//
function VehicleSearchListItem(id, value)
{
    this.id               = id;
    this.value             = value;
}
//
// Shelter Group Object
//
function ShelterGroup()
{
    this.visualOrder        = 2;
    this.shelters           = [];
    this.activeShelterID    = null;
    this.activeStopPatNum   = null;
    
    //
    // Updates for label refactoring code
    //
    this.marker             = null;
    this.quadrant           = 0;
    this.label              = null;
    this.labelID            = null;
    this.labelClassName     = "labelShelterGroupTooltip";
    this.labelText          = null;
    
    this.infoWindowHTML     = null;
    this.labelVisible       = false;

    //
    // Location for label per object.
    //
    this.quadOffset2        = new google.maps.Size(-(205+(shelterGroupIconWidth/2)+4),-shelterGroupIconAnchorOffset);
    this.quadOffset1        = new google.maps.Size((shelterGroupIconWidth/2),-shelterGroupIconAnchorOffset);
    this.quadOffset4        = new google.maps.Size((shelterGroupIconWidth/2), -77);
    this.quadOffset3        = new google.maps.Size(-(205+(shelterGroupIconWidth/2)+4),-77);

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

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

//
// Stop
//
function Stop(patNum, routeID, routeName)
{
    this.patNum     = patNum;
    this.routeID    = routeID;
    this.routeName  = routeName;

    this.labelText  = null;
}

//
// 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          = new Array();

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

var jsRouteLayers       = new Array();

var stopLocationMarkers = new Array();
var stopLocationLabels  = new Array();

// Global Flags
var mapCenter;

//
// Vehicle Icon
//
var vehicleIcon              = new google.maps.Icon();
vehicleIcon.image            = "images/vehicle_icon.png";
// vehicleIcon.shadow           = "images/vehicle_icon_shadow.png";
vehicleIcon.iconSize         = new google.maps.Size(vehicleIconWidth, vehicleIconHeight);
//vehicleIcon.iconSize         = new google.maps.Size(34, 34);
vehicleIcon.shadowSize       = new google.maps.Size(34, 22);
vehicleIcon.iconAnchor       = new google.maps.Point(17, 17);
vehicleIcon.infoWindowAnchor = new google.maps.Point(17, 11);

//
// Vehicle Directional Arrow
//
// NOTE: The actual image will be assigned once the direction of the vehicle is known.
//
var vehicleDirectionalIcon          = new google.maps.Icon();
vehicleDirectionalIcon.image        = "images/000.png";
vehicleDirectionalIcon.iconSize     = new google.maps.Size(34, 34);
vehicleDirectionalIcon.iconAnchor   = new google.maps.Point(17, 17);

//
// Shelter Icon
//
var shelterIcon              = new google.maps.Icon();
shelterIcon.image            = "images/shelter_icon.png";
// shelterIcon.shadow           = "images/shelter_icon_shadow.png";
shelterIcon.iconSize         = new google.maps.Size(shelterIconWidth, shelterIconHeight); // 19.0, 35.0
shelterIcon.shadowSize       = new google.maps.Size(37.0, 35.0);
shelterIcon.iconAnchor       = new google.maps.Point(7.0, 7.0); // 9.5, 34.0
shelterIcon.infoWindowAnchor = new google.maps.Point(8.0, 6.0);

//
// Shelter Group Icon
//
var shelterGroupIcon              = new google.maps.Icon();
shelterGroupIcon.image            = "images/multi_shelter_icon.png";
// shelterGroupIcon.shadow           = "images/shelter_icon_shadow.png";
shelterGroupIcon.iconSize         = new google.maps.Size(shelterGroupIconWidth, shelterGroupIconHeight); // 19.0, 35.0
shelterGroupIcon.shadowSize       = new google.maps.Size(37.0, 35.0);
shelterGroupIcon.iconAnchor       = new google.maps.Point(7.0, 7.0); // 9.5, 34.0
shelterGroupIcon.infoWindowAnchor = new google.maps.Point(8.0, 6.0);

//
// Transit Center Icon
//
var transitIcon              = new google.maps.Icon();
transitIcon.image            = "images/"+landmarkImage;
transitIcon.iconSize         = new google.maps.Size(transitIconWidth, transitIconHeight); // 35.0, 35.0
transitIcon.shadowSize       = new google.maps.Size(37.0, 35.0);
transitIcon.iconAnchor       = new google.maps.Point(17.5, 17.5); // 9.5, 34.0
transitIcon.infoWindowAnchor = new google.maps.Point(8.0, 6.0);

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



function isActiveRouteLayer(routeID)
{
    for (var x in routeArray)
    {
        if (routeArray[x].Route != null)
        {
            if(routeArray[x].Route.RouteID == routeID)
            {
                if (routeArray[x].Route.LayerActive == true)
                {
                    return true;
                }
            }
        }
    }
    return false;
}

//..................................................................................................................................................................................
// addMapRouteLayers - Adds the current jsRouteLayers to the
//                     map. This was implemented to help with 
//                     the asynchronous call to updateRouteLayer above.
function addMapRouteLayers(routeID)
{
    for (var z = 0 ; z < jsRouteLayers[routeID].polyLines.length; ++z) 
    {
        map.addOverlay(jsRouteLayers[routeID].polyLines[z]);
    }
}

function removeMapRouteLayers(routeID)
{
    for (var z = 0 ; z < jsRouteLayers[routeID].polyLines.length; ++z) 
    {
        map.removeOverlay(jsRouteLayers[routeID].polyLines[z]);
    }  
}

//..................................................................................................................................................................................
// 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 = new Array();
        }
        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");
            }
            // Must be transitioning from RESTART status to OK status.
            else
            {
                document.getElementById("otviaDRAVLServerStatus").style.display = ("none");
                document.getElementById("otviaDRAVLServerStatusMsg").style.display  = ("none");
            }
        }
        
        //  Force initialization of browserTimeWindows on first status update.  Take no other action.
     
        if (browserTimeWindows != null && browserTimeWindows.length == otviaTimeWindows.length)
        {
            var changeInTimeWindow = false;
            for (var k in otviaTimeWindows)
            {
                if (otviaTimeWindows[k].RouteTimeWindow != browserTimeWindows[k].RouteTimeWindow )
                {
                    
                    clearRouteLayer(otviaTimeWindows[k].RouteID);
                    //removeMapRouteLayers(otviaTimeWindows[k].RouteID);
                    jsRouteLayers[otviaTimeWindows[k].RouteID].polylines = Array();
                    jsRouteLayers[otviaTimeWindows[k].RouteID].polylines.length = 0;
                    updateRouteLayer(otviaTimeWindows[k].RouteID);
                    //toggleRouteLayer(otviaTimeWindows[k].RouteID)
                    
                    //[otviaTimeWindows[k].RouteID].polyLines = [];  // Clear any route layers with a new Time Regime; this will force an update on their next display.
                    // Ultimately, the updating of the display needs to be automated.
                    changeInTimeWindow = true;
                }
            }
            if (changeInTimeWindow)
            {
                //alert(regimeChangeMessage);
            }
        }
        // Initialize or update browserTimeWindows[].  This object array mirrors the most recently received version of otviaTimeWindows[].
        if(browserTimeWindows == null)
        {
            browserTimeWindows = new Array();
        }
        //        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 != undefined && json != null && json.Alerts != undefined && json.Alerts != null) {
        	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);
    }
}

//
// 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 = "";  // Local string array to list the active routes.
        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;
        }
        
        //
        // Here we'll sort the array by name and display this way.
        //
        routeArray.sort(routeArraySort);

        //
        // 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 != null)
            {
                routeBodyContent += "<div class='routeListItem' style='z-index:" + zIndex + "'>";
                routeBodyContent += "<li style='z-index:" + zIndex + "'>";
                /*
                //Suresh - on click on select all routes start
                routeBodyContent += "<div class='routeCheckbox' style='z-index:" + zIndex + "'><input type='checkbox' id='"+ route.RouteID +"' value='" + route.RouteID + "'";
                routeBodyContent += "     onClick='toggleRouteLayer(" + route.RouteID + ",true);'";
                routeBodyContent += "></div>";
                //Suresh - on click on select all routes end
                */
                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++)
                    {
                        nameIndex = a;
                        if (menusByRoute[a].getElementsByTagName("name")[0].childNodes[0].nodeValue.toLowerCase() == route.Name.toLowerCase())
                        {
                            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.
                        }
                    }
                }
                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);
                //
                // Construct the route ID list, so we don't get unregistered vehicles plotted on the initial display.'
                if (routeIDString == "")
                {
                    routeIDString += routeArray[x].Route.RouteID;                
                }
                else
                {
                    routeIDString += "," + routeArray[x].Route.RouteID;                
                }
            }
        }
        routeIDListString = routeIDString;
        routeBodyContent += "<br /><br /><br /><br /><br />";  // 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.
    //
    // Here we can use the Prototype library to do the update or simplely update
    // the document element.
    //
    // i.e. $('<HTML Document Element>').update(<variable>)
    //
    // Where <HTML Document Element> is the ID of the DOM element to update
    // and <variable> is the value used to set this element
    //
    // $('routes').update(routeBodyContent);
    
    //
    // jQuery equivalent
    //
    jQuery("div#routes").html(routeBodyContent);

    //
    // Make sure the Accordion re-sizes properly upon route list population
    resizeAccordion();

    getEditAlerts();
    
    //
    // Start the Timeout function HERE, now that we have loaded the active routes and tabulated their IDs.
    //vehicleTimeout = 0;
    //shelterTimeout = 0;
    //vehicleTimeoutID = setTimeout("updateVehicle(\"" + routeIDString + "\")", vehicleTimeout);
    
    // wait and give the drawers a chance to draw themselves
    dataTimeoutID = setTimeoutClear(dataTimeoutID, "updateVehicle(\"" + routeIDString + "\")", dataTimeout);
    /*
    //Suresh - on click on select all routes start
    if(isAllRoutesSelected){
        document.getElementById("allRoutesCB").checked = true;
        onClickAllRoutes(true);
    }
    //Suresh - on click on select all routes end
    */
    bRoutesLoaded = true;

    showRouteLayers();

}

function showRouteLayers()
{
    //
    // FTT - Added code here to toggle all routes.
    //
    // var visualRouteLayerOrder = [6, 7, 9, 5, 8, 2, 3];
    var visualRouteLayerOrder = [1, 5, 2, 4, 9, 6, 3];
    var counter = 0;
    while (counter < visualRouteLayerOrder.length)
    {
        var vr = visualRouteLayerOrder[counter++];
        for (var r = 0 ; r < routeArray.length ; r++)
        {
            var rlRoute = routeArray[r].Route;
            var visualRouteID = rlRoute.LogNum;

            if (visualRouteID == vr )
            {
                toggleRouteLayer(rlRoute.RouteID);
                break;
            }
        }
    }
}

//..................................................................................................................................................................................
function getJSONRouteLayer(data, responseCode)
{
    if (responseCode == "success")
    {
        var json = eval('(' + data + ')');
        routeLayerArray = json.RouteLayerArray;
        for (var x = 0 ; x < routeLayerArray.length; ++x)
        {
            var routeLayer = routeLayerArray[x].RouteLayer;
            var visualRouteID = routeLayer.LogNum;

            var polyWidth = 3;
            switch (visualRouteID)
            {
                // Tan
                case 1:
                    polyWidth = 6.25;
                    break;
                // Red
                case 2:
                    polyWidth = 4.00;
                    break;
                // Blue
                case 3:
                    polyWidth = 2.50;
                    break;
                // Purple
                case 4:
                    polyWidth = 2.75;
                    break;
                // Pink
                case 5:
                    polyWidth = 5.75;
                    break;
                // Yellow
                case 6:
                    polyWidth = 5.50;
                    break;
                // Green
                case 9:
                    polyWidth = 2.50;
                    break;
                default:
                    break;
            }
            
            if (routeLayer == undefined)
            {
                continue;
            }
            
            var polyCount = 0;
            var polyLines = Array();
            
            for (var y = 0 ; y < routeLayer.LayerArray.length; ++y)
            {
                var layer = routeLayer.LayerArray[y].Layer;
                
                if (layer == undefined)
                {
                    continue;
                }
                
                var vertCount = 0;
                var verticies = Array();
                
                for (var z = 0 ; z < layer.CoordArray.length; ++z)
                {
                    var coordinate = layer.CoordArray[z].Coordinate;
                    
                    if (coordinate == undefined)
                    {
                        continue;
                    }
                
                    //
                    // Create Polyline for Google Maps.
                    //
                    verticies[vertCount++] = new google.maps.LatLng(coordinate.Latitude / 100000, -coordinate.Longitude / 100000);
                }
                polyLines[polyCount++] = new google.maps.Polyline(verticies, "#" + routeLayer.ColorRoute, polyWidth, 1);
            }
            jsRouteLayers[routeLayer.RouteID].polyLines = polyLines;
            
            //
            // This is the initial call to update the Route Layer's being displayed
            // on the map.
            //
            if(isActiveRouteLayer(routeLayer.RouteID))
            {
                addMapRouteLayers(routeLayer.RouteID);
            }
        }
    }
}

function updateRouteIDString()
{
    routeIDString = "";
    for (var x = 0 ; x < routeArray.length ; ++x)
    {
        if (routeArray[x].Route.LayerActive == true)
        {
            if (routeIDString == "")
            {
                routeIDString += routeArray[x].Route.RouteID;                
            }
            else
            {
                routeIDString += "," + routeArray[x].Route.RouteID;                
            }
        }
    }

    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;                
            }
        }
    }
}
//
// 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(bFullShelterUpdate)
    {
        //the full update for update data has been triggered
        //start the timer for update all
        dataTimeoutID = setTimeoutClear(dataTimeoutID, "updateShelter(\"" + routeIDString + "\")", 0);
        return;
    }
    else if (responseCode != "success")
    {
        // There is a problem here. This javascript will wait
        // until the problem is cleared up to try again.
        dataTimeoutID = setTimeoutClear(dataTimeoutID, "updateVehicle()", dataFailTimeout);
        return;
    }
    else
    {
        //start vehicle timer
        dataTimeoutID = setTimeoutClear(dataTimeoutID, "updateVehicle(\"" + routeIDString + "\")", dataTimeout);
        
        var json=null;
        //eval the json string
        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;
        }

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

        //parse the JSON string
        var jsonShelterArrayLength = jsonShelterArray.length;
        for (var x = 0 ; x < jsonShelterArrayLength ; ++x)
        {
            var shelter = jsonShelterArray[x].Shelter;
            
            // Is shelter null for some reason?
            if (shelter != null)
            {
                // 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 == undefined || shelterObj == null)
                    {
                        //make a new shelter obj
                        shelterObj = new Shelter(shelter.ShelterId, shelter.ShelterName);
                        shelterArray[shelter.ShelterId] = shelterObj;
                        
                        //on new shelter process the shelter groups
                        bProcessGroups = true;
                    }
                    //get the info
                    shelterObj.shelterName = shelter.ShelterName;
                    shelterObj.lat = shelter.Latitude;
                    shelterObj.lon = shelter.Longitude;
                    if(shelter.update == true)
                    {
                    	shelterObj.newText = shelter.WebLabel;
                    }
                    else
                    {
                    	shelterObj.newText = null;                    	
                    }
                }
                // Filtered
                shelterObj.filtered = true;
            }
        }
        
        //parse the shelters
        var shelterArrayLength = shelterArray.length;
        for(var x=0;x<shelterArrayLength;x++)
        {
            //get the item
            var shelterObj = shelterArray[x];
            
            //check the shelter obj
            if(shelterObj != undefined && shelterObj != null)
            {
                // Does the shelter have a valide Lat/Lng? 
                if ((shelterObj.Latitude != 0) && (shelterObj.Longitude !=0))
                {
                    // make the map point
                    var point = new google.maps.LatLng(shelterObj.lat/100000.0, -shelterObj.lon/100000.0);
                        
                    //get the screen coordinates
                    var screen_point = map.fromLatLngToContainerPixel(point);
                    shelterObj.xScreen = screen_point.x;
                    shelterObj.yScreen = screen_point.y;
                    
                    // Marker
                    var marker;
                    if (shelterObj.marker == null)
                    {
                        // make the map marker

                        //
                        // XXX: Code here is first steps toward landmarks
                        //
                        if(isLandmarkActive)
                        {
                            if(shelterObj.shelterID == landmarkID)
                            {
                                marker = new google.maps.Marker(point, {icon: transitIcon, zIndexProcess: zOrder});
                            }
                            else
                            {
                                marker = new google.maps.Marker(point, {icon: shelterIcon, zIndexProcess: zOrder});
                            }
                        }
                        else
                        {
                            marker = new google.maps.Marker(point, {icon: shelterIcon, zIndexProcess: zOrder});
                        }
                        
                        //assign the new marker
                        shelterObj.marker = marker;
                        shelterObj.marker.visualOrder = shelterObj.visualOrder;
                        
                        //add to the overlay
                        map.addOverlay(shelterObj.marker);
                        marker = null;
                    }
                    else
                    {
                        //set the marker position
                        shelterObj.marker.setPoint(point);
                    }

                    //assign the web label
                    //if(shelterObj.labelText != shelterObj.newText)
                    //{
                        //shelterObj.labelText = shelterObj.newText;
                    //}
                    
                    //
                    // XXX - thomasp : This code is a must to keep the shelter
                    //                 labels from jumping around in Firefox.
                    //
                    if (shelterObj.label == null)
                    {
                    	// update label text if new text is available
                    	if (shelterObj.newText != null)
                    		shelterObj.labelText = shelterObj.newText; 
                    		
                        itemLabelController(shelterObj, shelterObj.labelText, point, false);
                                               
                    }
                    else
                    {
                    	// update only if label text has changed
                    	if (shelterObj.newText != null && shelterObj.labelText != shelterObj.newText)
                    	{
                        	shelterObj.labelText = shelterObj.newText;
                        	itemLabelUpdate(shelterObj, shelterObj.labelText);
                    	}                        
                    }
                }
            }
        }

        //
        // 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("");
        }
        
        //
        // Process Shelter Groups to see who should be grouped
        //
        if(bProcessGroups == true)
        {
            processShelterGroup(routeIDString);
            bProcessGroups = false;
        }
        //
        // Now check Route Filtering
        // 
        // from Prototype.js
        //
        var updatedShelterArray = shelterArray.clone();
        
        for (var x = 0 ; x < shelterArray.length ; ++x)
        {
            var shelter_check = shelterArray[x];
            
            if (shelter_check != undefined)
            {
                if (shelter_check.filtered == false)
                {
                    //check the label
                    if(shelter_check.label != null)
                    {
                        //remove the label
                        map.removeOverlay(shelter_check.label);
                    }
                    //check the makrer
                    if(shelter_check.marker != null)
                    {
                        //remove the marker
                        map.removeOverlay(shelter_check.marker);
                    }
                    updatedShelterArray[x] = undefined;
                }
                else if(shelter_check.grouped == true)
                {
                    // check the label
                    if (shelter_check.label != null)
                    {
                        //remove the label
                        //map.removeOverlay(shelterArray[x].label);
                        //shelterArray[x].label.hide();
                    }
                    // check the marker
                    if (shelter_check.marker != null)
                    {
                        // remove the marker
                        shelter_check.marker.setPoint(shelter_check.parent.shelters[0].marker.getPoint());
                        shelter_check.label.setAnchor(shelter_check.marker.getPoint());
                        adjustItemLabelOffset(shelter_check);
                        shelter_check.marker.hide();
                    }
                    //set filter to false for next pass
                    updatedShelterArray[x].filtered = false;
                    
                }
                else
                {
                    if(shelter_check.marker != null)
                    {
                        //set the marker point
                        var point = new google.maps.LatLng(shelter_check.lat/100000.0, -shelter_check.lon/100000.0);
                        shelter_check.marker.setPoint(point);

                        shelter_check.marker.show();
                    }
                    updatedShelterArray[x].filtered = false;
                }
            }
        }
        
        // Update Shelter Array
        shelterArray = updatedShelterArray;
        }

    //
    // Update the list of shelters for use with the Search drawer
    //
    // NOTE: isSearchDrawerActive is defined in index.jsp
    //
    if (isSearchDrawerActive)
    {
        refreshSearchList(shelterArray);
    }

    //
    // Reset force flag
    //
    forceShelterUpdate = false;
    
    //
    // Added for performance benchmarking 03182009
    //
    // var endDate = new Date();
    // var endTime = endDate.getTime();

    // GLog.write("Shelter process ending: " + endDate);
    // GLog.write("Shelter processing time: " + (endTime-startTime) + " ms ");

    //Till here - Added for performance benchmarking 03182009

}

function processShelterGroup(routeIDString)
{
    //parse the shelter groups to remove overlays
    for(var x=0;x<shelterGroupArray.length;x++)
    {
        //get the shelter group
        var shelterGroup = shelterGroupArray[x];
        
        //check the shelter group
        if(shelterGroup != null)
        {
            //parse the shelters
            for(var y=0;y<shelterGroup.shelters.length;y++)
            {
                //get the shelter
                shelterGroup.shelters[y].parent = null;
                shelterGroup.shelters[y] = null;
            }
            //set the length to zero for shelters
            shelterGroup.shelters.length = 0;
        }
    }
    
    //parse the shelters to check for grouping
    for (var x = 0 ; x < shelterArray.length ; ++x)
    {
        //get the shelter object
        var shelter = shelterArray[x];
        
        //check the shelter
        if(shelter != null)
        {
            //check for filtered
            if(shelter.filtered == true)
            {
                //add to the group array
                addShelterGroup(shelter);
            }
        }
    }
    
    //parse the shelter groups to add overlays
    for(var x=0;x<shelterGroupArray.length;x++)
    {
        //get the shelter group
        var shelterGroup = shelterGroupArray[x];
        
        //check the shelter group
        if(shelterGroup != null)
        {
            //check the number of item in the grouping
            if(shelterGroup.shelters.length > 1)
            {
                //get the first shelter
                //                var shelter_add = shelterGroup.shelters[0];
                var shelter_add = null;
                var keepGoing = true;
                for (var s = 0; (keepGoing  &&  (s < shelterGroup.shelters.length)); s++)
                {
                    if (shelterGroup.shelters[s] != null)
                    {
                        shelter_add = shelterGroup.shelters[s];
                        keepGoing = false;
                    }
                }
                
//                var point_add = null;
                    
                //check the shelter
                if(shelter_add != null)
                {
                    
                    //suresh transit center Icon start
                    var ss = 0;
                    var isTransitIconDisplay = false;
                    var shelterGroupSize = shelterGroup.shelters.length;
                    if(isLandmarkActive){
                        for(ss = 0; ss < shelterGroupSize; ss++)
                        {
                            if(shelterGroup.shelters[ss].shelterID == landmarkID){
                                isTransitIconDisplay = true;
                            }
                        }
                    }
                    //suresh transit center Icon end
                    //get the marker point
                    var point_add = shelter_add.marker.getPoint();

                    //check the marker
                    if(shelterGroup.marker == null)
                    {
                        //make the new group marker
                        //suresh transit center Icon start
                        //if isLandmarkActive is true and shelter id matches with landmarkId
                        var marker;
                        if(isTransitIconDisplay){
                            marker = new google.maps.Marker(point_add, {icon: transitIcon, zIndexProcess: zOrder});
                        }else{
                            marker = new google.maps.Marker(point_add, {icon: shelterGroupIcon, zIndexProcess: zOrder});
                        }
                        //suresh transit center Icon end
                        //var marker = new google.maps.Marker(point_add, {icon: shelterGroupIcon, zIndexProcess: zOrder});

                        //add marker to group
                        shelterGroup.marker = marker;
                        shelterGroup.marker.visualOrder = shelterGroup.visualOrder;

                        //remove the overlay
                        map.addOverlay(shelterGroup.marker);

                    }
                    else
                    {
                        //suresh transit center Icon start
                        if(isTransitIconDisplay){
                            shelterGroup.marker.setImage(transitIcon.image);
                        }else{
                            shelterGroup.marker.setImage(shelterGroupIcon.image);
                        }
                        //suresh transit center Icon end
                        shelterGroup.marker.setPoint(point_add);
                        
                    }
                }
                
                // Label
                if (shelterGroup.shelters != null)
                {
                    
                    //
                    // Create the label assignment for the shelterGroup and activate
                    //
                    var str = getGroupShelterList(shelterGroup, x, routeIDString);
                    if(shelterGroup.labelText != str)
                    {
                        shelterGroup.labelText = str;
                    }                    
                    itemLabelController(shelterGroup, shelterGroup.labelText, shelterGroup.marker.getPoint(), false);                    
                    
                }
                else
                {
                    shelterGroup.labelText = shelterGroup.ShelterName;
                }
                    
                // Filtered
                shelterGroup.filtered = true;
        
            }
            else
            {
                //parse the shelters
                for(var y=0;y<shelterGroup.shelters.length;y++)
                {
                    //get the shelter
                    var shelter_remove = shelterGroup.shelters[y];
                    
                    //test the shelter
                    if(shelter_remove != null)
                    {
                        //set the shelter grouping to false
                        shelter_remove.grouped = false;
                        shelter_remove.parent  = null;
                        shelter_remove.labelText = shelter_remove.groupedLabelText;
                        shelter_remove.groupedLabelText = null;
                        
                        //
                        // Removes the mcEvent for the shelter based on the grouping.
                        //
                        if (shelter_remove.label.mcEvent != null)
                        {
                            google.maps.Event.removeListener(shelter_remove.label.mcEvent);
                            shelter_remove.label.mcEvent = null;
                        }
                        
                        //
                        // This will add back the event based on the single shelter.
                        //
                        itemLabelController(shelter_remove, shelter_remove.labelText, shelter_remove.marker.getPoint(), false);

                    }
                }
                if(shelterGroup.marker != null)
                {
                    //remove the overlay
                    map.removeOverlay(shelterGroup.marker);
                }
                if(shelterGroup.label != null)
                {
                    //
                    // Clean up events and objects.
                    //
                    if (shelterGroup.label.mcEvent != null)
                    {
                        google.maps.Event.removeListener(shelterGroup.label.mcEvent);
                    }
                    
                    //remove the overlay
                    map.removeOverlay(shelterGroup.label);
                }
                //set the shelter item to undefined
                shelterGroupArray[x] = undefined;
            }
        }
    }
}

function addShelterGroup(shelter)
{
    //parse the shelter groups
    for(var x=0;x<shelterGroupArray.length;x++)
    {
        //get the shelter group
        var shelterGroup = shelterGroupArray[x];
        
        //check the shelter group
        if(shelterGroup != null)
        {
            //parse the shelters
            if(shelterGroup.shelters.length > 0)
            {
                //get the shelter
                var shelter_check = shelterGroup.shelters[0];
                
                //check the shelter check
                if(shelter_check != null)
                {
                    //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 = shelterIconHeight;
                    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)   
                    {
                        //add the shelter to this group
                        shelterGroup.shelters.push(shelter);

                        //set group flag
                        shelter.grouped = true;
                        shelter.parent  = shelterGroup;
                        
                        //
                        // Update the DIV tag here for the close icon.
                        //
                        if (shelter.labelText != null || shelter.labelText != undefined)
                        {
                            shelter.groupedLabelText = shelter.labelText;
                            shelter.labelText = shelter.groupedLabelText.replace(/<div class='labelCloseIcon'>/, "<div class='labelCloseIcon' onclick='jsShelterLabelController(" + shelter.shelterID + ", false, true)'>");
                            // itemLabelController(shelter, shelter.labelText, shelter.marker.getPoint(), false);
                            itemLabelUpdate(shelter, shelter.labelText);
                        }
                        
                        //
                        // 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 != null && shelter.label != undefined)
                            {
                                //
                                // 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 != null && shelter.label != undefined)
                            {
                                //
                                // 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.isClicked = false;
                                        shelter.label.isStatic  = false;
                                        shelter.label.hide(null,null);
                                    }
                                }
                            }                          
                        }
                        
                        //return since we have added to a group
                        return;
                    }
                }
            }
        }
    }
    
    //parse the groups for unused group
    for(var x=0;x<shelterGroupArray.length;x++)
    {
        //get the group array
        var shelterGroup_check = shelterGroupArray[x];
        
        //check if undefines
        if(shelterGroup_check == undefined)
        {
            //make a new shelter group
            var shelterGroup = new ShelterGroup();

            //add the shelter to the shelter group
            shelterGroup.shelters.push(shelter);

            //set group flag
            shelter.grouped = true;
            shelter.parent  = shelterGroup;
            
            //
            // Update the DIV tag here for the close icon.
            //
            if (shelter.labelText != null || shelter.labelText != undefined)
            {
                shelter.groupedLabelText = shelter.labelText;
                shelter.labelText = shelter.groupedLabelText.replace(/<div class='labelCloseIcon'>/, "<div class='labelCloseIcon' onclick='jsShelterLabelController(" + shelter.shelterID + ", false, true)'>");
                // itemLabelController(shelter, shelter.labelText, shelter.marker.getPoint(), false);
                itemLabelUpdate(shelter, shelter.labelText);
            }
            
            //
            // 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 != null && shelter.label != undefined)
                {
                    //
                    // 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 != null && shelter.label != undefined)
                {
                    //
                    // 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.isClicked = false;
                            shelter.label.isStatic  = false;
                            shelter.label.hide(null,null);
                        }
                    }
                }                          
            }                            
                        
            //assign at this location
            shelterGroupArray[x] = shelterGroup;
            
            //return we have updated the array
            return;
        }
        else if(shelterGroup_check.shelters.length == 0)
        {
            //set group flag
            shelter.grouped = true;
            shelter.parent  = shelterGroup_check;

            //
            // Update the DIV tag here for the close icon.
            //
            if (shelter.labelText != null || shelter.labelText != undefined)
            {
                shelter.groupedLabelText = shelter.labelText;
                shelter.labelText = shelter.groupedLabelText.replace(/<div class='labelCloseIcon'>/, "<div class='labelCloseIcon' onclick='jsShelterLabelController(" + shelter.shelterID + ", false, true)'>");
                // itemLabelController(shelter, shelter.labelText, shelter.marker.getPoint(), false);
                itemLabelUpdate(shelter, shelter.labelText);
            }
            
            //
            // Assign the first label found to the ShelterGroup.
            //
            if (!shelterGroup_check.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 != null && shelter.label != undefined)
                {
                    //
                    // 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_check.isShelterLabelActive = true;
                        shelterGroup_check.activeShelterLabelID = shelter.shelterID;
                        shelterGroup_check.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 != null && shelter.label != undefined)
                {
                    //
                    // 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_check.activeShelterLabelID != shelter.shelterID)
                        {
                            shelter.label.isClicked = false;
                            shelter.label.isStatic  = false;
                            shelter.label.hide(null,null);
                        }
                    }
                }                          
            }
                        
            //shelter group
            shelterGroup_check.shelters.push(shelter);

            //return
            return;
        }
    }
    //make a new shelter group
    var shelterGroup = new ShelterGroup();
    
    //set group flag
    shelter.grouped = true;
    shelter.parent  = shelterGroup;
            
    //
    // Update the DIV tag here for the close icon.
    //
    if (shelter.labelText != null || shelter.labelText != undefined)
    {
        shelter.groupedLabelText = shelter.labelText;
        shelter.labelText = shelter.groupedLabelText.replace(/<div class='labelCloseIcon'>/, "<div class='labelCloseIcon' onclick='jsShelterLabelController(" + shelter.shelterID + ", false, true)'>");
        // itemLabelController(shelter, shelter.labelText, shelter.marker.getPoint(), false);
        itemLabelUpdate(shelter, shelter.labelTextx);
    }
    
    //
    // 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 != null && shelter.label != undefined)
        {
            //
            // 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 != null && shelter.label != undefined)
        {
            //
            // 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)
            {
                shelter.label.isClicked = false;
                shelter.label.isStatic  = false;
                shelter.label.hide(null,null);
            }
        }                          
    }
                        
    //add the shelter to the shelter group
    shelterGroup.shelters.push(shelter);
    
   
    //add to the group array
    shelterGroupArray.push(shelterGroup);  
}

//
// createMarker - Needed to create a new marker for the Google Map API
//
// NOTE: 
// 
// A function to create the marker and set up the event window
// Dont try to unroll this function. It has to be here for the function closure
// Each instance of the function preserves the contends of a different instance
// of the "marker", "options" and "html" variables which will be needed later
// when the event triggers.    
//
function createMarker(point, options)
{
    var marker = new google.maps.Marker(point, options);
    return marker;
}

function jsShelterLabelController(shelterID, preview, clicked)
{
    //
    // Get our parent
    //
    var shelterObj = shelterArray[shelterID];
    var currentShelterGroup = shelterObj.parent;
    
    if (currentShelterGroup == null || currentShelterGroup == undefined)
    	return; // nothing to do...bail 
    
    //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 == undefined || currentShelterGroup.shelters[x].label.isClicked == false)
                {
                    currentShelterGroup.shelters[x].label.setStatic(false);
                }
            }
        }
    }
    
    //
    // Determine if we have an active label.
    //
    if (currentShelterGroup.isShelterLabelActive)
    {
        if (currentShelterGroup.activeShelterLabelID == shelterID)
        {
            //
            // 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.isClicked = false;
                shelterObj.label.setStatic(false);
                
                updateDataNow();
            }
        }
        else
        {
            return;
        }
    }
    else
    {
        //
        // User has initiated a sticky label.
        //
        if (clicked)
        {
            shelterObj.label.isClicked = true;
            shelterObj.label.setStatic(true);
            itemLabelController(shelterObj, shelterObj.labelText, currentShelterGroup.marker.getPoint(), clicked);
            currentShelterGroup.isShelterLabelActive = true;
            currentShelterGroup.activeShelterLabelID = shelterID;
            currentShelterGroup.labelID = shelterID;
        
            updateDataNow()
        }
        else
        {
            //
            // Just browsing.
            //
            if (preview)
            {
                itemLabelController(shelterObj, shelterObj.labelText, shelterObj.marker.getPoint(), clicked);
                shelterObj.label.setStatic(true);
            }
            else
            {
                itemLabelController(shelterObj, shelterObj.labelText, shelterObj.marker.getPoint(), clicked);
                shelterObj.label.setStatic(false);
            }
        }
    }
    updateDataNow();
}

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

    // Variables
    var updatedQuadrant;
    var hasNewQuadrant = false;

    var currentMapCenterLat;
    var currentMapCenterLng;
    
    try
    {
        currentMapCenterLat = map.getCenter().lat();
        currentMapCenterLng = map.getCenter().lng();
        
        if (item.marker.getLatLng().lng() <= currentMapCenterLng)
        {
            if (item.marker.getLatLng().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.marker.getLatLng().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.
    //
    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));
            break;
        case 4:
            item.labelOffset = new google.maps.Size(item.quadOffset4.width, -(item.label.height + item.labelHeightOffset));
            break;
    }
    item.label.setOffset(item.labelOffset);
}

function itemLabelUpdate(item, labelText)
{
    if (item.label != undefined && item.label != null)
    {
        var scrollTop = 0;
        
        if (item.labelClassName == "labelShelterTooltip")
        {    
            if (document.getElementById(item.labelID) != null)
            {  
                scrollTop = document.getElementById(item.labelID).scrollTop;
            }
        }
        
        item.label.setContent(labelText);
        adjustItemLabelOffset(item);
        
        if (item.labelClassName == "labelShelterTooltip")
        {
            if (document.getElementById(item.labelID) != null)
            {
                document.getElementById(item.labelID).scrollTop = scrollTop;
            }
        }
        scrollTop = null;
    }
}

//
// itemLabelPositionUpdate - This function checks the current quadrant of an item.
//                        An item MUST have the following object/attribute associated
//                        with it to work:
//
//                        marker - A google.maps.Marker
//                        quadrant - an attribute to identify which quandrant is active.
//
function itemLabelController(item, labelText, point, menuActivated)
{    
    //
    // Now updated the label given the information gathered.
    //
    if (item.label == null)
    {
        //create the item label
        item.label = new GxLabel(labelText, {className: item.labelClassName, marker: item.marker, isStatic: false, deleteHandle: true});
                
        // Add item to the map.
        map.addOverlay(item.label);                        
    }
    //get the labe display
    var labelDisplay = item.label.container.style.display;
    
    //check the label display for change
    if(item.label.content != labelText)
    {
        //make scroll top
        var scrollTop = 0;

        //get the scroll position
        if (item.labelClassName == "labelShelterTooltip")
        {
            if (document.getElementById(item.labelID).scrollTop != null)
            {
                scrollTop = document.getElementById(item.labelID).scrollTop;
            }
        }
        //set the label contents
        item.label.setContent(labelText);

        //reset the scroll position
        if (item.labelClassName == "labelShelterTooltip")
        {
            if (document.getElementById(item.labelID).scrollTop != null)
            {
                document.getElementById(item.labelID).scrollTop = scrollTop;
            }
        }
        scrollTop = null;
    }

    //set the label anchor
    item.label.setAnchor(point);
            
    //adjust the label offset
    adjustItemLabelOffset(item);
            
    //
    // FIXME : Code here is to show label. Might need more checks.
    //
    if (menuActivated)
    {
        item.label.isStatic = true;
        item.label.redraw();
        google.maps.Event.removeListener(item.label.moEvent);
        item.label.isClicked = true;

        item.label.show(point, item.labelOffset);
    }

    //get the current values of the label
    var isLabelStatic  = item.label.isStatic;
    var isLabelClicked = item.label.isClicked;
 
    //check for no data
    if (labelDisplay == "")
    {
        //check for label displayed static
        if (isLabelStatic)
        {
            item.label.setStatic(true);
        }
        //check for label is clicked on
        if (isLabelClicked)
        {
            google.maps.Event.removeListener(item.label.moEvent);
            item.label.isClicked = true;
        }
        //show the label
        item.label.show(point, item.labelOffset);
    }
}

function removeOutOfServiceVehicleOverlay(x){
    map.removeOverlay(outOfServicevehicleArray[x].label);
    map.removeOverlay(outOfServicevehicleArray[x].marker);
    map.removeOverlay(outOfServicevehicleArray[x].visibleMarker);
    if(isVehicleIdElabelActive){
        map.removeOverlay(outOfServicevehicleArray[x].vehicleIDLabel);
    }
    outOfServicevehicleArray[x] = undefined;
}

function removeVehicleOverlay(x){
    map.removeOverlay(vehicleArray[x].label);
    map.removeOverlay(vehicleArray[x].marker);
    map.removeOverlay(vehicleArray[x].visibleMarker);
    if(isVehicleIdElabelActive){
        map.removeOverlay(vehicleArray[x].vehicleIDLabel);
    }
    vehicleArray[x] = undefined;
}


function getJSONOutOfServiceVehicle(data, responseCode)
{
    if(responseCode == "success")
    {
        //turn the http data into json object
        var json = eval('(' + data + ')');
        var jsonVehicleArray = json.VehicleArray;
        lastOutOfServiceVehicleHttpRequestTime = json.lastUpdateTime;

        //
        // Must always put a check to see if the array values are defined or null.
        //
        var len = 0;
        if (jsonVehicleArray != undefined || jsonVehicleArray != null)
        {
            len = jsonVehicleArray.length;
        }
        var vehicleLen = vehicleArray.length;
        if(len > 0 &&  vehicleLen > 0){
            var x;
            var vId;
            for(x = 0; x < len; x++ ){
                vId = jsonVehicleArray[x].vehicle.id;
                if(vehicleArray[vId] != undefined){
                    removeVehicleOverlay(vId);
                }
            }
        }
        
//        if (jsonVehicleArray == undefined || jsonVehicleArray.length == 0)
//        {
//            return;
//        }
//
        //parse the vehicle array
        if(len > 0 )
        {
            for ( var x = 0 ; x < len; ++x)
            {
                //get the vehicle from vehicle array

                //
                // Must check here to see if you 
                if (jsonVehicleArray[x] == null || jsonVehicleArray[x] == undefined)
                {
                    continue;
                }
                
                var vehicle = jsonVehicleArray[x].vehicle;

                if (vehicle != null)
                {
                    //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(outOfServicevehicleArray[vehicle.id] != undefined)
                            outOfServicevehicleArray[vehicle.id].filtered = true;
                    }
                    else
                    {
                        //check the cvlocaltion info
                        if(vehicle.CVLocation != null)
                        {
                            if ((vehicle.CVLocation.latitude != 0) && (vehicle.CVLocation.longitude != 0))
                            {
                                //
                                // At this point the out of service vehicle should be valid and can then
                                // be added to outOfServicevehicleArray.
                                //
                                if (outOfServicevehicleArray[vehicle.id] == undefined)
                                {
                                    outOfServicevehicleArray[vehicle.id] = new Vehicle(vehicle.id);
                                }

                                //make the point
                                var point = new google.maps.LatLng(vehicle.CVLocation.latitude/100000.0, vehicle.CVLocation.longitude/100000.0);
                                
                                //suresh - start vehicle color icon load
                                var currentDirection = vehicle.CVLocation.angle;
                                var imageToBeLoaded = "";
                                var transparentImageToBeLoaded = "";
                                
                                if(currentDirection == undefined ){
                                    if(isSpecialRouteActive && vehicle.routeId == specialRouteId){
                                        imageToBeLoaded = imagepath + "/special-nodir" + imageExtension;
                                    }else{
                                        imageToBeLoaded = imagepath + "/a0a0a0-nodir" + imageExtension;
                                    }
                                    //transparentImageToBeLoaded = imagepath + "/transparent-nodir" + imageExtension;
                                }else{
                                    var dir = getVehicleDirectionalIcon(currentDirection);
                                    if(isSpecialRouteActive && vehicle.routeId == specialRouteId){
                                        imageToBeLoaded = imagepath + "/special-" +  dir + imageExtension;
                                    }else{
                                        imageToBeLoaded = imagepath + "/a0a0a0-" + dir + imageExtension;   //default image for out-of-service Vehicle
                                    }
                                    //transparentImageToBeLoaded = imagepath + "/transparent-" + dir + imageExtension;
                                }
                                
                                //suresh - end vehicle color icon load

                                 //make visible marker start
                                vehicleIcon.image = imageToBeLoaded;
                                var visibleMarker = new google.maps.Marker(point, {icon: vehicleIcon, zIndexProcess:zOrderVisible});
                                if (outOfServicevehicleArray[vehicle.id].visibleMarker == null)
                                {
                                    outOfServicevehicleArray[vehicle.id].visibleMarker = visibleMarker;
                                    outOfServicevehicleArray[vehicle.id].visibleMarker.visualOrder = outOfServicevehicleArray[vehicle.id].visualOrder;
                                    map.addOverlay(outOfServicevehicleArray[vehicle.id].visibleMarker);
                                }
                                else
                                {
                                    outOfServicevehicleArray[vehicle.id].visibleMarker.setPoint(point);
                                    outOfServicevehicleArray[vehicle.id].visibleMarker.setImage(vehicleIcon.image);
                                }
                                // make visible marker end
                                
                                //suresh - vehicle elabel start
                                if(isVehicleIdElabelActive){
                                    /*
                                    if(outOfServicevehicleArray[vehicle.id].vehicleIDLabel != null){
                                        map.removeOverlay(outOfServicevehicleArray[vehicle.id].vehicleIDLabel);
                                    }
                                    */

                                    var latitude = vehicle.CVLocation.latitude/100000.0;
                                    var longitude = vehicle.CVLocation.longitude/100000.0;

                                    //
                                    // Code check here does two things.
                                    //
                                    // 1. Determine if there is a vehicleIDLabel for a given vehicle, if not create one.
                                    // 2. If a label exists simply update its location DO NOT create a new label.
                                    //
                                    if (outOfServicevehicleArray[vehicle.id].vehicleIDLabel == null ||
                                        outOfServicevehicleArray[vehicle.id].vehicleIDLabel == undefined)
                                    {
                                        var content  =  vehicle.id;

                                        //
                                        // Added code here to adjust the elabel offset based on the vehicle ID
                                        //
                                        var pixelOffset;
                                        if ( vehicle.id < 10 )
                                        {
                                            pixelOffset = new google.maps.Size(-9.0, 1.0);
                                        }
                                        else if (vehicle.id < 100)
                                        {
                                            pixelOffset = new google.maps.Size(-11.0, 1.0);
                                        }
                                        else
                                        {
                                            pixelOffset = new google.maps.Size(-13.0, 1.0);
                                        }

                                        //
                                        // Code added to adjust the CSS.
                                        //
                                        var eLabelStyle;
                                        if(isSpecialRouteActive && vehicle.routeId == specialRouteId)
                                        {
                                            eLabelStyle = "vehicleLabelStyle-yellow";
                                        }
                                        else
                                        {
                                            eLabelStyle = "vehicleLabelStyle";
                                        }
                                        outOfServicevehicleArray[vehicle.id].vehicleIDLabel = new ELabel(new google.maps.LatLng(latitude,longitude), content,  eLabelStyle, pixelOffset, 100, zVisualOrder(outOfServicevehicleArray[vehicle.id].visualOrder));
                                        map.addOverlay(outOfServicevehicleArray[vehicle.id].vehicleIDLabel);
                                        outOfServicevehicleArray[vehicle.id].vehicleIDLabel.show();
                                    }
                                    else
                                    {
                                        outOfServicevehicleArray[vehicle.id].vehicleIDLabel.setPoint(new google.maps.LatLng(latitude,longitude));
                                    }
                                }
                                //suresh -  vehicle elabel end

                                vehicleIcon.image = transparentImageToBeLoaded;
                                //make the marker
                                var marker = new google.maps.Marker(point, {icon: vehicleIcon, zIndexProcess: zOrder});

                                //
                                // thomasp - Updated code to use Vehicle objects defined
                                //           here and pull them from the outOfServicevehicleArray
                                //
                                // 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 (outOfServicevehicleArray[vehicle.id].marker == null)
                                {
                                    outOfServicevehicleArray[vehicle.id].marker = marker;
                                    outOfServicevehicleArray[vehicle.id].marker.visualOrder = outOfServicevehicleArray[vehicle.id].visualOrder;
                                    map.addOverlay(outOfServicevehicleArray[vehicle.id].marker);
                                }
                                else
                                {
                                    outOfServicevehicleArray[vehicle.id].marker.setPoint(point);
                                    outOfServicevehicleArray[vehicle.id].marker.setImage(vehicleIcon.image);
                                }

                                // Label
                                var ttTitle = vehicle.WebLabel;
                                outOfServicevehicleArray[vehicle.id].labelText = vehicle.WebLabel;

                                //
                                // Function to control an items label.
                                //
                                itemLabelController(outOfServicevehicleArray[vehicle.id], outOfServicevehicleArray[vehicle.id].labelText, point, false);

                                //
                                // Set the filtered flag to active to see which vehicles/lables
                                // to remove from the map.
                                //
                                outOfServicevehicleArray[vehicle.id].filtered = true;

                               
                            }
                        }
                    }
                }
            }

            //
            // Start filtering vehicles that do not have the filtered flag
            //
            // from Prototype.js
            //
            var updatedVehicleArray = outOfServicevehicleArray.clone();

            for (var x = 0 ; x < outOfServicevehicleArray.length ; ++x)
            {
                if (outOfServicevehicleArray[x] != undefined)
                {
                    if (outOfServicevehicleArray[x].filtered == false)
                    {
                        map.removeOverlay(outOfServicevehicleArray[x].label);
                        map.removeOverlay(outOfServicevehicleArray[x].marker);
                        map.removeOverlay(outOfServicevehicleArray[x].visibleMarker);
                        if(isVehicleIdElabelActive){
                            map.removeOverlay(outOfServicevehicleArray[x].vehicleIDLabel);
                        }
                        updatedVehicleArray[x] = undefined;
                    }
                    else
                    {
                        updatedVehicleArray[x].filtered = false;
                    }
                }
            }

            //
            // Now set the outOfServicevehicleArray 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.
            //
            outOfServicevehicleArray = updatedVehicleArray;

            vehicle     = null;
            json        = null;

        }
        

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

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

    }
    

}

function getVehicleDirectionalIcon(currentDirection){
    var direction = "000";
    if (currentDirection > 337.50 && currentDirection <= 22.50)
    {
        direction = "000";
    }
    else if (currentDirection > 22.50 && currentDirection <= 67.50)
    {
        direction = "045";
    }
    else if (currentDirection > 67.50 && currentDirection <= 112.50)
    {
        direction = "090";
    }
    else if (currentDirection > 112.50 && currentDirection <= 157.50)
    {
        direction = "135";
    }
    else if (currentDirection > 157.50 && currentDirection <= 202.50)
    {
        direction = "180";
    }
    else if (currentDirection > 202.50 && currentDirection <= 247.50)
    {
        direction = "225";
    }
    else if (currentDirection > 247.50 && currentDirection <= 292.50)
    {
        direction = "270";
    }
    else if (currentDirection > 292.50 && currentDirection <= 337.50)
    {
        direction = "315";
    }
    return direction;
}
function getJSONVehicle(data, responseCode)
{

    if(bFullVehicleUpdate)
    {
        //the full update for update data has been triggered
        //start the timer for update all
        dataTimeoutID = setTimeoutClear(dataTimeoutID, "updateVehicle(\"" + routeIDString + "\")", 0);
        return;
    }
    else if (responseCode != "success")
    {
        // There is a problem here. This javascript will wait
        // until the problem is cleared up to try again.
        dataTimeoutID = setTimeoutClear(dataTimeoutID, "updateShelter()", dataFailTimeout);
        return;
    }
    else if (data == "" )
    {
        // There is a problem here. This javascript will wait
        // until the problem is cleared up to try again.
        dataTimeoutID = setTimeoutClear(dataTimeoutID, "updateShelter()", dataFailTimeout);
        return;
    }
    else
    {
    
	    // var startDate = new Date();
	    // var startTime = startDate.getTime();

	    // GLog.write("getJSONVehicle() starting: " + startDate);
    
        //start vehicle timer
        dataTimeoutID = setTimeoutClear(dataTimeoutID, "updateShelter(\"" + routeIDString + "\")", dataTimeout);
    
    	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;
        

        var len = jsonVehicleArray.length;
        
        if(len > 0 &&  outOfServicevehicleArray.length > 0){
            var x;
            var vId;
            for(x = 0; x < len; x++ ){
                vId = jsonVehicleArray[x].vehicle.id;
                if(outOfServicevehicleArray[vId] != undefined){
                    removeOutOfServiceVehicleOverlay(vId);
                }
            }
        }
        //parse the vehicle array
        for ( var x = 0 ; x < len; ++x)
        {
            //get the vehicle from vehicle array
            var vehicle = jsonVehicleArray[x].vehicle;
            
            if (vehicle != null)
            {
                //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] != undefined)
                        vehicleArray[vehicle.id].filtered = true;
                }
                else
                {
                    //check the cvlocaltion info
                    if(vehicle.CVLocation != null)
                    {
                        if ((vehicle.CVLocation.latitude != 0) && (vehicle.CVLocation.longitude != 0)) 
                        {
                            //
                            // At this point the vehicle should be valid and can then
                            // be added to vehicleArray.
                            //
                            if (vehicleArray[vehicle.id] == undefined)
                            {
                                vehicleArray[vehicle.id] = new Vehicle(vehicle.id);
                            }

                            //make the point
                            var point = new google.maps.LatLng(vehicle.CVLocation.latitude/100000.0, vehicle.CVLocation.longitude/100000.0);

                            //suresh - start vehicle color icon load
                            var currentDirection = vehicle.CVLocation.angle;
                            var imageToBeLoaded = "";
                            var transparentImageToBeLoaded = "";
                            if(isVehicleColoringActive){
                                var imgColor = json.vehicleImageHash[vehicle.id];
                                if(currentDirection == undefined ){
                                    imageToBeLoaded = imagepath + "/"+ imgColor +"-nodir"+ imageExtension;
                                    //transparentImageToBeLoaded = imagepath + "/transparent-nodir"+ imageExtension;
                                }else{
                                    var dir = getVehicleDirectionalIcon(currentDirection);
                                    imageToBeLoaded = imagepath + "/"+ imgColor + "-" + dir + imageExtension;
                                    //transparentImageToBeLoaded = imagepath + "/transparent-"+ dir + imageExtension;
                                }
                            }else{
                                imageToBeLoaded = imagepath +"/vehicle_icon"+ imageExtension;
                            }
                            
                            //make visible marker start
                            vehicleIcon.image = imageToBeLoaded;
                            var visibleMarker = new google.maps.Marker(point, {icon: vehicleIcon, zIndexProcess:zOrderVisible});
                            if (vehicleArray[vehicle.id].visibleMarker == null)
                            {
                                vehicleArray[vehicle.id].visibleMarker = visibleMarker;
                                vehicleArray[vehicle.id].visibleMarker.visualOrder = vehicleArray[vehicle.id].visualOrder;
                                map.addOverlay(vehicleArray[vehicle.id].visibleMarker);
                            }
                            else
                            {
                                vehicleArray[vehicle.id].visibleMarker.setPoint(point);
                                vehicleArray[vehicle.id].visibleMarker.setImage(vehicleIcon.image);
                            }
                            // make visible marker end

                            //suresh - vehicle elabel start
                            if(isVehicleIdElabelActive){
                                /*
                                if(vehicleArray[vehicle.id].vehicleIDLabel != null){
                                    map.removeOverlay(vehicleArray[vehicle.id].vehicleIDLabel);
                                }
                                */

                                var latitude = vehicle.CVLocation.latitude/100000.0;
                                var longitude = vehicle.CVLocation.longitude/100000.0;

                                //
                                // Code check here does two things.
                                //
                                // 1. Determine if there is a vehicleIDLabel for a given vehicle, if not create one.
                                // 2. If a label exists simply update its location DO NOT create a new label.
                                //
                                if (vehicleArray[vehicle.id].vehicleIDLabel == null ||
                                    vehicleArray[vehicle.id].vehicleIDLabel == undefined)
                                {
                                    var content  =  vehicle.id;

                                    //
                                    // Added code here to adjust the elabel offset based on the vehicle ID
                                    //
                                    var pixelOffset;
                                    if ( vehicle.id < 10 )
                                    {
                                        pixelOffset = new google.maps.Size(-9.0, 1.0);
                                    }
                                    else if (vehicle.id < 100)
                                    {
                                        pixelOffset = new google.maps.Size(-11.0, 1.0);
                                    }
                                    else
                                    {
                                        pixelOffset = new google.maps.Size(-13.0, 1.0);
                                    }

                                    //
                                    // FIXME: Very ROUGH fix here to control the icons font color based on color.
                                    //
                                    // In the future there should be a hash of elements, i.e. icons, and their
                                    // configuration parameters.
                                    //
                                    if(json.vehicleImageHash[vehicle.id] == "f9eb29" )
                                    {
                                        vehicleArray[vehicle.id].vehicleIDLabel = new ELabel(new google.maps.LatLng(latitude,longitude), content,  "vehicleLabelStyle-yellow", pixelOffset, 100, zVisualOrder(vehicleArray[vehicle.id].visualOrder));
                                    }
                                    else
                                    {
                                        vehicleArray[vehicle.id].vehicleIDLabel = new ELabel(new google.maps.LatLng(latitude,longitude), content,  "vehicleLabelStyle", pixelOffset, 100, zVisualOrder(vehicleArray[vehicle.id].visualOrder));
                                    }
                                    map.addOverlay(vehicleArray[vehicle.id].vehicleIDLabel);
                                    vehicleArray[vehicle.id].vehicleIDLabel.show();
                                }
                                else
                                {
                                    vehicleArray[vehicle.id].vehicleIDLabel.setPoint(new google.maps.LatLng(latitude,longitude));
                                }
                            }
                            //suresh -  vehicle elabel end

                            vehicleIcon.image = transparentImageToBeLoaded;
                            //suresh - end vehicle color icon load
                            //make the marker
                            var marker = new google.maps.Marker(point, {icon: vehicleIcon, zIndexProcess: zOrder});

                            //
                            // 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 == null)
                            {
                                vehicleArray[vehicle.id].marker = marker;
                                vehicleArray[vehicle.id].marker.visualOrder = vehicleArray[vehicle.id].visualOrder;
                                map.addOverlay(vehicleArray[vehicle.id].marker);
                            }
                            else
                            {
                                vehicleArray[vehicle.id].marker.setPoint(point);
                                vehicleArray[vehicle.id].marker.setImage(vehicleIcon.image);
                            }

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

                            //
                            // 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
        //
        // from Prototype.js
        //
        var updatedVehicleArray = vehicleArray.clone();
        
        for (var x = 0 ; x < vehicleArray.length ; ++x)
        {
            if (vehicleArray[x] != undefined)
            {
                if (vehicleArray[x].filtered == false)
                {
                    map.removeOverlay(vehicleArray[x].label);
                    map.removeOverlay(vehicleArray[x].marker);
                    map.removeOverlay(vehicleArray[x].visibleMarker);
                    if(isVehicleIdElabelActive){
                        map.removeOverlay(vehicleArray[x].vehicleIDLabel);
                    }
                    updatedVehicleArray[x] = undefined;
                }
                else
                {
                    updatedVehicleArray[x].filtered = 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));

    }
    //
    //
    // Reset force flag
    //

    if(isVehicleSearchActive){
        refreshVehicleList(vehicleArray, outOfServicevehicleArray);
    }
    
    forceVehicleUpdate = false;

}

//..................................................................................................................................................................................
// load - Used to load up the Javascript and HTML components for
//        the DSM client.
//
// FIXME: This is changing. Google has new way of initializing and loading
//        up the map component of a page. I'll beging to look into this
//        shortly.
function load() {

    //
    // Check the browser
    //
    checkDownloadFirefox();
    
    //
    // 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");
    
    //
    // 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");
            }
        }
    }

    if (google.maps.BrowserIsCompatible()) {
        
        // Create the Google Map.
        map = new google.maps.Map2(document.getElementById("map"));
        
        //
        // FIXME : This needs to be dynamically set during installation
        //
        //mapCenter = new google.maps.LatLng(33.960833, -83.377777);
        mapCenter = new google.maps.LatLng(mapCenterLat, mapCenterLong);  // FIXED!!! : 071219.anthonyt
        
        // Zoom factor is at 1000 Feet
        map.setCenter(mapCenter, 13);
        
        // Add desired controls for the Google Map.
        map.addControl(new google.maps.LargeMapControl());
        map.addControl(new google.maps.ScaleControl());
        
        // Google Map Interface mimic.
        map.addControl(new google.maps.HierarchicalMapTypeControl());
        map.addMapType(G_PHYSICAL_MAP);
        
        var mapTypes = map.getMapTypes();
        for (i=0; i<mapTypes.length; i++) {
        	mapTypes[i].getMinimumResolution = function() { return minMapZoom; }
        	mapTypes[i].getMaximumResolution = function() { return maxMapZoom; }
        }
        
        // Local Search
        
        //
        // thomasp - Removed experimental search feature.
        // var localSearchOptions = { suppressInitialResultSelection : true };
        // map.addControl(new google.maps.LocalSearch(localSearchOptions));
        
        // Attach the keyboard to the map when selected
        new google.maps.KeyboardHandler(map);
        
        // Activate mouse zooming
        map.enableDoubleClickZoom();
        map.enableContinuousZoom();
        map.enableScrollWheelZoom();
        
        // Geocoder for finding one's location.
        geocoder = new google.maps.ClientGeocoder();
        
        // Street View
        //        streetView = new google.maps.StreetviewOverlay();
        //        map.addOverlay(streetView);
        
        map.checkResize();
        
        //add zoom listener
        google.maps.Event.addListener(map, "zoomend", function() {

		    // var startDate = new Date();
		    // var startTime = startDate.getTime();

		    // GLog.write("Change Zoom starting: " + startDate);

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

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

            //
            // Update ALL Shelter/Vehicle objects.
            //
            updateDataNow();
        });
        
        // add move listener
        google.maps.Event.addListener(map, "movestart", function() {
            
            //
            // Stop Shelter/Vehicle updates
            //
            clearTimeout(dataTimeoutID);
        })
       
        //add moveend listener
        google.maps.Event.addListener(map, "moveend", function() {
            
            //
            // Start Shelter/Vehicle updates
            //
            bProcessGroups = true;
            dataTimeoutID = setTimeoutClear(dataTimeoutID, "updateShelter(\"" + routeIDString + "\")", 2000);            	
        });
        
    }
    
    
    // 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()", 10000);
    
    //
    // 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;
    // Suresh - out of service start
    if(isOutOfServiceVehicleTracked){
        getJSONTrackingVehicle();
    }
    // Suresh - out of service end

 if (isSearchDrawerActive)
    {
      htmlString = "<input id='routeSearchSelection' type='text'/>";
      jQuery("#search").html(htmlString);
    }
 if(isVehicleSearchActive)
   {
    htmlString = "<input id='vehicleSearchSelection' type='text'/>";
    jQuery("#vehicleSearch").html(htmlString);
   }
}

function getJSONTrackingVehicle(){
    setTimeout("getJSONTrackingVehicle()", (outOfServiceRefreshTime*1000));
    jQuery.get("packet/json/outOfServiceVehicle?lastVehicleHttpRequestTime=" + lastOutOfServiceVehicleHttpRequestTime+"&isOutOfServiceVehicle=true", getJSONOutOfServiceVehicle);
}

//
// set the timer and clear the timerID passed to the function
//
function setTimeoutClear(timerID, str, timeout)
{
    //clear the timerid
    clearTimeout(timerID);
    
    //cancel the http progress
    bHTTPInProgress = false;
        
    //sch the timeout
    return setTimeout(str, timeout)
}
//
// updateDataNow - Updates all data for Shelters/Vehicles
//
function updateDataNow()
{
    //set the full update variables
    bFullShelterUpdate = true;
    bFullVehicleUpdate = true;
    bProcessGroups = true;
    
    //check if in progress
    if(bHTTPInProgress)
    {
        //do nothing
        //when response comes in it will regtrigger the update
    }
    else
    {
        //
        // Let everyone know we need to update.
        //
        forceShelterUpdate = true;
        
        if (launchURLStatus)
        {
            //start the request
            dataTimeoutID = setTimeoutClear(dataTimeoutID, "updateShelter(\"" + routeIDString + "\")", 2000);
            launchURLStatus = false;
        }
        else
        {
            //start the request
            dataTimeoutID = setTimeoutClear(dataTimeoutID, "updateShelter(\"" + routeIDString + "\")", 0);
        }
    }
}

//..................................................................................................................................................................................
function purge(d) {
    var a = d.attributes, i, l, n;
    if (a) {
        l = a.length;
        for (i = 0 ; i < l ; i += 1) {
            n = a[i].name;
            if (typeof d[n] === 'function') {
                d[n] = null;
            }
        }
    }
    a = d.childNodes;
    if (a) {
        l = a.length;
        for (i = 0 ; i < l ; i += 1) {
            purge(d.childNodes[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                         ____________________

    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 resizeShelterLabel()
{
    //
    // thomasp - On each resize recalculate the quadrant size and adjust the
    //           maximum size of a Shelter Label.
    //
    var mapSize = map.getSize();
    var maxShelterLabelHeight = ((mapSize.height / 2) - (QUADRANT_HEIGHT_BUFFER * 2));
    
    //
    // Update the CSS for labelShelterRouteListing to adjust the maximum
    // height of the Shelter Labels. This is done by accessing the elements
    // of the DOM with jQuery and adjusting the CSS with the value adjusted
    // above.
    //
    jQuery('div.labelShelterRouteListing').css("max-height", maxShelterLabelHeight + "px");
}

//..................................................................................................................................................................................
function showAddress(address) {
    if (geocoder) {
        geocoder.getLatLng(
        address,
        function(point) {
            if (!point) {
                alert(address + " not found");
            } else {
                mapCenter = point;
                map.setCenter(mapCenter, 13);
                /*
                var marker = new google.maps.Marker(point);
                map.addOverlay(marker);
                marker.openInfoWindowHtml(address);
                 */
            }
        }
    );
    }
}


//..................................................................................................................................................................................
function toggleRouteLayer(routeID,isRouteClicked)
{
    if(isRouteClicked){
        callShowRouteLayers = false; //
    }
    for (var x = 0 ; x < routeArray.length; ++x)
    // for (var x in routeArray)
    {
        if (routeArray[x].Route != null)
        {
            if (routeID == routeArray[x].Route.RouteID)
            {
                //
                // FIXME: This attribute of the Route object is used
                //        only in the JavaScript. It can be passed up
                //        from the server with an initial value
                //        but it is only manipulated in the JavaScript
                //        code.
                //
                if (routeArray[x].Route.LayerActive == true)
                {
                    routeArray[x].Route.LayerActive = false;

                    //
                    // Here the code needs to toggle the visible layer, the
                    // vehicles represented by this layer and the stops
                    // associated with this layer.
                    //
                    for (var z = 0 ; z < jsRouteLayers[routeID].polyLines.length; ++z) 
                    {
                        map.removeOverlay(jsRouteLayers[routeID].polyLines[z]);
                    }
                    var index = routesSelectedList.indexOf(routeID);
                    routesSelectedList.splice(index,1);
                }
                else
                {
                    routeArray[x].Route.LayerActive = true;

                    //
                    // Here the code needs to toggle the visible layer, the
                    // vehicles represented by this layer and the stops
                    // associated with this layer.
                    //
                    
                    //
                    // Update the Route Layer for the current Route
                    //
                    if (jsRouteLayers[routeID].polyLines.length == 0)
                    {
                        updateRouteLayer(routeID);
                    }
                    else
                    {
                        addMapRouteLayers(routeID);
                    }
                    routesSelectedList.push(routeID);
                }
            }
        }
    }
    //update the route string
    updateRouteIDString();
    //Suresh - on click on select all routes start
    // 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
    updateDataNow();

}

function clearRouteLayer(routeID)
{
    for (var x = 0 ; x < routeArray.length; ++x)
    // for (var x in routeArray)
    {
        if (routeArray[x].Route != null)
        {
            if (routeID == routeArray[x].Route.RouteID)
            {
                //
                // FIXME: This attribute of the Route object is used
                //        only in the JavaScript. It can be passed up
                //        from the server with an initial value
                //        but it is only manipulated in the JavaScript
                //        code.
                //
                if (routeArray[x].Route.LayerActive == true)
                {
                    //routeArray[x].Route.LayerActive = false;

                    //
                    // Here the code needs to toggle the visible layer, the
                    // vehicles represented by this layer and the stops
                    // associated with this layer.
                    //
                    for (var z = 0 ; z < jsRouteLayers[routeID].polyLines.length; ++z) 
                    {
                        map.removeOverlay(jsRouteLayers[routeID].polyLines[z]);
                    }
                    //var index = routesSelectedList.indexOf(routeID);
                    //routesSelectedList.splice(index,1);
                }
                else
                {
                    //routeArray[x].Route.LayerActive = true;

                    //
                    // Here the code needs to toggle the visible layer, the
                    // vehicles represented by this layer and the stops
                    // associated with this layer.
                    //
                    
                    //
                    // Update the Route Layer for the current Route
                    //
                    //if (jsRouteLayers[routeID].polyLines.length == 0)
                    //{
                    //    updateRouteLayer(routeID);
                    //}
                    //else
                    //{
                    //    addMapRouteLayers(routeID);
                    //}
                    //routesSelectedList.push(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;
    }
    
    //
    // thomasp - Fixes map updates on width toggle.
    //
    var centerReference = map.getCenter();
    map.checkResize();
    map.setCenter(centerReference);
}

//..................................................................................................................................................................................
function toggleShowAllBuses()
{
    if (showAllBuses) 
    {
        showAllBuses = false;
    }
    else
    {
        showAllBuses = true;
    }
}

//..................................................................................................................................................................................
// 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';
}

//
// jsAlertModificaiton - Used as a hook to allow the Javascript to follow or
//                       adust the accordion based on its curent state and the
//                       alert action requested.
//
function jsAlertModification()
{
    // Stub
}

//..................................................................................................................................................................................
// Construct Group Shelter List menu based on information in the Shelter Group object.
function getGroupShelterList(groupObj, groupIndex, routeIDString)
{
//    var groupShelterList  = "<div style=\"background-color:#AAF8AA; width:200px; padding:0px; margin:0px;\">";
//    groupShelterList += "<ul style=\"background-color:#AAF8AA; padding:0px; margin:0px; display:block;\">";
//    groupShelterList += "<li style=\"background-color:#AAF8AA; font-variant:small-caps; font-weight:bold; font-size: 13px; text-align:center; margin-top:0px; display:block;\">";
//    groupShelterList += "Multi-Stop Icon</li>";
//    groupShelterList += "<li style=\"background-color:#AAF8AA; font-variant:small-caps; font-weight:bold; font-size: 13px; text-align:center; margin-top:0px; border-bottom-style: solid; border-bottom-width: 1px; display:block;\">";
//    groupShelterList += "Select A Stop Below:</li>";

    var groupShelterList  = "";
    groupShelterList += "<div class=\"labelShelterGroupInstructions\">\n";
    groupShelterList += "  <h1 class=\"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;
    for (var c = 0; c < groupObj.shelters.length; c++)
    {
        if (groupObj.isShelterLabelActive)
        {
            if (groupObj.activeShelterLabelID == groupObj.shelters[c].shelterID)
            {
                foundShelter = true;
                break;
            }
        }
    }
    
    if (!foundShelter)
    {
        groupObj.isShelterLabelActive = false;
    }
    
    // create list of shelters in this group sorted by name
    var sortedShelterList = sortSheltersInGroupByName(groupObj);
    
    // 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 < sortedShelterList.length; i++)
    {
        //
        // Determine if the group has an active label. If so change its onmouseover color.
        //
        var labelColor = "#000000";
        var mouseColor = "#0000ff";
        var foundActiveShelter=false;
        if (groupObj.isShelterLabelActive)
        {
            if (groupObj.activeShelterLabelID == sortedShelterList[i].id)
            {
                labelColor = "#0000ff";
                mouseColor = "#0000ff";
                foundActiveShelter = true;                
            }
            else
            {
                labelColor = "#CCCCCC";
                mouseColor = "#CCCCCC";
            }
        }
        else
        {
            labelColor = "#000000";
            mouseColor = "#0000ff";
        }
        
        if ((i % 2) == 0)
        {
            groupShelterList += "<div class=\"labelShelterGroupStopRowEven\">";
        }
        else
        {
            groupShelterList += "<div class=\"labelShelterGroupStopRowOdd\">";
        }
        groupShelterList += "<a style=\"color:" + labelColor + ";\"";
        if (foundActiveShelter)
        	groupShelterList += " id='"+groupObj.labelID+"'";        
        groupShelterList += "   onmouseover=\"this.style.color='" + mouseColor + "'; jsShelterLabelController(" + sortedShelterList[i].id + ", " + true + ", " + false;
        groupShelterList += ");\" onmouseout=\"this.style.color='" + labelColor + "'; jsShelterLabelController(" + sortedShelterList[i].id + ", " + false + ", " + false;
        groupShelterList += ");\" onclick=\"jsShelterLabelController(" + sortedShelterList[i].id + ", " + true + ", " + true + ");\"";
        groupShelterList += ">";
        groupShelterList += sortedShelterList[i].name;
        groupShelterList += "</a>";
        groupShelterList += "</div>";
    }
    groupShelterList += "</div>";
    groupShelterList += "<div class=\"labelCloseIcon\"></div>";
    return groupShelterList;
}

//..................................................................................................................................................................................
function isWellFormedJSON(data_str)
{
    var   braceCount = 0;
    var bracketCount = 0;
    var   quoteCount = 0;
    var     currChar = "";
    
    for (var i = 0; i < data_str.length; i++)
    {
        currChar = data_str.charAt(i);
        switch (currChar)
        {
            case '{':
                braceCount++;
                break;
            case '}':
                braceCount--;
                break;
            case '[':
                bracketCount++;
                break;
            case ']':
                bracketCount--;
                break;
            case '\"':
                quoteCount++;
                break;
            default:
                ;  // Do nothing.
                break;
        }
    }
    
    //    braceCount =   braceCount % 2;
    //    bracketCount = bracketCount % 2;
    quoteCount =   quoteCount % 2;
    
    if ((braceCount != 0)  ||  (bracketCount != 0)  ||  (quoteCount != 0))
    {
        return false;
    }
    else
    {
        return true;
    }
}

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

    //
    // Google mape unload function.
    //
    google.maps.Unload();
    
    purge(document.body);
}

function refreshVehicleList(tVehicleArray, tOutOfServicevehicleArray)
{
    
    if(!stopSearchFlag)
        {
           jQuery("#vehicleSearchSelection").focus();
        }

    //
    // Look to see if the vehicle array has changed. If so update it.
    //
    if (vehicleSearchListArray.length == 0 || forceVehicleUpdate)
    {
        //
        // Add vehicles on routes.
        //
        vehicleSearchListArray = new Array();
        var listIndex = 0;
        var len = tVehicleArray.length;
        for (seCounter = 0 ; seCounter < len ; seCounter++)
        {
            //
            // Pull a vehicle and get its name and id
            //
            var vehicle = tVehicleArray[seCounter];

            if (vehicle == null || vehicle == undefined)
            {
                continue;
            }
            //
            // Store this information in a Map for use in our completion list.
            var tssListItem = new VehicleSearchListItem(vehicle.vehicleID, vehicle.vehicleID+"");
            vehicleSearchListArray[listIndex++] = tssListItem;
        }

        //
        // Add tracking vehicles.
        //
        len = tOutOfServicevehicleArray.length;
        for (seCounter = 0 ; seCounter < len ; seCounter++)
        {
            //
            // Pull a vehicle and get its name and id
            //
            var vehicle = tOutOfServicevehicleArray[seCounter];

            if (vehicle == null || vehicle == undefined)
            {
                continue;
            }
            //
            // Store this information in a Map for use in our completion list.
            tssListItem = new VehicleSearchListItem(vehicle.vehicleID, vehicle.vehicleID+"");
            vehicleSearchListArray[listIndex++] = tssListItem;
        }

        //
        // Now sort the array alphabetically
        //
        vehicleSearchListArray.sort(vehicleSort);

        jQuery("#vehicleSearchSelection").autocomplete(vehicleSearchListArray, {
            minChars: 1,
            max: listIndex,
            top: 7,
            left: 0,
            width: 292,
            mustMatch: false,
            scroll: true,
            scrollHeight: 140,
            autoFill: false,
            matchContains: true,
            selectFirst: true,
            formatItem: acVehicleFormatItem
        }).result(acVehicleResult);

   }
}

function acVehicleFormatItem(row, position, count, search)
{
    return row.value;
}

function acVehicleResult(event, item)
{
    //
    // Check for item in the array holding vehicles on a route.
    //
    // Then check for item in the array holding vehicles that are out of service.
    //
    if (vehicleArray[item.id] != null || vehicleArray[item.id] != undefined)
    {
        var vehicle = vehicleArray[item.id];
        var tLatLng  = vehicle.marker.getLatLng();

        if (vehicle.label != null || vehicle.label != undefined)
        {
            //adjust the label offset
            adjustItemLabelOffset(vehicle);

            vehicle.label.isStatic = true;
            vehicle.label.redraw();
            google.maps.Event.removeListener(vehicle.label.moEvent);
            vehicle.label.isClicked = true;
        }
        //
        // FIXME: Here we'll also need to raise the vehicle to its highest z-order to place this item on the top.
        //
        map.panTo(tLatLng);
    }
    else if (outOfServicevehicleArray[item.id] != null || outOfServicevehicleArray[item.id] != undefined)
    {
        var vehicle = outOfServicevehicleArray[item.id];
        var tLatLng  = vehicle.marker.getLatLng();

        //
        // No label for these vehicles.
        //
        /*
        if (vehicle.label != null || vehicle.label != undefined)
        {
            //adjust the label offset
            adjustItemLabelOffset(vehicle);

            vehicle.label.isStatic = true;
            vehicle.label.redraw();
            google.maps.Event.removeListener(vehicle.label.moEvent);
            vehicle.label.isClicked = true;
        }
        */
        //
        // FIXME: Here we'll also need to raise the vehicle to its highest z-order to place this item on the top.
        //
        map.panTo(tLatLng);
    }
}

function vehicleSort(a,b)
{
    var x = a.value;
    var y = b.value;
    return ((x < y) ? -1 : ((x > y) ? 1 : 0));
}

function setSearch(val){
    if (val== "route"){
        stopSearchFlag = true;
    }else if(val== "vehicle"){
        stopSearchFlag = false;
    }
}

function refreshSearchList(tShelterArray)
{
    //
    // Look to see if the shelter array has changed. If so update it.
    //
    
    if(stopSearchFlag)
    {
       jQuery("#routeSearchSelection").focus();
    }
   
       
    if (shelterSearchListArray.length == 0 || forceShelterUpdate)
    {
        shelterSearchListArray = new Array();
        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 == null || tShelter == undefined)
            {
                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);


        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);

   }
}

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

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

    if (tShelter.label != null || tShelter.label != undefined)
    {
        //adjust the label offset
        adjustItemLabelOffset(tShelter);

        tShelter.label.isStatic = true;
        tShelter.label.redraw();
        google.maps.Event.removeListener(tShelter.label.moEvent);
        tShelter.label.isClicked = true;

        // tShelter.label.show(tShelter.marker.getPoint(), tShelter.labelOffset);
    }
    map.panTo(tLatLng);
}

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

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

//..................................................................................................................................................................................
// 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.
function updateRouteLayer(routeID)
{
    if (routeID == undefined)
    {
        jQuery.getSynch("packet/json/routelayer", getJSONRouteLayer);
    }
    else
    {
        jQuery.getSynch("packet/json/routelayer?" + routeID, getJSONRouteLayer);
    }
}

//
// updateStop(stopID)
//
function updateStop(stopID)
{
    if (stopID == undefined)
    {
        jQuery.get("packet/json/stop", getJSONStop);
    }
    else
    {
        jQuery.get("packet/json/stop?" + stopID, getJSONStop);
    }
}

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

//..................................................................................................................................................................................
// updateShelterMarker - Updates Shelter markers on the map.
function updateShelter(routeID)
{
    if (routeID == undefined)
    {
        jQuery.get("packet/json/shelter?lastShelterHttpRequestTime=" + lastShelterHttpRequestTime, getJSONShelter);
    }
    else if(bFullShelterUpdate == true)
    {
        jQuery.get("packet/json/shelter?routes=" + routeID + "&lastShelterHttpRequestTime=" + lastShelterHttpRequestTime + "&forceUpdate=true", getJSONShelter);
        forceShelterUpdate = true;
        bFullShelterUpdate = false;
    }
    else
    {
        jQuery.get("packet/json/shelter?routes=" + routeID + "&lastShelterHttpRequestTime=" + lastShelterHttpRequestTime, getJSONShelter);
    }
    bHTTPInProgress = true;
}
//..................................................................................................................................................................................
// 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;
}

//
// updateAlerts - Updates the browser with the various alerts the user may have configured.
//
function updateAlerts(cookieAlertTag)
{
    if (doCookiesExistWithPrefix(cookieAlertTag))
    {
        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()
{
    var errorMessage = "ERROR : ";
    try
    {
        if (window.ActiveXObject)                                     // This conditional will evaluate to true only for IE-5 and higher.
        {
            errorMessage += "Failure to load Route sub-menus using ActiveXObject (IE).";
            xmlMenuDoc = new ActiveXObject("Microsoft.XMLDOM");
            xmlMenuDoc.async = false;
            xmlMenuDoc.load(routeMenusFilePath);                      // Note: routeMenusFilePath is declared as a Global and its value set in index.html.
            menusByRoute = xmlMenuDoc.getElementsByTagName("route");  // Extract the route menu details from the image of the .xml file.
        }
        else  if (window.XMLHttpRequest)                              // This conditional evaluates to true for Safari and Firefox.
        {
            errorMessage += "Failure to load Route sub-menus using XMLHttpRequest (Safari or Firefox).";
            var tempdoc = new XMLHttpRequest();
            tempdoc.open("GET", routeMenusFilePath, false);
            tempdoc.send(null);
            xmlMenuDoc = tempdoc.responseXML;
            menusByRoute = xmlMenuDoc.getElementsByTagName("route");  // Extract the route menu details from the image of the .xml file.
        }
        else                                                          // Catch all for other Standards Compliant Browsers.  [Will also work with Firefox, but not Safari or IE.]
        {
            errorMessage += "Failure to load Route sub-menus using createDocument (Not IE, Safari, or Firefox).";
            xmlMenuDoc = document.implementation.createDocument("","doc",null);
            xmlMenuDoc.async = false;
            xmlMenuDoc.load(routeMenusFilePath);                      // Note: routeMenusFilePath is declared as a Global and its value set in index.html.
            menusByRoute = xmlMenuDoc.getElementsByTagName("route");  // Extract the route menu details from the image of the .xml file.
        }
    }
    catch(e)
    {
        haveRouteMenus = false;                                       // Note: haveRouteMenus is declared as a Global and set to true in index.html.
        alert(errorMessage);
    }
    finally
    {
        errorMessage = null;
    }
}

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 zDirectionalIconOrder(marker,b){
    return -marker.directionalIcon.visualOrder*1000000;
}

function zVisualOrder(visualOrder)
{
    return - visualOrder*1000000;
}

function launchURL(url)
{
    launchURLStatus = true;
    
    //
    // 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?"))
            {
                jQuery("#drawers").accordion("activate", "#alert-drawer");
                jQuery("#alerts").attr("src", url);
            }
            break;
        case "EDIT":
            if (confirm("You are already editing another Alert would you like to continue?"))
            {
                jQuery("#drawers").accordion("activate", "#alert-drawer");
                jQuery("#alerts").attr("src", url);
            }
            break;
        default:
            jQuery("#drawers").accordion("activate", "#alert-drawer");
            jQuery("#alerts").attr("src", url);
            break;
    }
}

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 callShowRouteLayers = true;   // if callShowRouteLayers is true toggleRouteLayer for a given route will not be called and vise versa
function onClickAllRoutes(isChecked){
    var toogleRouteId = generateRouteIdForToggle();
    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;
            }
            if(!callShowRouteLayers){
                toggleRouteLayer(routeId);
            }
        }
        if(callShowRouteLayers){
            callShowRouteLayers = false;
            showRouteLayers();
        }
    }
    if(!isChecked){ // select all check box is unchecked showRouteLayers is to be called.
       callShowRouteLayers = true;
    }
    return true;
}

function generateRouteIdForToggle(){
    var toogleRouteId = "";
    if(routeIDString != "" && routeIDListString != ""){
        var separator = ",";
        var allArray = routeIDListString.split(separator);
        var allArrayLength = allArray.length;
        var selectedRouteArray = routeIDString.split(separator);
        var selectedRouteArrayLength = selectedRouteArray.length;
        if(allArrayLength == selectedRouteArrayLength){
            toogleRouteId = routeIDListString;
            callShowRouteLayers = true;
        }else{
            var i;
            var j;
            var flag;
            for ( i = 0; i < allArrayLength; i++){
                flag = true;
                for ( j = 0; j < selectedRouteArrayLength; j++){
                    if(allArray[i] == selectedRouteArray[j]){
                        flag = false;
                    }
                }
                if(flag){
                    if(toogleRouteId == ""){
                        toogleRouteId = allArray[i];
                    }else{
                        toogleRouteId = toogleRouteId + separator + allArray[i];
                    }
                }
            }
        }
    }
    return toogleRouteId;
}

function exists(obj) {
	  if (obj == null || obj == undefined)
		return false;
		
	  return true;	
}

function sortSheltersInGroupByName(groupObj) {
	var result = [];
	
    for (var i = 0; i < groupObj.shelters.length; i++) {
    	result[i] = new ShelterSearchListItem(groupObj.shelters[i].shelterID, groupObj.shelters[i].shelterName);
    }
    
    result.sort(compareShelters);
	
	return result;
}

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

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

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

	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;		
}


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

//]]>
