diff --git a/Gruntfile.js b/Gruntfile.js index b34ad8f..8b0610e 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -151,7 +151,7 @@ module.exports = function(grunt) { }); /* Run tests once. */ - grunt.registerTask('test', [ 'jshint', 'karma:test', 'coverage' ]); + grunt.registerTask('test', [ 'jshint', 'karma:unit', 'coverage' ]); /* Default (development): Watch files and lint, test, and build on change. */ grunt.registerTask('default', ['karma:development:start', 'watch']); diff --git a/dist/leaflet.toolbar-src.js b/dist/leaflet.toolbar-src.js index 39f56cf..a40b4b4 100644 --- a/dist/leaflet.toolbar-src.js +++ b/dist/leaflet.toolbar-src.js @@ -17,6 +17,7 @@ L.Toolbar = L.Class.extend({ initialize: function(options) { L.setOptions(this, options); + this._toolbar_type = this.constructor._toolbar_class_id; }, addTo: function(map) { @@ -27,9 +28,20 @@ L.Toolbar = L.Class.extend({ return this; }, - onAdd: function() {}, + onAdd: function(map) { + var currentToolbar = map._toolbars[this._toolbar_type]; + + if (this._calculateDepth() === 0) { + if (currentToolbar) { map.removeLayer(currentToolbar); } + map._toolbars[this._toolbar_type] = this; + } + }, + + onRemove: function(map) { + if (this._calculateDepth() === 0) { + delete map._toolbars[this._toolbar_type]; + } - onRemove: function() { /* Cleanup event listeners. */ for (var i = 0, l = this._disabledEvents.length; i < l; i++) { L.DomEvent.off(this._ul, this._disabledEvents[i], L.DomEvent.stopPropagation); @@ -104,6 +116,23 @@ L.Toolbar = L.Class.extend({ L.toolbar = {}; +var toolbar_class_id = 0; + +L.Toolbar.extend = function extend(props) { + var statics = L.extend({}, props.statics, { + "_toolbar_class_id": toolbar_class_id + }); + + toolbar_class_id += 1; + L.extend(props, { statics: statics }); + + return L.Class.extend.call(this, props); +}; + +L.Map.addInitHook(function() { + this._toolbars = {}; +}); + L.ToolbarAction = L.Handler.extend({ statics: { baseClass: 'leaflet-toolbar-icon' @@ -212,10 +241,13 @@ L.Toolbar.Control = L.Toolbar.extend({ onAdd: function(map) { this._control.addTo(map); + L.Toolbar.prototype.onAdd.call(this, map); + this.appendToContainer(this._control.getContainer()); }, onRemove: function(map) { + L.Toolbar.prototype.onRemove.call(this, map); this._control.removeFrom(map); } }); @@ -260,6 +292,8 @@ L.Toolbar.Popup = L.Toolbar.extend({ this._map = map; this._marker.addTo(map); + L.Toolbar.prototype.onAdd.call(this, map); + this.appendToContainer(this._marker._icon); this._setStyles(); @@ -268,6 +302,8 @@ L.Toolbar.Popup = L.Toolbar.extend({ onRemove: function(map) { map.removeLayer(this._marker); + L.Toolbar.prototype.onRemove.call(this, map); + delete this._map; }, diff --git a/dist/leaflet.toolbar.js b/dist/leaflet.toolbar.js index 6d3ba65..ff8f281 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},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 +!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),this._toolbar_type=this.constructor._toolbar_class_id},addTo:function(a){return this._arguments=[].slice.call(arguments),a.addLayer(this),this},onAdd:function(a){var b=a._toolbars[this._toolbar_type];0===this._calculateDepth()&&(b&&a.removeLayer(b),a._toolbars[this._toolbar_type]=this)},onRemove:function(a){0===this._calculateDepth()&&delete a._toolbars[this._toolbar_type];for(var b=0,c=this._disabledEvents.length;c>b;b++)L.DomEvent.off(this._ul,this._disabledEvents[b],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={};var d=0;L.Toolbar.extend=function(a){var b=L.extend({},a.statics,{_toolbar_class_id:d});return d+=1,L.extend(a,{statics:b}),L.Class.extend.call(this,a)},L.Map.addInitHook(function(){this._toolbars={}}),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),L.Toolbar.prototype.onAdd.call(this,a),this.appendToContainer(this._control.getContainer())},onRemove:function(a){L.Toolbar.prototype.onRemove.call(this,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),L.Toolbar.prototype.onAdd.call(this,a),this.appendToContainer(this._marker._icon),this._setStyles()},onRemove:function(a){a.removeLayer(this._marker),L.Toolbar.prototype.onRemove.call(this,a),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/src/Toolbar.js b/src/Toolbar.js index e1b52c8..3185d3e 100644 --- a/src/Toolbar.js +++ b/src/Toolbar.js @@ -37,9 +37,7 @@ L.Toolbar = L.Class.extend({ if (this._calculateDepth() === 0) { delete map._toolbars[this._toolbar_type]; } - }, - onRemove: function() { /* Cleanup event listeners. */ for (var i = 0, l = this._disabledEvents.length; i < l; i++) { L.DomEvent.off(this._ul, this._disabledEvents[i], L.DomEvent.stopPropagation); @@ -112,6 +110,8 @@ L.Toolbar = L.Class.extend({ } }); +L.toolbar = {}; + var toolbar_class_id = 0; L.Toolbar.extend = function extend(props) { diff --git a/test/src/ToolbarSpec.js b/test/src/ToolbarSpec.js index 94149b9..6120e4e 100644 --- a/test/src/ToolbarSpec.js +++ b/test/src/ToolbarSpec.js @@ -10,8 +10,6 @@ describe("L.Toolbar", function() { toolbarTemplate = [L.ToolbarAction]; toolbar = new L.Toolbar({ actions: toolbarTemplate }); - - toolbar.addTo(map); }); describe("#onAdd", function() { @@ -35,20 +33,22 @@ describe("L.Toolbar", function() { describe("#addTo", function() { it("Should add a toolbar to the map.", function() { + toolbar.addTo(map); expect(map.hasLayer(toolbar)).to.equal(true); }); it("Should pass along its arguments to each toolbar action factory.", function(done) { var TestHandler = L.ToolbarAction.extend({ - initialize: function(arg1) { + initialize: function(arg1, arg2) { expect(arg1).to.equal(map); + expect(arg2).to.equal(2); done(); } }); toolbar = new L.Toolbar({ actions: [TestHandler] }); - toolbar.addTo(map); + toolbar.addTo(map, 2); toolbar.appendToContainer(container); }); }); @@ -67,6 +67,7 @@ describe("L.Toolbar", function() { describe("#_show", function() { it("Should set the display of the toolbar container to 'block'", function() { + toolbar.addTo(map); toolbar.appendToContainer(container); toolbar._show(); @@ -76,6 +77,7 @@ describe("L.Toolbar", function() { describe("#_hide", function() { it("Should set the display of the toolbar container to 'block'", function() { + toolbar.addTo(map); toolbar.appendToContainer(container); toolbar._hide(); @@ -85,6 +87,7 @@ describe("L.Toolbar", function() { describe("#_calculateToolbarDepth", function() { it("Should return 0 for a single toolbar", function() { + toolbar.addTo(map); expect(toolbar._calculateDepth()).to.equal(0); });