Files
openlayers/lib/OpenLayers/Layer/GoogleNG.js
Tim Schaub 9ae8eff1fc Requires fix.
git-svn-id: http://svn.openlayers.org/trunk/openlayers@12078 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
2011-06-10 16:32:45 +00:00

330 lines
11 KiB
JavaScript

/* 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 <OpenLayers.Tile.Google> tiles.
*
* Inherits from:
* - <OpenLayers.Layer.XYZ>
*/
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: attributionTemplate
* {String}
*/
attributionTemplate: '<span class="olGoogleAttribution ${mapType}">' +
'<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>${mapData}<a style="white-space: nowrap" target="_blank" ' +
'href="http://www.google.com/help/terms_maps.html">' +
'Terms of Use</a></span>',
/**
* 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&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)
* 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);
this.options.numZoomLevels = options.numZoomLevels;
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 numZoomLevels = mapType.maxZoom + 1;
if (this.options.numZoomLevels != null) {
numZoomLevels = Math.min(numZoomLevels, this.options.numZoomLevels);
}
var restrictedMinZoom;
if (this.restrictedMinZoom || mapType.minZoom) {
restrictedMinZoom = Math.max(
mapType.minZoom || 0, this.restrictedMinZoom || 0
);
}
this.addOptions({
restrictedMinZoom: restrictedMinZoom,
numZoomLevels: numZoomLevels,
tileSize: new OpenLayers.Size(
mapType.tileSize.width, mapType.tileSize.height
)
});
// redraw to populate tiles with content
this.redraw();
},
/**
* APIMethod: addTile
* Create a tile, initialize it, and add it to the layer div.
*
* Parameters
* bounds - {<OpenLayers.Bounds>}
* position - {<OpenLayers.Pixel>}
*
* Returns:
* {<OpenLayers.Tile.Google>} 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 <attributionTemplate>
*
* Parameters:
* copyrights - {Object} Object with "m", "k", "h" and "p" properties (see
* <mapTypes>), 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 &copy;" + 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});
},
/**
* 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:
* {<OpenLayers.Layer.GoogleNG>} An exact clone of this
* <OpenLayers.Layer.GoogleNG>
*/
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);
};