loading GoogleMapsApi asnc: inheriting from google.maps.OverlayView() not working

682 views
Skip to first unread message

Bost

unread,
Apr 6, 2016, 11:24:21 AM4/6/16
to Google Maps JavaScript API v3
My app loads GoogleMapsApi asynchronously. A class inherits from google.maps.OverlayView():

function ProjectionHelperOverlay(map) {
    this.setMap(map);
    initializeSomeVariables;

}

ProjectionHelperOverlay.prototype = new google.maps.OverlayView();

When I run the app I got the error:

this.setMap(map) is not a  function.

When I load GoogleMapsApi synchronously the app works with no error.

Anyone experienced the same error?
Is there any solution?


Barry Hunter

unread,
Apr 6, 2016, 11:34:44 AM4/6/16
to google-maps-js-api-v3


ProjectionHelperOverlay.prototype = new google.maps.OverlayView();

That's not really correct. THat is creating the prototype as one 'instance' of OverlayView. (It runs the function, and stores the result - its is an object, but its not complete) 

Been a while since done inheritance, with the API, but something like this

ProjectionHelperOverlay.prototype = Object.create(google.maps.OverlayView.prototype);

See also

 

When I load GoogleMapsApi synchronously the app works with no error.


Sounds like your code is running before the API has been fully loaded. 

But its hard to guess, without seeing your code. 



 
Message has been deleted
Message has been deleted

Barry Hunter

unread,
Apr 7, 2016, 12:31:55 PM4/7/16
to google-maps-js-api-v3
Ah, ok,  wrong about inheritance. 

Anyway, still guess you must be calling that code before the Maps API has loaded. 


The new fuller code doesnt actully show the creation of ProjectionHelperOverlay, but the code still needs to run AFTER the map API loads. ie it should perhaps be in the initialize() function. 


... also seem to be mixed how loading the api, you have &callback=initMap - but no function by that name. 
ANd you call initialize via DOMContentLoaded

... you should stick with one method. As the api provides functionality for callback, should use that. ie &callback=initialize

so it should be after the API knows its loaded, and remove DOMContentLoaded listener. 




On 7 April 2016 at 17:18, 'Bost' via Google Maps JavaScript API v3 <google-map...@googlegroups.com> wrote:
 Hallo,
thanks for your quick response.
For inheritance I followed this article:
https://developers.google.com/maps/documentation/javascript/customoverlays?hl=de#initialize

They prefer this:
ProjectionHelperOverlay.prototype = new google.maps.OverlayView();

Not Object.create.

Here are the main parts of my code;

<!DOCTYPE html>
<html>    
<head>
        <script async defer type="text/javascript"        
        src="https://maps.google.com/maps/api/js?language=de&key=MyKey&callback=initMap">
        </script>
        <script type="text/javascript" src="lib/routeMain.js" ></script>
       <script type="text/javascript" src="other javascript files"></script>
       
</head>
<body>

</body>

</html>

File routeMain.js:
var map;
var markerMgr;

