From 85c6f6218bf81f741b3de73a92d2e3e74fc42fa3 Mon Sep 17 00:00:00 2001 From: Justin Manley Date: Sun, 8 Feb 2015 13:57:07 -0600 Subject: [PATCH] Add anchor option to L.Toolbar.Popup (modifies the way that the popup toolbar is positioned w/ negative margins in L.Toolbar.Popup#_setStyles. Fixes #18. --- dist/leaflet.toolbar-src.js | 35 +++++++++++++++++++++-------------- dist/leaflet.toolbar.js | 2 +- examples/popup.html | 13 +------------ src/Toolbar.Popup.js | 35 +++++++++++++++++++++-------------- 4 files changed, 44 insertions(+), 41 deletions(-) diff --git a/dist/leaflet.toolbar-src.js b/dist/leaflet.toolbar-src.js index fb4d2c9..39f56cf 100644 --- a/dist/leaflet.toolbar-src.js +++ b/dist/leaflet.toolbar-src.js @@ -237,17 +237,23 @@ L.Toolbar.Popup = L.Toolbar.extend({ baseClass: 'leaflet-popup-toolbar ' + L.Toolbar.baseClass }, + options: { + anchor: [0, 0] + }, + initialize: function(latlng, options) { L.Toolbar.prototype.initialize.call(this, options); - var toolbarOptions = L.extend(this.options, { - icon: new L.DivIcon({ - html: '', - className: this.options.className - }) - }); - - this._marker = new L.Marker(latlng, toolbarOptions); + /* + * Developers can't pass a DivIcon in the options for L.Toolbar.Popup + * (the use of DivIcons is an implementation detail which may change). + */ + this._marker = new L.Marker(latlng, { + icon : new L.DivIcon({ + className: this.options.className, + iconAnchor: [0, 0] + }) + }); }, onAdd: function(map) { @@ -274,12 +280,13 @@ L.Toolbar.Popup = L.Toolbar.extend({ _setStyles: function() { var container = this._container, toolbar = this._ul, + anchor = L.point(this.options.anchor), icons = toolbar.querySelectorAll('.leaflet-toolbar-icon'), buttonHeights = [], toolbarWidth = 0, toolbarHeight, tipSize, - anchor; + tipAnchor; /* Calculate the dimensions of the toolbar. */ for (var i = 0, l = icons.length; i < l; i++) { @@ -296,14 +303,14 @@ L.Toolbar.Popup = L.Toolbar.extend({ this._tip = L.DomUtil.create('div', 'leaflet-toolbar-tip', this._tipContainer); - /* Set the anchor point. */ + /* Set the tipAnchor point. */ toolbarHeight = Math.max.apply(undefined, buttonHeights); tipSize = parseInt(L.DomUtil.getStyle(this._tip, 'width'), 10); + tipAnchor = new L.Point(toolbarWidth/2, toolbarHeight + 0.7071*tipSize); - anchor = new L.Point(toolbarWidth/2, toolbarHeight + 0.7071*tipSize); - - container.style.marginLeft = (-anchor.x) + 'px'; - container.style.marginTop = (-anchor.y) + 'px'; + /* The anchor option allows app developers to adjust the toolbar's position. */ + container.style.marginLeft = (anchor.x - tipAnchor.x) + 'px'; + container.style.marginTop = (anchor.y - tipAnchor.y) + 'px'; } }); diff --git a/dist/leaflet.toolbar.js b/dist/leaflet.toolbar.js index 29acc97..6d3ba65 100644 --- a/dist/leaflet.toolbar.js +++ b/dist/leaflet.toolbar.js @@ -1 +1 @@ -!function(a,b,c){"use strict";L.Toolbar=L.Class.extend({statics:{baseClass:"leaflet-toolbar"},includes:L.Mixin.Events,options:{className:"",filter:function(){return!0},actions:[]},initialize:function(a){L.setOptions(this,a)},addTo:function(a){return this._arguments=[].slice.call(arguments),a.addLayer(this),this},onAdd:function(){},onRemove:function(){for(var a=0,b=this._disabledEvents.length;b>a;a++)L.DomEvent.off(this._ul,this._disabledEvents[a],L.DomEvent.stopPropagation)},appendToContainer:function(a){var b,c,d,e,f,g,h=this.constructor.baseClass+"-"+this._calculateDepth(),i=h+" "+this.options.className;for(this._container=a,this._ul=L.DomUtil.create("ul",i,a),this._disabledEvents=["click","mousemove","dblclick"],e=0,g=this._disabledEvents.length;g>e;e++)L.DomEvent.on(this._ul,this._disabledEvents[e],L.DomEvent.stopPropagation);for(d=0,f=this.options.actions.length;f>d;d++)b=this._getActionConstructor(this.options.actions[d]),c=new b,c._createIcon(this,this._ul,this._arguments)},_getActionConstructor:function(a){var b=this._arguments,c=this;return a.extend({initialize:function(){a.prototype.initialize.apply(this,b)},enable:function(){c._active&&c._active.disable(),c._active=this,a.prototype.enable.call(this)}})},_hide:function(){this._ul.style.display="none"},_show:function(){this._ul.style.display="block"},_calculateDepth:function(){for(var a=0,b=this.parentToolbar;b;)a+=1,b=b.parentToolbar;return a}}),L.toolbar={},L.ToolbarAction=L.Handler.extend({statics:{baseClass:"leaflet-toolbar-icon"},options:{toolbarIcon:{html:"",className:"",tooltip:""},subToolbar:new L.Toolbar},initialize:function(a){var b=L.ToolbarAction.prototype.options.toolbarIcon;L.setOptions(this,a),this.options.toolbarIcon=L.extend({},b,this.options.toolbarIcon)},enable:function(){this._enabled||(this._enabled=!0,this.addHooks&&this.addHooks())},disable:function(){this._enabled&&(this._enabled=!1,this.removeHooks&&this.removeHooks())},_createIcon:function(a,b,c){var d=this.options.toolbarIcon;this.toolbar=a,this._icon=L.DomUtil.create("li","",b),this._link=L.DomUtil.create("a","",this._icon),this._link.innerHTML=d.html,this._link.setAttribute("href","#"),this._link.setAttribute("title",d.tooltip),L.DomUtil.addClass(this._link,this.constructor.baseClass),d.className&&L.DomUtil.addClass(this._link,d.className),L.DomEvent.on(this._link,"click",this.enable,this),this._addSubToolbar(a,this._icon,c)},_addSubToolbar:function(a,b,c){var d=this.options.subToolbar,e=this.addHooks,f=this.removeHooks;d.parentToolbar=a,d.options.actions.length>0&&(c=[].slice.call(c),c.push(this),d.addTo.apply(d,c),d.appendToContainer(b),this.addHooks=function(a){"function"==typeof e&&e.call(this,a),d._show()},this.removeHooks=function(a){"function"==typeof f&&f.call(this,a),d._hide()})}}),L.toolbarAction=function(a){return new L.ToolbarAction(a)},L.ToolbarAction.extendOptions=function(a){return this.extend({options:a})},L.Toolbar.Control=L.Toolbar.extend({statics:{baseClass:"leaflet-control-toolbar "+L.Toolbar.baseClass},initialize:function(a){L.Toolbar.prototype.initialize.call(this,a),this._control=new L.Control.Toolbar(this.options)},onAdd:function(a){this._control.addTo(a),this.appendToContainer(this._control.getContainer())},onRemove:function(a){this._control.removeFrom(a)}}),L.Control.Toolbar=L.Control.extend({onAdd:function(){return L.DomUtil.create("div","")}}),L.toolbar.control=function(a){return new L.Toolbar.Control(a)},L.Toolbar.Popup=L.Toolbar.extend({statics:{baseClass:"leaflet-popup-toolbar "+L.Toolbar.baseClass},initialize:function(a,b){L.Toolbar.prototype.initialize.call(this,b);var c=L.extend(this.options,{icon:new L.DivIcon({html:"",className:this.options.className})});this._marker=new L.Marker(a,c)},onAdd:function(a){this._map=a,this._marker.addTo(a),this.appendToContainer(this._marker._icon),this._setStyles()},onRemove:function(a){a.removeLayer(this._marker),delete this._map},setLatLng:function(a){return this._marker.setLatLng(a),this},_setStyles:function(){for(var a,b,d,e=this._container,f=this._ul,g=f.querySelectorAll(".leaflet-toolbar-icon"),h=[],i=0,j=0,k=g.length;k>j;j++)g[j].parentNode.parentNode===f&&(h.push(parseInt(L.DomUtil.getStyle(g[j],"height"),10)),i+=Math.ceil(parseFloat(L.DomUtil.getStyle(g[j],"width"))));f.style.width=i+"px",this._tipContainer=L.DomUtil.create("div","leaflet-toolbar-tip-container",e),this._tipContainer.style.width=i+"px",this._tip=L.DomUtil.create("div","leaflet-toolbar-tip",this._tipContainer),a=Math.max.apply(c,h),b=parseInt(L.DomUtil.getStyle(this._tip,"width"),10),d=new L.Point(i/2,a+.7071*b),e.style.marginLeft=-d.x+"px",e.style.marginTop=-d.y+"px"}}),L.toolbar.popup=function(a){return new L.Toolbar.Popup(a)}}(window,document); \ No newline at end of file +!function(a,b,c){"use strict";L.Toolbar=L.Class.extend({statics:{baseClass:"leaflet-toolbar"},includes:L.Mixin.Events,options:{className:"",filter:function(){return!0},actions:[]},initialize:function(a){L.setOptions(this,a)},addTo:function(a){return this._arguments=[].slice.call(arguments),a.addLayer(this),this},onAdd:function(){},onRemove:function(){for(var a=0,b=this._disabledEvents.length;b>a;a++)L.DomEvent.off(this._ul,this._disabledEvents[a],L.DomEvent.stopPropagation)},appendToContainer:function(a){var b,c,d,e,f,g,h=this.constructor.baseClass+"-"+this._calculateDepth(),i=h+" "+this.options.className;for(this._container=a,this._ul=L.DomUtil.create("ul",i,a),this._disabledEvents=["click","mousemove","dblclick"],e=0,g=this._disabledEvents.length;g>e;e++)L.DomEvent.on(this._ul,this._disabledEvents[e],L.DomEvent.stopPropagation);for(d=0,f=this.options.actions.length;f>d;d++)b=this._getActionConstructor(this.options.actions[d]),c=new b,c._createIcon(this,this._ul,this._arguments)},_getActionConstructor:function(a){var b=this._arguments,c=this;return a.extend({initialize:function(){a.prototype.initialize.apply(this,b)},enable:function(){c._active&&c._active.disable(),c._active=this,a.prototype.enable.call(this)}})},_hide:function(){this._ul.style.display="none"},_show:function(){this._ul.style.display="block"},_calculateDepth:function(){for(var a=0,b=this.parentToolbar;b;)a+=1,b=b.parentToolbar;return a}}),L.toolbar={},L.ToolbarAction=L.Handler.extend({statics:{baseClass:"leaflet-toolbar-icon"},options:{toolbarIcon:{html:"",className:"",tooltip:""},subToolbar:new L.Toolbar},initialize:function(a){var b=L.ToolbarAction.prototype.options.toolbarIcon;L.setOptions(this,a),this.options.toolbarIcon=L.extend({},b,this.options.toolbarIcon)},enable:function(){this._enabled||(this._enabled=!0,this.addHooks&&this.addHooks())},disable:function(){this._enabled&&(this._enabled=!1,this.removeHooks&&this.removeHooks())},_createIcon:function(a,b,c){var d=this.options.toolbarIcon;this.toolbar=a,this._icon=L.DomUtil.create("li","",b),this._link=L.DomUtil.create("a","",this._icon),this._link.innerHTML=d.html,this._link.setAttribute("href","#"),this._link.setAttribute("title",d.tooltip),L.DomUtil.addClass(this._link,this.constructor.baseClass),d.className&&L.DomUtil.addClass(this._link,d.className),L.DomEvent.on(this._link,"click",this.enable,this),this._addSubToolbar(a,this._icon,c)},_addSubToolbar:function(a,b,c){var d=this.options.subToolbar,e=this.addHooks,f=this.removeHooks;d.parentToolbar=a,d.options.actions.length>0&&(c=[].slice.call(c),c.push(this),d.addTo.apply(d,c),d.appendToContainer(b),this.addHooks=function(a){"function"==typeof e&&e.call(this,a),d._show()},this.removeHooks=function(a){"function"==typeof f&&f.call(this,a),d._hide()})}}),L.toolbarAction=function(a){return new L.ToolbarAction(a)},L.ToolbarAction.extendOptions=function(a){return this.extend({options:a})},L.Toolbar.Control=L.Toolbar.extend({statics:{baseClass:"leaflet-control-toolbar "+L.Toolbar.baseClass},initialize:function(a){L.Toolbar.prototype.initialize.call(this,a),this._control=new L.Control.Toolbar(this.options)},onAdd:function(a){this._control.addTo(a),this.appendToContainer(this._control.getContainer())},onRemove:function(a){this._control.removeFrom(a)}}),L.Control.Toolbar=L.Control.extend({onAdd:function(){return L.DomUtil.create("div","")}}),L.toolbar.control=function(a){return new L.Toolbar.Control(a)},L.Toolbar.Popup=L.Toolbar.extend({statics:{baseClass:"leaflet-popup-toolbar "+L.Toolbar.baseClass},options:{anchor:[0,0]},initialize:function(a,b){L.Toolbar.prototype.initialize.call(this,b),this._marker=new L.Marker(a,{icon:new L.DivIcon({className:this.options.className,iconAnchor:[0,0]})})},onAdd:function(a){this._map=a,this._marker.addTo(a),this.appendToContainer(this._marker._icon),this._setStyles()},onRemove:function(a){a.removeLayer(this._marker),delete this._map},setLatLng:function(a){return this._marker.setLatLng(a),this},_setStyles:function(){for(var a,b,d,e=this._container,f=this._ul,g=L.point(this.options.anchor),h=f.querySelectorAll(".leaflet-toolbar-icon"),i=[],j=0,k=0,l=h.length;l>k;k++)h[k].parentNode.parentNode===f&&(i.push(parseInt(L.DomUtil.getStyle(h[k],"height"),10)),j+=Math.ceil(parseFloat(L.DomUtil.getStyle(h[k],"width"))));f.style.width=j+"px",this._tipContainer=L.DomUtil.create("div","leaflet-toolbar-tip-container",e),this._tipContainer.style.width=j+"px",this._tip=L.DomUtil.create("div","leaflet-toolbar-tip",this._tipContainer),a=Math.max.apply(c,i),b=parseInt(L.DomUtil.getStyle(this._tip,"width"),10),d=new L.Point(j/2,a+.7071*b),e.style.marginLeft=g.x-d.x+"px",e.style.marginTop=g.y-d.y+"px"}}),L.toolbar.popup=function(a){return new L.Toolbar.Popup(a)}}(window,document); \ No newline at end of file diff --git a/examples/popup.html b/examples/popup.html index aa7e6c4..7bd7647 100644 --- a/examples/popup.html +++ b/examples/popup.html @@ -59,18 +59,7 @@ drawnItems.addLayer(layer); layer.on('click', function(event) { - var latlng = event.latlng; - - /* Override event.latlng to open the popup just above markers. */ - if (layer instanceof L.Marker) { - height = parseFloat(L.DomUtil.getStyle(layer._icon, 'height')); - latlng = map.layerPointToLatLng(map - .latLngToLayerPoint(latlng) - .add(L.point(0, -height)) - ); - } - - new L.EditToolbar.Popup(latlng, { + new L.EditToolbar.Popup(event.latlng, { className: 'leaflet-draw-toolbar', actions: editActions }).addTo(map, layer); diff --git a/src/Toolbar.Popup.js b/src/Toolbar.Popup.js index 272b790..c458c07 100644 --- a/src/Toolbar.Popup.js +++ b/src/Toolbar.Popup.js @@ -5,17 +5,23 @@ L.Toolbar.Popup = L.Toolbar.extend({ baseClass: 'leaflet-popup-toolbar ' + L.Toolbar.baseClass }, + options: { + anchor: [0, 0] + }, + initialize: function(latlng, options) { L.Toolbar.prototype.initialize.call(this, options); - var toolbarOptions = L.extend(this.options, { - icon: new L.DivIcon({ - html: '', - className: this.options.className - }) - }); - - this._marker = new L.Marker(latlng, toolbarOptions); + /* + * Developers can't pass a DivIcon in the options for L.Toolbar.Popup + * (the use of DivIcons is an implementation detail which may change). + */ + this._marker = new L.Marker(latlng, { + icon : new L.DivIcon({ + className: this.options.className, + iconAnchor: [0, 0] + }) + }); }, onAdd: function(map) { @@ -42,12 +48,13 @@ L.Toolbar.Popup = L.Toolbar.extend({ _setStyles: function() { var container = this._container, toolbar = this._ul, + anchor = L.point(this.options.anchor), icons = toolbar.querySelectorAll('.leaflet-toolbar-icon'), buttonHeights = [], toolbarWidth = 0, toolbarHeight, tipSize, - anchor; + tipAnchor; /* Calculate the dimensions of the toolbar. */ for (var i = 0, l = icons.length; i < l; i++) { @@ -64,14 +71,14 @@ L.Toolbar.Popup = L.Toolbar.extend({ this._tip = L.DomUtil.create('div', 'leaflet-toolbar-tip', this._tipContainer); - /* Set the anchor point. */ + /* Set the tipAnchor point. */ toolbarHeight = Math.max.apply(undefined, buttonHeights); tipSize = parseInt(L.DomUtil.getStyle(this._tip, 'width'), 10); + tipAnchor = new L.Point(toolbarWidth/2, toolbarHeight + 0.7071*tipSize); - anchor = new L.Point(toolbarWidth/2, toolbarHeight + 0.7071*tipSize); - - container.style.marginLeft = (-anchor.x) + 'px'; - container.style.marginTop = (-anchor.y) + 'px'; + /* The anchor option allows app developers to adjust the toolbar's position. */ + container.style.marginLeft = (anchor.x - tipAnchor.x) + 'px'; + container.style.marginTop = (anchor.y - tipAnchor.y) + 'px'; } });