1(function (root, factory) { 2 if(typeof define === "function" && define.amd) { 3 define(["openlayers"], factory); 4 } else if(typeof module === "object" && module.exports) { 5 module.exports = factory(require("openlayers")); 6 } else { 7 root.LayerSwitcher = factory(root.ol); 8 } 9}(this, function(ol) { 10 /** 11 * OpenLayers v3/v4 Layer Switcher Control. 12 * See [the examples](./examples) for usage. 13 * @constructor 14 * @extends {ol.control.Control} 15 * @param {Object} opt_options Control options, extends olx.control.ControlOptions adding: 16 * **`tipLabel`** `String` - the button tooltip. 17 */ 18 ol.control.LayerSwitcher = function(opt_options) { 19 20 var options = opt_options || {}; 21 22 var tipLabel = options.tipLabel ? 23 options.tipLabel : 'Legend'; 24 25 this.mapListeners = []; 26 27 this.hiddenClassName = 'ol-unselectable ol-control layer-switcher'; 28 if (ol.control.LayerSwitcher.isTouchDevice_()) { 29 this.hiddenClassName += ' touch'; 30 } 31 this.shownClassName = 'shown'; 32 33 var element = document.createElement('div'); 34 element.className = this.hiddenClassName; 35 36 var button = document.createElement('button'); 37 button.setAttribute('title', tipLabel); 38 element.appendChild(button); 39 40 this.panel = document.createElement('div'); 41 this.panel.className = 'panel'; 42 element.appendChild(this.panel); 43 ol.control.LayerSwitcher.enableTouchScroll_(this.panel); 44 45 var this_ = this; 46 47 button.onmouseover = function(e) { 48 this_.showPanel(); 49 }; 50 51 button.onclick = function(e) { 52 e = e || window.event; 53 this_.showPanel(); 54 e.preventDefault(); 55 }; 56 57 this_.panel.onmouseout = function(e) { 58 e = e || window.event; 59 if (!this_.panel.contains(e.toElement || e.relatedTarget)) { 60 this_.hidePanel(); 61 } 62 }; 63 64 ol.control.Control.call(this, { 65 element: element, 66 target: options.target 67 }); 68 69 }; 70 71 ol.inherits(ol.control.LayerSwitcher, ol.control.Control); 72 73 /** 74 * Show the layer panel. 75 */ 76 ol.control.LayerSwitcher.prototype.showPanel = function() { 77 if (!this.element.classList.contains(this.shownClassName)) { 78 this.element.classList.add(this.shownClassName); 79 this.renderPanel(); 80 } 81 }; 82 83 /** 84 * Hide the layer panel. 85 */ 86 ol.control.LayerSwitcher.prototype.hidePanel = function() { 87 if (this.element.classList.contains(this.shownClassName)) { 88 this.element.classList.remove(this.shownClassName); 89 } 90 }; 91 92 /** 93 * Re-draw the layer panel to represent the current state of the layers. 94 */ 95 ol.control.LayerSwitcher.prototype.renderPanel = function() { 96 97 this.ensureTopVisibleBaseLayerShown_(); 98 99 while(this.panel.firstChild) { 100 this.panel.removeChild(this.panel.firstChild); 101 } 102 103 var ul = document.createElement('ul'); 104 this.panel.appendChild(ul); 105 this.renderLayers_(this.getMap(), ul); 106 107 }; 108 109 /** 110 * Set the map instance the control is associated with. 111 * @param {ol.Map} map The map instance. 112 */ 113 ol.control.LayerSwitcher.prototype.setMap = function(map) { 114 // Clean up listeners associated with the previous map 115 for (var i = 0, key; i < this.mapListeners.length; i++) { 116 ol.Observable.unByKey(this.mapListeners[i]); 117 } 118 this.mapListeners.length = 0; 119 // Wire up listeners etc. and store reference to new map 120 ol.control.Control.prototype.setMap.call(this, map); 121 if (map) { 122 var this_ = this; 123 this.mapListeners.push(map.on('pointerdown', function() { 124 this_.hidePanel(); 125 })); 126 this.renderPanel(); 127 } 128 }; 129 130 /** 131 * Ensure only the top-most base layer is visible if more than one is visible. 132 * @private 133 */ 134 ol.control.LayerSwitcher.prototype.ensureTopVisibleBaseLayerShown_ = function() { 135 var lastVisibleBaseLyr; 136 ol.control.LayerSwitcher.forEachRecursive(this.getMap(), function(l, idx, a) { 137 if (l.get('type') === 'base' && l.getVisible()) { 138 lastVisibleBaseLyr = l; 139 } 140 }); 141 if (lastVisibleBaseLyr) this.setVisible_(lastVisibleBaseLyr, true); 142 }; 143 144 /** 145 * Toggle the visible state of a layer. 146 * Takes care of hiding other layers in the same exclusive group if the layer 147 * is toggle to visible. 148 * @private 149 * @param {ol.layer.Base} The layer whos visibility will be toggled. 150 */ 151 ol.control.LayerSwitcher.prototype.setVisible_ = function(lyr, visible) { 152 var map = this.getMap(); 153 lyr.setVisible(visible); 154 if (visible && lyr.get('type') === 'base') { 155 // Hide all other base layers regardless of grouping 156 ol.control.LayerSwitcher.forEachRecursive(map, function(l, idx, a) { 157 if (l != lyr && l.get('type') === 'base') { 158 l.setVisible(false); 159 } 160 }); 161 } 162 }; 163 164 /**
165 * Render all layers that are children of a group. 166 * @private 167 * @param {ol.layer.Base} lyr Layer to be rendered (should have a title property). 168 * @param {Number} idx Position in parent group list. 169 */ 170 ol.control.LayerSwitcher.prototype.renderLayer_ = function(lyr, idx) { 171 172 var this_ = this; 173 174 var li = document.createElement('li'); 175 176 var lyrTitle = lyr.get('title'); 177 var lyrId = ol.control.LayerSwitcher.uuid(); 178 179 var label = document.createElement('label'); 180 181 if (lyr.getLayers && !lyr.get('combine')) { 182 183 li.className = 'group'; 184 label.innerHTML = lyrTitle; 185 li.appendChild(label); 186 var ul = document.createElement('ul'); 187 li.appendChild(ul); 188 189 this.renderLayers_(lyr, ul); 190 191 } else { 192 193 li.className = 'layer'; 194 var input = document.createElement('input'); 195 if (lyr.get('type') === 'base') { 196 input.type = 'radio'; 197 input.name = 'base'; 198 } else { 199 input.type = 'checkbox'; 200 } 201 input.id = lyrId; 202 input.checked = lyr.get('visible'); 203 input.onchange = function(e) { 204 this_.setVisible_(lyr, e.target.checked); 205 }; 206 li.appendChild(input); 207 208 label.htmlFor = lyrId; 209 label.innerHTML = lyrTitle; 210 211 var rsl = this.getMap().getView().getResolution(); 212 if (rsl > lyr.getMaxResolution() || rsl < lyr.getMinResolution()){ 213 label.className += ' disabled'; 214 } 215 216 li.appendChild(label); 217 218 } 219 220 return li; 221 222 }; 223 224 /** 225 * Render all layers that are children of a group. 226 * @private 227 * @param {ol.layer.Group} lyr Group layer whos children will be rendered. 228 * @param {Element} elm DOM element that children will be appended to. 229 */ 230 ol.control.LayerSwitcher.prototype.renderLayers_ = function(lyr, elm) { 231 var lyrs = lyr.getLayers().getArray().slice().reverse(); 232 for (var i = 0, l; i < lyrs.length; i++) { 233 l = lyrs[i]; 234 if (l.get('title')) { 235 elm.appendChild(this.renderLayer_(l, i)); 236 } 237 } 238 }; 239 240 /** 241 * **Static** Call the supplied function for each layer in the passed layer group 242 * recursing nested groups. 243 * @param {ol.layer.Group} lyr The layer group to start iterating from. 244 * @param {Function} fn Callback which will be called for each `ol.layer.Base` 245 * found under `lyr`. The signature for `fn` is the same as `ol.Collection#forEach` 246 */ 247 ol.control.LayerSwitcher.forEachRecursive = function(lyr, fn) { 248 lyr.getLayers().forEach(function(lyr, idx, a) { 249 fn(lyr, idx, a); 250 if (lyr.getLayers) { 251 ol.control.LayerSwitcher.forEachRecursive(lyr, fn); 252 } 253 }); 254 }; 255 256 /** 257 * Generate a UUID 258 * @returns {String} UUID 259 * 260 * Adapted from http://stackoverflow.com/a/2117523/526860 261 */ 262 ol.control.LayerSwitcher.uuid = function() { 263 return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { 264 var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8); 265 return v.toString(16); 266 }); 267 } 268 269 /** 270 * @private 271 * @desc Apply workaround to enable scrolling of overflowing content within an 272 * element. Adapted from https://gist.github.com/chrismbarr/4107472 273 */ 274 ol.control.LayerSwitcher.enableTouchScroll_ = function(elm) { 275 if(ol.control.LayerSwitcher.isTouchDevice_()){ 276 var scrollStartPos = 0; 277 elm.addEventListener("touchstart", function(event) { 278 scrollStartPos = this.scrollTop + event.touches[0].pageY; 279 }, false); 280 elm.addEventListener("touchmove", function(event) { 281 this.scrollTop = scrollStartPos - event.touches[0].pageY; 282 }, false); 283 } 284 }; 285 286 /** 287 * @private
288 * @desc Determine if the current browser supports touch events. Adapted from 289 * https://gist.github.com/chrismbarr/4107472 290 */ 291 ol.control.LayerSwitcher.isTouchDevice_ = function() { 292 try { 293 document.createEvent("TouchEvent"); 294 return true; 295 } catch(e) { 296 return false; 297 } 298 }; 299 var LayerSwitcher = ol.control.LayerSwitcher; 300 return LayerSwitcher; 301}));
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.