Unknown error creating a GMaps with IE8 - javascript

I'm trying to create a Google Map on a div that it's generated dinamically and IE fails to load correctly the map and throws an error while loading all the elements "unknown error at line 25 of main.js"
A test file can be found here: http://martinezdelizarrondo.com/bugs/map.html
This is the code:
<p>
<img height="370" id="gMapPreview" src="http://maps.google.com/maps/
api/staticmap?
center=37.4419,-122.1419&zoom=11&size=500x370&maptype=roadmap&sensor=false"
width="500" />
</p>
<script type="text/javascript">
function initLoader()
{
// Create a div replacing the existing img preview
var imgMap = document.getElementById("gMapPreview"),
dMap = document.createElement("div");
imgMap.parentNode.replaceChild( dMap, imgMap);
dMap.style.width = "500px";
dMap.style.height = "370px";
new google.maps.Map( dMap, {
zoom: 11,
center: new google.maps.LatLng(37.4419,-122.1419),
mapTypeId: google.maps.MapTypeId.ROADMAP
});
}
if (window.addEventListener) {
window.addEventListener("load", initLoader, false);
} else {
window.attachEvent("onload", initLoader);
}
</script>
If I put the div in the original source instead of creating it with javascript then it works correctly, but for this project I want to do it this way. I've tried to do the creation of the div also before the page is finished loading, but that doesn't change the problem.
I haven't tested with IE9, just with IE8 but as this is meant to run in the public side of websites the solution should work also with IE6 & 7 as they are supported by the GoogleMaps api.

Off the top of my head I would suggest doing something before the new:
var map = new google.maps.Map( dMap, {
zoom: 11,
center: new google.maps.LatLng(37.4419,-122.1419),
mapTypeId: google.maps.MapTypeId.ROADMAP
});

IE8 doesn't want you to put block level element(div here) within p tag. Change p to div should fix the problem.

Related

Google maps zoom scrollbar does not appear on new version

