-1

I am printing a page containing google maps API v3 map from within an iframe. I implemented the following code to make sure the page has loaded fully before printing the iframe.

/**
*    Auto print the page once the full document has finished loading
*/
function checkDocumentStateChange(documentElement) {

  var document = documentElement;
  console.log('Document ReadyState: ' + document.readyState);
  document.onreadystatechange = function () {

     console.log('Document ReadyState: ' + document.readyState);

     if (document.readyState === 'complete') {
        console.log("Document fully loaded!");
        console.log("Printing report from within iframe");
        setTimeout(function () {
           window.print();

           var requestOrigin = '@viewModel.RequestOrigin';
           if(!!requestOrigin) {
              // Tell the parent window that the print has occurred, so it can prepare to cleanup and remove this iframe
              console.log("Send postMessage: secret");
              parent.postMessage('secret', requestOrigin);
           }
        }, 500);

     }
  }

}

However, even with with a 500 millisecond delay AFTER document.readystate === 'complete' is true, often times the page prints with a grey/blank google maps canvas, with no images.

If I hit window.print() again without reloading the page, then it prints the iframe with all map images as expected. So the document ready state is lying.

What can I do to solve this besides increasing the delay even longer (which I don't want to do as it punishes people to wait long when the content loads quickly)

TetraDev
  • 16,074
  • 6
  • 60
  • 61
  • 3
    gmaps adds content after the document is ready, that content loading doesn't affect the readyState – dandavis May 23 '17 at 21:18
  • If you control the iframe, you can set a CORS header on it. – Daniel Beck May 23 '17 at 21:27
  • @dandavis thats what I thought. – TetraDev May 23 '17 at 21:27
  • @daniel beck I'll take a look at that and see If i can use any answers. I do control the iframe. I have been using `.postmessage` to communicate across domain. How could the cors header help in this situation? – TetraDev May 23 '17 at 21:27
  • If you're already using postMessage, then you already have CORS set up (or else your iframes are on the same domain). Either way -- you can use postMessage to send the notification that the google maps event fired. – Daniel Beck May 23 '17 at 22:10
  • Thanks, with the help of the other question, I got it working. This did it for me `google.maps.event.addListener(map, 'idle', function () { //set flag to check for here });` – TetraDev May 24 '17 at 20:01

1 Answers1

0

The answer was simple, just use Google Maps event handler api. In my tests, it fires bounds_changed, then tilesloaded and finally idle in that order. So I just set a flag to check for later into the idle event and it works perfectly.

      // this callback runs when the mapobject is created and rendered (because bound_changed fires at initialization), only fire it once to prevent unnecessary callbacks during panning/zooming
      google.maps.event.addListenerOnce(map, 'bounds_changed', function () {
         // do something only the first time the map is loaded
         console.log("Google Maps event: bounds_changed");
      });

      // this callback runs when the mapobject is shown for the first time and all tiles are loaded
      google.maps.event.addListener(map, 'tilesloaded', function () {
         console.log("Google Maps event: tilesloaded");
      });

      // this callback runs when the mapobject is fully created and rendered and the map is completely idle
      google.maps.event.addListener(map, 'idle', function () {
         // do something only the first time the map is loaded
         console.log("Google Maps event: idle");
         mapReadyToPrint = true;
         console.log("mapReadyToPrint:", mapReadyToPrint);
      });
TetraDev
  • 16,074
  • 6
  • 60
  • 61