Google Map JavaScript Error(s) - html

I am trying to install a Google Map via JavaScript on to my website which will have multiple markers. I am getting several errors and I cannot figure them out or resolve them. Please can someone help me?
The map:
<div id="map-canvas"></div>
I am loading the following JavaScript in the footer (below the map-canvas):
<!-- Google Map -->
<script async defer src="https://maps.googleapis.com/maps/api/js?key=API REMOVED&callback=initMap" type="text/javascript"></script>
<script type="text/javascript" src="js/map.js"></script>
In my map.js I have:
// necessary variables
var map;
var infoWindow;
// markersdata variable stores the information necessary to each marker
var markersData = [{
lat: 40.6386333,
lng: -8.745,
name: "Camping Praia da Barra",
address1: "Rua Diogo Cão, 125",
address2: "Praia da Barra",
postalCode: "3830-772 Gafanha da Nazaré"
},
{
lat: 40.59955,
lng: -8.7498167,
name: "Camping Costa Nova",
address1: "Quinta dos Patos, n.º 2",
address2: "Praia da Costa Nova",
postalCode: "3830-453 Gafanha da Encarnação"
},
{
lat: 40.6247167,
lng: -8.7129167,
name: "Camping Gafanha da Nazaré",
address1: "Rua dos Balneários do Complexo Desportivo",
address2: "Gafanha da Nazaré",
postalCode: "3830-225 Gafanha da Nazaré"
}
];
function initialize() {
var mapOptions = {
center: new google.maps.LatLng(40.601203, -8.668173),
zoom: 9,
mapTypeId: 'roadmap',
};
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
// a new info window is created
infoWindow = new google.maps.InfoWindow();
// event that closes the info window with a click on the map
google.maps.event.addListener(map, 'click', function() {
infoWindow.close();
});
// finally displaymarkers() function is called to begin the markers creation
displayMarkers();
}
google.maps.event.addDomListener(window, 'load', initialize);
// this function will iterate over markersdata array
// creating markers with createmarker function
function displayMarkers() {
// this variable sets the map bounds according to markers position
var bounds = new google.maps.LatLngBounds();
// for loop traverses markersdata array calling createmarker function for each marker
for (var i = 0; i < markersData.length; i++) {
var latlng = new google.maps.LatLng(markersData[i].lat, markersData[i].lng);
var name = markersData[i].name;
var address1 = markersData[i].address1;
var address2 = markersData[i].address2;
var postalCode = markersData[i].postalCode;
createMarker(latlng, name, address1, address2, postalCode);
// marker position is added to bounds variable
bounds.extend(latlng);
}
// finally the bounds variable is used to set the map bounds
// with fitbounds() function
map.fitBounds(bounds);
}
// this function creates each marker and it sets their info window content
function createMarker(latlng, name, address1, address2, postalCode) {
var marker = new google.maps.Marker({
map: map,
position: latlng,
title: name
});
// this event expects a click on a marker
// when this event is fired the info window content is created
// and the info window is opened.
google.maps.event.addListener(marker, 'click', function() {
// creating the content to be inserted in the infowindow
var iwContent = '<div id="iw_container">' +
'<div class="iw_title">' + name + '</div>' +
'<div class="iw_content">' + address1 + '<br />' +
address2 + '<br />' +
postalCode + '</div></div>';
// including content to the info window.
infoWindow.setContent(iwContent);
// opening the info window in the current map and at the current marker location.
infoWindow.open(map, marker);
});
}
The errors that I am getting are:
1. Uncaught ReferenceError: google is not defined at map.js:52
2. Uncaught Qb
What does this mean?

You should be passing the name of your map initialisation function (initialize) in the callback query parameter of the google maps URL:
<script async defer src="https://maps.googleapis.com/maps/api/js?key=API REMOVED&callback=initialize" type="text/javascript"></script>
You also need to load your javascript file before loading the google maps API to ensure that your initialisation function is defined when the callback is called:
<script type="text/javascript" src="js/map.js"></script>
<script async defer src="https://maps.googleapis.com/maps/api/js?key=API REMOVED&callback=initialize" type="text/javascript"></script>