I have a web-page here. It uses google maps and it worked well. Recently a new version of google maps was released where some changes were made. For instance, instead of e.latLng.F, e.latLng.lng and instead of e.latLng.A, e.latLng.lat should be used. So far, so good. However, for some reason, the zoom scrollbar cannot be seen. I know one can still zoom with mouse scrolling, however, what about devices where mouse scroll is not defined, like a laptop with a touchpad?
This is a part of initialization:
var mapOptions = {
center: { lat: lat, lng: lon},
zoom: 14
};
if (!administrator) {
mapOptions.mapTypeId = google.maps.MapTypeId.HYBRID;
}
var map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
I believe I should define an attribute for mapOptions, but I do not know what should be defined there. When I searched for this on google, I have not found the answer. It is possible that I will find out the answer soon, but anyway, I ask the question here to make sure that others will have an answer to this question in the future. Thanks.
EDIT:
At this page I can see a zoom control. This is the code there:
<!DOCTYPE html>
<html>
<head>
<script
src="http://maps.googleapis.com/maps/api/js">
</script>
<script>
function initialize()
{
var mapProp = {
center: new google.maps.LatLng(51.508742,-0.120850),
zoom:7,
zoomControl:true,
zoomControlOptions: {
style:google.maps.ZoomControlStyle.SMALL
},
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("googleMap"),mapProp);
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div id="googleMap" style="width:500px;height:380px;"></div>
</body>
</html>
if I modify it to this:
<!DOCTYPE html>
<html>
<head>
<script
src="http://maps.googleapis.com/maps/api/js">
</script>
<script>
function initialize()
{
var mapProp = {
center: { lat: 51.508742, lng: -0.120850},
zoom:7,
};
var map = new google.maps.Map(document.getElementById("googleMap"),mapProp);
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div id="googleMap" style="width:500px;height:380px;"></div>
</body>
</html>
the zoom control is still displayed. I wonder why is the zoom control displayed at w3c and not at my end, since:
both the example and my code uses a div
the properties are initialized in a similar manner
the map is initialized in a similar manner
the dom listener is initialized in a similar manner
They've removed the scroll bar from the newest API, but they left the + and - zoom controls. Strangely, I see that your map doesn't have those either.
This article about the changes made to the map controls might be useful
The zoom control was always displayed, but the footer overflown it. It seems that the zoom control is positioned to the right bottom by default, while earlier it was positioned to the left top by default. The solution is either to make sure that the div where the map is displayed is displayed fully, or to initialize the position of the zoom control, like this:
var mapOptions = {
center: { lat: lat, lng: lon},
zoom: 14,
zoomControlOptions: {
position: google.maps.ControlPosition.LEFT_TOP
}
};

How does the Google Maps API work with AngularJS?

How is it possible to use the Google Maps API with AngularJS?
I am using this code in my AngularJS app:
<style>
#googleMap {
width: 200px;
height: 200px;
}
</style>
<div id="googleMap"></div>
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js"></script>
<script language="javascript">
var map;
function initialize() {
var mapOptions = {
mapTypeId: google.maps.MapTypeId.ROADMAP,
zoom: 8,
center: new google.maps.LatLng(-34.397, 150.644)
};
map = new google.maps.Map(document.getElementById('googleMap'), mapOptions);
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
This code is in the view and not in the controller.
I have other functions in the view and they work, but google map is still not working.
This is the error I get in the browser console:
Error: google is not defined
#http://localhost:3000/js/jquery-1.11.2.min.js line 2 > eval:10:2
.globalEval/<#http://localhost:3000/js/jquery-1.11.2.min.js:2:2615
.globalEval#http://localhost:3000/js/jquery-1.11.2.min.js:2:2589
.domManip#http://localhost:3000/js/jquery-1.11.2.min.js:3:23105
.after#http://localhost:3000/js/jquery-1.11.2.min.js:3:21067
Cehttp://localhost:3000/js/angular/lib/angular.min.js:176:70
n#http://localhost:3000/js/angular/lib/angular-route-segment.min.js:7:5868
.compile/http://localhost:3000/js/angular/lib/angular-route-segment.min.js:7:6428
Pe/this.$gethttp://localhost:3000/js/angular/lib/angular.min.js:128:120
p#http://localhost:3000/js/angular/lib/angular-route-segment.min.js:7:2649
this.$gethttp://localhost:3000/js/angular/lib/angular-route-segment.min.js:7:3989
f/<#http://localhost:3000/js/angular/lib/angular.min.js:112:20
Pe/this.$gethttp://localhost:3000/js/angular/lib/angular.min.js:125:301
Pe/this.$gethttp://localhost:3000/js/angular/lib/angular.min.js:122:390
Pe/this.$gethttp://localhost:3000/js/angular/lib/angular.min.js:126:56
l#http://localhost:3000/js/angular/lib/angular.min.js:81:169
S#http://localhost:3000/js/angular/lib/angular.min.js:85:301
vf/http://localhost:3000/js/angular/lib/angular.min.js:86:315
What am I doing wrong?
I searched the web but everyone seems to be using libraries like angular-google-map or ui-map. Why is no one using the direct API?
You can implement google maps in angularjs without using any plugins like this,
<!--use this div where ever you want to create a map-->
<div id="map"></div>
define the width and height for map div,
#map {
height:420px;
width:600px;
}
in controller you glue this id="map" with scope like this,
$scope.mapOptions = {
zoom: 4,
center: new google.maps.LatLng(41.923, 12.513),
mapTypeId: google.maps.MapTypeId.TERRAIN
}
$scope.map = new google.maps.Map(document.getElementById('map'), $scope.mapOptions);
if you want to create markers for the cities or countries you want,
var cities = "Atlanta, USA";
var geocoder= new google.maps.Geocoder();
$scope.markers = [];
var createMarker = function (info){
var marker = new google.maps.Marker({
map: $scope.map,
position: new google.maps.LatLng(info.lat(), info.lng())
});
}
geocoder.geocode( { 'address': cities }, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
newAddress = results[0].geometry.location;
$scope.map.setCenter(newAddress);
createMarker(newAddress)
}
});
Last but not least make sure you added the google maps api script before doing all this stuff,
<script type="text/javascript" src="https://maps.google.com/maps/api/js?sensor=false"> </script>
Here is the working plunker with this code, inside a bootstrap model,
http://embed.plnkr.co/VT7cO0L2ckSWG6g63TVG/preview
Reference
Hope this helps!
It was late to post but I have done this as solution. By this there is no need to add the google map script src in the head of the html or there is no chance of any error for google map src related errors. The script will be added automatically by the loadScript function. In angular it is needed to add new js src in partials rather than the head of main script. So I think this will be the best solution
I used this code chunk into my controller.
$scope.initialize = function() {
$scope.mapOptions = {
zoom: 8,
center: new google.maps.LatLng(22.649907498685803, 88.36255413913727)
};
$scope.map = new google.maps.Map(document.getElementById('googleMap'), $scope.mapOptions);
}
$scope.loadScript = function() {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'https://maps.google.com/maps/api/js?sensor=false&callback=initialize';
document.body.appendChild(script);
setTimeout(function() {
$scope.initialize();
}, 500);
}
setTimeout is there because some time is needed for google map src to be downloaded and be ready. & callback=initialize is needed because by this google map will be ready for a callback.The main problem was that the code google.maps.event.addDomListener(window, 'load', initialize) was not executing if I add the google map src in partial rather than the head of main index.html. But this setup works flawlessly.
And this chunk to the html
<div class="form-group col-lg-12" id="googleMap">
<center>Waiting for the map...</center>
</div>
Now place ng-init="loadScript()" anywhere in any outer div so that loadScript initializes before.

