PageSourceSearch

https://www.erquery.fr/wp-content/plugins/annuaire/assets/librairie/layersupport.js

js erquery.fr collected 2026-10-03 02:47:11 UTC 16,299 bytes, 558 lines download raw bytes

1/**
2 * Extends the L.MarkerClusterGroup class by mainly overriding methods for
3 * addition/removal of layers, so that they can also be directly added/removed
4 * from the map later on while still clustering in this group.
5 * @type {L.MarkerClusterGroup}
6 */
7L.MarkerClusterGroup.LayerSupport = L.MarkerClusterGroup.extend({
8
9	options: {
10		// Buffer single addLayer and removeLayer requests for efficiency.
11		singleAddRemoveBufferDuration: 0 // in ms.
12	},
13
14	initialize: function (options) {
15		L.MarkerClusterGroup.prototype.initialize.call(this, options);
16
17		// Replace the MCG internal featureGroup's so that they directly
18		// access the map add/removal methods, bypassing the switch agent.
19		this._featureGroup = new _ByPassingFeatureGroup();
20		this._featureGroup.addEventParent(this);
21
22		this._nonPointGroup = new _ByPassingFeatureGroup();
23		this._nonPointGroup.addEventParent(this);
24
25		// Keep track of what should be "represented" on map (can be clustered).
26		this._layers = {};
27		this._proxyLayerGroups = {};
28		this._proxyLayerGroupsNeedRemoving = {};
29
30		// Buffer single addLayer and removeLayer requests.
31		this._singleAddRemoveBuffer = [];
32	},
33
34	/**
35	 * Stamps the passed layers as being part of this group, but without adding
36	 * them to the map right now.
37	 * @param layers L.Layer|Array(L.Layer) layer(s) to be stamped.
38	 * @returns {L.MarkerClusterGroup.LayerSupport} this.
39	 */
40	checkIn: function (layers) {
41		var layersArray = this._toArray(layers);
42
43		this._checkInGetSeparated(layersArray);
44
45		return this;
46	},
47
48	/**
49	 * Un-stamps the passed layers from being part of this group. It has to
50	 * remove them from map (if they are) since they will no longer cluster.
51	 * @param layers L.Layer|Array(L.Layer) layer(s) to be un-stamped.
52	 * @returns {L.MarkerClusterGroup.LayerSupport} this.
53	 */
54	checkOut: function (layers) {
55		var layersArray = this._toArray(layers),
56		    separated = this._separateSingleFromGroupLayers(layersArray, {
57		        groups: [],
58		        singles: []
59		    }),
60		    groups = separated.groups,
61		    singles = separated.singles,
62		    i, layer;
63
64		// Un-stamp single layers.
65		for (i = 0; i < singles.length; i++) {
66			layer = singles[i];
67			delete this._layers[L.stamp(layer)];
68			delete layer._mcgLayerSupportGroup;
69		}
70
71		// Batch remove single layers from MCG.
72		// Note: as for standard MCG, if single layers have been added to
73		// another MCG in the meantime, their __parent will have changed,
74		// so weird things would happen.
75		this._originalRemoveLayers(singles);
76
77		// Dismiss Layer Groups.
78		for (i = 0; i < groups.length; i++) {
79			layer = groups[i];
80			this._dismissProxyLayerGroup(layer);
81		}
82
83		return this;
84	},
85
86	/**
87	 * Checks in and adds an array of layers to this group.
88	 * Layer Groups are also added to the map to fire their event.
89	 * @param layers (L.Layer|L.Layer[]) single and/or group layers to be added.
90	 * @returns {L.MarkerClusterGroup.LayerSupport} this.
91	 */
92	addLayers: function (layers) {
93		var layersArray = this._toArray(layers),
94		    separated = this._checkInGetSeparated(layersArray),
95		    groups = separated.groups,
96		    i, group, id;
97
98		// Batch add all single layers.
99		this._originalAddLayers(separated.singles);
100
101		// Add Layer Groups to the map so that they are registered there and
102		// the map fires 'layeradd' events for them as well.
103		for (i = 0; i < groups.length; i++) {
104			group = groups[i];
105			id = L.stamp(group);
106			this._proxyLayerGroups[id] = group;
107			delete this._proxyLayerGroupsNeedRemoving[id];
108			if (this._map) {
109				this._map._originalAddLayer(group);
110			}
111		}
112	},
113	addLayer: function (layer) {
114		this._bufferSingleAddRemove(layer, "addLayers");
115		return this;
116	},
117	_originalAddLayer: L.MarkerClusterGroup.prototype.addLayer,
118	_originalAddLayers: L.MarkerClusterGroup.prototype.addLayers,
119
120	/**
121	 * Removes layers from this group but without check out.
122	 * Layer Groups are also removed from the map to fire their event.
123	 * @param layers (L.Layer|L.Layer[]) single and/or group layers to be removed.
124	 * @returns {L.MarkerClusterGroup.LayerSupport} this.
125	 */
126	removeLayers: function (layers) {
127		var layersArray = this._toArray(layers),
128		    separated = this._separateSingleFromGroupLayers(layersArray, {
129		        groups: [],
130		        singles: []
131		    }),
132		    groups = separated.groups,
133		    singles = separated.singles,
134		    i = 0,
135		    group, id;
136
137		// Batch remove single layers from MCG.
138		this._originalRemoveLayers(singles);
139
140		// Remove Layer Groups from the map so that they are un-registered
141		// there and the map fires 'layerremove' events for them as well.
142		for (; i < groups.length; i++) {
143			group = groups[i];
144			id = L.stamp(group);
145			delete this._proxyLayerGroups[id];
146			if (this._map) {
147				this._map._originalRemoveLayer(group);
148			} else {
149				this._proxyLayerGroupsNeedRemoving[id] = group;
150			}
151		}
152
153		return this;
154	},
155	removeLayer: function (layer) {
156		this._bufferSingleAddRemove(layer, "removeLayers");
157		return this;
158	},
159	_originalRemoveLayer: L.MarkerClusterGroup.prototype.removeLayer,
160	_originalRemoveLayers: L.MarkerClusterGroup.prototype.removeLayers,
161
162	onAdd: function (map) {
163		// Replace the map addLayer and removeLayer methods to place the
164		// switch agent that redirects layers when required.
165		map._originalAddLayer = map._originalAddLayer || map.addLayer;
166		map._originalRemoveLayer = map._originalRemoveLayer || map.removeLayer;
167		L.extend(map, _layerSwitchMap);
168
169		// As this plugin allows the Application to add layers on map, some
170		// checked in layers might have been added already, whereas LayerSupport
171		// did not have a chance to inject the switch agent in to the map
172		// (if it was never added to map before). Therefore we need to
173		// remove all checked in layers from map!
174		var toBeReAdded = this._removePreAddedLayers(map),
175		    id, group, i;
176
177		// Normal MCG onAdd.
178		this._originalOnAdd.call(this, map);
179
180		// If layer Groups are added/removed from this group while it is not
181		// on map, Control.Layers gets out of sync until this is added back.
182
183		// Restore proxy Layer Groups that may have been added to this
184		// group while it was off map.
185		for (id in this._proxyLayerGroups) {
186			group = this._proxyLayerGroups[id];
187			map._originalAddLayer(group);
188		}
189
190		// Remove proxy Layer Groups that may have been removed from this
191		// group while it was off map.
192		for (id in this._proxyLayerGroupsNeedRemoving) {
193			group = this._proxyLayerGroupsNeedRemoving[id];
194			map._originalRemoveLayer(group);
195			delete this._proxyLayerGroupsNeedRemoving[id];
196		}
197
198		// Restore Layers.
199		for (i = 0; i < toBeReAdded.length; i++) {
200			map.addLayer(toBeReAdded[i]);
201		}
202	},
203	_originalOnAdd: L.MarkerClusterGroup.prototype.onAdd,
204
205	// Do not restore the original map methods when removing the group from it.
206	// Leaving them as-is does not harm, whereas restoring the original ones
207	// may kill the functionality of potential other LayerSupport groups on
208	// the same map. Therefore we do not need to override onRemove.
209
210	_bufferSingleAddRemove: function (layer, operationType) {
211		var duration = this.options.singleAddRemoveBufferDuration,
212		    fn;
213
214		if (duration > 0) {
215			this._singleAddRemoveBuffer.push({
216				type: operationType,
217				layer: layer
218			});
219
220			if (!this._singleAddRemoveBufferTimeout) {
221				fn = L.bind(this._processSingleAddRemoveBuffer, this);
222
223				this._singleAddRemoveBufferTimeout = setTimeout(fn, duration);
224			}
225		} else { // If duration <= 0, process synchronously.
226			this[operationType](layer);
227		}
228	},
229	_processSingleAddRemoveBuffer: function () {
230		// For now, simply cut the processes at each operation change
231		// (addLayers, removeLayers).
232		var singleAddRemoveBuffer = this._singleAddRemoveBuffer,
233		    i = 0,
234		    layersBuffer = [],
235		    currentOperation,
236		    currentOperationType;
237
238		for (; i < singleAddRemoveBuffer.length; i++) {
239			currentOperation = singleAddRemoveBuffer[i];
240			if (!currentOperationType) {
241				currentOperationType = currentOperation.type;
242			}
243			if (currentOperation.type === currentOperationType) {
244				layersBuffer.push(currentOperation.layer);
245			} else {
246				this[currentOperationType](layersBuffer);
247				currentOperationType = currentOperation.type;
248				layersBuffer = [currentOperation.layer];
249			}
250		}
251		this[currentOperationType](layersBuffer);
252		singleAddRemoveBuffer.length = 0;
253		clearTimeout(this._singleAddRemoveBufferTimeout);
254		this._singleAddRemoveBufferTimeout = null;
255	},
256
257	_checkInGetSeparated: function (layersArray) {
258		var separated = this._separateSingleFromGroupLayers(layersArray, {
259		        groups: [],
260		        singles: []
261		    }),
262		    groups = separated.groups,
263		    singles = separated.singles,
264		    i, layer;
265
266		// Recruit Layer Groups.
267		// If they do not already belong to this group, they will be
268		// removed from map (together will all child layers).
269		for (i = 0; i < groups.length; i++) {
270			layer = groups[i];
271			this._recruitLayerGroupAsProxy(layer);
272		}
273
274		// Stamp single layers.
275		for (i = 0; i < singles.length; i++) {
276			layer = singles[i];
277
278			// Remove from previous group first.
279			this._removeFromOtherGroupsOrMap(layer);
280
281			this._layers[L.stamp(layer)] = layer;
282			layer._mcgLayerSupportGroup = this;
283		}
284
285		return separated;
286	},
287
288	_separateSingleFromGroupLayers: function (inputLayers, output) {
289		var groups = output.groups,
290		    singles = output.singles,
291		    isArray = L.Util.isArray,
292		    layer;
293
294		for (var i = 0; i < inputLayers.length; i++) {
295			layer = inputLayers[i];
296
297			if (layer instanceof L.LayerGroup) {
298				groups.push(layer);
299				this._separateSingleFromGroupLayers(layer.getLayers(), output);
300				continue;
301			} else if (isArray(layer)) {
302				this._separateSingleFromGroupLayers(layer, output);
303				continue;
304			}
305
306			singles.push(layer);
307		}
308
309		return output;
310	},
311
312	// Recruit the LayerGroup as a proxy, so that any layer that is added
313	// to / removed from that group later on is also added to / removed from
314	// this group.
315	// Check in and addition of already contained markers must be taken care
316	// of externally.
317	_recruitLayerGroupAsProxy: function (layerGroup) {
318		var otherMcgLayerSupportGroup = layerGroup._proxyMcgLayerSupportGroup;
319
320		// If it is not yet in this group, remove it from previous group
321		// or from map.
322		if (otherMcgLayerSupportGroup) {
323			if (otherMcgLayerSupportGroup === this) {
324				return;
325			}
326			// Remove from previous Layer Support group first.
327			// It will also be removed from map with child layers.
328			otherMcgLayerSupportGroup.checkOut(layerGroup);
329		} else {
330			this._removeFromOwnMap(layerGroup);
331		}
332
333		layerGroup._proxyMcgLayerSupportGroup = this;
334		layerGroup._originalAddLayer =
335			layerGroup._originalAddLayer || layerGroup.addLayer;
336		layerGroup._originalRemoveLayer =
337			layerGroup._originalRemoveLayer || layerGroup.removeLayer;
338		layerGroup._originalOnAdd =
339				layerGroup._originalOnAdd || layerGroup.onAdd;
340		layerGroup._originalOnRemove =
341				layerGroup._originalOnRemove || layerGroup.onRemove;
342		L.extend(layerGroup, _proxyLayerGroup);
343	},
344
345	// Restore the normal LayerGroup behaviour.
346	// Removal and check out of contained markers must be taken care of externally.
347	_dismissProxyLayerGroup: function (layerGroup) {
348		if (layerGroup._proxyMcgLayerSupportGroup === undefined ||
349			layerGroup._proxyMcgLayerSupportGroup !== this) {
350
351			return;
352		}
353
354		delete layerGroup._proxyMcgLayerSupportGroup;
355		layerGroup.addLayer = layerGroup._originalAddLayer;
356		layerGroup.removeLayer = layerGroup._originalRemoveLayer;
357		layerGroup.onAdd = layerGroup._originalOnAdd;
358		layerGroup.onRemove = layerGroup._originalOnRemove;
359
360		var id = L.stamp(layerGroup);
361		delete this._proxyLayerGroups[id];
362		delete this._proxyLayerGroupsNeedRemoving[id];
363
364		this._removeFromOwnMap(layerGroup);
365	},
366
367	_removeFromOtherGroupsOrMap: function (layer) {
368		var otherMcgLayerSupportGroup = layer._mcgLayerSupportGroup;
369
370		if (otherMcgLayerSupportGroup) { // It is a Layer Support group.
371			if (otherMcgLayerSupportGroup === this) {
372				return;
373			}
374			otherMcgLayerSupportGroup.checkOut(layer);
375
376		} else if (layer.__parent) { // It is in a normal MCG.
377			layer.__parent._group.removeLayer(layer);
378
379		} else { // It could still be on a map.
380			this._removeFromOwnMap(layer);
381		}
382	},
383
384	// Remove layers that are being checked in, because they can now cluster.
385	_removeFromOwnMap: function (layer) {
386		if (layer._map) {
387			// This correctly fires layerremove event for Layer Groups as well.
388			layer._map.removeLayer(layer);
389		}
390	},
391
392	// In case checked in layers have been added to map whereas map is not redirected.
393	_removePreAddedLayers: function (map) {
394		var layers = this._layers,
395		    toBeReAdded = [],
396		    layer;
397
398		for (var id in layers) {
399			layer = layers[id];
400			if (layer._map) {
401				toBeReAdded.push(layer);
402				map._originalRemoveLayer(layer);
403			}
404		}
405
406		return toBeReAdded;
407	},
408
409	_toArray: function (item) {
410		return L.Util.isArray(item) ? item : [item];
411	}
412
413});
414
415/**
416 * Extends the FeatureGroup by overriding add/removal methods that directly
417 * access the map original methods, bypassing the switch agent.
418 * Used internally in Layer Support for _featureGroup and _nonPointGroup only.
419 * @type {L.FeatureGroup}
420 * @private
421 */
422var _ByPassingFeatureGroup = L.FeatureGroup.extend({
423
424	// Re-implement just to change the map method.
425	addLayer: function (layer) {
426		if (this.hasLayer(layer)) {
427			return this;
428		}
429
430		layer.addEventParent(this);
431
432		var id = L.stamp(layer);
433
434		this._layers[id] = layer;
435
436		if (this._map) {
437			// Use the original map addLayer.
438			this._map._originalAddLayer(layer);
439		}
440
441		return this.fire('layeradd', {layer: layer});
442	},
443
444	// Re-implement just to change the map method.
445	removeLayer: function (layer) {
446		if (!this.hasLayer(layer)) {
447			return this;
448		}
449		if (layer in this._layers) {
450			layer = this._layers[layer];
451		}
452
453		layer.removeEventParent(this);
454
455		var id = L.stamp(layer);
456
457		if (this._map && this._layers[id]) {
458			// Use the original map removeLayer.
459			this._map._originalRemoveLayer(this._layers[id]);
460		}
461
462		delete this._layers[id];
463
464		return this.fire('layerremove', {layer: layer});
465	},
466
467	onAdd: function (map) {
468		this._map = map;
469		// Use the original map addLayer.
470		this.eachLayer(map._originalAddLayer, map);
471	},
472
473	onRemove: function (map) {
474		// Use the original map removeLayer.
475		this.eachLayer(map._originalRemoveLayer, map);
476		this._map = null;
477	}
478
479});
480
481/**
482 * Toolbox to equip LayerGroups recruited as proxy.
483 * @type {{addLayer: Function, removeLayer: Function}}
484 * @private
485 */
486var _proxyLayerGroup = {
487
488	// Re-implement to redirect addLayer to Layer Support group instead of map.
489	addLayer: function (layer) {
490		var id = this.getLayerId(layer);
491
492		this._layers[id] = layer;
493
494		if (this._map) {
495			this._proxyMcgLayerSupportGroup.addLayer(layer);
496		} else {
497			this._proxyMcgLayerSupportGroup.checkIn(layer);
498		}
499
500		return this;
501	},
502
503	// Re-implement to redirect removeLayer to Layer Support group instead of map.
504	removeLayer: function (layer) {
505
506		var id = layer in this._layers ? layer : this.getLayerId(layer);
507
508		this._proxyMcgLayerSupportGroup.removeLayer(layer);
509
510		delete this._layers[id];
511
512		return this;
513	},
514
515	// Make sure it uses addLayers when added to map.
516	onAdd: function () {
517		this._proxyMcgLayerSupportGroup.addLayers(this.getLayers());
518	},
519
520	// Make sure it uses removeLayers when removed from map.
521	onRemove: function () {
522		this._proxyMcgLayerSupportGroup.removeLayers(this.getLayers());
523	}
524
525};
526
527/**
528 * Toolbox to equip the Map with a switch agent that redirects layers
529 * addition/removal to their Layer Support group when defined.
530 * @type {{addLayer: Function, removeLayer: Function}}
531 * @private
532 */
533var _layerSwitchMap = {
534
535	addLayer: function (layer) {
536		if (layer._mcgLayerSupportGroup) {
537			// Use the original MCG addLayer.
538			return layer._mcgLayerSupportGroup._originalAddLayer(layer);
539		}
540
541		return this._originalAddLayer(layer);
542	},
543
544	removeLayer: function (layer) {
545		if (layer._mcgLayerSupportGroup) {
546			// Use the original MCG removeLayer.
547			return layer._mcgLayerSupportGroup._originalRemoveLayer(layer);
548		}
549
550		return this._originalRemoveLayer(layer);
551	}
552
553};
554
555// Supply with a factory for consistency with Leaflet.
556L.markerClusterGroup.layerSupport = function (options) {
557	return new L.MarkerClusterGroup.LayerSupport(options);
558};

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.