summaryrefslogtreecommitdiff
path: root/misc/openlayers/lib/OpenLayers/Map.js
diff options
context:
space:
mode:
Diffstat (limited to 'misc/openlayers/lib/OpenLayers/Map.js')
-rw-r--r--misc/openlayers/lib/OpenLayers/Map.js2867
1 files changed, 0 insertions, 2867 deletions
diff --git a/misc/openlayers/lib/OpenLayers/Map.js b/misc/openlayers/lib/OpenLayers/Map.js
deleted file mode 100644
index 56763fa..0000000
--- a/misc/openlayers/lib/OpenLayers/Map.js
+++ /dev/null
@@ -1,2867 +0,0 @@
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
- * full list of contributors). Published under the 2-clause BSD license.
- * See license.txt in the OpenLayers distribution or repository for the
- * full text of the license. */
-
-/**
- * @requires OpenLayers/BaseTypes/Class.js
- * @requires OpenLayers/Util.js
- * @requires OpenLayers/Util/vendorPrefix.js
- * @requires OpenLayers/Events.js
- * @requires OpenLayers/Tween.js
- * @requires OpenLayers/Projection.js
- */
-
-/**
- * Class: OpenLayers.Map
- * Instances of OpenLayers.Map are interactive maps embedded in a web page.
- * Create a new map with the <OpenLayers.Map> constructor.
- *
- * On their own maps do not provide much functionality. To extend a map
- * it's necessary to add controls (<OpenLayers.Control>) and
- * layers (<OpenLayers.Layer>) to the map.
- */
-OpenLayers.Map = OpenLayers.Class({
-
- /**
- * Constant: Z_INDEX_BASE
- * {Object} Base z-indexes for different classes of thing
- */
- Z_INDEX_BASE: {
- BaseLayer: 100,
- Overlay: 325,
- Feature: 725,
- Popup: 750,
- Control: 1000
- },
-
- /**
- * APIProperty: events
- * {<OpenLayers.Events>}
- *
- * Register a listener for a particular event with the following syntax:
- * (code)
- * map.events.register(type, obj, listener);
- * (end)
- *
- * Listeners will be called with a reference to an event object. The
- * properties of this event depends on exactly what happened.
- *
- * All event objects have at least the following properties:
- * object - {Object} A reference to map.events.object.
- * element - {DOMElement} A reference to map.events.element.
- *
- * Browser events have the following additional properties:
- * xy - {<OpenLayers.Pixel>} The pixel location of the event (relative
- * to the the map viewport).
- *
- * Supported map event types:
- * preaddlayer - triggered before a layer has been added. The event
- * object will include a *layer* property that references the layer
- * to be added. When a listener returns "false" the adding will be
- * aborted.
- * addlayer - triggered after a layer has been added. The event object
- * will include a *layer* property that references the added layer.
- * preremovelayer - triggered before a layer has been removed. The event
- * object will include a *layer* property that references the layer
- * to be removed. When a listener returns "false" the removal will be
- * aborted.
- * removelayer - triggered after a layer has been removed. The event
- * object will include a *layer* property that references the removed
- * layer.
- * changelayer - triggered after a layer name change, order change,
- * opacity change, params change, visibility change (actual visibility,
- * not the layer's visibility property) or attribution change (due to
- * extent change). Listeners will receive an event object with *layer*
- * and *property* properties. The *layer* property will be a reference
- * to the changed layer. The *property* property will be a key to the
- * changed property (name, order, opacity, params, visibility or
- * attribution).
- * movestart - triggered after the start of a drag, pan, or zoom. The event
- * object may include a *zoomChanged* property that tells whether the
- * zoom has changed.
- * move - triggered after each drag, pan, or zoom
- * moveend - triggered after a drag, pan, or zoom completes
- * zoomend - triggered after a zoom completes
- * mouseover - triggered after mouseover the map
- * mouseout - triggered after mouseout the map
- * mousemove - triggered after mousemove the map
- * changebaselayer - triggered after the base layer changes
- * updatesize - triggered after the <updateSize> method was executed
- */
-
- /**
- * Property: id
- * {String} Unique identifier for the map
- */
- id: null,
-
- /**
- * Property: fractionalZoom
- * {Boolean} For a base layer that supports it, allow the map resolution
- * to be set to a value between one of the values in the resolutions
- * array. Default is false.
- *
- * When fractionalZoom is set to true, it is possible to zoom to
- * an arbitrary extent. This requires a base layer from a source
- * that supports requests for arbitrary extents (i.e. not cached
- * tiles on a regular lattice). This means that fractionalZoom
- * will not work with commercial layers (Google, Yahoo, VE), layers
- * using TileCache, or any other pre-cached data sources.
- *
- * If you are using fractionalZoom, then you should also use
- * <getResolutionForZoom> instead of layer.resolutions[zoom] as the
- * former works for non-integer zoom levels.
- */
- fractionalZoom: false,
-
- /**
- * APIProperty: events
- * {<OpenLayers.Events>} An events object that handles all
- * events on the map
- */
- events: null,
-
- /**
- * APIProperty: allOverlays
- * {Boolean} Allow the map to function with "overlays" only. Defaults to
- * false. If true, the lowest layer in the draw order will act as
- * the base layer. In addition, if set to true, all layers will
- * have isBaseLayer set to false when they are added to the map.
- *
- * Note:
- * If you set map.allOverlays to true, then you *cannot* use
- * map.setBaseLayer or layer.setIsBaseLayer. With allOverlays true,
- * the lowest layer in the draw layer is the base layer. So, to change
- * the base layer, use <setLayerIndex> or <raiseLayer> to set the layer
- * index to 0.
- */
- allOverlays: false,
-
- /**
- * APIProperty: div
- * {DOMElement|String} The element that contains the map (or an id for
- * that element). If the <OpenLayers.Map> constructor is called
- * with two arguments, this should be provided as the first argument.
- * Alternatively, the map constructor can be called with the options
- * object as the only argument. In this case (one argument), a
- * div property may or may not be provided. If the div property
- * is not provided, the map can be rendered to a container later
- * using the <render> method.
- *
- * Note:
- * If you are calling <render> after map construction, do not use
- * <maxResolution> auto. Instead, divide your <maxExtent> by your
- * maximum expected dimension.
- */
- div: null,
-
- /**
- * Property: dragging
- * {Boolean} The map is currently being dragged.
- */
- dragging: false,
-
- /**
- * Property: size
- * {<OpenLayers.Size>} Size of the main div (this.div)
- */
- size: null,
-
- /**
- * Property: viewPortDiv
- * {HTMLDivElement} The element that represents the map viewport
- */
- viewPortDiv: null,
-
- /**
- * Property: layerContainerOrigin
- * {<OpenLayers.LonLat>} The lonlat at which the later container was
- * re-initialized (on-zoom)
- */
- layerContainerOrigin: null,
-
- /**
- * Property: layerContainerDiv
- * {HTMLDivElement} The element that contains the layers.
- */
- layerContainerDiv: null,
-
- /**
- * APIProperty: layers
- * {Array(<OpenLayers.Layer>)} Ordered list of layers in the map
- */
- layers: null,
-
- /**
- * APIProperty: controls
- * {Array(<OpenLayers.Control>)} List of controls associated with the map.
- *
- * If not provided in the map options at construction, the map will
- * by default be given the following controls if present in the build:
- * - <OpenLayers.Control.Navigation> or <OpenLayers.Control.TouchNavigation>
- * - <OpenLayers.Control.Zoom> or <OpenLayers.Control.PanZoom>
- * - <OpenLayers.Control.ArgParser>
- * - <OpenLayers.Control.Attribution>
- */
- controls: null,
-
- /**
- * Property: popups
- * {Array(<OpenLayers.Popup>)} List of popups associated with the map
- */
- popups: null,
-
- /**
- * APIProperty: baseLayer
- * {<OpenLayers.Layer>} The currently selected base layer. This determines
- * min/max zoom level, projection, etc.
- */
- baseLayer: null,
-
- /**
- * Property: center
- * {<OpenLayers.LonLat>} The current center of the map
- */
- center: null,
-
- /**
- * Property: resolution
- * {Float} The resolution of the map.
- */
- resolution: null,
-
- /**
- * Property: zoom
- * {Integer} The current zoom level of the map
- */
- zoom: 0,
-
- /**
- * Property: panRatio
- * {Float} The ratio of the current extent within
- * which panning will tween.
- */
- panRatio: 1.5,
-
- /**
- * APIProperty: options
- * {Object} The options object passed to the class constructor. Read-only.
- */
- options: null,
-
- // Options
-
- /**
- * APIProperty: tileSize
- * {<OpenLayers.Size>} Set in the map options to override the default tile
- * size for this map.
- */
- tileSize: null,
-
- /**
- * APIProperty: projection
- * {String} Set in the map options to specify the default projection
- * for layers added to this map. When using a projection other than EPSG:4326
- * (CRS:84, Geographic) or EPSG:3857 (EPSG:900913, Web Mercator),
- * also set maxExtent, maxResolution or resolutions. Default is "EPSG:4326".
- * Note that the projection of the map is usually determined
- * by that of the current baseLayer (see <baseLayer> and <getProjectionObject>).
- */
- projection: "EPSG:4326",
-
- /**
- * APIProperty: units
- * {String} The map units. Possible values are 'degrees' (or 'dd'), 'm',
- * 'ft', 'km', 'mi', 'inches'. Normally taken from the projection.
- * Only required if both map and layers do not define a projection,
- * or if they define a projection which does not define units
- */
- units: null,
-
- /**
- * APIProperty: resolutions
- * {Array(Float)} A list of map resolutions (map units per pixel) in
- * descending order. If this is not set in the layer constructor, it
- * will be set based on other resolution related properties
- * (maxExtent, maxResolution, maxScale, etc.).
- */
- resolutions: null,
-
- /**
- * APIProperty: maxResolution
- * {Float} Required if you are not displaying the whole world on a tile
- * with the size specified in <tileSize>.
- */
- maxResolution: null,
-
- /**
- * APIProperty: minResolution
- * {Float}
- */
- minResolution: null,
-
- /**
- * APIProperty: maxScale
- * {Float}
- */
- maxScale: null,
-
- /**
- * APIProperty: minScale
- * {Float}
- */
- minScale: null,
-
- /**
- * APIProperty: maxExtent
- * {<OpenLayers.Bounds>|Array} If provided as an array, the array
- * should consist of four values (left, bottom, right, top).
- * The maximum extent for the map.
- * Default depends on projection; if this is one of those defined in OpenLayers.Projection.defaults
- * (EPSG:4326 or web mercator), maxExtent will be set to the value defined there;
- * else, defaults to null.
- * To restrict user panning and zooming of the map, use <restrictedExtent> instead.
- * The value for <maxExtent> will change calculations for tile URLs.
- */
- maxExtent: null,
-
- /**
- * APIProperty: minExtent
- * {<OpenLayers.Bounds>|Array} If provided as an array, the array
- * should consist of four values (left, bottom, right, top).
- * The minimum extent for the map. Defaults to null.
- */
- minExtent: null,
-
- /**
- * APIProperty: restrictedExtent
- * {<OpenLayers.Bounds>|Array} If provided as an array, the array
- * should consist of four values (left, bottom, right, top).
- * Limit map navigation to this extent where possible.
- * If a non-null restrictedExtent is set, panning will be restricted
- * to the given bounds. In addition, zooming to a resolution that
- * displays more than the restricted extent will center the map
- * on the restricted extent. If you wish to limit the zoom level
- * or resolution, use maxResolution.
- */
- restrictedExtent: null,
-
- /**
- * APIProperty: numZoomLevels
- * {Integer} Number of zoom levels for the map. Defaults to 16. Set a
- * different value in the map options if needed.
- */
- numZoomLevels: 16,
-
- /**
- * APIProperty: theme
- * {String} Relative path to a CSS file from which to load theme styles.
- * Specify null in the map options (e.g. {theme: null}) if you
- * want to get cascading style declarations - by putting links to
- * stylesheets or style declarations directly in your page.
- */
- theme: null,
-
- /**
- * APIProperty: displayProjection
- * {<OpenLayers.Projection>} Requires proj4js support for projections other
- * than EPSG:4326 or EPSG:900913/EPSG:3857. Projection used by
- * several controls to display data to user. If this property is set,
- * it will be set on any control which has a null displayProjection
- * property at the time the control is added to the map.
- */
- displayProjection: null,
-
- /**
- * APIProperty: tileManager
- * {<OpenLayers.TileManager>|Object} By default, and if the build contains
- * TileManager.js, the map will use the TileManager to queue image requests
- * and to cache tile image elements. To create a map without a TileManager
- * configure the map with tileManager: null. To create a TileManager with
- * non-default options, supply the options instead or alternatively supply
- * an instance of {<OpenLayers.TileManager>}.
- */
-
- /**
- * APIProperty: fallThrough
- * {Boolean} Should OpenLayers allow events on the map to fall through to
- * other elements on the page, or should it swallow them? (#457)
- * Default is to swallow.
- */
- fallThrough: false,
-
- /**
- * APIProperty: autoUpdateSize
- * {Boolean} Should OpenLayers automatically update the size of the map
- * when the resize event is fired. Default is true.
- */
- autoUpdateSize: true,
-
- /**
- * APIProperty: eventListeners
- * {Object} If set as an option at construction, the eventListeners
- * object will be registered with <OpenLayers.Events.on>. Object
- * structure must be a listeners object as shown in the example for
- * the events.on method.
- */
- eventListeners: null,
-
- /**
- * Property: panTween
- * {<OpenLayers.Tween>} Animated panning tween object, see panTo()
- */
- panTween: null,
-
- /**
- * APIProperty: panMethod
- * {Function} The Easing function to be used for tweening. Default is
- * OpenLayers.Easing.Expo.easeOut. Setting this to 'null' turns off
- * animated panning.
- */
- panMethod: OpenLayers.Easing.Expo.easeOut,
-
- /**
- * Property: panDuration
- * {Integer} The number of steps to be passed to the
- * OpenLayers.Tween.start() method when the map is
- * panned.
- * Default is 50.
- */
- panDuration: 50,
-
- /**
- * Property: zoomTween
- * {<OpenLayers.Tween>} Animated zooming tween object, see zoomTo()
- */
- zoomTween: null,
-
- /**
- * APIProperty: zoomMethod
- * {Function} The Easing function to be used for tweening. Default is
- * OpenLayers.Easing.Quad.easeOut. Setting this to 'null' turns off
- * animated zooming.
- */
- zoomMethod: OpenLayers.Easing.Quad.easeOut,
-
- /**
- * Property: zoomDuration
- * {Integer} The number of steps to be passed to the
- * OpenLayers.Tween.start() method when the map is zoomed.
- * Default is 20.
- */
- zoomDuration: 20,
-
- /**
- * Property: paddingForPopups
- * {<OpenLayers.Bounds>} Outside margin of the popup. Used to prevent
- * the popup from getting too close to the map border.
- */
- paddingForPopups : null,
-
- /**
- * Property: layerContainerOriginPx
- * {Object} Cached object representing the layer container origin (in pixels).
- */
- layerContainerOriginPx: null,
-
- /**
- * Property: minPx
- * {Object} An object with a 'x' and 'y' values that is the lower
- * left of maxExtent in viewport pixel space.
- * Used to verify in moveByPx that the new location we're moving to
- * is valid. It is also used in the getLonLatFromViewPortPx function
- * of Layer.
- */
- minPx: null,
-
- /**
- * Property: maxPx
- * {Object} An object with a 'x' and 'y' values that is the top
- * right of maxExtent in viewport pixel space.
- * Used to verify in moveByPx that the new location we're moving to
- * is valid.
- */
- maxPx: null,
-
- /**
- * Constructor: OpenLayers.Map
- * Constructor for a new OpenLayers.Map instance. There are two possible
- * ways to call the map constructor. See the examples below.
- *
- * Parameters:
- * div - {DOMElement|String} The element or id of an element in your page
- * that will contain the map. May be omitted if the <div> option is
- * provided or if you intend to call the <render> method later.
- * options - {Object} Optional object with properties to tag onto the map.
- *
- * Valid options (in addition to the listed API properties):
- * center - {<OpenLayers.LonLat>|Array} The default initial center of the map.
- * If provided as array, the first value is the x coordinate,
- * and the 2nd value is the y coordinate.
- * Only specify if <layers> is provided.
- * Note that if an ArgParser/Permalink control is present,
- * and the querystring contains coordinates, center will be set
- * by that, and this option will be ignored.
- * zoom - {Number} The initial zoom level for the map. Only specify if
- * <layers> is provided.
- * Note that if an ArgParser/Permalink control is present,
- * and the querystring contains a zoom level, zoom will be set
- * by that, and this option will be ignored.
- * extent - {<OpenLayers.Bounds>|Array} The initial extent of the map.
- * If provided as an array, the array should consist of
- * four values (left, bottom, right, top).
- * Only specify if <center> and <zoom> are not provided.
- *
- * Examples:
- * (code)
- * // create a map with default options in an element with the id "map1"
- * var map = new OpenLayers.Map("map1");
- *
- * // create a map with non-default options in an element with id "map2"
- * var options = {
- * projection: "EPSG:3857",
- * maxExtent: new OpenLayers.Bounds(-200000, -200000, 200000, 200000),
- * center: new OpenLayers.LonLat(-12356463.476333, 5621521.4854095)
- * };
- * var map = new OpenLayers.Map("map2", options);
- *
- * // map with non-default options - same as above but with a single argument,
- * // a restricted extent, and using arrays for bounds and center
- * var map = new OpenLayers.Map({
- * div: "map_id",
- * projection: "EPSG:3857",
- * maxExtent: [-18924313.432222, -15538711.094146, 18924313.432222, 15538711.094146],
- * restrictedExtent: [-13358338.893333, -9608371.5085962, 13358338.893333, 9608371.5085962],
- * center: [-12356463.476333, 5621521.4854095]
- * });
- *
- * // create a map without a reference to a container - call render later
- * var map = new OpenLayers.Map({
- * projection: "EPSG:3857",
- * maxExtent: new OpenLayers.Bounds(-200000, -200000, 200000, 200000)
- * });
- * (end)
- */
- initialize: function (div, options) {
-
- // If only one argument is provided, check if it is an object.
- if(arguments.length === 1 && typeof div === "object") {
- options = div;
- div = options && options.div;
- }
-
- // Simple-type defaults are set in class definition.
- // Now set complex-type defaults
- this.tileSize = new OpenLayers.Size(OpenLayers.Map.TILE_WIDTH,
- OpenLayers.Map.TILE_HEIGHT);
-
- this.paddingForPopups = new OpenLayers.Bounds(15, 15, 15, 15);
-
- this.theme = OpenLayers._getScriptLocation() +
- 'theme/default/style.css';
-
- // backup original options
- this.options = OpenLayers.Util.extend({}, options);
-
- // now override default options
- OpenLayers.Util.extend(this, options);
-
- var projCode = this.projection instanceof OpenLayers.Projection ?
- this.projection.projCode : this.projection;
- OpenLayers.Util.applyDefaults(this, OpenLayers.Projection.defaults[projCode]);
-
- // allow extents and center to be arrays
- if (this.maxExtent && !(this.maxExtent instanceof OpenLayers.Bounds)) {
- this.maxExtent = new OpenLayers.Bounds(this.maxExtent);
- }
- if (this.minExtent && !(this.minExtent instanceof OpenLayers.Bounds)) {
- this.minExtent = new OpenLayers.Bounds(this.minExtent);
- }
- if (this.restrictedExtent && !(this.restrictedExtent instanceof OpenLayers.Bounds)) {
- this.restrictedExtent = new OpenLayers.Bounds(this.restrictedExtent);
- }
- if (this.center && !(this.center instanceof OpenLayers.LonLat)) {
- this.center = new OpenLayers.LonLat(this.center);
- }
-
- // initialize layers array
- this.layers = [];
-
- this.id = OpenLayers.Util.createUniqueID("OpenLayers.Map_");
-
- this.div = OpenLayers.Util.getElement(div);
- if(!this.div) {
- this.div = document.createElement("div");
- this.div.style.height = "1px";
- this.div.style.width = "1px";
- }
-
- OpenLayers.Element.addClass(this.div, 'olMap');
-
- // the viewPortDiv is the outermost div we modify
- var id = this.id + "_OpenLayers_ViewPort";
- this.viewPortDiv = OpenLayers.Util.createDiv(id, null, null, null,
- "relative", null,
- "hidden");
- this.viewPortDiv.style.width = "100%";
- this.viewPortDiv.style.height = "100%";
- this.viewPortDiv.className = "olMapViewport";
- this.div.appendChild(this.viewPortDiv);
-
- this.events = new OpenLayers.Events(
- this, this.viewPortDiv, null, this.fallThrough,
- {includeXY: true}
- );
-
- if (OpenLayers.TileManager && this.tileManager !== null) {
- if (!(this.tileManager instanceof OpenLayers.TileManager)) {
- this.tileManager = new OpenLayers.TileManager(this.tileManager);
- }
- this.tileManager.addMap(this);
- }
-
- // the layerContainerDiv is the one that holds all the layers
- id = this.id + "_OpenLayers_Container";
- this.layerContainerDiv = OpenLayers.Util.createDiv(id);
- this.layerContainerDiv.style.zIndex=this.Z_INDEX_BASE['Popup']-1;
- this.layerContainerOriginPx = {x: 0, y: 0};
- this.applyTransform();
-
- this.viewPortDiv.appendChild(this.layerContainerDiv);
-
- this.updateSize();
- if(this.eventListeners instanceof Object) {
- this.events.on(this.eventListeners);
- }
-
- if (this.autoUpdateSize === true) {
- // updateSize on catching the window's resize
- // Note that this is ok, as updateSize() does nothing if the
- // map's size has not actually changed.
- this.updateSizeDestroy = OpenLayers.Function.bind(this.updateSize,
- this);
- OpenLayers.Event.observe(window, 'resize',
- this.updateSizeDestroy);
- }
-
- // only append link stylesheet if the theme property is set
- if(this.theme) {
- // check existing links for equivalent url
- var addNode = true;
- var nodes = document.getElementsByTagName('link');
- for(var i=0, len=nodes.length; i<len; ++i) {
- if(OpenLayers.Util.isEquivalentUrl(nodes.item(i).href,
- this.theme)) {
- addNode = false;
- break;
- }
- }
- // only add a new node if one with an equivalent url hasn't already
- // been added
- if(addNode) {
- var cssNode = document.createElement('link');
- cssNode.setAttribute('rel', 'stylesheet');
- cssNode.setAttribute('type', 'text/css');
- cssNode.setAttribute('href', this.theme);
- document.getElementsByTagName('head')[0].appendChild(cssNode);
- }
- }
-
- if (this.controls == null) { // default controls
- this.controls = [];
- if (OpenLayers.Control != null) { // running full or lite?
- // Navigation or TouchNavigation depending on what is in build
- if (OpenLayers.Control.Navigation) {
- this.controls.push(new OpenLayers.Control.Navigation());
- } else if (OpenLayers.Control.TouchNavigation) {
- this.controls.push(new OpenLayers.Control.TouchNavigation());
- }
- if (OpenLayers.Control.Zoom) {
- this.controls.push(new OpenLayers.Control.Zoom());
- } else if (OpenLayers.Control.PanZoom) {
- this.controls.push(new OpenLayers.Control.PanZoom());
- }
-
- if (OpenLayers.Control.ArgParser) {
- this.controls.push(new OpenLayers.Control.ArgParser());
- }
- if (OpenLayers.Control.Attribution) {
- this.controls.push(new OpenLayers.Control.Attribution());
- }
- }
- }
-
- for(var i=0, len=this.controls.length; i<len; i++) {
- this.addControlToMap(this.controls[i]);
- }
-
- this.popups = [];
-
- this.unloadDestroy = OpenLayers.Function.bind(this.destroy, this);
-
-
- // always call map.destroy()
- OpenLayers.Event.observe(window, 'unload', this.unloadDestroy);
-
- // add any initial layers
- if (options && options.layers) {
- /**
- * If you have set options.center, the map center property will be
- * set at this point. However, since setCenter has not been called,
- * addLayers gets confused. So we delete the map center in this
- * case. Because the check below uses options.center, it will
- * be properly set below.
- */
- delete this.center;
- delete this.zoom;
- this.addLayers(options.layers);
- // set center (and optionally zoom)
- if (options.center && !this.getCenter()) {
- // zoom can be undefined here
- this.setCenter(options.center, options.zoom);
- }
- }
-
- if (this.panMethod) {
- this.panTween = new OpenLayers.Tween(this.panMethod);
- }
- if (this.zoomMethod && this.applyTransform.transform) {
- this.zoomTween = new OpenLayers.Tween(this.zoomMethod);
- }
- },
-
- /**
- * APIMethod: getViewport
- * Get the DOMElement representing the view port.
- *
- * Returns:
- * {DOMElement}
- */
- getViewport: function() {
- return this.viewPortDiv;
- },
-
- /**
- * APIMethod: render
- * Render the map to a specified container.
- *
- * Parameters:
- * div - {String|DOMElement} The container that the map should be rendered
- * to. If different than the current container, the map viewport
- * will be moved from the current to the new container.
- */
- render: function(div) {
- this.div = OpenLayers.Util.getElement(div);
- OpenLayers.Element.addClass(this.div, 'olMap');
- this.viewPortDiv.parentNode.removeChild(this.viewPortDiv);
- this.div.appendChild(this.viewPortDiv);
- this.updateSize();
- },
-
- /**
- * Method: unloadDestroy
- * Function that is called to destroy the map on page unload. stored here
- * so that if map is manually destroyed, we can unregister this.
- */
- unloadDestroy: null,
-
- /**
- * Method: updateSizeDestroy
- * When the map is destroyed, we need to stop listening to updateSize
- * events: this method stores the function we need to unregister in
- * non-IE browsers.
- */
- updateSizeDestroy: null,
-
- /**
- * APIMethod: destroy
- * Destroy this map.
- * Note that if you are using an application which removes a container
- * of the map from the DOM, you need to ensure that you destroy the
- * map *before* this happens; otherwise, the page unload handler
- * will fail because the DOM elements that map.destroy() wants
- * to clean up will be gone. (See
- * http://trac.osgeo.org/openlayers/ticket/2277 for more information).
- * This will apply to GeoExt and also to other applications which
- * modify the DOM of the container of the OpenLayers Map.
- */
- destroy:function() {
- // if unloadDestroy is null, we've already been destroyed
- if (!this.unloadDestroy) {
- return false;
- }
-
- // make sure panning doesn't continue after destruction
- if(this.panTween) {
- this.panTween.stop();
- this.panTween = null;
- }
- // make sure zooming doesn't continue after destruction
- if(this.zoomTween) {
- this.zoomTween.stop();
- this.zoomTween = null;
- }
-
- // map has been destroyed. dont do it again!
- OpenLayers.Event.stopObserving(window, 'unload', this.unloadDestroy);
- this.unloadDestroy = null;
-
- if (this.updateSizeDestroy) {
- OpenLayers.Event.stopObserving(window, 'resize',
- this.updateSizeDestroy);
- }
-
- this.paddingForPopups = null;
-
- if (this.controls != null) {
- for (var i = this.controls.length - 1; i>=0; --i) {
- this.controls[i].destroy();
- }
- this.controls = null;
- }
- if (this.layers != null) {
- for (var i = this.layers.length - 1; i>=0; --i) {
- //pass 'false' to destroy so that map wont try to set a new
- // baselayer after each baselayer is removed
- this.layers[i].destroy(false);
- }
- this.layers = null;
- }
- if (this.viewPortDiv && this.viewPortDiv.parentNode) {
- this.viewPortDiv.parentNode.removeChild(this.viewPortDiv);
- }
- this.viewPortDiv = null;
-
- if (this.tileManager) {
- this.tileManager.removeMap(this);
- this.tileManager = null;
- }
-
- if(this.eventListeners) {
- this.events.un(this.eventListeners);
- this.eventListeners = null;
- }
- this.events.destroy();
- this.events = null;
-
- this.options = null;
- },
-
- /**
- * APIMethod: setOptions
- * Change the map options
- *
- * Parameters:
- * options - {Object} Hashtable of options to tag to the map
- */
- setOptions: function(options) {
- var updatePxExtent = this.minPx &&
- options.restrictedExtent != this.restrictedExtent;
- OpenLayers.Util.extend(this, options);
- // force recalculation of minPx and maxPx
- updatePxExtent && this.moveTo(this.getCachedCenter(), this.zoom, {
- forceZoomChange: true
- });
- },
-
- /**
- * APIMethod: getTileSize
- * Get the tile size for the map
- *
- * Returns:
- * {<OpenLayers.Size>}
- */
- getTileSize: function() {
- return this.tileSize;
- },
-
-
- /**
- * APIMethod: getBy
- * Get a list of objects given a property and a match item.
- *
- * Parameters:
- * array - {String} A property on the map whose value is an array.
- * property - {String} A property on each item of the given array.
- * match - {String | Object} A string to match. Can also be a regular
- * expression literal or object. In addition, it can be any object
- * with a method named test. For reqular expressions or other, if
- * match.test(map[array][i][property]) evaluates to true, the item will
- * be included in the array returned. If no items are found, an empty
- * array is returned.
- *
- * Returns:
- * {Array} An array of items where the given property matches the given
- * criteria.
- */
- getBy: function(array, property, match) {
- var test = (typeof match.test == "function");
- var found = OpenLayers.Array.filter(this[array], function(item) {
- return item[property] == match || (test && match.test(item[property]));
- });
- return found;
- },
-
- /**
- * APIMethod: getLayersBy
- * Get a list of layers with properties matching the given criteria.
- *
- * Parameters:
- * property - {String} A layer property to be matched.
- * match - {String | Object} A string to match. Can also be a regular
- * expression literal or object. In addition, it can be any object
- * with a method named test. For reqular expressions or other, if
- * match.test(layer[property]) evaluates to true, the layer will be
- * included in the array returned. If no layers are found, an empty
- * array is returned.
- *
- * Returns:
- * {Array(<OpenLayers.Layer>)} A list of layers matching the given criteria.
- * An empty array is returned if no matches are found.
- */
- getLayersBy: function(property, match) {
- return this.getBy("layers", property, match);
- },
-
- /**
- * APIMethod: getLayersByName
- * Get a list of layers with names matching the given name.
- *
- * Parameters:
- * match - {String | Object} A layer name. The name can also be a regular
- * expression literal or object. In addition, it can be any object
- * with a method named test. For reqular expressions or other, if
- * name.test(layer.name) evaluates to true, the layer will be included
- * in the list of layers returned. If no layers are found, an empty
- * array is returned.
- *
- * Returns:
- * {Array(<OpenLayers.Layer>)} A list of layers matching the given name.
- * An empty array is returned if no matches are found.
- */
- getLayersByName: function(match) {
- return this.getLayersBy("name", match);
- },
-
- /**
- * APIMethod: getLayersByClass
- * Get a list of layers of a given class (CLASS_NAME).
- *
- * Parameters:
- * match - {String | Object} A layer class name. The match can also be a
- * regular expression literal or object. In addition, it can be any
- * object with a method named test. For reqular expressions or other,
- * if type.test(layer.CLASS_NAME) evaluates to true, the layer will
- * be included in the list of layers returned. If no layers are
- * found, an empty array is returned.
- *
- * Returns:
- * {Array(<OpenLayers.Layer>)} A list of layers matching the given class.
- * An empty array is returned if no matches are found.
- */
- getLayersByClass: function(match) {
- return this.getLayersBy("CLASS_NAME", match);
- },
-
- /**
- * APIMethod: getControlsBy
- * Get a list of controls with properties matching the given criteria.
- *
- * Parameters:
- * property - {String} A control property to be matched.
- * match - {String | Object} A string to match. Can also be a regular
- * expression literal or object. In addition, it can be any object
- * with a method named test. For reqular expressions or other, if
- * match.test(layer[property]) evaluates to true, the layer will be
- * included in the array returned. If no layers are found, an empty
- * array is returned.
- *
- * Returns:
- * {Array(<OpenLayers.Control>)} A list of controls matching the given
- * criteria. An empty array is returned if no matches are found.
- */
- getControlsBy: function(property, match) {
- return this.getBy("controls", property, match);
- },
-
- /**
- * APIMethod: getControlsByClass
- * Get a list of controls of a given class (CLASS_NAME).
- *
- * Parameters:
- * match - {String | Object} A control class name. The match can also be a
- * regular expression literal or object. In addition, it can be any
- * object with a method named test. For reqular expressions or other,
- * if type.test(control.CLASS_NAME) evaluates to true, the control will
- * be included in the list of controls returned. If no controls are
- * found, an empty array is returned.
- *
- * Returns:
- * {Array(<OpenLayers.Control>)} A list of controls matching the given class.
- * An empty array is returned if no matches are found.
- */
- getControlsByClass: function(match) {
- return this.getControlsBy("CLASS_NAME", match);
- },
-
- /********************************************************/
- /* */
- /* Layer Functions */
- /* */
- /* The following functions deal with adding and */
- /* removing Layers to and from the Map */
- /* */
- /********************************************************/
-
- /**
- * APIMethod: getLayer
- * Get a layer based on its id
- *
- * Parameters:
- * id - {String} A layer id
- *
- * Returns:
- * {<OpenLayers.Layer>} The Layer with the corresponding id from the map's
- * layer collection, or null if not found.
- */
- getLayer: function(id) {
- var foundLayer = null;
- for (var i=0, len=this.layers.length; i<len; i++) {
- var layer = this.layers[i];
- if (layer.id == id) {
- foundLayer = layer;
- break;
- }
- }
- return foundLayer;
- },
-
- /**
- * Method: setLayerZIndex
- *
- * Parameters:
- * layer - {<OpenLayers.Layer>}
- * zIdx - {int}
- */
- setLayerZIndex: function (layer, zIdx) {
- layer.setZIndex(
- this.Z_INDEX_BASE[layer.isBaseLayer ? 'BaseLayer' : 'Overlay']
- + zIdx * 5 );
- },
-
- /**
- * Method: resetLayersZIndex
- * Reset each layer's z-index based on layer's array index
- */
- resetLayersZIndex: function() {
- for (var i=0, len=this.layers.length; i<len; i++) {
- var layer = this.layers[i];
- this.setLayerZIndex(layer, i);
- }
- },
-
- /**
- * APIMethod: addLayer
- *
- * Parameters:
- * layer - {<OpenLayers.Layer>}
- *
- * Returns:
- * {Boolean} True if the layer has been added to the map.
- */
- addLayer: function (layer) {
- for(var i = 0, len = this.layers.length; i < len; i++) {
- if (this.layers[i] == layer) {
- return false;
- }
- }
- if (this.events.triggerEvent("preaddlayer", {layer: layer}) === false) {
- return false;
- }
- if(this.allOverlays) {
- layer.isBaseLayer = false;
- }
-
- layer.div.className = "olLayerDiv";
- layer.div.style.overflow = "";
- this.setLayerZIndex(layer, this.layers.length);
-
- if (layer.isFixed) {
- this.viewPortDiv.appendChild(layer.div);
- } else {
- this.layerContainerDiv.appendChild(layer.div);
- }
- this.layers.push(layer);
- layer.setMap(this);
-
- if (layer.isBaseLayer || (this.allOverlays && !this.baseLayer)) {
- if (this.baseLayer == null) {
- // set the first baselaye we add as the baselayer
- this.setBaseLayer(layer);
- } else {
- layer.setVisibility(false);
- }
- } else {
- layer.redraw();
- }
-
- this.events.triggerEvent("addlayer", {layer: layer});
- layer.events.triggerEvent("added", {map: this, layer: layer});
- layer.afterAdd();
-
- return true;
- },
-
- /**
- * APIMethod: addLayers
- *
- * Parameters:
- * layers - {Array(<OpenLayers.Layer>)}
- */
- addLayers: function (layers) {
- for (var i=0, len=layers.length; i<len; i++) {
- this.addLayer(layers[i]);
- }
- },
-
- /**
- * APIMethod: removeLayer
- * Removes a layer from the map by removing its visual element (the
- * layer.div property), then removing it from the map's internal list
- * of layers, setting the layer's map property to null.
- *
- * a "removelayer" event is triggered.
- *
- * very worthy of mention is that simply removing a layer from a map
- * will not cause the removal of any popups which may have been created
- * by the layer. this is due to the fact that it was decided at some
- * point that popups would not belong to layers. thus there is no way
- * for us to know here to which layer the popup belongs.
- *
- * A simple solution to this is simply to call destroy() on the layer.
- * the default OpenLayers.Layer class's destroy() function
- * automatically takes care to remove itself from whatever map it has
- * been attached to.
- *
- * The correct solution is for the layer itself to register an
- * event-handler on "removelayer" and when it is called, if it
- * recognizes itself as the layer being removed, then it cycles through
- * its own personal list of popups, removing them from the map.
- *
- * Parameters:
- * layer - {<OpenLayers.Layer>}
- * setNewBaseLayer - {Boolean} Default is true
- */
- removeLayer: function(layer, setNewBaseLayer) {
- if (this.events.triggerEvent("preremovelayer", {layer: layer}) === false) {
- return;
- }
- if (setNewBaseLayer == null) {
- setNewBaseLayer = true;
- }
-
- if (layer.isFixed) {
- this.viewPortDiv.removeChild(layer.div);
- } else {
- this.layerContainerDiv.removeChild(layer.div);
- }
- OpenLayers.Util.removeItem(this.layers, layer);
- layer.removeMap(this);
- layer.map = null;
-
- // if we removed the base layer, need to set a new one
- if(this.baseLayer == layer) {
- this.baseLayer = null;
- if(setNewBaseLayer) {
- for(var i=0, len=this.layers.length; i<len; i++) {
- var iLayer = this.layers[i];
- if (iLayer.isBaseLayer || this.allOverlays) {
- this.setBaseLayer(iLayer);
- break;
- }
- }
- }
- }
-
- this.resetLayersZIndex();
-
- this.events.triggerEvent("removelayer", {layer: layer});
- layer.events.triggerEvent("removed", {map: this, layer: layer});
- },
-
- /**
- * APIMethod: getNumLayers
- *
- * Returns:
- * {Int} The number of layers attached to the map.
- */
- getNumLayers: function () {
- return this.layers.length;
- },
-
- /**
- * APIMethod: getLayerIndex
- *
- * Parameters:
- * layer - {<OpenLayers.Layer>}
- *
- * Returns:
- * {Integer} The current (zero-based) index of the given layer in the map's
- * layer stack. Returns -1 if the layer isn't on the map.
- */
- getLayerIndex: function (layer) {
- return OpenLayers.Util.indexOf(this.layers, layer);
- },
-
- /**
- * APIMethod: setLayerIndex
- * Move the given layer to the specified (zero-based) index in the layer
- * list, changing its z-index in the map display. Use
- * map.getLayerIndex() to find out the current index of a layer. Note
- * that this cannot (or at least should not) be effectively used to
- * raise base layers above overlays.
- *
- * Parameters:
- * layer - {<OpenLayers.Layer>}
- * idx - {int}
- */
- setLayerIndex: function (layer, idx) {
- var base = this.getLayerIndex(layer);
- if (idx < 0) {
- idx = 0;
- } else if (idx > this.layers.length) {
- idx = this.layers.length;
- }
- if (base != idx) {
- this.layers.splice(base, 1);
- this.layers.splice(idx, 0, layer);
- for (var i=0, len=this.layers.length; i<len; i++) {
- this.setLayerZIndex(this.layers[i], i);
- }
- this.events.triggerEvent("changelayer", {
- layer: layer, property: "order"
- });
- if(this.allOverlays) {
- if(idx === 0) {
- this.setBaseLayer(layer);
- } else if(this.baseLayer !== this.layers[0]) {
- this.setBaseLayer(this.layers[0]);
- }
- }
- }
- },
-
- /**
- * APIMethod: raiseLayer
- * Change the index of the given layer by delta. If delta is positive,
- * the layer is moved up the map's layer stack; if delta is negative,
- * the layer is moved down. Again, note that this cannot (or at least
- * should not) be effectively used to raise base layers above overlays.
- *
- * Paremeters:
- * layer - {<OpenLayers.Layer>}
- * delta - {int}
- */
- raiseLayer: function (layer, delta) {
- var idx = this.getLayerIndex(layer) + delta;
- this.setLayerIndex(layer, idx);
- },
-
- /**
- * APIMethod: setBaseLayer
- * Allows user to specify one of the currently-loaded layers as the Map's
- * new base layer.
- *
- * Parameters:
- * newBaseLayer - {<OpenLayers.Layer>}
- */
- setBaseLayer: function(newBaseLayer) {
-
- if (newBaseLayer != this.baseLayer) {
-
- // ensure newBaseLayer is already loaded
- if (OpenLayers.Util.indexOf(this.layers, newBaseLayer) != -1) {
-
- // preserve center and scale when changing base layers
- var center = this.getCachedCenter();
- var newResolution = OpenLayers.Util.getResolutionFromScale(
- this.getScale(), newBaseLayer.units
- );
-
- // make the old base layer invisible
- if (this.baseLayer != null && !this.allOverlays) {
- this.baseLayer.setVisibility(false);
- }
-
- // set new baselayer
- this.baseLayer = newBaseLayer;
-
- if(!this.allOverlays || this.baseLayer.visibility) {
- this.baseLayer.setVisibility(true);
- // Layer may previously have been visible but not in range.
- // In this case we need to redraw it to make it visible.
- if (this.baseLayer.inRange === false) {
- this.baseLayer.redraw();
- }
- }
-
- // recenter the map
- if (center != null) {
- // new zoom level derived from old scale
- var newZoom = this.getZoomForResolution(
- newResolution || this.resolution, true
- );
- // zoom and force zoom change
- this.setCenter(center, newZoom, false, true);
- }
-
- this.events.triggerEvent("changebaselayer", {
- layer: this.baseLayer
- });
- }
- }
- },
-
-
- /********************************************************/
- /* */
- /* Control Functions */
- /* */
- /* The following functions deal with adding and */
- /* removing Controls to and from the Map */
- /* */
- /********************************************************/
-
- /**
- * APIMethod: addControl
- * Add the passed over control to the map. Optionally
- * position the control at the given pixel.
- *
- * Parameters:
- * control - {<OpenLayers.Control>}
- * px - {<OpenLayers.Pixel>}
- */
- addControl: function (control, px) {
- this.controls.push(control);
- this.addControlToMap(control, px);
- },
-
- /**
- * APIMethod: addControls
- * Add all of the passed over controls to the map.
- * You can pass over an optional second array
- * with pixel-objects to position the controls.
- * The indices of the two arrays should match and
- * you can add null as pixel for those controls
- * you want to be autopositioned.
- *
- * Parameters:
- * controls - {Array(<OpenLayers.Control>)}
- * pixels - {Array(<OpenLayers.Pixel>)}
- */
- addControls: function (controls, pixels) {
- var pxs = (arguments.length === 1) ? [] : pixels;
- for (var i=0, len=controls.length; i<len; i++) {
- var ctrl = controls[i];
- var px = (pxs[i]) ? pxs[i] : null;
- this.addControl( ctrl, px );
- }
- },
-
- /**
- * Method: addControlToMap
- *
- * Parameters:
- *
- * control - {<OpenLayers.Control>}
- * px - {<OpenLayers.Pixel>}
- */
- addControlToMap: function (control, px) {
- // If a control doesn't have a div at this point, it belongs in the
- // viewport.
- control.outsideViewport = (control.div != null);
-
- // If the map has a displayProjection, and the control doesn't, set
- // the display projection.
- if (this.displayProjection && !control.displayProjection) {
- control.displayProjection = this.displayProjection;
- }
-
- control.setMap(this);
- var div = control.draw(px);
- if (div) {
- if(!control.outsideViewport) {
- div.style.zIndex = this.Z_INDEX_BASE['Control'] +
- this.controls.length;
- this.viewPortDiv.appendChild( div );
- }
- }
- if(control.autoActivate) {
- control.activate();
- }
- },
-
- /**
- * APIMethod: getControl
- *
- * Parameters:
- * id - {String} ID of the control to return.
- *
- * Returns:
- * {<OpenLayers.Control>} The control from the map's list of controls
- * which has a matching 'id'. If none found,
- * returns null.
- */
- getControl: function (id) {
- var returnControl = null;
- for(var i=0, len=this.controls.length; i<len; i++) {
- var control = this.controls[i];
- if (control.id == id) {
- returnControl = control;
- break;
- }
- }
- return returnControl;
- },
-
- /**
- * APIMethod: removeControl
- * Remove a control from the map. Removes the control both from the map
- * object's internal array of controls, as well as from the map's
- * viewPort (assuming the control was not added outsideViewport)
- *
- * Parameters:
- * control - {<OpenLayers.Control>} The control to remove.
- */
- removeControl: function (control) {
- //make sure control is non-null and actually part of our map
- if ( (control) && (control == this.getControl(control.id)) ) {
- if (control.div && (control.div.parentNode == this.viewPortDiv)) {
- this.viewPortDiv.removeChild(control.div);
- }
- OpenLayers.Util.removeItem(this.controls, control);
- }
- },
-
- /********************************************************/
- /* */
- /* Popup Functions */
- /* */
- /* The following functions deal with adding and */
- /* removing Popups to and from the Map */
- /* */
- /********************************************************/
-
- /**
- * APIMethod: addPopup
- *
- * Parameters:
- * popup - {<OpenLayers.Popup>}
- * exclusive - {Boolean} If true, closes all other popups first
- */
- addPopup: function(popup, exclusive) {
-
- if (exclusive) {
- //remove all other popups from screen
- for (var i = this.popups.length - 1; i >= 0; --i) {
- this.removePopup(this.popups[i]);
- }
- }
-
- popup.map = this;
- this.popups.push(popup);
- var popupDiv = popup.draw();
- if (popupDiv) {
- popupDiv.style.zIndex = this.Z_INDEX_BASE['Popup'] +
- this.popups.length;
- this.layerContainerDiv.appendChild(popupDiv);
- }
- },
-
- /**
- * APIMethod: removePopup
- *
- * Parameters:
- * popup - {<OpenLayers.Popup>}
- */
- removePopup: function(popup) {
- OpenLayers.Util.removeItem(this.popups, popup);
- if (popup.div) {
- try { this.layerContainerDiv.removeChild(popup.div); }
- catch (e) { } // Popups sometimes apparently get disconnected
- // from the layerContainerDiv, and cause complaints.
- }
- popup.map = null;
- },
-
- /********************************************************/
- /* */
- /* Container Div Functions */
- /* */
- /* The following functions deal with the access to */
- /* and maintenance of the size of the container div */
- /* */
- /********************************************************/
-
- /**
- * APIMethod: getSize
- *
- * Returns:
- * {<OpenLayers.Size>} An <OpenLayers.Size> object that represents the
- * size, in pixels, of the div into which OpenLayers
- * has been loaded.
- * Note - A clone() of this locally cached variable is
- * returned, so as not to allow users to modify it.
- */
- getSize: function () {
- var size = null;
- if (this.size != null) {
- size = this.size.clone();
- }
- return size;
- },
-
- /**
- * APIMethod: updateSize
- * This function should be called by any external code which dynamically
- * changes the size of the map div (because mozilla wont let us catch
- * the "onresize" for an element)
- */
- updateSize: function() {
- // the div might have moved on the page, also
- var newSize = this.getCurrentSize();
- if (newSize && !isNaN(newSize.h) && !isNaN(newSize.w)) {
- this.events.clearMouseCache();
- var oldSize = this.getSize();
- if (oldSize == null) {
- this.size = oldSize = newSize;
- }
- if (!newSize.equals(oldSize)) {
-
- // store the new size
- this.size = newSize;
-
- //notify layers of mapresize
- for(var i=0, len=this.layers.length; i<len; i++) {
- this.layers[i].onMapResize();
- }
-
- var center = this.getCachedCenter();
-
- if (this.baseLayer != null && center != null) {
- var zoom = this.getZoom();
- this.zoom = null;
- this.setCenter(center, zoom);
- }
-
- }
- }
- this.events.triggerEvent("updatesize");
- },
-
- /**
- * Method: getCurrentSize
- *
- * Returns:
- * {<OpenLayers.Size>} A new <OpenLayers.Size> object with the dimensions
- * of the map div
- */
- getCurrentSize: function() {
-
- var size = new OpenLayers.Size(this.div.clientWidth,
- this.div.clientHeight);
-
- if (size.w == 0 && size.h == 0 || isNaN(size.w) && isNaN(size.h)) {
- size.w = this.div.offsetWidth;
- size.h = this.div.offsetHeight;
- }
- if (size.w == 0 && size.h == 0 || isNaN(size.w) && isNaN(size.h)) {
- size.w = parseInt(this.div.style.width);
- size.h = parseInt(this.div.style.height);
- }
- return size;
- },
-
- /**
- * Method: calculateBounds
- *
- * Parameters:
- * center - {<OpenLayers.LonLat>} Default is this.getCenter()
- * resolution - {float} Default is this.getResolution()
- *
- * Returns:
- * {<OpenLayers.Bounds>} A bounds based on resolution, center, and
- * current mapsize.
- */
- calculateBounds: function(center, resolution) {
-
- var extent = null;
-
- if (center == null) {
- center = this.getCachedCenter();
- }
- if (resolution == null) {
- resolution = this.getResolution();
- }
-
- if ((center != null) && (resolution != null)) {
- var halfWDeg = (this.size.w * resolution) / 2;
- var halfHDeg = (this.size.h * resolution) / 2;
-
- extent = new OpenLayers.Bounds(center.lon - halfWDeg,
- center.lat - halfHDeg,
- center.lon + halfWDeg,
- center.lat + halfHDeg);
- }
-
- return extent;
- },
-
-
- /********************************************************/
- /* */
- /* Zoom, Center, Pan Functions */
- /* */
- /* The following functions handle the validation, */
- /* getting and setting of the Zoom Level and Center */
- /* as well as the panning of the Map */
- /* */
- /********************************************************/
- /**
- * APIMethod: getCenter
- *
- * Returns:
- * {<OpenLayers.LonLat>}
- */
- getCenter: function () {
- var center = null;
- var cachedCenter = this.getCachedCenter();
- if (cachedCenter) {
- center = cachedCenter.clone();
- }
- return center;
- },
-
- /**
- * Method: getCachedCenter
- *
- * Returns:
- * {<OpenLayers.LonLat>}
- */
- getCachedCenter: function() {
- if (!this.center && this.size) {
- this.center = this.getLonLatFromViewPortPx({
- x: this.size.w / 2,
- y: this.size.h / 2
- });
- }
- return this.center;
- },
-
- /**
- * APIMethod: getZoom
- *
- * Returns:
- * {Integer}
- */
- getZoom: function () {
- return this.zoom;
- },
-
- /**
- * APIMethod: pan
- * Allows user to pan by a value of screen pixels
- *
- * Parameters:
- * dx - {Integer}
- * dy - {Integer}
- * options - {Object} Options to configure panning:
- * - *animate* {Boolean} Use panTo instead of setCenter. Default is true.
- * - *dragging* {Boolean} Call setCenter with dragging true. Default is
- * false.
- */
- pan: function(dx, dy, options) {
- options = OpenLayers.Util.applyDefaults(options, {
- animate: true,
- dragging: false
- });
- if (options.dragging) {
- if (dx != 0 || dy != 0) {
- this.moveByPx(dx, dy);
- }
- } else {
- // getCenter
- var centerPx = this.getViewPortPxFromLonLat(this.getCachedCenter());
-
- // adjust
- var newCenterPx = centerPx.add(dx, dy);
-
- if (this.dragging || !newCenterPx.equals(centerPx)) {
- var newCenterLonLat = this.getLonLatFromViewPortPx(newCenterPx);
- if (options.animate) {
- this.panTo(newCenterLonLat);
- } else {
- this.moveTo(newCenterLonLat);
- if(this.dragging) {
- this.dragging = false;
- this.events.triggerEvent("moveend");
- }
- }
- }
- }
-
- },
-
- /**
- * APIMethod: panTo
- * Allows user to pan to a new lonlat
- * If the new lonlat is in the current extent the map will slide smoothly
- *
- * Parameters:
- * lonlat - {<OpenLayers.LonLat>}
- */
- panTo: function(lonlat) {
- if (this.panTween && this.getExtent().scale(this.panRatio).containsLonLat(lonlat)) {
- var center = this.getCachedCenter();
-
- // center will not change, don't do nothing
- if (lonlat.equals(center)) {
- return;
- }
-
- var from = this.getPixelFromLonLat(center);
- var to = this.getPixelFromLonLat(lonlat);
- var vector = { x: to.x - from.x, y: to.y - from.y };
- var last = { x: 0, y: 0 };
-
- this.panTween.start( { x: 0, y: 0 }, vector, this.panDuration, {
- callbacks: {
- eachStep: OpenLayers.Function.bind(function(px) {
- var x = px.x - last.x,
- y = px.y - last.y;
- this.moveByPx(x, y);
- last.x = Math.round(px.x);
- last.y = Math.round(px.y);
- }, this),
- done: OpenLayers.Function.bind(function(px) {
- this.moveTo(lonlat);
- this.dragging = false;
- this.events.triggerEvent("moveend");
- }, this)
- }
- });
- } else {
- this.setCenter(lonlat);
- }
- },
-
- /**
- * APIMethod: setCenter
- * Set the map center (and optionally, the zoom level).
- *
- * Parameters:
- * lonlat - {<OpenLayers.LonLat>|Array} The new center location.
- * If provided as array, the first value is the x coordinate,
- * and the 2nd value is the y coordinate.
- * zoom - {Integer} Optional zoom level.
- * dragging - {Boolean} Specifies whether or not to trigger
- * movestart/end events
- * forceZoomChange - {Boolean} Specifies whether or not to trigger zoom
- * change events (needed on baseLayer change)
- *
- * TBD: reconsider forceZoomChange in 3.0
- */
- setCenter: function(lonlat, zoom, dragging, forceZoomChange) {
- if (this.panTween) {
- this.panTween.stop();
- }
- if (this.zoomTween) {
- this.zoomTween.stop();
- }
- this.moveTo(lonlat, zoom, {
- 'dragging': dragging,
- 'forceZoomChange': forceZoomChange
- });
- },
-
- /**
- * Method: moveByPx
- * Drag the map by pixels.
- *
- * Parameters:
- * dx - {Number}
- * dy - {Number}
- */
- moveByPx: function(dx, dy) {
- var hw = this.size.w / 2;
- var hh = this.size.h / 2;
- var x = hw + dx;
- var y = hh + dy;
- var wrapDateLine = this.baseLayer.wrapDateLine;
- var xRestriction = 0;
- var yRestriction = 0;
- if (this.restrictedExtent) {
- xRestriction = hw;
- yRestriction = hh;
- // wrapping the date line makes no sense for restricted extents
- wrapDateLine = false;
- }
- dx = wrapDateLine ||
- x <= this.maxPx.x - xRestriction &&
- x >= this.minPx.x + xRestriction ? Math.round(dx) : 0;
- dy = y <= this.maxPx.y - yRestriction &&
- y >= this.minPx.y + yRestriction ? Math.round(dy) : 0;
- if (dx || dy) {
- if (!this.dragging) {
- this.dragging = true;
- this.events.triggerEvent("movestart");
- }
- this.center = null;
- if (dx) {
- this.layerContainerOriginPx.x -= dx;
- this.minPx.x -= dx;
- this.maxPx.x -= dx;
- }
- if (dy) {
- this.layerContainerOriginPx.y -= dy;
- this.minPx.y -= dy;
- this.maxPx.y -= dy;
- }
- this.applyTransform();
- var layer, i, len;
- for (i=0, len=this.layers.length; i<len; ++i) {
- layer = this.layers[i];
- if (layer.visibility &&
- (layer === this.baseLayer || layer.inRange)) {
- layer.moveByPx(dx, dy);
- layer.events.triggerEvent("move");
- }
- }
- this.events.triggerEvent("move");
- }
- },
-
- /**
- * Method: adjustZoom
- *
- * Parameters:
- * zoom - {Number} The zoom level to adjust
- *
- * Returns:
- * {Integer} Adjusted zoom level that shows a map not wider than its
- * <baseLayer>'s maxExtent.
- */
- adjustZoom: function(zoom) {
- if (this.baseLayer && this.baseLayer.wrapDateLine) {
- var resolution, resolutions = this.baseLayer.resolutions,
- maxResolution = this.getMaxExtent().getWidth() / this.size.w;
- if (this.getResolutionForZoom(zoom) > maxResolution) {
- if (this.fractionalZoom) {
- zoom = this.getZoomForResolution(maxResolution);
- } else {
- for (var i=zoom|0, ii=resolutions.length; i<ii; ++i) {
- if (resolutions[i] <= maxResolution) {
- zoom = i;
- break;
- }
- }
- }
- }
- }
- return zoom;
- },
-
- /**
- * APIMethod: getMinZoom
- * Returns the minimum zoom level for the current map view. If the base
- * layer is configured with <wrapDateLine> set to true, this will be the
- * first zoom level that shows no more than one world width in the current
- * map viewport. Components that rely on this value (e.g. zoom sliders)
- * should also listen to the map's "updatesize" event and call this method
- * in the "updatesize" listener.
- *
- * Returns:
- * {Number} Minimum zoom level that shows a map not wider than its
- * <baseLayer>'s maxExtent. This is an Integer value, unless the map is
- * configured with <fractionalZoom> set to true.
- */
- getMinZoom: function() {
- return this.adjustZoom(0);
- },
-
- /**
- * Method: moveTo
- *
- * Parameters:
- * lonlat - {<OpenLayers.LonLat>}
- * zoom - {Integer}
- * options - {Object}
- */
- moveTo: function(lonlat, zoom, options) {
- if (lonlat != null && !(lonlat instanceof OpenLayers.LonLat)) {
- lonlat = new OpenLayers.LonLat(lonlat);
- }
- if (!options) {
- options = {};
- }
- if (zoom != null) {
- zoom = parseFloat(zoom);
- if (!this.fractionalZoom) {
- zoom = Math.round(zoom);
- }
- }
- var requestedZoom = zoom;
- zoom = this.adjustZoom(zoom);
- if (zoom !== requestedZoom) {
- // zoom was adjusted, so keep old lonlat to avoid panning
- lonlat = this.getCenter();
- }
- // dragging is false by default
- var dragging = options.dragging || this.dragging;
- // forceZoomChange is false by default
- var forceZoomChange = options.forceZoomChange;
-
- if (!this.getCachedCenter() && !this.isValidLonLat(lonlat)) {
- lonlat = this.maxExtent.getCenterLonLat();
- this.center = lonlat.clone();
- }
-
- if(this.restrictedExtent != null) {
- // In 3.0, decide if we want to change interpretation of maxExtent.
- if(lonlat == null) {
- lonlat = this.center;
- }
- if(zoom == null) {
- zoom = this.getZoom();
- }
- var resolution = this.getResolutionForZoom(zoom);
- var extent = this.calculateBounds(lonlat, resolution);
- if(!this.restrictedExtent.containsBounds(extent)) {
- var maxCenter = this.restrictedExtent.getCenterLonLat();
- if(extent.getWidth() > this.restrictedExtent.getWidth()) {
- lonlat = new OpenLayers.LonLat(maxCenter.lon, lonlat.lat);
- } else if(extent.left < this.restrictedExtent.left) {
- lonlat = lonlat.add(this.restrictedExtent.left -
- extent.left, 0);
- } else if(extent.right > this.restrictedExtent.right) {
- lonlat = lonlat.add(this.restrictedExtent.right -
- extent.right, 0);
- }
- if(extent.getHeight() > this.restrictedExtent.getHeight()) {
- lonlat = new OpenLayers.LonLat(lonlat.lon, maxCenter.lat);
- } else if(extent.bottom < this.restrictedExtent.bottom) {
- lonlat = lonlat.add(0, this.restrictedExtent.bottom -
- extent.bottom);
- }
- else if(extent.top > this.restrictedExtent.top) {
- lonlat = lonlat.add(0, this.restrictedExtent.top -
- extent.top);
- }
- }
- }
-
- var zoomChanged = forceZoomChange || (
- (this.isValidZoomLevel(zoom)) &&
- (zoom != this.getZoom()) );
-
- var centerChanged = (this.isValidLonLat(lonlat)) &&
- (!lonlat.equals(this.center));
-
- // if neither center nor zoom will change, no need to do anything
- if (zoomChanged || centerChanged || dragging) {
- dragging || this.events.triggerEvent("movestart", {
- zoomChanged: zoomChanged
- });
-
- if (centerChanged) {
- if (!zoomChanged && this.center) {
- // if zoom hasnt changed, just slide layerContainer
- // (must be done before setting this.center to new value)
- this.centerLayerContainer(lonlat);
- }
- this.center = lonlat.clone();
- }
-
- var res = zoomChanged ?
- this.getResolutionForZoom(zoom) : this.getResolution();
- // (re)set the layerContainerDiv's location
- if (zoomChanged || this.layerContainerOrigin == null) {
- this.layerContainerOrigin = this.getCachedCenter();
- this.layerContainerOriginPx.x = 0;
- this.layerContainerOriginPx.y = 0;
- this.applyTransform();
- var maxExtent = this.getMaxExtent({restricted: true});
- var maxExtentCenter = maxExtent.getCenterLonLat();
- var lonDelta = this.center.lon - maxExtentCenter.lon;
- var latDelta = maxExtentCenter.lat - this.center.lat;
- var extentWidth = Math.round(maxExtent.getWidth() / res);
- var extentHeight = Math.round(maxExtent.getHeight() / res);
- this.minPx = {
- x: (this.size.w - extentWidth) / 2 - lonDelta / res,
- y: (this.size.h - extentHeight) / 2 - latDelta / res
- };
- this.maxPx = {
- x: this.minPx.x + Math.round(maxExtent.getWidth() / res),
- y: this.minPx.y + Math.round(maxExtent.getHeight() / res)
- };
- }
-
- if (zoomChanged) {
- this.zoom = zoom;
- this.resolution = res;
- }
-
- var bounds = this.getExtent();
-
- //send the move call to the baselayer and all the overlays
-
- if(this.baseLayer.visibility) {
- this.baseLayer.moveTo(bounds, zoomChanged, options.dragging);
- options.dragging || this.baseLayer.events.triggerEvent(
- "moveend", {zoomChanged: zoomChanged}
- );
- }
-
- bounds = this.baseLayer.getExtent();
-
- for (var i=this.layers.length-1; i>=0; --i) {
- var layer = this.layers[i];
- if (layer !== this.baseLayer && !layer.isBaseLayer) {
- var inRange = layer.calculateInRange();
- if (layer.inRange != inRange) {
- // the inRange property has changed. If the layer is
- // no longer in range, we turn it off right away. If
- // the layer is no longer out of range, the moveTo
- // call below will turn on the layer.
- layer.inRange = inRange;
- if (!inRange) {
- layer.display(false);
- }
- this.events.triggerEvent("changelayer", {
- layer: layer, property: "visibility"
- });
- }
- if (inRange && layer.visibility) {
- layer.moveTo(bounds, zoomChanged, options.dragging);
- options.dragging || layer.events.triggerEvent(
- "moveend", {zoomChanged: zoomChanged}
- );
- }
- }
- }
-
- this.events.triggerEvent("move");
- dragging || this.events.triggerEvent("moveend");
-
- if (zoomChanged) {
- //redraw popups
- for (var i=0, len=this.popups.length; i<len; i++) {
- this.popups[i].updatePosition();
- }
- this.events.triggerEvent("zoomend");
- }
- }
- },
-
- /**
- * Method: centerLayerContainer
- * This function takes care to recenter the layerContainerDiv.
- *
- * Parameters:
- * lonlat - {<OpenLayers.LonLat>}
- */
- centerLayerContainer: function (lonlat) {
- var originPx = this.getViewPortPxFromLonLat(this.layerContainerOrigin);
- var newPx = this.getViewPortPxFromLonLat(lonlat);
-
- if ((originPx != null) && (newPx != null)) {
- var oldLeft = this.layerContainerOriginPx.x;
- var oldTop = this.layerContainerOriginPx.y;
- var newLeft = Math.round(originPx.x - newPx.x);
- var newTop = Math.round(originPx.y - newPx.y);
- this.applyTransform(
- (this.layerContainerOriginPx.x = newLeft),
- (this.layerContainerOriginPx.y = newTop));
- var dx = oldLeft - newLeft;
- var dy = oldTop - newTop;
- this.minPx.x -= dx;
- this.maxPx.x -= dx;
- this.minPx.y -= dy;
- this.maxPx.y -= dy;
- }
- },
-
- /**
- * Method: isValidZoomLevel
- *
- * Parameters:
- * zoomLevel - {Integer}
- *
- * Returns:
- * {Boolean} Whether or not the zoom level passed in is non-null and
- * within the min/max range of zoom levels.
- */
- isValidZoomLevel: function(zoomLevel) {
- return ( (zoomLevel != null) &&
- (zoomLevel >= 0) &&
- (zoomLevel < this.getNumZoomLevels()) );
- },
-
- /**
- * Method: isValidLonLat
- *
- * Parameters:
- * lonlat - {<OpenLayers.LonLat>}
- *
- * Returns:
- * {Boolean} Whether or not the lonlat passed in is non-null and within
- * the maxExtent bounds
- */
- isValidLonLat: function(lonlat) {
- var valid = false;
- if (lonlat != null) {
- var maxExtent = this.getMaxExtent();
- var worldBounds = this.baseLayer.wrapDateLine && maxExtent;
- valid = maxExtent.containsLonLat(lonlat, {worldBounds: worldBounds});
- }
- return valid;
- },
-
- /********************************************************/
- /* */
- /* Layer Options */
- /* */
- /* Accessor functions to Layer Options parameters */
- /* */
- /********************************************************/
-
- /**
- * APIMethod: getProjection
- * This method returns a string representing the projection. In
- * the case of projection support, this will be the srsCode which
- * is loaded -- otherwise it will simply be the string value that
- * was passed to the projection at startup.
- *
- * FIXME: In 3.0, we will remove getProjectionObject, and instead
- * return a Projection object from this function.
- *
- * Returns:
- * {String} The Projection string from the base layer or null.
- */
- getProjection: function() {
- var projection = this.getProjectionObject();
- return projection ? projection.getCode() : null;
- },
-
- /**
- * APIMethod: getProjectionObject
- * Returns the projection obect from the baselayer.
- *
- * Returns:
- * {<OpenLayers.Projection>} The Projection of the base layer.
- */
- getProjectionObject: function() {
- var projection = null;
- if (this.baseLayer != null) {
- projection = this.baseLayer.projection;
- }
- return projection;
- },
-
- /**
- * APIMethod: getMaxResolution
- *
- * Returns:
- * {String} The Map's Maximum Resolution
- */
- getMaxResolution: function() {
- var maxResolution = null;
- if (this.baseLayer != null) {
- maxResolution = this.baseLayer.maxResolution;
- }
- return maxResolution;
- },
-
- /**
- * APIMethod: getMaxExtent
- *
- * Parameters:
- * options - {Object}
- *
- * Allowed Options:
- * restricted - {Boolean} If true, returns restricted extent (if it is
- * available.)
- *
- * Returns:
- * {<OpenLayers.Bounds>} The maxExtent property as set on the current
- * baselayer, unless the 'restricted' option is set, in which case
- * the 'restrictedExtent' option from the map is returned (if it
- * is set).
- */
- getMaxExtent: function (options) {
- var maxExtent = null;
- if(options && options.restricted && this.restrictedExtent){
- maxExtent = this.restrictedExtent;
- } else if (this.baseLayer != null) {
- maxExtent = this.baseLayer.maxExtent;
- }
- return maxExtent;
- },
-
- /**
- * APIMethod: getNumZoomLevels
- *
- * Returns:
- * {Integer} The total number of zoom levels that can be displayed by the
- * current baseLayer.
- */
- getNumZoomLevels: function() {
- var numZoomLevels = null;
- if (this.baseLayer != null) {
- numZoomLevels = this.baseLayer.numZoomLevels;
- }
- return numZoomLevels;
- },
-
- /********************************************************/
- /* */
- /* Baselayer Functions */
- /* */
- /* The following functions, all publicly exposed */
- /* in the API?, are all merely wrappers to the */
- /* the same calls on whatever layer is set as */
- /* the current base layer */
- /* */
- /********************************************************/
-
- /**
- * APIMethod: getExtent
- *
- * Returns:
- * {<OpenLayers.Bounds>} A Bounds object which represents the lon/lat
- * bounds of the current viewPort.
- * If no baselayer is set, returns null.
- */
- getExtent: function () {
- var extent = null;
- if (this.baseLayer != null) {
- extent = this.baseLayer.getExtent();
- }
- return extent;
- },
-
- /**
- * APIMethod: getResolution
- *
- * Returns:
- * {Float} The current resolution of the map.
- * If no baselayer is set, returns null.
- */
- getResolution: function () {
- var resolution = null;
- if (this.baseLayer != null) {
- resolution = this.baseLayer.getResolution();
- } else if(this.allOverlays === true && this.layers.length > 0) {
- // while adding the 1st layer to the map in allOverlays mode,
- // this.baseLayer is not set yet when we need the resolution
- // for calculateInRange.
- resolution = this.layers[0].getResolution();
- }
- return resolution;
- },
-
- /**
- * APIMethod: getUnits
- *
- * Returns:
- * {Float} The current units of the map.
- * If no baselayer is set, returns null.
- */
- getUnits: function () {
- var units = null;
- if (this.baseLayer != null) {
- units = this.baseLayer.units;
- }
- return units;
- },
-
- /**
- * APIMethod: getScale
- *
- * Returns:
- * {Float} The current scale denominator of the map.
- * If no baselayer is set, returns null.
- */
- getScale: function () {
- var scale = null;
- if (this.baseLayer != null) {
- var res = this.getResolution();
- var units = this.baseLayer.units;
- scale = OpenLayers.Util.getScaleFromResolution(res, units);
- }
- return scale;
- },
-
-
- /**
- * APIMethod: getZoomForExtent
- *
- * Parameters:
- * bounds - {<OpenLayers.Bounds>}
- * closest - {Boolean} Find the zoom level that most closely fits the
- * specified bounds. Note that this may result in a zoom that does
- * not exactly contain the entire extent.
- * Default is false.
- *
- * Returns:
- * {Integer} A suitable zoom level for the specified bounds.
- * If no baselayer is set, returns null.
- */
- getZoomForExtent: function (bounds, closest) {
- var zoom = null;
- if (this.baseLayer != null) {
- zoom = this.baseLayer.getZoomForExtent(bounds, closest);
- }
- return zoom;
- },
-
- /**
- * APIMethod: getResolutionForZoom
- *
- * Parameters:
- * zoom - {Float}
- *
- * Returns:
- * {Float} A suitable resolution for the specified zoom. If no baselayer
- * is set, returns null.
- */
- getResolutionForZoom: function(zoom) {
- var resolution = null;
- if(this.baseLayer) {
- resolution = this.baseLayer.getResolutionForZoom(zoom);
- }
- return resolution;
- },
-
- /**
- * APIMethod: getZoomForResolution
- *
- * Parameters:
- * resolution - {Float}
- * closest - {Boolean} Find the zoom level that corresponds to the absolute
- * closest resolution, which may result in a zoom whose corresponding
- * resolution is actually smaller than we would have desired (if this
- * is being called from a getZoomForExtent() call, then this means that
- * the returned zoom index might not actually contain the entire
- * extent specified... but it'll be close).
- * Default is false.
- *
- * Returns:
- * {Integer} A suitable zoom level for the specified resolution.
- * If no baselayer is set, returns null.
- */
- getZoomForResolution: function(resolution, closest) {
- var zoom = null;
- if (this.baseLayer != null) {
- zoom = this.baseLayer.getZoomForResolution(resolution, closest);
- }
- return zoom;
- },
-
- /********************************************************/
- /* */
- /* Zooming Functions */
- /* */
- /* The following functions, all publicly exposed */
- /* in the API, are all merely wrappers to the */
- /* the setCenter() function */
- /* */
- /********************************************************/
-
- /**
- * APIMethod: zoomTo
- * Zoom to a specific zoom level. Zooming will be animated unless the map
- * is configured with {zoomMethod: null}. To zoom without animation, use
- * <setCenter> without a lonlat argument.
- *
- * Parameters:
- * zoom - {Integer}
- */
- zoomTo: function(zoom, xy) {
- // non-API arguments:
- // xy - {<OpenLayers.Pixel>} optional zoom origin
-
- var map = this;
- if (map.isValidZoomLevel(zoom)) {
- if (map.baseLayer.wrapDateLine) {
- zoom = map.adjustZoom(zoom);
- }
- if (map.zoomTween) {
- var currentRes = map.getResolution(),
- targetRes = map.getResolutionForZoom(zoom),
- start = {scale: 1},
- end = {scale: currentRes / targetRes};
- if (map.zoomTween.playing && map.zoomTween.duration < 3 * map.zoomDuration) {
- // update the end scale, and reuse the running zoomTween
- map.zoomTween.finish = {
- scale: map.zoomTween.finish.scale * end.scale
- };
- } else {
- if (!xy) {
- var size = map.getSize();
- xy = {x: size.w / 2, y: size.h / 2};
- }
- map.zoomTween.start(start, end, map.zoomDuration, {
- minFrameRate: 50, // don't spend much time zooming
- callbacks: {
- eachStep: function(data) {
- var containerOrigin = map.layerContainerOriginPx,
- scale = data.scale,
- dx = ((scale - 1) * (containerOrigin.x - xy.x)) | 0,
- dy = ((scale - 1) * (containerOrigin.y - xy.y)) | 0;
- map.applyTransform(containerOrigin.x + dx, containerOrigin.y + dy, scale);
- },
- done: function(data) {
- map.applyTransform();
- var resolution = map.getResolution() / data.scale,
- zoom = map.getZoomForResolution(resolution, true)
- map.moveTo(map.getZoomTargetCenter(xy, resolution), zoom, true);
- }
- }
- });
- }
- } else {
- var center = xy ?
- map.getZoomTargetCenter(xy, map.getResolutionForZoom(zoom)) :
- null;
- map.setCenter(center, zoom);
- }
- }
- },
-
- /**
- * APIMethod: zoomIn
- *
- */
- zoomIn: function() {
- this.zoomTo(this.getZoom() + 1);
- },
-
- /**
- * APIMethod: zoomOut
- *
- */
- zoomOut: function() {
- this.zoomTo(this.getZoom() - 1);
- },
-
- /**
- * APIMethod: zoomToExtent
- * Zoom to the passed in bounds, recenter
- *
- * Parameters:
- * bounds - {<OpenLayers.Bounds>|Array} If provided as an array, the array
- * should consist of four values (left, bottom, right, top).
- * closest - {Boolean} Find the zoom level that most closely fits the
- * specified bounds. Note that this may result in a zoom that does
- * not exactly contain the entire extent.
- * Default is false.
- *
- */
- zoomToExtent: function(bounds, closest) {
- if (!(bounds instanceof OpenLayers.Bounds)) {
- bounds = new OpenLayers.Bounds(bounds);
- }
- var center = bounds.getCenterLonLat();
- if (this.baseLayer.wrapDateLine) {
- var maxExtent = this.getMaxExtent();
-
- //fix straddling bounds (in the case of a bbox that straddles the
- // dateline, it's left and right boundaries will appear backwards.
- // we fix this by allowing a right value that is greater than the
- // max value at the dateline -- this allows us to pass a valid
- // bounds to calculate zoom)
- //
- bounds = bounds.clone();
- while (bounds.right < bounds.left) {
- bounds.right += maxExtent.getWidth();
- }
- //if the bounds was straddling (see above), then the center point
- // we got from it was wrong. So we take our new bounds and ask it
- // for the center.
- //
- center = bounds.getCenterLonLat().wrapDateLine(maxExtent);
- }
- this.setCenter(center, this.getZoomForExtent(bounds, closest));
- },
-
- /**
- * APIMethod: zoomToMaxExtent
- * Zoom to the full extent and recenter.
- *
- * Parameters:
- * options - {Object}
- *
- * Allowed Options:
- * restricted - {Boolean} True to zoom to restricted extent if it is
- * set. Defaults to true.
- */
- zoomToMaxExtent: function(options) {
- //restricted is true by default
- var restricted = (options) ? options.restricted : true;
-
- var maxExtent = this.getMaxExtent({
- 'restricted': restricted
- });
- this.zoomToExtent(maxExtent);
- },
-
- /**
- * APIMethod: zoomToScale
- * Zoom to a specified scale
- *
- * Parameters:
- * scale - {float}
- * closest - {Boolean} Find the zoom level that most closely fits the
- * specified scale. Note that this may result in a zoom that does
- * not exactly contain the entire extent.
- * Default is false.
- *
- */
- zoomToScale: function(scale, closest) {
- var res = OpenLayers.Util.getResolutionFromScale(scale,
- this.baseLayer.units);
-
- var halfWDeg = (this.size.w * res) / 2;
- var halfHDeg = (this.size.h * res) / 2;
- var center = this.getCachedCenter();
-
- var extent = new OpenLayers.Bounds(center.lon - halfWDeg,
- center.lat - halfHDeg,
- center.lon + halfWDeg,
- center.lat + halfHDeg);
- this.zoomToExtent(extent, closest);
- },
-
- /********************************************************/
- /* */
- /* Translation Functions */
- /* */
- /* The following functions translate between */
- /* LonLat, LayerPx, and ViewPortPx */
- /* */
- /********************************************************/
-
- //
- // TRANSLATION: LonLat <-> ViewPortPx
- //
-
- /**
- * Method: getLonLatFromViewPortPx
- *
- * Parameters:
- * viewPortPx - {<OpenLayers.Pixel>|Object} An OpenLayers.Pixel or
- * an object with a 'x'
- * and 'y' properties.
- *
- * Returns:
- * {<OpenLayers.LonLat>} An OpenLayers.LonLat which is the passed-in view
- * port <OpenLayers.Pixel>, translated into lon/lat
- * by the current base layer.
- */
- getLonLatFromViewPortPx: function (viewPortPx) {
- var lonlat = null;
- if (this.baseLayer != null) {
- lonlat = this.baseLayer.getLonLatFromViewPortPx(viewPortPx);
- }
- return lonlat;
- },
-
- /**
- * APIMethod: getViewPortPxFromLonLat
- *
- * Parameters:
- * lonlat - {<OpenLayers.LonLat>}
- *
- * Returns:
- * {<OpenLayers.Pixel>} An OpenLayers.Pixel which is the passed-in
- * <OpenLayers.LonLat>, translated into view port
- * pixels by the current base layer.
- */
- getViewPortPxFromLonLat: function (lonlat) {
- var px = null;
- if (this.baseLayer != null) {
- px = this.baseLayer.getViewPortPxFromLonLat(lonlat);
- }
- return px;
- },
-
- /**
- * Method: getZoomTargetCenter
- *
- * Parameters:
- * xy - {<OpenLayers.Pixel>} The zoom origin pixel location on the screen
- * resolution - {Float} The resolution we want to get the center for
- *
- * Returns:
- * {<OpenLayers.LonLat>} The location of the map center after the
- * transformation described by the origin xy and the target resolution.
- */
- getZoomTargetCenter: function (xy, resolution) {
- var lonlat = null,
- size = this.getSize(),
- deltaX = size.w/2 - xy.x,
- deltaY = xy.y - size.h/2,
- zoomPoint = this.getLonLatFromPixel(xy);
- if (zoomPoint) {
- lonlat = new OpenLayers.LonLat(
- zoomPoint.lon + deltaX * resolution,
- zoomPoint.lat + deltaY * resolution
- );
- }
- return lonlat;
- },
-
- //
- // CONVENIENCE TRANSLATION FUNCTIONS FOR API
- //
-
- /**
- * APIMethod: getLonLatFromPixel
- *
- * Parameters:
- * px - {<OpenLayers.Pixel>|Object} An OpenLayers.Pixel or an object with
- * a 'x' and 'y' properties.
- *
- * Returns:
- * {<OpenLayers.LonLat>} An OpenLayers.LonLat corresponding to the given
- * OpenLayers.Pixel, translated into lon/lat by the
- * current base layer
- */
- getLonLatFromPixel: function (px) {
- return this.getLonLatFromViewPortPx(px);
- },
-
- /**
- * APIMethod: getPixelFromLonLat
- * Returns a pixel location given a map location. The map location is
- * translated to an integer pixel location (in viewport pixel
- * coordinates) by the current base layer.
- *
- * Parameters:
- * lonlat - {<OpenLayers.LonLat>} A map location.
- *
- * Returns:
- * {<OpenLayers.Pixel>} An OpenLayers.Pixel corresponding to the
- * <OpenLayers.LonLat> translated into view port pixels by the current
- * base layer.
- */
- getPixelFromLonLat: function (lonlat) {
- var px = this.getViewPortPxFromLonLat(lonlat);
- px.x = Math.round(px.x);
- px.y = Math.round(px.y);
- return px;
- },
-
- /**
- * Method: getGeodesicPixelSize
- *
- * Parameters:
- * px - {<OpenLayers.Pixel>} The pixel to get the geodesic length for. If
- * not provided, the center pixel of the map viewport will be used.
- *
- * Returns:
- * {<OpenLayers.Size>} The geodesic size of the pixel in kilometers.
- */
- getGeodesicPixelSize: function(px) {
- var lonlat = px ? this.getLonLatFromPixel(px) : (
- this.getCachedCenter() || new OpenLayers.LonLat(0, 0));
- var res = this.getResolution();
- var left = lonlat.add(-res / 2, 0);
- var right = lonlat.add(res / 2, 0);
- var bottom = lonlat.add(0, -res / 2);
- var top = lonlat.add(0, res / 2);
- var dest = new OpenLayers.Projection("EPSG:4326");
- var source = this.getProjectionObject() || dest;
- if(!source.equals(dest)) {
- left.transform(source, dest);
- right.transform(source, dest);
- bottom.transform(source, dest);
- top.transform(source, dest);
- }
-
- return new OpenLayers.Size(
- OpenLayers.Util.distVincenty(left, right),
- OpenLayers.Util.distVincenty(bottom, top)
- );
- },
-
-
-
- //
- // TRANSLATION: ViewPortPx <-> LayerPx
- //
-
- /**
- * APIMethod: getViewPortPxFromLayerPx
- *
- * Parameters:
- * layerPx - {<OpenLayers.Pixel>}
- *
- * Returns:
- * {<OpenLayers.Pixel>} Layer Pixel translated into ViewPort Pixel
- * coordinates
- */
- getViewPortPxFromLayerPx:function(layerPx) {
- var viewPortPx = null;
- if (layerPx != null) {
- var dX = this.layerContainerOriginPx.x;
- var dY = this.layerContainerOriginPx.y;
- viewPortPx = layerPx.add(dX, dY);
- }
- return viewPortPx;
- },
-
- /**
- * APIMethod: getLayerPxFromViewPortPx
- *
- * Parameters:
- * viewPortPx - {<OpenLayers.Pixel>}
- *
- * Returns:
- * {<OpenLayers.Pixel>} ViewPort Pixel translated into Layer Pixel
- * coordinates
- */
- getLayerPxFromViewPortPx:function(viewPortPx) {
- var layerPx = null;
- if (viewPortPx != null) {
- var dX = -this.layerContainerOriginPx.x;
- var dY = -this.layerContainerOriginPx.y;
- layerPx = viewPortPx.add(dX, dY);
- if (isNaN(layerPx.x) || isNaN(layerPx.y)) {
- layerPx = null;
- }
- }
- return layerPx;
- },
-
- //
- // TRANSLATION: LonLat <-> LayerPx
- //
-
- /**
- * Method: getLonLatFromLayerPx
- *
- * Parameters:
- * px - {<OpenLayers.Pixel>}
- *
- * Returns:
- * {<OpenLayers.LonLat>}
- */
- getLonLatFromLayerPx: function (px) {
- //adjust for displacement of layerContainerDiv
- px = this.getViewPortPxFromLayerPx(px);
- return this.getLonLatFromViewPortPx(px);
- },
-
- /**
- * APIMethod: getLayerPxFromLonLat
- *
- * Parameters:
- * lonlat - {<OpenLayers.LonLat>} lonlat
- *
- * Returns:
- * {<OpenLayers.Pixel>} An OpenLayers.Pixel which is the passed-in
- * <OpenLayers.LonLat>, translated into layer pixels
- * by the current base layer
- */
- getLayerPxFromLonLat: function (lonlat) {
- //adjust for displacement of layerContainerDiv
- var px = this.getPixelFromLonLat(lonlat);
- return this.getLayerPxFromViewPortPx(px);
- },
-
- /**
- * Method: applyTransform
- * Applies the given transform to the <layerContainerDiv>. This method has
- * a 2-stage fallback from translate3d/scale3d via translate/scale to plain
- * style.left/style.top, in which case no scaling is supported.
- *
- * Parameters:
- * x - {Number} x parameter for the translation. Defaults to the x value of
- * the map's <layerContainerOriginPx>
- * y - {Number} y parameter for the translation. Defaults to the y value of
- * the map's <layerContainerOriginPx>
- * scale - {Number} scale. Defaults to 1 if not provided.
- */
- applyTransform: function(x, y, scale) {
- scale = scale || 1;
- var origin = this.layerContainerOriginPx,
- needTransform = scale !== 1;
- x = x || origin.x;
- y = y || origin.y;
-
- var style = this.layerContainerDiv.style,
- transform = this.applyTransform.transform,
- template = this.applyTransform.template;
-
- if (transform === undefined) {
- transform = OpenLayers.Util.vendorPrefix.style('transform');
- this.applyTransform.transform = transform;
- if (transform) {
- // Try translate3d, but only if the viewPortDiv has a transform
- // defined in a stylesheet
- var computedStyle = OpenLayers.Element.getStyle(this.viewPortDiv,
- OpenLayers.Util.vendorPrefix.css('transform'));
- if (!computedStyle || computedStyle !== 'none') {
- template = ['translate3d(', ',0) ', 'scale3d(', ',1)'];
- style[transform] = [template[0], '0,0', template[1]].join('');
- }
- // If no transform is defined in the stylesheet or translate3d
- // does not stick, use translate and scale
- if (!template || !~style[transform].indexOf(template[0])) {
- template = ['translate(', ') ', 'scale(', ')'];
- }
- this.applyTransform.template = template;
- }
- }
-
- // If we do 3d transforms, we always want to use them. If we do 2d
- // transforms, we only use them when we need to.
- if (transform !== null && (template[0] === 'translate3d(' || needTransform === true)) {
- // Our 2d transforms are combined with style.left and style.top, so
- // adjust x and y values and set the origin as left and top
- if (needTransform === true && template[0] === 'translate(') {
- x -= origin.x;
- y -= origin.y;
- style.left = origin.x + 'px';
- style.top = origin.y + 'px';
- }
- style[transform] = [
- template[0], x, 'px,', y, 'px', template[1],
- template[2], scale, ',', scale, template[3]
- ].join('');
- } else {
- style.left = x + 'px';
- style.top = y + 'px';
- // We previously might have had needTransform, so remove transform
- if (transform !== null) {
- style[transform] = '';
- }
- }
- },
-
- CLASS_NAME: "OpenLayers.Map"
-});
-
-/**
- * Constant: TILE_WIDTH
- * {Integer} 256 Default tile width (unless otherwise specified)
- */
-OpenLayers.Map.TILE_WIDTH = 256;
-/**
- * Constant: TILE_HEIGHT
- * {Integer} 256 Default tile height (unless otherwise specified)
- */
-OpenLayers.Map.TILE_HEIGHT = 256;