I’m trying to increase page speed by loading my Google Maps two seconds after page load. While doing so, I keep on getting “Cannot read property ‘extend’ of undefined”. I know there is some asynchronous loading going on but I’m not sure how to get it in proper order to get this map to load 2 seconds after the page is done. Any help is greatly appreciated.
Page Code:
<div id="mapCont"></div> <script defer type='text/javascript' src='/js/maps.js'></script>
maps.js
$(window).bind("load", function() { $.getScript('https://maps.googleapis.com/maps/api/js?key=key', function() { setTimeout(function(){ function doMap(callback) { $("#mapCont").html('<div id="mapInfoManual" class="searchMap mb5"></div>'); callback(); } doMap(function() { initialize(); var map = null; var markers = []; var openedInfoWindow =""; var bounds = new google.maps.LatLngBounds(); function initialize() { var mapOptions = { zoom: 8, center: new google.maps.LatLng(64.85599578876611, -147.83363628361917), mapTypeId: google.maps.MapTypeId.ROADMAP, mapTypeControl: true, mapTypeControlOptions: { style: google.maps.MapTypeControlStyle.DROPDOWN_MENU }, zoomControl: true, zoomControlOptions: { style: google.maps.ZoomControlStyle.SMALL } }; map = new google.maps.Map(document.getElementById("mapInfoManual"), mapOptions); google.maps.event.addListener(map, 'zoom_changed', function() { zoomChangeBoundsListener = google.maps.event.addListener(map, 'bounds_changed', function(event) { if (this.getZoom() > 20) // Change max/min zoom here this.setZoom(18); google.maps.event.removeListener(zoomChangeBoundsListener); }); }); addMarker(); } function addMarker() { var bounds = new google.maps.LatLngBounds(); for (i = 0; i < markersArray.length; i++) { CodeAddress(markersArray[i]); } } // Address To Marker function CodeAddress(markerEntry) { var mytitle = (markersArray[i]['title']); var myaddress = (markersArray[i]['address']); var linkid = (markersArray[i]['linkid']); var linkurl = (markersArray[i]['linkurl']); var image = { url: '/images/MapPin.png', }; var lat = markerEntry['lat']; var long = markerEntry['long']; // var myLatLng = {lat: markerEntry['lat'], lng: markerEntry['long']}; var myLatlng = new google.maps.LatLng(parseFloat(lat),parseFloat(long)); var marker = new google.maps.Marker({ position: myLatlng, map: map, icon: image }); bounds.extend(marker.getPosition()); var infoWindowContent = "<div class='cityMapInfoPop'><span style='font-weight:700;'>"+ mytitle +"</span><br /><br />" + myaddress + "<br /><br /><a href='/center/" + linkurl + "/'>More Details</a></div>"; openInfoWindow(marker, infoWindowContent); markers.push(marker); map.fitBounds(bounds); } //Info Window function openInfoWindow(marker, infoWindowContent) { var infowindow = new google.maps.InfoWindow({ content: '<div class="cityMapInfoPop">' + infoWindowContent + '</div>' }); google.maps.event.addListener(marker, 'click', function() { if (openedInfoWindow != "") { openedInfoWindow.close(); } infowindow.open(map, marker); openedInfoWindow = infowindow; }); } }); }, 2000); }); });
Advertisement
Answer
The initial https://maps.googleapis.com/maps/api/js?key=key
loads additional scripts that are not being captured by your implementation. The package, https://www.npmjs.com/package/@googlemaps/js-api-loader, enables the following pattern and is probably what you want:
import { Loader } from '@googlemaps/js-api-loader'; const loader = new Loader({ apiKey: "", version: "weekly", libraries: ["places"] }); loader .load() .then(() => { doMap(); initialize(); }) .catch(e => { // do something });
Alternative(use callback) if you want JQuery and your existing pattern:
window.callback = () => { doMap(); initialize(); }; $(window).bind("load", function() { $.getScript('https://maps.googleapis.com/maps/api/js?key=key&callback=callback', () => {}); // do nothing here
Also related: https://developers.google.com/maps/documentation/javascript/examples/programmatic-load-button