PageSourceSearch

https://stonemaiergames.com/wp-content/plugins/wp-google-maps/js/v…/leaflet-map.js?ver=10.1.09%2Bpro-10.1.05

js stonemaiergames.com collected 2026-09-24 15:30:12 UTC 24,791 bytes, 854 lines download raw bytes

1/**
2 * @namespace WPGMZA
3 * @module LeafletMap
4 * @requires WPGMZA.Map
5 * @pro-requires WPGMZA.ProMap
6 */
7jQuery(function($) {
8	
9	var Parent;
10	
11	WPGMZA.LeafletMap = function(element, options)
12	{
13		var self = this;
14		
15		Parent.call(this, element);
16		
17		this.setOptions(options);
18		
19		$(this.element).html("");
20
21		let mapOptions = this.settings.toLeafletViewOptions();
22        mapOptions = mapOptions ? mapOptions : {};
23
24		this.mapType = mapOptions.mapType ? mapOptions.mapType : 'roadmap';
25		this.tileLayers = this.getTileLayers();
26
27        mapOptions.layers = this.tileLayers;
28
29		if(this.customTileMode){
30			mapOptions.crs = L.extend({}, L.CRS.Simple, {
31				scale: (zoom) => {
32					const initialScale = Math.min(
33						1000 / this.customTileDimensions.width,
34						1000 / this.customTileDimensions.height
35					);
36					return initialScale * Math.pow(2, zoom);
37				}
38			});
39
40			if(this.customTileBounds){
41				const mapBounds = L.latLngBounds(this.customTileBounds);
42				if(!mapBounds.contains(mapOptions.center)){
43					/* Starting location is out of bounds */
44					mapOptions.center = mapBounds.getCenter();
45					this.onBoundsChanged();
46				}
47			}
48		}
49
50		mapOptions = this.extendNativeConfig(mapOptions);
51
52        this.leafletMap = L.map($(element)[0], mapOptions);
53
54		function isSettingDisabled(value) {
55			if(value === "yes"){
56				return true;
57			}
58			return (value ? true : false);
59		}
60		
61		/* Gesture Handling */
62		if(!(this.settings.wpgmza_force_greedy_gestures == "greedy" || this.settings.wpgmza_force_greedy_gestures == "yes" || this.settings.wpgmza_force_greedy_gestures == true)){
63			this.gestureOverlay = $("<div class='wpgmza-gesture-overlay'></div>")
64			this.gestureOverlayTimeoutID = null;
65			
66			if(WPGMZA.isTouchDevice()) {
67				/* Touch : Two finger pan for drag events */
68				if(this.leafletMap.dragging){
69					this.leafletMap.dragging.disable();
70
71					this.gestureState = {
72						touches : {},
73						touchCount : 0,
74						midpoint : null,
75						center : null
76					};
77
78					const leafletContainer = this.leafletMap.getContainer();
79
80					L.DomEvent.on(leafletContainer, 'touchstart', (event) => {
81						Array.from(event.touches).forEach((touch) => {
82							this.gestureState.touches[touch.identifier] = {
83								x : touch.clientX,
84								y : touch.clientY
85							};
86						});
87
88						this.gestureState.touchCount = Object.keys(this.gestureState.touches).length;
89						if(this.gestureState.touchCount === 2){
90							/* Two finger pan, track the gesture event for panning */
91							L.DomEvent.preventDefault(event);
92
93							let touches = {
94								a : event.touches[0],
95								b : event.touches[1]
96							};
97
98							this.gestureState.midpoint = L.point(
99								(touches.a.clientX + touches.b.clientX) / 2,
100								(touches.a.clientY + touches.b.clientY) / 2
101							);
102
103							this.gestureState.center = this.leafletMap.getCenter();
104						} else if(this.gestureState.touchCount === 1){
105							/* If one touch, show the notice, if more we don't do anything */
106							this.showGestureOverlay();
107						}
108					});
109
110					L.DomEvent.on(leafletContainer, 'touchmove', (event) => {
111						if(this.gestureState.touchCount === 2 && event.touches.length === 2){
112							L.DomEvent.preventDefault(event);
113
114							let touches = {
115								a : event.touches[0],
116								b : event.touches[1]
117							};
118
119							const midpoint = L.point(
120								(touches.a.clientX + touches.b.clientX) / 2,
121								(touches.a.clientY + touches.b.clientY) / 2
122							);
123
124							const delta = {
125								x : midpoint.x - this.gestureState.midpoint.x,
126								y : midpoint.y - this.gestureState.midpoint.y
127							};
128
129							const mapCenterPoint = this.leafletMap.latLngToContainerPoint(this.gestureState.center);
130
131							this.leafletMap.panTo(
132								this.leafletMap.containerPointToLatLng(
133									L.point(
134										mapCenterPoint.x - delta.x,
135										mapCenterPoint.y - delta.y
136									)
137								),
138								{
139									animate : false
140								}
141							);
142						}
143					});
144
145					L.DomEvent.on(leafletContainer, 'touchend', (event) => {
146						Array.from(event.changedTouches).forEach((touch) => {
147							delete this.gestureState.touches[touch.identifier];
148						});
149
150						if(Object.keys(this.gestureState.touches).length < 2){
151							this.gestureState.midpoint = null;
152							this.gestureState.center = null;
153						}
154					});
155
156					L.DomEvent.on(leafletContainer, 'touchcancel', (event) => {
157						this.gestureState.touches = {};
158						this.gestureState.midpoint = null;
159						this.gestureState.center = null;
160					});
161
162					this.gestureOverlay.text(WPGMZA.localized_strings.use_two_fingers);
163				}
164			} else {
165				/* Desktop : Require CTLR or CMD + Scroll to zoom, show overlay if not */
166				if(this.leafletMap.scrollWheelZoom){
167					this.leafletMap.scrollWheelZoom.disable();
168
169					const leafletContainer = this.leafletMap.getContainer();
170					L.DomEvent.on(leafletContainer, 'wheel', (event) => {
171						L.DomEvent.preventDefault(event);
172
173						if(event.ctrlKey || event.metaKey){
174							const delta = L.DomEvent.getWheelDelta(event);
175							this.leafletMap.setZoom(this.leafletMap.getZoom() + (delta > 0 ? 1 : -1));
176						} else {
177							this.showGestureOverlay();
178						}
179					});
180
181					let getstureString = WPGMZA.localized_strings.use_ctrl_scroll_to_zoom;
182					if(WPGMZA.isDeviceiOS()){
183						getstureString = WPGMZA.localized_strings.use_ctrl_scroll_to_zoom_ios;
184					}
185					
186					this.gestureOverlay.text(getstureString);
187				}
188			}
189		}
190		
191		/* Layer control */
192		const multiLayerConfig = this.settings.hasMutlilayerTileServer();
193		if(multiLayerConfig && !this.customTileMode){
194			/* This map has more than one layer in it's tile server configuration */
195
196			if(!isSettingDisabled(WPGMZA.settings.wpgmza_settings_map_type)){
197				this.addMapTypeControl(multiLayerConfig);
198			}
199		}
200
201		/* Fullscreen Controller */
202		if(!isSettingDisabled(WPGMZA.settings.wpgmza_settings_map_full_screen_control)){
203			this.addFullscreenControl();
204		}
205
206		/* Scale Control */
207		if(this.settings.enable_scale_control){
208			this.enableScaleControl(true);
209		}
210
211		/* Click listener */
212		this.leafletMap.on('click', (event) => {
213			this.dispatchEvent({
214				type: "click", 
215				map: this, 
216				latLng : {
217					lat : event.latlng.lat, 
218					lng : event.latlng.lng
219				}
220			});
221		})
222		
223		/* Drag Start */
224		this.leafletMap.on("movestart", (event) => {
225			this.isBeingDragged = true;
226		});
227		
228		/* Drag End */
229		this.leafletMap.on("moveend", (event) => {
230			// this.wrapLongitude();
231			
232			if(this.isBeingDragged){
233				this.dispatchEvent("dragend");
234				this.isBeingDragged = false;
235			}
236			this.onIdle();
237		});
238		
239		/* Zoom Event */
240		this.leafletMap.on('zoomend', (event) => {
241			this.dispatchEvent("zoom_changed");
242			this.dispatchEvent("zoomchanged");
243			setTimeout(() => {
244				this.onIdle();
245			}, 10);
246		});
247		
248		/* Bounds change */
249		this.leafletMap.on("move", () => {
250			this.onBoundsChanged();
251		});
252
253		this.onBoundsChanged();
254		
255		/* Right click listener */
256		this.leafletMap.on('click contextmenu', (event) => {
257			let isRight;
258			
259			if("which" in event.originalEvent)
260				isRight = event.originalEvent.which == 3;
261			else if("button" in event.originalEvent)
262				isRight = event.originalEvent.button == 2;
263			
264			if(event.originalEvent.which == 1 || event.originalEvent.button == 1){
265				if(this.isBeingDragged){
266					return;
267				}
268			}
269			
270			if(!isRight){
271				return;
272			}
273			
274			return this.onRightClick(event);
275		});
276		
277		// Dispatch event
278		if(!WPGMZA.isProVersion()) {
279			this.trigger("init");
280			
281			this.dispatchEvent("created");
282			WPGMZA.events.dispatchEvent({type: "mapcreated", map: this});
283			
284			// Legacy event
285			$(this.element).trigger("wpgooglemaps_loaded");
286		}
287
288		if(this.innerStack && this.innerStack.length > 0){
289			/* Disable inner stack components from allowing clicks through to the map surface */
290			this.innerStack.each((index, element) => {
291				L.DomEvent.disableClickPropagation(element);
292				L.DomEvent.disableScrollPropagation(element);
293				L.DomEvent.on(element, 'mousedown', L.DomEvent.stopPropagation);
294			});
295		}
296
297		/* Force a Leaflet origin recalc after the page has actually painted.
298		 * `L.map(...)` above snapshots the container's dimensions at construction
299		 * time and computes its internal pixel origin from them; if the page
300		 * hasn't finished its initial layout (web fonts still settling, parent
301		 * flex/grid widths still resolving, a `display:none` ancestor that just
302		 * became visible, etc.) the snapshot is wrong and every marker placed
303		 * thereafter is offset against that bad origin.
304		 *
305		 * Double-nested requestAnimationFrame is the standard "after first
306		 * paint" signal: the outer rAF fires before the next paint, the inner
307		 * rAF guarantees the browser has actually painted at least once before
308		 * we measure. Leaflet's invalidateSize() compares old vs new dimensions
309		 * internally and bails when nothing changed, so this is safe to fire
310		 * unconditionally — the happy-path cost is one size measurement. */
311		if(typeof window !== 'undefined' && typeof window.requestAnimationFrame === 'function'){
312			window.requestAnimationFrame(() => {
313				window.requestAnimationFrame(() => {
314					if(this.leafletMap && typeof this.leafletMap.invalidateSize === 'function'){
315						this.leafletMap.invalidateSize();
316					}
317				});
318			});
319		}
320	}
321
322	if(WPGMZA.isProVersion())
323		Parent = WPGMZA.ProMap;
324	else
325		Parent = WPGMZA.Map;
326	
327	WPGMZA.LeafletMap.prototype = Object.create(Parent.prototype);
328	WPGMZA.LeafletMap.prototype.constructor = WPGMZA.LeafletMap;
329	
330	WPGMZA.LeafletMap.prototype.getTileLayers = function(){
331		let url = WPGMZA.settings.tile_server_url ? WPGMZA.settings.tile_server_url : "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png";
332		let tileKey = WPGMZA.settings.leaflet_api_key ? WPGMZA.settings.leaflet_api_key : false;
333
334		switch(WPGMZA.settings.engine){
335			case 'leaflet-azure':
336				/* Remap to Azure settings */
337				url = WPGMZA.settings.tile_server_url_leaflet_azure ? WPGMZA.settings.tile_server_url_leaflet_azure : url;
338				tileKey = WPGMZA.settings.wpgmza_leaflet_azure_key ? WPGMZA.settings.wpgmza_leaflet_azure_key : tileKey;
339				break;
340			case 'leaflet-stadia':
341				/* Remap to Stadia settings */
342				url = WPGMZA.settings.tile_server_url_leaflet_stadia ? WPGMZA.settings.tile_server_url_leaflet_stadia : url;
343				tileKey = WPGMZA.settings.wpgmza_leaflet_stadia_key ? WPGMZA.settings.wpgmza_leaflet_stadia_key : tileKey;
344				break;
345			case 'leaflet-maptiler':
346				/* Remap to Maptiler settings */
347				url = WPGMZA.settings.tile_server_url_leaflet_maptiler ? WPGMZA.settings.tile_server_url_leaflet_maptiler : url;
348				tileKey = WPGMZA.settings.wpgmza_leaflet_maptiler_key ? WPGMZA.settings.wpgmza_leaflet_maptiler_key : tileKey;
349				break;
350			case 'leaflet-locationiq':
351				/* Remap to LocationIQ settings */
352				url = WPGMZA.settings.tile_server_url_leaflet_locationiq ? WPGMZA.settings.tile_server_url_leaflet_locationiq : url;
353				tileKey = WPGMZA.settings.wpgmza_leaflet_locationiq_key ? WPGMZA.settings.wpgmza_leaflet_locationiq_key : tileKey;
354				break;
355			case 'leaflet-zerocost':
356				/* Remap to zerocost settings */
357				url = WPGMZA.settings.tile_server_url_leaflet_zerocost ? WPGMZA.settings.tile_server_url_leaflet_zerocost : url;
358				break;
359		}
360
361		const config = this.settings.configureTileServer(url, {
362			authentication : tileKey, 
363			preferServerGlobals : true,
364			map : this
365		});
366
367		if(config && config.url){
368			if(config.type && config.type === 'vector' && typeof L.maplibreGL !== 'undefined'){
369				/* Vector base layer, so we use MapLibreGL */
370				let mapLibreOptions = {style :  config.url};
371				if(config.options){
372					for(let key in config.options){
373						if(key === 'url'){
374							continue;
375						}
376
377						mapLibreOptions[key] = config.options[key];
378					};
379				}
380				
381				return [L.maplibreGL(mapLibreOptions)];
382			} else if (config.type && config.type === 'custom'){
383				this.customTileDimensions = {width : config.custom.width, height : config.custom.height};
384				this.customTileBounds = [[0,0], [this.customTileDimensions.height, this.customTileDimensions.width]];
385				this.customTileMode = true;
386				return [L.imageOverlay(config.url, this.customTileBounds, {
387					attribution: config.custom.attribution ? config.custom.attribution : '©'
388				})];
389			}
390
391			const layers = [];
392
393			if(config.dependencies){
394				for(let dependency of config.dependencies){
395					layers.push(new L.tileLayer(dependency.url, config.options ? config.options : {}));
396				}
397			}
398
399			layers.push(new L.tileLayer(config.url, config.options ? config.options : {}));
400			return layers;
401		} 
402
403		/* Fallback */
404		return [new L.tileLayer(url, {})];
405	}
406	
407	WPGMZA.LeafletMap.prototype.wrapLongitude = function(){
408		let center = this.leafletMap.getCenter();
409		if(center.lng >= -180 && center.lng <= 180){
410			return;
411		}
412		
413		center.lng = center.lng - 360 * Math.floor(center.lng / 360);
414		
415		if(center.lng > 180){
416			center.lng -= 360;
417		}
418		
419		this.setCenter(center);
420	}
421	
422	WPGMZA.LeafletMap.prototype.getCenter = function(){
423		const center = this.leafletMap.getCenter();
424		return {
425			lat: center.lat,
426			lng: center.lng
427		};
428	}
429	
430	WPGMZA.LeafletMap.prototype.setCenter = function(latLng) {
431		WPGMZA.Map.prototype.setCenter.call(this, latLng);
432		
433		this.leafletMap.panTo(L.latLng({lat : latLng.lat, lng : latLng.lng}), {animate : false});
434		// this.wrapLongitude();
435
436		this.onBoundsChanged();
437	}
438	
439	WPGMZA.LeafletMap.prototype.getBounds = function() {
440		let bounds = this.leafletMap.getBounds();
441		let nativeBounds = new WPGMZA.LatLngBounds();
442		
443		nativeBounds.north = bounds.getNorth();
444		nativeBounds.south = bounds.getSouth();
445		
446		nativeBounds.west = bounds.getWest();
447		nativeBounds.east = bounds.getEast();
448		
449		return nativeBounds;
450	}
451	
452	/**
453	 * Fit to given boundaries
454	 * @return void
455	 */
456	WPGMZA.LeafletMap.prototype.fitBounds = function(southWest, northEast) {
457		if(southWest instanceof WPGMZA.LatLng){
458			southWest = {lat: southWest.lat, lng: southWest.lng};
459		}
460
461		if(northEast instanceof WPGMZA.LatLng){
462			northEast = {lat: northEast.lat, lng: northEast.lng};
463		} else if(southWest instanceof WPGMZA.LatLngBounds) {
464			var bounds = southWest;
465			
466			southWest = {
467				lat: bounds.south,
468				lng: bounds.west
469			};
470			
471			northEast = {
472				lat: bounds.north,
473				lng: bounds.east
474			};
475		}
476		
477		const leafletBounds = L.latLngBounds(
478			L.latLng({lat : northEast.lat, lng : northEast.lng}), 
479			L.latLng({lat : southWest.lat, lng : southWest.lng})
480		);
481
482		this.leafletMap.fitBounds(leafletBounds, { padding : [60, 60]});
483	}
484	
485	WPGMZA.LeafletMap.prototype.panTo = function(latLng, zoom) {
486		if(arguments.length > 1){
487			this.leafletMap.flyTo(L.latLng({lat: latLng.lat, lng: latLng.lng}), parseInt(zoom));
488		} else {
489			this.leafletMap.flyTo(L.latLng({lat: latLng.lat, lng: latLng.lng}));
490		}
491	}
492	
493	WPGMZA.LeafletMap.prototype.getZoom = function() {
494		return Math.round( this.leafletMap.getZoom() );
495	}
496	
497	WPGMZA.LeafletMap.prototype.setZoom = function(value) {
498		this.leafletMap.setZoom(value);
499	}
500	
501	WPGMZA.LeafletMap.prototype.getMinZoom = function() {
502		return this.leafletMap.getMinZoom();
503	}
504	
505	WPGMZA.LeafletMap.prototype.setMinZoom = function(value) {
506		this.leafletMap.setMinZoom(value);
507	}
508	
509	WPGMZA.LeafletMap.prototype.getMaxZoom = function() {
510		return this.leafletMap.getMaxZoom();
511	}
512	
513	WPGMZA.LeafletMap.prototype.setMaxZoom = function(value) {
514		this.leafletMap.setMaxZoom(value);
515	}
516
517	WPGMZA.LeafletMap.prototype.setMapType = function(type){
518		if(this.mapType !== type){
519			this.mapType = type;
520
521			if(this.tileLayers){
522				for(let layer of this.tileLayers){
523					if(this.leafletMap.hasLayer(layer)){
524						this.leafletMap.removeLayer(layer);
525					}
526				}
527			}
528
529			this.tileLayers = this.getTileLayers();
530
531			for(let layer of this.tileLayers){
532				this.leafletMap.addLayer(layer);
533			}
534
535			$(this.element).find('.leaflet-layer-button[data-map-type]').removeClass('selected');
536			$(this.element).find('.leaflet-layer-button[data-map-type="' + type + '"]').addClass('selected');
537		}	
538	}
539
540	WPGMZA.LeafletMap.prototype.getMapType = function(){
541		return this.mapType ? this.mapType : 'roadmap';
542	}
543	
544	WPGMZA.LeafletMap.prototype.setOptions = function(options) {
545		Parent.prototype.setOptions.call(this, options);
546		
547		if(!this.leafletMap){
548			/* Hasn't been initialized yet */
549			return;
550		}
551
552		/* Leaflet doesn't allow a bulk setter like other engines, we need to manage this internally */
553		let mapOptions = this.settings.toLeafletViewOptions();
554		for (const key in mapOptions) {
555			if (!mapOptions.hasOwnProperty(key)) {
556				continue;
557			}
558
559        	const value = options[key];
560
561			switch (key) {
562				case 'zoomControl':
563					if (value === false && this.leafletMap.zoomControl) {
564						this.leafletMap.removeControl(this.leafletMap.zoomControl);
565					} else if (value === true && !this.leafletMap.zoomControl) {
566						this.leafletMap.addControl(L.control.zoom());
567					}
568					break;
569				case 'dragging':
570				case 'doubleClickZoom':
571				case 'scrollWheelZoom':
572				case 'boxZoom':
573				case 'keyboard':
574				case 'tap': 
575				case 'touchZoom':
576					if (this.leafletMap[key]) {
577						if (value === true) {
578							this.leafletMap[key].enable();
579						} else {
580							this.leafletMap[key].disable();
581						}
582					}
583					break;
584				case 'minZoom':
585					this.setMinZoom(value);
586					break;
587				case 'maxZoom':
588					this.setMaxZoom(value);
589					break;
590				default:
591					break;
592			}
593		}
594	}
595	
596	/**
597	 * TODO: Consider moving all these functions to their respective classes, same on google map (DO IT!!! It's very misleading having them here)
598	 */
599	WPGMZA.LeafletMap.prototype.addMarker = function(marker) {
600		marker.leafletMarker.addTo(this.leafletMap);
601		Parent.prototype.addMarker.call(this, marker);
602	}
603	
604	WPGMZA.LeafletMap.prototype.removeMarker = function(marker) {
605		marker.leafletMarker.removeFrom(this.leafletMap);
606		Parent.prototype.removeMarker.call(this, marker);
607	}
608	
609	WPGMZA.LeafletMap.prototype.addPolygon = function(polygon) {
610		polygon.leafletFeature.addTo(this.leafletMap);
611		Parent.prototype.addPolygon.call(this, polygon);
612	}
613	
614	WPGMZA.LeafletMap.prototype.removePolygon = function(polygon) {
615		polygon.leafletFeature.remove();
616		Parent.prototype.removePolygon.call(this, polygon);
617	}
618	
619	WPGMZA.LeafletMap.prototype.addPolyline = function(polyline) {
620		polyline.leafletFeature.addTo(this.leafletMap);
621		Parent.prototype.addPolyline.call(this, polyline);
622	}
623	
624	WPGMZA.LeafletMap.prototype.removePolyline = function(polyline) {
625		polyline.leafletFeature.remove();
626		Parent.prototype.removePolyline.call(this, polyline);
627	}
628	
629	WPGMZA.LeafletMap.prototype.addCircle = function(circle) {
630		circle.leafletFeature.addTo(this.leafletMap);
631		Parent.prototype.addCircle.call(this, circle);
632	}
633	
634	WPGMZA.LeafletMap.prototype.removeCircle = function(circle) {
635		circle.leafletFeature.remove();
636		Parent.prototype.removeCircle.call(this, circle);
637	}
638	
639	WPGMZA.LeafletMap.prototype.addRectangle = function(rectangle) {
640		rectangle.leafletFeature.addTo(this.leafletMap);
641		Parent.prototype.addRectangle.call(this, rectangle);
642	}
643	
644	WPGMZA.LeafletMap.prototype.removeRectangle = function(rectangle) {
645		rectangle.leafletFeature.remove();
646		Parent.prototype.removeRectangle.call(this, rectangle);
647	}
648	
649	WPGMZA.LeafletMap.prototype.pixelsToLatLng = function(x, y) {
650		if(y == undefined) {
651			if("x" in x && "y" in x) {
652				y = x.y;
653				x = x.x;
654			} else {
655				console.warn("Y coordinate undefined in pixelsToLatLng (did you mean to pass 2 arguments?)");
656			}
657		}
658		
659		let coord = this.leafletMap.containerPointToLatLng(L.point(x, y));
660		if(!coord){
661			return {
662				x: null,
663				y: null
664			};
665		}
666		
667		return {
668			lat: coord.lat,
669			lng: coord.lng
670		};
671	}
672	
673	WPGMZA.LeafletMap.prototype.latLngToPixels = function(latLng) {
674		let pixel = this.leafletMap.latLngToContainerPoint(latLng);
675		if(!pixel){
676			return {
677				x: null,
678				y: null
679			};
680		}
681		
682		return {
683			x: pixel.x,
684			y: pixel.y
685		};
686	}
687	
688	WPGMZA.LeafletMap.prototype.showGestureOverlay = function() {
689		clearTimeout(this.gestureOverlayTimeoutID);
690		
691		$(this.gestureOverlay).stop().animate({opacity: "100"});
692		$(this.element).append(this.gestureOverlay);
693		
694		$(this.gestureOverlay).css({
695			"line-height":	$(this.element).height() + "px",
696			"opacity":		"1.0"
697		});
698
699		$(this.gestureOverlay).show();
700		
701		this.gestureOverlayTimeoutID = setTimeout(() => {
702			this.gestureOverlay.fadeOut(500);
703		}, 1000);
704	}
705	
706	WPGMZA.LeafletMap.prototype.onRightClick = function(event) {
707		this.trigger({type: "rightclick", latLng: event.latlng});
708
709		// Legacy event compatibility
710		$(this.element).trigger({type: "rightclick", latLng: event.latlng});
711		
712		// Prevent menu
713		event.originalEvent.preventDefault();
714		return false;
715	}
716
717	WPGMZA.LeafletMap.prototype.addFullscreenControl = function(){
718		if(this.leafletMap){
719			const fullscreenController = L.control({position : 'topright'});
720			fullscreenController.onAdd = (map) => {
721				const container = L.DomUtil.create('div');
722				container.classList.add('leaflet-bar');
723				container.classList.add('leaflet-control');
724				container.classList.add('leaflet-control-fullscreen');
725
726				const button = L.DomUtil.create('a');
727				button.classList.add('leaflet-control-button');
728				button.classList.add('leaflet-fullscreen-button');
729				button.href = '#';
730
731				button.setAttribute('aria-label', "Fullscreen");
732
733				const corners = ['tl' , 'tr' , 'bl', 'br'];
734				for(let corner of corners){
735					const element = L.DomUtil.create('span');
736					element.classList.add('leaflet-fullscreen-corner');
737					element.classList.add('leaflet-fullscreen-corner-' + corner);
738					button.append(element);
739				}
740				
741				container.append(button);
742
743				L.DomEvent.on(button, 'click', (event) => {
744					event.preventDefault();
745					if(document.fullscreenElement){
746						document.exitFullscreen();
747					} else {
748						const mapContainer = this.element;
749						if (mapContainer.requestFullscreen) {
750							mapContainer.requestFullscreen();
751						} else if (mapContainer.mozRequestFullScreen) {
752							mapContainer.mozRequestFullScreen();
753						} else if (mapContainer.webkitRequestFullscreen) {
754							mapContainer.webkitRequestFullscreen();
755						} else if (mapContainer.msRequestFullscreen) {
756							mapContainer.msRequestFullscreen();
757						}
758					}
759				});
760
761				return container;
762			}
763
764			fullscreenController.addTo(this.leafletMap);
765		}
766	}
767
768	WPGMZA.LeafletMap.prototype.addMapTypeControl = function(config){
769		if(this.leafletMap && config && config.layers && config.layers.length >= 2){
770			const layerController = L.control({position : 'topright'});
771			layerController.onAdd = (map) => {
772				const container = L.DomUtil.create('div');
773				container.classList.add('leaflet-bar');
774				container.classList.add('leaflet-control');
775				container.classList.add('leaflet-control-layers');
776
777				for(let index in config.layers){
778					const layer = config.layers[index];
779
780					let label = WPGMZA.localized_strings[`map_type_${layer}`] ? WPGMZA.localized_strings[`map_type_${layer}`] : WPGMZA.capitalizeWords(layer);
781
782					const button = L.DomUtil.create('a');
783					button.innerText = label;
784					button.classList.add('leaflet-control-button');
785					button.classList.add('leaflet-layer-button');
786					button.href = '#';
787
788					button.setAttribute('data-map-type', layer);
789
790					if(config.active && config.active === layer){
791						button.classList.add('selected');
792					}
793
794					container.append(button);
795
796					L.DomEvent.on(button, 'click', (event) => {
797						event.preventDefault();
798						this.setMapType(layer);
799					});
800				}
801				
802
803				return container;
804			}
805
806			layerController.addTo(this.leafletMap);
807		}
808	}
809
810	/**
811	 * Enables / disables the scale control bar
812	 * @param enable boolean, enable or not
813	 * @return void
814	 */
815	WPGMZA.LeafletMap.prototype.enableScaleControl = function(enable)
816	{
817		if(!this.leafletMap)
818			return;
819
820		if(this.scaleControl){
821			this.scaleControl.remove();
822			this.scaleControl = null;
823		}
824
825		if(enable){
826			const imperial = (this.settings.store_locator_distance == WPGMZA.Distance.MILES);
827
828			this.scaleControl = L.control.scale({
829				imperial: imperial,
830				metric: !imperial,
831				position: 'bottomleft'
832			}).addTo(this.leafletMap);
833		}
834	}
835
836	WPGMZA.LeafletMap.prototype.getLayerGroupPane = function(pane, layer, basePane){
837		basePane = typeof basePane === 'undefined' || !basePane ? 'overlayPane' : basePane;
838		if(this.leafletMap){
839			let nativePane = this.leafletMap.getPane(`${pane}${layer}`);
840			if(!nativePane){
841				nativePane = this.leafletMap.createPane(`${pane}${layer}`, this.leafletMap.getPane(basePane)); 
842				nativePane.style.zIndex = layer;    
843			} 
844
845			return `${pane}${layer}`;
846		}
847		return false;
848	}
849
850	WPGMZA.LeafletMap.prototype.resetBounds = function() {
851		var latlng = new WPGMZA.LatLng(this.settings.map_start_lat, this.settings.map_start_lng);
852		this.panTo(latlng, this.settings.map_start_zoom);
853	}
854});

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.