@wikicasa-dev/utilities 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/dist/index.d.ts +1 -0
  2. package/dist/utilities.cjs +4 -4
  3. package/dist/utilities.iife.js +2 -2
  4. package/dist/utilities.mjs +57 -51
  5. package/dist/utils/DateUtils.d.ts +1 -0
  6. package/package.json +2 -5
  7. package/src/custom/constants.ts +3 -0
  8. package/src/custom/icons.ts +63 -0
  9. package/src/custom/leaflet_map.ts +946 -0
  10. package/src/index.ts +173 -0
  11. package/src/services/agencyAPI.ts +105 -0
  12. package/src/services/geographyAPI.ts +129 -0
  13. package/src/services/insightsAPI.ts +20 -0
  14. package/src/services/mailAPI.ts +89 -0
  15. package/src/services/placesAPI.ts +72 -0
  16. package/src/services/portfolioCustomerAPI.ts +16 -0
  17. package/src/services/publicUserAPI.ts +216 -0
  18. package/src/services/realEstateAPI.ts +133 -0
  19. package/src/services/requestAPI.ts +40 -0
  20. package/src/services/servicesUtils.ts +27 -0
  21. package/src/services/statisticsAPI.ts +84 -0
  22. package/src/services/valuationAPI.ts +45 -0
  23. package/src/services/wikicasaPro.ts +25 -0
  24. package/src/utils/AppRedirectUtils.ts +26 -0
  25. package/src/utils/ArrayUtils.ts +2 -0
  26. package/src/utils/ColorUtils.ts +11 -0
  27. package/src/utils/CookieUtils.ts +43 -0
  28. package/src/utils/CurrencyUtils.ts +18 -0
  29. package/src/utils/DOMUtils.ts +28 -0
  30. package/src/utils/DateUtils.ts +9 -0
  31. package/src/utils/DeviceDetectionUtils.ts +17 -0
  32. package/src/utils/EmailUtils.ts +45 -0
  33. package/src/utils/FavoriteUtils.ts +19 -0
  34. package/src/utils/FunctionUtils.ts +29 -0
  35. package/src/utils/GAEvents.ts +414 -0
  36. package/src/utils/GAutocompleteUtils.ts +70 -0
  37. package/src/utils/GenericUtils.ts +37 -0
  38. package/src/utils/LazyLoadingBg.ts +18 -0
  39. package/src/utils/MapUtils.ts +118 -0
  40. package/src/utils/NumberUtils.ts +90 -0
  41. package/src/utils/ObjectUtils.ts +34 -0
  42. package/src/utils/ObserverUtils.ts +32 -0
  43. package/src/utils/PermissionUtils.ts +41 -0
  44. package/src/utils/RESB_UrlBuilder.ts +99 -0
  45. package/src/utils/RequestUtils.ts +20 -0
  46. package/src/utils/StringUtils.ts +67 -0
  47. package/src/utils/URLBuilderUtils.ts +21 -0
  48. package/src/utils/URLPagesFactory.ts +20 -0
  49. package/src/vite-env.d.ts +1 -0
  50. package/tsconfig.json +38 -0
  51. package/vite.config.ts +42 -0
