/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for * full list of contributors). Published under the Clear BSD license. * See http://svn.openlayers.org/trunk/openlayers/license.txt for the * full text of the license. */ /** * @requires OpenLayers/Layer/XYZ.js * @requires OpenLayers/Tile/Google.js * @requires OpenLayers/Layer/SphericalMercator.js */ /** * Class: OpenLayers.Layer.GoogleNG * Google layer using tiles. * * Inherits from: * - */ OpenLayers.Layer.GoogleNG = OpenLayers.Class(OpenLayers.Layer.XYZ, { /** * Property: SUPPORTED_TRANSITIONS * {Array} An immutable (that means don't change it!) list of supported * transitionEffect values. This layer type supports none. */ SUPPORTED_TRANSITIONS: [], /** * Property: serverResolutions * {Array} the resolutions provided by the Google API. */ serverResolutions: [ 156543.03390625, 78271.516953125, 39135.7584765625, 19567.87923828125, 9783.939619140625, 4891.9698095703125, 2445.9849047851562, 1222.9924523925781, 611.4962261962891, 305.74811309814453, 152.87405654907226, 76.43702827453613, 38.218514137268066, 19.109257068634033, 9.554628534317017, 4.777314267158508, 2.388657133579254, 1.194328566789627, 0.5971642833948135, 0.29858214169740677, 0.14929107084870338, 0.07464553542435169, 0.037322767712175846 ], /** * Property: attributionTemplate * {String} */ attributionTemplate: '' + '
' + '
${mapData}' + 'Terms of Use
', /** * Property: mapTypes * {Object} mapping of {google.maps.MapTypeId} to the t param of * http://maps.google.com/maps? permalinks */ mapTypes: { "roadmap": "m", "satellite": "k", "hybrid": "h", "terrain": "p" }, /** * APIProperty: type * {google.maps.MapTypeId} See * http://code.google.com/apis/maps/documentation/javascript/reference.html#MapTypeId */ type: null, /** * Constructor: OpenLayers.Layer.GoogleNG * Create a new GoogleNG layer. Requires the GMaps v3 JavaScript API script * (http://maps.google.com/maps/api/js?v=3.5&sensor=false) loaded in * the html document. Note: Terms of Service compliant use requires the map * to be configured with an control and * the attribution placed on the map. * * Example: * (code) * var terrain = new OpenLayers.Layer.GoogleNG({ * name: "Google Terrain", * type: google.maps.MapTypeId.TERRAIN * }); * (end) * * Parameters: * options - {Object} Configuration properties for the layer. * * Required configuration properties: * type - {google.maps.MapTypeId} The layer identifier. See * http://code.google.com/apis/maps/documentation/javascript/reference.html#MapTypeId * for valid types. * * Any other documented layer properties can be provided in the config object. */ initialize: function(options) { options = OpenLayers.Util.applyDefaults({ sphericalMercator: true }, options); if (!options.type) { options.type = google.maps.MapTypeId.ROADMAP; } var newArgs = [options.name, null, options]; OpenLayers.Layer.XYZ.prototype.initialize.apply(this, newArgs); if (!OpenLayers.Layer.GoogleNG.mapObject) { OpenLayers.Layer.GoogleNG.mapObject = new google.maps.Map(document.createElement("div")); } if (OpenLayers.Layer.GoogleNG.mapObject.mapTypes[this.type]) { this.initLayer(); } else { google.maps.event.addListenerOnce( OpenLayers.Layer.GoogleNG.mapObject, "idle", OpenLayers.Function.bind(this.initLayer, this) ); } }, /** * Method: initLayer * * Sets layer properties according to the metadata provided by the API */ initLayer: function() { var mapType = OpenLayers.Layer.GoogleNG.mapObject.mapTypes[this.type]; if (!this.name) { this.setName("Google " + mapType.name); } var minZoom = mapType.minZoom || 0; this.addOptions({ maxResolution: Math.min( this.serverResolutions[minZoom], this.maxResolution ), zoomOffset: minZoom, numZoomLevels: Math.min( mapType.maxZoom + 1 - minZoom, this.numZoomLevels ) }, true); }, /** * Method: addTile * Create a tile, initialize it, and add it to the layer div. * * Parameters * bounds - {} * position - {} * * Returns: * {} The added OpenLayers.Tile.Google */ addTile:function(bounds, position) { return new OpenLayers.Tile.Google( this, position, bounds, this.tileOptions ); }, /** * Method: updateAttribution * Updates the attribution using the * * Parameters: * copyrights - {Object} Object with "m", "k", "h" and "p" properties (see * ), each holding an array of copyrights. */ 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 ©" + new Date().getFullYear() + " " + myCopyrights.join(", ") + " - "; var center = this.map.getCenter(); center && center.transform( this.map.getProjectionObject(), new OpenLayers.Projection("EPSG:4326") ); var size = this.map.getSize(); this.attribution = OpenLayers.String.format(this.attributionTemplate, { t: this.mapTypes[this.type], zoom: this.map.getZoom(), center: center.lat + "," + center.lon, mapType: this.type, mapData: mapData }); this.map && this.map.events.triggerEvent("changelayer", { layer: this, property: "attribution" }); }, /** * Method: setMap */ setMap: function() { OpenLayers.Layer.XYZ.prototype.setMap.apply(this, arguments); this.events.register("moveend", this, OpenLayers.Layer.GoogleNG.loadCopyrights ); }, /** * Method: removeMap */ removeMap: function() { OpenLayers.Layer.XYZ.prototype.removeMap.apply(this, arguments); this.events.unregister("moveend", this, OpenLayers.Layer.GoogleNG.loadCopyrights ); }, /** * APIMethod: clone * * Parameters: * obj - {Object} * * Returns: * {} An exact clone of this * */ clone: function(obj) { if (obj == null) { obj = new OpenLayers.Layer.GoogleNG(this.options); } //get all additions from superclasses obj = OpenLayers.Layer.XYZ.prototype.clone.apply(this, [obj]); // copy/set any non-init, non-simple values here return obj; }, CLASS_NAME: "OpenLayers.Layer.GoogleNG" }); /** * 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); };