function load() {
  if (GBrowserIsCompatible()) {
    // this function checks to make sure the browser is compatible,
    // then loads the basics and goes to the function that sets the initial map
    map = new GMap2(document.getElementById('map'));
    geocoder = new GClientGeocoder();
    map.addControl(new GSmallMapControl());
    map.addControl(new GMapTypeControl());
    initializeMap(startPoint, 11); // args: human-readable address set as a global, zoom level; startPoint is set in the globals code
    //the next line checks to see if there is a query string, and if so, processes any zipcode value passed
    if (window.location.search.substring(1) != '') {
      //here we check to see if the zipcode arg is present in the query string
      var zip = getQueryString('zipcode');
      //no entry for zipcode means zip will be ''
      if (zip == '') {
        zip = '';
        //no zip, so look for a branch name
        var branch = getQueryString('branch');
        //if no entry for branch, it will be an empty string
        if (branch.length > 0) {
          searchByBranchName(branch);
        }
      } else {
        //enter the zip code in the input box, then search for and display for the zip code
        document.getElementById('zipcode').value=zip;
        searchByZip(zip);
      }
    }
  } else { // if not GBrowserIsCompatible
    alert("Unfortunately, the Google Maps function of this page is not compatible with the browser you are using.");
  }
}

function initializeMap(address, zoom) {
  // this function gets the lat/long for a center point
  // then either displays the map centered over that point
  // zoomed to the arg passed when function called
  geocoder.getLatLng(address, function(point) {
    if (!point) {
      alert('Please check your entry. The address: ' + address + ' was not found.');
    } else {
      map.setCenter(new GLatLng(point.lat(),point.lng()), zoom);
    }
  })
}

function getQueryString(key) {
  //function used with the section of the load() function that looks for a query string
  key = key.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
  var regex = new RegExp("[\\?&]"+key+"=([^&#]*)");
  var qs = regex.exec(window.location.href);
  if (qs == null) return '';
  else return qs[1];
}

function searchByZip(zipcode) {
  // function gets a center point for a zip, then calls function to get the radius around that point
  if (zipcode == '') {
    alert('You must enter a zip code.');
    return;
  }
  geocoder.getLatLng(zipcode, function(point) {
    if (!point) {
      alert('Please check your entry. The zip code: ' + zipcode + ' was not found.');
    } else {
      getRadius(point);
    }
  });
}

function searchByBranchName(name) {
  // set the xmlHttp object for the appropriate browser; if the user's browser doesn't support xmlHttp, null will be returnd
  xmlHttp = GetXmlHttpObject();
  if (xmlHttp == null) {
    alert('It appears that your browser does not support AJAX, required for this feature');
    return;
  }
  // the following is a callback function that runs whenever the state of xmlHttp changes
  xmlHttp.onreadystatechange=function() {
    // readyState 4 means the data retrieval is complete
    if (xmlHttp.readyState == 4) {
      // status 200 is returned if the URL was accessible and the server answered
      if (xmlHttp.status != 200) {
        alert('There is a problem with the server at this time. Please try again later.');
      } else {
        // store the retrieved values in lat and long for passing on the the other function for further processing
        var xmlDoc = xmlHttp.responseXML;
        var lat = xmlDoc.getElementsByTagName("lat")[0].childNodes[0].nodeValue;
        var lng = xmlDoc.getElementsByTagName("long")[0].childNodes[0].nodeValue;
        getRadius(0, lat, lng)
      }
    }
  }
  // set up the URL that runs the MySQL data access
  var searchUrl = 'bin/locator_code(branchLatLong).php?branch=' + name;
  // then get the data and process it
  xmlHttp.open("GET", searchUrl, true);
  // send the request to the server
  xmlHttp.send(null);
}

function GetXmlHttpObject() {
  // function to define the appropriate xmlHttp object based on user's browser
  if (window.XMLHttpRequest) {
    // code for IE7+, Firefox, Chrome, Opera, Safari
    return new XMLHttpRequest();
  }
  if (window.ActiveXObject) {
    // code for IE6, IE5
    return new ActiveXObject("Microsoft.XMLHTTP");
  } else {
    return null;
  }
}

