/** * @class L.Draw.Toolbar * @aka Toolbar * * The toolbar class of the API — it is used to create the ui * This will be depreciated * * @example * * ```js * var toolbar = L.Toolbar(); * toolbar.addToolbar(map); * ``` * * ### Disabling a toolbar * * If you do not want a particular toolbar in your app you can turn it off by setting the toolbar to false. * * ```js * var drawControl = new L.Control.Draw({ * draw: false, * edit: { * featureGroup: editableLayers * } * }); * ``` * * ### Disabling a toolbar item * * If you want to turn off a particular toolbar item, set it to false. The following disables drawing polygons and * markers. It also turns off the ability to edit layers. * * ```js * var drawControl = new L.Control.Draw({ * draw: { * polygon: false, * marker: false * }, * edit: { * featureGroup: editableLayers, * edit: false * } * }); * ``` */ L.Toolbar = L.Class.extend({ // @section Methods for modifying the toolbar // @method initialize(options): void // Toolbar constructor initialize: function (options) { L.setOptions(this, options); this._modes = {}; this._actionButtons = []; this._activeMode = null; var version = L.version.split('.'); //If Version is >= 1.2.0 if (parseInt(version[0], 10) === 1 && parseInt(version[1], 10) >= 2) { L.Toolbar.include(L.Evented.prototype); } else { L.Toolbar.include(L.Mixin.Events); } }, // @method enabled(): boolean // Gets a true/false of whether the toolbar is enabled enabled: function () { return this._activeMode !== null; }, // @method disable(): void // Disables the toolbar disable: function () { if (!this.enabled()) { return; } this._activeMode.handler.disable(); }, // @method addToolbar(map): L.DomUtil // Adds the toolbar to the map and returns the toolbar dom element addToolbar: function (map) { var container = L.DomUtil.create('div', 'leaflet-draw-section'), buttonIndex = 0, buttonClassPrefix = this._toolbarClass || '', modeHandlers = this.getModeHandlers(map), i; this._toolbarContainer = L.DomUtil.create('div', 'leaflet-draw-toolbar leaflet-bar'); this._map = map; for (i = 0; i < modeHandlers.length; i++) { if (modeHandlers[i].enabled) { this._initModeHandler( modeHandlers[i].handler, this._toolbarContainer, buttonIndex++, buttonClassPrefix, modeHandlers[i].title ); } } // if no buttons were added, do not add the toolbar if (!buttonIndex) { return; } // Save button index of the last button, -1 as we would have ++ after the last button this._lastButtonIndex = --buttonIndex; // Create empty actions part of the toolbar this._actionsContainer = L.DomUtil.create('ul', 'leaflet-draw-actions'); // Add draw and cancel containers to the control container container.appendChild(this._toolbarContainer); container.appendChild(this._actionsContainer); return container; }, // @method removeToolbar(): void // Removes the toolbar and drops the handler event listeners removeToolbar: function () { // Dispose each handler for (var handlerId in this._modes) { if (this._modes.hasOwnProperty(handlerId)) { // Unbind handler button this._disposeButton( this._modes[handlerId].button, this._modes[handlerId].handler.enable, this._modes[handlerId].handler ); // Make sure is disabled this._modes[handlerId].handler.disable(); // Unbind handler this._modes[handlerId].handler .off('enabled', this._handlerActivated, this) .off('disabled', this._handlerDeactivated, this); } } this._modes = {}; // Dispose the actions toolbar for (var i = 0, l = this._actionButtons.length; i < l; i++) { this._disposeButton( this._actionButtons[i].button, this._actionButtons[i].callback, this ); } this._actionButtons = []; this._actionsContainer = null; }, _initModeHandler: function (handler, container, buttonIndex, classNamePredix, buttonTitle) { var type = handler.type; this._modes[type] = {}; this._modes[type].handler = handler; this._modes[type].button = this._createButton({ type: type, title: buttonTitle, className: classNamePredix + '-' + type, container: container, callback: this._modes[type].handler.enable, context: this._modes[type].handler }); this._modes[type].buttonIndex = buttonIndex; this._modes[type].handler .on('enabled', this._handlerActivated, this) .on('disabled', this._handlerDeactivated, this); }, /* Detect iOS based on browser User Agent, based on: * http://stackoverflow.com/a/9039885 */ _detectIOS: function () { var iOS = (/iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream); return iOS; }, _createButton: function (options) { var link = L.DomUtil.create('a', options.className || '', options.container); // Screen reader tag var sr = L.DomUtil.create('span', 'sr-only', options.container); link.href = '#'; link.appendChild(sr); if (options.title) { link.title = options.title; sr.innerHTML = options.title; } if (options.text) { link.innerHTML = options.text; sr.innerHTML = options.text; } /* iOS does not use click events */ var buttonEvent = this._detectIOS() ? 'touchstart' : 'click'; L.DomEvent .on(link, 'click', L.DomEvent.stopPropagation) .on(link, 'mousedown', L.DomEvent.stopPropagation) .on(link, 'dblclick', L.DomEvent.stopPropagation) .on(link, 'touchstart', L.DomEvent.stopPropagation) .on(link, 'click', L.DomEvent.preventDefault) .on(link, buttonEvent, options.callback, options.context); return link; }, _disposeButton: function (button, callback) { /* iOS does not use click events */ var buttonEvent = this._detectIOS() ? 'touchstart' : 'click'; L.DomEvent .off(button, 'click', L.DomEvent.stopPropagation) .off(button, 'mousedown', L.DomEvent.stopPropagation) .off(button, 'dblclick', L.DomEvent.stopPropagation) .off(button, 'touchstart', L.DomEvent.stopPropagation) .off(button, 'click', L.DomEvent.preventDefault) .off(button, buttonEvent, callback); }, _handlerActivated: function (e) { // Disable active mode (if present) this.disable(); // Cache new active feature this._activeMode = this._modes[e.handler]; L.DomUtil.addClass(this._activeMode.button, 'leaflet-draw-toolbar-button-enabled'); this._showActionsToolbar(); this.fire('enable'); }, _handlerDeactivated: function () { this._hideActionsToolbar(); L.DomUtil.removeClass(this._activeMode.button, 'leaflet-draw-toolbar-button-enabled'); this._activeMode = null; this.fire('disable'); }, _createActions: function (handler) { var container = this._actionsContainer, buttons = this.getActions(handler), l = buttons.length, li, di, dl, button; // Dispose the actions toolbar (todo: dispose only not used buttons) for (di = 0, dl = this._actionButtons.length; di < dl; di++) { this._disposeButton(this._actionButtons[di].button, this._actionButtons[di].callback); } this._actionButtons = []; // Remove all old buttons while (container.firstChild) { container.removeChild(container.firstChild); } for (var i = 0; i < l; i++) { if ('enabled' in buttons[i] && !buttons[i].enabled) { continue; } li = L.DomUtil.create('li', '', container); button = this._createButton({ title: buttons[i].title, text: buttons[i].text, container: li, callback: buttons[i].callback, context: buttons[i].context }); this._actionButtons.push({ button: button, callback: buttons[i].callback }); } }, _showActionsToolbar: function () { var buttonIndex = this._activeMode.buttonIndex, lastButtonIndex = this._lastButtonIndex, toolbarPosition = this._activeMode.button.offsetTop - 1; // Recreate action buttons on every click this._createActions(this._activeMode.handler); // Correctly position the cancel button this._actionsContainer.style.top = toolbarPosition + 'px'; if (buttonIndex === 0) { L.DomUtil.addClass(this._toolbarContainer, 'leaflet-draw-toolbar-notop'); L.DomUtil.addClass(this._actionsContainer, 'leaflet-draw-actions-top'); } if (buttonIndex === lastButtonIndex) { L.DomUtil.addClass(this._toolbarContainer, 'leaflet-draw-toolbar-nobottom'); L.DomUtil.addClass(this._actionsContainer, 'leaflet-draw-actions-bottom'); } this._actionsContainer.style.display = 'block'; this._map.fire(L.Draw.Event.TOOLBAROPENED); }, _hideActionsToolbar: function () { this._actionsContainer.style.display = 'none'; L.DomUtil.removeClass(this._toolbarContainer, 'leaflet-draw-toolbar-notop'); L.DomUtil.removeClass(this._toolbarContainer, 'leaflet-draw-toolbar-nobottom'); L.DomUtil.removeClass(this._actionsContainer, 'leaflet-draw-actions-top'); L.DomUtil.removeClass(this._actionsContainer, 'leaflet-draw-actions-bottom'); this._map.fire(L.Draw.Event.TOOLBARCLOSED); } });