Oct
2010
Openlayers draggable popups
Problem:
Recently I have been working on Openlayers, vector features where the user can draw different vector features on the Openlayers map and than show the results like area covered or radius of the polygon drawn.
The best way I could found was to use Openlayers Popup but in this case a ‘draggable popup‘ so that user can drag this information popup around to see the map and features around. I didn’t find any built-in property to do so, so I tried jQuery-ui draggable plugin to drag the popup. It worked fine other than, when you double click the popup and the popup will stick to your mouse pointer forever and there is no way but to refresh the page to get rid of it. Here is the code I was trying:
;(function($) {
//Create Openlayers map object
map = new OpenLayers.Map( 'map' );
//Layer object
layer = new OpenLayers.Layer.WMS(
"OpenLayers WMS",
"http://labs.metacarta.com/wms/vmap0",
{layers: 'basic'} );
//Add layer to the map
map.addLayer(layer);
//Zooms out to the maximum extent of the map
map.zoomToMaxExtent();
//Openlayers popup
popup = new OpenLayers.Popup(
"dragging-issue",
new OpenLayers.LonLat(5,40),
new OpenLayers.Size(80,60),
"Drag Me:Single click, fineDouble click : ( ", true);
//Add this popup to the map
map.addPopup(popup);
//Apply jQuery draggable to the map container of the popup
$('.olPopup').draggable();
})(jQuery);
All I can think of this problem is that there is a conflict between double click event in jQuery and Openlayers. I tried to stop propagation for double click event on popup and tried few other ways but it didn’t help.
Solution:
Thanks to Matt Walker for the perfect solution by coding an extension for Openlayers popup which enables it to be draggable.
//In the above code, we will replace $('.olPopup').draggable(); with
var dragPopup = new OpenLayers.Control.DragPopup(popup);
map.addControl(dragPopup);
Here is code which enables an Openlayers popup to be draggable:
/*
* Move a popup with a drag.
*
* @author Matt Walker
* @class
*/
OpenLayers.Control.DragPopup = OpenLayers.Class(OpenLayers.Control, {
down: false,
popPnt: null,
mapPnt: null,
popup: null,
docMouseUpProxy: null,
/**
* Constructor: OpenLayers.Control.DragPopup
* Create a new control to drag a popup.
*
* Parameters:
* @param {OpenLayers.Popup} popup
* @param {Object} options
*/
initialize: function(popup, options) {
OpenLayers.Control.prototype.initialize.apply(this, [options]);
this.popup = popup;
this.popup.events.register('mousedown', this, this.mouseDown);
this.popup.events.register('mouseup', this, this.mouseUp);
this.popup.events.register('mousemove', this, this.mouseMove);
// Define a function bound to this used to listen for
// document mouseout events
this.docMouseUpProxy = OpenLayers.Function.bind(this.mouseUp, this);
},
/**
* Method: setMap
* Set the map property for the control.
*
* Parameters:
* map - {} The controls map.
*/
setMap: function(map) {
OpenLayers.Control.prototype.setMap.apply(this, [map]);
this.map.events.register('mousemove', this, this.mouseMove);
},
mouseDown: function(evt) {
//console.log('mouseDown');
this.down = true;
this.popPnt = this.popup.events.getMousePosition(evt);
OpenLayers.Event.observe(document, 'mouseup', this.docMouseUpProxy);
OpenLayers.Event.stop(evt);
},
mouseUp: function(evt) {
//console.log('mouseUp');
this.down = false;
OpenLayers.Event.stopObserving(document, 'mouseup', this.docMouseUpProxy);
OpenLayers.Event.stop(evt);
},
mouseOut: function(evt) {
//console.log('map.mouseOut');
this.down = false;
OpenLayers.Event.stop(evt);
},
mouseMove: function(evt) {
//console.log('mouseMove');
if (this.down) {
var mapPntPx = this.map.events.getMousePosition(evt);
mapPntPx = mapPntPx.add((this.popPnt.x*-1), (this.popPnt.y*-1));
this.popup.lonlat = this.map.getLonLatFromViewPortPx(mapPntPx);
this.popup.updatePosition();
}
OpenLayers.Event.stop(evt);
},
destroy: function() {
// Remove listeners
this.popup.events.unregister('mousedown', this, this.mouseDown);
this.popup.events.unregister('mouseup', this, this.mouseUp);
this.popup.events.unregister('mousemove', this, this.mouseMove);
this.map.events.unregister('mousemove', this, this.mouseMove);
// Clear object references
this.popup = null;
this.popPnt = null;
// allow our superclass to tidy up
OpenLayers.Control.prototype.destroy.apply(this, []);
},
/** @final @type String */
CLASS_NAME: "OpenLayers.Control.DragPopup"
});
Please comment if you know a better/easy way to make Openlayers popup draggable.







Hey, I can’t view your site properly within Opera, I actually hope you look into fixing this.
Thank you for informing me. I will make sure it work on Opera too.
Works like a charm. The Anchored/Framed/
Cloud popups act weird while dragging because they’re being repositioned every time. I fixed this by using the ‘old’ moveTo method when the dragControl.down == true ;
popup.moveTo = function() {
if (dragPopup.down) {
OpenLayers.Popup.prototype.moveTo.apply(this, arguments);
} else {
OpenLayers.Popup.Anchored.prototype.moveTo.apply(this, arguments);
}
}
Another problem for me: I use input elements in my popups and events are captured. Fixed by wrapping mouseUp and mouseDown:
if ( ! $(evt.target).is(':input') ) { /* original code */}Thanks Ivor for the updates.
Can you please copy paste whole code (with your fixes) somewhere so I can update the post.
Visitor recommendations…
[...]one of our visitors recently recommended the following website[...]……