Google Maps with Meteor not working

For my project i need google maps api.
I just can serve the api via script tag, so i tried something like that.
my html:
<head>
<title>app</title>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"> </script>
</head>
<body>
{{> hello}}
</body>
<template name="hello">
<div id="map-canvas"/>
</template>
my js:
if (Meteor.isClient) {
var mapOptions = {
center: new google.maps.LatLng(-34.397, 150.644),
zoom: 8,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map-canvas"),
mapOptions);
}
if (Meteor.isServer) {
Meteor.startup(function () {
// code to run on server at startup
});
}
On execution the error is:
Uncaught ReferenceError: google is not defined
How can i get this working?
The meteor script is typically run before the google maps API is loaded so its best to put your code in a Template.rendered : see Template.rendered at the meteor docs
e.g If you have a template
<template name="maps">
<div id="map-canvas"></div>
</template>
Your js would be:
Template.maps.rendered = function() {
var mapOptions = {
center: new google.maps.LatLng(-34.397, 150.644),
zoom: 8,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map-canvas"),
mapOptions);
}
It really depends more on what your template looks like. The rendered callback will re run everytime the template changes reactively too. So if you find it re-renders you might have to use a Session hash to check it only sets the maps center/settings only once.
Another option would be to put your map centering code in Meteor.startup(function() { ... });, but again this depends on your template structure as the map needs to be visible on the first template and not one another page (as the div element wont be on the screen)

Binding a google map instance to an html element nested within another element