function getRadius(center, lat, lng) {
  // function queries lat/long table to return all points in specified radius
  // NOTE: may want to change so that radius is passed by the call statment for increased flexibility of use,
  //            say, for using with the single branch lat/long function
  // the function allows lat and lng to be optional, so it can be called by getRadius(point) or getRadius(0, lat, lng)
  // NOTE that lat and lng are used only if center is set to 0
  // we could leave alone the lat and lng values when not passed, but lets set them
  if (typeof lat == 'undefined' ) lat = null;
  if (typeof lng == 'undefined' ) lng = null;
  // then check to see if there is a center, and if not, set the lat and long
  // this is so the same code can be used no matter which args are passed
  if (center != 0) {
    var lat = center.lat();
    var lng = center.lng();
  }
  var radius = document.getElementById('radiusSelect').value;
  var searchUrl = 'bin/locator_code(dbQueries).php?lat=' + lat + '&long=' + lng + '&radius=' + radius;
  GDownloadUrl(searchUrl, function(data, responseCode) {
    if (responseCode == 200) { //checks to make sure the url was accessible
        var xml = GXml.parse(data);
        markersXML = xml.documentElement.getElementsByTagName('marker');
        setMarkers(markersXML);
    } else {
      alert('There appears to be a problem with the server at this time. Please try again later.');
    }
  })
}

