1/* 2 * L.Control.Loading is a control that shows a loading indicator when tiles are 3 * loading or when map-related AJAX requests are taking place. 4 */ 5 6(function () { 7 8 var console = window.console || { 9 error: function () {}, 10 warn: function () {} 11 }; 12 13 function defineLeafletLoading(L) { 14 L.Control.Loading = L.Control.extend({ 15 options: { 16 delayIndicator: null, 17 position: 'topleft', 18 separate: false, 19 zoomControl: null, 20 spinjs: false, 21 spin: { 22 lines: 7, 23 length: 3, 24 width: 3, 25 radius: 5, 26 rotate: 13, 27 top: "83%" 28 } 29 }, 30 31 initialize: function(options) { 32 L.setOptions(this, options); 33 this._dataLoaders = {}; 34 35 // Try to set the zoom control this control is attached to from 36 // the options 37 if (this.options.zoomControl !== null) { 38 this.zoomControl = this.options.zoomControl; 39 } 40 }, 41 42 onAdd: function(map) { 43 if (this.options.spinjs && (typeof Spinner !== 'function')) { 44 return console.error("Leaflet.loading cannot load because you didn't load spin.js (http://fgnass.github.io/spin.js/), even though you set it in options."); 45 } 46 this._addLayerListeners(map); 47 this._addMapListeners(map); 48 49 // Try to set the zoom control this control is attached to from the map 50 // the control is being added to 51 if (!this.options.separate && !this.zoomControl) { 52 if (map.zoomControl) { 53 this.zoomControl = map.zoomControl; 54 } else if (map.zoomsliderControl) { 55 this.zoomControl = map.zoomsliderControl; 56 } 57 } 58 59 // Create the loading indicator 60 var classes = 'leaflet-control-loading'; 61 var container; 62 if (this.zoomControl && !this.options.separate) { 63 // If there is a zoom control, hook into the bottom of it 64 container = this.zoomControl._container; 65 // These classes are no longer used as of Leaflet 0.6 66 classes += ' leaflet-bar-part-bottom leaflet-bar-part last'; 67 68 // Loading control will be added to the zoom control. So the visible last element is not the 69 // last dom element anymore. So add the part-bottom class. 70 L.DomUtil.addClass(this._getLastControlButton(), 'leaflet-bar-part-bottom'); 71 } 72 else { 73 // Otherwise, create a container for the indicator 74 container = L.DomUtil.create('div', 'leaflet-control-zoom leaflet-control-layer-container leaflet-bar'); 75 } 76 this._indicatorContainer = container; 77 this._indicator = L.DomUtil.create('a', classes, container); 78 if (this.options.spinjs) { 79 this._spinner = new Spinner(this.options.spin).spin(); 80 this._indicator.appendChild(this._spinner.el); 81 } 82 return container; 83 }, 84 85 onRemove: function(map) { 86 this._removeLayerListeners(map); 87 this._removeMapListeners(map); 88 }, 89 90 removeFrom: function (map) { 91 if (this.zoomControl && !this.options.separate) { 92 // Override Control.removeFrom() to avoid clobbering the entire 93 // _container, which is the same as zoomControl's 94 this._container.removeChild(this._indicator); 95 this._map = null; 96 this.onRemove(map); 97 return this; 98 } 99 else { 100 // If this control is separate from the zoomControl, call the 101 // parent method so we don't leave behind an empty container 102 return L.Control.prototype.removeFrom.call(this, map); 103 } 104 }, 105 106 addLoader: function(id) { 107 this._dataLoaders[id] = true; 108 if (this.options.delayIndicator && !this.delayIndicatorTimeout) { 109 // If we are delaying showing the indicator and we're not 110 // already waiting for that delay, set up a timeout. 111 var that = this; 112 this.delayIndicatorTimeout = setTimeout(function () { 113 that.updateIndicator(); 114 that.delayIndicatorTimeout = null; 115 }, this.options.delayIndicator); 116 } 117 else { 118 // Otherwise show the indicator immediately 119 this.updateIndicator(); 120 } 121 }, 122 123 removeLoader: function(id) { 124 delete this._dataLoaders[id]; 125 this.updateIndicator(); 126 127 // If removing this loader means we're in no danger of loading, 128 // clear the timeout. This prevents old delays from instantly 129 // triggering the indicator. 130 if (this.options.delayIndicator && this.delayIndicatorTimeout && !this.isLoading()) { 131 clearTimeout(this.delayIndicatorTimeout); 132 this.delayIndicatorTimeout = null; 133 } 134 }, 135 136 updateIndicator: function() { 137 if (this.isLoading()) { 138 this._showIndicator(); 139 } 140 else { 141 this._hideIndicator(); 142 } 143 }, 144 145 isLoading: function() { 146 return this._countLoaders() > 0; 147 }, 148 149 _countLoaders: function() { 150 var size = 0, key; 151 for (key in this._dataLoaders) { 152 if (this._dataLoaders.hasOwnProperty(key)) size++; 153 } 154 return size; 155 }, 156 157 _showIndicator: function() { 158 // Show loading indicator 159 L.DomUtil.addClass(this._indicator, 'is-loading'); 160 L.DomUtil.addClass(this._indicatorContainer, 'is-loading'); 161
162 // If zoomControl exists, make the zoom-out button not last 163 if (!this.options.separate) { 164 if (this.zoomControl instanceof L.Control.Zoom) { 165 L.DomUtil.removeClass(this._getLastControlButton(), 'leaflet-bar-part-bottom'); 166 } 167 else if (typeof L.Control.Zoomslider === 'function' && this.zoomControl instanceof L.Control.Zoomslider) { 168 L.DomUtil.removeClass(this.zoomControl._ui.zoomOut, 'leaflet-bar-part-bottom'); 169 } 170 } 171 }, 172 173 _hideIndicator: function() { 174 // Hide loading indicator 175 L.DomUtil.removeClass(this._indicator, 'is-loading'); 176 L.DomUtil.removeClass(this._indicatorContainer, 'is-loading'); 177 178 // If zoomControl exists, make the zoom-out button last 179 if (!this.options.separate) { 180 if (this.zoomControl instanceof L.Control.Zoom) { 181 L.DomUtil.addClass(this._getLastControlButton(), 'leaflet-bar-part-bottom'); 182 } 183 else if (typeof L.Control.Zoomslider === 'function' && this.zoomControl instanceof L.Control.Zoomslider) { 184 L.DomUtil.addClass(this.zoomControl._ui.zoomOut, 'leaflet-bar-part-bottom'); 185 } 186 } 187 }, 188 189 _getLastControlButton: function() { 190 var container = this.zoomControl._container, 191 index = container.children.length - 1; 192 193 // Find the last visible control button that is not our loading 194 // indicator 195 while (index > 0) { 196 var button = container.children[index]; 197 if (!(this._indicator === button || button.offsetWidth === 0 || button.offsetHeight === 0)) { 198 break; 199 } 200 index--; 201 } 202 203 return container.children[index]; 204 }, 205 206 _handleLoading: function(e) { 207 this.addLoader(this.getEventId(e)); 208 }, 209 210 _handleBaseLayerChange: function (e) { 211 var that = this; 212 213 // Check for a target 'layer' that contains multiple layers, such as 214 // L.LayerGroup. This will happen if you have an L.LayerGroup in an 215 // L.Control.Layers. 216 if (e.layer && e.layer.eachLayer && typeof e.layer.eachLayer === 'function') { 217 e.layer.eachLayer(function (layer) { 218 that._handleBaseLayerChange({ layer: layer }); 219 }); 220 } 221 else { 222 // If we're changing to a canvas layer, don't handle loading 223 // as canvas layers will not fire load events. 224 if (!(L.TileLayer.Canvas && e.layer instanceof L.TileLayer.Canvas)) { 225 that._handleLoading(e); 226 } 227 } 228 }, 229 230 _handleLoad: function(e) { 231 this.removeLoader(this.getEventId(e)); 232 }, 233 234 getEventId: function(e) { 235 if (e.id) { 236 return e.id; 237 } 238 else if (e.layer) { 239 return e.layer._leaflet_id; 240 } 241 return e.target._leaflet_id; 242 }, 243 244 _layerAdd: function(e) { 245 if (!e.layer || !e.layer.on) return 246 try { 247 e.layer.on({ 248 loading: this._handleLoading, 249 load: this._handleLoad 250 }, this); 251 } 252 catch (exception) { 253 console.warn('L.Control.Loading: Tried and failed to add ' + 254 ' event handlers to layer', e.layer); 255 console.warn('L.Control.Loading: Full details', exception); 256 } 257 }, 258 259 _layerRemove: function(e) { 260 if (!e.layer || !e.layer.off) return; 261 try { 262 e.layer.off({ 263 loading: this._handleLoading, 264 load: this._handleLoad 265 }, this); 266 } 267 catch (exception) { 268 console.warn('L.Control.Loading: Tried and failed to remove ' + 269 'event handlers from layer', e.layer); 270 console.warn('L.Control.Loading: Full details', exception); 271 } 272 }, 273 274 _addLayerListeners: function(map) { 275 // Add listeners for begin and end of load to any layers already 276 // on the map 277 map.eachLayer(function(layer) { 278 if (!layer.on) return; 279 layer.on({ 280 loading: this._handleLoading, 281 load: this._handleLoad 282 }, this); 283 }, this); 284 285 // When a layer is added to the map, add listeners for begin and 286 // end of load 287 map.on('layeradd', this._layerAdd, this); 288 map.on('layerremove', this._layerRemove, this); 289 }, 290 291 _removeLayerListeners: function(map) { 292 // Remove listeners for begin and end of load from all layers 293 map.eachLayer(function(layer) { 294 if (!layer.off) return; 295 layer.off({ 296 loading: this._handleLoading, 297 load: this._handleLoad 298 }, this); 299 }, this); 300 301 // Remove layeradd/layerremove listener from map 302 map.off('layeradd', this._layerAdd, this); 303 map.off('layerremove', this._layerRemove, this); 304 }, 305 306 _addMapListeners: function(map) { 307 // Add listeners to the map for (custom) dataloading and dataload 308 // events, eg, for AJAX calls that affect the map but will not be 309 // reflected in the above layer events. 310 map.on({ 311 baselayerchange: this._handleBaseLayerChange, 312 dataloading: this._handleLoading, 313 dataload: this._handleLoad, 314 layerremove: this._handleLoad 315 }, this); 316 }, 317 318 _removeMapListeners: function(map) { 319 map.off({ 320 baselayerchange: this._handleBaseLayerChange, 321 dataloading: this._handleLoading, 322 dataload: this._handleLoad, 323 layerremove: this._handleLoad 324 }, this); 325 } 326 }); 327 328 L.Map.addInitHook(function () { 329 if (this.options.loadingControl) { 330 this.loadingControl = new L.Control.Loading(); 331 this.addControl(this.loadingControl); 332 } 333 }); 334 335 L.Control.loading = function(options) { 336 return new L.Control.Loading(options); 337 }; 338 } 339 340 if (typeof define === 'function' && define.amd) { 341 // Try to add leaflet.loading to Leaflet using AMD 342 define(['front/view/js/bower_components/Leaflet/default/leaflet'], function (L) { 343 defineLeafletLoading(L); 344 }); 345 } 346 else { 347 // Else use the global L 348 defineLeafletLoading(L); 349 } 350 351})();
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.