|
/* Copyright (c) 2006-2010 by OpenLayers Contributors (see authors.txt for |
|
* full list of contributors). Published under the Clear BSD license. |
|
* See http://svn.openlayers.org/trunk/openlayers/license.txt for the |
|
* full text of the license. */ |
|
|
|
/** |
|
* @requires OpenLayers/Control.js |
|
* @requires OpenLayers/BaseTypes.js |
|
* @requires OpenLayers/Events.js |
|
*/ |
|
|
|
/** |
|
* Class: OpenLayers.Control.OverviewMap |
|
* The OverMap control creates a small overview map, useful to display the |
|
* extent of a zoomed map and your main map and provide additional |
|
* navigation options to the User. By default the overview map is drawn in |
|
* the lower right corner of the main map. Create a new overview map with the |
|
* <OpenLayers.Control.OverviewMap> constructor. |
|
* |
|
* Inerits from: |
|
* - <OpenLayers.Control> |
|
*/ |
|
OpenLayers.Control.OverviewMap = OpenLayers.Class(OpenLayers.Control, { |
|
|
|
/** |
|
* Property: element |
|
* {DOMElement} The DOM element that contains the overview map |
|
*/ |
|
element: null, |
|
|
|
/** |
|
* APIProperty: ovmap |
|
* {<OpenLayers.Map>} A reference to the overview map itself. |
|
*/ |
|
ovmap: null, |
|
|
|
/** |
|
* APIProperty: size |
|
* {<OpenLayers.Size>} The overvew map size in pixels. Note that this is |
|
* the size of the map itself - the element that contains the map (default |
|
* class name olControlOverviewMapElement) may have padding or other style |
|
* attributes added via CSS. |
|
*/ |
|
size: new OpenLayers.Size(180, 90), |
|
|
|
/** |
|
* APIProperty: layers |
|
* {Array(<OpenLayers.Layer>)} Ordered list of layers in the overview map. |
|
* If none are sent at construction, the base layer for the main map is used. |
|
*/ |
|
layers: null, |
|
|
|
/** |
|
* APIProperty: minRectSize |
|
* {Integer} The minimum width or height (in pixels) of the extent |
|
* rectangle on the overview map. When the extent rectangle reaches |
|
* this size, it will be replaced depending on the value of the |
|
* <minRectDisplayClass> property. Default is 15 pixels. |
|
*/ |
|
minRectSize: 15, |
|
|
|
/** |
|
* APIProperty: minRectDisplayClass |
|
* {String} Replacement style class name for the extent rectangle when |
|
* <minRectSize> is reached. This string will be suffixed on to the |
|
* displayClass. Default is "RectReplacement". |
|
* |
|
* Example CSS declaration: |
|
* (code) |
|
* .olControlOverviewMapRectReplacement { |
|
* overflow: hidden; |
|
* cursor: move; |
|
* background-image: url("img/overview_replacement.gif"); |
|
* background-repeat: no-repeat; |
|
* background-position: center; |
|
* } |
|
* (end) |
|
*/ |
|
minRectDisplayClass: "RectReplacement", |
|
|
|
/** |
|
* APIProperty: minRatio |
|
* {Float} The ratio of the overview map resolution to the main map |
|
* resolution at which to zoom farther out on the overview map. |
|
*/ |
|
minRatio: 8, |
|
|
|
/** |
|
* APIProperty: maxRatio |
|
* {Float} The ratio of the overview map resolution to the main map |
|
* resolution at which to zoom farther in on the overview map. |
|
*/ |
|
maxRatio: 32, |
|
|
|
/** |
|
* APIProperty: mapOptions |
|
* {Object} An object containing any non-default properties to be sent to |
|
* the overview map's map constructor. These should include any |
|
* non-default options that the main map was constructed with. |
|
*/ |
|
mapOptions: null, |
|
|
|
/** |
|
* APIProperty: autoPan |
|
* {Boolean} Always pan the overview map, so the extent marker remains in |
|
* the center. Default is false. If true, when you drag the extent |
|
* marker, the overview map will update itself so the marker returns |
|
* to the center. |
|
*/ |
|
autoPan: false, |
|
|
|
/** |
|
* Property: handlers |
|
* {Object} |
|
*/ |
|
handlers: null, |
|
|
|
/** |
|
* Property: resolutionFactor |
|
* {Object} |
|
*/ |
|
resolutionFactor: 1, |
|
|
|
/** |
|
* APIProperty: maximized |
|
* {Boolean} Start as maximized (visible). Defaults to false. |
|
*/ |
|
maximized: false, |
|
|
|
/** |
|
* Constructor: OpenLayers.Control.OverviewMap |
|
* Create a new overview map |
|
* |
|
* Parameters: |
|
* object - {Object} Properties of this object will be set on the overview |
|
* map object. Note, to set options on the map object contained in this |
|
* control, set <mapOptions> as one of the options properties. |
|
*/ |
|
initialize: function(options) { |
|
this.layers = []; |
|
this.handlers = {}; |
|
OpenLayers.Control.prototype.initialize.apply(this, [options]); |
|
}, |
|
|
|
/** |
|
* APIMethod: destroy |
|
* Deconstruct the control |
|
*/ |
|
destroy: function() { |
|
if (!this.mapDiv) { // we've already been destroyed |
|
return; |
|
} |
|
if (this.handlers.click) { |
|
this.handlers.click.destroy(); |
|
} |
|
if (this.handlers.drag) { |
|
this.handlers.drag.destroy(); |
|
} |
|
|
|
this.mapDiv.removeChild(this.extentRectangle); |
|
this.extentRectangle = null; |
|
|
|
if (this.rectEvents) { |
|
this.rectEvents.destroy(); |
|
this.rectEvents = null; |
|
} |
|
|
|
if (this.ovmap) { |
|
this.ovmap.destroy(); |
|
this.ovmap = null; |
|
} |
|
|
|
this.element.removeChild(this.mapDiv); |
|
this.mapDiv = null; |
|
|
|
this.div.removeChild(this.element); |
|
this.element = null; |
|
|
|
if (this.maximizeDiv) { |
|
OpenLayers.Event.stopObservingElement(this.maximizeDiv); |
|
this.div.removeChild(this.maximizeDiv); |
|
this.maximizeDiv = null; |
|
} |
|
|
|
if (this.minimizeDiv) { |
|
OpenLayers.Event.stopObservingElement(this.minimizeDiv); |
|
this.div.removeChild(this.minimizeDiv); |
|
this.minimizeDiv = null; |
|
} |
|
|
|
this.map.events.un({ |
|
"moveend": this.update, |
|
"changebaselayer": this.baseLayerDraw, |
|
scope: this |
|
}); |
|
|
|
OpenLayers.Control.prototype.destroy.apply(this, arguments); |
|
}, |
|
|
|
/** |
|
* Method: draw |
|
* Render the control in the browser. |
|
*/ |
|
draw: function() { |
|
OpenLayers.Control.prototype.draw.apply(this, arguments); |
|
if(!(this.layers.length > 0)) { |
|
if (this.map.baseLayer) { |
|
var layer = this.map.baseLayer.clone(); |
|
this.layers = [layer]; |
|
} else { |
|
this.map.events.register("changebaselayer", this, this.baseLayerDraw); |
|
return this.div; |
|
} |
|
} |
|
|
|
// create overview map DOM elements |
|
this.element = document.createElement('div'); |
|
this.element.className = this.displayClass + 'Element'; |
|
this.element.style.display = 'none'; |
|
|
|
this.mapDiv = document.createElement('div'); |
|
this.mapDiv.style.width = this.size.w + 'px'; |
|
this.mapDiv.style.height = this.size.h + 'px'; |
|
this.mapDiv.style.position = 'relative'; |
|
this.mapDiv.style.overflow = 'hidden'; |
|
this.mapDiv.id = OpenLayers.Util.createUniqueID('overviewMap'); |
|
|
|
this.extentRectangle = document.createElement('div'); |
|
this.extentRectangle.style.position = 'absolute'; |
|
this.extentRectangle.style.zIndex = 1000; //HACK |
|
this.extentRectangle.className = this.displayClass+'ExtentRectangle'; |
|
this.mapDiv.appendChild(this.extentRectangle); |
|
|
|
this.element.appendChild(this.mapDiv); |
|
|
|
this.div.appendChild(this.element); |
|
|
|
// Optionally add min/max buttons if the control will go in the |
|
// map viewport. |
|
if(!this.outsideViewport) { |
|
this.div.className += " " + this.displayClass + 'Container'; |
|
var imgLocation = OpenLayers.Util.getImagesLocation(); |
|
// maximize button div |
|
var img = imgLocation + 'layer-switcher-maximize.png'; |
|
this.maximizeDiv = OpenLayers.Util.createAlphaImageDiv( |
|
this.displayClass + 'MaximizeButton', |
|
null, |
|
new OpenLayers.Size(18,18), |
|
img, |
|
'absolute'); |
|
this.maximizeDiv.style.display = 'none'; |
|
this.maximizeDiv.className = this.displayClass + 'MaximizeButton'; |
|
OpenLayers.Event.observe(this.maximizeDiv, 'click', |
|
OpenLayers.Function.bindAsEventListener(this.maximizeControl, |
|
this) |
|
); |
|
this.div.appendChild(this.maximizeDiv); |
|
|
|
// minimize button div |
|
var img = imgLocation + 'layer-switcher-minimize.png'; |
|
this.minimizeDiv = OpenLayers.Util.createAlphaImageDiv( |
|
'OpenLayers_Control_minimizeDiv', |
|
null, |
|
new OpenLayers.Size(18,18), |
|
img, |
|
'absolute'); |
|
this.minimizeDiv.style.display = 'none'; |
|
this.minimizeDiv.className = this.displayClass + 'MinimizeButton'; |
|
OpenLayers.Event.observe(this.minimizeDiv, 'click', |
|
OpenLayers.Function.bindAsEventListener(this.minimizeControl, |
|
this) |
|
); |
|
this.div.appendChild(this.minimizeDiv); |
|
|
|
var eventsToStop = ['dblclick','mousedown']; |
|
|
|
for (var i=0, len=eventsToStop.length; i<len; i++) { |
|
|
|
OpenLayers.Event.observe(this.maximizeDiv, |
|
eventsToStop[i], |
|
OpenLayers.Event.stop); |
|
|
|
OpenLayers.Event.observe(this.minimizeDiv, |
|
eventsToStop[i], |
|
OpenLayers.Event.stop); |
|
} |
|
|
|
this.minimizeControl(); |
|
} else { |
|
// show the overview map |
|
this.element.style.display = ''; |
|
} |
|
if(this.map.getExtent()) { |
|
this.update(); |
|
} |
|
|
|
this.map.events.register('moveend', this, this.update); |
|
|
|
if (this.maximized) { |
|
this.maximizeControl(); |
|
} |
|
return this.div; |
|
}, |
|
|
|
/** |
|
* Method: baseLayerDraw |
|
* Draw the base layer - called if unable to complete in the initial draw |
|
*/ |
|
baseLayerDraw: function() { |
|
this.draw(); |
|
this.map.events.unregister("changebaselayer", this, this.baseLayerDraw); |
|
}, |
|
|
|
/** |
|
* Method: rectDrag |
|
* Handle extent rectangle drag |
|
* |
|
* Parameters: |
|
* px - {<OpenLayers.Pixel>} The pixel location of the drag. |
|
*/ |
|
rectDrag: function(px) { |
|
var deltaX = this.handlers.drag.last.x - px.x; |
|
var deltaY = this.handlers.drag.last.y - px.y; |
|
if(deltaX != 0 || deltaY != 0) { |
|
var rectTop = this.rectPxBounds.top; |
|
var rectLeft = this.rectPxBounds.left; |
|
var rectHeight = Math.abs(this.rectPxBounds.getHeight()); |
|
var rectWidth = this.rectPxBounds.getWidth(); |
|
// don't allow dragging off of parent element |
|
var newTop = Math.max(0, (rectTop - deltaY)); |
|
newTop = Math.min(newTop, |
|
this.ovmap.size.h - this.hComp - rectHeight); |
|
var newLeft = Math.max(0, (rectLeft - deltaX)); |
|
newLeft = Math.min(newLeft, |
|
this.ovmap.size.w - this.wComp - rectWidth); |
|
this.setRectPxBounds(new OpenLayers.Bounds(newLeft, |
|
newTop + rectHeight, |
|
newLeft + rectWidth, |
|
newTop)); |
|
} |
|
}, |
|
|
|
/** |
|
* Method: mapDivClick |
|
* Handle browser events |
|
* |
|
* Parameters: |
|
* evt - {<OpenLayers.Event>} evt |
|
*/ |
|
mapDivClick: function(evt) { |
|
var pxCenter = this.rectPxBounds.getCenterPixel(); |
|
var deltaX = evt.xy.x - pxCenter.x; |
|
var deltaY = evt.xy.y - pxCenter.y; |
|
var top = this.rectPxBounds.top; |
|
var left = this.rectPxBounds.left; |
|
var height = Math.abs(this.rectPxBounds.getHeight()); |
|
var width = this.rectPxBounds.getWidth(); |
|
var newTop = Math.max(0, (top + deltaY)); |
|
newTop = Math.min(newTop, this.ovmap.size.h - height); |
|
var newLeft = Math.max(0, (left + deltaX)); |
|
newLeft = Math.min(newLeft, this.ovmap.size.w - width); |
|
this.setRectPxBounds(new OpenLayers.Bounds(newLeft, |
|
newTop + height, |
|
newLeft + width, |
|
newTop)); |
|
this.updateMapToRect(); |
|
}, |
|
|