[OpenLayers-Commits] r12070 - in trunk/openlayers: examples lib/OpenLayers/Layer lib/OpenLayers/Tile tests/Layer theme/default

commits-20090109 at openlayers.org commits-20090109 at openlayers.org
Tue Jun 7 19:49:36 EDT 2011


Author: ahocevar
Date: 2011-06-07 16:49:35 -0700 (Tue, 07 Jun 2011)
New Revision: 12070

Modified:
   trunk/openlayers/examples/google-ng.html
   trunk/openlayers/lib/OpenLayers/Layer/GoogleNG.js
   trunk/openlayers/lib/OpenLayers/Tile/Google.js
   trunk/openlayers/tests/Layer/GoogleNG.html
   trunk/openlayers/theme/default/style.css
Log:
making attribution as Terms of Service compliant as we possibly can. p=bartvde (closes #3330)

Modified: trunk/openlayers/examples/google-ng.html
===================================================================
--- trunk/openlayers/examples/google-ng.html	2011-06-07 21:41:07 UTC (rev 12069)
+++ trunk/openlayers/examples/google-ng.html	2011-06-07 23:49:35 UTC (rev 12070)
@@ -14,6 +14,7 @@
             right: inherit;
             bottom: 3px; 
             line-height: 11px;
+            font-family: Arial, sans-serif;
         }
         </style>
         <script src="http://maps.google.com/maps/api/js?v=3.5&amp;sensor=false"></script>

Modified: trunk/openlayers/lib/OpenLayers/Layer/GoogleNG.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Layer/GoogleNG.js	2011-06-07 21:41:07 UTC (rev 12069)
+++ trunk/openlayers/lib/OpenLayers/Layer/GoogleNG.js	2011-06-07 23:49:35 UTC (rev 12070)
@@ -10,10 +10,7 @@
 
 /** 
  * Class: OpenLayers.Layer.GoogleNG
- * Google layer using <OpenLayers.Tile.Google> tiles. Note: Terms of Service
- * compliant use requires the map to be configured with an
- * <OpenLayers.Control.Attribution> control and the attribution placed on or
- * near the map.
+ * Google layer using <OpenLayers.Tile.Google> tiles.
  * 
  * Inherits from:
  *  - <OpenLayers.Layer.XYZ>
@@ -32,13 +29,11 @@
      * {String}
      */
     attributionTemplate: '<span class="olGoogleAttribution ${mapType}">' +
-         '<div><a target="_blank" href="http://maps.google.com/maps?' +
+         '<div><a title="Click to see this area on Google Maps" ' + 
+         'target="_blank" href="http://maps.google.com/maps?' +
          'll=${center}&z=${zoom}&t=${t}"><img width="62" height="24" ' +
          'src="http://maps.gstatic.com/mapfiles/google_white.png"/></a>' +
-         '</div><a style="white-space: nowrap" target="_blank" ' +
-         'href="http://maps.google.com/maps/api/staticmap?sensor=true' +
-         '&center=${center}&zoom=${zoom}&size=${size}&maptype=${mapType}">' +
-         'Map data</a> - <a style="white-space: nowrap" target="_blank" ' +
+         '</div>${mapData}<a style="white-space: nowrap" target="_blank" ' +
          'href="http://www.google.com/help/terms_maps.html">' +
          'Terms of Use</a></span>',
     
