diff --git a/build/build.bat b/build/build.bat index 55c6a25e..15c70e3f 100644 --- a/build/build.bat +++ b/build/build.bat @@ -37,6 +37,7 @@ java -jar ../lib/closure-compiler/compiler.jar ^ --js ../src/handler/ScrollWheelZoom.js ^ --js ../src/handler/DoubleClickZoom.js ^ --js ../src/handler/ShiftDragZoom.js ^ +--js ../src/handler/MarkerDrag.js ^ --js ../src/control/Control.js ^ --js ../src/control/Control.Zoom.js ^ --js ../src/map/Map.js ^ diff --git a/build/deps.js b/build/deps.js index 0fd6496e..9a36a775 100644 --- a/build/deps.js +++ b/build/deps.js @@ -75,7 +75,7 @@ var deps = { 'dom/Draggable.js', 'handler/Handler.js', 'handler/MapDrag.js'], - desc: 'Makes the map draggable (on both desktop and mobile webkit browsers).', + desc: 'Makes the map draggable (by mouse or touch).', heading: 'Interaction' }, @@ -100,6 +100,12 @@ var deps = { desc: 'Enables zooming to bounding box by shift-dragging the map.' }, + MarkerDrag: { + src: ['handler/MarkerDrag.js'], + desc: 'Makes markers draggable (by mouse or touch).' + }, + + ControlZoom: { src: ['control/Control.js', 'map/ext/Map.Control.js', diff --git a/debug/include.js b/debug/include.js index c8d23faa..f9f729b3 100644 --- a/debug/include.js +++ b/debug/include.js @@ -47,6 +47,7 @@ 'handler/DoubleClickZoom.js', 'handler/ScrollWheelZoom.js', 'handler/ShiftDragZoom.js', + 'handler/MarkerDrag.js', 'control/Control.js', 'control/Control.Zoom.js', diff --git a/src/core/Class.js b/src/core/Class.js index 5ae58a3a..09a9e539 100644 --- a/src/core/Class.js +++ b/src/core/Class.js @@ -24,6 +24,9 @@ L.Class.extend = function(/*Object*/ props) /*-> Class*/ { // add superclass access proto.superclass = this.prototype; + // add class name + //proto.className = props; + // mix static properties into the class if (props.statics) { L.Util.extend(NewClass, props.statics); diff --git a/src/dom/DomEvent.js b/src/dom/DomEvent.js index d259a694..08d7fa93 100644 --- a/src/dom/DomEvent.js +++ b/src/dom/DomEvent.js @@ -84,8 +84,8 @@ L.DomEvent = { getWheelDelta: function(e) { var delta = 0; if (e.wheelDelta) { delta = e.wheelDelta/120; } - if (e.detail) { delta = -e.detail/3; } - return delta; + if (e.detail) { delta = -e.detail/3; } + return delta; } }; diff --git a/src/handler/Handler.js b/src/handler/Handler.js index 195986b8..c38a6b6a 100644 --- a/src/handler/Handler.js +++ b/src/handler/Handler.js @@ -1,5 +1,5 @@ /* - * L.Handler classes are used internally to inject interaction features to the Map class. + * L.Handler classes are used internally to inject interaction features to classes like Map and Marker. */ L.Handler = L.Class.extend({ diff --git a/src/handler/MapDrag.js b/src/handler/MapDrag.js index 997a66ad..49c47af6 100644 --- a/src/handler/MapDrag.js +++ b/src/handler/MapDrag.js @@ -3,6 +3,7 @@ */ L.Handler.MapDrag = L.Handler.extend({ + enable: function() { if (this._enabled) { return; } if (!this._draggable) { diff --git a/src/handler/MarkerDrag.js b/src/handler/MarkerDrag.js new file mode 100644 index 00000000..a19922b5 --- /dev/null +++ b/src/handler/MarkerDrag.js @@ -0,0 +1,54 @@ +/* + * L.Handler.MarkerDrag is used internally by L.Marker to make the markers draggable. + */ + +L.Handler.MarkerDrag = L.Handler.extend({ + initialize: function(marker) { + this._marker = marker; + }, + + enable: function() { + if (this._enabled) { return; } + if (!this._draggable) { + this._draggable = new L.Draggable(this._marker._icon, this._marker._icon); + this._draggable.on('dragstart', this._onDragStart, this); + this._draggable.on('drag', this._onDrag, this); + this._draggable.on('dragend', this._onDragEnd, this); + } + this._draggable.enable(); + this._enabled = true; + }, + + disable: function() { + if (!this._enabled) { return; } + this._draggable.disable(); + this._enabled = false; + }, + + moved: function() { + return this._draggable._moved; + }, + + _onDragStart: function(e) { + this._marker.closePopup(); + + this._marker.fire('movestart'); + this._marker.fire('dragstart'); + }, + + _onDrag: function(e) { + // update shadow position + var iconPos = L.DomUtil.getPosition(this._marker._icon); + L.DomUtil.setPosition(this._marker._shadow, iconPos); + + this._marker._latlng = this._marker._map.layerPointToLatLng(iconPos); + + this._marker.fire('move'); + this._marker.fire('drag'); + }, + + _onDragEnd: function() { + this._marker.fire('moveend'); + this._marker.fire('dragend'); + } +}); diff --git a/src/layer/Popup.js b/src/layer/Popup.js index 8d3a970a..bf67d611 100644 --- a/src/layer/Popup.js +++ b/src/layer/Popup.js @@ -12,10 +12,8 @@ L.Popup = L.Class.extend({ autoPanPadding: new L.Point(5, 5) }, - initialize: function(latlng, content, options) { + initialize: function(options) { L.Util.setOptions(this, options); - this._latlng = latlng; - this._content = content; }, onAdd: function(map) { @@ -33,6 +31,8 @@ L.Popup = L.Class.extend({ this._update(); this._container.style.opacity = '1'; //TODO fix ugly opacity hack + + this._opened = true; }, onRemove: function(map) { @@ -41,10 +41,28 @@ L.Popup = L.Class.extend({ map.off('click', this._close, this); this._container.style.opacity = '0'; + + this._opened = false; + }, + + setLatLng: function(latlng) { + this._latlng = latlng; + if (this._opened) { + this._update(); + } + }, + + setContent: function(content) { + this._content = content; + if (this._opened) { + this._update(); + } }, _close: function() { - this._map.removeLayer(this); + if (this._opened) { + this._map.removeLayer(this); + } }, _initLayout: function() { diff --git a/src/layer/marker/Marker.Popup.js b/src/layer/marker/Marker.Popup.js index b63542ac..4c5cad04 100644 --- a/src/layer/marker/Marker.Popup.js +++ b/src/layer/marker/Marker.Popup.js @@ -4,17 +4,23 @@ L.Marker.include({ openPopup: function() { - this._map.closePopup(); - if (this._popup) { - this._map.openPopup(this._popup); - } + this._popup.setLatLng(this._latlng); + this._map.openPopup(this._popup); + return this; }, + closePopup: function() { + if (this._popup) { + this._popup._close(); + } + }, + bindPopup: function(content, options) { options = L.Util.extend({offset: this.options.icon.popupAnchor}, options); - this._popup = new L.Popup(this._latlng, content, options); + this._popup = new L.Popup(options); + this._popup.setContent(content); this.on('click', this.openPopup, this); return this; diff --git a/src/layer/marker/Marker.js b/src/layer/marker/Marker.js index 074a8392..9367ce00 100644 --- a/src/layer/marker/Marker.js +++ b/src/layer/marker/Marker.js @@ -2,18 +2,19 @@ * L.Marker is used to display clickable/draggable icons on the map. */ - L.Marker = L.Class.extend({ + includes: L.Mixin.Events, options: { icon: new L.Icon(), - clickable: true + clickable: true, + draggable: false }, initialize: function(latlng, options) { L.Util.setOptions(this, options); - this._latlng = latlng; + this._latlng = latlng; }, onAdd: function(map) { @@ -60,9 +61,20 @@ L.Marker = L.Class.extend({ if (this.options.clickable) { this._icon.className += ' leaflet-clickable'; L.DomEvent.addListener(this._icon, 'mousedown', this._fireMouseEvent, this); - L.DomEvent.addListener(this._icon, 'click', this._fireMouseEvent, this); + L.DomEvent.addListener(this._icon, 'click', this._onMouseClick, this); L.DomEvent.addListener(this._icon, 'dblclick', this._fireMouseEvent, this); } + + if (this.options.draggable) { + this.dragging = new L.Handler.MarkerDrag(this); + this.dragging.enable(); + } + }, + + _onMouseClick: function(e) { + L.DomEvent.stopPropagation(e); + if (this.dragging && this.dragging.moved()) { return; } + this.fire(e.type); }, _fireMouseEvent: function(e) { diff --git a/src/layer/vector/Path.Popup.js b/src/layer/vector/Path.Popup.js index b1f1eeb1..1934fc32 100644 --- a/src/layer/vector/Path.Popup.js +++ b/src/layer/vector/Path.Popup.js @@ -4,18 +4,14 @@ L.Path.include({ bindPopup: function(content, options) { - this._popup = new L.Popup(null, content, options); + this._popup = new L.Popup(options); + this._popup.setContent(content); this.on('click', this._openPopup, this); return this; }, _openPopup: function(e) { - this._popup._latlng = e.position; - if (this._popup._map) { - this._popup._updatePosition(); - } - - this._map.closePopup(); + this._popup.setLatLng(e.position); this._map.openPopup(this._popup); } }); \ No newline at end of file diff --git a/src/map/Map.js b/src/map/Map.js index abeb8287..286ec560 100644 --- a/src/map/Map.js +++ b/src/map/Map.js @@ -129,6 +129,7 @@ L.Map = L.Class.extend({ this.on('load', onMapLoad, this); } } + return this; },