I'm using JQuery to locate a DOM Element that I want to bind a google map instance to:
var GoogleMap;
var ListOfMarkers = new Array();
function DisplayMap(GoogleMapPlaceHolder) {
var MapCenterPoint = new google.maps.LatLng(39.28629188966093, -76.60345947265624);
var MapOptions = {
zoom: 8,
center: MapCenterPoint,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
//Create a new GoogleMap instance
var MapDiv = $('#' + GoogleMapPlaceHolder)[0];
GoogleMap = new google.maps.Map(MapDiv, MapOptions);
}
HTML:
<body onload="DisplayMap('DivMap')">
<form id="form1" runat="server">
<div>
<div id="DivMap"></div>
</div>
</form>
</body>
Edit: I am referencing the Google Maps Javascript(not displayed).
When the page renders, the map will not display. Why is the code failing to display the map?
My first thought is that Google Maps fills the containing space without pushing its CSS height attribute. Do you have styles defining the height of #DivMap? If not, block level elements like divs will be generated by a browser with a 0px calculated height value.

Google Maps Api v3 - getBounds is undefined

I'm switching from v2 to v3 google maps api and got a problem with gMap.getBounds() function.
I need to get the bounds of my map after its initialization.
Here is my javascript code:
var gMap;
$(document).ready(
function() {
var latlng = new google.maps.LatLng(55.755327, 37.622166);
var myOptions = {
zoom: 12,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
gMap = new google.maps.Map(document.getElementById("GoogleMapControl"), myOptions);
alert(gMap.getBounds());
}
);
So now it alerts me that gMap.getBounds() is undefined.
I've tried to get getBounds values in click event and it works fine for me, but I cannot get the same results in load map event.
Also getBounds works fine while document is loading in Google Maps API v2, but it fails in V3.
Could you please help me to solve this problem?
In the early days of the v3 API, the getBounds() method required the map tiles to have finished loading for it to return correct results. However now it seems that you can listen to bounds_changed event, which is fired even before the tilesloaded event:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<title>Google Maps v3 - getBounds is undefined</title>
<script src="http://maps.google.com/maps/api/js?sensor=false"
type="text/javascript"></script>
</head>
<body>
<div id="map" style="width: 500px; height: 350px;"></div>
<script type="text/javascript">
var map = new google.maps.Map(document.getElementById("map"), {
zoom: 12,
center: new google.maps.LatLng(55.755327, 37.622166),
mapTypeId: google.maps.MapTypeId.ROADMAP
});
google.maps.event.addListener(map, 'bounds_changed', function() {
alert(map.getBounds());
});
</script>
</body>
</html>
It should be working, atleast according to the documentation for getBounds(). Nevertheless:
var gMap;
$(document).ready(function() {
var latlng = new google.maps.LatLng(55.755327, 37.622166);
var myOptions = {
zoom: 12,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
gMap = new google.maps.Map(document.getElementById("GoogleMapControl"), myOptions);
google.maps.event.addListenerOnce(gMap, 'idle', function(){
alert(this.getBounds());
});
});
See it working here.
I was saying Salman's solution is better because the idle event is called earlier than the tilesloaded one, since it waits for all the tiles to be loaded. But on a closer look, it seems bounds_changed is called even earlier and it also makes more sense, since you're looking for the bounds, right? :)
So my solution would be:
google.maps.event.addListenerOnce(gMap, 'bounds_changed', function(){
alert(this.getBounds());
});
In other comments here, it's adviced to use the "bounds_changed" event over "idle", which I agree with. Certainly under IE8 which triggers "idle" before "bounds_changed" on my dev machine at least, leaving me with a reference to null on getBounds.
The "bounds_changed" event however, will be triggered continuously when you'll drag the map. Therefor, if you want to use this event to start loading markers, it will be heavy on your webserver.
My multi browser solution to this problem:
google.maps.event.addListenerOnce(gmap, "bounds_changed", function(){
loadMyMarkers();
google.maps.event.addListener(gmap, "idle", loadMyMarkers);
});
Well, i'm not sure if i'm too late, but here's my solution using gmaps.js plugin:
map = new GMaps({...});
// bounds loaded? if not try again after 0.5 sec
var check_bounds = function(){
var ok = true;
if (map.getBounds() === undefined)
ok = false;
if (! ok)
setTimeout(check_bounds, 500);
else {
//ok to query bounds here
var bounds = map.getBounds();
}
}
//call it
check_bounds();
Adding an answer for 2021.
Map.getBounds() may return undefined initially. The preferred workaround to this is to use the bounds_changed event. Typically, an undefined value will only happen in the initialization of the map and never again.
const map = new google.maps.Map(document.getElementById("map"), {
zoom: 12,
center: new google.maps.LatLng(55.755327, 37.622166),
mapTypeId: google.maps.MapTypeId.ROADMAP
});
map.addEventListener('bounds_changed', () => {
console.log(map.getBounds());
});
https://developers.google.com/maps/documentation/javascript/reference/map#Map.bounds_changed

Categories