diff --git a/examples/overviewmap.html b/examples/overviewmap.html index ddab54510a..f4fd8c916d 100644 --- a/examples/overviewmap.html +++ b/examples/overviewmap.html @@ -86,7 +86,7 @@ map2.addLayers([bos]); map2.addControl(new OpenLayers.Control.LayerSwitcher()); - // create an overview map control with the default options + // create an overview map control with non-default options var controlOptions = { mapOptions: mapOptions } diff --git a/lib/OpenLayers/Control/OverviewMap.js b/lib/OpenLayers/Control/OverviewMap.js index e55bd2abc5..3a2a58dc27 100644 --- a/lib/OpenLayers/Control/OverviewMap.js +++ b/lib/OpenLayers/Control/OverviewMap.js @@ -19,12 +19,6 @@ */ OpenLayers.Control.OverviewMap = OpenLayers.Class(OpenLayers.Control, { - /** - * Property: id - * {String} For div.id - */ - id: "OverviewMap", - /** * Property: element * {DOMElement} The DOM element that contains the overview map @@ -36,7 +30,7 @@ OpenLayers.Control.OverviewMap = OpenLayers.Class(OpenLayers.Control, { * {} A reference to the overvew map itself. */ ovmap: null, - + /** * APIProperty: size * {} The overvew map size in pixels. Note that this is @@ -52,6 +46,34 @@ OpenLayers.Control.OverviewMap = OpenLayers.Class(OpenLayers.Control, { * 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 + * property. Default is 15 pixels. + */ + minRectSize: 15, + + /** + * APIProperty: minRectDisplayClass + * {String} Replacement style class name for the extent rectangle when + * 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 @@ -74,6 +96,12 @@ OpenLayers.Control.OverviewMap = OpenLayers.Class(OpenLayers.Control, { * options that the main map was constructed with. */ mapOptions: null, + + /** + * Property: dragHandler + * {} A handler for dragging the extent rectangle. + */ + dragHandler: null, /** * Constructor: OpenLayers.Control.OverviewMap @@ -97,6 +125,9 @@ OpenLayers.Control.OverviewMap = OpenLayers.Class(OpenLayers.Control, { if (!this.mapDiv) { // we've already been destroyed return; } + this.dragHandler.destroy(); + this.clickHandler.destroy(); + this.mapDiv.removeChild(this.extentRectangle); this.extentRectangle = null; this.rectEvents.destroy(); @@ -107,13 +138,9 @@ OpenLayers.Control.OverviewMap = OpenLayers.Class(OpenLayers.Control, { this.element.removeChild(this.mapDiv); this.mapDiv = null; - this.mapDivEvents.destroy(); - this.mapDivEvents = null; this.div.removeChild(this.element); this.element = null; - this.elementEvents.destroy(); - this.elementEvents = null; if (this.maximizeDiv) { OpenLayers.Event.stopObservingElement(this.maximizeDiv); @@ -165,45 +192,14 @@ OpenLayers.Control.OverviewMap = OpenLayers.Class(OpenLayers.Control, { this.extentRectangle = document.createElement('div'); this.extentRectangle.style.position = 'absolute'; this.extentRectangle.style.zIndex = 1000; //HACK - this.extentRectangle.style.overflow = 'hidden'; - this.extentRectangle.style.backgroundImage = 'url(' + - OpenLayers.Util.getImagesLocation() + - 'blank.gif)'; this.extentRectangle.className = this.displayClass+'ExtentRectangle'; this.mapDiv.appendChild(this.extentRectangle); - + this.element.appendChild(this.mapDiv); this.div.appendChild(this.element); this.map.events.register('moveend', this, this.update); - - // Set up events. The image div recenters the map on click. - // The extent rectangle can be dragged to recenter the map. - // If the mousedown happened elsewhere, then mousemove and mouseup - // should slip through. - this.elementEvents = new OpenLayers.Events(this, this.element); - this.elementEvents.register('mousedown', this, function(e) { - OpenLayers.Event.stop(e); - }); - this.elementEvents.register('click', this, function(e) { - OpenLayers.Event.stop(e); - }); - this.elementEvents.register('dblclick', this, function(e) { - OpenLayers.Event.stop(e); - }); - this.rectEvents = new OpenLayers.Events(this, this.extentRectangle, - null, true); - this.rectEvents.register('mouseout', this, this.rectMouseOut); - this.rectEvents.register('mousedown', this, this.rectMouseDown); - this.rectEvents.register('mousemove', this, this.rectMouseMove); - this.rectEvents.register('mouseup', this, this.rectMouseUp); - this.rectEvents.register('click', this, function(e) { - OpenLayers.Event.stop(e); - }); - this.rectEvents.register('dblclick', this, this.rectDblClick ); - this.mapDivEvents = new OpenLayers.Events(this, this.mapDiv); - this.mapDivEvents.register('click', this, this.mapDivClick); // Optionally add min/max buttons if the control will go in the // map viewport. @@ -276,64 +272,20 @@ OpenLayers.Control.OverviewMap = OpenLayers.Class(OpenLayers.Control, { }, /** - * Method: rectMouseOut - * Handle browser events + * Method: rectDrag + * Handle extent rectangle drag * * Parameters: - * evt - {} evt + * px - {} The pixel location of the drag. */ - rectMouseOut: function (evt) { - if(this.rectDragStart != null) { - if(this.performedRectDrag) { - this.rectMouseMove(evt); - var rectPxBounds = this.getRectPxBounds(); - // if we're off of the overview map, update the main map - // otherwise, keep moving the rect - if((rectPxBounds.top <= 0) || (rectPxBounds.left <= 0) || - (rectPxBounds.bottom >= this.size.h - this.hComp) || - (rectPxBounds.right >= this.size.w - this.wComp)) { - this.updateMapToRect(); - } else { - return; - } - } - document.onselectstart = null; - this.rectDragStart = null; - } - }, - - /** - * Method: rectMouseDown - * Handle browser events - * - * Parameters: - * evt - {} evt - */ - rectMouseDown: function (evt) { - if(!OpenLayers.Event.isLeftClick(evt)) { - return; - } - this.rectDragStart = evt.xy.clone(); - this.performedRectDrag = false; - OpenLayers.Event.stop(evt); - }, - - /** - * Method: rectMouseMove - * Handle browser events - * - * Parameters: - * evt - {} evt - */ - rectMouseMove: function(evt) { - if(this.rectDragStart != null) { - var deltaX = this.rectDragStart.x - evt.xy.x; - var deltaY = this.rectDragStart.y - evt.xy.y; - var rectPxBounds = this.getRectPxBounds(); - var rectTop = rectPxBounds.top; - var rectLeft = rectPxBounds.left; - var rectHeight = Math.abs(rectPxBounds.getHeight()); - var rectWidth = rectPxBounds.getWidth(); + rectDrag: function(px) { + var deltaX = this.dragHandler.last.x - px.x; + var deltaY = this.dragHandler.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, @@ -345,44 +297,9 @@ OpenLayers.Control.OverviewMap = OpenLayers.Class(OpenLayers.Control, { newTop + rectHeight, newLeft + rectWidth, newTop)); - this.rectDragStart = evt.xy.clone(); - this.performedRectDrag = true; - OpenLayers.Event.stop(evt); } }, - - /** - * Method: rectMouseUp - * Handle browser events - * - * Parameters: - * evt - {} evt - */ - rectMouseUp: function(evt) { - if(!OpenLayers.Event.isLeftClick(evt)) { - return; - } - if(this.performedRectDrag) { - this.updateMapToRect(); - OpenLayers.Event.stop(evt); - } - document.onselectstart = null; - this.rectDragStart = null; - }, - /** - * Method: rectDblClick - * Handle browser events - * - * Parameters: - * evt - {} evt - */ - rectDblClick: function(evt) { - this.performedRectDrag = false; - OpenLayers.Event.stop(evt); - this.updateOverview(); - }, - /** * Method: mapDivClick * Handle browser events @@ -391,14 +308,13 @@ OpenLayers.Control.OverviewMap = OpenLayers.Class(OpenLayers.Control, { * evt - {} evt */ mapDivClick: function(evt) { - var pxBounds = this.getRectPxBounds(); - var pxCenter = pxBounds.getCenterPixel(); + var pxCenter = this.rectPxBounds.getCenterPixel(); var deltaX = evt.xy.x - pxCenter.x; var deltaY = evt.xy.y - pxCenter.y; - var top = pxBounds.top; - var left = pxBounds.left; - var height = Math.abs(pxBounds.getHeight()); - var width = pxBounds.getWidth(); + 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)); @@ -532,6 +448,40 @@ OpenLayers.Control.OverviewMap = OpenLayers.Class(OpenLayers.Control, { parseInt(OpenLayers.Element.getStyle(this.extentRectangle, 'border-bottom-width')); this.hComp = (this.hComp) ? this.hComp : 2; + + this.dragHandler = new OpenLayers.Handler.Drag( + this, {move: this.rectDrag, done: this.updateMapToRect}, + {map: this.ovmap} + ); + this.clickHandler = new OpenLayers.Handler.Click( + this, { + "click": this.mapDivClick + },{ + "single": true, "double": false, + "stopSingle": true, "stopDouble": true, + "pixelTolerance": 1, + map: this.ovmap + } + ); + this.clickHandler.activate(); + + this.rectEvents = new OpenLayers.Events(this, this.extentRectangle, + null, true); + this.rectEvents.register("mouseover", this, function(e) { + if(!this.dragHandler.active && !this.map.dragging) { + // this click handler de/activation can be removed when + // ticket #1247 is addressed + this.clickHandler.deactivate(); + this.dragHandler.activate(); + this.clickHandler.activate(); + } + }); + this.rectEvents.register("mouseout", this, function(e) { + if(!this.dragHandler.dragging) { + this.dragHandler.deactivate(); + } + }); + }, /** @@ -548,7 +498,7 @@ OpenLayers.Control.OverviewMap = OpenLayers.Class(OpenLayers.Control, { } var pxBounds = this.getRectBoundsFromMapBounds(this.map.getExtent()); if (pxBounds) { - this.setRectPxBounds(pxBounds); + this.setRectPxBounds(pxBounds); } }, @@ -557,26 +507,9 @@ OpenLayers.Control.OverviewMap = OpenLayers.Class(OpenLayers.Control, { * Updates the map extent to match the extent rectangle position and size */ updateMapToRect: function() { - var pxBounds = this.getRectPxBounds(); - var lonLatBounds = this.getMapBoundsFromRectBounds(pxBounds); + var lonLatBounds = this.getMapBoundsFromRectBounds(this.rectPxBounds); this.map.setCenter(lonLatBounds.getCenterLonLat(), this.map.zoom); }, - - /** - * Method: getRectPxBounds - * Get extent rectangle pixel bounds - * - * Returns: - * {} A bounds which is the extent rectangle's pixel - * bounds (relative to the parent element) - */ - getRectPxBounds: function() { - var top = parseInt(this.extentRectangle.style.top); - var left = parseInt(this.extentRectangle.style.left); - var height = parseInt(this.extentRectangle.style.height); - var width = parseInt(this.extentRectangle.style.width); - return new OpenLayers.Bounds(left, top + height, left + width, top); - }, /** * Method: setRectPxBounds @@ -592,10 +525,29 @@ OpenLayers.Control.OverviewMap = OpenLayers.Class(OpenLayers.Control, { this.ovmap.size.h - this.hComp); var right = Math.min(pxBounds.left + pxBounds.getWidth(), this.ovmap.size.w - this.wComp); - this.extentRectangle.style.top = parseInt(top) + 'px'; - this.extentRectangle.style.left = parseInt(left) + 'px'; - this.extentRectangle.style.height = parseInt(Math.max(bottom - top, 0))+ 'px'; - this.extentRectangle.style.width = parseInt(Math.max(right - left, 0)) + 'px'; + 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) + ); }, /** diff --git a/lib/OpenLayers/Map.js b/lib/OpenLayers/Map.js index c5721b24f8..61d4bdb632 100644 --- a/lib/OpenLayers/Map.js +++ b/lib/OpenLayers/Map.js @@ -53,6 +53,12 @@ OpenLayers.Map = OpenLayers.Class({ * {DOMElement} The element that contains the map */ div: null, + + /** + * Property: dragging + * {Boolean} The map is currently being dragged. + */ + dragging: false, /** * Property: size @@ -1221,7 +1227,8 @@ OpenLayers.Map = OpenLayers.Class({ * TBD: reconsider forceZoomChange in 3.0 */ setCenter: function (lonlat, zoom, dragging, forceZoomChange) { - + this.dragging = !!dragging; + if (!this.center && !this.isValidLonLat(lonlat)) { lonlat = this.maxExtent.getCenterLonLat(); } diff --git a/tests/Control/test_OverviewMap.html b/tests/Control/test_OverviewMap.html index 92cd01bb94..920f83f8df 100644 --- a/tests/Control/test_OverviewMap.html +++ b/tests/Control/test_OverviewMap.html @@ -51,9 +51,12 @@ t.eq(cent.lon, -71.3515625, "Clicking on the Overview Map has the correct effect on map lon"); t.eq(cent.lat, 42.17578125, "Clicking on the Overview Map has the correct effect on map lat"); - control.rectMouseDown({'xy':new OpenLayers.Pixel(5,5), 'which':1}); - control.rectMouseMove({'xy':new OpenLayers.Pixel(15,15), 'which':1}); - control.rectMouseUp({'xy':new OpenLayers.Pixel(15,15), 'which':1}); + control.dragHandler = { + last: new OpenLayers.Pixel(5,5), + destroy: function() {} + }; + control.rectDrag(new OpenLayers.Pixel(15, 15)); + control.updateMapToRect(); var cent = map.getCenter(); t.eq(cent.lon, -71.2734375, "Dragging on the Overview Map has the correct effect on map lon"); diff --git a/theme/default/img/blank.gif b/theme/default/img/blank.gif new file mode 100644 index 0000000000..4bcc753a12 Binary files /dev/null and b/theme/default/img/blank.gif differ diff --git a/theme/default/img/overview_replacement.gif b/theme/default/img/overview_replacement.gif new file mode 100644 index 0000000000..a82cf5fc54 Binary files /dev/null and b/theme/default/img/overview_replacement.gif differ diff --git a/theme/default/style.css b/theme/default/style.css index 242e5d3589..77029ace5e 100644 --- a/theme/default/style.css +++ b/theme/default/style.css @@ -64,9 +64,19 @@ div.olControlMousePosition { } .olControlOverviewMapExtentRectangle { - cursor: move; + overflow: hidden; + background-image: url("img/blank.gif"); + cursor: move; border: 2px dotted red; } +.olControlOverviewMapRectReplacement { + overflow: hidden; + cursor: move; + background-image: url("img/overview_replacement.gif"); + background-repeat: no-repeat; + background-position: center; +} + .olLayerGeoRSSDescription { float:left; width:100%;