@@ -55,13 +50,6 @@
     },
     
     /**
-     * Property: mapObject
-     * {google.maps.Map} Shared GMaps instance - will be set on the prototype
-     * upon instantiation of the 1st GoogleNG layer
-     */
-    mapObject: null,
-
-    /**
      * APIProperty: type
      * {google.maps.MapTypeId} See
      * http://code.google.com/apis/maps/documentation/javascript/reference.html#MapTypeId
@@ -71,7 +59,10 @@
     /**
      * Constructor: OpenLayers.Layer.GoogleNG
      * Create a new GoogleNG layer. Requires the GMaps v3 JavaScript API script
-     * included in the html document.
+     * (http://maps.google.com/maps/api/js?v=3.5&amp;sensor=false) loaded in
+     * the html document. Note: Terms of Service compliant use requires the map
+     * to be configured with an <OpenLayers.Control.Attribution> control and
+     * the attribution placed on the map.
      *
      * Example:
      * (code)
@@ -103,15 +94,15 @@
         OpenLayers.Layer.XYZ.prototype.initialize.apply(this, newArgs);
         
         this.options.numZoomLevels = options.numZoomLevels;
-        if (!this.mapObject) {
-            OpenLayers.Layer.GoogleNG.prototype.mapObject =
+        if (!OpenLayers.Layer.GoogleNG.mapObject) {
+            OpenLayers.Layer.GoogleNG.mapObject =
                 new google.maps.Map(document.createElement("div"));
         }
-        if (this.mapObject.mapTypes[this.type]) {
+        if (OpenLayers.Layer.GoogleNG.mapObject.mapTypes[this.type]) {
             this.initLayer();
         } else {
             google.maps.event.addListenerOnce(
-                this.mapObject, 
+                OpenLayers.Layer.GoogleNG.mapObject, 
                 "idle", 
                 OpenLayers.Function.bind(this.initLayer, this)
             );
@@ -124,7 +115,7 @@
      * Sets layer properties according to the metadata provided by the API
      */
     initLayer: function() {
-        var mapType = this.mapObject.mapTypes[this.type];
+        var mapType = OpenLayers.Layer.GoogleNG.mapObject.mapTypes[this.type];
         if (!this.name) {
             this.setName("Google " + mapType.name);
         }
@@ -171,8 +162,31 @@
     /**
      * Method: updateAttribution
      * Updates the attribution using the <attributionTemplate>
+     *
+     * Parameters:
+     * copyrights - {Object} Object with "m", "k", "h" and "p" properties (see
+     *     <mapTypes>), each holding an array of copyrights.
      */
-    updateAttribution: function() {
+    updateAttribution: function(copyrights) {
+        var myCopyrights;
+        if (this.type == google.maps.MapTypeId.HYBRID) {
+            // the Copyright Service returns "k" and "m" copyrights for the
+            // HYBRID layer type.
+            var candidates = [].concat(
+                copyrights["h"], copyrights["k"], copyrights["m"]
+            );
+            myCopyrights = [];
+            for (var i=candidates.length-1; i>=0; --i) {
+                if (OpenLayers.Util.indexOf(candidates, myCopyrights) == -1) {
+                    myCopyrights.push(candidates[i]);
+                }
+            }
+        } else {
+            myCopyrights = copyrights[this.mapTypes[this.type]];
+        }
+        var mapData = myCopyrights.length == 0 ? "" :
+            "Map Data &copy;" + new Date().getFullYear() + " " +
+            myCopyrights.join(", ") + " - ";
         var center = this.map.getCenter();
         center && center.transform(
             this.map.getProjectionObject(),
@@ -180,23 +194,23 @@
         );
         var size = this.map.getSize();
         this.attribution = OpenLayers.String.format(this.attributionTemplate, {
-            center: center ? center.lat + "," + center.lon : "",
+            t: this.mapTypes[this.type],
             zoom: this.map.getZoom(),
-            size: size.w + "x" + size.h,
-            t: this.mapTypes[this.type],
-            mapType: this.type
+            center: center.lat + "," + center.lon,
+            mapType: this.type,
+            mapData: mapData
         });
         this.map && this.map.events.triggerEvent("changelayer", {layer: this});
     },
-
+    
     /**
      * Method: setMap
      */
     setMap: function() {
         OpenLayers.Layer.XYZ.prototype.setMap.apply(this, arguments);
-
-        this.updateAttribution();
-        this.map.events.register("moveend", this, this.updateAttribution);
+        this.events.register("moveend", this,
+            OpenLayers.Layer.GoogleNG.loadCopyrights
+        );
     },
     
     /**
@@ -204,7 +218,9 @@
      */
     removeMap: function() {
         OpenLayers.Layer.XYZ.prototype.removeMap.apply(this, arguments);
-        this.map.events.unregister("moveend", this, this.updateAttribution);
+        this.events.unregister("moveend", this,
+            OpenLayers.Layer.GoogleNG.loadCopyrights
+        );
     },
         
     /**
@@ -227,14 +243,86 @@
         return obj;
     },
     
-    /**
-     * Method: destroy
-     */
-    destroy: function() {
-        this.map &&
-            this.map.events.unregister("moveend", this, this.updateAttribution);
-        OpenLayers.Layer.XYZ.prototype.destroy.apply(this, arguments);
-    },
-    
     CLASS_NAME: "OpenLayers.Layer.GoogleNG"
-});
\ No newline at end of file
+});
+
+/**
+ * Property: mapObject
+ * {google.maps.Map} Shared GMaps instance - will be set upon instantiation of
+ * the 1st GoogleNG layer
+ */
+OpenLayers.Layer.GoogleNG.mapObject = null;
+
+/**
+ * Function: loadCopyrights
+ * Using the Google Maps Copyright Service mode (see
+ * http://mapki.com/wiki/Google_Map_Parameters#Misc) to get the attribution for
+ * the current map extent. Will be called by each GoogleNG layer instance on
+ * moveend. 
+ */
+OpenLayers.Layer.GoogleNG.loadCopyrights = function() {
+    var me = OpenLayers.Layer.GoogleNG.loadCopyrights;
+    if (me.numLoadingScripts == undefined) {
+        me.loadingScripts = [];
+        me.numLoadingScripts = 0;
+        me.copyrights = {"m": [], "k": [], "h": [], "p": []};
+        
+        // store window scope functions before overwriting them
+        me.origGAddCopyright = window.GAddCopyright;
+        me.origGVerify = window.GVerify;
+        me.origGAppFeatures = window.GAppFeatures;
+        
+        // defining window scope functions called by the script that the
+        // Copyright Service returns
+        window.GAddCopyright = function() {
+            var copyright = arguments[7];
+            var category = me.copyrights[arguments[0]];
+            if (OpenLayers.Util.indexOf(category, copyright) == -1) {
+                copyright && category.push(copyright);
+            }
+        };
+        window.GVerify = OpenLayers.Function.True;
+        window.GAppFeatures = OpenLayers.Function.bind(function() {
+            me.numLoadingScripts--;
+            if (me.numLoadingScripts == 0) {
+                var script;
+                for (var i=me.loadingScripts.length-1; i>=0; --i) {
+                    script = me.loadingScripts[i][0];
+                    me.loadingScripts[i][1].updateAttribution(me.copyrights);
+                    script.parentNode.removeChild(script);
+                }
+                
+                // restore original functions
+                window.GAddCopyright = me.origGAddCopyright;
+                delete me.origGAddCopyright;
+                window.GVerify = me.origGVerify;
+                delete me.origGVerify;
+                window.GAppFeatures = me.origGAppFeatures;
+                delete me.origGAppFeatures;
+                
+                delete me.loadingScripts;
+                delete me.numLoadingScripts;
+                delete me.copyrights;
+            }
+        }, this);
+    }
+    var mapProj = this.map.getProjectionObject();
+    var llProj = new OpenLayers.Projection("EPSG:4326");
+    var center = this.map.getCenter().transform(mapProj, llProj);
+    var extent = this.map.getExtent().transform(mapProj, llProj);
+    var params = {
+        spn: extent.getHeight() + "," + extent.getWidth(),
+        z: this.map.getZoom(),
+        t: this.mapTypes[this.type],
+        vp: center.lat + "," + center.lon
+    };
+    var url = "http://maps.google.com/maps?" +
+        OpenLayers.Util.getParameterString(params);
+    var script = document.createElement("script");
+    script.type = "text/javascript";
+    script.src = url;
+    me.numLoadingScripts++;
+    me.loadingScripts.push([script, this]);
+    document.getElementsByTagName("head")[0].appendChild(script);
+};
+

