   //
   // NOTE: The functions below are modified from the following web example:
   //    http://econym.googlepages.com/example_map4c.htm
   //

    //<![CDATA[

   var contactsGoogleMap =
   {
      lastMarker: -1,

      init:
      function(mapDiv, searchDiv, sLinkDiv, xmlFile)
      {
         // Exit here if the browser is not compatible with google maps
         if (!GBrowserIsCompatible()) return;

         // Cannot proceed if there is no XML file to load
         if(xmlFile == "" || xmlFile == null) return;

         // Exit if the mapDivID is not a string
         this.objMap = (typeof(mapDiv) == "string") ? document.getElementById(mapDiv) : mapDiv;
         // Exit if objMap could not be found or is not an object
         if(!this.objMap) return;
         
         this.sLinkDiv = (typeof(sLinkDiv) == "string") ? document.getElementById(sLinkDiv) : sLinkDiv;

         // arrays to hold variants of the info window html with get direction forms open
         this.gmarkers = [];

         this.map = new GMap2(this.objMap);
         // Add map controls so the user can zoom and pan the map
         this.map.addControl(new GLargeMapControl());    // alternative: GSmallMapControl()
         this.map.addControl(new GMapTypeControl());     // Toggle between map types
         this.map.addControl(new GScaleControl());       // Map Scale
         this.map.enableScrollWheelZoom();  // Enable zoom by mouse wheel

         // Add an overview map control
         var ovMap = new GOverviewMapControl();
         this.map.addControl(ovMap);
         // Hide the overview by default:
         ovMap.hide();
         
         // Begin centering the map on the sac and los points
         this.map.setCenter(new GLatLng(0,0), 0); // Set a default center position for now

         // Load the new coordinates through an xml file
         GDownloadUrl(xmlFile, this.doLoad);

         // Add GDirections object
         var gdirLayer = (typeof(searchDiv) == "string") ? document.getElementById(searchDiv) : searchDiv;
         // Exit here if the search div could not be found
         if(gdirLayer == null) return;

         this.gdir = new GDirections(this.map, gdirLayer);
         this.gdir.Layer = gdirLayer;

         // === Array for decoding the failure codes ===
         var reasons=[];
         reasons[G_GEO_SUCCESS]            = "Success";
         reasons[G_GEO_MISSING_ADDRESS]    = "Missing Address: The address was either missing or had no value.";
         reasons[G_GEO_UNKNOWN_ADDRESS]    = "Unknown Address:  No corresponding geographic location could be found for the specified address.";
         reasons[G_GEO_UNAVAILABLE_ADDRESS]= "Unavailable Address:  The geocode for the given address cannot be returned due to legal or contractual reasons.";
         reasons[G_GEO_BAD_KEY]            = "Bad Key: The API key is either invalid or does not match the domain for which it was given";
         reasons[G_GEO_TOO_MANY_QUERIES]   = "Too Many Queries: The daily geocoding quota for this site has been exceeded.";
         reasons[G_GEO_SERVER_ERROR]       = "Server error: The geocoding request could not be successfully processed.";
         reasons[G_GEO_BAD_REQUEST]        = "A directions request could not be successfully parsed.";
         reasons[G_GEO_MISSING_QUERY]      = "No query was specified in the input.";
         reasons[G_GEO_UNKNOWN_DIRECTIONS] = "The GDirections object could not compute directions between the points.";

         this.gdir.errCode = reasons;

         // === catch Directions errors ===
         var errSearchFunc =
            function() {
              var code = this.getStatus().code;
              var reason = "Code " + code;
              if (this.errCode[code])
              {
                reason = this.errCode[code]
              }

               this.Layer.style.display = "block";   // Show the layer
               this.Layer.innerHTML = "<h3>Failed to obtain directions</h3>" + reason;
            };

         var loadSearchFunc =
            function() {
               this.Layer.style.display = "block";   // Show the layer
               contactsGoogleMap.setSelectionLinks();
               // Clear the directions layer
               this.Layer.innerHTML = "";

               // Scroll the window to the directions
               var xPos, yPos;
               xPos = this.Layer.offsetLeft;
               yPos = this.Layer.offsetTop;
               
               //setTimeout("window.scrollTo(" + xPos + "," + yPos + ")", 10);

               // Close the maps info window
               contactsGoogleMap.map.closeInfoWindow();
               contactsGoogleMap.map.checkResize();
           };

         GEvent.addListener(this.gdir, "error", errSearchFunc);
         GEvent.addListener(this.gdir, "load", loadSearchFunc);
      },

      // Loads XML data into the google map
      doLoad:
      function(data, responseCode)
      {
         var map = contactsGoogleMap.map;
         if(map == null) return;
         
         // Create new bounds item to extend the map's zoom level         
         var bounds = new GLatLngBounds();
         
         var xml = GXml.parse(data);
         var markers = xml.documentElement.getElementsByTagName("marker");
         // Loop through each marker and set a new point on the map
         for (var i = 0; i < markers.length; i++)
         {
            var point = new GLatLng(parseFloat(markers[i].getAttribute("lat")),
                                    parseFloat(markers[i].getAttribute("lng")));

            // Get title and detail attributes
            var title = markers[i].getAttribute("title");
            var details = markers[i].getAttribute("details");

            // Create a new marker for this point
            var newMarker = contactsGoogleMap.createMarker(point, title, details);
            // Add the marker to the map overlay
            map.addOverlay(newMarker);
            // Extend the map bounds
            bounds.extend(point);
         }

         // Setup the selection links
         contactsGoogleMap.setSelectionLinks();

         // Center the map on both points
         map.setZoom(map.getBoundsZoomLevel(bounds));
         //this.map.setCenter(new GLatLng(38.601044, -121.450139));
         map.setCenter(bounds.getCenter());
      },

      setSelectionLinks:
      function()
      {
         if(!this.sLinkDiv) return;

         var elemOn = this.lastMarker;

         // Clear the selection link html
         this.sLinkDiv.innerHTML = "";
         for(var i = 0; i < this.gmarkers.length; i++)
         {
            var elemCSS = "mapLink" + ( (i == elemOn) ? " sel" : "");
            var title = this.gmarkers[i].selTitle;
            var detail = this.gmarkers[i].selDetail;
            var html = '<div class="' + elemCSS + '">' +
                       '<div><a href="javascript:contactsGoogleMap.showMarkerHTML(' + i + ')" class="title" ' +
                       'title="' + title + '"><big>' + title + '</big></a></div>' +
                       '<div class="details">' + detail + '</div></div>';
            this.sLinkDiv.innerHTML += html;
         }
      },

      getGMapFormHTML:
      function(htmlStart, topForm, hideFieldID, markerID, lat, lng)
      {
         // If selection is FROM then the start address is TO, and visa versa.
         var startAddr = "daddr";
         var enterAddrText = "To ";
         if(hideFieldID == "daddr")
         {
            startAddr = "saddr";
            enterAddrText = "From ";
         }
         var htmlForm = '<form action="javascript:contactsGoogleMap.getDirections()" ' +
                        'class="formstyle1 flat bgForm1" style="width: 300px;">' +
                        '<fieldset class="compress">' + htmlStart +
                        '<ol>' +
                        '<li class="nofloat">' + topForm + '</li>' +
                        '<li>' +
                        '<label for="' + startAddr + '">' + enterAddrText + 'Address</label>' +
                        '<input type="text" size="30" maxlength="40" class="bluefield" ' +
                        'name="' + startAddr + '" id="' + startAddr + '" value="" />' +
                        '</li>' +
                        '<li class="nofloat blueBar_top">' +
                        '<label for="walk">Walk&nbsp;</label><input type="checkbox" name="walk" id="walk" />' +
                        '&nbsp;&nbsp;' +
                        '<label for="highways">Avoid Highways&nbsp;</label><input type="checkbox" name="highways" id="highways" />' +
                        '</li>' +
                        '<li class="buttons blueBar_top">' +
                        '<input value="Get Directions" type="submit" class="bluebut" />' +
                        '</li>' +
                        '</ol><input type="hidden" name="' + hideFieldID + '" id="' + hideFieldID + '" ' +
                        'value="' + markerID + '@' + lat + ',' + lng + '" />' +
                        '</fieldset></form>';
         return htmlForm;
      },

      // A function to create the marker and set up the event window
      createMarker:
      function(point, name, details)
      {
         var markerPos = this.gmarkers.length;
         var htmlStartBasic = '<b>' + name + '</b><div style="white-space: nowrap;">' + details + '</div>';
         var htmlStart = '<legend class="legend"><b>' + name + '</b></legend><div class="highlight">' + details + '</div>';

         var format_toHTML = 'Directions:&nbsp;<b>To Here</b> - ' +
                             '<a href="javascript:contactsGoogleMap.showMarkerHTML(' + markerPos + ',2)">From Here</a>';

         format_toHTML = this.getGMapFormHTML(htmlStart, format_toHTML, "daddr", name, point.lat(), point.lng());

         var format_fromHTML = 'Directions:&nbsp;' +
                              '<a href="javascript:contactsGoogleMap.showMarkerHTML(' + markerPos + ',1)">To Here</a> - ' +
                              '<b>From Here</b>';

         format_fromHTML = this.getGMapFormHTML(htmlStart, format_fromHTML, "saddr", name, point.lat(), point.lng());

         var marker = new GMarker(point);

         // Use the marker as an object to setup it's html and functions
         marker.toHTML = format_toHTML;
         marker.fromHTML = format_fromHTML;

         var newHtml = htmlStartBasic + 'Directions:&nbsp;<a href="javascript:contactsGoogleMap.showMarkerHTML(' + markerPos + ',1)">To Here</a>' +
                              ' - <a href="javascript:contactsGoogleMap.showMarkerHTML(' + markerPos + ',2)">From Here</a><br />';

         marker.htmlStart = newHtml;

         GEvent.addListener(marker, "click",
            function() { marker.openInfoWindowHtml(newHtml); }
            );
         // save the info we need to use later for the side_bar
         this.gmarkers.push(marker);

         // Finally, add the link to the selection div
         marker.selTitle = name;
         marker.selDetail = details;

         return marker;
      },

      // functions that open the directions forms
      showMarkerHTML:
      function(i, mode)
      {
         this.lastMarker = i;

         var mode = (isNaN(parseInt(mode))) ? 0 : parseInt(mode);
         if(mode > 2) mode = 2;
         // Modes:
         // 0 = Start
         // 1 = To
         // 2 = From

         var html;
         switch(mode)
         {
            case 0:
               html = this.gmarkers[i].htmlStart;
            break;
            case 1:
               html = this.gmarkers[i].toHTML;
            break;
            case 2:
               html = this.gmarkers[i].fromHTML;
            break;
         }
         this.gmarkers[i].openInfoWindowHtml(html);
      },

      // ===== request the directions =====
      getDirections:
      function()
      {
         if(this.objMap == null) return;
         if(this.gdir == null) return;

         // ==== set the start and end locations ====
         var saddr = document.getElementById("saddr").value;
         var daddr = document.getElementById("daddr").value;

         if(saddr == "" || daddr == "")
         {
            this.gdir.Layer.style.display = "block";
            this.gdir.Layer.innerHTML = "<h4>Please enter an address</h4>";
            return;
         }
         
         // Clear the directions layer
         this.gdir.Layer.innerHTML = '<img src="http://framework.communitycollege.org/images/tccf_loader1.gif" ' +
                                     'alt="tccf_loader1.gif" align="absmiddle" />' +
                                     '&nbsp;Loading directions, please wait...';

         // ==== Set up the walk and avoid highways options ====
         var opts = {};
         if (document.getElementById("walk").checked)
           opts.travelMode = G_TRAVEL_MODE_WALKING;

         if (document.getElementById("highways").checked)
           opts.avoidHighways = true;
           
         // Clear any previous loads
         this.gdir.clear();
         this.gdir.load("from: "+saddr+" to: "+daddr, opts);
      }
   };
    //]]>