You're loading the Google API async.
<script async defer src="https://maps.googleapis.com/maps/api/js?key=API REMOVED&callback=initMap" type="text/javascript"></script>
Which means your map.js is being executed before it's loaded, in addition: the callback is 'initMap' which isn't doing anything in your own map.js at this moment.
google.maps.event.addDomListener(window, 'load', initialize);
Remove this line, and change the callback function in your script to initialize.

This line google.maps.event.addDomListener(window, 'load', initialize);
should be in your initialize function cos at the point where it is as your error says, it has not been loaded

Ok, let's looking for what is happening here. You have imported the g maps dependencies with this:
<script async defer src="https://maps.googleapis.com/maps/api/js?key=API REMOVED&callback=initMap" type="text/javascript"></script>
Look at that "async" word. That says that the js file will be loaded asynchronously. Now, look at the src attr:
https://maps.googleapis.com/maps/api/js?key=API_REMOVED&callback=initMap
The attribute callback in the query string defines a JS function that you need have in your code, that will be executed when the async load is finished. You don't have this function in your code,so you should create it with the inialization of your map.
Maybe, putting all your JS code into this will works:
function initMap(){
// your code here
}

Related

How to get the latitude and longitude in this code

Here i am using google map API ,user search their area means i want to get the latitude and logidute and stored in my database, i don't know how to do ,i am new in google map integrating please help me some one
// This sample uses the Place Autocomplete widget to allow the user to search
// for and select a place. The sample then displays an info window containing
// the place ID and other information about the place that the user has
// selected.
// This example requires the Places library. Include the libraries=places
// parameter when you first load the API. For example:
// <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places">
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
center: {lat: -33.8688, lng: 151.2195},
zoom: 13
});
var input = document.getElementById('pac-input');
var autocomplete = new google.maps.places.Autocomplete(input);
autocomplete.bindTo('bounds', map);
map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);
var infowindow = new google.maps.InfoWindow();
var marker = new google.maps.Marker({
map: map
});
marker.addListener('click', function() {
infowindow.open(map, marker);
});
autocomplete.addListener('place_changed', function() {
infowindow.close();
var place = autocomplete.getPlace();
if (!place.geometry) {
return;
}
if (place.geometry.viewport) {
map.fitBounds(place.geometry.viewport);
} else {
map.setCenter(place.geometry.location);
map.setZoom(17);
}
// Set the position of the marker using the place ID and location.
marker.setPlace({
placeId: place.place_id,
location: place.geometry.location
});
marker.setVisible(true);
document.getElementById('place-name').textContent = place.name;
document.getElementById('place-id').textContent = place.place_id;
document.getElementById('place-address').textContent =
place.formatted_address;
infowindow.setContent(document.getElementById('infowindow-content'));
infowindow.open(map, marker);
});
}
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCW8mAAfcRRb4hrB33AWG_Mk71ZtORjOAo&libraries=places&callback=initMap"
async defer></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<input id="pac-input" class="controls" type="text"
placeholder="Enter a location">
<div id="map"></div>
<div id="infowindow-content">
<span id="place-name" class="title"></span><br>
Place ID <span id="place-id"></span><br>
<span id="place-address"></span>
</div>
As described in the documentation you can use the Google Maps Geocoding API and query using an address and the api will respond with the geocoding (including latitude and longitude) for that address. For example the following request,
curl "https://maps.googleapis.com/maps/api/geocode/json?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&key=YOUR_API_KEY"
, will repsond with
{
...
"geometry" : {
"location" : {
"lat" : 37.4223664,
"lng" : -122.084406
},
...
},
...
}
You can find a detailed example here.

Can't load markers into Google Maps API from JSON

