I have a page that uses Google Maps API to display a Map with 10 markes.
When I load the page the map is shown, but markers disappear and the console show me the following error :
Uncaught ReferenceError: google is not defined
at new Location (app.js:60)
at app.js:97
Here is my JS code:
// Initialize Google Map to Florence
var map;
function initialize() {
var mapOptions = {
zoom: 12,
center: new google.maps.LatLng(43.7792500, 11.2462600),
disableDefaultUI: true
};
map = new google.maps.Map(document.getElementById('map'), mapOptions);
}
function mapError() {
console.log("Issue in retrieving data and resouces. Please, try to reload the page.");
}
// Create Location Class.
var Location = function(title, x, y, foursquare_id) {
var self = this;
// Set Location Title.
this.title = title;
// Set Location coordinates.
this.x = x; // Longitude.
this.y = y; // Latitude.
// Set Location id from Foursquare.
this.foursquare_id = foursquare_id;
// Request 10 most recent comments from Foursquare.
this.Request = function() {
var comments = [];
var foursquare_url = 'https://api.foursquare.com/v2/venues/';
var request = foursquare_url + self.foursquare_id + '/tips?sort=recent&limit=10&v=20150609&client_id=' + client_id + '&client_secret=' + client_secret;
// Get Request and Return formatted Data
$.getJSON(request,
function(data) {
$.each(data.response.tips.items, function(i, tips) {
comments.push('<li>' + tips.text + '</li>');
});
// If Request Succeeds.
}).done(function() {
self.content = "<fieldset><legend><h1>" + self.title + "</h1></legend><h3>10 Most Recent Comments from Foursquare</h3><ol class='tips'>" + comments.join('') + "</ol><cite>Source: Foursquare Labs, Inc.</cite></fieldset>";
// If Request Fails.
}).fail(function(jqXHR, textStatus, errorThrown) {
self.content = "<fieldset><legend><h1>" + self.title + "</h1></legend><h3>Foursquare says Sorry!</h3><h4>There was a problem in retrieving data from Foursquare. Please, try to reload the page.</h4></fieldset>";
console.log('getJSON request failed! ' + textStatus);
});
}();
// Initialize Google Maps InfoWindow.
this.infowindow = new google.maps.InfoWindow();
// Assign Markers to Locations.
this.marker = new google.maps.Marker({
map: map,
draggable: true,
animation: google.maps.Animation.BOUNCE,
position: new google.maps.LatLng(self.x, self.y),
title: self.title
});
self.marker.addListener('click', toggleBounce);
function toggleBounce() {
if (self.marker.getAnimation() !== null) {
self.marker.setAnimation(google.maps.Animation.BOUNCE);
} else {
self.marker.setAnimation(google.maps.Animation.BOUNCE);
}
}
// Show Info Window.
this.openInfowindow = function() {
for (var i = 0; i < Data.locations.length; i++) {
Data.locations[i].infowindow.close();
}
map.panTo(self.marker.getPosition())
self.infowindow.setContent(self.content);
self.infowindow.open(map, self.marker);
};
// Click event-listener to each Marker that shows the relative Info Window.
this.addListener = google.maps.event.addListener(self.marker, 'click', (this.openInfowindow));
};
// Create Location Objects.
var Data = {
locations: [
new Location("Palazzo Pitti", 43.765264, 11.250094, "4bc8c9d7af07a593d4aa812d"),
new Location("Uffizi Gallery", 43.768439, 11.2559, "51191cdfb0ed67c8fff5610b"),
new Location("Florence Cathedral", 43.773083, 11.256222, "4bd00cdb046076b00a576f71"),
new Location("Palazzo Vecchio", 43.769315, 11.256174, "4bd01b8077b29c74a0298a82"),
new Location("Piazza della Signoria", 43.7684152597, 11.2534589862, "4b81729af964a520a7a630e3"),
new Location("Giotto's Campanile", 43.772772, 11.255786, "4b49cd73f964a520d87326e3"),
new Location("Piazzale Michelangelo", 43.762462, 11.264897, "4b3276d5f964a520620c25e3"),
new Location("Ponte Vecchio", 43.768009, 11.253165, "4b6ed35df964a52038cc2ce3"),
new Location("Boboli Gardens", 43.762361, 11.248297, "4bc97abcfb84c9b6f62e1b3e"),
new Location("Vinci", 43.783333, 10.916667, "4ca4f0a0965c9c74530dc7fa"),
],
query: ko.observable(''),
};
// Search by name into the locations list.
Data.search = ko.computed(function() {
var self = this;
var search = this.query().toLowerCase();
return ko.utils.arrayFilter(self.locations, function(location) {
var isMatching = location.title.toLowerCase().indexOf(search) >= 0;
if (isMatching) {
Marker.setVisible(true);
} else {
Marker.setVisible(false);
}
return isMatching;
});
})
ko.applyBindings(Data);
Here is my HTML code :
<!DOCTYPE html>
<html>
<head>
<title>Map</title>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1.0">
<link rel="stylesheet" href="css/styles.css">
</head>
<body>
<div class="container">
<div class="row">
<div class="search" id="search">
<input class="input" type="text" placeholder="Search..." data- bind="value: query, valueUpdate: 'keyup'">
<ul class="list" data-bind="template: { name:'location', foreach:search }"></ul>
</div>
<!-- Search Form. -->
<div class="map" id="map"></div>
<!-- Google Map. -->
</div>
<!-- ROW. -->
</div>
<!-- CONTAINER. -->
<!-- Show list under the search form. -->
<script type="text/html" id="location">
<li class="item" data-bind="text: title, click: openInfowindow"></li>
</script>
<!-- Import knockout framework, jquery library, personal js and Google Maps Apis -->
<script src="js/knockout-3.4.1.js"></script>
<script src="js/jquery-3.1.1.js"></script>
<script src="js/app.js"></script>
<script async defer src="https://maps.googleapis.com/maps/api/js? key=AIzaSyCFSYzAYNIkokmho_gNRE7vWO7-dAZW46g&callback=initialize" onerror="mapError()"></script>
</body>
</html>