Modified: trunk/openlayers/lib/OpenLayers/Tile/Google.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Tile/Google.js	2011-06-07 21:41:07 UTC (rev 12069)
+++ trunk/openlayers/lib/OpenLayers/Tile/Google.js	2011-06-07 23:49:35 UTC (rev 12070)
@@ -86,7 +86,9 @@
      * {Boolean} Always returns true.
      */
     draw: function() {
-        var layerType = this.layer.mapObject.mapTypes[this.layer.type];
+        var layerType = OpenLayers.Layer.GoogleNG.mapObject.mapTypes[
+            this.layer.type
+        ];
         if (layerType && OpenLayers.Tile.prototype.draw.apply(this, arguments)) {
             var xyz = this.layer.getXYZ(this.bounds);
             var point = new google.maps.Point(xyz.x, xyz.y);
@@ -143,7 +145,9 @@
         if (this.node) {
             this.node.parentNode &&
                 this.node.parentNode.removeChild(this.node);
-            this.layer.mapObject.mapTypes[this.layer.type].releaseTile(this.node);
+            OpenLayers.Layer.GoogleNG.mapObject.mapTypes[
+                this.layer.type
+            ].releaseTile(this.node);
         }
     },
     

Modified: trunk/openlayers/tests/Layer/GoogleNG.html
===================================================================
--- trunk/openlayers/tests/Layer/GoogleNG.html	2011-06-07 21:41:07 UTC (rev 12069)
+++ trunk/openlayers/tests/Layer/GoogleNG.html	2011-06-07 23:49:35 UTC (rev 12070)
@@ -34,11 +34,11 @@
             numZoomLevels: 24,
             initLayer: function() {
                 log[layer2.id] = true;
-                var origMinZoom = layer2.mapObject.mapTypes[layer2.type].minZoom;
+                var origMinZoom = OpenLayers.Layer.GoogleNG.mapObject.mapTypes[layer2.type].minZoom;
                 // pretend the API reports a minZoom of 1
-                layer2.mapObject.mapTypes[layer2.type].minZoom = 1;
+                OpenLayers.Layer.GoogleNG.mapObject.mapTypes[layer2.type].minZoom = 1;
                 OpenLayers.Layer.GoogleNG.prototype.initLayer.apply(this, arguments);
-                layer2.mapObject.mapTypes[layer2.type].minZoom = origMinZoom;
+                OpenLayers.Layer.GoogleNG.mapObject.mapTypes[layer2.type].minZoom = origMinZoom;
             }
         });
         map2.addLayer(layer2);
