diff options
Diffstat (limited to 'misc/openlayers/lib/OpenLayers/Map.js')
-rw-r--r-- | misc/openlayers/lib/OpenLayers/Map.js | 2867 |
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; |