// @ts-nocheck /** * @name Sidebar * @class L.Control.Sidebar * @extends L.Control * @param {string} id - The id of the sidebar element (without the # character) * @param {Object} [options] - Optional options object * @param {string} [options.autopan=false] - whether to move the map when opening the sidebar to make maintain the visible center point * @param {string} [options.position=left] - Position of the sidebar: 'left' or 'right' * @param {string} [options.id] - ID of a predefined sidebar container that should be used * @param {boolean} [data.close=true] Whether to add a close button to the pane header * @see L.control.sidebar */ L.Control.Sidebar = L.Control.extend(/** @lends L.Control.Sidebar.prototype */ { includes: L.Evented ? L.Evented.prototype : L.Mixin.Events, options: { autopan: false, closeButton: true, container: null, position: 'left' }, /** * Create a new sidebar on this object. * * @constructor * @param {Object} [options] - Optional options object * @param {string} [options.autopan=false] - whether to move the map when opening the sidebar to make maintain the visible center point * @param {string} [options.position=left] - Position of the sidebar: 'left' or 'right' * @param {string} [options.container] - ID of a predefined sidebar container that should be used * @param {bool} [data.close=true] Whether to add a close button to the pane header */ initialize: function(options, deprecatedOptions) { if (typeof options === 'string') { console.warn('this syntax is deprecated. please use L.control.sidebar({ container }) now'); options = { container: options }; } if (typeof options === 'object' && options.id) { console.warn('this syntax is deprecated. please use L.control.sidebar({ container }) now'); options.container = options.id; } this._tabitems = []; this._panes = []; this._closeButtons = []; L.setOptions(this, Object.assign({}, options, deprecatedOptions)); return this; }, /** * Add this sidebar to the specified map. * * @param {L.Map} map * @returns {Sidebar} */ onAdd: function(map) { var i, child, tabContainers, newContainer, container; // use container from previous onAdd() container = this._container // use the container given via options. if (!container) { container = this._container || typeof this.options.container === 'string' ? L.DomUtil.get(this.options.container) : this.options.container; } // if no container was specified or not found, create it and apply an ID if (!container) { container = L.DomUtil.create('div', 'leaflet-sidebar collapsed'); if (typeof this.options.container === 'string') container.id = this.options.container; } // Find paneContainer in DOM & store reference this._paneContainer = container.querySelector('div.leaflet-sidebar-content'); // If none is found, create it if (this._paneContainer === null) this._paneContainer = L.DomUtil.create('div', 'leaflet-sidebar-content', container); // Find tabContainerTop & tabContainerBottom in DOM & store reference tabContainers = container.querySelectorAll('ul.leaflet-sidebar-tabs, div.leaflet-sidebar-tabs > ul'); this._tabContainerTop = tabContainers[0] || null; this._tabContainerBottom = tabContainers[1] || null; // If no container was found, create it if (this._tabContainerTop === null) { newContainer = L.DomUtil.create('div', 'leaflet-sidebar-tabs', container); newContainer.setAttribute('role', 'tablist'); this._tabContainerTop = L.DomUtil.create('ul', '', newContainer); } if (this._tabContainerBottom === null) { newContainer = this._tabContainerTop.parentNode; this._tabContainerBottom = L.DomUtil.create('ul', '', newContainer); } // Store Tabs in Collection for easier iteration for (i = 0; i < this._tabContainerTop.children.length; i++) { child = this._tabContainerTop.children[i]; child._sidebar = this; child._id = child.querySelector('a').hash.slice(1); // FIXME: this could break for links! this._tabitems.push(child); } for (i = 0; i < this._tabContainerBottom.children.length; i++) { child = this._tabContainerBottom.children[i]; child._sidebar = this; child._id = child.querySelector('a').hash.slice(1); // FIXME: this could break for links! this._tabitems.push(child); } // Store Panes in Collection for easier iteration for (i = 0; i < this._paneContainer.children.length; i++) { child = this._paneContainer.children[i]; if (child.tagName === 'DIV' && L.DomUtil.hasClass(child, 'leaflet-sidebar-pane')) { this._panes.push(child); // Save references to close buttons var closeButtons = child.querySelectorAll('.leaflet-sidebar-close'); if (closeButtons.length) { this._closeButtons.push(closeButtons[closeButtons.length - 1]); this._closeClick(closeButtons[closeButtons.length - 1], 'on'); } } } // set click listeners for tab & close buttons for (i = 0; i < this._tabitems.length; i++) { this._tabClick(this._tabitems[i], 'on'); } // leaflet moves the returned container to the right place in the DOM return container; }, /** * Remove this sidebar from the map. * * @param {L.Map} map * @returns {Sidebar} */ onRemove: function (map) { var i; this._map = null; this._tabitems = []; this._panes = []; this._closeButtons = []; // Remove click listeners for tab & close buttons for (i = 0; i < this._tabitems.length; i++) this._tabClick(this._tabitems[i], 'off'); for (i = 0; i < this._closeButtons.length; i++) this._closeClick(this._closeButtons[i], 'off'); return this; }, /** * @method addTo(map: Map): this * Adds the control to the given map. Overrides the implementation of L.Control, * changing the DOM mount target from map._controlContainer.topleft to map._container */ addTo: function (map) { this.onRemove(); this._map = map; this._container = this.onAdd(map); L.DomUtil.addClass(this._container, 'leaflet-control'); L.DomUtil.addClass(this._container, 'leaflet-sidebar-' + this.getPosition()); if (L.Browser.touch) L.DomUtil.addClass(this._container, 'leaflet-touch'); // when adding to the map container, we should stop event propagation L.DomEvent.disableScrollPropagation(this._container); L.DomEvent.disableClickPropagation(this._container); L.DomEvent.on(this._container, 'contextmenu', L.DomEvent.stopPropagation); // insert as first child of map container (important for css) map._container.insertBefore(this._container, map._container.firstChild); return this; }, /** * @deprecated - Please use remove() instead of removeFrom(), as of Leaflet 0.8-dev, the removeFrom() has been replaced with remove() * Removes this sidebar from the map. * @param {L.Map} map * @returns {Sidebar} */ removeFrom: function(map) { console.warn('removeFrom() has been deprecated, please use remove() instead as support for this function will be ending soon.'); this._map._container.removeChild(this._container); this.onRemove(map); return this; }, /** * Open sidebar (if it's closed) and show the specified tab. * * @param {string} id - The ID of the tab to show (without the # character) * @returns {L.Control.Sidebar} */ open: function(id) { var i, child, tab; // If panel is disabled, stop right here tab = this._getTab(id); if (L.DomUtil.hasClass(tab, 'disabled')) return this; // Hide old active contents and show new content for (i = 0; i < this._panes.length; i++) { child = this._panes[i]; if (child.id === id) L.DomUtil.addClass(child, 'active'); else if (L.DomUtil.hasClass(child, 'active')) L.DomUtil.removeClass(child, 'active'); } // Remove old active highlights and set new highlight for (i = 0; i < this._tabitems.length; i++) { child = this._tabitems[i]; if (child.querySelector('a').hash === '#' + id) L.DomUtil.addClass(child, 'active'); else if (L.DomUtil.hasClass(child, 'active')) L.DomUtil.removeClass(child, 'active'); } this.fire('content', { id: id }); // Open sidebar if it's closed if (L.DomUtil.hasClass(this._container, 'collapsed')) { this.fire('opening'); L.DomUtil.removeClass(this._container, 'collapsed'); if (this.options.autopan) this._panMap('open'); } return this; }, /** * Close the sidebar (if it's open). * * @returns {L.Control.Sidebar} */ close: function() { var i; // Remove old active highlights for (i = 0; i < this._tabitems.length; i++) { var child = this._tabitems[i]; if (L.DomUtil.hasClass(child, 'active')) L.DomUtil.removeClass(child, 'active'); } // close sidebar, if it's opened if (!L.DomUtil.hasClass(this._container, 'collapsed')) { this.fire('closing'); L.DomUtil.addClass(this._container, 'collapsed'); if (this.options.autopan) this._panMap('close'); } return this; }, /** * Add a panel to the sidebar * * @example * sidebar.addPanel({ * id: 'userinfo', * tab: '', * pane: someDomNode.innerHTML, * position: 'bottom' * }); * * @param {Object} [data] contains the data for the new Panel: * @param {String} [data.id] the ID for the new Panel, must be unique for the whole page * @param {String} [data.position='top'] where the tab will appear: * on the top or the bottom of the sidebar. 'top' or 'bottom' * @param {HTMLString} {DOMnode} [data.tab] content of the tab item, as HTMLstring or DOM node * @param {HTMLString} {DOMnode} [data.pane] content of the panel, as HTMLstring or DOM node * @param {String} [data.link] URL to an (external) link that will be opened instead of a panel * @param {String} [data.title] Title for the pane header * @param {String} {Function} [data.button] URL to an (external) link or a click listener function that will be opened instead of a panel * @param {bool} [data.disabled] If the tab should be disabled by default * * @returns {L.Control.Sidebar} */ addPanel: function(data) { var pane, tab, tabHref, closeButtons, content; // Create tab node tab = L.DomUtil.create('li', data.disabled ? 'disabled' : ''); tabHref = L.DomUtil.create('a', '', tab); tabHref.href = '#' + data.id; tabHref.setAttribute('role', 'tab'); tabHref.innerHTML = data.tab; tab._sidebar = this; tab._id = data.id; tab._button = data.button; // to allow links to be disabled, the href cannot be used if (data.title && data.title[0] !== '<') tab.title = data.title; // append it to the DOM and store JS references if (data.position === 'bottom') this._tabContainerBottom.appendChild(tab); else this._tabContainerTop.appendChild(tab); this._tabitems.push(tab); // Create pane node if (data.pane) { if (typeof data.pane === 'string') { // pane is given as HTML string pane = L.DomUtil.create('DIV', 'leaflet-sidebar-pane', this._paneContainer); content = ''; if (data.title) content += '