@@ -49,7 +49,7 @@
             t.eq(log[layer2.id], true, "initLayer called for 2nd layer");
             
             t.eq(layer.numZoomLevels, 10, "numZoomLevels from configuration takes precedence if lower");
-            t.eq(layer2.numZoomLevels, layer2.mapObject.mapTypes[layer2.type].maxZoom+1, "numZoomLevels from API takes precedence if lower");
+            t.eq(layer2.numZoomLevels, OpenLayers.Layer.GoogleNG.mapObject.mapTypes[layer2.type].maxZoom+1, "numZoomLevels from API takes precedence if lower");
 
             t.eq(layer.restrictedMinZoom, 2, "restrictedMinZoom from configuration takes precedence if higher");
             t.eq(layer2.restrictedMinZoom, 1, "restrictedMinZoom from API takes precedence if higher");
@@ -60,18 +60,25 @@
     }
     
     function test_attribution(t) {
-        t.plan(3);
+        t.plan(4);
         
         var log = [];
         map = new OpenLayers.Map("map");
-        layer = new OpenLayers.Layer.GoogleNG({type: google.maps.MapTypeId.HYBRID});
+        layer = new OpenLayers.Layer.GoogleNG({
+            type: google.maps.MapTypeId.HYBRID,
+            updateAttribution: function(copyrights) {
+                log.push(copyrights);
+                OpenLayers.Layer.GoogleNG.prototype.updateAttribution.apply(this, arguments);
+            }
+        });
         map.addLayer(layer);
-        map.zoomToMaxExtent();
+        map.setCenter(new OpenLayers.LonLat(16, 48).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject()), 5);
         
-        t.delay_call(1, function() {
-            t.ok(layer.attribution.indexOf('olGoogleAttribution hybrid') !== -1, "Attribution has the correct css class");
-            t.ok(layer.attribution.indexOf('?ll=0,0&z=0&t=h"') != -1, "maps.google.com link has correct parameters");
-            t.ok(layer.attribution.indexOf('&center=0,0&zoom=0&size=500x550&maptype=hybrid') != -1 , "Attribution has correct map data link");
+        t.delay_call(3, function() {
+            t.eq(log.length, 1, "updateAttribution was called once");
+            t.ok(log[0]["m"].length && log[0]["k"].length, "'m' and 'k' copyrights populated for hybrid layer");
+            t.ok(layer.attribution.indexOf('olGoogleAttribution hybrid') != -1, "Attribution has the correct css class");
+            t.ok(layer.attribution.indexOf('?ll=48,16&z=5&t=h"') != -1, "maps.google.com link has correct parameters");
             map.destroy();
         });
     }

Modified: trunk/openlayers/theme/default/style.css
===================================================================
--- trunk/openlayers/theme/default/style.css	2011-06-07 21:41:07 UTC (rev 12069)
+++ trunk/openlayers/theme/default/style.css	2011-06-07 23:49:35 UTC (rev 12070)
@@ -356,7 +356,7 @@
 }
 
 .olGoogleAttribution.hybrid, .olGoogleAttribution.satellite {
-    color: #DDD;
+    color: #EEE;
 }
 .olGoogleAttribution {
     color: #333;
@@ -365,7 +365,7 @@
     color: #77C;
 }
 span.olGoogleAttribution.hybrid a, span.olGoogleAttribution.satellite a {
-    color: white;
+    color: #EEE;
 }
 
 /**



More information about the Commits mailing list