/** * Leaflet Panel Layers v1.2.6 - 2020-04-08 * * Copyright 2020 Stefano Cudini * stefano.cudini@gmail.com * https://opengeo.tech/ * * Licensed under the MIT license. * * Demos: * https://opengeo.tech/maps/leaflet-panel-layers/ * * Source: * git@github.com:stefanocudini/leaflet-panel-layers.git * */ (function (factory) { if (typeof define === 'function' && define.amd) { //AMD define(['leaflet'], factory); } else if (typeof module !== 'undefined') { // Node/CommonJS module.exports = factory(require('leaflet')); } else { // Browser globals if (typeof window.L === 'undefined') throw 'Leaflet must be loaded first'; factory(window.L); } })(function (L) { L.Control.PanelLayers = L.Control.Layers.extend({ includes: L.version[0]==='1' ? L.Evented.prototype : L.Mixin.Events, options: { compact: false, compactOffset: 0, collapsed: false, autoZIndex: true, collapsibleGroups: false, buildItem: null, //function that return row item html node(or html string) title: '', //title of panel className: '', //additional class name for panel position: 'topright' }, initialize: function (baseLayers, overlays, options) { L.setOptions(this, options); this._layers = []; this._groups = {}; this._items = {}; this._layersActives = []; this._lastZIndex = 0; this._handlingClick = false; this.className = 'leaflet-panel-layers'; var i, n, isCollapsed; for (i in baseLayers) { if (baseLayers[i].group && baseLayers[i].layers) { isCollapsed = baseLayers[i].collapsed || false; for (n in baseLayers[i].layers) this._addLayer(baseLayers[i].layers[n], false, baseLayers[i].group, isCollapsed); } else this._addLayer(baseLayers[i], false); } for (i in overlays) { if (overlays[i].group && overlays[i].layers) { isCollapsed = overlays[i].collapsed || false; for (n in overlays[i].layers) this._addLayer(overlays[i].layers[n], true, overlays[i].group, isCollapsed); } else this._addLayer(overlays[i], true); } }, onAdd: function (map) { var self = this; for (var i in this._layersActives) { map.addLayer(this._layersActives[i]); } L.Control.Layers.prototype.onAdd.call(this, map); this._map.on('resize', function(e) { self._updateHeight(e.newSize.y); }); return this._container; }, //TODO addBaseLayerGroup //TODO addOverlayGroup addBaseLayer: function (layer, name, group) { layer.name = name || layer.name || ''; this._addLayer(layer, false, group); this._update(); return this; }, addOverlay: function (layer, name, group) { layer.name = name || layer.name || ''; this._addLayer(layer, true, group); this._update(); return this; }, removeLayer: function (layerDef) { var layer = layerDef.hasOwnProperty('layer') ? this._layerFromDef(layerDef) : layerDef; this._map.removeLayer(layer); L.Control.Layers.prototype.removeLayer.call(this, layer); return this; }, clearLayers: function () { for (var i = 0; i < this._layers.length; i++) { this.removeLayer(this._layers[i]); } }, _layerFromDef: function (layerDef) { for (var i = 0; i < this._layers.length; i++) { var id = L.stamp(this._layers[i].layer); //TODO add more conditions to comparing definitions if (this._getLayer(id).name === layerDef.name) return this._getLayer(id).layer; } }, _update: function () { this._groups = {}; this._items = {}; L.Control.Layers.prototype._update.call(this); }, _getLayer: function (id) { for (var i = 0; i < this._layers.length; i++) { if (this._layers[i] && this._layers[i].id == id) { return this._layers[i]; } } }, _addLayer: function (layerDef, overlay, group, isCollapsed) { if(!layerDef.layer) throw new Error('layer not defined in item: '+(layerDef.name||'')); if (!(layerDef.layer instanceof L.Class) && (layerDef.layer.type && layerDef.layer.args)) { layerDef.layer = this._getPath(L, layerDef.layer.type).apply(L, layerDef.layer.args); } if(!layerDef.hasOwnProperty('id')) layerDef.id = L.stamp(layerDef.layer); if(layerDef.active) this._layersActives.push(layerDef.layer); this._layers.push(L.Util.extend(layerDef, { collapsed: isCollapsed, overlay: overlay, group: group })); if (this.options.autoZIndex && layerDef.layer && layerDef.layer.setZIndex) { this._lastZIndex++; layerDef.layer.setZIndex(this._lastZIndex); } }, _createItem: function (obj) { var self = this; var item, input, checked; item = L.DomUtil.create('div', this.className + '-item' + (obj.active ? ' active' : '')); checked = this._map.hasLayer(obj.layer); if (obj.overlay) { input = L.DomUtil.create('input', this.className + '-selector'); input.type = 'checkbox'; input.defaultChecked = checked; //TODO name } else input = this._createRadioElement('leaflet-base-layers', checked, obj); input.value = obj.id; input.layerId = obj.id; input.id = obj.id; input._layer = obj; L.DomEvent.on(input, 'click', function (e) { self._onInputClick(); if (e.target.checked) { self.fire('panel:selected', e.target._layer); } else { self.fire('panel:unselected', e.target._layer); } }, this); var label = L.DomUtil.create('label', this.className + '-title'); //TODO label.htmlFor = input.id; var title = L.DomUtil.create('span'); title.innerHTML = obj.name || ''; if (obj.icon) { var icon = L.DomUtil.create('i', this.className + '-icon'); if (typeof obj.icon === 'string') icon.innerHTML = obj.icon || ''; else icon.appendChild(obj.icon); label.appendChild(icon); } label.appendChild(input); label.appendChild(title); item.appendChild(label); if (this.options.buildItem) { var node = this.options.buildItem.call(this, obj); //custom node node or html string if (typeof node === 'string') { var tmp = L.DomUtil.create('div'); tmp.innerHTML = node; item.appendChild(tmp.firstChild); } else item.appendChild(node); } this._items[input.value] = item; return item; }, // IE7 bugs out if you create a radio dynamically, so you have to do it this hacky way (see https://bit.ly/PqYLBe) _createRadioElement: function (name, checked, obj) { var radioHtml = ''; container.appendChild(titlabel); } container.appendChild(this._form); }, _updateHeight: function (h) { h = h || this._map.getSize().y; if (this.options.compact) this._form.style.maxHeight = (h - this.options.compactOffset) + 'px'; else this._form.style.height = h + 'px'; }, _expand: function () { L.DomUtil.addClass(this._container, 'expanded'); }, _collapse: function () { this._container.className = this._container.className.replace('expanded', ''); }, _getPath: function (obj, prop) { var parts = prop.split('.'), last = parts.pop(), len = parts.length, cur = parts[0], i = 1; if (len > 0) while ((obj = obj[cur]) && i < len) cur = parts[i++]; if (obj) return obj[last]; } }); L.control.panelLayers = function (baseLayers, overlays, options) { return new L.Control.PanelLayers(baseLayers, overlays, options); }; return L.Control.PanelLayers; });