I have managed to create a simple map with a marked route between 2 destinations. Additionally, I need to pull the distance value and then do some basic math with it (multiply it by 2). It all works, but not on page load. More precise, map is displayed on page load as well as distance, but distance value doesn't get pulled and it doesn't get multiplied by 2. I have managed to make it work on mouse move, but it's not the perfect replacement.
Here is the code:
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<title>Directions</title>
<link href="/maps/documentation/javascript/examples/default.css" rel="stylesheet">
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false®ion=US"></script>
<script src="http://code.jquery.com/jquery-1.7.1.js" type="text/javascript"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/jquery-ui.min.js"></script>
<script src="http://www.pengoworks.com/workshop/jquery/calculation/jquery.calculation.min.js" type="text/javascript"></script>
<script>
$(document).ready(function() {
var rendererOptions = {
draggable: false
};
var directionsDisplay = new google.maps.DirectionsRenderer(rendererOptions);;
var directionsService = new google.maps.DirectionsService();
var map;
function initialize() {
var mapOptions = {
zoom: 7,
mapTypeId: google.maps.MapTypeId.ROADMAP,
};
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
directionsDisplay.setMap(map);
directionsDisplay.setPanel(document.getElementById('directionsPanel'));
google.maps.event.addListener(directionsDisplay, 'directions_changed', function() {
computeTotalDistance(directionsDisplay.directions);
});
calcRoute();
}
function calcRoute() {
var request = {
origin: 'Houston',
destination: 'Dallas',
travelMode: google.maps.DirectionsTravelMode.DRIVING
};
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
}
});
}
function computeTotalDistance(result) {
var total = 0;
var myroute = result.routes[0];
for (var i = 0; i < myroute.legs.length; i++) {
total += myroute.legs[i].distance.value;
}
total = total / 1000.
document.getElementById('total').innerHTML = total + ' km';
}
google.maps.event.addDomListener(window, 'load', initialize);
function stripint() {
var val = $('[jsdisplay=distance]').text(); // get text content of <span jstcache="7">
// Replace using regex instead of strings, to catch more than the first match
val = val.replace(/\./g, "");
val = val.replace(/,/g, ".");
val = val.replace(/_/g, ",");
$('#dist').val(val);
}
function recalc() {
$("[id^='total_price_ht']").calc(
// the equation to use for the calculation
"di * 10", {
bind: "keyup",
di: $("[id^='dist']")
}, function(s) {
// return the number as a dollar amount
return "$" + s.toFixed(2);
});
}
$('#content').mousemove(function() {
stripint();
recalc();
});
stripint();
recalc();
});
</script>
</head>
<body>
<div id="content">
<p>Distance: <span id="total"></span>
</p>
<input type="text" value="0" name="dist" id="dist" />
<div id="total_price_ht_0" class="price">$0.00</div>
<div id="map-canvas" style="width:100%; height:500px"></div>
<div id="directionsPanel" style="width:100%; height:auto"></div>
</div>
</body>
first of all you don't need to use $(document).ready() because you already bind the initialize function to the window onLoad event google.maps.event.addDomListener(window, 'load', initialize);
what you want is wait until the directions and distance are calculated, you don't really need to read it from the directionsPanel, you can read whatever you need directly from the API response.
use the callback in calcRoute like this:
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
dist = response.routes[0].legs[0].distance.text;
stripint(dist);
recalc();
}
});
you also need to add the dist argument to you strprint:
function stripint(val) {
// Replace using regex instead of strings, to catch more than the first match
val = val.replace(/\./g, "");
val = val.replace(/,/g, ".");
val = val.replace(/_/g, ",");
$('#dist').val(val);
}
so your new code doesn't use document.ready and calculates the price immediately when the API responds.
the new <script> tag:
var rendererOptions = {
draggable: false
};
var directionsDisplay = new google.maps.DirectionsRenderer(rendererOptions);
var directionsService = new google.maps.DirectionsService();
var map;
function initialize() {
var mapOptions = {
zoom: 7,
mapTypeId: google.maps.MapTypeId.ROADMAP,
};
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
directionsDisplay.setMap(map);
directionsDisplay.setPanel(document.getElementById('directionsPanel'));
google.maps.event.addListener(directionsDisplay, 'directions_changed', function () {
computeTotalDistance(directionsDisplay.directions);
});
calcRoute();
}
function calcRoute() {
var request = {
origin: 'Houston',
destination: 'Dallas',
travelMode: google.maps.DirectionsTravelMode.DRIVING
};
directionsService.route(request, function (response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
dist = response.routes[0].legs[0].distance.text;
stripint(dist);
recalc();
}
});
}
function computeTotalDistance(result) {
var total = 0;
var myroute = result.routes[0];
for (var i = 0; i < myroute.legs.length; i++) {
total += myroute.legs[i].distance.value;
}
total = total / 1000.
document.getElementById('total').innerHTML = total + ' km';
}
google.maps.event.addDomListener(window, 'load', initialize);
function stripint(val) {
// Replace using regex instead of strings, to catch more than the first match
val = val.replace(/\./g, "");
val = val.replace(/,/g, ".");
val = val.replace(/_/g, ",");
$('#dist').val(val);
}
function recalc() {
$("[id^='total_price_ht']").calc(
// the equation to use for the calculation
"di * 10", {
bind: "keyup",
di: $("[id^='dist']")
}, function (s) {
// return the number as a dollar amount
return "$" + s.toFixed(2);
});
}
here is no need to have two tags; you can put everything inside one. Some of your functions use jQuery selectors, try to put all of them inside the $(document).ready(), this will guarantee that all the selected elements are available by the time they are called:
$(document).ready(function(){
//Insert your functions with selectors here
});
Here is the rearranged code with everything inside document.ready: http://jsbin.com/iqejiy/1/edit
Hope it helps.
i think you are missing document.ready() here.
Related
I am trying to make a google map API that has moveable points but also includes a search option to search address. I have gotten the draggable points but get a Uncaught ReferenceError: SearchAddress is not defined at HTMLInputElement.onclick when I try and run this code. I cannot figure out how to get this to work. I have tried removing the SearchAddress function out of the other InitMap function but still Help would be greatly appreciated.
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<title>Draggable directions</title>
<link rel="stylesheet" type="text/css" href="stylesheet1.css">
<script type="text/javascript">
var x = document.createElement("INPUT");
x.setAttribute("type", "text");
var moveloc1 = {lat: 55, lng: -7.3};
var moveloc2 = {lat: 55, lng: -7.1};
function initMap()
{
console.log("error checker1");
var geocoder = new google.maps.Geocoder();
var map = new google.maps.Map(document.getElementById('map'),
{
zoom: 14,
center: {lat: 55, lng: -7.3} // Australia.
});
var directionsService = new google.maps.DirectionsService;
var directionsDisplay = new google.maps.DirectionsRenderer
({
draggable: true,
map: map,
panel: document.getElementById('right-panel')
});
directionsDisplay.addListener('directions_changed', function()
{
computeTotalDistance(directionsDisplay.getDirections());
});
displayRoute(moveloc1, moveloc2 , directionsService,
directionsDisplay);
console.log("error checker2");
function SearchAddress()
{
console.log("error checker3");
var locate1 = document.getElementById("pass1").value;
var locate2 = document.getElementById("pass2").value;
console.log(locate1);
console.log(locate2);
geocoder.geocode( { 'pass1': address}, function(results, status)
{
if (status == 'OK')
{
map.setCenter(results[0].geometry.location);
moveloc1 =
({
position: results[0].geometry.location
});
}
else
{
alert('Geocode was not successful for the following reason: ' +
status);
}
});
}
}
function displayRoute(origin, destination, service, display)
{
service.route
({
origin: origin,
destination: destination,
travelMode: 'DRIVING',
avoidTolls: true
},
function(response, status)
{
if (status === 'OK')
{
display.setDirections(response);
}
else
{
alert('Could not display directions due to: ' + status);
}
});
}
function computeTotalDistance(result)
{
var total = 0;
var myroute = result.routes[0];
for (var i = 0; i < myroute.legs.length; i++)
{
total += myroute.legs[i].distance.value;
}
total = total / 1000;
document.getElementById('total').innerHTML = total + ' km';
}
</script>
</head>
<body>
<div id="map"></div>
<div id="right-panel">
<form>
Start<input class="textBox" id="pass1" type="text" maxlength="30" /> <br>
End<input class="textBox" id="pass2" type="text" maxlength="30" />
<input type = "button" id="button" name="button" value="search" onclick =
"SearchAddress()"/>
</form>
<p>Total Distance: <span id="total"></span></p>
</div>
<script async defer
src="https://maps.googleapis.com/maps/api/js?
key=AIzaSyBtQt_1BqPPuSdIbXTuYW9I8yNUGIItPuk&callback=initMap">
</script>
</body>
</html>`
<script type="text/javascript">
var x = document.createElement("INPUT");
x.setAttribute("type", "text");
var geocoder;
var moveloc1 = {lat: 55, lng: -7.3};
var moveloc2 = {lat: 55, lng: -7.1};
function SearchAddress()
{
console.log("error checker3");
var locate1 = document.getElementById("pass1").value;
var locate2 = document.getElementById("pass2").value;
console.log(locate1);
console.log(locate2);
// adress must be defined
geocoder.geocode( { 'pass1': adress}, function(results, status)
{
if (status == 'OK')
{
map.setCenter(results[0].geometry.location);
moveloc1 =
({
position: results[0].geometry.location
});
}
else
{
alert('Geocode was not successful for the following reason: ' +
status);
}
});
}
function initMap()
{
console.log("error checker1");
geocoder = new google.maps.Geocoder();
var map = new google.maps.Map(document.getElementById('map'),
{
zoom: 14,
center: {lat: 55, lng: -7.3} // Australia.
});
var directionsService = new google.maps.DirectionsService;
var directionsDisplay = new google.maps.DirectionsRenderer
({
draggable: true,
map: map,
panel: document.getElementById('right-panel')
});
directionsDisplay.addListener('directions_changed', function()
{
computeTotalDistance(directionsDisplay.getDirections());
});
displayRoute(moveloc1, moveloc2 , directionsService,
directionsDisplay);
console.log("error checker2");
}
function displayRoute(origin, destination, service, display)
{
service.route
({
origin: origin,
destination: destination,
travelMode: 'DRIVING',
avoidTolls: true
},
function(response, status)
{
if (status === 'OK')
{
display.setDirections(response);
}
else
{
alert('Could not display directions due to: ' + status);
}
});
}
function computeTotalDistance(result)
{
var total = 0;
var myroute = result.routes[0];
for (var i = 0; i < myroute.legs.length; i++)
{
total += myroute.legs[i].distance.value;
}
total = total / 1000;
document.getElementById('total').innerHTML = total + ' km';
}
</script>
Problem:
Your problem is that you declared SearchAddress function inside of initMap function and you tried to access it from global scope (in the HTML element), which is impossible.
Explanation:
In fact a local functions and local variables can't be accessed from the global scope or from other functions. Note that in HTML elements events you can only access functions declared in the global windowscope.
You need to declare it in the global scope so you can access it from all functions and from HTML elements.
Note:
You need to fix that problem with all your functions declarations in your code.
So I am trying to make a simple application that will allow the user to search for restaurants and have the results show as markers on the map and as text below. The results object that returns from the textSearch doesn't provide detailed information like: phone number, pictures, etc. So i decided to create an array of place id's pushed from the results object, get the place details for each id, then push that into an array. The problem I get is a message from google saying I'm over my quota and I think it's because I'm requesting the place details for every single search result.
Is there a way I can request the place details only for the marker I click? Or is there a better solution to my problem? Thank you in advance for your help.
<!DOCTYPE html>
<html>
<head>
<title>gMap test</title>
<style type="text/css">
#map-canvas{
height:500px;
}
</style>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?libraries=places&sensor=false"></script>
<script type="text/javascript">
function performSearch(){
var locationBox;
var address = document.getElementById("address").value;
var searchRadius = metricConversion(document.getElementById("radius").value);
//gMaps method to find coordinates based on address
geocoder.geocode({'address':address}, function(results,status){
if(status == google.maps.GeocoderStatus.OK){
map.setCenter(results[0].geometry.location);
var marker = new google.maps.Marker({
map:map,
position: results[0].geometry.location
});
var latitude = results[0].geometry.location.A;
var longitude = results[0].geometry.location.F;
locationBox = new google.maps.LatLng(latitude, longitude);
}else{
errorStatus(status);
return;
}
//search request object
var request = {
query: document.getElementById('keyword').value,
location: locationBox,
radius: searchRadius,
//minPriceLvl: minimumPrice,
//maxPriceLvl: maximumPrice,
types: ["restaurant"]
}
//search method. sending request object and callback function
service.textSearch(request, handleSearchResults);
});
};
var latLngArray = [];
var placeIdArray = [];
//callback function
function handleSearchResults(results,status){
if( status == google.maps.places.PlacesServiceStatus.OK) {
for (var i = 0; i < results.length; i++) {
placeIdArray.push(results[i].place_id)
latLngArray.push(results[i].geometry.location);
};
for(var j = 0; j<placeIdArray.length; j++){
service.getDetails({placeId: placeIdArray[j]},getDetails)
};
}
else{errorStatus(status)};
};
var detailedArray = [];
function getDetails(results,status){
if (status == google.maps.places.PlacesServiceStatus.OK) {
detailedArray.push(results);
for(var i = 0; i<detailedArray.length; i++){
createMarker(detailedArray[i],i);
}
}
else{
errorStatus(status)
};
}
//array of all marker objects
var allMarkers = [];
//creates markers and info windows for search results
function createMarker(place, i) {
var image = 'images/number_icons/number_'+(i+1)+'.png';
var marker = new google.maps.Marker({
map: map,
position: place.geometry.location,
html:
"<div class = 'markerPop'>" + "<h3>" + (i+1) + ". " + place.name + "</h3><br>" + "<p>Address: "
+ place.formatted_address + "</p><br>" + "<p> Price Range: "+ priceLevel(place.price_level)
+ "</p>" + "</div>",
icon: image
});
allMarkers.push(marker);
marker.infowindow = new google.maps.InfoWindow();
//on marker click event do function
google.maps.event.addListener(marker, 'click', function() {
//service.getDetails({placeId: placeIdArray[j]},getDetails)
//sets infowindow content and opens infowindow
infowindow.setContent(this.html);
infowindow.open(map,this);
});
//create new bounds object
var bounds = new google.maps.LatLngBounds();
//iterates through all coordinates to extend bounds
for(var i = 0;i<latLngArray.length;i++){
bounds.extend(latLngArray[i]);
};
//recenters map around bounds
map.fitBounds(bounds);
};
var map;
var service;
var geocoder;
var infowindow;
function initialize(location){
var mapOptions = {
center: new google.maps.LatLng(37.804, -122.271),
zoom: 8,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
geocoder = new google.maps.Geocoder();
map = new google.maps.Map(document.getElementById("map-canvas"),mapOptions);
service = new google.maps.places.PlacesService(map)
infowindow = new google.maps.InfoWindow();
};
$(document).ready(function(){
initialize();
$('#search').on('click', function(){
removeMarkers();
performSearch();
});
});
//::::::Random Functions:::::::
//Clears all markers between searches
function removeMarkers(){
for(var i = 0; i<allMarkers.length;i++){
allMarkers[i].setMap(null);
};
};
//converts miles to meters for search object
function metricConversion(miles){
var meters;
meters = miles * 1609.34;
return meters;
}
//converts number value to $ sign
function priceLevel(number){
var moneySigns = ""
for(var i =0;i<=number;i++){
moneySigns += "$";
};
return moneySigns;
}
//errors for search results
function errorStatus(status){
switch(status){
case "ERROR": alert("There was a problem contacting Google Servers");
break;
case "INVALID_REQUEST": alert("This request was not valid");
break;
case "OVER_QUERY_LIMIT": alert("This webpage has gone over its request quota");
break;
case "NOT_FOUND": alert("This location could not be found in the database");
break;
case "REQUEST_DENIED": alert("The webpage is not allowed to use the PlacesService");
break;
case "UNKNOWN_ERROR": alert("The request could not be processed due to a server error. The request may succeed if you try again");
break;
case "ZERO_RESULTS": alert("No result was found for this request. Please try again");
break;
default: alert("There was an issue with your request. Please try again.")
};
};
</script>
</head>
<body>
<div id="map-canvas"></div>
<div id="searchBar">
<h3>search options</h3>
Location:<input type="text" id="address" value="enter address here" /><br>
Keyword<input type="text" id="keyword" value="name or keyword" /><br>
Advanced Filters:<br>
Search Radius:<select id="radius">
<option>5</option>
<option>10 </option>
<option>15 </option>
<option>20 </option>
<option>25 </option>
</select>miles<br>
<div id="minMaxPrice">
Min Price<select id="minPrice">
<option>$</option>
<option>$$</option>
<option>$$$</option>
<option>$$$$</option>
</select>
Max Price<select id="maxPrice">
<option>$</option>
<option>$$</option>
<option>$$$</option>
<option>$$$$</option>
</select>
</div>
<input type="button" id="search" value="Submit Search"/><br>
</div>
<div id='searchResults'>
</div>
</body>
</html>
The radarSearch example in the documentation requests the details of the marker on click.
code snippet:
var map;
var infoWindow;
var service;
function initialize() {
map = new google.maps.Map(document.getElementById('map-canvas'), {
center: new google.maps.LatLng(-33.8668283734, 151.2064891821),
zoom: 15,
styles: [{
stylers: [{
visibility: 'simplified'
}]
}, {
elementType: 'labels',
stylers: [{
visibility: 'off'
}]
}]
});
infoWindow = new google.maps.InfoWindow();
service = new google.maps.places.PlacesService(map);
google.maps.event.addListenerOnce(map, 'bounds_changed', performSearch);
}
function performSearch() {
var request = {
bounds: map.getBounds(),
keyword: 'best view'
};
service.radarSearch(request, callback);
}
function callback(results, status) {
if (status != google.maps.places.PlacesServiceStatus.OK) {
alert(status);
return;
}
for (var i = 0, result; result = results[i]; i++) {
createMarker(result);
}
}
function createMarker(place) {
var marker = new google.maps.Marker({
map: map,
position: place.geometry.location,
icon: {
// Star
path: 'M 0,-24 6,-7 24,-7 10,4 15,21 0,11 -15,21 -10,4 -24,-7 -6,-7 z',
fillColor: '#ffff00',
fillOpacity: 1,
scale: 1 / 4,
strokeColor: '#bd8d2c',
strokeWeight: 1
}
});
google.maps.event.addListener(marker, 'click', function() {
service.getDetails(place, function(result, status) {
if (status != google.maps.places.PlacesServiceStatus.OK) {
alert(status);
return;
}
var htmlStr = "<b>"+result.name+"</b><br>";
if (result.website) htmlStr += "<a href='"+result.website+"'>"+result.website+"</a><br>";
if (result.adr_address) htmlStr += result.adr_address+"<br>";
infoWindow.setContent(htmlStr);
infoWindow.open(map, marker);
});
});
}
google.maps.event.addDomListener(window, 'load', initialize);
html,
body,
#map-canvas {
height: 100%;
margin: 0px;
padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&signed_in=true&libraries=places"></script>
<div id="map-canvas"></div>
I had the same issue some time ago. The geocoding function by google is done in order to avoid the user executing it on a large set of data (and then, avoid you to get a large amount of geocoded address easily).
My solution was to execute the geocoding function only when the user choose a particular place, and then, display this particular data (handled by the click on the pin).
I think it would be very useful to initiate a jsfiddle with a working version of your code.
Basically on your function :
google.maps.event.addListener(marker, 'click', function() {
//Execute geocoding function here on marker object
//Complete your html template content
infowindow.setContent(this.html);
infowindow.open(map,this);
});
I have a project whereby a route is generated by the google maps directions service, and I have a loop to obtain all coordinates along it (using a functioned called showPathInfo - see base of query for full HTML):
var tp = result.routes[0].legs[i].steps[j].path[k]; // local variable
var z = new google.maps.LatLng(tp.lat(),tp.lng()); // local variable
I wish to make a call to the elevation service during each loop iteration using:
elevation = getElevation(z); // global variable but NOT an array
where getElevation is a function (see base of query for full HTML).
For some reason, even though the coords are correctly passed to the function, and are rendered appropriately into a getElevationForLocations object (I have checked this by having the getElevation return variables before the getElevationForLocations call); the service returns "undefined" for
return results[0].elevation;
I am interested in getting this solution to work to take advantage of the higher accuracy afforded to individual elevation service requests, and am trying to avoid batch requests with locations[] as a full array or using the getElevationForPath function.
Admittedly there is the problem of a limit to the number of single elevation requests that can be made per second and in total, but I have tried slowing down the code execution and limiting the distances in order to get this to work at least once:
function wait() { setTimeout(function () {
elevation = getElevation(z); // here defined as a global variable
}, 500);}
wait();
Does anyone have any ideas why such a nested call like this cannot work?
The full fiddle html code is as follows:
<!DOCTYPE html>
<html><head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<style>html, body, #map-canvas {height: 100%;margin: 0px;padding: 0px}</style>
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&signed_in=true"></script>
<script>
var rendererOptions = { draggable: true };
var directionsDisplay = new google.maps.DirectionsRenderer(rendererOptions);;
var directionsService = new google.maps.DirectionsService();
var infowindow = new google.maps.InfoWindow();
var map;
var elevation; // *******************
var elevator;
var start = new google.maps.LatLng(55.60289406109326, -2.88885779678822);
var wpnt1 = new google.maps.LatLng(55.59226543103951, -2.91247397661209);
var wpnt2 = new google.maps.LatLng(55.57330299699533, -2.88813963532448);
var wpnt3 = new google.maps.LatLng(55.58132161006218, -2.84357875585556);
var wpnt4 = new google.maps.LatLng(55.58602383263128, -2.87256672978401);
var wpnt5 = new google.maps.LatLng(55.60450928199337, -2.89154000580311);
var ended = new google.maps.LatLng(55.60289406109326, -2.88885779678822);
function initialize() {
elevator = new google.maps.ElevationService();
var mapOptions = { zoom: 10,center: start };
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
directionsDisplay.setMap(map);
directionsDisplay.setPanel(document.getElementById('directionsPanel'));
google.maps.event.addListener(directionsDisplay, 'directions_changed', function() {
document.getElementById('points').innerHTML = "";
showPathInfo(directionsDisplay.getDirections());
});
calcRoute();
} // ***** End of initialise function
function calcRoute() {
var request = {origin: start,destination: ended,
waypoints:[{location: wpnt1}, {location: wpnt2}, {location: wpnt3}, {location: wpnt4}, {location: wpnt5}],
travelMode: google.maps.TravelMode.WALKING
};
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
}
});
}
function showPathInfo(result) {
var total = 0;
var ns = 0;
var pt = 0;
var myroute = result.routes[0];
document.getElementById('points').insertAdjacentHTML('beforeend', '<th>Point</th><th>Lat</th><th>Lon</th><th>Elevation</th>');
for (var i = 0; i < myroute.legs.length; i++) {
total += myroute.legs[i].distance.value;
ns += myroute.legs[i].steps.length;
for (var j = 0; j < myroute.legs[i].steps.length; j++) {
for (var k = 0; k < myroute.legs[i].steps[j].path.length; k++) {
var tp = myroute.legs[i].steps[j].path[k];
var z = new google.maps.LatLng(tp.lat(),tp.lng());
//function wait() { setTimeout(function () {
elevation = getElevation(z);
//}, 500);} // End of getAndWait
//wait();
document.getElementById('points').insertAdjacentHTML('beforeend',
'<tr><td>' + pt + '</td><td>' +
tp.lat().toFixed(7) + '</td><td>' +
tp.lng().toFixed(7) + '</td><td>' +
elevation + '</td></tr>');
pt += 1;
}
}
}
total = total / 1000.0;
document.getElementById('total').innerHTML = total + ' km';
document.getElementById('legs').innerHTML = myroute.legs.length;
document.getElementById('steps').innerHTML = ns;
}
function getElevation(z) {
var locations = [];
var clickedLocation = z;
locations.push(clickedLocation);
var positionalRequest = { 'locations': locations }
elevator.getElevationForLocations(positionalRequest, function(results, status) {
if (status == google.maps.ElevationStatus.OK) {
// Retrieve the first result
if (results[0]) {
return results[0].elevation;
} else {
return 'No results found';
}
} else {
return 'Elevation service failed due to: ' + status;
}
});
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div id="map-canvas" style="float:left;width:70%; height:100%"></div>
<div id="directionsPanel" style="float:right;width:30%;height 25%">
<p>Total Distance: <span id="total"></span> Legs: <span id="legs"></span>Steps: <span id="steps"></span></p>
<table id="points"></table>
</div>
</body>
</html>
Postscript
In the end it was the use of a Bluebird promise loop that worked.
<script src="https://cdn.jsdelivr.net/bluebird/latest/bluebird.js"></script>
For the record I was not using node.js or any other functionality other than just plain js plus bluebird. Promises are dealt with in detail by many answers in StackOverflow so I recommend reading these and looking through the API: https://github.com/petkaantonov/bluebird/blob/master/API.md .
I need to pass two addresses to the following code to show the direction between them based on chosen transportation mode. Once user selects two cities from the Dropdown box in page 1, I am going to send them to the code (page 2) to show their locations and direction between them.
I have copied this sample code from Google.I am now trying to combine it with my code but do not know how.
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<title>Travel modes in directions</title>
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script>
<style type="text/css">
html, body {
height: 50%;
margin: 0;
padding: 0;
}
#map-canvas {
height: 200%;
width:25%;
}
#media print {
html, body {
height: auto;
}
#map-canvas {
height: 650px;
}
}
</style>
<script>
function GetLocation(add) {
var geocoder = new google.maps.Geocoder();
var address = add;
geocoder.geocode({ 'address': address }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var latitude = results[0].geometry.location.lat();
var longitude = results[0].geometry.location.lng();
var output = latitude + "," + longitude;
return output;
} else {
alert("Request failed.")
}
});
};
var directionsDisplay;
var directionsService = new google.maps.DirectionsService();
var map;
var haight = new google.maps.LatLng(-37.81411, 144.96327999999999);
var oceanBeach = new google.maps.LatLng(-37.814107, 144.96327999999994);
function initialize() {
directionsDisplay = new google.maps.DirectionsRenderer();
var mapOptions = {
zoom: 14,
mapTypeId: google.maps.MapTypeId.ROADMAP,
center: haight
}
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
directionsDisplay.setMap(map);
}
function calcRoute() {
var selectedMode = document.getElementById('mode').value;
var request = {
origin: haight,
destination: oceanBeach,
// Note that Javascript allows us to access the constant
// using square brackets and a string value as its
// "property."
travelMode: google.maps.TravelMode[selectedMode]
};
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
}
});
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div id="panel">
<b>Mode of Travel: </b>
<select id="mode" onchange="calcRoute();">
<option value="DRIVING">Driving</option>
<option value="WALKING">Walking</option>
<option value="BICYCLING">Bicycling</option>
<option value="TRANSIT">Transit</option>
</select>
<script>GetLocation("Los Angeles, USA");</script>
<script>GetLocation("Las Vegas, USA");</script>
</div>
<div id="map-canvas"></div>
</body>
</html>
You are essentially asking about SearchBox . You don't need it though. You can directly take a form and get the submitted values and Geocode it to be passed in the aforementioned script.
If you want to pass the two addresses to the 2nd page in the query string, you can do something like this:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<title>Travel modes in directions</title>
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script>
<style type="text/css">
html, body {
margin: 0;
padding: 0;
}
#map-canvas {
height: 500px;
width:600px;
}
</style>
<script>
var directionsDisplay;
var directionsService = new google.maps.DirectionsService();
var map;
var origin = "Los Angeles, USA";
var destination = "Las Vegas, USA";
var maptype = google.maps.MapTypeId.ROADMAP;
var travelMode = google.maps.TravelMode.DRIVING;
var arrivalTime = null;
var departureTime = null;
function initialize() {
// If there are any parameters at eh end of the URL, they will be in location.search
// looking something like "?marker=3"
// skip the first character, we are not interested in the "?"
var query = location.search.substring(1);
// split the rest at each "&" character to give a list of "argname=value" pairs
var pairs = query.split("&");
for (var i=0; i<pairs.length; i++) {
// break each pair at the first "=" to obtain the argname and value
var pos = pairs[i].indexOf("=");
var argname = pairs[i].substring(0,pos).toLowerCase();
var value = pairs[i].substring(pos+1).toLowerCase();
// process each possible argname - use unescape() if theres any chance of spaces
if (argname == "origin") {origin = unescape(value);}
if (argname == "dest") {destination = unescape(value);}
if (argname == "type") {
if (value == "m") {maptype = google.maps.MapTypeId.ROADMAP;}
if (value == "k") {maptype = google.maps.MapTypeId.SATELLITE;}
if (value == "h") {maptype = google.maps.MapTypeId.HYBRID;}
if (value == "t") {maptype = google.maps.MapTypeId.TERRAIN;}
}
if (argname == "mode") {
if (value == "driving") {travelMode = google.maps.TravelMode.DRIVING; }
if (value == "walking") {travelMode = google.maps.TravelMode.WALKING; }
if (value == "transit") {travelMode = google.maps.TravelMode.TRANSIT; }
if (value == "bicycling") {travelMode = google.maps.TravelMode.BICYCLING; }
}
if (argname == "arrive") {
arrivalTime = new Date(value);
}
if (argname == "depart") {
departureTime = new Date(value);
}
}
directionsDisplay = new google.maps.DirectionsRenderer();
var mapOptions = {
zoom: 14,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
directionsDisplay.setMap(map);
directionsDisplay.setPanel(document.getElementById('panel'));
calcRoute(origin, destination, travelMode, departureTime, arrivalTime);
}
function calcRoute(origin, destination, mode, departureTime, arrivalTime) {
var request = {
origin: origin,
destination: destination,
travelMode: mode,
};
if (travelMode == google.maps.TravelMode.TRANSIT)
request.transitOptions = {};
if (travelMode == google.maps.TravelMode.TRANSIT && !!departureTime)
request.transitOptions.departureTime = departureTime;
if (travelMode == google.maps.TravelMode.TRANSIT && !!arrivalTime)
request.transitOptions.departureTime = departureTime;
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
} else alert("Directions Request failed: "+status);
});
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div id="map-canvas"></div>
<div id="panel"></div>
<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-162157-1";
urchinTracker();
</script>
</body>
</html>
working example
and working example with form input
I am currently working on a project about taxis. I want to display some taxis on Google Map but encountered the following problem. When the program turns into function print_taxi(), all data in taxilatlng[] will disappear! It seems that all of the data can only be kept inside directionsservice.route(){}. Need help.
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script>
onerror=handleErr
var txt=""
function handleErr(msg,url,l)
{
txt="There was an error on this page.\n\n"
txt+="Error: " + msg + "\n"
txt+="URL: " + url + "\n"
txt+="Line: " + l + "\n\n"
txt+="Click OK to continue.\n\n"
alert(txt)
return true
}
var centerlat=22.551622;
var centerlng=114.121178;
var taxi_num=10;
var taxiradius=0.005;
var taxilatlng = new Array();
var taximarker = new Array();
var taxilat = new Array();
var taxilng = new Array();
var map;
var RANDOM_DATA_INITIALIZED;
function get_random(lowerbound, upperbound){
return lowerbound+Math.floor((upperbound-lowerbound)*Math.random());
}
function get_random_loc(now, radius){
return now+radius-Math.random()*2*radius;
}
function get_random_latlng(taxiradius){
var tmp=new google.maps.LatLng(get_random_loc(centerlat,taxiradius), get_random_loc(centerlng,taxiradius));
return tmp;
}
function dump_obj(myObject) {
var s = "";
for (var property in myObject) {
s = s + "\n "+property +": " + myObject[property] ;
}
alert(s);
}
function init_map()
{
var latlng=new google.maps.LatLng(centerlat, centerlng);
var options={
zoom:16,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map=new google.maps.Map(document.getElementById("map_canvas"), options);
}
function print_taxi(){
image="taxi.gif";
for(var i=1;i<=taxi_num; ++i){
taximarker[i]=new google.maps.Marker({
position: taxilatlng[i],
icon: image,
map: map
});
}
}
function get_taxi_pos()
{
var cnt_generatedcar=0;
for(var i=1;i<=taxi_num; i++)
{
var from=get_random_latlng(taxiradius);
var to=get_random_latlng(taxiradius);
var directionsservice=new google.maps.DirectionsService();
var taxirenderer=new google.maps.DirectionsRenderer();
var DirReq={
origin: from,
destination: to,
travelMode: google.maps.DirectionsTravelMode.DRIVING
};
directionsservice.route(DirReq, function(response, status){
if(status==google.maps.DirectionsStatus.OK)
{
var all_routes = response.routes;
for(curroute in all_routes)
{
++cnt_generatedcar;
var all_paths = all_routes[curroute].overview_path;
var cnt_paths = all_paths.length;
var id_path=get_random(0, cnt_paths-1);
taxilatlng[i] = all_paths[id_path];
if(cnt_generatedcar==taxi_num){
print_taxi();
}
}
}
});
}
}
function init(){
init_map();
get_taxi_pos();
}
</script>
</head>
<body onload="init();">
<div id="map_canvas" style="float:left; width:70%; height:100%"></div>
<div id="msg"></div>
</body>
</html>
directionsservice.route is a callback method and is called only after i >taxi_num. As a result the value in taxilatlng is getting set only once at index (taxi_num+1). You can modify the code to something like :
var ctr = -1; // added
directionsservice.route(DirReq, function(response, status){if(status==google.maps.DirectionsStatus.OK)
{
var all_routes = response.routes;
ctr++;
for(curroute in all_routes)
{
++cnt_generatedcar;
var all_paths = all_routes[curroute].overview_path;
var cnt_paths = all_paths.length;
var id_path=get_random(0, cnt_paths-1);
taxilatlng[ctr] = all_paths[id_path];
if(cnt_generatedcar==taxi_num){
print_taxi();
}
}
}
});
I've just used a new variable as a counter instead of i.