if (document.addEventListener) {
    document.addEventListener('DOMContentLoaded', function () {
       //called, when html and scripts are loaded.
        initialize();
    });

function initialize() {
     //loads the map
    var latlng = new google.maps.LatLng(51.31893, 9.49601); //Kassel, Germany
    var myOptions = {
        zoom: 7,
        center: latlng,
        mapTypeControl: true,
        mapTypeId: google.maps.MapTypeId.ROADMAP,
        scaleControl: true
    };
    map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);

--
You received this message because you are subscribed to the Google Groups "Google Maps JavaScript API v3" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-maps-js-a...@googlegroups.com.
To post to this group, send email to google-map...@googlegroups.com.
Visit this group at https://groups.google.com/group/google-maps-js-api-v3.
For more options, visit https://groups.google.com/d/optout.

Bost

unread,
Apr 7, 2016, 12:54:56 PM4/7/16
to Google Maps JavaScript API v3
Hallo,
thanks for your quick response.
For inheritance I followed this article:
https://developers.google.com/maps/documentation/javascript/customoverlays?hl=de#initialize

They prefer this:
ProjectionHelperOverlay.prototype = new google.maps.OverlayView();

Not Object.create.

Here are the main parts of my code;

<!DOCTYPE html>
<html>    
<head>
        <script async defer type="text/javascript"        
        src="https://maps.google.com/maps/api/js?language=de&key=MyKey&callback=initMap">
        </script>
        <script type="text/javascript" src="lib/routeMain.js" ></script>
        <script type="text/javascript" src="lib/markermanager.js" ></script>


       <script type="text/javascript" src="other javascript files"></script>
       
</head>
<body>

</body>

</html>

File routeMain.js:
var map;
var markerMgr;

function initMap(){
     //indicates that Google Maps Api is loaded
     //this event happens before event  DOMContentLoaded happened

}

if (document.addEventListener) {
    document.addEventListener('DOMContentLoaded', function () {
       //called, when html and scripts are loaded.
        initialize();
    });

function initialize() {
     //loads the map
    var latlng = new google.maps.LatLng(51.31893, 9.49601); //Kassel, Germany
    var myOptions = {
        zoom: 7,
        center: latlng,
        mapTypeControl: true,
        mapTypeId: google.maps.MapTypeId.ROADMAP,
        scaleControl: true
    };
    map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
    markerMgr = new MarkerManager(map);


}

File MarkerManager.js:

function MarkerManager(map, opt_opts) {
 var me = this;
  me.map_ = map;
me.projectionHelper_ = new ProjectionHelperOverlay(map);
    google.maps.event.addListener(me.projectionHelper_, 'ready', function () {
        me.projection_ = this.getProjection();
        me.initialize(map, opt_opts);
    });

function ProjectionHelperOverlay(map) {
    this.setMap(map); //method of google.maps.OverlayView
    this._map = map;
    this._zoom = -1;
    this._X0 =
    this._Y0 =
    this._X1 =
    this._Y1 = -1;
}
// ProjectionHelperOverlay inherits from google.maps.OverlayView
ProjectionHelperOverlay.prototype = new google.maps.OverlayView();

/**
 * Draw function only triggers a ready event for
 * MarkerManager to know projection can proceed to
 * initialize.
 */
ProjectionHelperOverlay.prototype.draw = function () {
    if (!this.ready) {
        this.ready = true;
        google.maps.event.trigger(this, 'ready');
    }
};
}
When the app is loaded asynchronously I got the Error in ProjectionHelperOverlay(map)
this.setMap is not a function.
When stepping slowly with the debugger, sometimes the app works correctly. So I assume there will be a timing problem.

When loading synchronously the app worked correctly.

------------------------------------------------------------------------------------------------------------------


Am Mittwoch, 6. April 2016 17:34:44 UTC+2 schrieb barryhunter:

Bost

unread,
Apr 7, 2016, 1:04:38 PM4/7/16
to Google Maps JavaScript API v3
This comment was posted by accident; it was not complete. See my next comment.
Sorry.
To unsubscribe from this group and stop receiving emails from it, send an email to google-maps-js-api-v3+unsub...@googlegroups.com.

Bost

unread,
Apr 9, 2016, 8:13:55 AM4/9/16
to Google Maps JavaScript API v3
Hallo,
I solved this issue.
The script markermanager.js depends on the GoogleMapsApi, which is loaded asynchronously with the attribute defer. That means, that it is executed, when the page has finished parsing. markermanager.js  is fetched and executed immediately, before the browser continues parsing the page.
Adding the defer attribute to loading markermanager.js solved this issue.

Replace

<script type="text/javascript" src="lib/markermanager.js" ></script>
by
<script defer type="text/javascript" src="lib/markermanager.js" ></script>

Bost

unread,
Apr 29, 2016, 1:31:52 PM4/29/16
to Google Maps JavaScript API v3
My last comment was a rather hasty one. The script worked on an old, slow laptop. I t did not work on a newer, faster one.
But now the issue is solved.
The problem is,that the script markerManager depends on a fully loaded Goggle Maps Api. The attributes defer did not do the job. Defer means, that a script is loaded, after the page was parsed, but not,that other scripts are fully loaded.
The issue is solved by:
  • in the callback initMap: wait until Google Maps Api is fully loaded
  • initialyze the map and other scripts
  • load the dependent script markerManager dynamically.
function initMap() {
     
var timer = setInterval(function () {
       
//wait until document is fully loaded
       
if (/interactive|complete/.test(document.readyState)) {
            clearInterval
(timer);
           
if (!isOnline()) {
               
return;
           
}
            setMap
();
            initialize
();
            downloadScript
();
       
}
   
}, 10);
}
function downloadScript() {
   
var element = document.createElement("script");
    element
.type = 'text/javascript';
    element
.src = "lib/markermanager.js";
    document
.body.appendChild(element);
}


Reply all
Reply to author
Forward
0 new messages