Thanks in advance for any help you can provide! I'm trying to create markers in my Google Map using JSON data. The good news is that I've got the data in the format I need it. The bad news is that I'm new to JSON, and I can't seem to get the markers to show up on the map. From the console's response, the issue seems to be the mapInit line at the bottom of the code below.
I have tried resolving this problem by reviewing solutions at different markers on google maps v3, Using JSON markers in Google Maps API with Javascript, and Google Maps API v3: Adding markers from an array doesn't work, among others. I've also tried duplicating the examples at http://weareallrobots.com/demos/map.html and other sites, but I'm still having trouble.
My code:
<script>
var directionsDisplay;
var directionsService = new google.maps.DirectionsService();
var map;
function initialize() {
var rendererOptions = {
draggable: true,
panel:document.getElementById('directions_panel')
};
directionsDisplay = new google.maps.DirectionsRenderer(rendererOptions);
var chicago = new google.maps.LatLng(41.850033, -87.6500523);
var mapOptions = {
zoom: 6,
center: chicago,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
directionsDisplay.setMap(map);
// HERE'S WHERE PROBLEMS START
$.getJSON("mapall.js", {}, function(data){
$.each(data.masterlocation, function(i, item){
$("#markers").append('<li>' + item.nickname + '</li>');
var marker = new google.maps.Marker({
position: new google.maps.LatLng(item.latitude, item.longitude),
map: map_canvas,
title: item.nickname
});
arrMarkers[i] = marker;
var infowindow = new google.maps.InfoWindow({
content: "<h3>"+ item.nickname +"</h3>"
});
arrInfoWindows[i] = infowindow;
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(map, marker);
});
});
});
}
function calcRoute() {
UNRELATED ROUTING CODE HERE
}
// HERE'S WHERE MORE PROBLEMS START
$(function(){
// initialize map (create markers, infowindows and list)
mapInit();
// "live" bind click event
$("#markers a").live("click", function(){
var i = $(this).attr("rel");
// this next line closes all open infowindows before opening the selected one
//for(x=0; x < arrInfoWindows.length; x++){ arrInfoWindows[x].close(); }
arrInfoWindows[i].open(map, arrMarkers[i]);
});
});
</script>
My JSON Data
[{"masterlocation":{"latitude":"33.5","nickname":"First","longitude":"-86.8"}},{"masterlocation":{"latitude":"34.7","nickname":"Second","longitude":"-86.6"}},
UPDATE 1
As per comments from geocodezip and Adam, I've updated my code to the below. I added the + symbol before latitude and longitude, and I replaced mapInit with initialize. However, I'm still not getting any markers to show up. Firebug is telling me that I have errors in my jQuery file, but I'm not sure if these are related. Thanks for sticking with me!
Code:
// HERE'S WHERE PROBLEMS START
$.getJSON("mapall.js", {}, function(data){
$.each(data.masterlocation, function(i, item){
$("#markers").append('<li>' + item.nickname + '</li>');
var marker = new google.maps.Marker({
position: new google.maps.LatLng(+item.latitude, +item.longitude),
map: map_canvas,
title: item.nickname
});
arrMarkers[i] = marker;
var infowindow = new google.maps.InfoWindow({
content: "<h3>"+ item.nickname +"</h3>"
});
arrInfoWindows[i] = infowindow;
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(map, marker);
});
});
});
}
function calcRoute() {
UNRELATED ROUTING CODE HERE
}
// HERE'S WHERE MORE PROBLEMS START
$(function(){
// initialize map (create markers, infowindows and list)
initialize();
// "live" bind click event
$("#markers a").live("click", function(){
var i = $(this).attr("rel");
// this next line closes all open infowindows before opening the selected one
//for(x=0; x < arrInfoWindows.length; x++){ arrInfoWindows[x].close(); }
arrInfoWindows[i].open(map, arrMarkers[i]);
});
});
JQuery errors
TypeError: a is undefined
[Break On This Error]
...rn a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,b,d){...
jquery.js (line 29)
TypeError: a is undefined
[Break On This Error]
...rn a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,b,d){...
UPDATE 2
My current code is below, as well as the error codes I am getting in the console. New errors appeared when I reloaded the page, and they refer to the line in my javascript where function initialize first occurs. Maybe this is the problem?
Also, is it possible that the problem is in the JSON? Each JSON entry is preceded by the name of the MYSQL table, "Masterlocation" (see above.) In other JSON examples I've seen, the term that comes after the "." in "$.each(data.masterlocation)" only occurs once.
My Javascript:
<script>
var directionsDisplay;
var directionsService = new google.maps.DirectionsService();
var map;
function initialize() {
var rendererOptions = {
draggable: true,
panel:document.getElementById('directions_panel')
};
directionsDisplay = new google.maps.DirectionsRenderer(rendererOptions);
var chicago = new google.maps.LatLng(41.850033, -87.6500523);
var mapOptions = {
zoom: 6,
center: chicago,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
directionsDisplay.setMap(map);
$.getJSON("mapall.js", {}, function(data){
console.log(data);
$.each(data.masterlocation, function(i, item){
console.log(item);
$("#markers").append('<li>' + item.nickname + '</li>');
var marker = new google.maps.Marker({
position: new google.maps.LatLng(+item.latitude, +item.longitude),
map: map,
title: item.nickname
});
arrMarkers[i] = marker;
var infowindow = new google.maps.InfoWindow({
content: "<h3>"+ item.nickname +"</h3>"
});
arrInfoWindows[i] = infowindow;
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(map, marker);
});
});
});
}
function calcRoute() {
ROUTING CODE
var request = {
origin: start,
destination: end,
waypoints: waypts,
optimizeWaypoints: optimize,
travelMode: google.maps.TravelMode.DRIVING
};
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
var route = response.routes[0];
var summaryPanel = document.getElementById("directions_panel");
}
$(function(){
// initialize map (create markers, infowindows and list)
initialize();
// "live" bind click event
$("#markers a").live("click", function(){
var i = $(this).attr("rel");
// this next line closes all open infowindows before opening the selected one
//for(x=0; x < arrInfoWindows.length; x++){ arrInfoWindows[x].close(); }
arrInfoWindows[i].open(map, arrMarkers[i]);
});
});
</script>
Javascript Errors from Console: these only occurred after I reloaded the page.
Uncaught TypeError: Cannot read property 'length' of undefined jquery.js:29
c.extend.each jquery.js:29
(anonymous function) mapall:87
b jquery.js:121
w.onreadystatechange jquery.js:127
Uncaught TypeError: Cannot read property 'length' of undefined jquery.js:29
c.extend.each jquery.js:29
(anonymous function) mapall:87
b jquery.js:121
w.onreadystatechange jquery.js:127
In addition to any other errors, the way you're accessing the JSON data doesn't match the format of that data.
Your code to access the JSON data is:
$.getJSON( "mapall.js", {}, function( data ) {
$.each( data.masterlocation, function( i, item ) {
... use item.nickname, item.latitude, and item.longitude here
});
});
Now there's nothing wrong with that code, if the JSON data looked like this:
{
"masterlocation": [
{
"nickname": "First",
"latitude": 33.5,
"longitude": -86.8
},
{
"nickname": "Second",
"latitude": 34.7,
"longitude": -86.6
}
]
}
This JSON data is an object with a single property named masterlocation. That property is an array of objects, each one containing nickname, a string, and latitude and longitude, two numbers.
That's a pretty sensible way to lay out the JSON data. I would do it just about the same myself. (The only things I can think of changing would be the naming conventions: I'd probably use a name like locations instead of masterlocation because I like to see plural names for arrays, and I like shorter names for commonly-used properties, e.g. name, lat, and lng. But that's purely a matter of style—the structure I'd use is identical aside for names.)
Unfortunately, your actual JSON data looks like this:
[
{
"masterlocation": {
"latitude": "33.5",
"nickname": "First",
"longitude": "-86.8"
}
},
{
"masterlocation": {
"latitude": "34.7",
"nickname": "Second",
"longitude": "-86.6"
}
}
]
This is an array of two elements. Each element is an object with one property named masterlocation. Each masterlocation object contains the nickname, latitude, and longitude properties. And the latitude and longitude are strings instead of numbers like they should be.
It would be easy enough to change your code to work with this structure:
$.getJSON( "mapall.js", {}, function( data ) {
$.each( data, function( i, item ) {
var loc = item.masterlocation;
... use loc.nickname, +loc.latitude, and +loc.longitude here
});
});
But if you have the option of changing the format of your JSON format, I'd do that instead. You had the right idea in your JavaScript code, just change the JSON output to match.
Make sure the latitude and longitude are actually numbers in JS, not strings.
To do a type convert, just put a + in front of the string
position: new google.maps.LatLng(+item.latitude, +item.longitude)
For some reason, google's API was not built smart enough to handle passing in strings containing numbers....go figure.
EDIT
Ditto to the comment on your post as well - you are calling a function mapInit() but you should be calling the function initialize() from the looks of it.
EDIT2
This line:
map: map_canvas,
should be
map: map,

