Make Google maps callback wait for rest of functions to finish - javascript

I am having difficulty with the way google calls its maps api. I have the following calling initMap
<script defer
src="https://maps.googleapis.com/maps/api/js?key=API_KEY_REMOVED&callback=initMap">
</script>
but inside initMap, the following condition if(getPosition() !== false) { never evaluates to true because init map is done before getPosition() has set its object values.
function initMap() {
// set new map, assign default properties
map = new google.maps.Map(document.getElementById('map'), {
center: { lat, lng }, zoom: 14
});
// check if the requested data is usable (lat, lng === numbers) before trying to use it
if(getPosition() !== false) {
map.setCenter( getPosition() ); // set latest position as the map center
addMarker();
console.log("InitMap ran here");
}
}
How can I make it so initMap waits until getPosition() has had a chance to wait for other functions to do their thing? Here is my complete script so it makes more sense.
<script>
console.log(formatTime(Date()));
// https://developers.google.com/maps/documentation/javascript/geolocation
var map; var marker;
var lat = 65.025984; var lng = 25.470794; // default map location in case no position response is available
var res_data; var res_longitude; var res_latitude; var res_speed; var res_time; // res = response (data from the ajax call)
var xhr = new XMLHttpRequest();
function getPosition() {
pos = {
lat: res_latitude,
lng: res_longitude,
};
return ( isNaN(pos.lat) || isNaN(pos.lng) ) ? false : pos; // return pos only if lat and lng values are numbers
}
function initMap() {
// set new map, assign default properties
map = new google.maps.Map(document.getElementById('map'), {
center: { lat, lng }, zoom: 14
});
// check if the requested data is usable (lat, lng === numbers) before trying to use it
if(getPosition() !== false) {
map.setCenter( getPosition() ); // set latest position as the map center
addMarker();
console.log("InitMap ran here");
}
}
// place marker on the map
function addMarker() {
//console.log("Add Marker ran");
//https://developers.google.com/maps/documentation/javascript/markers
if(marker){ marker.setMap(null); } // remove visibility of current marker
marker = new google.maps.Marker({
position: getPosition(),
map: map,
title: formatTime(res_time),
});
marker.setMap(map); // set the marker
}
function getData() {
xhr.addEventListener("load", reqListener);
xhr.open("GET", "http://example.com/data.txt");
xhr.send();
}
function reqListener() {
// res_data = long, lat, accuracy, speed, time
//console.log("reqListener: " + xhr.responseText);
res_data = '[' + xhr.responseText + ']';
res_data = JSON.parse(res_data);
res_latitude = res_data[0]; res_longitude = res_data[1]; res_accuracy = res_data[2]; res_speed = res_data[3]; res_time = res_data[4];
var formatted_time = formatTime(res_time);
document.getElementById('info').innerHTML = '<span class="info">Lat: ' + res_latitude + '</span><span class="info">Long: ' + res_longitude + '</span><span class="info">Accuracy: ' + res_accuracy + '</span><span class="info">Speed: ' + res_speed + '</span><span class="info">' + formatted_time + '</span>';
addMarker();
}
function formatTime(time) {
var t = new Date(time);
var hours, mins, secs;
if(t.getHours() < 10) { hours = "0" + t.getHours(); } else { hours = t.getHours(); }
if(t.getMinutes() < 10) { mins = "0" + t.getMinutes(); } else { mins = t.getMinutes(); }
if(t.getSeconds() < 10) { secs = "0" + t.getSeconds(); } else { secs = t.getSeconds(); }
var hms = hours +':'+ mins +':'+ secs;
return 'Updated: ' + hms;
}
function init() {
getData();
setInterval(getData, 5000);
}
init();
</script>
<script defer
src="https://maps.googleapis.com/maps/api/js?key=API_KEY_REMOVED&callback=initMap">
</script>

Get rid of the callback=initMap from where you load in the Maps API.
Instead make a call to initMap only from where you are then certain everything is loaded. e.g. at the end of reqListener.
function reqListener() {
res_data = '[' + xhr.responseText + ']';
res_data = JSON.parse(res_data);
res_latitude = res_data[0]; res_longitude = res_data[1]; res_accuracy = res_data[2]; res_speed = res_data[3]; res_time = res_data[4];
var formatted_time = formatTime(res_time);
document.getElementById('info').innerHTML = '<span class="info">Lat: ' + res_latitude + '</span><span class="info">Long: ' + res_longitude + '</span><span class="info">Accuracy: ' + res_accuracy + '</span><span class="info">Speed: ' + res_speed + '</span><span class="info">' + formatted_time + '</span>';
initMap();
addMarker();
}
If you're calling reqListener at repeated intervals and don't want to recreate your map, add some logic to the top of initMap like:
if (map !== null) {
return;
}

Related

trying to use scope knowledge to turn variables lati, longi to the values inside ajax response so i can call google map api. is there a flaw?

trying to use scope knowledge to turn variables lati, longi to the values inside ajax response so i can call google map api. is there a flaw?
var lati = 0;
var longi = 0;
$("#artistButton").on('click', function () {
var artist = $("#artistSearch").val().trim()
var queryURL = "https://rest.bandsintown.com/artists/" + artist + "/events?app_id=test&date=upcoming" + artist + "?app_id=test";
var test = $("#map").attr('data-vision')
console.log(test)
if (test === 'hide') {
console.log('this is hidden')
$('#map').hide()
$("#map").attr('data-vision', 'show')
}
else {
console.log('this is visible')
$('#map').show()
$("#map").attr('data-vision', 'hide')
}
$.ajax({
url: queryURL,
method: "GET",
}).then(function (response) {
console.log(response)
var imageURL = response[0].artist.image_url;
var image = $("<img id='pictureSize'>")
var artistName = response[0].artist.name
var todayDate = new Date()
var today = new Date(todayDate);
$("#artistName").html(artistName)
image.attr('src', imageURL)
$("#artistImage").html(image)
$("#venue").html(response[125].venue.name)
lati = response[0].venue.latitude
longi = response[0].venue.longitude
console.log('latitude ' + lati)
console.log('longitude ' + longi)
for (var i = 0; i < response.length; i++) {
var time = moment(response[i].datetime).format("MMM Do, YYYY hh:mm");
var concertDate = new Date(response[i].datetime)
var venueName = response[i].venue.name
var city = response[i].venue.city;
var region = response[i].venue.region
if (today.getTime() < concertDate.getTime()) {
$(".tableData").before($("<tr><td>" + venueName + "</td>" + "<td>" + city + ', ' + region + "</td>" + "<td>" + time + "</td></tr>"))
} else {
continue;
}
}
$("#map").show()
});
$("#concertInfo").find("td").remove();
})
$(document).ajaxComplete(function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
zoom: 10,
center: {
lat: lati,
lng: - longi
}
});
})

