I am using the google.maps.places.Autocomplete API and this morning I was getting a 502 Bad Gateway error. It lasted about 10 minutes and started working again. I assume this had to do with the service being unavailable.
I was wondering how I can error handle when this happens. My (javascript) autocomplete code looks like this:
$('#StartAddress').change(function () {
google.maps.event.trigger(startAutocomplete, 'place_changed');
return false;
});
var source, destination;
var directionsDisplay;
var directionsService;
if (typeof google === 'object' && typeof google.maps === 'object') {
directionsService = new google.maps.DirectionsService();
// set up places autocomplete
var start = document.getElementById('StartAddress');
var startAutocomplete = new google.maps.places.Autocomplete(start);
var end = document.getElementById('EndAddress');
var endAutocomplete = new google.maps.places.Autocomplete(end);
// add the places auto complete listener for when the values change
startAutocomplete.addListener('place_changed', function () {
var startAddress = $('#StartAddress').val();
var endAddress = $('#EndAddress').val();
if (endAddress && startAddress) {
GetRoute(startAddress, endAddress, false);
}
});
endAutocomplete.addListener('place_changed', function () {
var endAddress = $('#EndAddress').val();
var startAddress = $('#StartAddress').val();
if (endAddress && startAddress) {
GetRoute(startAddress, endAddress, false);
}
});
directionsDisplay = new google.maps.DirectionsRenderer({ 'draggable': false });
}
The GetRoute(startAddress, endAddress, false) function is a call to the google.maps.Map and that works fine. It was only the autocomplete service that was down.
Also, is it possible this error occurred because I am using the developer key instead of production? Like the googles dev environment is much more resource limited?
The service was down this time. Try again now.
Related
I'm working on a multi-tenant apps. Each app will have a video module which takes several youtube playlists/channels id as input.
Apps = {_id: "app01", playlists:['PL4IrNZLvgtED4RTH3xCf9085hwqKmb4lM','PLlYqpJ9JE-J8QIlua0KsBIxp-VQLyM_nO']}
Apps = {_id: "app02", playlists:['id22','id23']}
and so on.
When user redirect to address localhost:3000/app/:_id, the app subscribe to Meteor.subscribe('apps',_id).
Now on the client side, i need to render a page that shows a list of playlists (or list of channels) with playlist's name, playlist thumbnail; and then if user clicks on the name/thumbnail, it displays another page with a list of videos belongs to that playlist/channel.
What i am doing is to have a helper to retrieve all youtube playlists's info:
Template.Videos.helpers({
myPlaylist:function(){
return Apps.findOne({}, {
transform: function (doc){
playlists = doc.playlists;
doc.date = new Date(); //for testing
doc.videos = [];
for (var i=0;i<playlists.length;i++){
console.log('find playlist: ',playlists[i]);
var url = 'https://gdata.youtube.com/feeds/api/playlists/'+playlists[i]+'?v=2&alt=json';
$.getJSON(url, function(response){
var video={};
video._id = response.feed.yt$playlistId.$t;
video.title = response.feed.title;
video.entry = response.feed.entry;
videos.push(video);
})//end getJSON
}//end for
doc.videos = videos;
console.log('Result:', doc);
return doc;
}
});
}
});
The problem is in my template, I can see myPlaylist.date as a result of transform, but I cannot see myPlaylist.videos (although I see the console.log result has data)
Does anyone has an idea how to solve this? Very appreciate!
As #Ian Jones commented, $.getJSON is asynchronous so doc.videos will never have a value where you’ve put your console.log. To solve this, use the ReactiveVar package:
Template.Videos.onCreated(function() {
this.videos = new ReactiveVar([]);
var self = this;
Apps.findOne({}, {
transform: function (doc){
playlists = doc.playlists;
for (var i=0;i<playlists.length;i++){
console.log('find playlist: ',playlists[i]);
var url = 'https://gdata.youtube.com/feeds/api/playlists/'+playlists[i]+'?v=2&alt=json';
$.getJSON(url, function(response){
var video={};
video._id = response.feed.yt$playlistId.$t;
video.title = response.feed.title;
video.entry = response.feed.entry;
var videos = self.videos.get();
videos.push(video);
self.videos.set(videos);
})//end getJSON
}//end for
}
});
}
});
Template.Videos.helpers({
myPlaylist:function(){
var instance = Template.instance();
return instance.videos.get();
}
});
Thanks for all your helps. I was unwilling to do reactive-var from the beginning, but your answer motivated me to go for it, big thanks.
This is my final code:
Template.Videos.created = function(){
var instance = this;
instance.videos = new ReactiveVar([]);
instance.autorun(function(){
MenusList.findOne({}, {
transform: function (doc){
playlists = doc.playlists;
for (var i=0;i<playlists.length;i++){
console.log('find playlist: ',playlists[i]);
var url = 'https://gdata.youtube.com/feeds/api/playlists/'+playlists[i]+'?v=2&alt=json';
$.getJSON(url, function(response){
var video={};
video._id = response.feed.yt$playlistId.$t;
video.title = response.feed.title;
video.entry = response.feed.entry;
var videos = instance.videos.get();
videos.push(video);
instance.videos.set(videos);
})//end getJSON
}//end for
return doc;
}//end transform
});//end findOne
});//end autorun
}
Template.Videos.helpers({
myPlaylist:function(){
var instance = Template.instance();
return instance.videos.get();
}
});
I'm trying to detect when the user hits "refresh" from my app to load some data.
I have this:
var refresh = function() {
alert('refresh');
};
var vm = {
refresh: refresh,
data: ko.observable()
};
However I never get the alert in my browser, and a breakpoint set at the opening of the function does not get hit when I refresh the page from this view. How can I properly use the refresh function?
I would suggest hooking into the canDeactivate method in your view model.
var refresh = function() {
alert('refresh');
};
var canDeactivate = function(isClose){
if (isClose)
{
refresh();
return false;
}
else return true;
};
var vm = {
data: ko.observable(),
canDeactivate: canDeactivate
};
I've got a Google Maps widget working on an .xhtml page served by a JSF2 project in Java. The map displays, and I have a function for adding markers that works just fine. However, any attempt to use Geocoder seems to result in the returned status of 'ERROR'. Google Maps API mentions no such error status amongst its five possible candidates for return values of the 'status' variable.
Followng is a .js file deployed, and the offending function in question is codeAddress(). Similar code to codeAddress() works elsewhere online that I can find, so it must be something to do with the circumstances under which its being called. Given that the map displays just fine, and I can place markers, my expectation is that my session is just fine. This leaves me puzzled :( Does anyone know what 'ERROR' could come from??
var map;
var marker;
var geocoder;
function placeMarker(location) {
if (!marker) {
marker = new google.maps.Marker({
position: location,
map: map
});
} else {
marker.setPosition(location);
}
map.setCenter(location);
var field = document.getElementById("portCreate:coordinate");
field.value = "POINT (" + location.lat() + " " + location.lng() + ")";
}
function initialize() {
var mapOptions = {
center : new google.maps.LatLng(55.761123, 13.084717),
zoom : 5,
mapTypeId : google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(
document.getElementById("map"), mapOptions);
google.maps.event.addListener(map, 'click', function(event) {
placeMarker(event.latLng);
});
setMarker(document.getElementById("portCreate:coordinate"));
geocoder = new google.maps.Geocoder();
}
function setMarker(field) {
if (field.value) {
var regex = /POINT.+?([-0-9\.]+).+?([-0-9\.]+)/;
var matches = regex.exec(field.value);
placeMarker(new google.maps.LatLng(Number(matches[1]), Number(matches[2])));
}
}
function codeAddress(address) {
geocoder.geocode( { 'address': address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
map.setCenter(results[0].geometry.location);
} else {
alert("Geocode was not successful for the following reason: " + status + "\nFor address " + address);
}
});
}
function loadScript() {
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "https://maps.googleapis.com/maps/api/js?key=<API key here>&sensor=false&callback=initialize";
document.body.appendChild(script);
}
window.onload = loadScript;
After having this same problem today I've remembered that instead of doing a link to the API I downloaded the code as .js. After changing it to a link it works agains. I think Google updates the script regurlaly, if it had any version conflict they return the ERROR status.
The documentation for javascript/geocoding shows 'ERROR' as a possible result:
"ERROR" indicates that the request timed out or there was a problem contacting the Google servers. The request may succeed if you try again.
I had the same problem. I was working with ASP .Net application. After I changed the ASP .Net button control to HTML input Button, it is working now. Not sure where the problem is.
<input type="button" value="Geocode" onclick="codeAddress()">
I was troubleshooting a similar issue, where I was able to recreate the ERROR status by canceling the google API http request before it returned a response.
I am unable to display all the results requested from the Google Places Api..
var Latlng = new google.maps.LatLng(Latitute, Longitute);
map = new google.maps.Map(document.getElementById('map_canvas'), {
mapTypeId: google.maps.MapTypeId.ROADMAP,
center: Latlng,
zoom: 10});
var request = {location: Latlng,types: [type]};
var service = new google.maps.places.PlacesService(map);
service.search(request, callback);
}
function callback(results,status,pagination) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
for (var i = 0; i < results.length; i++) {
createMarker(results[i]);
}
if (pagination.hasNextPage) {
pagination.nextPage(); }}}
function createMarker(place) {
var placeLoc = place.geometry.location;
var marker = new google.maps.Marker({map: map,zIndex: 100,position: place.geometry.location});
var request = {reference : place.reference,};
service = new google.maps.places.PlacesService(map);
service.getDetails(request, function detailsDisplay(details, status){
if (status === google.maps.places.PlacesServiceStatus.OK) {
console.log(status);
$('#placesdata').append('<tr><td><a href='+details.url+'>' + details.name+ '</a></td></tr>');
} else if (status === google.maps.GeocoderStatus.OVER_QUERY_LIMIT) {
setTimeout(function() {
createMarker(place);
}, 200);}});} };
i used pagination and getting 60 results but only can display 20..and 40 using settimeout() function...getting the following error: Uncaught TypeError: Cannot read property 'length' of null. Any clue?
Most likely you are getting OVER_QUERY_LIMIT on line:
if (status == google.maps.places.PlacesServiceStatus.OK)
because you are already creating Markers, which eats up your quota.
Try queuing the details requests for after you have all the list completed, and adding the same timeout logic to check for google.maps.places.PlacesServiceStatus.OVER_QUERY_LIMIT on this line.
For example you could say:
if (pagination.hasNextPage) {
//add all places to the list
setTimeout('pagination.nextPage()',2000);
} else {
createMarkers(placesList);
}
btw. the Places equivalent of google.maps.GeocoderStatus.OVER_QUERY_LIMIT is google.maps.places.PlacesServiceStatus.OVER_QUERY_LIMIT and you should use this when using Places.
HTH
I have done all those effort. Thanks for you guys for posting but i got solution. really a good solution. See working example below.
When you call this method to check if it has pages or not
if(pagination.hasNextPage){
pagination.nextPage(); // let this do recursive loop against request.
}
// when nextPage() request finishes
if(pagination.b == null){
// here pagination.b has next page token. so it return null when last request sent.
createMarkers(placesList);
}
Right now, the autocomplete box works just fine when I click on the location, but when I press down, highlight the location that I want to go to, and press enter, it simply goes back to the home location of the map. Any insights on this? I call this function in initialize(). I'm lost as to what I possibly did wrong. Is this just a google api bug? If so, any insights as to how to work around it?
function setupAutoComplete() {
var defaultBounds = new google.maps.LatLngBounds(
new google.maps.LatLng(-90, -180),
new google.maps.LatLng(90, 180));
var input = document.getElementById('placeSearch');
var options = {
bounds: defaultBounds,
types: ['(regions)']
};
autocomplete = new google.maps.places.Autocomplete(input, options);
google.maps.event.addListener(autocomplete, 'place_changed', function() {
alert('hi');
removeAllOverlays();
var place = autocomplete.getPlace();
var mapCenter = place.geometry.location;
var colLat = mapCenter.lat() - (halfPoints)*latSeparation;
var colLng = mapCenter.lng() - (halfPoints)*lngSeparation;
var tempStart = new google.maps.LatLng(colLat, colLng);
map.setCenter(mapCenter);
pointArray[0][0] = tempStart;
reService();
mapSearch();
drawBounds();
});
}
Thanks so much!
I guess the input#placeSearch is placed inside a <form>.
You submit the form when you press [ENTER].
You may either remove the surrounding form or cancel the submission by adding:
onsubmit="return false"
...to the form-element.
I just hit this issue and went with the following, as I do want to submit the form at a later stage. This code is from google groups.
var input = document.getElementById('create-location');
var options = {
//types: ['(cities)'],
};
autocomplete = new google.maps.places.Autocomplete(input, options);
google.maps.event.addDomListener(input, 'keydown', function(e) {
if (e.keyCode == 13)
{
if (e.preventDefault)
{
e.preventDefault();
}
else
{
// Since the google event handler framework does not handle early IE versions, we have to do it by our self. :-(
e.cancelBubble = true;
e.returnValue = false;
}
}
});