title: Javascript insists it's not defined, it totally is
body: <p>I'm not used to writing JS, honestly, and to make matters worse I'm working with the Google Maps API which, while well-documented, is a bear. So, I've written a function that allows a users to zoom onto the map from a link. But the interpreter insists my function isn't defined when I call it. The function is "zoomTo" and it appears in the following monster script.</p>
  
  <pre><code>function load() {
      if (GBrowserIsCompatible()) {
          var gmarkers = [];
          var htmls = [];
          var i = 0;
          // Read the data
          //++++++++++++++++
          GDownloadUrl("/assets/data/nolag.xml", function(data) {
                  var xml = GXml.parse(data);
                  var markers = 
  
          xml.documentElement.getElementsByTagName("marker");
  
          // Draw icons
          for (var i = 0; i &lt; markers.length; i++) {
              var locoName = markers[i].getAttribute("locoName");
              var speed = markers[i].getAttribute("speed");
              var ip = markers[i].getAttribute("ip");
              var date = markers[i].getAttribute("captureTime");
              var lat = markers[i].getAttribute("lat");
              var lng = markers[i].getAttribute("lng");
              var location = markers[i].getAttribute("location");
              var heading = markers[i].getAttribute("heading");
              var type = markers[i].getAttribute("type");
              var point = new GLatLng(parseFloat(markers[i].getAttribute("lat")),
                                     parseFloat(markers[i].getAttribute("lng")));
              var marker = createMarker(point, locoName, speed, ip, date, lat, lng, location, heading, type);
              map.addOverlay(marker);
              }
          });
  
  
          // create the map
          var map = new GMap2(document.getElementById("map"));
          map.addControl(new GLargeMapControl3D());
          map.addControl(new GMapTypeControl());
          map.setCenter(new GLatLng(40.5500, -72.1700), 7);
          map.enableScrollWheelZoom(); 
          NEC = new GPolyline(NECRoute, "#0d004c", 3, 0.7);
          map.addOverlay(NEC);
  
      // A function to create the marker and set up the event window
      //+++++++++++++++++
  
      function createMarker(point, locoName, speed, ip, date, lat, lng, location, heading, type) {
              var marker = new GMarker(point, customIcons[type]);
              marker.tooltip = '&lt;div class="tooltip"&gt;&lt;h1&gt;' + locoName + '&lt;/h1&gt;&lt;h2&gt;' + speed + '&lt;br/&gt;' + location + '&lt;/h2&gt;&lt;/div&gt;';
              marker.contextmenu = '&lt;div class="contextmenu"&gt;Hello world&lt;/div&gt;';
              var satellite = "&lt;img src=\"./images/icons/satellite.gif\"&gt;";
              var gps = "&lt;img src=\"./images/icons/gps.gif\"&gt;";
              var cmu = "&lt;img src=\"./images/icons/cmu.gif\"&gt;";
              var ftp = "&lt;img src=\"./images/icons/ftp.gif\"&gt;";
              var me1k = "&lt;img src=\"./images/icons/me1k.gif\"&gt;";
              var html = "&lt;div class=\"bubble\"&gt;";
                  html += "&lt;h3&gt;" + locoName + "&lt;span class=\"small-data\"&gt; Route 2150&lt;/span&gt;&lt;/h3&gt;";;
                  html += "&lt;div class=\"toolbar\"&gt;" + gps + satellite + cmu + ftp + me1k + "&lt;/div&gt;";
                  html += "&lt;h4&gt;Heading " + heading + " @ " + speed + " MPH&lt;/h4&gt;"
                  html += "&lt;h4&gt;Lat: " + lat + "&lt;/h4&gt;&lt;h4&gt; Lng: " + lng + "&lt;/h4&gt;";
                  html += "&lt;h4&gt;IP: " + ip + "&lt;/h4&gt;";
                  html += "&lt;h4&gt;&lt;div class=\"sm-button\"&gt;&lt;a style='color: #FFFFFF; decoration:none;' href='map_detail.php'&gt;Details&lt;/a&gt;&lt;/div&gt;&lt;div class=\"sm-button\"&gt;Zoom To&lt;/div&gt;&lt;/h4&gt;";
                  html += "&lt;/div&gt;";
          GEvent.addListener(marker, "click", function() {
              marker.openInfoWindowHtml(html);
          });
          gmarkers[i] = marker;
          htmls[i] = html;
          i++;
  
          //  ======  The new marker "mouseover" and "mouseout" listeners  ======
          GEvent.addListener(marker,"mouseover", function() {
              showTooltip(marker);
          });        
          GEvent.addListener(marker,"mouseout", function() {
              tooltip.style.visibility="hidden"
          }); 
          return marker;
          } 
  
          // ====== This function displays the tooltip ======
          //+++++++++++++++++++++++++++++++++++++++++++++++++++
          function showTooltip(marker) {
              tooltip.innerHTML = marker.tooltip;
              var point=map.getCurrentMapType().getProjection().fromLatLngToPixel(map.getBounds().getSouthWest(),map.getZoom());
              var offset=map.getCurrentMapType().getProjection().fromLatLngToPixel(marker.getPoint(),map.getZoom());
              var anchor=marker.getIcon().iconAnchor;
              var width=marker.getIcon().iconSize.width;
              var pos = new GControlPosition(G_ANCHOR_BOTTOM_LEFT, new GSize(offset.x - point.x - anchor.x + width,- offset.y + point.y +anchor.y)); 
              pos.apply(tooltip);
              tooltip.style.visibility="visible";
          }
  
  
          // ===== This function is invoked when the mouse goes over an entry in the side_bar =====
          function mymouseover(i) {
              showTooltip(gmarkers[i])
          }
          // ===== This function is invoked when the mouse leaves an entry in the side_bar =====
          function mymouseout() {
              tooltip.style.visibility="hidden";
          }
  
          // This function picks up the side_bar click and opens the corresponding info window
          function myclick(i) {
              gmarkers[i].openInfoWindowHtml(htmls[i]);
          }
  
  
  
  
          // ====== set up marker mouseover tooltip div ======
          var tooltip = document.createElement("div");
          document.getElementById("map").appendChild(tooltip);
          tooltip.style.visibility="hidden";
  
  
          // === create the context menu div ===
          var contextmenu = document.createElement("div");
          contextmenu.style.visibility="hidden";
  
  
          // === functions that perform the context menu options ===
          function zoomTo( lat, lng, level) {
              // perform the requested operation
              map.setCenter( new GLatLng(lat,lng), level);
              // hide the context menu now that it has been used
              contextmenu.style.visibility="hidden";
          }
  
  
          contextmenu.innerHTML = '&lt;div class="context"&gt;&lt;ul&gt;'
          + '&lt;li class="sectionheading"&gt;&lt;a href="javascript:map.setCenter(new GLatLng(40.5500, -72.1700), 7)"&gt;Zoom Out&lt;/a&gt;&lt;/li&gt;'
          + '&lt;li class="sectionheading"&gt;&lt;a href="javascript:zoomTo(42.343193, -71.049442, 14)"&gt;Boston Area&lt;/a&gt;&lt;/li&gt;'
          + '&lt;li&gt;&lt;a href="javascript:zoomTo(42.351662,-71.054978,17)"&gt;South Station, Boston&lt;/a&gt;&lt;/li&gt;'
          + '&lt;li&gt;&lt;a href="javascript:zoomTo(42.333161,-71.060096,17)"&gt;South Hampton&lt;/a&gt;&lt;/li&gt;'
          + '&lt;li&gt;&lt;a href="javascript:zoomTo(41.293422,-72.928587,17)"&gt;New Haven&lt;/a&gt;&lt;/li&gt;'
          + '&lt;li class="sectionheading"&gt;&lt;a href="javascript:zoomTo(40.745696, -74.019699, 12)"&gt;New York Area&lt;/a&gt;&lt;/li&gt;'
          + '&lt;li&gt;&lt;a href="javascript:zoomTo(40.749061,-73.930553,17)"&gt;Sunny Side&lt;/a&gt;&lt;/li&gt;'
          + '&lt;li&gt;&lt;a href="javascript:zoomTo(40.752556,-73.998113,17)"&gt;NY, Penn Station&lt;/a&gt;&lt;/li&gt;'
          + '&lt;li&gt;&lt;a href="javascript:zoomTo(39.957517,-75.181376,17)"&gt;30th Street, Philadelphia&lt;/a&gt;&lt;/li&gt;'
          + '&lt;li&gt;&lt;a href="javascript:zoomTo(39.746481,-75.522090,17)"&gt;Wilmington Shops&lt;/a&gt;&lt;/li&gt;'
          + '&lt;li&gt;&lt;a href="javascript:zoomTo(39.307817,-76.615412,17)"&gt;Baltimore, Penn Station&lt;/a&gt;&lt;/li&gt;'
          + '&lt;li class="sectionheading"&gt;&lt;a href="javascript:zoomTo(38.912675, -76.992874, 14)"&gt;DC Area&lt;/a&gt;&lt;/li&gt;'
          + '&lt;li&gt;&lt;a href="javascript:zoomTo(38.916531,-76.987703,17)"&gt;DC, Ivy City&lt;/a&gt;&lt;/li&gt;'
          + '&lt;li&gt;&lt;a href="javascript:zoomTo(38.900210,-77.005266,17)"&gt;DC, Union Station&lt;/a&gt;&lt;/li&gt;'
          + '&lt;/ul&lt;/div&gt;'; 
  
          map.getContainer().appendChild(contextmenu);
  
  
          // === listen for singlerightclick ===
          GEvent.addListener(map,"singlerightclick",function(pixel,tile) {
              clickedPixel = pixel;
              var x=pixel.x;
              var y=pixel.y;
              if (x &gt; map.getSize().width - 120) { x = map.getSize().width - 120 }
              if (y &gt; map.getSize().height - 100) { y = map.getSize().height - 100 }
              var pos = new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(x,y));
              pos.apply(contextmenu);
              contextmenu.style.visibility = "visible";
          });
          // === If the user clicks on the map, close the context menu ===
          GEvent.addListener(map, "click", function() {
              contextmenu.style.visibility="hidden";
          });
      } else {
        alert("Sorry, the Google Maps API is not compatible with this browser");
      }
  }
  </code></pre>