MODX getResources with Google maps infowindows

I am populating a Google Map with the following code:
<script type="text/javascript">
google.maps.event.addDomListener(window, 'load', function() {
var map = new google.maps.Map(document.getElementById('gmap'), {
zoom: 8,
center: new google.maps.LatLng(51.414487, -0.207644),
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var infoWindow = new google.maps.InfoWindow;
var onMarkerClick = function() {
var marker = this;
var latLng = marker.getPosition();
infoWindow.setContent('<div class="map-info-window">\
<h3>WEA [[+pagetitle]]</h3>\
<p><strong>Branch contact:</strong> [[+branch-latlng]]</p>\
<p><strong>Telephone no:</strong> [[+branch-phone:htmlent]]</p>\
<p><strong>Email:</strong> [[+branch-email.htmlent]]</p>\
[[+branch-more.htmlent]]\
</div>' );
infoWindow.open(map, marker);
};
google.maps.event.addListener(map, 'click', function() {
infoWindow.close();
});
[[getResources? &debug=`0` &showHidden=`1` &parents=`[[*id]]` &depth=`4` &tpl=`newBranchMapMarkerTpl` &includeTVs=`1` &processTVs=`1` &tvPrefix=`` &limit=`0` &where=`{"template:=":9}`]]
[[getResources? &debug=`0` &showHidden=`1` &parents=`[[*id]]` &depth=`4` &tpl=`newMarkerInit` &includeTVs=`1` &processTVs=`1` &tvPrefix=`` &limit=`0` &where=`{"template:=":9}`]]
});
</script>
And the contents of the 2 getResources calls are as follows:
newBranchMapMarkerTpl:
var marker[[+id]] = new google.maps.Marker({
map: map,
position: new google.maps.LatLng([[+branch-latlng]]),
title:"[[+pagetitle]]"
});
newMarkerInit:
google.maps.event.addListener(marker[[+id]], 'click', onMarkerClick);
but it does not grab the template variables as laid out in the setContent code; this is because it is only referenced once in the map page header, and normally would need to loop through each document. I've tried to create a new infowindow within the BranchMapMarkerTpl and it works but does not close the last infowindow when another is opened.
How could this be re-factored so it would pick up the template variable values?
Thanks in advance.
The syntax for template variables in a Template is [[*tvname]]. Try:
infoWindow.setContent('<div class="map-info-window">\
<h3>WEA [[*pagetitle]]</h3>\
<p><strong>Branch contact:</strong> [[*branch-latlng]]</p>\
<p><strong>Telephone no:</strong> [[*branch-phone:htmlent]]</p>\
<p><strong>Email:</strong> [[*branch-email:htmlent]]</p>\
[[*branch-more:htmlent]]\
</div>' );
[[+tvname]] is correct as used within your getResources chunks, as the Template Variable values are being output to placeholders and not parsed via Template Variable tags.

jQuery executes before Google map loads: "map is undefined"

Aside from jQuery and Google Maps, I have two scripts included in the head of my page:
<script src="js/map.js" type="text/javascript"></script>
<script src="js/site.js" type="text/javascript"></script>
map.js contains the code to initialize my map and also have the following function to place a marker on it:
function placeMarker(marker){
clearLocations();
var latlng = new google.maps.LatLng(
parseFloat(marker.lat),
parseFloat(marker.lng)
);
var marker = createMarker(latlng);
map.setZoom(14);
var latLng = marker.getPosition();
map.setCenter(latLng);
}
When I call placeMarker inside $(document).ready() in site.js, I get the error, 'map is undefined'. However when I call another function in site.js that executes when a button is clicked, placeMarker runs in its callback without a problem:
$.ajax({
url: 'ajax/json.php',
dataType: 'json',
data: 'search_string='+inpMapSearch+'&country='+Country,
success: function(data) {
console.log(data);
placeMarker(data);
}
});
Does this mean that the placeMarker function call inside $(document).ready() is trying to execute before the map is initialized? How can I run placeMarker after the map is initialized?
=== EDIT ===
As per request here is the code that initializes the map:
google.maps.event.addDomListener(window, 'load', load);
function load() {
map = new google.maps.Map(document.getElementById("map"), {
center: new google.maps.LatLng(18.735693,-70.162651),
zoom: 8,
mapTypeId: 'roadmap',
mapTypeControlOptions: {style: google.maps.MapTypeControlStyle.DROPDOWN_MENU}
});
}
Because the window load event fires after the document.ready. Hence your map is initialized after the document.ready. You could instead wrap your other code in the $(window).load
$(window).load(function(){
your code here
});

Map doesn't respond on mouse clicks with Google Maps API V3 and QWebView

EDIT 4
All this while I was thinking that it is the markers problem, that they do not get dragged!
Now I have realized, that NO mouse click works on the map when it is displayed in Qt widget.
The following code, I pasted in an HTML file and opened through Firefox, this worked flawlessly! and the same doesn't respond when I click on the map on QtWidget :rolleyes:
Can anyone confirm this for me or tell me what wrong I am doing?
Google Maps JavaScript API Example
<script type="text/javascript">
var map;
var latlng = new google.maps.LatLng (34.7607233, -117.0107599);
var directionsDisplay = new google.maps.DirectionsRenderer ();;
var directionsService = new google.maps.DirectionsService ();
var pointsArray = new Array();
var arrayToBeReturned = new Array();
function initialize ()
{
var myOptions =
{
zoom:8,
center:latlng,
mapTypeId:google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map (document.getElementById ("map"), myOptions);
directionsDisplay.setMap (map);
google.maps.event.addListener (map, "click", function ()
{
alert("You clicked the map.");
});
}
</script>
</head>
<body onload="initialize()" topmargin="0" leftmargin="0">
<div id="map" style="width: 341px; height: 271px"></div>
<div id="directionsPanel" style="float:right;width:30%;height 100%"></div>
</body>
</html>
You are looking at the wrong place for the events :) In the references each object have their own events. You can see the ones for markers here:
[http://code.google.com/apis/maps/documentation/javascript/reference.html#Marker][1]
I have used the dragend event plenty of times and it works smoothly.
The code to do it could be:
var map = new google.maps.Map(document.getElementById("map"), myOptions);
var marker = new google.maps.Marker({
position: latlng,
map: map,
draggable: true
});
google.maps.event.addListener(marker, 'dragend', function () {
document.getElementById("txtLatitude").value = marker.getPosition().lat();
document.getElementById("txtLongitude").value = marker.getPosition().lng();
});
[1]: http://code.google.com/apis/maps/documentation/javascript/reference.html#Markermap = new
Found the solution:
Add this class in the source file where you are "loading" the HTML file (containing Javascript API) in the Qt widget.
class myWebPage : public QWebPage
{
virtual QString userAgentForUrl(const QUrl& url) const {
return "Chrome/1.0";
}
};
Then in your own class in the same source file, add the setPage function call as shown below and see the magic happen!
MainScreen::MainScreen(QWidget *parent):QWidget(parent)
{
...
***map->setPage (new myWebPage());***
map->load (QUrl("./index.html") ) ;
};
google.maps.event.addListener (initialPointMarker, 'click',
function () { map.closeInfoWindow(); });
How about single quotes around the click arguement