@@ -0,0 +1,946 @@
1
+ import { createCustomEvent } from "@utils/GenericUtils";
2
+ import { MAP_TILER_STYLE, MAP_TILER_TOKEN } from "./constants";
3
+ import { SVG } from "./icons";
4
+
5
+ import "core-js/modules/es.array.iterator";
6
+ import type {
7
+ LatLng,
8
+ MarkerCluster,
9
+ Popup,
10
+ Marker,
11
+ Polyline,
12
+ MarkerClusterGroup,
13
+ LayerGroup,
14
+ LeafletEvent,
15
+ FitBoundsOptions,
16
+ } from "leaflet";
17
+
18
+ declare global {
19
+ interface Window {
20
+ _cdn: string;
21
+ touch: boolean;
22
+ }
23
+ }
24
+
25
+ let FreeDraw: any;
26
+ let L: Record<string, any>;
27
+
28
+ export const MAX_ZOOM = 18;
29
+
30
+ const defaultDrawingOptions = (
31
+ COLORS: Record<string, any>
32
+ ): Record<string, any> => ({
33
+ guidelineDistance: 15,
34
+ showArea: true,
35
+ fillColor: COLORS.lightPrimary,
36
+ fillOpacity: 0.75,
37
+ color: COLORS.primary,
38
+ opacity: 1,
39
+ weight: 3,
40
+ zIndex: 1,
41
+ stroke: true,
42
+ fill: true,
43
+ clickable: true,
44
+ });
45
+
46
+ let drawingOptions: Record<string, any>;
47
+
48
+ /*
49
+ const clusterStyles = [
50
+ {
51
+ textColor: "white",
52
+ url: "/_ui/img/map/marker24x24.png",
53
+ height: 24,
54
+ width: 24
55
+ },
56
+ {
57
+ textColor: "white",
58
+ url: "/_ui/img/map/marker36x36.png",
59
+ height: 36,
60
+ width: 36
61
+ },
62
+ {
63
+ textColor: "white",
64
+ url: "/_ui/img/map/marker48x48.png",
65
+ height: 48,
66
+ width: 48,
67
+ }
68
+ ];
69
+ */
70
+
71
+ interface LMap extends L.Map {
72
+ touchExtend: Record<string, any>;
73
+ }
74
+
75
+ /**
76
+ * @author Andrea Moraglia
77
+ */
78
+ export default class {
79
+ private markers: Map<number, L.Marker>;
80
+ private callbacks: Array<any>;
81
+ private initialized: boolean;
82
+ private markerClusterer: MarkerClusterGroup;
83
+ private clusterHightlight: any;
84
+ private map: LMap;
85
+ private mapContainer: HTMLElement;
86
+ private infowindow: Popup;
87
+ private infowindowCarousel: Popup;
88
+ private freeDraw: any;
89
+ private shapeLayer: LayerGroup;
90
+ private config: {
91
+ cluster: boolean;
92
+ search: boolean;
93
+ center: Array<number>;
94
+ drawing: boolean;
95
+ zoom: number;
96
+ };
97
+ private drawHandler: L.Handler;
98
+ private spinner: HTMLDivElement;
99
+ private buttonsWrapper: JQuery<HTMLElement>;
100
+ private spinnerIcon: HTMLDivElement;
101
+ private drawing: boolean;
102
+ // @ts-ignore
103
+ private search: any;
104
+
105
+ constructor() {
106
+ this.callbacks = [];
107
+ this.markers = new Map<number, L.Marker>();
108
+ this.initialized = false;
109
+ this.drawing = false;
110
+ }
111
+
112
+ findMarker(id: number): Marker | undefined {
113
+ return this.markers.get(id);
114
+ }
115
+
116
+ findCluster(id: number): Marker | undefined {
117
+ const marker = this.markers.get(id);
118
+
119
+ if (marker) return this.markerClusterer.getVisibleParent(marker);
120
+
121
+ return undefined;
122
+ }
123
+
124
+ highlightCluster(cluster: MarkerCluster): void {
125
+ if (!cluster) return;
126
+
127
+ if (this.clusterHightlight) this.clearHighlight();
128
+
129
+ this.clusterHightlight = cluster;
130
+ this.clusterHightlight._icon.classList.add("marker-cluster-selected");
131
+ }
132
+
133
+ highlightMarker(id: number): void {
134
+ const marker = this.markers.get(id);
135
+
136
+ if (!marker) return;
137
+
138
+ this.clusterHightlight = this.markerClusterer.getVisibleParent(marker);
139
+
140
+ if (this.clusterHightlight)
141
+ this.clusterHightlight._icon.classList.add("marker-cluster-selected");
142
+ }
143
+
144
+ clearHighlight(): void {
145
+ if (this.clusterHightlight && this.clusterHightlight._icon)
146
+ this.clusterHightlight._icon.classList.remove("marker-cluster-selected");
147
+ }
148
+
149
+ addMarkerBulk(
150
+ data: Array<Marker>,
151
+ center: L.LatLng | null,
152
+ limit: number,
153
+ icon: string = "/_ui/img/map/mrkr-wikicasa.png"
154
+ ): void {
155
+ const myIcon = L.icon({
156
+ iconUrl: icon,
157
+ iconSize: [27, 34],
158
+ iconAnchor: [0, 33],
159
+ /* popupAnchor: [-3, -76],
160
+ shadowSize: [68, 95],
161
+ shadowAnchor: [22, 94]*/
162
+ });
163
+
164
+ const bulk: Array<Marker> = [];
165
+
166
+ if (center && !this.validateCoordinate(center.lat, center.lng))
167
+ center = null;
168
+
169
+ const mapRange = limit ? limit : window["_mapRange"] || 10000;
170
+
171
+ for (let i = 0; i < data.length; i++) {
172
+ const item: Record<string, any> = data[i];
173
+ const id = item["id"];
174
+ const position = {
175
+ lat: item["latitude"],
176
+ lng: item["longitude"],
177
+ } as LatLng;
178
+
179
+ if (!center || this.getDistance(center, position) < mapRange) {
180
+ const marker = L.marker(position, { icon: myIcon });
181
+ marker.id = id;
182
+ this.markers.set(id, marker);
183
+
184
+ if (this.markerClusterer) {
185
+ bulk.push(marker);
186
+ } else marker.addTo(this.map);
187
+ }
188
+ }
189
+
190
+ if (bulk.length > 0) this.markerClusterer.addLayers(bulk);
191
+ }
192
+
193
+ addMarker(key: number | null, position: LatLng, icon?: any): void {
194
+ //if (!validateCoordinate(position))
195
+ // return;
196
+
197
+ const defOpts = {
198
+ iconUrl: icon ? icon : `${window["_cdn"]}/_ui/img/Ico/pin-blue.svg`,
199
+ iconSize: [48, 48],
200
+ iconAnchor: [24, 48],
201
+ /* popupAnchor: [-3, -76],
202
+ shadowSize: [68, 95],
203
+ shadowAnchor: [22, 94]*/
204
+ };
205
+
206
+ const iconOpts = $.extend({}, defOpts, icon);
207
+
208
+ const myIcon = L.icon(iconOpts);
209
+
210
+ const marker = L.marker(position, { icon: myIcon });
211
+
212
+ if (key != null) {
213
+ marker.id = key;
214
+ this.markers.set(key, marker);
215
+ }
216
+
217
+ if (this.markerClusterer) {
218
+ this.markerClusterer.addLayer(marker);
219
+ } else {
220
+ marker.addTo(this.map);
221
+ }
222
+ }
223
+
224
+ addCompleteMarker(marker: Marker): void {
225
+ // @ts-ignore
226
+ this.markers.set(marker.id, marker);
227
+
228
+ if (this.markerClusterer) {
229
+ this.markerClusterer.addLayer(marker);
230
+ } else {
231
+ marker.addTo(this.map);
232
+ }
233
+ }
234
+
235
+ removeMarker(id: number): void {
236
+ const marker = this.findMarker(id);
237
+
238
+ if (marker) this.map.removeLayer(marker);
239
+ }
240
+
241
+ getVisibleMarkersId(): Array<number> {
242
+ const visibleIds: Array<number> = [];
243
+ const keys = Object.keys(this.markers);
244
+ const bounds = this.map.getBounds();
245
+
246
+ for (let i = 0; i < keys.length; i++) {
247
+ const key = keys[i];
248
+ const marker = this.findMarker(Number(key));
249
+ if (marker && bounds.contains(marker.getLatLng())) {
250
+ visibleIds.push(Number(key));
251
+ }
252
+ }
253
+
254
+ return visibleIds;
255
+ }
256
+
257
+ initMarkerClusterer(): Promise<unknown> {
258
+ const options = {
259
+ showCoverageOnHover: true,
260
+ spiderfyOnMaxZoom: false,
261
+ spiderLegPolylineOptions: {
262
+ color: drawingOptions.color,
263
+ },
264
+ singleMarkerMode: true,
265
+ };
266
+
267
+ const self = this;
268
+
269
+ return new Promise(
270
+ (
271
+ resolve: (...args: Array<unknown>) => unknown,
272
+ reject: () => unknown
273
+ ) => {
274
+ Promise.all([
275
+ require(/* webpackChunkName: "chunks/leaflet.markercluster" */ "leaflet.markercluster/dist/MarkerCluster.css"),
276
+ import(
277
+ /* webpackChunkName: "chunks/leaflet.markercluster" */ "leaflet.markercluster"
278
+ ),
279
+ ])
280
+ .then(() => {
281
+ self.markerClusterer = L.markerClusterGroup(options);
282
+
283
+ self.map.addLayer(self.markerClusterer);
284
+
285
+ resolve();
286
+ })
287
+ .catch((error: any) => {
288
+ console.error(error);
289
+ reject();
290
+ });
291
+ }
292
+ );
293
+ }
294
+
295
+ detachMarkerClusterer(): void {
296
+ this.map.removeLayer(this.markerClusterer);
297
+ }
298
+
299
+ attachMarkerClusterer(): void {
300
+ this.map.addLayer(this.markerClusterer);
301
+ }
302
+
303
+ disableControls(): void {
304
+ this.map.boxZoom.disable();
305
+ this.map.doubleClickZoom.disable();
306
+ this.map.dragging.disable();
307
+ this.map.keyboard.disable();
308
+ this.map.scrollWheelZoom.disable();
309
+ this.map.touchZoom.disable();
310
+ }
311
+
312
+ enableControls(): void {
313
+ this.map.boxZoom.enable();
314
+ this.map.doubleClickZoom.enable();
315
+ this.map.dragging.enable();
316
+ this.map.keyboard.enable();
317
+ this.map.scrollWheelZoom.enable();
318
+ this.map.touchZoom.enable();
319
+ }
320
+
321
+ setDrawing(): void {
322
+ this.stopDrawing();
323
+
324
+ this.disableControls();
325
+
326
+ if (this.freeDraw) {
327
+ this.freeDraw.mode(FreeDraw.CREATE);
328
+ this.map["touchExtend"].enable();
329
+ }
330
+
331
+ if (this.shapeLayer) {
332
+ this.drawHandler = new L.Draw.Polygon(this.map, drawingOptions);
333
+ this.drawHandler.enable();
334
+ }
335
+
336
+ this.drawing = true;
337
+ }
338
+
339
+ stopDrawing(): void {
340
+ this.enableControls();
341
+
342
+ if (this.freeDraw) {
343
+ this.map["touchExtend"].disable();
344
+ this.freeDraw.cancel();
345
+ this.freeDraw.mode(FreeDraw.EDIT);
346
+ }
347
+
348
+ if (this.drawHandler) this.drawHandler.disable();
349
+
350
+ this.drawing = false;
351
+ }
352
+
353
+ isDrawing(): boolean {
354
+ return this.drawing;
355
+ }
356
+
357
+ initDrawingManager(): Promise<unknown> {
358
+ if (!window["touch"]) {
359
+ return new Promise(
360
+ (
361
+ resolve: (...args: Array<unknown>) => unknown,
362
+ reject: () => unknown
363
+ ) => {
364
+ Promise.all([
365
+ import(
366
+ /* webpackChunkName: "chunks/leaflet.draw" */ "leaflet-draw"
367
+ ),
368
+ require(/* webpackChunkName: "chunks/leaflet.draw" */ "leaflet-draw/dist/leaflet.draw.css"),
369
+ ])
370
+ .then(() => {
371
+ this.shapeLayer = new L.FeatureGroup();
372
+
373
+ this.map.addLayer(this.shapeLayer);
374
+
375
+ this.map.on("draw:created", (e: LeafletEvent) => {
376
+ const polygon = e.layer;
377
+ this.shapeLayer.clearLayers();
378
+ this.shapeLayer.addLayer(polygon);
379
+ polygon.options.editing || (polygon.options.editing = {});
380
+ polygon.editing.enable();
381
+ this.fitBounds(polygon.getBounds());
382
+ });
383
+
384
+ L.drawLocal.draw.handlers.polygon.tooltip = {
385
+ start: "Clicca per iniziare a disegnare il poligono",
386
+ cont: "Clicca per continuare a disegnare il poligono",
387
+ end: "Clicca sul primo punto per chiudere il poligono",
388
+ };
389
+
390
+ resolve();
391
+ })
392
+ .catch((error: string) => {
393
+ console.error(error);
394
+ reject();
395
+ });
396
+ }
397
+ );
398
+ } else {
399
+ return new Promise(
400
+ (
401
+ resolve: (...args: Array<unknown>) => unknown,
402
+ reject: () => unknown
403
+ ) => {
404
+ // @ts-ignore
405
+ import(
406
+ /* webpackChunkName: "chunks/leaflet.freedraw" */ "leaflet-freedraw"
407
+ )
408
+ .then((module: any) => {
409
+ FreeDraw = module.default;
410
+
411
+ this.freeDraw = new FreeDraw();
412
+
413
+ this.freeDraw.on("markers", (e: any) => {
414
+ if (
415
+ e.eventType === "create" &&
416
+ e.latLngs.length &&
417
+ e.latLngs[0].length > 2
418
+ ) {
419
+ const polygon = L.polygon(
420
+ e.latLngs,
421
+ drawingOptions
422
+ ) as L.Polygon;
423
+
424
+ this.fitBounds(polygon.getBounds());
425
+
426
+ this.map.fire("draw:created", {
427
+ originalEvent: e,
428
+ layer: polygon,
429
+ });
430
+
431
+ this.stopDrawing();
432
+ }
433
+ });
434
+
435
+ this.map.addLayer(this.freeDraw);
436
+
437
+ this.freeDraw.mode(FreeDraw.NONE);
438
+
439
+ resolve();
440
+ })
441
+ .catch((error: string) => {
442
+ console.error(error);
443
+ reject();
444
+ });
445
+ }
446
+ );
447
+ }
448
+ }
449
+
450
+ drawPolygonFromPoints(latLngs: Array<LatLng>): void {
451
+ if (!latLngs) return;
452
+
453
+ const polygon = L.polygon(latLngs, drawingOptions);
454
+
455
+ if (this.freeDraw) this.freeDraw.create(polygon.getLatLngs()[0]);
456
+ else if (this.shapeLayer) this.shapeLayer.addLayer(polygon);
457
+ else {
458
+ this.shapeLayer = new L.FeatureGroup();
459
+ this.map.addLayer(this.shapeLayer);
460
+ this.shapeLayer.addLayer(polygon);
461
+ }
462
+
463
+ /*if (!this.freeDraw)
464
+ this.map.fitBounds(polygon.getBounds(), {
465
+ padding: [10, 10]
466
+ });
467
+ */
468
+
469
+ this.map.fire("draw:created", {
470
+ layer: polygon,
471
+ });
472
+ }
473
+
474
+ deleteMarkers(): void {
475
+ const keys = Object.keys(this.markers);
476
+
477
+ for (let i = 0; i < keys.length; i++) {
478
+ const key = keys[i];
479
+
480
+ const marker = this.findMarker(Number(key));
481
+
482
+ if (marker) this.map.removeLayer(marker);
483
+ }
484
+
485
+ this.markers.clear();
486
+
487
+ if (this.markerClusterer) this.markerClusterer.clearLayers();
488
+ }
489
+
490
+ deleteShape(): void {
491
+ if (this.freeDraw) this.freeDraw.clear();
492
+
493
+ if (this.shapeLayer) this.shapeLayer.clearLayers();
494
+
495
+ this.map.fire("draw:deleted");
496
+ }
497
+
498
+ hasShape(): boolean {
499
+ return (
500
+ (this.freeDraw && this.freeDraw.size() > 0) ||
501
+ (this.shapeLayer && this.shapeLayer.getLayers().length > 0)
502
+ );
503
+ }
504
+
505
+ getShape(): Polyline {
506
+ return this.freeDraw
507
+ ? this.freeDraw.all()[0]
508
+ : this.shapeLayer
509
+ ? this.shapeLayer.getLayers()[0]
510
+ : null;
511
+ }
512
+
513
+ getShapePoints(): Array<LatLng> {
514
+ return (this.getShape()?.getLatLngs()[0] as Array<LatLng>) ?? [];
515
+ }
516
+
517
+ initSearch(): Promise<unknown> {
518
+ return new Promise(
519
+ (
520
+ resolve: (...args: Array<unknown>) => unknown,
521
+ reject: () => unknown
522
+ ) => {
523
+ Promise.all([
524
+ require(/* webpackChunkName: "chunks/leaflet.geocoder" */ "leaflet-control-geocoder/dist/Control.Geocoder.css"),
525
+ // @ts-ignore
526
+ import(
527
+ /* webpackChunkName: "chunks/leaflet.geocoder" */ "leaflet-control-geocoder"
528
+ ),
529
+ ])
530
+ .then(() => {
531
+ this.search = new L.Control.Geocoder({
532
+ defaultMarkGeocode: false,
533
+ collapsed: false,
534
+ placeholder: "Inserisci un indirizzo",
535
+ errorMessage: "Nessun luogo trovato",
536
+ geocoder: new L.Control.Geocoder.Mapbox(MAP_TILER_TOKEN, {
537
+ serviceUrl:
538
+ "https://api.mapbox.com/geocoding/v5/mapbox.places/",
539
+ geocodingQueryParams: { language: "it" },
540
+ reverseQueryParams: {},
541
+ }),
542
+ })
543
+ .on("markgeocode", (e: any) => {
544
+ this.stopDrawing();
545
+ this.deleteShape();
546
+ this.fitBounds(e.geocode.bbox);
547
+ this.setDrawing();
548
+ })
549
+ .addTo(this.map);
550
+
551
+ resolve();
552
+ })
553
+ .catch((error: string) => {
554
+ console.error(error);
555
+ reject();
556
+ });
557
+ }
558
+ );
559
+ }
560
+
561
+ isInitialized(): boolean {
562
+ return this.initialized;
563
+ }
564
+
565
+ getInfowindow(): Popup {
566
+ return this.infowindow;
567
+ }
568
+
569
+ getInfowindowCarousel(): Popup {
570
+ return this.infowindowCarousel;
571
+ }
572
+
573
+ getMap(): LMap {
574
+ return this.map;
575
+ }
576
+
577
+ getMapContainer(): HTMLElement {
578
+ return this.mapContainer;
579
+ }
580
+
581
+ getMarkers(): Map<number, Marker> {
582
+ return this.markers;
583
+ }
584
+
585
+ getMarkersCount(): number {
586
+ return this.markers.size;
587
+ }
588
+
589
+ getMarkerClusterer(): MarkerClusterGroup {
590
+ return this.markerClusterer;
591
+ }
592
+
593
+ addListener(
594
+ obj: any,
595
+ event: string,
596
+ fn: (args?: any) => unknown | void
597
+ ): void {
598
+ obj.on(event, fn);
599
+ }
600
+
601
+ init(
602
+ selector: JQuery,
603
+ apiKey: string,
604
+ COLORS: Record<string, string>,
605
+ opts?: any,
606
+ longLat: { longitude: number; latitude: number } | null = null,
607
+ zoom: number = 12
608
+ ): void {
609
+ this.mapContainer = selector[0];
610
+ if (!this.mapContainer || this.map) return;
611
+
612
+ drawingOptions = defaultDrawingOptions(COLORS);
613
+
614
+ const dataZoom = this.mapContainer.getAttribute("data-zoom");
615
+ if (dataZoom) zoom = parseInt(dataZoom);
616
+
617
+ let lat, lng;
618
+ if (longLat) {
619
+ lat = longLat.latitude;
620
+ lng = longLat.longitude;
621
+ } else {
622
+ lat = parseFloat(this.mapContainer.getAttribute("data-lat") || String(0));
623
+ lng = parseFloat(this.mapContainer.getAttribute("data-lng") || String(0));
624
+ }
625
+
626
+ const drawing = this.mapContainer.hasAttribute("data-drawing-manager");
627
+ const search = this.mapContainer.hasAttribute("data-search");
628
+ const cluster = this.mapContainer.hasAttribute("data-cluster");
629
+
630
+ let center = [lat, lng];
631
+
632
+ if (!this.validateCoordinate(center[0], center[1])) {
633
+ center = [45.464161, 9.190336];
634
+ }
635
+
636
+ this.config = { zoom, center, cluster, search, drawing };
637
+
638
+ this.load(this.config, apiKey, opts);
639
+ }
640
+
641
+ load(config: any, apiKey: string, opts: any): void {
642
+ if (!this.spinner) {
643
+ this.spinner = document.createElement("div");
644
+ this.spinner.className = "spinner-wrapper";
645
+
646
+ this.spinnerIcon = document.createElement("div");
647
+ this.spinnerIcon.className = "spinner";
648
+
649
+ this.spinnerIcon.innerHTML = SVG;
650
+
651
+ this.spinner.appendChild(this.spinnerIcon);
652
+ this.mapContainer.appendChild(this.spinner);
653
+ }
654
+
655
+ const defOpts = {
656
+ maxZoom: MAX_ZOOM,
657
+ zoomControl: false,
658
+ };
659
+
660
+ const options = $.extend({}, defOpts, opts);
661
+
662
+ getL().then(([leaflet]: any) => {
663
+ window["L"] = leaflet;
664
+ L = leaflet;
665
+
666
+ const self = this;
667
+
668
+ if (window["touch"]) this.addTouchHandler();
669
+
670
+ this.map = new L.Map(this.mapContainer, options);
671
+
672
+ L.control
673
+ .zoom({
674
+ position: "bottomright",
675
+ })
676
+ .addTo(this.map);
677
+
678
+ // eslint-disable-next-line max-len
679
+ //L.tileLayer(`https://api.mapbox.com/styles/v1/wikicasa/cjjfg09rh57nr2rqumbg6dds3/tiles/256/{z}/{x}/{y}@2x?access_token=${token}`).addTo(this.map);
680
+ L.tileLayer(
681
+ `https://api.maptiler.com/maps/${MAP_TILER_STYLE}/{z}/{x}/{y}@2x.png?key=${apiKey}`,
682
+ {
683
+ tileSize: 512,
684
+ zoomOffset: -1,
685
+ minZoom: 1,
686
+ // eslint-disable-next-line max-len
687
+ attribution:
688
+ '<a href="https://www.maptiler.com/copyright/" target="_blank">© MapTiler</a> <a href="https://www.openstreetmap.org/copyright" target="_blank">© OpenStreetMap contributors</a>',
689
+ crossOrigin: true,
690
+ }
691
+ ).addTo(this.map);
692
+
693
+ this.map.setView(config.center, config.zoom);
694
+
695
+ // eslint-disable-next-line max-len
696
+ this.infowindow = L.popup().setContent(
697
+ '<div id="infowindow" class="infowindow"><div id="wrapper-single" class="wrapper-single"></div><div id="wrapper-multiple" class="wrapper-multiple"></div></div>'
698
+ );
699
+
700
+ L.Control.infowindowCarousel = L.Control.extend({
701
+ options: {
702
+ position: "bottomleft",
703
+ },
704
+ onAdd: function (map: LMap) {
705
+ this._div = L.DomUtil.create("div");
706
+ this._div.id = "infowindow-carousel";
707
+ this._div.className =
708
+ "infowindow-carousel siema bg-white text-left m-0 d-sm-none";
709
+
710
+ this._div.addEventListener("mouseover", () => {
711
+ map.dragging.disable();
712
+ });
713
+
714
+ this._div.addEventListener("mouseout", () => {
715
+ map.dragging.enable();
716
+ });
717
+
718
+ self.infowindowCarousel = this._div;
719
+
720
+ return this._div;
721
+ },
722
+ });
723
+
724
+ this.map.addControl(new L.Control.infowindowCarousel());
725
+
726
+ Promise.all([
727
+ config.search ? this.initSearch() : Promise.resolve(),
728
+ config.cluster ? this.initMarkerClusterer() : Promise.resolve(),
729
+ config.drawing ? this.initDrawingManager() : Promise.resolve(),
730
+ new Promise((resolve: (...args: Array<unknown>) => void) =>
731
+ this.map.whenReady(() => resolve())
732
+ ),
733
+ ]).then(() => {
734
+ this.stopSpinner();
735
+
736
+ this.mapContainer.dispatchEvent(
737
+ createCustomEvent("ready", {
738
+ detail: {
739
+ description: "Map init is complete",
740
+ },
741
+ bubbles: true,
742
+ cancelable: true,
743
+ })
744
+ );
745
+
746
+ this.initialized = true;
747
+
748
+ for (let i = 0; i < this.callbacks.length; i++) {
749
+ this.callbacks[i]();
750
+ }
751
+ });
752
+ });
753
+ }
754
+
755
+ startSpinner(): void {
756
+ this.spinner.style.display = "block";
757
+ }
758
+
759
+ stopSpinner(): void {
760
+ this.spinner.style.display = "none";
761
+ }
762
+
763
+ ready(fn: () => unknown): void {
764
+ if (this.isInitialized()) fn();
765
+ else this.callbacks.push(fn);
766
+ }
767
+
768
+ on(event: string, fn: any): void {
769
+ this.ready(() => {
770
+ this.map.on(event, fn);
771
+ });
772
+ }
773
+
774
+ setCenter(lat: number, lng: number, zoom: number = 13): void {
775
+ if (!this.map) return;
776
+
777
+ if (!this.validateCoordinate(lat, lng)) return;
778
+ this.map.setView([lat, lng], zoom);
779
+ }
780
+
781
+ setZoom(zoom: number): void {
782
+ this.map.setView(this.map.getCenter(), zoom);
783
+ }
784
+
785
+ getZoom(): number {
786
+ return this.map.getZoom();
787
+ }
788
+
789
+ reset(): void {
790
+ this.stopDrawing();
791
+ this.deleteShape();
792
+ this.deleteMarkers();
793
+ }
794
+
795
+ fitBounds(
796
+ myBounds: { getNorthEast: () => LatLng; getSouthWest: () => LatLng },
797
+ opts: FitBoundsOptions = { padding: [0, 0] }
798
+ ): void {
799
+ // Andrea M: use LatLngBounds constructor to pass always real LatLngBounds class to fitBounds method
800
+ this.map.fitBounds(
801
+ L.latLngBounds(myBounds.getNorthEast(), myBounds.getSouthWest()),
802
+ opts
803
+ );
804
+ }
805
+
806
+ fitZoom(myPoint: LatLng): void {
807
+ // reduces the zoom-level of myMap until it contains myPoint
808
+ if (!this.map.getBounds().contains(myPoint) && this.map.getZoom() > 1) {
809
+ this.map.setZoom(this.map.getZoom() - 1);
810
+ this.fitZoom(myPoint);
811
+ }
812
+ }
813
+
814
+ validateCoordinate(lat: number, lng: number): boolean {
815
+ if (!lat || 0 === lat || 90 < Math.abs(lat)) {
816
+ return false;
817
+ }
818
+ if (!lng || 0 === lng || 180 < Math.abs(lng)) {
819
+ return false;
820
+ }
821
+ return true;
822
+ }
823
+
824
+ getDistance(latLng: LatLng, otherLatLng: LatLng): number {
825
+ return this.map.distance(latLng, otherLatLng);
826
+ }
827
+
828
+ geocode(address: string): JQueryPromise<unknown> {
829
+ return $.ajax({
830
+ dataType: "json",
831
+ contentType: "application/json",
832
+ type: "GET",
833
+ url: `https://api.mapbox.com/geocoding/v5/mapbox.places/${address}.json?language=it&access_token=${MAP_TILER_TOKEN}`,
834
+ });
835
+ }
836
+
837
+ isMarkerInsidePolygon(
838
+ coordinates: Array<number>,
839
+ points: Array<LatLng>
840
+ ): boolean {
841
+ const x = coordinates[0],
842
+ y = coordinates[1];
843
+
844
+ let inside = false;
845
+ for (let i = 0, j = points.length - 1; i < points.length; j = i++) {
846
+ const xi = points[i].lat,
847
+ yi = points[i].lng;
848
+ const xj = points[j].lat,
849
+ yj = points[j].lng;
850
+
851
+ const intersect =
852
+ yi > y != yj > y && x < ((xj - xi) * (y - yi)) / (yj - yi) + xi;
853
+ if (intersect) inside = !inside;
854
+ }
855
+
856
+ return inside;
857
+ }
858
+
859
+ addButton(btn: JQuery): void {
860
+ if (!this.buttonsWrapper) {
861
+ this.buttonsWrapper = $(`<div class="map-btn"></div>`);
862
+ $(this.mapContainer).append(this.buttonsWrapper);
863
+ }
864
+
865
+ this.buttonsWrapper.append(btn);
866
+ }
867
+
868
+ addTouchHandler(): void {
869
+ L.Map.mergeOptions({
870
+ touchExtend: true,
871
+ });
872
+
873
+ L.Map.TouchExtend = L.Handler.extend({
874
+ initialize: function (map: LMap) {
875
+ this._map = map;
876
+ this._container = map.getContainer();
877
+ },
878
+
879
+ addHooks: function () {
880
+ L.DomEvent.on(this._container, "touchstart", this._onTouchStart, this);
881
+ L.DomEvent.on(this._container, "touchend", this._onTouchEnd, this);
882
+ L.DomEvent.on(this._container, "touchmove", this._onTouchMove, this);
883
+ },
884
+
885
+ removeHooks: function () {
886
+ L.DomEvent.off(this._container, "touchstart", this._onTouchStart, this);
887
+ L.DomEvent.off(this._container, "touchend", this._onTouchEnd, this);
888
+ L.DomEvent.off(this._container, "touchmove", this._onTouchMove, this);
889
+ },
890
+
891
+ _onTouchEvent: function (e: TouchEvent, type: string) {
892
+ if (!this._map._loaded) {
893
+ return;
894
+ }
895
+
896
+ const touch = e.touches[0],
897
+ rect = this._container.getBoundingClientRect(),
898
+ lat = touch.clientX - rect.left - this._container.clientLeft,
899
+ lng = touch.clientY - rect.top - this._container.clientTop,
900
+ containerPoint = L.point(lat, lng),
901
+ layerPoint = this._map.containerPointToLayerPoint(containerPoint),
902
+ latlng = this._map.layerPointToLatLng(layerPoint);
903
+
904
+ //const containerPoint = this._map.mouseEventToContainerPoint(e);
905
+ //const layerPoint = this._map.containerPointToLayerPoint(containerPoint);
906
+ //const latlng = this._map.layerPointToLatLng(layerPoint);
907
+ try {
908
+ this._map.fire(type, {
909
+ latlng: latlng,
910
+ layerPoint: layerPoint,
911
+ containerPoint: containerPoint,
912
+ originalEvent: e,
913
+ });
914
+ // eslint-disable-next-line no-empty
915
+ } catch (e) {}
916
+ },
917
+
918
+ _onTouchStart: function (e: LeafletEvent) {
919
+ this._onTouchEvent(e, "mousedown");
920
+ },
921
+
922
+ _onTouchEnd: function (e: LeafletEvent) {
923
+ if (!this._map._loaded) {
924
+ return;
925
+ }
926
+ this._map.fire("mouseup", {
927
+ originalEvent: e,
928
+ });
929
+ },
930
+
931
+ _onTouchMove: function (e: LeafletEvent) {
932
+ this._onTouchEvent(e, "mousemove");
933
+ },
934
+ });
935
+
936
+ L.Map.addInitHook("addHandler", "touchExtend", L.Map.TouchExtend);
937
+ }
938
+ }
939
+
940
+ export function getL(): any {
941
+ return Promise.all([
942
+ // @ts-ignore
943
+ import(/* webpackChunkName: "chunks/leaflet" */ "leaflet/src/Leaflet"),
944
+ require(/* webpackChunkName: "chunks/leaflet" */ "leaflet/dist/leaflet.css"),
945
+ ]);
946
+ }