/* global L */
// A layer control which provides for layer groupings. // Author: Ishmael Smyrnow L.Control.GroupedLayers = L.Control.extend({
options: { collapsed: true, position: 'topright', autoZIndex: true }, initialize: function (baseLayers, groupedOverlays, options) { var i, j; L.Util.setOptions(this, options); this._layers = {}; this._lastZIndex = 0; this._handlingClick = false; this._groupList = []; this._domGroups = []; for (i in baseLayers) { this._addLayer(baseLayers[i], i); } for (i in groupedOverlays) { for (var j in groupedOverlays[i]) { this._addLayer(groupedOverlays[i][j], j, i, true); } } }, onAdd: function (map) { this._initLayout(); this._update(); map .on('layeradd', this._onLayerChange, this) .on('layerremove', this._onLayerChange, this); return this._container; }, onRemove: function (map) { map .off('layeradd', this._onLayerChange) .off('layerremove', this._onLayerChange); }, addBaseLayer: function (layer, name) { this._addLayer(layer, name); this._update(); return this; }, addOverlay: function (layer, name, group) { this._addLayer(layer, name, group, true); this._update(); return this; }, removeLayer: function (layer) { var id = L.Util.stamp(layer); delete this._layers[id]; this._update(); return this; }, _initLayout: function () { var className = 'leaflet-control-layers', container = this._container = L.DomUtil.create('div', className); //Makes this work on IE10 Touch devices by stopping it from firing a mouseout event when the touch is released container.setAttribute('aria-haspopup', true); if (!L.Browser.touch) { L.DomEvent.disableClickPropagation(container); L.DomEvent.on(container, 'wheel', L.DomEvent.stopPropagation); } else { L.DomEvent.on(container, 'click', L.DomEvent.stopPropagation); } var form = this._form = L.DomUtil.create('form', className + '-list'); if (this.options.collapsed) { if (!L.Browser.android) { L.DomEvent .on(container, 'mouseover', this._expand, this) .on(container, 'mouseout', this._collapse, this); } var link = this._layersLink = L.DomUtil.create('a', className + '-toggle', container); link.href = '#'; link.title = 'Layers'; if (L.Browser.touch) { L.DomEvent .on(link, 'click', L.DomEvent.stop) .on(link, 'click', this._expand, this); } else { L.DomEvent.on(link, 'focus', this._expand, this); } this._map.on('click', this._collapse, this); // TODO keyboard accessibility } else { this._expand(); } this._baseLayersList = L.DomUtil.create('div', className + '-base', form); this._separator = L.DomUtil.create('div', className + '-separator', form); this._overlaysList = L.DomUtil.create('div', className + '-overlays', form); container.appendChild(form); }, _addLayer: function (layer, name, group, overlay) { var id = L.Util.stamp(layer); this._layers[id] = { layer: layer, name: name, overlay: overlay }; if (group) { var groupId = this._groupList.indexOf(group); if (groupId === -1) { groupId = this._groupList.push(group) - 1; } this._layers[id].group = { name: group, id: groupId }; } if (this.options.autoZIndex && layer.setZIndex) { this._lastZIndex++; layer.setZIndex(this._lastZIndex); } }, _update: function () { if (!this._container) { return; } this._baseLayersList.innerHTML = ''; this._overlaysList.innerHTML = ''; this._domGroups.length = 0; var baseLayersPresent = false, overlaysPresent = false, i, obj; for (i in this._layers) { obj = this._layers[i]; this._addItem(obj); overlaysPresent = overlaysPresent || obj.overlay; baseLayersPresent = baseLayersPresent || !obj.overlay; } this._separator.style.display = overlaysPresent && baseLayersPresent ? '' : 'none'; }, _onLayerChange: function (e) { var obj = this._layers[L.Util.stamp(e.layer)]; if (!obj) { return; } if (!this._handlingClick) { this._update(); } var type = obj.overlay ? (e.type === 'layeradd' ? 'overlayadd' : 'overlayremove') : (e.type === 'layeradd' ? 'baselayerchange' : null); if (type) { this._map.fire(type, obj); } }, // IE7 bugs out if you create a radio dynamically, so you have to do it this hacky way (see http://bit.ly/PqYLBe) _createRadioElement: function (name, checked) { var radioHtml = '<input type="radio" class="leaflet-control-layers-selector" name="' + name + '"'; if (checked) { radioHtml += ' checked="checked"'; } radioHtml += '/>'; var radioFragment = document.createElement('div'); radioFragment.innerHTML = radioHtml; return radioFragment.firstChild; }, _addItem: function (obj) { var label = document.createElement('label'), input, checked = this._map.hasLayer(obj.layer), container; if (obj.overlay) { input = document.createElement('input'); input.type = 'checkbox'; input.className = 'leaflet-control-layers-selector'; input.defaultChecked = checked; } else { input = this._createRadioElement('leaflet-base-layers', checked); } input.layerId = L.Util.stamp(obj.layer); L.DomEvent.on(input, 'click', this._onInputClick, this); var name = document.createElement('span'); name.innerHTML = ' ' + obj.name; label.appendChild(input); label.appendChild(name); if (obj.overlay) { container = this._overlaysList; var groupContainer = this._domGroups[obj.group.id]; // Create the group container if it doesn't exist if (!groupContainer) { groupContainer = document.createElement('div'); groupContainer.className = 'leaflet-control-layers-group'; groupContainer.id = 'leaflet-control-layers-group-' + obj.group.id; var groupLabel = document.createElement('span'); groupLabel.className = 'leaflet-control-layers-group-name'; groupLabel.innerHTML = obj.group.name; groupContainer.appendChild(groupLabel); container.appendChild(groupContainer); this._domGroups[obj.group.id] = groupContainer; } container = groupContainer; } else { container = this._baseLayersList; } container.appendChild(label); return label; }, _onInputClick: function () { var i, input, obj, inputs = this._form.getElementsByTagName('input'), inputsLen = inputs.length; this._handlingClick = true; for (i = 0; i < inputsLen; i++) { input = inputs[i]; obj = this._layers[input.layerId]; if (input.checked && !this._map.hasLayer(obj.layer)) { this._map.addLayer(obj.layer); } else if (!input.checked && this._map.hasLayer(obj.layer)) { this._map.removeLayer(obj.layer); } } this._handlingClick = false; }, _expand: function () { L.DomUtil.addClass(this._container, 'leaflet-control-layers-expanded'); }, _collapse: function () { this._container.className = this._container.className.replace(' leaflet-control-layers-expanded', ''); }
});
L.control.groupedLayers = function (baseLayers, groupedOverlays, options) {
return new L.Control.GroupedLayers(baseLayers, groupedOverlays, options);
};