/* 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/Map.js * @requires OpenLayers/Projection.js */ /** * Class: OpenLayers.Layer */ OpenLayers.Layer = OpenLayers.Class({ /** * APIProperty: id * {String} */ id: null, /** * APIProperty: name * {String} */ name: null, /** * APIProperty: div * {DOMElement} */ div: null, /** * APIProperty: opacity * {Float} The layer's opacity. Float number between 0.0 and 1.0. Default * is 1. */ opacity: 1, /** * APIProperty: alwaysInRange * {Boolean} If a layer's display should not be scale-based, this should * be set to true. This will cause the layer, as an overlay, to always * be 'active', by always returning true from the calculateInRange() * function. * * If not explicitly specified for a layer, its value will be * determined on startup in initResolutions() based on whether or not * any scale-specific properties have been set as options on the * layer. If no scale-specific options have been set on the layer, we * assume that it should always be in range. * * See #987 for more info. */ alwaysInRange: null, /** * Constant: RESOLUTION_PROPERTIES * {Array} The properties that are used for calculating resolutions * information. */ RESOLUTION_PROPERTIES: [ 'scales', 'resolutions', 'maxScale', 'minScale', 'maxResolution', 'minResolution', 'numZoomLevels', 'maxZoomLevel' ], /** * APIProperty: events * {} * * Register a listener for a particular event with the following syntax: * (code) * layer.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 layer.events.object. * element - {DOMElement} A reference to layer.events.element. * * Supported map event types: * loadstart - Triggered when layer loading starts. When using a Vector * layer with a Fixed or BBOX strategy, the event object includes * a *filter* property holding the OpenLayers.Filter used when * calling read on the protocol. * loadend - Triggered when layer loading ends. When using a Vector layer * with a Fixed or BBOX strategy, the event object includes a * *response* property holding an OpenLayers.Protocol.Response object. * visibilitychanged - Triggered when the layer's visibility property is * changed, e.g. by turning the layer on or off in the layer switcher. * Note that the actual visibility of the layer can also change if it * gets out of range (see ). If you also want to catch * these cases, register for the map's 'changelayer' event instead. * move - Triggered when layer moves (triggered with every mousemove * during a drag). * moveend - Triggered when layer is done moving, object passed as * argument has a zoomChanged boolean property which tells that the * zoom has changed. * added - Triggered after the layer is added to a map. Listeners will * receive an object with a *map* property referencing the map and a * *layer* property referencing the layer. * removed - Triggered after the layer is removed from the map. Listeners * will receive an object with a *map* property referencing the map and * a *layer* property referencing the layer. */ events: null, /** * APIProperty: map * {} This variable is set when the layer is added to * the map, via the accessor function setMap(). */ map: null, /** * APIProperty: isBaseLayer * {Boolean} Whether or not the layer is a base layer. This should be set * individually by all subclasses. Default is false */ isBaseLayer: false, /** * Property: alpha * {Boolean} The layer's images have an alpha channel. Default is false. */ alpha: false, /** * APIProperty: displayInLayerSwitcher * {Boolean} Display the layer's name in the layer switcher. Default is * true. */ displayInLayerSwitcher: true, /** * APIProperty: visibility * {Boolean} The layer should be displayed in the map. Default is true. */ visibility: true, /** * APIProperty: attribution * {String} Attribution string, displayed when an * has been added to the map. */ attribution: null, /** * Property: inRange * {Boolean} The current map resolution is within the layer's min/max * range. This is set in whenever the zoom * changes. */ inRange: false, /** * Propery: imageSize * {} For layers with a gutter, the image is larger than * the tile by twice the gutter in each dimension. */ imageSize: null, // OPTIONS /** * Property: options * {Object} An optional object whose properties will be set on the layer. * Any of the layer properties can be set as a property of the options * object and sent to the constructor when the layer is created. */ options: null, /** * APIProperty: eventListeners * {Object} If set as an option at construction, the eventListeners * object will be registered with . Object * structure must be a listeners object as shown in the example for * the events.on method. */ eventListeners: null, /** * APIProperty: gutter * {Integer} Determines the width (in pixels) of the gutter around image * tiles to ignore. By setting this property to a non-zero value, * images will be requested that are wider and taller than the tile * size by a value of 2 x gutter. This allows artifacts of rendering * at tile edges to be ignored. Set a gutter value that is equal to * half the size of the widest symbol that needs to be displayed. * Defaults to zero. Non-tiled layers always have zero gutter. */ gutter: 0, /** * APIProperty: projection * {} or {} Specifies the projection of the layer. * Can be set in the layer options. If not specified in the layer options, * it is set to the default projection specified in the map, * when the layer is added to the map. * Projection along with default maxExtent and resolutions * are set automatically with commercial baselayers in EPSG:3857, * such as Google, Bing and OpenStreetMap, and do not need to be specified. * Otherwise, if specifying projection, also set maxExtent, * maxResolution or resolutions as appropriate. * When using vector layers with strategies, layer projection should be set * to the projection of the source data if that is different from the map default. * * Can be either a string or an object; * if a string is passed, will be converted to an object when * the layer is added to the map. * */ projection: null, /** * APIProperty: units * {String} The layer map units. Defaults to null. 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: scales * {Array} An array of map scales in descending order. The values in the * array correspond to the map scale denominator. Note that these * values only make sense if the display (monitor) resolution of the * client is correctly guessed by whomever is configuring the * application. In addition, the units property must also be set. * Use instead wherever possible. */ scales: null, /** * APIProperty: resolutions * {Array} 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: maxExtent * {|Array} If provided as an array, the array * should consist of four values (left, bottom, right, top). * The maximum extent for the layer. Defaults to null. * * The center of these bounds will not stray outside * of the viewport extent during panning. In addition, if * is set to false, data will not be * requested that falls completely outside of these bounds. */ maxExtent: null, /** * APIProperty: minExtent * {|Array} If provided as an array, the array * should consist of four values (left, bottom, right, top). * The minimum extent for the layer. Defaults to null. */ minExtent: null, /** * APIProperty: maxResolution * {Float} Default max is 360 deg / 256 px, which corresponds to * zoom level 0 on gmaps. Specify a different value in the layer * options if you are not using the default * and displaying the whole world. */ maxResolution: null, /** * APIProperty: minResolution * {Float} */ minResolution: null, /** * APIProperty: numZoomLevels * {Integer} */ numZoomLevels: null, /** * APIProperty: minScale * {Float} */ minScale: null, /** * APIProperty: maxScale * {Float} */ maxScale: null, /** * APIProperty: displayOutsideMaxExtent * {Boolean} Request map tiles that are completely outside of the max * extent for this layer. Defaults to false. */ displayOutsideMaxExtent: false, /** * APIProperty: wrapDateLine * {Boolean} Wraps the world at the international dateline, so the map can * be panned infinitely in longitudinal direction. Only use this on the * base layer, and only if the layer's maxExtent equals the world bounds. * #487 for more info. */ wrapDateLine: false, /** * Property: metadata * {Object} This object can be used to store additional information on a * layer object. */ metadata: null, /** * Constructor: OpenLayers.Layer * * Parameters: * name - {String} The layer name * options - {Object} Hashtable of extra options to tag onto the layer */ initialize: function(name, options) { this.metadata = {}; options = OpenLayers.Util.extend({}, options); // make sure we respect alwaysInRange if set on the prototype if (this.alwaysInRange != null) { options.alwaysInRange = this.alwaysInRange; } this.addOptions(options); this.name = name; if (this.id == null) { this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_"); this.div = OpenLayers.Util.createDiv(this.id); this.div.style.width = "100%"; this.div.style.height = "100%"; this.div.dir = "ltr"; this.events = new OpenLayers.Events(this, this.div); if(this.eventListeners instanceof Object) { this.events.on(this.eventListeners); } } }, /** * Method: destroy * Destroy is a destructor: this is to alleviate cyclic references which * the Javascript garbage cleaner can not take care of on its own. * * Parameters: * setNewBaseLayer - {Boolean} Set a new base layer when this layer has * been destroyed. Default is true. */ destroy: function(setNewBaseLayer) { if (setNewBaseLayer == null) { setNewBaseLayer = true; } if (this.map != null) { this.map.removeLayer(this, setNewBaseLayer); } this.projection = null; this.map = null; this.name = null; this.div = null; this.options = null; if (this.events) { if(this.eventListeners) { this.events.un(this.eventListeners); } this.events.destroy(); } this.eventListeners = null; this.events = null; }, /** * Method: clone * * Parameters: * obj - {} The layer to be cloned * * Returns: * {} An exact clone of this */ clone: function (obj) { if (obj == null) { obj = new OpenLayers.Layer(this.name, this.getOptions()); } // catch any randomly tagged-on properties OpenLayers.Util.applyDefaults(obj, this); // a cloned layer should never have its map property set // because it has not been added to a map yet. obj.map = null; return obj; }, /** * Method: getOptions * Extracts an object from the layer with the properties that were set as * options, but updates them with the values currently set on the * instance. * * Returns: * {Object} the of the layer, representing the current state. */ getOptions: function() { var options = {}; for(var o in this.options) { options[o] = this[o]; } return options; }, /** * APIMethod: setName * Sets the new layer name for this layer. Can trigger a changelayer event * on the map. * * Parameters: * newName - {String} The new name. */ setName: function(newName) { if (newName != this.name) { this.name = newName; if (this.map != null) { this.map.events.triggerEvent("changelayer", { layer: this, property: "name" }); } } }, /** * APIMethod: addOptions * * Parameters: * newOptions - {Object} * reinitialize - {Boolean} If set to true, and if resolution options of the * current baseLayer were changed, the map will be recentered to make * sure that it is displayed with a valid resolution, and a * changebaselayer event will be triggered. */ addOptions: function (newOptions, reinitialize) { if (this.options == null) { this.options = {}; } if (newOptions) { // make sure this.projection references a projection object if(typeof newOptions.projection == "string") { newOptions.projection = new OpenLayers.Projection(newOptions.projection); } if (newOptions.projection) { // get maxResolution, units and maxExtent from projection defaults if // they are not defined already OpenLayers.Util.applyDefaults(newOptions, OpenLayers.Projection.defaults[newOptions.projection.getCode()]); } // allow array for extents if (newOptions.maxExtent && !(newOptions.maxExtent instanceof OpenLayers.Bounds)) { newOptions.maxExtent = new OpenLayers.Bounds(newOptions.maxExtent); } if (newOptions.minExtent && !(newOptions.minExtent instanceof OpenLayers.Bounds)) { newOptions.minExtent = new OpenLayers.Bounds(newOptions.minExtent); } } // update our copy for clone OpenLayers.Util.extend(this.options, newOptions); // add new options to this OpenLayers.Util.extend(this, newOptions); // get the units from the projection, if we have a projection // and it it has units if(this.projection && this.projection.getUnits()) { this.units = this.projection.getUnits(); } // re-initialize resolutions if necessary, i.e. if any of the // properties of the "properties" array defined below is set // in the new options if(this.map) { // store current resolution so we can try to restore it later var resolution = this.map.getResolution(); var properties = this.RESOLUTION_PROPERTIES.concat( ["projection", "units", "minExtent", "maxExtent"] ); for(var o in newOptions) { if(newOptions.hasOwnProperty(o) && OpenLayers.Util.indexOf(properties, o) >= 0) { this.initResolutions(); if (reinitialize && this.map.baseLayer === this) { // update map position, and restore previous resolution this.map.setCenter(this.map.getCenter(), this.map.getZoomForResolution(resolution), false, true ); // trigger a changebaselayer event to make sure that // all controls (especially // OpenLayers.Control.PanZoomBar) get notified of the // new options this.map.events.triggerEvent("changebaselayer", { layer: this }); } break; } } } }, /** * APIMethod: onMapResize * This function can be implemented by subclasses */ onMapResize: function() { //this function can be implemented by subclasses }, /** * APIMethod: redraw * Redraws the layer. Returns true if the layer was redrawn, false if not. * * Returns: * {Boolean} The layer was redrawn. */ redraw: function() { var redrawn = false; if (this.map) { // min/max Range may have changed this.inRange = this.calculateInRange(); // map's center might not yet be set var extent = this.getExtent(); if (extent && this.inRange && this.visibility) { var zoomChanged = true; this.moveTo(extent, zoomChanged, false); this.events.triggerEvent("moveend", {"zoomChanged": zoomChanged}); redrawn = true; } } return redrawn; }, /** * Method: moveTo * * Parameters: * bounds - {} * zoomChanged - {Boolean} Tells when zoom has changed, as layers have to * do some init work in that case. * dragging - {Boolean} */ moveTo:function(bounds, zoomChanged, dragging) { var display = this.visibility; if (!this.isBaseLayer) { display = display && this.inRange; } this.display(display); }, /** * Method: moveByPx * Move the layer based on pixel vector. To be implemented by subclasses. * * Parameters: * dx - {Number} The x coord of the displacement vector. * dy - {Number} The y coord of the displacement vector. */ moveByPx: function(dx, dy) { }, /** * Method: setMap * Set the map property for the layer. This is done through an accessor * so that subclasses can override this and take special action once * they have their map variable set. * * Here we take care to bring over any of the necessary default * properties from the map. * * Parameters: * map - {} */ setMap: function(map) { if (this.map == null) { this.map = map; // grab some essential layer data from the map if it hasn't already // been set this.maxExtent = this.maxExtent || this.map.maxExtent; this.minExtent = this.minExtent || this.map.minExtent; this.projection = this.projection || this.map.projection; if (typeof this.projection == "string") { this.projection = new OpenLayers.Projection(this.projection); } // Check the projection to see if we can get units -- if not, refer // to properties. this.units = this.projection.getUnits() || this.units || this.map.units; this.initResolutions(); if (!this.isBaseLayer) { this.inRange = this.calculateInRange(); var show = ((this.visibility) && (this.inRange)); this.div.style.display = show ? "" : "none"; } // deal with gutters this.setTileSize(); } }, /** * Method: afterAdd * Called at the end of the map.addLayer sequence. At this point, the map * will have a base layer. To be overridden by subclasses. */ afterAdd: function() { }, /** * APIMethod: removeMap * Just as setMap() allows each layer the possibility to take a * personalized action on being added to the map, removeMap() allows * each layer to take a personalized action on being removed from it. * For now, this will be mostly unused, except for the EventPane layer, * which needs this hook so that it can remove the special invisible * pane. * * Parameters: * map - {} */ removeMap: function(map) { //to be overridden by subclasses }, /** * APIMethod: getImageSize * * Parameters: * bounds - {} optional tile bounds, can be used * by subclasses that have to deal with different tile sizes at the * layer extent edges (e.g. Zoomify) * * Returns: * {} The size that the image should be, taking into * account gutters. */ getImageSize: function(bounds) { return (this.imageSize || this.tileSize); }, /** * APIMethod: setTileSize * Set the tile size based on the map size. This also sets layer.imageSize * or use by Tile.Image. * * Parameters: * size - {} */ setTileSize: function(size) { var tileSize = (size) ? size : ((this.tileSize) ? this.tileSize : this.map.getTileSize()); this.tileSize = tileSize; if(this.gutter) { // layers with gutters need non-null tile sizes //if(tileSize == null) { // OpenLayers.console.error("Error in layer.setMap() for " + // this.name + ": layers with " + // "gutters need non-null tile sizes"); //} this.imageSize = new OpenLayers.Size(tileSize.w + (2*this.gutter), tileSize.h + (2*this.gutter)); } }, /** * APIMethod: getVisibility * * Returns: * {Boolean} The layer should be displayed (if in range). */ getVisibility: function() { return this.visibility; }, /** * APIMethod: setVisibility * Set the visibility flag for the layer and hide/show & redraw * accordingly. Fire event unless otherwise specified * * Note that visibility is no longer simply whether or not the layer's * style.display is set to "block". Now we store a 'visibility' state * property on the layer class, this allows us to remember whether or * not we *desire* for a layer to be visible. In the case where the * map's resolution is out of the layer's range, this desire may be * subverted. * * Parameters: * visibility - {Boolean} Whether or not to display the layer (if in range) */ setVisibility: function(visibility) { if (visibility != this.visibility) { this.visibility = visibility; this.display(visibility); this.redraw(); if (this.map != null) { this.map.events.triggerEvent("changelayer", { layer: this, property: "visibility" }); } this.events.triggerEvent("visibilitychanged"); } }, /** * APIMethod: display * Hide or show the Layer. This is designed to be used internally, and * is not generally the way to enable or disable the layer. For that, * use the setVisibility function instead.. * * Parameters: * display - {Boolean} */ display: function(display) { if (display != (this.div.style.display != "none")) { this.div.style.display = (display && this.calculateInRange()) ? "block" : "none"; } }, /** * APIMethod: calculateInRange * * Returns: * {Boolean} The layer is displayable at the current map's current * resolution. Note that if 'alwaysInRange' is true for the layer, * this function will always return true. */ calculateInRange: function() { var inRange = false; if (this.alwaysInRange) { inRange = true; } else { if (this.map) { var resolution = this.map.getResolution(); inRange = ( (resolution >= this.minResolution) && (resolution <= this.maxResolution) ); } } return inRange; }, /** * APIMethod: setIsBaseLayer * * Parameters: * isBaseLayer - {Boolean} */ setIsBaseLayer: function(isBaseLayer) { if (isBaseLayer != this.isBaseLayer) { this.isBaseLayer = isBaseLayer; if (this.map != null) { this.map.events.triggerEvent("changebaselayer", { layer: this }); } } }, /********************************************************/ /* */ /* Baselayer Functions */ /* */ /********************************************************/ /** * Method: initResolutions * This method's responsibility is to set up the 'resolutions' array * for the layer -- this array is what the layer will use to interface * between the zoom levels of the map and the resolution display * of the layer. * * The user has several options that determine how the array is set up. * * For a detailed explanation, see the following wiki from the * openlayers.org homepage: * http://trac.openlayers.org/wiki/SettingZoomLevels */ initResolutions: function() { // ok we want resolutions, here's our strategy: // // 1. if resolutions are defined in the layer config, use them // 2. else, if scales are defined in the layer config then derive // resolutions from these scales // 3. else, attempt to calculate resolutions from maxResolution, // minResolution, numZoomLevels, maxZoomLevel set in the // layer config // 4. if we still don't have resolutions, and if resolutions // are defined in the same, use them // 5. else, if scales are defined in the map then derive // resolutions from these scales // 6. else, attempt to calculate resolutions from maxResolution, // minResolution, numZoomLevels, maxZoomLevel set in the // map // 7. hope for the best! var i, len, p; var props = {}, alwaysInRange = true; // get resolution data from layer config // (we also set alwaysInRange in the layer as appropriate) for(i=0, len=this.RESOLUTION_PROPERTIES.length; i} A Bounds object which represents the lon/lat * bounds of the current viewPort. */ getExtent: function() { // just use stock map calculateBounds function -- passing no arguments // means it will user map's current center & resolution // return this.map.calculateBounds(); }, /** * APIMethod: getZoomForExtent * * Parameters: * extent - {} * 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} The index of the zoomLevel (entry in the resolutions array) * for the passed-in extent. We do this by calculating the ideal * resolution for the given extent (based on the map size) and then * calling getZoomForResolution(), passing along the 'closest' * parameter. */ getZoomForExtent: function(extent, closest) { var viewSize = this.map.getSize(); var idealResolution = Math.max( extent.getWidth() / viewSize.w, extent.getHeight() / viewSize.h ); return this.getZoomForResolution(idealResolution, closest); }, /** * Method: getDataExtent * Calculates the max extent which includes all of the data for the layer. * This function is to be implemented by subclasses. * * Returns: * {} */ getDataExtent: function () { //to be implemented by subclasses }, /** * APIMethod: getResolutionForZoom * * Parameters: * zoom - {Float} * * Returns: * {Float} A suitable resolution for the specified zoom. */ getResolutionForZoom: function(zoom) { zoom = Math.max(0, Math.min(zoom, this.resolutions.length - 1)); var resolution; if(this.map.fractionalZoom) { var low = Math.floor(zoom); var high = Math.ceil(zoom); resolution = this.resolutions[low] - ((zoom-low) * (this.resolutions[low]-this.resolutions[high])); } else { resolution = this.resolutions[Math.round(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} The index of the zoomLevel (entry in the resolutions array) * that corresponds to the best fit resolution given the passed in * value and the 'closest' specification. */ getZoomForResolution: function(resolution, closest) { var zoom, i, len; if(this.map.fractionalZoom) { var lowZoom = 0; var highZoom = this.resolutions.length - 1; var highRes = this.resolutions[lowZoom]; var lowRes = this.resolutions[highZoom]; var res; for(i=0, len=this.resolutions.length; i= resolution) { highRes = res; lowZoom = i; } if(res <= resolution) { lowRes = res; highZoom = i; break; } } var dRes = highRes - lowRes; if(dRes > 0) { zoom = lowZoom + ((highRes - resolution) / dRes); } else { zoom = lowZoom; } } else { var diff; var minDiff = Number.POSITIVE_INFINITY; for(i=0, len=this.resolutions.length; i minDiff) { break; } minDiff = diff; } else { if (this.resolutions[i] < resolution) { break; } } } zoom = Math.max(0, i-1); } return zoom; }, /** * APIMethod: getLonLatFromViewPortPx * * Parameters: * viewPortPx - {|Object} An OpenLayers.Pixel or * an object with a 'x' * and 'y' properties. * * Returns: * {} An OpenLayers.LonLat which is the passed-in * view port , translated into lon/lat by the layer. */ getLonLatFromViewPortPx: function (viewPortPx) { var lonlat = null; var map = this.map; if (viewPortPx != null && map.minPx) { var res = map.getResolution(); var maxExtent = map.getMaxExtent({restricted: true}); var lon = (viewPortPx.x - map.minPx.x) * res + maxExtent.left; var lat = (map.minPx.y - viewPortPx.y) * res + maxExtent.top; lonlat = new OpenLayers.LonLat(lon, lat); if (this.wrapDateLine) { lonlat = lonlat.wrapDateLine(this.maxExtent); } } return lonlat; }, /** * APIMethod: getViewPortPxFromLonLat * Returns a pixel location given a map location. This method will return * fractional pixel values. * * Parameters: * lonlat - {|Object} An OpenLayers.LonLat or * an object with a 'lon' * and 'lat' properties. * * Returns: * {} An which is the passed-in * lonlat translated into view port pixels. */ getViewPortPxFromLonLat: function (lonlat, resolution) { var px = null; if (lonlat != null) { resolution = resolution || this.map.getResolution(); var extent = this.map.calculateBounds(null, resolution); px = new OpenLayers.Pixel( (1/resolution * (lonlat.lon - extent.left)), (1/resolution * (extent.top - lonlat.lat)) ); } return px; }, /** * APIMethod: setOpacity * Sets the opacity for the entire layer (all images) * * Parameters: * opacity - {Float} */ setOpacity: function(opacity) { if (opacity != this.opacity) { this.opacity = opacity; var childNodes = this.div.childNodes; for(var i = 0, len = childNodes.length; i < len; ++i) { var element = childNodes[i].firstChild || childNodes[i]; var lastChild = childNodes[i].lastChild; //TODO de-uglify this if (lastChild && lastChild.nodeName.toLowerCase() === "iframe") { element = lastChild.parentNode; } OpenLayers.Util.modifyDOMElement(element, null, null, null, null, null, null, opacity); } if (this.map != null) { this.map.events.triggerEvent("changelayer", { layer: this, property: "opacity" }); } } }, /** * Method: getZIndex * * Returns: * {Integer} the z-index of this layer */ getZIndex: function () { return this.div.style.zIndex; }, /** * Method: setZIndex * * Parameters: * zIndex - {Integer} */ setZIndex: function (zIndex) { this.div.style.zIndex = zIndex; }, /** * Method: adjustBounds * This function will take a bounds, and if wrapDateLine option is set * on the layer, it will return a bounds which is wrapped around the * world. We do not wrap for bounds which *cross* the * maxExtent.left/right, only bounds which are entirely to the left * or entirely to the right. * * Parameters: * bounds - {} */ adjustBounds: function (bounds) { if (this.gutter) { // Adjust the extent of a bounds in map units by the // layer's gutter in pixels. var mapGutter = this.gutter * this.map.getResolution(); bounds = new OpenLayers.Bounds(bounds.left - mapGutter, bounds.bottom - mapGutter, bounds.right + mapGutter, bounds.top + mapGutter); } if (this.wrapDateLine) { // wrap around the date line, within the limits of rounding error var wrappingOptions = { 'rightTolerance':this.getResolution(), 'leftTolerance':this.getResolution() }; bounds = bounds.wrapDateLine(this.maxExtent, wrappingOptions); } return bounds; }, CLASS_NAME: "OpenLayers.Layer" });