/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
* license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
* full text of the license. */
/**
* Class: OpenLayers.Control
* Controls affect the display or behavior of the map. They allow everything
* from panning and zooming to displaying a scale indicator. Controls by
* default are added to the map they are contained within however it is
* possible to add a control to an external div by passing the div in the
* options parameter.
*
* Example:
* The following example shows how to add many of the common controls
* to a map.
*
* > var map = new OpenLayers.Map('map', { controls: [] });
* >
* > map.addControl(new OpenLayers.Control.PanZoomBar());
* > map.addControl(new OpenLayers.Control.MouseToolbar());
* > map.addControl(new OpenLayers.Control.LayerSwitcher({'ascending':false}));
* > map.addControl(new OpenLayers.Control.Permalink());
* > map.addControl(new OpenLayers.Control.Permalink('permalink'));
* > map.addControl(new OpenLayers.Control.MousePosition());
* > map.addControl(new OpenLayers.Control.OverviewMap());
* > map.addControl(new OpenLayers.Control.KeyboardDefaults());
*
* The next code fragment is a quick example of how to intercept
* shift-mouse click to display the extent of the bounding box
* dragged out by the user.  Usually controls are not created
* in exactly this manner.  See the source for a more complete
* example:
*
* > var control = new OpenLayers.Control();
* > OpenLayers.Util.extend(control, {
* >     draw: function () {
* >         // this Handler.Box will intercept the shift-mousedown
* >         // before Control.MouseDefault gets to see it
* >         this.box = new OpenLayers.Handler.Box( control,
* >             {"done": this.notice},
* >             {keyMask: OpenLayers.Handler.MOD_SHIFT});
* >         this.box.activate();
* >     },
* >
* >     notice: function (bounds) {
* >         alert(bounds);
* >     }
* > });
* > map.addControl(control);
*
*/
OpenLayers.Control = OpenLayers.Class({
/**
* Property: id
* {String}
*/
id: null,
/**
* Property: map
* {<OpenLayers.Map>} this gets set in the addControl() function in
* OpenLayers.Map
*/
map: null,
/**
* Property: div
* {DOMElement}
*/
div: null,
/**
* Property: type
* {OpenLayers.Control.TYPES} Controls can have a 'type'. The type
* determines the type of interactions which are possible with them when
* they are placed into a toolbar.
*/
type: null,
/**
* Property: allowSelection
* {Boolean} By deafault, controls do not allow selection, because
* it may interfere with map dragging. If this is true, OpenLayers
* will not prevent selection of the control.
* Default is false.
*/
allowSelection: false,
/**
* Property: displayClass
* {string}  This property is used for CSS related to the drawing of the
* Control.
*/
displayClass: "",
/**
* Property: title
* {string}  This property is used for showing a tooltip over the
* Control.
*/
title: "",
/**
* Property: active
* {Boolean} The control is active.
*/
active: null,
/**
* Property: handler
* {<OpenLayers.Handler>} null
*/
handler: null,
/**
* 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: events
* {<OpenLayers.Events>} Events instance for triggering control specific
*     events.
*/
events: null,
/**
* Constant: EVENT_TYPES
* {Array(String)} Supported application event types.  Register a listener
*     for a particular event with the following syntax:
* (code)
* control.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 control.events.object (a reference
*      to the control).
*  - *element* {DOMElement} A reference to control.events.element (which
*      will be null unless documented otherwise).
*
* Supported map event types:
*  - *activate* Triggered when activated.
*  - *deactivate* Triggered when deactivated.
*/
EVENT_TYPES: ["activate", "deactivate"],
/**
* Constructor: OpenLayers.Control
* Create an OpenLayers Control.  The options passed as a parameter
* directly extend the control.  For example passing the following:
*
* > var control = new OpenLayers.Control({div: myDiv});
*
* Overrides the default div attribute value of null.
*
* Parameters:
* options - {Object}
*/
initialize: function (options) {
// We do this before the extend so that instances can override
// className in options.
this.displayClass =
this.CLASS_NAME.replace("OpenLayers.", "ol").replace(/\./g, "");
OpenLayers.Util.extend(this, options);
this.events = new OpenLayers.Events(this, null, this.EVENT_TYPES);
if(this.eventListeners instanceof Object) {
this.events.on(this.eventListeners);
}
this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_");
},
/**
* Method: destroy
* The destroy method is used to perform any clean up before the control
* is dereferenced.  Typically this is where event listeners are removed
* to prevent memory leaks.
*/
destroy: function () {
if(this.events) {
if(this.eventListeners) {
this.events.un(this.eventListeners);
}
this.events.destroy();
this.events = null;
}
this.eventListeners = null;
// eliminate circular references
if (this.handler) {
this.handler.destroy();
this.handler = null;
}
if(this.handlers) {
for(var key in this.handlers) {
if(this.handlers.hasOwnProperty(key) &&
typeof this.handlers[key].destroy == "function") {
this.handlers[key].destroy();
}
}
this.handlers = null;
}
if (this.map) {
this.map.removeControl(this);
this.map = null;
}
},
/**
* Method: setMap
* Set the map property for the control. This is done through an accessor
* so that subclasses can override this and take special action once
* they have their map variable set.
*
* Parameters:
* map - {<OpenLayers.Map>}
*/
setMap: function(map) {
this.map = map;
if (this.handler) {
this.handler.setMap(map);
}
},
/**
* Method: draw
* The draw method is called when the control is ready to be displayed
* on the page.  If a div has not been created one is created.  Controls
* with a visual component will almost always want to override this method
* to customize the look of control.
*
* Parameters:
* px - {<OpenLayers.Pixel>} The top-left pixel position of the control
*      or null.
*
* Returns:
* {DOMElement} A reference to the DIV DOMElement containing the control
*/
draw: function (px) {
if (this.div == null) {
this.div = OpenLayers.Util.createDiv(this.id);
this.div.className = this.displayClass;
if (!this.allowSelection) {
this.div.className += " olControlNoSelect";
this.div.setAttribute("unselectable", "on", 0);
this.div.onselectstart = function() { return(false); };
}
if (this.title != "") {
this.div.title = this.title;
}
}
if (px != null) {
this.position = px.clone();
}
this.moveTo(this.position);
return this.div;
},
/**
* Method: moveTo
* Sets the left and top style attributes to the passed in pixel
* coordinates.
*
* Parameters:
* px - {<OpenLayers.Pixel>}
*/
moveTo: function (px) {
if ((px != null) && (this.div != null)) {
this.div.style.left = px.x + "px";
this.div.style.top = px.y + "px";
}
},
/**
* Method: activate
* Explicitly activates a control and it's associated
* handler if one has been set.  Controls can be
* deactivated by calling the deactivate() method.
*
* Returns:
* {Boolean}  True if the control was successfully activated or
*            false if the control was already active.
*/
activate: function () {
if (this.active) {
return false;
}
if (this.handler) {
this.handler.activate();
}
this.active = true;
this.events.triggerEvent("activate");
return true;
},
/**
* Method: deactivate
* Deactivates a control and it's associated handler if any.  The exact
* effect of this depends on the control itself.
*
* Returns:
* {Boolean} True if the control was effectively deactivated or false
*           if the control was already inactive.
*/
deactivate: function () {
if (this.active) {
if (this.handler) {
this.handler.deactivate();
}
this.active = false;
this.events.triggerEvent("deactivate");
return true;
}
return false;
},
CLASS_NAME: "OpenLayers.Control"
});
OpenLayers.Control.TYPE_BUTTON = 1;
OpenLayers.Control.TYPE_TOGGLE = 2;
OpenLayers.Control.TYPE_TOOL   = 3;
/* Copyright (c) 2006-2008 MetaCarta, Inc., 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
*/
/**
* Class: OpenLayers.Control.Attribution
* Add attribution from layers to the map display. Uses 'attribution' property
* of each layer.
*/
OpenLayers.Control.Attribution =
OpenLayers.Class(OpenLayers.Control, {
/**
* APIProperty: seperator
* {String} String used to seperate layers.
*/
separator: ", ",
/**
* Constructor: OpenLayers.Control.Attribution
*
* Parameters:
* options - {Object} Options for control.
*/
initialize: function(options) {
OpenLayers.Control.prototype.initialize.apply(this, arguments);
},
/**
* Method: destroy
* Destroy control.
*/
destroy: function() {
this.map.events.un({
"removelayer": this.updateAttribution,
"addlayer": this.updateAttribution,
"changelayer": this.updateAttribution,
"changebaselayer": this.updateAttribution,
scope: this
});
OpenLayers.Control.prototype.destroy.apply(this, arguments);
},
/**
* Method: draw
* Initialize control.
*
* Returns:
* {DOMElement} A reference to the DIV DOMElement containing the control
*/
draw: function() {
OpenLayers.Control.prototype.draw.apply(this, arguments);
this.map.events.on({
'changebaselayer': this.updateAttribution,
'changelayer': this.updateAttribution,
'addlayer': this.updateAttribution,
'removelayer': this.updateAttribution,
scope: this
});
this.updateAttribution();
return this.div;
},
/**
* Method: updateAttribution
* Update attribution string.
*/
updateAttribution: function() {
var attributions = [];
if (this.map && this.map.layers) {
for(var i=0; i < this.map.layers.length; i++) {
var layer = this.map.layers[i];
if (layer.attribution && layer.getVisibility()) {
attributions.push( layer.attribution );
}
}
this.div.innerHTML = attributions.join(this.separator);
}
},
CLASS_NAME: "OpenLayers.Control.Attribution"
});
/* Copyright (c) 2006-2007 MetaCarta, Inc., published under a modified BSD license.
* See http://svn.openlayers.org/trunk/openlayers/repository-license.txt
* for the full text of the license. */
/**
* @requires OpenLayers/Control.js
*/
/**
* Class: OpenLayers.Control.Button
* A very simple button controlfor use with <OpenLayers.Control.Panel>.
* When clicked, the function trigger() is executed.
*
* Inherits from:
*  - <OpenLayers.Control>
*
* Use:
* (code)
* var button = new OpenLayers.Control.Button({
*     displayClass: "MyButton", trigger: myFunction
* });
* panel.addControls([button]);
* (end)
*
* Will create a button with CSS class MyButtonItemInactive, that
*     will call the function MyFunction() when clicked.
*/
OpenLayers.Control.Button = OpenLayers.Class(OpenLayers.Control, {
/**
* Property: type
* {Integer} OpenLayers.Control.TYPE_BUTTON.
*/
type: OpenLayers.Control.TYPE_BUTTON,
/**
* Method: trigger
* Called by a control panel when the button is clicked.
*/
trigger: function() {},
CLASS_NAME: "OpenLayers.Control.Button"
});
/* Copyright (c) 2006-2008 MetaCarta, Inc., 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/Handler/Box.js
*/
/**
* Class: OpenLayers.Control.ZoomBox
*
* Inherits from:
*  - <OpenLayers.Control>
*/
OpenLayers.Control.ZoomBox = OpenLayers.Class(OpenLayers.Control, {
/**
* Property: type
* {OpenLayers.Control.TYPE}
*/
type: OpenLayers.Control.TYPE_TOOL,
/**
* Property: out
* {Boolean} Should the control be used for zooming out?
*/
out: false,
/**
* Method: draw
*/
draw: function() {
this.handler = new OpenLayers.Handler.Box( this,
{done: this.zoomBox}, {keyMask: this.keyMask} );
},
/**
* Method: zoomBox
*
* Parameters:
* position - {<OpenLayers.Bounds>} or {<OpenLayers.Pixel>}
*/
zoomBox: function (position) {
if (position instanceof OpenLayers.Bounds) {
if (!this.out) {
var minXY = this.map.getLonLatFromPixel(
new OpenLayers.Pixel(position.left, position.bottom));
var maxXY = this.map.getLonLatFromPixel(
new OpenLayers.Pixel(position.right, position.top));
var bounds = new OpenLayers.Bounds(minXY.lon, minXY.lat,
maxXY.lon, maxXY.lat);
} else {
var pixWidth = Math.abs(position.right-position.left);
var pixHeight = Math.abs(position.top-position.bottom);
var zoomFactor = Math.min((this.map.size.h / pixHeight),
(this.map.size.w / pixWidth));
var extent = this.map.getExtent();
var center = this.map.getLonLatFromPixel(
position.getCenterPixel());
var xmin = center.lon - (extent.getWidth()/2)*zoomFactor;
var xmax = center.lon + (extent.getWidth()/2)*zoomFactor;
var ymin = center.lat - (extent.getHeight()/2)*zoomFactor;
var ymax = center.lat + (extent.getHeight()/2)*zoomFactor;
var bounds = new OpenLayers.Bounds(xmin, ymin, xmax, ymax);
}
this.map.zoomToExtent(bounds);
} else { // it's a pixel
if (!this.out) {
this.map.setCenter(this.map.getLonLatFromPixel(position),
this.map.getZoom() + 1);
} else {
this.map.setCenter(this.map.getLonLatFromPixel(position),
this.map.getZoom() - 1);
}
}
},
CLASS_NAME: "OpenLayers.Control.ZoomBox"
});
/* Copyright (c) 2006-2008 MetaCarta, Inc., 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/Handler/Drag.js
*/
/**
* Class: OpenLayers.Control.DragPan
* DragPan control.
*
* Inherits from:
*  - <OpenLayers.Control>
*/
OpenLayers.Control.DragPan = OpenLayers.Class(OpenLayers.Control, {
/**
* Property: type
* {OpenLayers.Control.TYPES}
*/
type: OpenLayers.Control.TYPE_TOOL,
/**
* Property: panned
* {Boolean} The map moved.
*/
panned: false,
/**
* Method: draw
* Creates a Drag handler, using <panMap> and
* <panMapDone> as callbacks.
*/
draw: function() {
this.handler = new OpenLayers.Handler.Drag(this,
{"move": this.panMap, "done": this.panMapDone});
},
/**
* Method: panMap
*
* Parameters:
* xy - {<OpenLayers.Pixel>} Pixel of the mouse position
*/
panMap: function(xy) {
this.panned = true;
this.map.pan(
this.handler.last.x - xy.x,
this.handler.last.y - xy.y,
{dragging: this.handler.dragging, animate: false}
);
},
/**
* Method: panMapDone
* Finish the panning operation.  Only call setCenter (through <panMap>)
*     if the map has actually been moved.
*
* Parameters:
* xy - {<OpenLayers.Pixel>} Pixel of the mouse position
*/
panMapDone: function(xy) {
if(this.panned) {
this.panMap(xy);
this.panned = false;
}
},
CLASS_NAME: "OpenLayers.Control.DragPan"
});
/* Copyright (c) 2006-2008 MetaCarta, Inc., 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/ZoomBox.js
* @requires OpenLayers/Control/DragPan.js
* @requires OpenLayers/Handler/MouseWheel.js
* @requires OpenLayers/Handler/Click.js
*/
/**
* Class: OpenLayers.Control.Navigation
* The navigation control handles map browsing with mouse events (dragging,
*     double-clicking, and scrolling the wheel).  Create a new navigation
*     control with the <OpenLayers.Control.Navigation> control.
*
*     Note that this control is added to the map by default (if no controls
*     array is sent in the options object to the <OpenLayers.Map>
*     constructor).
*
* Inherits:
*  - <OpenLayers.Control>
*/
OpenLayers.Control.Navigation = OpenLayers.Class(OpenLayers.Control, {
/**
* Property: dragPan
* {<OpenLayers.Control.DragPan>}
*/
dragPan: null,
/**
* Property: zoomBox
* {<OpenLayers.Control.ZoomBox>}
*/
zoomBox: null,
/**
* APIProperty: zoomWheelEnabled
* {Boolean} Whether the mousewheel should zoom the map
*/
zoomWheelEnabled: true,
/**
* Constructor: OpenLayers.Control.Navigation
* Create a new navigation control
*
* Parameters:
* options - {Object} An optional object whose properties will be set on
*                    the control
*/
initialize: function(options) {
this.handlers = {};
OpenLayers.Control.prototype.initialize.apply(this, arguments);
},
/**
* Method: destroy
* The destroy method is used to perform any clean up before the control
* is dereferenced.  Typically this is where event listeners are removed
* to prevent memory leaks.
*/
destroy: function() {
this.deactivate();
if (this.dragPan) {
this.dragPan.destroy();
}
this.dragPan = null;
if (this.zoomBox) {
this.zoomBox.destroy();
}
this.zoomBox = null;
OpenLayers.Control.prototype.destroy.apply(this,arguments);
},
/**
* Method: activate
*/
activate: function() {
this.dragPan.activate();
if (this.zoomWheelEnabled) {
this.handlers.wheel.activate();
}
this.handlers.click.activate();
this.zoomBox.activate();
return OpenLayers.Control.prototype.activate.apply(this,arguments);
},
/**
* Method: deactivate
*/
deactivate: function() {
this.zoomBox.deactivate();
this.dragPan.deactivate();
this.handlers.click.deactivate();
this.handlers.wheel.deactivate();
return OpenLayers.Control.prototype.deactivate.apply(this,arguments);
},
/**
* Method: draw
*/
draw: function() {
this.handlers.click = new OpenLayers.Handler.Click(this,
{ 'dblclick': this.defaultDblClick },
{
'double': true,
'stopDouble': true
});
this.dragPan = new OpenLayers.Control.DragPan({map: this.map});
this.zoomBox = new OpenLayers.Control.ZoomBox(
{map: this.map, keyMask: OpenLayers.Handler.MOD_SHIFT});
this.dragPan.draw();
this.zoomBox.draw();
this.handlers.wheel = new OpenLayers.Handler.MouseWheel(
this, {"up"  : this.wheelUp,
"down": this.wheelDown} );
this.activate();
},
/**
* Method: defaultDblClick
*
* Parameters:
* evt - {Event}
*/
defaultDblClick: function (evt) {
var newCenter = this.map.getLonLatFromViewPortPx( evt.xy );
this.map.setCenter(newCenter, this.map.zoom + 1);
},
/**
* Method: wheelChange
*
* Parameters:
* evt - {Event}
* deltaZ - {Integer}
*/
wheelChange: function(evt, deltaZ) {
var newZoom = this.map.getZoom() + deltaZ;
if (!this.map.isValidZoomLevel(newZoom)) {
return;
}
var size    = this.map.getSize();
var deltaX  = size.w/2 - evt.xy.x;
var deltaY  = evt.xy.y - size.h/2;
var newRes  = this.map.baseLayer.getResolutionForZoom(newZoom);
var zoomPoint = this.map.getLonLatFromPixel(evt.xy);
var newCenter = new OpenLayers.LonLat(
zoomPoint.lon + deltaX * newRes,
zoomPoint.lat + deltaY * newRes );
this.map.setCenter( newCenter, newZoom );
},
/**
* Method: wheelUp
* User spun scroll wheel up
*
* Parameters:
* evt - {Event}
*/
wheelUp: function(evt) {
this.wheelChange(evt, 1);
},
/**
* Method: wheelDown
* User spun scroll wheel down
*
* Parameters:
* evt - {Event}
*/
wheelDown: function(evt) {
this.wheelChange(evt, -1);
},
/**
* Method: disableZoomWheel
*/
disableZoomWheel : function() {
this.zoomWheelEnabled = false;
this.handlers.wheel.deactivate();
},
/**
* Method: enableZoomWheel
*/
enableZoomWheel : function() {
this.zoomWheelEnabled = true;
if (this.active) {
this.handlers.wheel.activate();
}
},
CLASS_NAME: "OpenLayers.Control.Navigation"
});
/* Copyright (c) 2006-2008 MetaCarta, Inc., 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
*/
/**
* Class: OpenLayers.Control.MouseDefaults
*
* Inherits from:
*  - <OpenLayers.Control>
*/
OpenLayers.Control.MouseDefaults = OpenLayers.Class(OpenLayers.Control, {
/** WARNING WARNING WARNING!!!
This class is DEPRECATED in 2.4 and will be removed by 3.0.
If you need this functionality, use Control.Navigation instead!!! */
/**
* Property: performedDrag
* {Boolean}
*/
performedDrag: false,
/**
* Property: wheelObserver
* {Function}
*/
wheelObserver: null,
/**
* Constructor: OpenLayers.Control.MouseDefaults
*/
initialize: function() {
OpenLayers.Control.prototype.initialize.apply(this, arguments);
},
/**
* APIMethod: destroy
*/
destroy: function() {
if (this.handler) {
this.handler.destroy();
}
this.handler = null;
this.map.events.un({
"click": this.defaultClick,
"dblclick": this.defaultDblClick,
"mousedown": this.defaultMouseDown,
"mouseup": this.defaultMouseUp,
"mousemove": this.defaultMouseMove,
"mouseout": this.defaultMouseOut,
scope: this
});
//unregister mousewheel events specifically on the window and document
OpenLayers.Event.stopObserving(window, "DOMMouseScroll",
this.wheelObserver);
OpenLayers.Event.stopObserving(window, "mousewheel",
this.wheelObserver);
OpenLayers.Event.stopObserving(document, "mousewheel",
this.wheelObserver);
this.wheelObserver = null;
OpenLayers.Control.prototype.destroy.apply(this, arguments);
},
/**
* Method: draw
*/
draw: function() {
this.map.events.on({
"click": this.defaultClick,
"dblclick": this.defaultDblClick,
"mousedown": this.defaultMouseDown,
"mouseup": this.defaultMouseUp,
"mousemove": this.defaultMouseMove,
"mouseout": this.defaultMouseOut,
scope: this
});
this.registerWheelEvents();
},
/**
* Method: registerWheelEvents
*/
registerWheelEvents: function() {
this.wheelObserver = OpenLayers.Function.bindAsEventListener(
this.onWheelEvent, this
);
//register mousewheel events specifically on the window and document
OpenLayers.Event.observe(window, "DOMMouseScroll", this.wheelObserver);
OpenLayers.Event.observe(window, "mousewheel", this.wheelObserver);
OpenLayers.Event.observe(document, "mousewheel", this.wheelObserver);
},
/**
* Method: defaultClick
*
* Parameters:
* evt - {Event}
*
* Returns:
* {Boolean}
*/
defaultClick: function (evt) {
if (!OpenLayers.Event.isLeftClick(evt)) {
return;
}
var notAfterDrag = !this.performedDrag;
this.performedDrag = false;
return notAfterDrag;
},
/**
* Method: defaultDblClick
*
* Parameters:
* evt - {Event}
*/
defaultDblClick: function (evt) {
var newCenter = this.map.getLonLatFromViewPortPx( evt.xy );
this.map.setCenter(newCenter, this.map.zoom + 1);
OpenLayers.Event.stop(evt);
return false;
},
/**
* Method: defaultMouseDown
*
* Parameters:
* evt - {Event}
*/
defaultMouseDown: function (evt) {
if (!OpenLayers.Event.isLeftClick(evt)) {
return;
}
this.mouseDragStart = evt.xy.clone();
this.performedDrag  = false;
if (evt.shiftKey) {
this.map.div.style.cursor = "crosshair";
this.zoomBox = OpenLayers.Util.createDiv('zoomBox',
this.mouseDragStart,
null,
null,
"absolute",
"2px solid red");
this.zoomBox.style.backgroundColor = "white";
this.zoomBox.style.filter = "alpha(opacity=50)"; // IE
this.zoomBox.style.opacity = "0.50";
this.zoomBox.style.fontSize = "1px";
this.zoomBox.style.zIndex = this.map.Z_INDEX_BASE["Popup"] - 1;
this.map.viewPortDiv.appendChild(this.zoomBox);
}
document.onselectstart=function() { return false; };
OpenLayers.Event.stop(evt);
},
/**
* Method: defaultMouseMove
*
* Parameters:
* evt - {Event}
*/
defaultMouseMove: function (evt) {
// record the mouse position, used in onWheelEvent
this.mousePosition = evt.xy.clone();
if (this.mouseDragStart != null) {
if (this.zoomBox) {
var deltaX = Math.abs(this.mouseDragStart.x - evt.xy.x);
var deltaY = Math.abs(this.mouseDragStart.y - evt.xy.y);
this.zoomBox.style.width = Math.max(1, deltaX) + "px";
this.zoomBox.style.height = Math.max(1, deltaY) + "px";
if (evt.xy.x < this.mouseDragStart.x) {
this.zoomBox.style.left = evt.xy.x+"px";
}
if (evt.xy.y < this.mouseDragStart.y) {
this.zoomBox.style.top = evt.xy.y+"px";
}
} else {
var deltaX = this.mouseDragStart.x - evt.xy.x;
var deltaY = this.mouseDragStart.y - evt.xy.y;
var size = this.map.getSize();
var newXY = new OpenLayers.Pixel(size.w / 2 + deltaX,
size.h / 2 + deltaY);
var newCenter = this.map.getLonLatFromViewPortPx( newXY );
this.map.setCenter(newCenter, null, true);
this.mouseDragStart = evt.xy.clone();
this.map.div.style.cursor = "move";
}
this.performedDrag = true;
}
},
/**
* Method: defaultMouseUp
*
* Parameters:
* evt - {<OpenLayers.Event>}
*/
defaultMouseUp: function (evt) {
if (!OpenLayers.Event.isLeftClick(evt)) {
return;
}
if (this.zoomBox) {
this.zoomBoxEnd(evt);
} else {
if (this.performedDrag) {
this.map.setCenter(this.map.center);
}
}
document.onselectstart=null;
this.mouseDragStart = null;
this.map.div.style.cursor = "";
},
/**
* Method: defaultMouseOut
*
* Parameters:
* evt - {Event}
*/
defaultMouseOut: function (evt) {
if (this.mouseDragStart != null &&
OpenLayers.Util.mouseLeft(evt, this.map.div)) {
if (this.zoomBox) {
this.removeZoomBox();
}
this.mouseDragStart = null;
}
},
/**
* Method: defaultWheelUp
* User spun scroll wheel up
*
*/
defaultWheelUp: function(evt) {
if (this.map.getZoom() <= this.map.getNumZoomLevels()) {
this.map.setCenter(this.map.getLonLatFromPixel(evt.xy),
this.map.getZoom() + 1);
}
},
/**
* Method: defaultWheelDown
* User spun scroll wheel down
*/
defaultWheelDown: function(evt) {
if (this.map.getZoom() > 0) {
this.map.setCenter(this.map.getLonLatFromPixel(evt.xy),
this.map.getZoom() - 1);
}
},
/**
* Method: zoomBoxEnd
* Zoombox function.
*/
zoomBoxEnd: function(evt) {
if (this.mouseDragStart != null) {
if (Math.abs(this.mouseDragStart.x - evt.xy.x) > 5 ||
Math.abs(this.mouseDragStart.y - evt.xy.y) > 5) {
var start = this.map.getLonLatFromViewPortPx( this.mouseDragStart );
var end = this.map.getLonLatFromViewPortPx( evt.xy );
var top = Math.max(start.lat, end.lat);
var bottom = Math.min(start.lat, end.lat);
var left = Math.min(start.lon, end.lon);
var right = Math.max(start.lon, end.lon);
var bounds = new OpenLayers.Bounds(left, bottom, right, top);
this.map.zoomToExtent(bounds);
} else {
var end = this.map.getLonLatFromViewPortPx( evt.xy );
this.map.setCenter(new OpenLayers.LonLat(
(end.lon),
(end.lat)
), this.map.getZoom() + 1);
}
this.removeZoomBox();
}
},
/**
* Method: removeZoomBox
* Remove the zoombox from the screen and nullify our reference to it.
*/
removeZoomBox: function() {
this.map.viewPortDiv.removeChild(this.zoomBox);
this.zoomBox = null;
},
/**
*  Mouse ScrollWheel code thanks to http://adomas.org/javascript-mouse-wheel/
*/
/**
* Method: onWheelEvent
* Catch the wheel event and handle it xbrowserly
*
* Parameters:
* e - {Event}
*/
onWheelEvent: function(e){
// first determine whether or not the wheeling was inside the map
var inMap = false;
var elem = OpenLayers.Event.element(e);
while(elem != null) {
if (this.map && elem == this.map.div) {
inMap = true;
break;
}
elem = elem.parentNode;
}
if (inMap) {
var delta = 0;
if (!e) {
e = window.event;
}
if (e.wheelDelta) {
delta = e.wheelDelta/120;
if (window.opera && window.opera.version() < 9.2) {
delta = -delta;
}
} else if (e.detail) {
delta = -e.detail / 3;
}
if (delta) {
// add the mouse position to the event because mozilla has a bug
// with clientX and clientY (see https://bugzilla.mozilla.org/show_bug.cgi?id=352179)
// getLonLatFromViewPortPx(e) returns wrong values
e.xy = this.mousePosition;
if (delta < 0) {
this.defaultWheelDown(e);
} else {
this.defaultWheelUp(e);
}
}
//only wheel the map, not the window
OpenLayers.Event.stop(e);
}
},
CLASS_NAME: "OpenLayers.Control.MouseDefaults"
});
/* Copyright (c) 2006-2008 MetaCarta, Inc., 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
*/
/**
* Class: OpenLayers.Control.MousePosition
*/
OpenLayers.Control.MousePosition = OpenLayers.Class(OpenLayers.Control, {
/**
* Property: element
* {DOMElement}
*/
element: null,
/**
* APIProperty: prefix
* {String}
*/
prefix: '',
/**
* APIProperty: separator
* {String}
*/
separator: ', ',
/**
* APIProperty: suffix
* {String}
*/
suffix: '',
/**
* APIProperty: numDigits
* {Integer}
*/
numdigits: 5,
/**
* APIProperty: granularity
* {Integer}
*/
granularity: 10,
/**
* Property: lastXy
* {<OpenLayers.LonLat>}
*/
lastXy: null,
/**
* APIProperty: displayProjection
* {<OpenLayers.Projection>} A projection that the
* mousecontrol will display.
*/
displayProjection: null,
/**
* Constructor: OpenLayers.Control.MousePosition
*
* Parameters:
* options - {DOMElement} Options for control.
*/
initialize: function(options) {
OpenLayers.Control.prototype.initialize.apply(this, arguments);
},
/**
* Method: destroy
*/
destroy: function() {
if (this.map) {
this.map.events.unregister('mousemove', this, this.redraw);
}
OpenLayers.Control.prototype.destroy.apply(this, arguments);
},
/**
* Method: draw
* {DOMElement}
*/
draw: function() {
OpenLayers.Control.prototype.draw.apply(this, arguments);
if (!this.element) {
this.div.left = "";
this.div.top = "";
this.element = this.div;
}
this.redraw();
return this.div;
},
/**
* Method: redraw
*/
redraw: function(evt) {
var lonLat;
if (evt == null) {
lonLat = new OpenLayers.LonLat(0, 0);
} else {
if (this.lastXy == null ||
Math.abs(evt.xy.x - this.lastXy.x) > this.granularity ||
Math.abs(evt.xy.y - this.lastXy.y) > this.granularity)
{
this.lastXy = evt.xy;
return;
}
lonLat = this.map.getLonLatFromPixel(evt.xy);
if (!lonLat) {
// map has not yet been properly initialized
return;
}
if (this.displayProjection) {
lonLat.transform(this.map.getProjectionObject(),
this.displayProjection );
}
this.lastXy = evt.xy;
}
var newHtml = this.formatOutput(lonLat);
if (newHtml != this.element.innerHTML) {
this.element.innerHTML = newHtml;
}
},
/**
* Method: formatOutput
* Override to provide custom display output
*
* Parameters:
* lonLat - {<OpenLayers.LonLat>} Location to display
*/
formatOutput: function(lonLat) {
var digits = parseInt(this.numdigits);
var newHtml =
this.prefix +
lonLat.lon.toFixed(digits) +
this.separator +
lonLat.lat.toFixed(digits) +
this.suffix;
return newHtml;
},
/**
* Method: setMap
*/
setMap: function() {
OpenLayers.Control.prototype.setMap.apply(this, arguments);
this.map.events.register( 'mousemove', this, this.redraw);
},
CLASS_NAME: "OpenLayers.Control.MousePosition"
});
/* Copyright (c) 2006-2008 MetaCarta, Inc., 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
* Create an overview map to display the extent of your main map and provide
* additional navigation control.  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,
/**
* Property: handlers
* {Object}
*/
handlers: null,
/**
* 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;
}
this.handlers.click.destroy();
this.mapDiv.removeChild(this.extentRectangle);
this.extentRectangle = null;
this.rectEvents.destroy();
this.rectEvents = null;
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 + 'omap-switcher-maximize.png';
this.maximizeDiv = OpenLayers.Util.createAlphaImageDiv(
this.displayClass + 'MaximizeButton',
null,
new OpenLayers.Size(20,20),
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 + 'omap-switcher-minimize.png';
this.minimizeDiv = OpenLayers.Util.createAlphaImageDiv(
'OpenLayers_Control_minimizeDiv',
null,
new OpenLayers.Size(20,20),
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; i < eventsToStop.length; 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);
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();
},
/**
* Method: maximizeControl
* Unhide the control.  Called when the control is in the map viewport.
*
* Parameters:
* e - {<OpenLayers.Event>}
*/
maximizeControl: function(e) {
this.element.style.display = '';
this.showToggle(false);
if (e != null) {
OpenLayers.Event.stop(e);
}
},
/**
* Method: minimizeControl
* Hide all the contents of the control, shrink the size,
* add the maximize icon
*
* Parameters:
* e - {<OpenLayers.Event>}
*/
minimizeControl: function(e) {
this.element.style.display = 'none';
this.showToggle(true);
if (e != null) {
OpenLayers.Event.stop(e);
}
},
/**
* Method: showToggle
* Hide/Show the toggle depending on whether the control is minimized
*
* Parameters:
* minimize - {Boolean}
*/
showToggle: function(minimize) {
this.maximizeDiv.style.display = minimize ? '' : 'none';
this.minimizeDiv.style.display = minimize ? 'none' : '';
},
/**
* Method: update
* Update the overview map after layers move.
*/
update: function() {
if(this.ovmap == null) {
this.createMap();
}
if(!this.isSuitableOverview()) {
this.updateOverview();
}
// update extent rectangle
this.updateRectToMap();
},
/**
* Method: isSuitableOverview
* Determines if the overview map is suitable given the extent and
* resolution of the main map.
*/
isSuitableOverview: function() {
var mapExtent = this.map.getExtent();
var maxExtent = this.map.maxExtent;
var testExtent = new OpenLayers.Bounds(
Math.max(mapExtent.left, maxExtent.left),
Math.max(mapExtent.bottom, maxExtent.bottom),
Math.min(mapExtent.right, maxExtent.right),
Math.min(mapExtent.top, maxExtent.top));
var resRatio = this.ovmap.getResolution() / this.map.getResolution();
return ((resRatio > this.minRatio) &&
(resRatio <= this.maxRatio) &&
(this.ovmap.getExtent().containsBounds(testExtent)));
},
/**
* Method updateOverview
* Called by <update> if <isSuitableOverview> returns true
*/
updateOverview: function() {
var mapRes = this.map.getResolution();
var targetRes = this.ovmap.getResolution();
var resRatio = targetRes / mapRes;
if(resRatio > this.maxRatio) {
// zoom in overview map
targetRes = this.minRatio * mapRes;
} else if(resRatio <= this.minRatio) {
// zoom out overview map
targetRes = this.maxRatio * mapRes;
}
this.ovmap.setCenter(this.map.center,
this.ovmap.getZoomForResolution(targetRes));
this.updateRectToMap();
},
/**
* Method: createMap
* Construct the map that this control contains
*/
createMap: function() {
// create the overview map
var options = OpenLayers.Util.extend(
{controls: [], maxResolution: 'auto',
fallThrough: false}, this.mapOptions);
this.ovmap = new OpenLayers.Map(this.mapDiv, options);
// prevent ovmap from being destroyed when the page unloads, because
// the OverviewMap control has to do this (and does it).
OpenLayers.Event.stopObserving(window, 'unload', this.ovmap.unloadDestroy);
this.ovmap.addLayers(this.layers);
this.ovmap.zoomToMaxExtent();
// check extent rectangle border width
this.wComp = parseInt(OpenLayers.Element.getStyle(this.extentRectangle,
'border-left-width')) +
parseInt(OpenLayers.Element.getStyle(this.extentRectangle,
'border-right-width'));
this.wComp = (this.wComp) ? this.wComp : 2;
this.hComp = parseInt(OpenLayers.Element.getStyle(this.extentRectangle,
'border-top-width')) +
parseInt(OpenLayers.Element.getStyle(this.extentRectangle,
'border-bottom-width'));
this.hComp = (this.hComp) ? this.hComp : 2;
this.handlers.drag = new OpenLayers.Handler.Drag(
this, {move: this.rectDrag, done: this.updateMapToRect},
{map: this.ovmap}
);
this.handlers.click = new OpenLayers.Handler.Click(
this, {
"click": this.mapDivClick
},{
"single": true, "double": false,
"stopSingle": true, "stopDouble": true,
"pixelTolerance": 1,
map: this.ovmap
}
);
this.handlers.click.activate();
this.rectEvents = new OpenLayers.Events(this, this.extentRectangle,
null, true);
this.rectEvents.register("mouseover", this, function(e) {
if(!this.handlers.drag.active && !this.map.dragging) {
this.handlers.drag.activate();
}
});
this.rectEvents.register("mouseout", this, function(e) {
if(!this.handlers.drag.dragging) {
this.handlers.drag.deactivate();
}
});
},
/**
* Method: updateRectToMap
* Updates the extent rectangle position and size to match the map extent
*/
updateRectToMap: function() {
// The base layer for overview map needs to be in the same projection
// as the base layer for the main map.  This should be made more robust.
if(this.map.units != 'degrees') {
if(this.ovmap.getProjection() && (this.map.getProjection() != this.ovmap.getProjection())) {
alert(OpenLayers.i18n("sameProjection"));
}
}
var pxBounds = this.getRectBoundsFromMapBounds(this.map.getExtent());
if (pxBounds) {
this.setRectPxBounds(pxBounds);
}
},
/**
* Method: updateMapToRect
* Updates the map extent to match the extent rectangle position and size
*/
updateMapToRect: function() {
var lonLatBounds = this.getMapBoundsFromRectBounds(this.rectPxBounds);
this.map.panTo(lonLatBounds.getCenterLonLat());
},
/**
* Method: setRectPxBounds
* Set extent rectangle pixel bounds.
*
* Parameters:
* pxBounds - {<OpenLayers.Bounds>}
*/
setRectPxBounds: function(pxBounds) {
var top = Math.max(pxBounds.top, 0);
var left = Math.max(pxBounds.left, 0);
var bottom = Math.min(pxBounds.top + Math.abs(pxBounds.getHeight()),
this.ovmap.size.h - this.hComp);
var right = Math.min(pxBounds.left + pxBounds.getWidth(),
this.ovmap.size.w - this.wComp);
var width = Math.max(right - left, 0);
var height = Math.max(bottom - top, 0);
if(width < this.minRectSize || height < this.minRectSize) {
this.extentRectangle.className = this.displayClass +
this.minRectDisplayClass;
var rLeft = left + (width / 2) - (this.minRectSize / 2);
var rTop = top + (height / 2) - (this.minRectSize / 2);
this.extentRectangle.style.top = Math.round(rTop) + 'px';
this.extentRectangle.style.left = Math.round(rLeft) + 'px';
this.extentRectangle.style.height = this.minRectSize + 'px';
this.extentRectangle.style.width = this.minRectSize + 'px';
} else {
this.extentRectangle.className = this.displayClass +
'ExtentRectangle';
this.extentRectangle.style.top = Math.round(top) + 'px';
this.extentRectangle.style.left = Math.round(left) + 'px';
this.extentRectangle.style.height = Math.round(height) + 'px';
this.extentRectangle.style.width = Math.round(width) + 'px';
}
this.rectPxBounds = new OpenLayers.Bounds(
Math.round(left), Math.round(bottom),
Math.round(right), Math.round(top)
);
},
/**
* Method: getRectBoundsFromMapBounds
* Get the rect bounds from the map bounds.
*
* Parameters:
* lonLatBounds - {<OpenLayers.Bounds>}
*
* Returns:
* {<OpenLayers.Bounds>}A bounds which is the passed-in map lon/lat extent
* translated into pixel bounds for the overview map
*/
getRectBoundsFromMapBounds: function(lonLatBounds) {
var leftBottomLonLat = new OpenLayers.LonLat(lonLatBounds.left,
lonLatBounds.bottom);
var rightTopLonLat = new OpenLayers.LonLat(lonLatBounds.right,
lonLatBounds.top);
var leftBottomPx = this.getOverviewPxFromLonLat(leftBottomLonLat);
var rightTopPx = this.getOverviewPxFromLonLat(rightTopLonLat);
var bounds = null;
if (leftBottomPx && rightTopPx) {
bounds = new OpenLayers.Bounds(leftBottomPx.x, leftBottomPx.y,
rightTopPx.x, rightTopPx.y);
}
return bounds;
},
/**
* Method: getMapBoundsFromRectBounds
* Get the map bounds from the rect bounds.
*
* Parameters:
* pxBounds - {<OpenLayers.Bounds>}
*
* Returns:
* {<OpenLayers.Bounds>} Bounds which is the passed-in overview rect bounds
* translated into lon/lat bounds for the overview map
*/
getMapBoundsFromRectBounds: function(pxBounds) {
var leftBottomPx = new OpenLayers.Pixel(pxBounds.left,
pxBounds.bottom);
var rightTopPx = new OpenLayers.Pixel(pxBounds.right,
pxBounds.top);
var leftBottomLonLat = this.getLonLatFromOverviewPx(leftBottomPx);
var rightTopLonLat = this.getLonLatFromOverviewPx(rightTopPx);
return new OpenLayers.Bounds(leftBottomLonLat.lon, leftBottomLonLat.lat,
rightTopLonLat.lon, rightTopLonLat.lat);
},
/**
* Method: getLonLatFromOverviewPx
* Get a map location from a pixel location
*
* Parameters:
* overviewMapPx - {<OpenLayers.Pixel>}
*
* Returns:
* {<OpenLayers.LonLat>} Location which is the passed-in overview map
* OpenLayers.Pixel, translated into lon/lat by the overview map
*/
getLonLatFromOverviewPx: function(overviewMapPx) {
var size = this.ovmap.size;
var res  = this.ovmap.getResolution();
var center = this.ovmap.getExtent().getCenterLonLat();
var delta_x = overviewMapPx.x - (size.w / 2);
var delta_y = overviewMapPx.y - (size.h / 2);
return new OpenLayers.LonLat(center.lon + delta_x * res ,
center.lat - delta_y * res);
},
/**
* Method: getOverviewPxFromLonLat
* Get a pixel location from a map location
*
* Parameters:
* lonlat - {<OpenLayers.LonLat>}
*
* Returns:
* {<OpenLayers.Pixel>} Location which is the passed-in OpenLayers.LonLat,
* translated into overview map pixels
*/
getOverviewPxFromLonLat: function(lonlat) {
var res  = this.ovmap.getResolution();
var extent = this.ovmap.getExtent();
var px = null;
if (extent) {
px = new OpenLayers.Pixel(
Math.round(1/res * (lonlat.lon - extent.left)),
Math.round(1/res * (extent.top - lonlat.lat)));
}
return px;
},
CLASS_NAME: 'OpenLayers.Control.OverviewMap'
});
/* Copyright (c) 2006-2008 MetaCarta, Inc., 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/Handler/Keyboard.js
*/
/**
* Class: OpenLayers.Control.KeyboardDefaults
*
* Inherits from:
*  - <OpenLayers.Control>
*/
OpenLayers.Control.KeyboardDefaults = OpenLayers.Class(OpenLayers.Control, {
/**
* APIProperty: slideFactor
* Pixels to slide by.
*/
slideFactor: 75,
/**
* Constructor: OpenLayers.Control.KeyboardDefaults
*/
initialize: function() {
OpenLayers.Control.prototype.initialize.apply(this, arguments);
},
/**
* APIMethod: destroy
*/
destroy: function() {
if (this.handler) {
this.handler.destroy();
}
this.handler = null;
OpenLayers.Control.prototype.destroy.apply(this, arguments);
},
/**
* Method: draw
* Create handler.
*/
draw: function() {
this.handler = new OpenLayers.Handler.Keyboard( this, {
"keypress": this.defaultKeyPress });
this.activate();
},
/**
* Method: defaultKeyPress
*
* Parameters:
* code - {Integer}
*/
defaultKeyPress: function (code) {
switch(code) {
case OpenLayers.Event.KEY_LEFT:
this.map.pan(-this.slideFactor, 0);
break;
case OpenLayers.Event.KEY_RIGHT:
this.map.pan(this.slideFactor, 0);
break;
case OpenLayers.Event.KEY_UP:
this.map.pan(0, -this.slideFactor);
break;
case OpenLayers.Event.KEY_DOWN:
this.map.pan(0, this.slideFactor);
break;
case 33: // Page Up
var size = this.map.getSize();
this.map.pan(0, -0.75*size.h);
break;
case 34: // Page Down
var size = this.map.getSize();
this.map.pan(0, 0.75*size.h);
break;
case 35: // End
var size = this.map.getSize();
this.map.pan(0.75*size.w, 0);
break;
case 36: // Pos1
var size = this.map.getSize();
this.map.pan(-0.75*size.w, 0);
break;
case 43: // +
this.map.zoomIn();
break;
case 45: // -
this.map.zoomOut();
break;
case 107: // + (IE only)
this.map.zoomIn();
break;
case 109: // - (IE only)
this.map.zoomOut();
break;
}
},
CLASS_NAME: "OpenLayers.Control.KeyboardDefaults"
});
/* Copyright (c) 2006-2008 MetaCarta, Inc., 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
*/
/**
* Class: OpenLayers.Control.PanZoom
*
* Inherits from:
*  - <OpenLayers.Control>
*/
OpenLayers.Control.PanZoom = OpenLayers.Class(OpenLayers.Control, {
/**
* APIProperty: slideFactor
* {Integer} Number of pixels by which we'll pan the map in any direction
*     on clicking the arrow buttons.
*/
slideFactor: 50,
/**
* Property: buttons
* {Array(DOMElement)} Array of Button Divs
*/
buttons: null,
/**
* Property: position
* {<OpenLayers.Pixel>}
*/
position: null,
/**
* Constructor: OpenLayers.Control.PanZoom
*
* Parameters:
* options - {Object}
*/
initialize: function(options) {
this.position = new OpenLayers.Pixel(OpenLayers.Control.PanZoom.X,
OpenLayers.Control.PanZoom.Y);
OpenLayers.Control.prototype.initialize.apply(this, arguments);
},
/**
* APIMethod: destroy
*/
destroy: function() {
OpenLayers.Control.prototype.destroy.apply(this, arguments);
while(this.buttons.length) {
var btn = this.buttons.shift();
btn.map = null;
OpenLayers.Event.stopObservingElement(btn);
}
this.buttons = null;
this.position = null;
},
/**
* Method: draw
*
* Parameters:
* px - {<OpenLayers.Pixel>}
*
* Returns:
* {DOMElement} A reference to the container div for the PanZoom control.
*/
draw: function(px) {
// initialize our internal div
OpenLayers.Control.prototype.draw.apply(this, arguments);
px = this.position;
// place the controls
this.buttons = [];
var sz = new OpenLayers.Size(18,18);
var centered = new OpenLayers.Pixel(px.x+sz.w/2, px.y);
this._addButton("panup", "north-mini.png", centered, sz);
px.y = centered.y+sz.h;
this._addButton("panleft", "west-mini.png", px, sz);
this._addButton("panright", "east-mini.png", px.add(sz.w, 0), sz);
this._addButton("pandown", "south-mini.png",
centered.add(0, sz.h*2), sz);
this._addButton("zoomin", "zoom-plus-mini.png",
centered.add(0, sz.h*3+5), sz);
this._addButton("zoomworld", "zoom-world-mini.png",
centered.add(0, sz.h*4+5), sz);
this._addButton("zoomout", "zoom-minus-mini.png",
centered.add(0, sz.h*5+5), sz);
return this.div;
},
/**
* Method: _addButton
*
* Parameters:
* id - {String}
* img - {String}
* xy - {<OpenLayers.Pixel>}
* sz - {<OpenLayers.Size>}
*
* Returns:
* {DOMElement} A Div (an alphaImageDiv, to be precise) that contains the
*     image of the button, and has all the proper event handlers set.
*/
_addButton:function(id, img, xy, sz) {
var imgLocation = OpenLayers.Util.getImagesLocation() + img;
var btn = OpenLayers.Util.createAlphaImageDiv(
"OpenLayers_Control_PanZoom_" + id,
xy, sz, imgLocation, "absolute");
//we want to add the outer div
this.div.appendChild(btn);
OpenLayers.Event.observe(btn, "mousedown",
OpenLayers.Function.bindAsEventListener(this.buttonDown, btn));
OpenLayers.Event.observe(btn, "dblclick",
OpenLayers.Function.bindAsEventListener(this.doubleClick, btn));
OpenLayers.Event.observe(btn, "click",
OpenLayers.Function.bindAsEventListener(this.doubleClick, btn));
btn.action = id;
btn.map = this.map;
btn.slideFactor = this.slideFactor;
//we want to remember/reference the outer div
this.buttons.push(btn);
return btn;
},
/**
* Method: doubleClick
*
* Parameters:
* evt - {Event}
*
* Returns:
* {Boolean}
*/
doubleClick: function (evt) {
OpenLayers.Event.stop(evt);
return false;
},
/**
* Method: buttonDown
*
* Parameters:
* evt - {Event}
*/
buttonDown: function (evt) {
if (!OpenLayers.Event.isLeftClick(evt)) {
return;
}
switch (this.action) {
case "panup":
this.map.pan(0, -this.slideFactor);
break;
case "pandown":
this.map.pan(0, this.slideFactor);
break;
case "panleft":
this.map.pan(-this.slideFactor, 0);
break;
case "panright":
this.map.pan(this.slideFactor, 0);
break;
case "zoomin":
this.map.zoomIn();
break;
case "zoomout":
this.map.zoomOut();
break;
case "zoomworld":
this.map.zoomToMaxExtent();
break;
}
OpenLayers.Event.stop(evt);
},
CLASS_NAME: "OpenLayers.Control.PanZoom"
});
/**
* Constant: X
* {Integer}
*/
OpenLayers.Control.PanZoom.X = 4;
/**
* Constant: Y
* {Integer}
*/
OpenLayers.Control.PanZoom.Y = 4;
/* Copyright (c) 2006-2008 MetaCarta, Inc., 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/PanZoom.js
*/
/**
* Class: OpenLayers.Control.PanZoomBar
*
* Inherits from:
*  - <OpenLayers.Control.PanZoom>
*/
OpenLayers.Control.PanZoomBar = OpenLayers.Class(OpenLayers.Control.PanZoom, {
/**
* APIProperty: zoomStopWidth
*/
zoomStopWidth: 18,
/**
* APIProperty: zoomStopHeight
*/
zoomStopHeight: 10,
/**
* Property: slider
*/
slider: null,
/**
* Property: sliderEvents
* {<OpenLayers.Events>}
*/
sliderEvents: null,
/**
* Property: zoomBarDiv
* {DOMElement}
*/
zoomBarDiv: null,
/**
* Property: divEvents
* {<OpenLayers.Events>}
*/
divEvents: null,
/**
* Property: zoomWorldIcon
* {Boolean}
*/
zoomWorldIcon: true,
/**
* Constructor: OpenLayers.Control.PanZoomBar
*/
initialize: function() {
OpenLayers.Control.PanZoom.prototype.initialize.apply(this, arguments);
},
/**
* APIMethod: destroy
*/
destroy: function() {
this.div.removeChild(this.slider);
this.slider = null;
this.sliderEvents.destroy();
this.sliderEvents = null;
this.div.removeChild(this.zoombarDiv);
this.zoomBarDiv = null;
this.divEvents.destroy();
this.divEvents = null;
this.map.events.un({
"zoomend": this.moveZoomBar,
"changebaselayer": this.redraw,
scope: this
});
OpenLayers.Control.PanZoom.prototype.destroy.apply(this, arguments);
},
/**
* Method: setMap
*
* Parameters:
* map - {<OpenLayers.Map>}
*/
setMap: function(map) {
OpenLayers.Control.PanZoom.prototype.setMap.apply(this, arguments);
this.map.events.register("changebaselayer", this, this.redraw);
},
/**
* Method: redraw
* clear the div and start over.
*/
redraw: function() {
if (this.div != null) {
this.div.innerHTML = "";
}
this.draw();
},
/**
* Method: draw
*
* Parameters:
* px - {<OpenLayers.Pixel>}
*/
draw: function(px) {
// initialize our internal div
OpenLayers.Control.prototype.draw.apply(this, arguments);
px = this.position.clone();
// place the controls
this.buttons = [];
var sz = new OpenLayers.Size(18,18);
var centered = new OpenLayers.Pixel(px.x+sz.w/2, px.y);
var wposition = sz.w;
if (this.zoomWorldIcon) {
centered = new OpenLayers.Pixel(px.x+sz.w, px.y);
}
this._addButton("panup", "north-mini.png", centered, sz);
px.y = centered.y+sz.h;
this._addButton("panleft", "west-mini.png", px, sz);
if (this.zoomWorldIcon) {
this._addButton("zoomworld", "zoom-world-mini.png", px.add(sz.w, 0), sz);
wposition *= 2;
}
this._addButton("panright", "east-mini.png", px.add(wposition, 0), sz);
this._addButton("pandown", "south-mini.png", centered.add(0, sz.h*2), sz);
this._addButton("zoomin", "zoom-plus-mini.png", centered.add(0, sz.h*3+5), sz);
centered = this._addZoomBar(centered.add(0, sz.h*4 + 5));
this._addButton("zoomout", "zoom-minus-mini.png", centered, sz);
return this.div;
},
/**
* Method: _addZoomBar
*
* Parameters:
* location - {<OpenLayers.Pixel>} where zoombar drawing is to start.
*/
_addZoomBar:function(centered) {
var imgLocation = OpenLayers.Util.getImagesLocation();
var id = "OpenLayers_Control_PanZoomBar_Slider" + this.map.id;
var zoomsToEnd = this.map.getNumZoomLevels() - 1 - this.map.getZoom();
var slider = OpenLayers.Util.createAlphaImageDiv(id,
centered.add(-1, zoomsToEnd * this.zoomStopHeight),
new OpenLayers.Size(20,8),
imgLocation+"slider.png",
"absolute");
this.slider = slider;
this.sliderEvents = new OpenLayers.Events(this, slider, null, true);
this.sliderEvents.on({
"mousedown": this.zoomBarDown,
"mousemove": this.zoomBarDrag,
"mouseup": this.zoomBarUp,
"dblclick": this.doubleClick,
"click": this.doubleClick
});
var sz = new OpenLayers.Size();
sz.h = this.zoomStopHeight * this.map.getNumZoomLevels();
sz.w = this.zoomStopWidth;
var div = null;
if (OpenLayers.Util.alphaHack()) {
var id = "OpenLayers_Control_PanZoomBar" + this.map.id;
div = OpenLayers.Util.createAlphaImageDiv(id, centered,
new OpenLayers.Size(sz.w,
this.zoomStopHeight),
imgLocation + "zoombar.png",
"absolute", null, "crop");
div.style.height = sz.h;
} else {
div = OpenLayers.Util.createDiv(
'OpenLayers_Control_PanZoomBar_Zoombar' + this.map.id,
centered,
sz,
imgLocation+"zoombar.png");
}
this.zoombarDiv = div;
this.divEvents = new OpenLayers.Events(this, div, null, true);
this.divEvents.on({
"mousedown": this.divClick,
"mousemove": this.passEventToSlider,
"dblclick": this.doubleClick,
"click": this.doubleClick
});
this.div.appendChild(div);
this.startTop = parseInt(div.style.top);
this.div.appendChild(slider);
this.map.events.register("zoomend", this, this.moveZoomBar);
centered = centered.add(0,
this.zoomStopHeight * this.map.getNumZoomLevels());
return centered;
},
/*
* Method: passEventToSlider
* This function is used to pass events that happen on the div, or the map,
* through to the slider, which then does its moving thing.
*
* Parameters:
* evt - {<OpenLayers.Event>}
*/
passEventToSlider:function(evt) {
this.sliderEvents.handleBrowserEvent(evt);
},
/*
* Method: divClick
* Picks up on clicks directly on the zoombar div
*           and sets the zoom level appropriately.
*/
divClick: function (evt) {
if (!OpenLayers.Event.isLeftClick(evt)) {
return;
}
var y = evt.xy.y;
var top = OpenLayers.Util.pagePosition(evt.object)[1];
var levels = (y - top)/this.zoomStopHeight;
if(!this.map.fractionalZoom) {
levels = Math.floor(levels);
}
var zoom = (this.map.getNumZoomLevels() - 1) - levels;
zoom = Math.min(Math.max(zoom, 0), this.map.getNumZoomLevels() - 1);
this.map.zoomTo(zoom);
OpenLayers.Event.stop(evt);
},
/*
* Method: zoomBarDown
* event listener for clicks on the slider
*
* Parameters:
* evt - {<OpenLayers.Event>}
*/
zoomBarDown:function(evt) {
if (!OpenLayers.Event.isLeftClick(evt)) {
return;
}
this.map.events.on({
"mousemove": this.passEventToSlider,
"mouseup": this.passEventToSlider,
scope: this
});
this.mouseDragStart = evt.xy.clone();
this.zoomStart = evt.xy.clone();
this.div.style.cursor = "move";
// reset the div offsets just in case the div moved
this.zoombarDiv.offsets = null;
OpenLayers.Event.stop(evt);
},
/*
* Method: zoomBarDrag
* This is what happens when a click has occurred, and the client is
* dragging.  Here we must ensure that the slider doesn't go beyond the
* bottom/top of the zoombar div, as well as moving the slider to its new
* visual location
*
* Parameters:
* evt - {<OpenLayers.Event>}
*/
zoomBarDrag:function(evt) {
if (this.mouseDragStart != null) {
var deltaY = this.mouseDragStart.y - evt.xy.y;
var offsets = OpenLayers.Util.pagePosition(this.zoombarDiv);
if ((evt.clientY - offsets[1]) > 0 &&
(evt.clientY - offsets[1]) < parseInt(this.zoombarDiv.style.height) - 2) {
var newTop = parseInt(this.slider.style.top) - deltaY;
this.slider.style.top = newTop+"px";
}
this.mouseDragStart = evt.xy.clone();
OpenLayers.Event.stop(evt);
}
},
/*
* Method: zoomBarUp
* Perform cleanup when a mouseup event is received -- discover new zoom
* level and switch to it.
*
* Parameters:
* evt - {<OpenLayers.Event>}
*/
zoomBarUp:function(evt) {
if (!OpenLayers.Event.isLeftClick(evt)) {
return;
}
if (this.zoomStart) {
this.div.style.cursor="";
this.map.events.un({
"mouseup": this.passEventToSlider,
"mousemove": this.passEventToSlider,
scope: this
});
var deltaY = this.zoomStart.y - evt.xy.y;
var zoomLevel = this.map.zoom;
if (this.map.fractionalZoom) {
zoomLevel += deltaY/this.zoomStopHeight;
zoomLevel = Math.min(Math.max(zoomLevel, 0),
this.map.getNumZoomLevels() - 1);
} else {
zoomLevel += Math.round(deltaY/this.zoomStopHeight);
}
this.map.zoomTo(zoomLevel);
this.moveZoomBar();
this.mouseDragStart = null;
OpenLayers.Event.stop(evt);
}
},
/*
* Method: moveZoomBar
* Change the location of the slider to match the current zoom level.
*/
moveZoomBar:function() {
var newTop =
((this.map.getNumZoomLevels()-1) - this.map.getZoom()) *
this.zoomStopHeight + this.startTop + 1;
this.slider.style.top = newTop + "px";
},
CLASS_NAME: "OpenLayers.Control.PanZoomBar"
});
/* Copyright (c) 2006-2008 MetaCarta, Inc., 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
*/
/**
* Class: OpenLayers.Control.LayerSwitcher
*
* Inherits from:
*  - <OpenLayers.Control>
*/
OpenLayers.Control.LayerSwitcher =
OpenLayers.Class(OpenLayers.Control, {
/**
* Property: activeColor
* {String}
*/
activeColor: "#ffffff",
/**
* Property: layerStates
* {Array(Object)} Basically a copy of the "state" of the map's layers
*     the last time the control was drawn. We have this in order to avoid
*     unnecessarily redrawing the control.
*/
layerStates: null,
// DOM Elements
/**
* Property: layersDiv
* {DOMElement}
*/
layersDiv: null,
/**
* Property: baseLayersDiv
* {DOMElement}
*/
baseLayersDiv: null,
/**
* Property: baseLayers
* {Array(<OpenLayers.Layer>)}
*/
baseLayers: null,
/**
* Property: dataLbl
* {DOMElement}
*/
dataLbl: null,
/**
* Property: dataLayersDiv
* {DOMElement}
*/
dataLayersDiv: null,
/**
* Property: dataLayers
* {Array(<OpenLayers.Layer>)}
*/
dataLayers: null,
/**
* Property: minimizeDiv
* {DOMElement}
*/
minimizeDiv: null,
/**
* Property: maximizeDiv
* {DOMElement}
*/
maximizeDiv: null,
/**
* APIProperty: ascending
* {Boolean}
*/
ascending: true,
/**
* Constructor: OpenLayers.Control.LayerSwitcher
*
* Parameters:
* options - {Object}
*/
initialize: function(options) {
OpenLayers.Control.prototype.initialize.apply(this, arguments);
this.layerStates = [];
},
/**
* APIMethod: destroy
*/
destroy: function() {
OpenLayers.Event.stopObservingElement(this.div);
OpenLayers.Event.stopObservingElement(this.minimizeDiv);
OpenLayers.Event.stopObservingElement(this.maximizeDiv);
//clear out layers info and unregister their events
this.clearLayersArray("base");
this.clearLayersArray("data");
this.map.events.un({
"addlayer": this.redraw,
"changelayer": this.redraw,
"removelayer": this.redraw,
"changebaselayer": this.redraw,
scope: this
});
OpenLayers.Control.prototype.destroy.apply(this, arguments);
},
/**
* Method: setMap
*
* Properties:
* map - {<OpenLayers.Map>}
*/
setMap: function(map) {
OpenLayers.Control.prototype.setMap.apply(this, arguments);
this.map.events.on({
"addlayer": this.redraw,
"changelayer": this.redraw,
"removelayer": this.redraw,
"changebaselayer": this.redraw,
scope: this
});
},
/**
* Method: draw
*
* Returns:
* {DOMElement} A reference to the DIV DOMElement containing the
*     switcher tabs.
*/
draw: function() {
OpenLayers.Control.prototype.draw.apply(this);
// create layout divs
this.loadContents();
// set mode to minimize
if(!this.outsideViewport) {
this.minimizeControl();
}
// populate div with current info
this.redraw();
return this.div;
},
/**
* Method: clearLayersArray
* User specifies either "base" or "data". we then clear all the
*     corresponding listeners, the div, and reinitialize a new array.
*
* Parameters:
* layersType - {String}
*/
clearLayersArray: function(layersType) {
var layers = this[layersType + "Layers"];
if (layers) {
for(var i=0; i < layers.length; i++) {
var layer = layers[i];
OpenLayers.Event.stopObservingElement(layer.inputElem);
OpenLayers.Event.stopObservingElement(layer.labelSpan);
}
}
this[layersType + "LayersDiv"].innerHTML = "";
this[layersType + "Layers"] = [];
},
/**
* Method: checkRedraw
* Checks if the layer state has changed since the last redraw() call.
*
* Returns:
* {Boolean} The layer state changed since the last redraw() call.
*/
checkRedraw: function() {
var redraw = false;
if ( !this.layerStates.length ||
(this.map.layers.length != this.layerStates.length) ) {
redraw = true;
} else {
for (var i=0; i < this.layerStates.length; i++) {
var layerState = this.layerStates[i];
var layer = this.map.layers[i];
if ( (layerState.name != layer.name) ||
(layerState.inRange != layer.inRange) ||
(layerState.id != layer.id) ||
(layerState.visibility != layer.visibility) ) {
redraw = true;
break;
}
}
}
return redraw;
},
/**
* Method: redraw
* Goes through and takes the current state of the Map and rebuilds the
*     control to display that state. Groups base layers into a
*     radio-button group and lists each data layer with a checkbox.
*
* Returns:
* {DOMElement} A reference to the DIV DOMElement containing the control
*/
redraw: function() {
//if the state hasn't changed since last redraw, no need
// to do anything. Just return the existing div.
if (!this.checkRedraw()) {
return this.div;
}
//clear out previous layers
this.clearLayersArray("base");
this.clearLayersArray("data");
var containsOverlays = false;
var containsBaseLayers = false;
// Save state -- for checking layer if the map state changed.
// We save this before redrawing, because in the process of redrawing
// we will trigger more visibility changes, and we want to not redraw
// and enter an infinite loop.
this.layerStates = new Array(this.map.layers.length);
for (var i = 0; i < this.map.layers.length; i++) {
var layer = this.map.layers[i];
this.layerStates[i] = {
'name': layer.name,
'visibility': layer.visibility,
'inRange': layer.inRange,
'id': layer.id
};
}
var layers = this.map.layers.slice();
if (!this.ascending) { layers.reverse(); }
for( var i = 0; i < layers.length; i++) {
var layer = layers[i];
var baseLayer = layer.isBaseLayer;
if (layer.displayInLayerSwitcher) {
if (baseLayer) {
containsBaseLayers = true;
} else {
containsOverlays = true;
}
// only check a baselayer if it is *the* baselayer, check data
//  layers if they are visible
var checked = (baseLayer) ? (layer == this.map.baseLayer)
: layer.getVisibility();
// create input element
var inputElem = document.createElement("input");
inputElem.id = "input_" + layer.name;
inputElem.name = (baseLayer) ? "baseLayers" : layer.name;
inputElem.type = (baseLayer) ? "radio" : "checkbox";
inputElem.value = layer.name;
inputElem.checked = checked;
inputElem.defaultChecked = checked;
if (!baseLayer && !layer.inRange) {
inputElem.disabled = true;
}
var context = {
'inputElem': inputElem,
'layer': layer,
'layerSwitcher': this
};
OpenLayers.Event.observe(inputElem, "mouseup",
OpenLayers.Function.bindAsEventListener(this.onInputClick,
context)
);
// create span
var labelSpan = document.createElement("span");
if (!baseLayer && !layer.inRange) {
labelSpan.style.color = "gray";
}
labelSpan.innerHTML = layer.name;
labelSpan.style.verticalAlign = (baseLayer) ? "bottom"
: "baseline";
OpenLayers.Event.observe(labelSpan, "click",
OpenLayers.Function.bindAsEventListener(this.onInputClick,
context)
);
// create line break
var br = document.createElement("br");
var groupArray = (baseLayer) ? this.baseLayers
: this.dataLayers;
groupArray.push({
'layer': layer,
'inputElem': inputElem,
'labelSpan': labelSpan
});
var groupDiv = (baseLayer) ? this.baseLayersDiv
: this.dataLayersDiv;
groupDiv.appendChild(inputElem);
groupDiv.appendChild(labelSpan);
groupDiv.appendChild(br);
}
}
// if no overlays, dont display the overlay label
this.dataLbl.style.display = (containsOverlays) ? "" : "none";
// if no baselayers, dont display the baselayer label
this.baseLbl.style.display = (containsBaseLayers) ? "" : "none";
return this.div;
},
/**
* Method:
* A label has been clicked, check or uncheck its corresponding input
*
* Parameters:
* e - {Event}
*
* Context:
*  - {DOMElement} inputElem
*  - {<OpenLayers.Control.LayerSwitcher>} layerSwitcher
*  - {<OpenLayers.Layer>} layer
*/
onInputClick: function(e) {
if (!this.inputElem.disabled) {
if (this.inputElem.type == "radio") {
this.inputElem.checked = true;
this.layer.map.setBaseLayer(this.layer);
} else {
this.inputElem.checked = !this.inputElem.checked;
this.layerSwitcher.updateMap();
}
}
OpenLayers.Event.stop(e);
},
/**
* Method: onLayerClick
* Need to update the map accordingly whenever user clicks in either of
*     the layers.
*
* Parameters:
* e - {Event}
*/
onLayerClick: function(e) {
this.updateMap();
},
/**
* Method: updateMap
* Cycles through the loaded data and base layer input arrays and makes
*     the necessary calls to the Map object such that that the map's
*     visual state corresponds to what the user has selected in
*     the control.
*/
updateMap: function() {
// set the newly selected base layer
for(var i=0; i < this.baseLayers.length; i++) {
var layerEntry = this.baseLayers[i];
if (layerEntry.inputElem.checked) {
this.map.setBaseLayer(layerEntry.layer, false);
}
}
// set the correct visibilities for the overlays
for(var i=0; i < this.dataLayers.length; i++) {
var layerEntry = this.dataLayers[i];
layerEntry.layer.setVisibility(layerEntry.inputElem.checked);
}
},
/**
* Method: maximizeControl
* Set up the labels and divs for the control
*
* Parameters:
* e - {Event}
*/
maximizeControl: function(e) {
//HACK HACK HACK - find a way to auto-size this layerswitcher
this.div.style.width = "20em";
this.div.style.height = "";
this.showControls(false);
if (e != null) {
OpenLayers.Event.stop(e);
}
},
/**
* Method: minimizeControl
* Hide all the contents of the control, shrink the size,
*     add the maximize icon
*
* Parameters:
* e - {Event}
*/
minimizeControl: function(e) {
this.div.style.width = "0px";
this.div.style.height = "0px";
this.showControls(true);
if (e != null) {
OpenLayers.Event.stop(e);
}
},
/**
* Method: showControls
* Hide/Show all LayerSwitcher controls depending on whether we are
*     minimized or not
*
* Parameters:
* minimize - {Boolean}
*/
showControls: function(minimize) {
this.maximizeDiv.style.display = minimize ? "" : "none";
this.minimizeDiv.style.display = minimize ? "none" : "";
this.layersDiv.style.display = minimize ? "none" : "";
},
/**
* Method: loadContents
* Set up the labels and divs for the control
*/
loadContents: function() {
//configure main div
this.div.style.position = "absolute";
this.div.style.top = "25px";
this.div.style.right = "0px";
this.div.style.left = "";
this.div.style.fontFamily = "sans-serif";
this.div.style.fontWeight = "bold";
this.div.style.marginTop = "3px";
this.div.style.marginLeft = "3px";
this.div.style.marginBottom = "3px";
this.div.style.fontSize = "smaller";
this.div.style.color = "#333333";
this.div.style.backgroundColor = "transparent";
OpenLayers.Event.observe(this.div, "mouseup",
OpenLayers.Function.bindAsEventListener(this.mouseUp, this));
OpenLayers.Event.observe(this.div, "click",
this.ignoreEvent);
OpenLayers.Event.observe(this.div, "mousedown",
OpenLayers.Function.bindAsEventListener(this.mouseDown, this));
OpenLayers.Event.observe(this.div, "dblclick", this.ignoreEvent);
// layers list div
this.layersDiv = document.createElement("div");
this.layersDiv.id = "layersDiv";
this.layersDiv.style.paddingTop = "5px";
this.layersDiv.style.paddingLeft = "10px";
this.layersDiv.style.paddingBottom = "5px";
this.layersDiv.style.paddingRight = "75px";
this.layersDiv.style.backgroundColor = this.activeColor;
// had to set width/height to get transparency in IE to work.
// thanks -- http://jszen.blogspot.com/2005/04/ie6-opacity-filter-caveat.html
//
//        this.layersDiv.style.width = "100%";
this.layersDiv.style.height = "100%";
this.baseLbl = document.createElement("div");
this.baseLbl.innerHTML = OpenLayers.i18n("baseLayer");
this.baseLbl.style.marginTop = "3px";
this.baseLbl.style.marginLeft = "3px";
this.baseLbl.style.marginBottom = "3px";
this.baseLayersDiv = document.createElement("div");
this.baseLayersDiv.id = "baseLayersDiv";
this.baseLayersDiv.style.paddingLeft = "10px";
/*OpenLayers.Event.observe(this.baseLayersDiv, "click",
OpenLayers.Function.bindAsEventListener(this.onLayerClick, this));
*/
this.dataLbl = document.createElement("div");
this.dataLbl.innerHTML = OpenLayers.i18n("overlays");
this.dataLbl.style.marginTop = "3px";
this.dataLbl.style.marginLeft = "3px";
this.dataLbl.style.marginBottom = "3px";
this.dataLayersDiv = document.createElement("div");
this.dataLayersDiv.style.paddingLeft = "10px";
if (this.ascending) {
this.layersDiv.appendChild(this.baseLbl);
this.layersDiv.appendChild(this.baseLayersDiv);
this.layersDiv.appendChild(this.dataLbl);
this.layersDiv.appendChild(this.dataLayersDiv);
} else {
this.layersDiv.appendChild(this.dataLbl);
this.layersDiv.appendChild(this.dataLayersDiv);
this.layersDiv.appendChild(this.baseLbl);
this.layersDiv.appendChild(this.baseLayersDiv);
}
this.div.appendChild(this.layersDiv);
OpenLayers.Rico.Corner.round(this.div, {corners: "tl bl",
bgColor: "transparent",
color: this.activeColor,
blend: false});
OpenLayers.Rico.Corner.changeOpacity(this.layersDiv, 0.75);
var imgLocation = OpenLayers.Util.getImagesLocation();
var sz = new OpenLayers.Size(54,20);
// maximize button div
var img = imgLocation + 'layer-switcher-maximize.png';
this.maximizeDiv = OpenLayers.Util.createAlphaImageDiv(
"OpenLayers_Control_MaximizeDiv",
null,
sz,
img,
"absolute");
this.maximizeDiv.style.top = "0";
this.maximizeDiv.style.right = "0px";
this.maximizeDiv.style.left = "";
this.maximizeDiv.style.display = "none";
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';
var sz = new OpenLayers.Size(16,16);
this.minimizeDiv = OpenLayers.Util.createAlphaImageDiv(
"OpenLayers_Control_MinimizeDiv",
null,
sz,
img,
"absolute");
this.minimizeDiv.style.top = "2px";
this.minimizeDiv.style.right = "2px";
this.minimizeDiv.style.left = "";
this.minimizeDiv.style.display = "none";
OpenLayers.Event.observe(this.minimizeDiv, "click",
OpenLayers.Function.bindAsEventListener(this.minimizeControl, this)
);
this.div.appendChild(this.minimizeDiv);
},
/**
* Method: ignoreEvent
*
* Parameters:
* evt - {Event}
*/
ignoreEvent: function(evt) {
OpenLayers.Event.stop(evt);
},
/**
* Method: mouseDown
* Register a local 'mouseDown' flag so that we'll know whether or not
*     to ignore a mouseUp event
*
* Parameters:
* evt - {Event}
*/
mouseDown: function(evt) {
this.isMouseDown = true;
this.ignoreEvent(evt);
},
/**
* Method: mouseUp
* If the 'isMouseDown' flag has been set, that means that the drag was
*     started from within the LayerSwitcher control, and thus we can
*     ignore the mouseup. Otherwise, let the Event continue.
*
* Parameters:
* evt - {Event}
*/
mouseUp: function(evt) {
if (this.isMouseDown) {
this.isMouseDown = false;
this.ignoreEvent(evt);
}
},
CLASS_NAME: "OpenLayers.Control.LayerSwitcher"
});
/* Copyright (c) 2006-2008 MetaCarta, Inc., 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/Feature/Vector.js
* @requires OpenLayers/Handler/Feature.js
*/
/**
* Class: OpenLayers.Control.SelectFeature
* Selects vector features from a given layer on click or hover.
*
* Inherits from:
*  - <OpenLayers.Control>
*/
OpenLayers.Control.SelectFeature = OpenLayers.Class(OpenLayers.Control, {
/**
* Property: multipleKey
* {String} An event modifier ('altKey' or 'shiftKey') that temporarily sets
*     the <multiple> property to true.  Default is null.
*/
multipleKey: null,
/**
* Property: toggleKey
* {String} An event modifier ('altKey' or 'shiftKey') that temporarily sets
*     the <toggle> property to true.  Default is null.
*/
toggleKey: null,
/**
* APIProperty: multiple
* {Boolean} Allow selection of multiple geometries.  Default is false.
*/
multiple: false,
/**
* APIProperty: clickout
* {Boolean} Unselect features when clicking outside any feature.
*     Default is true.
*/
clickout: true,
/**
* APIProperty: toggle
* {Boolean} Unselect a selected feature on click.  Default is false.  Only
*     has meaning if hover is false.
*/
toggle: false,
/**
* APIProperty: hover
* {Boolean} Select on mouse over and deselect on mouse out.  If true, this
* ignores clicks and only listens to mouse moves.
*/
hover: false,
/**
* APIProperty: onSelect
* {Function} Optional function to be called when a feature is selected.
* The function should expect to be called with a feature.
*/
onSelect: function() {},
/**
* APIProperty: onUnselect
* {Function} Optional function to be called when a feature is unselected.
*                  The function should expect to be called with a feature.
*/
onUnselect: function() {},
/**
* APIProperty: geometryTypes
* {Array(String)} To restrict selecting to a limited set of geometry types,
*     send a list of strings corresponding to the geometry class names.
*/
geometryTypes: null,
/**
* Property: layer
* {<OpenLayers.Layer.Vector>}
*/
layer: null,
/**
* APIProperty: callbacks
* {Object} The functions that are sent to the handler for callback
*/
callbacks: null,
/**
* APIProperty: selectStyle
* {Object} Hash of styles
*/
selectStyle: null,
/**
* Property: renderIntent
* {String} key used to retrieve the select style from the layer's
* style map.
*/
renderIntent: "select",
/**
* Property: handler
* {<OpenLayers.Handler.Feature>}
*/
handler: null,
/**
* Constructor: <OpenLayers.Control.SelectFeature>
*
* Parameters:
* layer - {<OpenLayers.Layer.Vector>}
* options - {Object}
*/
initialize: function(layer, options) {
OpenLayers.Control.prototype.initialize.apply(this, [options]);
this.layer = layer;
this.callbacks = OpenLayers.Util.extend({
click: this.clickFeature,
clickout: this.clickoutFeature,
over: this.overFeature,
out: this.outFeature
}, this.callbacks);
var handlerOptions = { geometryTypes: this.geometryTypes};
this.handler = new OpenLayers.Handler.Feature(this, layer,
this.callbacks,
handlerOptions);
},
/**
* Method: unselectAll
* Unselect all selected features.  To unselect all except for a single
*     feature, set the options.except property to the feature.
*
* Parameters:
* options - {Object} Optional configuration object.
*/
unselectAll: function(options) {
// we'll want an option to supress notification here
var feature;
for(var i=this.layer.selectedFeatures.length-1; i>=0; --i) {
feature = this.layer.selectedFeatures[i];
if(!options || options.except != feature) {
this.unselect(feature);
}
}
},
/**
* Method: clickFeature
* Called on click in a feature
* Only responds if this.hover is false.
*
* Parameters:
* feature - {<OpenLayers.Feature.Vector>}
*/
clickFeature: function(feature) {
if(!this.hover) {
var selected = (OpenLayers.Util.indexOf(this.layer.selectedFeatures,
feature) > -1);
if(selected) {
if(this.toggleSelect()) {
this.unselect(feature);
} else if(!this.multipleSelect()) {
this.unselectAll({except: feature});
}
} else {
if(!this.multipleSelect()) {
this.unselectAll({except: feature});
}
this.select(feature);
}
}
},
/**
* Method: multipleSelect
* Allow for multiple selected features based on <multiple> property and
*     <multipleKey> event modifier.
*
* Returns:
* {Boolean} Allow for multiple selected features.
*/
multipleSelect: function() {
return this.multiple || this.handler.evt[this.multipleKey];
},
/**
* Method: toggleSelect
* Event should toggle the selected state of a feature based on <toggle>
*     property and <toggleKey> event modifier.
*
* Returns:
* {Boolean} Toggle the selected state of a feature.
*/
toggleSelect: function() {
return this.toggle || this.handler.evt[this.toggleKey];
},
/**
* Method: clickoutFeature
* Called on click outside a previously clicked (selected) feature.
* Only responds if this.hover is false.
*
* Parameters:
* feature - {<OpenLayers.Vector.Feature>}
*/
clickoutFeature: function(feature) {
if(!this.hover && this.clickout) {
this.unselectAll();
}
},
/**
* Method: overFeature
* Called on over a feature.
* Only responds if this.hover is true.
*
* Parameters:
* feature - {<OpenLayers.Feature.Vector>}
*/
overFeature: function(feature) {
if(this.hover &&
(OpenLayers.Util.indexOf(this.layer.selectedFeatures, feature) == -1)) {
this.select(feature);
}
},
/**
* Method: outFeature
* Called on out of a selected feature.
* Only responds if this.hover is true.
*
* Parameters:
* feature - {<OpenLayers.Feature.Vector>}
*/
outFeature: function(feature) {
if(this.hover) {
this.unselect(feature);
}
},
/**
* Method: select
* Add feature to the layer's selectedFeature array, render the feature as
* selected, and call the onSelect function.
*
* Parameters:
* feature - {<OpenLayers.Feature.Vector>}
*/
select: function(feature) {
this.layer.selectedFeatures.push(feature);
var selectStyle = this.selectStyle || this.renderIntent;
this.layer.drawFeature(feature, selectStyle);
this.layer.events.triggerEvent("featureselected", {feature: feature});
this.onSelect(feature);
},
/**
* Method: unselect
* Remove feature from the layer's selectedFeature array, render the feature as
* normal, and call the onUnselect function.
*
* Parameters:
* feature - {<OpenLayers.Feature.Vector>}
*/
unselect: function(feature) {
// Store feature style for restoration later
this.layer.drawFeature(feature, "default");
OpenLayers.Util.removeItem(this.layer.selectedFeatures, feature);
this.layer.events.triggerEvent("featureunselected", {feature: feature});
this.onUnselect(feature);
},
/**
* Method: setMap
* Set the map property for the control.
*
* Parameters:
* map - {<OpenLayers.Map>}
*/
setMap: function(map) {
this.handler.setMap(map);
OpenLayers.Control.prototype.setMap.apply(this, arguments);
},
CLASS_NAME: "OpenLayers.Control.SelectFeature"
});