function setMarkers() {
  // function sets the markers on the map
  map.clearOverlays();
  var sidebar = document.getElementById('sidebar'); // set object reference for the sidebar on the left
  sidebar.innerHTML = ''; // whenever redrawing, first clear
  // test to make sure nodes were returned in the xml stream and give 
  if (markersXML.length == 0) {
    sidebar.innerHTML = '<p style="margin:0px 0px 0px 4px">Please check your entery to make sure it is correct. No results were found for what was entered.</p>';
    return;
  }
  var bounds = new GLatLngBounds();
  for (var i = 0; i < markersXML.length; i++) {
    var distance = parseFloat(markersXML[i].getAttribute('distance'));
    address = markersXML[i].getAttribute('address')
    var point = new GLatLng(parseFloat(markersXML[i].getAttribute('lat')), parseFloat(markersXML[i].getAttribute('long')));
    // in the following the name and content is set for each of the three tabs; label1, 2, 3 refer to the names on the tabs; html1, 2, 3 are the content; toHere and fromHere are the changing content
    var label1 = 'Branch Info';
    // for now the branch page locations are different from the central page, so get what is needed for the reference
    //var loc = (markersXML[i].getAttribute('name') == 'central') ? '/central/' : ''; // commented out because was creating /central//central/
    var loc = '';
    var html1 = 
      '<div style="width:280px; height:200px;">' +
        '<strong><a href="' + loc + markersXML[i].getAttribute('link') + '" target="_blank">' + 
          markersXML[i].getAttribute('fullName') + 
        '</a></strong><br />' +
        '<p>' + markersXML[i].getAttribute('address') + ', ' + markersXML[i].getAttribute('zip') +
          ' | ' + markersXML[i].getAttribute('phone') + ' | ' +
          '<a href="mailto:' + markersXML[i].getAttribute('email') + '">' + markersXML[i].getAttribute('email') + '</a>' +
        '</p>' +
        '<strong>Service Hours:</strong>'+
        '<ul style="list-style-type: none">' +
          '<li>Monday: ' + markersXML[i].getAttribute('Mon') + '</li>' +
          '<li>Tuesday: ' + markersXML[i].getAttribute('Tue') + '</li>' +
          '<li>Wednesday: ' + markersXML[i].getAttribute('Wed') + '</li>' +
          '<li>Thursday: ' + markersXML[i].getAttribute('Thu') + '</li>' +
          '<li>Friday: ' + markersXML[i].getAttribute('Fri') + '</li>' +
          '<li>Saturday: ' + markersXML[i].getAttribute('Sat') + '</li>' +
          '<li>Sunday: ' + markersXML[i].getAttribute('Sun') + '</li>' +
        '</ul>'+
      '</div>';
    var label2 = 'Drive';
    // arrays are provided for the second and third tabs of each marker so that the text can be easily referenced and changed
    html2_toHere[i] = 
      '<div style="width:300px; height:200px">' +
        '<br />' +
        '<div style="float:left; width:110px; font-size:180%">' +
          '<strong>To here</strong>' +
        '</div>' +
        '<div style="float:right; width:190px">' +
          '(<a href="javascript:fromHereDrive(' + i + ')">Click here to get driving directions from this library</a>)' +
        '</div>' +
        '<div style="clear:both"></div>' +
        '<hr />' +
        '<p>Enter the address and zip code you are driving <strong>from</strong> below. ' + 
        '<strong>Example:</strong> "123 Main St., 12345"</p>' +
        '<form action="http://maps.google.com/maps" method="get" target="_blank">' +
          '<input type="text" size=40 maxlength=40 name="saddr" id="saddr" value="" /><br><br />' +
          '<input value="Get Directions" type="submit">' +
          '<input type="hidden" name="daddr" value="' + 
          point.lat() + ',' + point.lng() + "(" + markersXML[i].getAttribute('fullName') + ")" + '" />' +
        '</form>' +
      '</div>';
    html2_fromHere[i] = 
      '<div style="width:300px; height:200px">' +
        '<br />' +
        '<div style="float:left; width:110px; font-size:180%">' +
          '<strong>From here</strong>' +
        '</div>' +
        '<div style="float:right; width:190px">' +
          '(<a href="javascript:toHereDrive(' + i + ')">Click here to get driving directions to this library</a>)' +
        '</div>' +
        '<div style="clear:both"></div>' +
        '<hr />' +
        '<p>Enter the address and zip code you are driving <strong>to</strong> below. ' +
        '<strong>Example:</strong> "123 Main St., 12345"</p>' +
        '<form action="http://maps.google.com/maps" method="get"" target="_blank">' +
          '<input type="text" size=40 maxlength=40 name="daddr" id="daddr" value="" /><br /><br />' +
          '<input value="Get Directions" type="submit">' +
          '<input type="hidden" name="saddr" value="' + 
          point.lat() + ',' + point.lng() + " (" + markersXML[i].getAttribute('fullName') + ")" + '"/>' +
        '</form>' +
      '</div>';
    var label3 = 'Bus/Train';
    html3_toHere[i] =
      '<div style="width:300px; height:200px">' +
        '<br />' +
        '<div style="float:left; width:110px; font-size:180%">' +
          '<strong>To here</strong>' +
        '</div>' +
        '<div style="float:right; width:190px">' +
          '(<a href="javascript:fromHereTransit(' + i + ')">Click here to get public transit directions from this library</a>)' +
        '</div>' +
        '<div style="clear:both"></div>' +
        '<hr />' +
        '<p>Enter the address and zip code you are travelling <strong>from</strong> below. ' + 
        '<strong>Example:</strong> "123 Main St., 12345"</p>' +
        '<form action="http://maps.google.com/maps" method="get" target="_blank">' +
          '<input type="text" size=40 maxlength=40 name="saddr" id="saddr" value="" /><br><br />' +
          '<input value="Get Directions" type="submit">' +
          '<input type="hidden" name="daddr" value="' + 
          point.lat() + ',' + point.lng() + "(" + markersXML[i].getAttribute('fullName') + ")" + '" />' +
          '<input type="hidden" name="dirflg" value="r">' +
        '</form>' +
      '</div>';
    html3_fromHere[i] =
      '<div style="width:300px; height:200px">' +
        '<br />' +
        '<div style="float:left; width:110px; font-size:180%">' +
          '<strong>From here</strong>' +
        '</div>' +
        '<div style="float:right; width:190px">' +
          '(<a href="javascript:toHereTransit(' + i + ')">Click here to get public transit directions to this library</a>)' +
        '</div>' +
        '<div style="clear:both"></div>' +
        '<hr />' +
        '<p>Enter the address and zip code you are travelling <strong>to</strong> below. ' +
        '<strong>Example:</strong> "123 Main St., 12345"</p>' +
        '<form action="http://maps.google.com/maps" method="get"" target="_blank">' +
          '<input type="text" size=40 maxlength=40 name="daddr" id="daddr" value="" /><br /><br />' +
          '<input value="Get Directions" type="submit">' +
          '<input type="hidden" name="saddr" value="' + 
          point.lat() + ',' + point.lng() + " (" + markersXML[i].getAttribute('fullName') + ")" + '"/>' +
          '<input type="hidden" name="dirflg" value="r">' +
        '</form>' +
      '</div>';
    // call the function that created the tabbed infoWindow
    markers[i] = createTabbedMarker(point, label1, html1, label2, html2_toHere[i], label3, html3_toHere[i]);
    map.addOverlay(markers[i]); // add the marker to the map
    bounds.extend(point);
    // create the sidebar entry and then add it to the sidebar
    var sidebarEntry = createSidebarEntry(markers[i], i, distance);
    sidebar.appendChild(sidebarEntry);
  }
  // with all the markers created, we set the center and zoom and draw the map
  var zoom = (map.getBoundsZoomLevel(bounds) >= minZoom) ? minZoom : map.getBoundsZoomLevel(bounds);
  //map.setCenter(bounds.getCenter(), map.getBoundsZoomLevel(bounds));
  map.setCenter(bounds.getCenter(), zoom);
}

