Release/2.11/GoogleMaps37

OpenLayers 2.11 and Google Maps API version 3.7

[Written the 25th of May, 2012]

OpenLayers 2.11 does not work with Google Maps API version 3.7 (the current "frozen" version) and higher -- a "Map Data" popup gets displayed on each map move. The issue has been fixed in the 2.12 and master branches ( https://github.com/openlayers/openlayers/pull/472). To use OpenLayers 2.11 with Google Maps API 3.7 you need to "hot-patch" OpenLayers. This is done by inserting the following JavaScript code into your page. This code must be evaluated after OpenLayers itself, so it must come after the OpenLayers script tag in the page.

OpenLayers.Layer.Google.v3.repositionMapElements = function() {
    // This is the first time any Google layer in this mapObject has been
    // made visible.  The mapObject needs to know the container size.
    google.maps.event.trigger(this.mapObject, "resize");
    
    var div = this.mapObject.getDiv().firstChild;
    if (!div || div.childNodes.length < 3) {
        this.repositionTimer = window.setTimeout(
            OpenLayers.Function.bind(this.repositionMapElements, this),
            250
        );
        return false;
    }

    var cache = OpenLayers.Layer.Google.cache[this.map.id];
    var container = this.map.viewPortDiv;
    
    // move the ToS and branding stuff up to the container div
    // depends on value of zIndex, which is not robust
    for (var i=div.children.length-1; i>=0; --i) {
        if (div.children[i].style.zIndex == 1000001) {
            var termsOfUse = div.children[i];
            container.appendChild(termsOfUse);
            termsOfUse.style.zIndex = "1100";
            termsOfUse.style.bottom = "";
            termsOfUse.className = "olLayerGoogleCopyright olLayerGoogleV3";
            termsOfUse.style.display = "";
            cache.termsOfUse = termsOfUse;
        }
        if (div.children[i].style.zIndex == 1000000) {
            var poweredBy = div.children[i];
            container.appendChild(poweredBy);
            poweredBy.style.zIndex = "1100";
            poweredBy.style.bottom = "";
            poweredBy.className = "olLayerGooglePoweredBy olLayerGoogleV3 gmnoprint";
            poweredBy.style.display = "";
            cache.poweredBy = poweredBy;
        }
        if (div.children[i].style.zIndex == 10000002) {
            container.appendChild(div.children[i]);
        }
    }

    this.setGMapVisibility(this.visibility);
};

For example, here's what the google-v3.html example page looks like with the patch:

<!DOCTYPE html>
<html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
    <meta name="apple-mobile-web-app-capable" content="yes">
        <title>OpenLayers Google (v3) Layer Example</title>
        <link rel="stylesheet" href="../theme/default/style.css" type="text/css">
        <link rel="stylesheet" href="../theme/default/google.css" type="text/css">
        <link rel="stylesheet" href="style.css" type="text/css">
        <script src="http://maps.google.com/maps/api/js?v=3.5&amp;sensor=false"></script>
        <script src="../lib/OpenLayers.js"></script>
        <script>
        OpenLayers.Layer.Google.v3.repositionMapElements = function() {
            // This is the first time any Google layer in this mapObject has been
            // made visible.  The mapObject needs to know the container size.
            google.maps.event.trigger(this.mapObject, "resize");
            
            var div = this.mapObject.getDiv().firstChild;
            if (!div || div.childNodes.length < 3) {
                this.repositionTimer = window.setTimeout(
                    OpenLayers.Function.bind(this.repositionMapElements, this),
                    250
                );
                return false;
            }

            var cache = OpenLayers.Layer.Google.cache[this.map.id];
            var container = this.map.viewPortDiv;
            
            // move the ToS and branding stuff up to the container div
            // depends on value of zIndex, which is not robust
            for (var i=div.children.length-1; i>=0; --i) {
                if (div.children[i].style.zIndex == 1000001) {
                    var termsOfUse = div.children[i];
                    container.appendChild(termsOfUse);
                    termsOfUse.style.zIndex = "1100";
                    termsOfUse.style.bottom = "";
                    termsOfUse.className = "olLayerGoogleCopyright olLayerGoogleV3";
                    termsOfUse.style.display = "";
                    cache.termsOfUse = termsOfUse;
                }
                if (div.children[i].style.zIndex == 1000000) {
                    var poweredBy = div.children[i];
                    container.appendChild(poweredBy);
                    poweredBy.style.zIndex = "1100";
                    poweredBy.style.bottom = "";
                    poweredBy.className = "olLayerGooglePoweredBy olLayerGoogleV3 gmnoprint";
                    poweredBy.style.display = "";
                    cache.poweredBy = poweredBy;
                }
                if (div.children[i].style.zIndex == 10000002) {
                    container.appendChild(div.children[i]);
                }
            }

            this.setGMapVisibility(this.visibility);
        };
        </script>
        <script src="google-v3.js"></script>
    </head>
    <body onload="init()">
        <h1 id="title">Google (v3) Layer Example</h1>
        <div id="tags">
            Google, api key, apikey
        </div>
        <p id="shortdesc">
            Demonstrate use the Google Maps v3 API.
        </p>
        <div id="map" class="smallmap"></div>
        <div id="docs">
            <p><input id="animate" type="checkbox" checked="checked">Animated
                zoom (if supported by GMaps on your device)</input></p>
            <p>
                If you use the Google Maps v3 API with a Google layer, you don't
                need to include an API key.  This layer only works in the 
                spherical mercator projection.  See the 
                <a href="google-v3.js" target="_blank">google-v3.js source</a> 
                to see how this is done.
            <p>
                In order to position the Google attribution div in the default 
                location, you must include the extra theme/default/google.css 
                stylesheet.
            </p>
        </div>
    </body>
</html>