Google Map Geocoded TypeError in Callback function

I have the following 2 functions to pull in, geocode, and place markers in a google map.
I keep getting a TypeError: adds[i] is undefined, which of course is causing the rest of the map to bomb.
Here is my code:
// Place Markers on the Map
var PlaceMarkers = function (iw, adds, gc) {
var image = {url: "http://meatmysite.com/Images/star2.png", size: new google.maps.Size(24, 24)};
var aCt = adds.length;
for(var i = 0; i < aCt; ++i) {
GetLatLng(gc, adds[i].address, function(pos) {
if(pos) {
var ipop = '<h1>' + adds[i].title + '</h1>'; // <----- TypeError: adds[i] is undefined
if(!isBlank(adds[i].url)){
ipop += '' + adds[i].url + '<br />';
}
ipop += '<div class="map_item_content" id="mi_content' + i + '">' + adds[i].content + '</div>';
if(!isBlank(adds[i].mainphone)){
ipop += '<br /><strong>Phone:</strong> ' + adds[i].mainphone + '';
}
if(!isBlank(adds[i].mainemail)){
ipop += '<br /><strong>Email:</strong> ' + adds[i].mainemail + '';
}
console.log('HEY NOW: ' + pos.toString() + ' - Location Found!');
var mark = new google.maps.Marker({title: adds[i].title, position: pos, map: map, icon: image, html: ipop});
google.maps.event.addListener(mark, 'click', function(){
iw.setContent(this.html);
iw.open(map, this);
});
}
});
}
};
// Get Lat/Lng Location
var GetLatLng = function(gc, add, f) {
var ret = '';
gc.geocode({'address': add}, function(res, status) {
if (status == 'OK') {
f(res[0].geometry.location);
console.log('Found Here: ' + ret.toString());
}
});
return -1;
};
DEMO RETURNED DATA FOR adds
[
{
"address": "1 My Street Gilbert, AZ 85234",
"title": "My Title 1",
"url": "http://www.myurl.com/",
"mainphone": null,
"mainemail": null,
"content": "1 My Street<br />Gilbert, AZ 85234"
},
{
"address": "2 My Street North Richland Hills, TX 76182",
"title": "My Title 2",
"url": null,
"mainphone": null,
"mainemail": null,
"content": "2 My Street<br />North Richland Hills, TX 76182"
}
]
One option, pass the complete "address" object into the GetLatLng function, and from there into its callback (so you get function closure on it):
// Get Lat/Lng Location
var GetLatLng = function (gc, add, f) {
gc.geocode({
'address': add.address
}, function (res, status) {
if (status == 'OK') {
f(res[0].geometry.location, add);
}
});
};
Then use it like this inside the callback (you could pass just the index into the array also):
GetLatLng(gc, adds[i], function (pos, add) {
if (pos) {
var ipop = '<h1>' + add.title + '</h1>';
if (!isBlank(add.url)) {
ipop += '' + add.url + '<br />';
}
ipop += '<div class="map_item_content" id="mi_content' + i + '">' + add.content + '</div>';
if (!isBlank(add.mainphone)) {
ipop += '<br /><strong>Phone:</strong> ' + add.mainphone + '';
}
if (!isBlank(add.mainemail)) {
ipop += '<br /><strong>Email:</strong> ' + add.mainemail + '';
}
console.log('HEY NOW: ' + pos.toString() + ' - Location Found!');
var mark = new google.maps.Marker({
title: add.title,
position: pos,
map: map,
icon: image,
html: ipop
});
google.maps.event.addListener(mark, 'click', function () {
iw.setContent(this.html);
iw.open(map, this);
});
}
});
proof of concept fiddle
code snippet:
var geocoder = new google.maps.Geocoder();
var map;
var infoWindow = new google.maps.InfoWindow();
function initialize() {
map = new google.maps.Map(
document.getElementById("map_canvas"), {
center: new google.maps.LatLng(37.4419, -122.1419),
zoom: 13,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
PlaceMarkers(infoWindow, adds, geocoder);
}
google.maps.event.addDomListener(window, "load", initialize);
// Place Markers on the Map
var PlaceMarkers = function(iw, adds, gc) {
var bounds = new google.maps.LatLngBounds();
var image = {
url: "http://meatmysite.com/Images/star2.png",
size: new google.maps.Size(24, 24)
};
var aCt = adds.length;
for (var i = 0; i < aCt; ++i) {
GetLatLng(gc, adds[i], function(pos, add) {
if (pos) {
var ipop = '<h1>' + add.title + '</h1>'; // <----- TypeError: adds[i] is undefined
if (!isBlank(add.url)) {
ipop += '' + add.url + '<br />';
}
ipop += '<div class="map_item_content" id="mi_content' + i + '">' + add.content + '</div>';
if (!isBlank(add.mainphone)) {
ipop += '<br /><strong>Phone:</strong> ' + add.mainphone + '';
}
if (!isBlank(add.mainemail)) {
ipop += '<br /><strong>Email:</strong> ' + add.mainemail + '';
}
console.log('HEY NOW: ' + pos.toString() + ' - Location Found!');
var mark = new google.maps.Marker({
title: add.title,
position: pos,
map: map,
// icon: image,
html: ipop
});
bounds.extend(mark.getPosition());
map.fitBounds(bounds);
google.maps.event.addListener(mark, 'click', function() {
iw.setContent(this.html);
iw.open(map, this);
});
}
});
}
};
// Get Lat/Lng Location
var GetLatLng = function(gc, add, f) {
gc.geocode({
'address': add.address
}, function(res, status) {
if (status == 'OK') {
f(res[0].geometry.location, add);
}
});
};
var adds = [{
"address": "1 My Street Gilbert, AZ 85234",
"title": "My Title 1",
"url": "http://www.myurl.com/",
"mainphone": null,
"mainemail": null,
"content": "1 My Street<br />Gilbert, AZ 85234"
}, {
"address": "2 My Street North Richland Hills, TX 76182",
"title": "My Title 2",
"url": null,
"mainphone": null,
"mainemail": null,
"content": "2 My Street<br />North Richland Hills, TX 76182"
}];
function isBlank(str) {
return (!str || /^\s*$/.test(str));
}
html,
body,
#map_canvas {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js"></script>
<div id="map_canvas"></div>
This looks like a typical binding issue. By the time your callback is called, the value of adds[i] will have changed. It is likely that the loop terminated and i has now a value of last index + 1, which is pointing to nothing. Note that it could also point to the wrong index, that would not fail but use the wrong data.
You must bind the value of adds[i] locally for each iteration or the callback will just use a reference to a global value. There a multiple ways to go about this, here is a simple one where we keep passing adds[i] along as a function argument.
Replace adds[i].address with adds[i] when calling GetLatLng and add a second parameter add to the callback:
GetLatLng(gc, adds[i], function(pos, add) {
...
});
Then modify GetLatLng to use add.address instead of just add and add add to the callback call:
// Get Lat/Lng Location
var GetLatLng = function(gc, add, f) {
var ret = '';
gc.geocode({'address': add.address}, function(res, status) {
if (status == 'OK') {
f(res[0].geometry.location, add);
console.log('Found Here: ' + ret.toString());
}
});
return -1;
};
Then in the callback function, replace all instances of adds[i] with add to use the local variable.
I didn't set up a test but it should theoretically work.
you appear to be overcomplicating things. Any reason why you can't do this?
// Place Markers on the Map
var PlaceMarkers = function (iw, adds, gc) {
var aCt = adds.length;
for(var i = 0; i < aCt; ++i) {
var obj=adds[i];
GetLatLng(gc, obj)
}
};
// Get Lat/Lng Location
var GetLatLng = function(gc, obj) {
var ret = '';
gc.geocode({'address': obj.address}, function(res, status) {
if (status == 'OK') {
var pos=res[0].geometry.location;
var ipop = '<h1>' + obj.title + '</h1>'; // <----- TypeError: adds[i] is undefined
if(!isBlank(obj.url)){
ipop += '' + obj.url + '<br />';
}
ipop += '<div class="map_item_content" id="mi_content">' + obj.content + '</div>';
if(!isBlank(obj.mainphone)){
ipop += '<br /><strong>Phone:</strong> ' + obj.mainphone + '';
}
if(!isBlank(obj.mainemail)){
ipop += '<br /><strong>Email:</strong> ' + obj.mainemail + '';
}
console.log('HEY NOW: ' + pos.toString() + ' - Location Found!');
var mark = new google.maps.Marker({title: obj.title, position: pos, map: map, html: ipop});
google.maps.event.addListener(mark, 'click', function(){
iw.setContent(this.html);
iw.open(map, this);
});
} else {
console.log("geocoder problem!")
}
});
};
for(var i = 0; i < aCt - 1; ++i). You need to add "-1" in you for-loop. The array starts at index 0 and not 1. You also need to be careful with using functions in a for loop. Within javascript a for-loop does not have a scope from itself. Only functions create new scopes.

Why markers do not move correcly on map

Sample of JSON data (from the comments):
[{"id":"280","id_vehicle":"VL0847810531","lat":"30.0761","longi":"1.01981","spee‌​d":"144","time":"2014-12-03 12:07:23"},{"id":"202","id_vehicle":"VL0645210631","lat":"34.7344","longi":"7.32‌​019","speed":"78","time":"2014-12-03 11:55:44"}]
function updateLocations(jsonData)
{
for (i=0 ;i< jsonData.length; i++) //for all vehicles
{
var id_vehicle = jsonData[i]["id_vehicle"];
var lat = jsonData[i]["lat"];
var lng = jsonData[i]["longi"];
var speed = jsonData[i]["speed"];
var str_time = jsonData[i]["time"];
/************************update list*******************************/
var state_icon, marker_icon, state;
var time = moment(str_time);
var last_10_Min = moment().subtract({minutes: 60 + 10});
if(time.isBefore(last_10_Min)) //if before 10 last minutes
{
state_icon = INACTIVE_IMG;
marker_icon = INACTIVE_VEHICLE;
state = "INACTIVE";
}
else //if befor
{
if(jsonData[i]["speed"] > 10) //if > 2 km/h then running
{
state_icon = RUN_IMG;
marker_icon = RUN_VEHICLE;
state = "RUN";
}
else
{
state_icon = STOP_IMG;
marker_icon = STOP_VEHICLE;
state = "STOP";
}
}
$("#state_img_"+id_vehicle).attr("src", state_icon);
$("#state_img_"+id_vehicle).attr('state',state);
$("#select_"+id_vehicle).attr("disabled" , false ); // enable selection
/************************update location info*******************************/
var locationInfo = new Array();
img = "<img src=" + state_icon + " width='16' height='16' >";
locationInfo.push("Etat : " + state + " " + img + "<br>");
locationInfo.push("Latitude : " + lat + "<br>");
locationInfo.push("Longitude : " + lng + "<br>");
locationInfo.push("Vitess: " + speed + " klm/h<br>");
locationInfo.push("Temps : " + str_time + "<br>");
$("#info_location_" +id_vehicle).html(locationInfo.join(""));
/*****************update vehicles on map *************/
try {
cBox = $("#select_"+id_vehicle);
if(cBox.is(':checked')) //update selected only
{
//get marker index
var id_map = cBox.attr("id_map");
//change title
title = "Latitude: "+ lat + "\nLongitude: " + lng + "\nSpeed: " + speed + "\nTime: " + str_time;
arrayMarker[id_map].setTitle(title); //update title
arrayMarker[id_map].setIcon(marker_icon);
//move marker
arrayMarker[id_map].setPosition( new google.maps.LatLng(parseFloat(lat),parseFloat(lng)) );
}
}catch(error){};
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
my question is why whene this function is executed (updating locations) just fisrt vehicle on map is moved correctly, the ohers are updated (title, icon ...) but do not move?
I noticed that , they move and return to their old location quickly.
Thanks for any suggestion.
finaly i found problem, it was here:
var marker = new MarkerWithLabel({......});
arrayMarker[id_map] = marker; //put marker in arrayMarker at indexMarker position
the bug occur whene i filled my arrayMarker using MarkerWithLabel (3th lib)
whene changed to native google.maps.Marker it work correcly:
var marker = new google.maps.Marker({......});
arrayMarker[id_map] = marker;

Javascript function works on postback but not page load

I'm using a Google Maps plugin, and I want it to show up on the page load as well as all postbacks. It seems to only work on postbacks though. Any ideas? I have the body onload tag as "body background="#ccccff" onload="initialize()"", but the function is not defined the first time. Why? Here is the code:
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"> </script>
<script type="text/javascript">
var mostRecentInfo;
function initialize() {
var center = new google.maps.LatLng(0, 0);
var mapOptions = {
center: center,
zoom:1,
mapTypeId: google.maps.MapTypeId.SATELLITE
};
var map = new google.maps.Map(document.getElementById("map"), mapOptions);
var posStr = <%=JSON%>;
if (posStr.toString() != "0") {
var test = posStr.toString().split(',');
var groundstation = <%=groundStation%>;
var dateTimeStr = <%=datetimesStr%>;
var AUStr = <%=auStr%>;
var spaceCraft = <%=spacecraft%>;
var dateTimes = dateTimeStr.toString().split(',');
var auIDs = AUStr.toString().split(',');
var latitude = new Array((test.length / 2));
var longitude = new Array(latitude.length);
var i = 0;
var markerArray = new Array();
for (var j = 0; j < (test.length - 1); j = j + 2) {
latitude[i] = eval(test[j+1]);
longitude[i] = eval(test[j]);
var position = new google.maps.LatLng(latitude[i], longitude[i]);
var marker = new google.maps.Marker({
map:map,
position:position
});
markerArray.push(marker);
i++;
}
var sumLat = 0;
var sumLong = 0;
for (i = 0; i < latitude.length; i++) {
sumLat += latitude[i];
sumLong += longitude[i];
}
var avgLat = sumLat / latitude.length;
var avgLong = sumLong / longitude.length;
center = new google.maps.LatLng(avgLat, avgLong);
map.panTo(center);
var circle;
var contentStr = new Array();
for (i = 0; i < markerArray.length; i++) {
position = markerArray[i].getPosition();
var circOptions = {
strokeColor:"#770000",
strokeOpacity:0.1,
fillColor:"#881111",
fillOpacity:0.4,
map:map,
center:position,
radius:2500000
};
circle = new google.maps.Circle(circOptions);
marker = markerArray[i];
contentStr[i] = '<div id="content">' +
'<b>Spacecraft: </b>' + spaceCraft.toString() + '<br />' +
'<b>Start Time (UTC): </b>' + dateTimes[i].toString() + '<br />' +
'<b>Position: </b>(' + latitude[i].toString() + ', ' + longitude[i].toString() + ')<br />' +
'<b>AU ID: </b>' + auIDs[i] + '<br />' +
'<b>Downlink Station: </b>' + groundstation.toString() + '<br />' +
'</div>';
addListener(map, marker, contentStr[i]);
}
}
}
function addListener(map, marker, content) {
var infowindow = new google.maps.InfoWindow({
content:content
});
google.maps.event.addListener(marker, 'mouseover', function() {
if (mostRecentInfo)
mostRecentInfo.close();
mostRecentInfo = infowindow;
infowindow.open(map, this);
});
}
etc.
It is likely a timing issue with the onload function being called before the initialize function is ready. This is the reason libraries like jQuery have a document.ready function. You can try removing the onload and place a call to initialize() at the bottom of your HTML, just prior to the closing body tag. This will probably work for you.
If you have the option, I'd use a library so you can assure that the function is there and your page is ready. If you haven't tried it, give jQuery a shot.

Javascript insists it's not defined, it totally is

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.
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 < 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 = '<div class="tooltip"><h1>' + locoName + '</h1><h2>' + speed + '<br/>' + location + '</h2></div>';
marker.contextmenu = '<div class="contextmenu">Hello world</div>';
var satellite = "<img src=\"./images/icons/satellite.gif\">";
var gps = "<img src=\"./images/icons/gps.gif\">";
var cmu = "<img src=\"./images/icons/cmu.gif\">";
var ftp = "<img src=\"./images/icons/ftp.gif\">";
var me1k = "<img src=\"./images/icons/me1k.gif\">";
var html = "<div class=\"bubble\">";
html += "<h3>" + locoName + "<span class=\"small-data\"> Route 2150</span></h3>";;
html += "<div class=\"toolbar\">" + gps + satellite + cmu + ftp + me1k + "</div>";
html += "<h4>Heading " + heading + " # " + speed + " MPH</h4>"
html += "<h4>Lat: " + lat + "</h4><h4> Lng: " + lng + "</h4>";
html += "<h4>IP: " + ip + "</h4>";
html += "<h4><div class=\"sm-button\"><a style='color: #FFFFFF; decoration:none;' href='map_detail.php'>Details</a></div><div class=\"sm-button\">Zoom To</div></h4>";
html += "</div>";
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 = '<div class="context"><ul>'
+ '<li class="sectionheading">Zoom Out</li>'
+ '<li class="sectionheading">Boston Area</li>'
+ '<li>South Station, Boston</li>'
+ '<li>South Hampton</li>'
+ '<li>New Haven</li>'
+ '<li class="sectionheading">New York Area</li>'
+ '<li>Sunny Side</li>'
+ '<li>NY, Penn Station</li>'
+ '<li>30th Street, Philadelphia</li>'
+ '<li>Wilmington Shops</li>'
+ '<li>Baltimore, Penn Station</li>'
+ '<li class="sectionheading">DC Area</li>'
+ '<li>DC, Ivy City</li>'
+ '<li>DC, Union Station</li>'
+ '</ul</div>';
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 > map.getSize().width - 120) { x = map.getSize().width - 120 }
if (y > 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");
}
}
It appears that zoomTo is an annonymous function inside of the top-level function load() - therefore, it's not available to top-level calls.
Instead of
// === 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";
}
put the function in the top level, and pass in the map and contextmenu variables:
// === 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";
}
As it dont looks well in comment. posting the comment above here again
<html>
<head>
<script type="text/javascript">
function zoomTo(x,y,z) {
....
}
</script>
.....
</head>
......
</html>

Categories

Resources