function createTabbedMarker(point, label1, html1, label2, html2, label3, html3) {
  //this is the function to create a tabbed info box for a marker
  var marker = new GMarker(point);
  GEvent.addListener(marker, "click", function() {
    marker.openInfoWindowTabsHtml([new GInfoWindowTab(label1,html1), new GInfoWindowTab(label2,html2), new GInfoWindowTab(label3,html3)]);
  });
  return marker;
}

function toHereDrive(i) {
  // this changes the content section of the second tab to show the "toHere" interface
  map.updateCurrentTab(function(currentTab) {
    currentTab.contentElem.innerHTML = html2_toHere[i];
  })
}

function fromHereDrive(i) {
  // this changes the content section of the second tab to show the "fromHere" interface
  map.updateCurrentTab(function(currentTab) {
    currentTab.contentElem.innerHTML = html2_fromHere[i];
  })
}

function toHereTransit(i) {
  // this changes the content section of the third tab to show the "toHere" interface
  map.updateCurrentTab(function(currentTab) {
    currentTab.contentElem.innerHTML = html3_toHere[i];
  })
}

function fromHereTransit(i) {
  // this changes the content section of the third tab to show the "fromHere" interface
  map.updateCurrentTab(function(currentTab) {
    currentTab.contentElem.innerHTML = html3_fromHere[i];
  })
}

function createSidebarEntry(marker, i, distanceToCenter) {
  // function to draw the sidebar entry
  var div = document.createElement('div');
  //if the distince is needed, use "distanceToCenter.toFixed(1) to retrieve it
  var html = 
    '<p style="margin:0px 0px 0px 4px">' +
    '<strong>' + markersXML[i].getAttribute('fullName') + '</strong><br/>' +
    markersXML[i].getAttribute('address') + '</p>';
  div.innerHTML = html;
  div.style.cursor = 'pointer';
  div.style.marginBottom = '5px'; 
  GEvent.addDomListener(div, 'click', function() {
    GEvent.trigger(marker, 'click');
  });
  GEvent.addDomListener(div, 'mouseover', function() {
    div.style.backgroundColor = '#eee';
  });
  GEvent.addDomListener(div, 'mouseout', function() {
    div.style.backgroundColor = '#fff';
  });
  return div;
}

