@maplat/ui 0.11.11 → 0.12.0

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.
@@ -1,630 +1,630 @@
1
- import { Control, Rotate, Zoom as BaseZoom } from "ol/control";
2
- import { CLASS_UNSELECTABLE, CLASS_CONTROL } from "ol/css";
3
- import { MapEvent } from "ol";
4
-
5
- import pointer from "./pointer_images";
6
- import { MaplatApp } from "@maplat/core";
7
- import { createElement } from "./ui_utils";
8
- import { getIcon } from "./icons";
9
- import type { MaplatUi } from "./index";
10
- import type { ControlOptions } from "./types";
11
-
12
- export let control_settings: Record<string, string> = {};
13
- const delegator: { [key: string]: string } = {
14
- compass: "compass.png",
15
- border: "border.png",
16
- attr: "attr.png",
17
- gps: "gps.png",
18
- zoom_plus: "plus.png",
19
- zoom_minus: "minus.png",
20
- help: "help.png",
21
- home: "home.png",
22
- hide_marker: "hide_marker.png",
23
- marker_list: "marker_list.png",
24
- share: "share.png",
25
- slider_in_help: "slider.png",
26
- favicon: "favicon.png"
27
- };
28
-
29
- function hexRgb(hex: string) {
30
- const ret: { red: number; green: number; blue: number } = {
31
- red: 0,
32
- green: 0,
33
- blue: 0
34
- };
35
- if (hex.match(/^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i)) {
36
- ret.red = parseInt(RegExp.$1, 16);
37
- ret.green = parseInt(RegExp.$2, 16);
38
- ret.blue = parseInt(RegExp.$3, 16);
39
- } else if (hex.match(/^#?([0-9A-F])([0-9A-F])([0-9A-F])$/i)) {
40
- ret.red = parseInt(`${RegExp.$1}${RegExp.$1}`, 16);
41
- ret.green = parseInt(`${RegExp.$2}${RegExp.$2}`, 16);
42
- ret.blue = parseInt(`${RegExp.$3}${RegExp.$3}`, 16);
43
- }
44
- return ret;
45
- }
46
-
47
- export function setControlSettings(options: Record<string, string>) {
48
- control_settings = options;
49
- for (const key of Object.keys(control_settings)) {
50
- if (delegator[key]) {
51
- (pointer as Record<string, string>)[delegator[key]] =
52
- control_settings[key];
53
- }
54
- }
55
- }
56
-
57
- export class SliderNew extends Control {
58
- constructor(opt_options: ControlOptions) {
59
- const options = opt_options ? opt_options : {};
60
- const containerElement = document.createElement("input");
61
- containerElement.type = "range";
62
- containerElement.min = "0";
63
- containerElement.max = "1";
64
- const initialValue = options.initialValue || 0;
65
- containerElement.value = `${1 - initialValue}`;
66
- containerElement.step = "0.01";
67
- const render = options.render
68
- ? options.render
69
- : function (mapEvent: MapEvent) {
70
- if (!mapEvent.frameState) return;
71
- };
72
- super({
73
- element: containerElement,
74
- render
75
- });
76
- const className =
77
- options.className !== undefined ? options.className : "ol-slidernew";
78
- this.set("slidervalue", initialValue);
79
-
80
- containerElement.title = options.tipLabel || "";
81
- containerElement.className = `${className} ${CLASS_UNSELECTABLE} ${CLASS_CONTROL}`;
82
- containerElement.addEventListener("click", ev => {
83
- ev.stopPropagation();
84
- });
85
- containerElement.addEventListener("pointerdown", ev => {
86
- ev.stopPropagation();
87
- });
88
- containerElement.addEventListener("pointerup", ev => {
89
- ev.stopPropagation();
90
- });
91
-
92
- containerElement.addEventListener("input", _ev => {
93
- this.set(
94
- "slidervalue",
95
- 1 - parseFloat((this.element as HTMLInputElement).value)
96
- );
97
- });
98
-
99
- if (control_settings["slider_color"]) {
100
- const rgb = hexRgb(control_settings["slider_color"]);
101
- containerElement.classList.add("ol-slider-originalcolor");
102
- const sheets = document.styleSheets;
103
- const sheet = sheets[sheets.length - 1] as CSSStyleSheet;
104
- try {
105
- sheet.insertRule(
106
- `.maplat.with-opacity .ol-slider-originalcolor.${className}::-webkit-slider-thumb {
107
- background: rgba(${rgb.red},${rgb.green},${rgb.blue}, 0.5);
108
- }`,
109
- sheet.cssRules.length
110
- );
111
-
112
- sheet.insertRule(
113
- `.maplat.with-opacity .ol-slider-originalcolor.${className}::-moz-range-thumb {
114
- background: rgba(${rgb.red},${rgb.green},${rgb.blue}, 0.5);
115
- }`,
116
- sheet.cssRules.length
117
- );
118
-
119
- sheet.insertRule(
120
- `.maplat.with-opacity .ol-slider-originalcolor.${className}[disabled]::-webkit-slider-thumb {
121
- background: rgba(${rgb.red},${rgb.green},${rgb.blue}, 0.2);
122
- }`,
123
- sheet.cssRules.length
124
- );
125
-
126
- sheet.insertRule(
127
- `.maplat.with-opacity .ol-slider-originalcolor.${className}[disabled]::-moz-range-thumb {
128
- background: rgba(${rgb.red},${rgb.green},${rgb.blue}, 0.2);
129
- }`,
130
- sheet.cssRules.length
131
- );
132
-
133
- sheet.insertRule(
134
- `.maplat.with-opacity .ol-slider-originalcolor.${className}:not([disabled])::-webkit-slider-thumb:hover {
135
- background: rgba(${rgb.red},${rgb.green},${rgb.blue}, 0.7);
136
- }`,
137
- sheet.cssRules.length
138
- );
139
-
140
- sheet.insertRule(
141
- `.maplat.with-opacity .ol-slider-originalcolor.${className}:not([disabled])::-moz-range-thumb:hover {
142
- background: rgba(${rgb.red},${rgb.green},${rgb.blue}, 0.7);
143
- }`,
144
- sheet.cssRules.length
145
- );
146
- } catch (e) {
147
- console.error(e);
148
- }
149
- }
150
- }
151
-
152
- setMap(map: import("ol").Map) {
153
- super.setMap(map);
154
- if (map) {
155
- map.render();
156
- }
157
- }
158
-
159
- setEnable(cond: boolean) {
160
- const elem = this.element as HTMLInputElement;
161
- if (cond) {
162
- elem.disabled = false;
163
- } else {
164
- elem.disabled = true;
165
- }
166
- }
167
-
168
- setValue(res: number) {
169
- this.set("slidervalue", res);
170
- (this.element as HTMLInputElement).value = (1 - res).toString();
171
- }
172
- }
173
-
174
- export class CustomControl extends Control {
175
- center_: import("ol/coordinate").Coordinate | undefined;
176
- zoom_: number | undefined;
177
- callResetNorth_: unknown;
178
- lastRotation_: number = 0;
179
- label_!: HTMLElement;
180
- ui!: MaplatUi;
181
- moveTo_: boolean = false;
182
-
183
- constructor(optOptions: ControlOptions) {
184
- const options: ControlOptions = optOptions || {};
185
- const element = document.createElement("div");
186
-
187
- super({
188
- element,
189
- target: options.target,
190
- render: options.render
191
- });
192
-
193
- const button = document.createElement("button");
194
- button.setAttribute("type", "button");
195
- button.title = options.tipLabel || "";
196
- const span = document.createElement("span");
197
- span.innerHTML = options.character || "";
198
- button.appendChild(span);
199
- let timer: number | null | undefined | boolean;
200
- let touchstart: boolean;
201
-
202
- button.addEventListener("click", e => {
203
- e.stopPropagation();
204
- });
205
- button.addEventListener(
206
- "mouseup",
207
- e => {
208
- if (!touchstart) {
209
- if (timer) {
210
- if (options.long_callback) {
211
- clearTimeout(timer as number);
212
- }
213
- timer = null;
214
- if (options.callback) options.callback.apply(this);
215
- }
216
- }
217
- e.stopPropagation();
218
- },
219
- false
220
- );
221
- button.addEventListener(
222
- "mousemove",
223
- e => {
224
- e.stopPropagation();
225
- },
226
- false
227
- );
228
- button.addEventListener(
229
- "mousedown",
230
- e => {
231
- if (!touchstart) {
232
- if (options.long_callback) {
233
- timer = window.setTimeout(() => {
234
- timer = null;
235
- if (options.long_callback) options.long_callback.apply(this);
236
- }, 1500);
237
- } else {
238
- timer = true;
239
- }
240
- }
241
- e.stopPropagation();
242
- },
243
- false
244
- );
245
- button.addEventListener(
246
- "touchstart",
247
- e => {
248
- touchstart = true;
249
- if (options.long_callback) {
250
- timer = window.setTimeout(() => {
251
- timer = null;
252
- if (options.long_callback) options.long_callback.apply(this);
253
- }, 1500);
254
- } else {
255
- timer = true;
256
- }
257
- e.stopPropagation();
258
- },
259
- false
260
- );
261
- button.addEventListener(
262
- "touchend",
263
- e => {
264
- if (timer) {
265
- if (options.long_callback) {
266
- clearTimeout(timer as number);
267
- }
268
- timer = null;
269
- if (options.callback) options.callback.apply(this);
270
- }
271
- e.stopPropagation();
272
- },
273
- false
274
- );
275
- button.addEventListener(
276
- "mouseout",
277
- e => {
278
- if (options.long_callback && typeof timer === "number") {
279
- clearTimeout(timer);
280
- }
281
- timer = null;
282
- e.stopPropagation();
283
- },
284
- false
285
- );
286
- button.addEventListener(
287
- "dblclick",
288
- e => {
289
- e.preventDefault();
290
- },
291
- false
292
- );
293
-
294
- element.className = `${options.cls} ol-unselectable ol-control`;
295
- element.appendChild(button);
296
- }
297
- }
298
-
299
- export class GoHome extends CustomControl {
300
- constructor(optOptions: ControlOptions) {
301
- const options: ControlOptions = optOptions || {};
302
- options.character = control_settings["home"]
303
- ? `<img src="${control_settings["home"]}">`
304
- : getIcon("house", "far fa-lg");
305
- options.cls = "home";
306
- options.callback = function (this: Control) {
307
- const map = this.getMap();
308
- if (map) {
309
- const source = (
310
- map.getLayers().item(0) as import("ol/layer").Layer
311
- ).getSource();
312
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
313
- if (source && (source as any).goHome) {
314
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
315
- (source as any).goHome();
316
- }
317
- }
318
- };
319
- super(options);
320
- if (control_settings["home"]) {
321
- const button = this.element.querySelector("button");
322
- if (button) button.style.backgroundColor = "rgba(0,0,0,0)";
323
- }
324
- }
325
- }
326
-
327
- export class SetGPS extends CustomControl {
328
- constructor(optOptions: ControlOptions) {
329
- const options: ControlOptions = optOptions || {};
330
- options.character = control_settings["gps"]
331
- ? `<img src="${control_settings["gps"]}">`
332
- : getIcon("location-crosshairs", "far fa-lg");
333
- options.cls = "gps";
334
- options.render = function (this: SetGPS, mapEvent: MapEvent) {
335
- const frameState = mapEvent.frameState;
336
- if (!frameState) {
337
- return;
338
- }
339
- const core = this.ui!.core as MaplatApp;
340
- if (core && core.getGPSEnabled) {
341
- const enabled = core.getGPSEnabled();
342
- const isDisabled = this.element.classList.contains("disable");
343
-
344
- if (enabled && isDisabled) {
345
- this.element.classList.remove("disable");
346
- } else if (!enabled && !isDisabled) {
347
- this.element.classList.add("disable");
348
- }
349
- }
350
- };
351
- options.callback = function (this: Control) {
352
- const self = this as SetGPS;
353
- const core = self.ui.core as MaplatApp;
354
-
355
- const currentlyEnabled = core.getGPSEnabled();
356
-
357
- if (core.alwaysGpsOn) {
358
- core.handleGPS(true);
359
- if (self.ui.lastGPSError === "gps_out") {
360
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
361
- self.ui.core!.dispatchEvent(new CustomEvent("outOfMap") as any);
362
- }
363
- } else {
364
- core.handleGPS(!currentlyEnabled);
365
- }
366
- };
367
-
368
- super(options);
369
-
370
- this.ui = options.ui!;
371
- this.moveTo_ = false;
372
-
373
- if (control_settings["gps"]) {
374
- const button = this.element.querySelector("button");
375
- if (button) button.style.backgroundColor = "rgba(0,0,0,0)";
376
- }
377
- }
378
- }
379
-
380
- export class CompassRotate extends Rotate {
381
- center_?: import("ol/coordinate").Coordinate;
382
- zoom_?: number;
383
- customLabel_: HTMLElement;
384
- lastRotation_: number = 0;
385
-
386
- constructor(optOptions: ControlOptions) {
387
- const options: ControlOptions = optOptions || {};
388
- options.autoHide = false;
389
- const span = document.createElement("span");
390
- span.innerHTML = control_settings["compass"]
391
- ? `<img src="${control_settings["compass"]}">`
392
- : getIcon("compass", "far fa-lg ol-compass-fa");
393
- options.label = span;
394
- options.render = function (this: CompassRotate, mapEvent: MapEvent) {
395
- const frameState = mapEvent.frameState;
396
-
397
- if (!frameState) {
398
- return;
399
- }
400
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
401
- const view = (this.getMap() as any).getView();
402
- const rotation = frameState.viewState.rotation;
403
- const center = view.getCenter();
404
- const zoom = view.getDecimalZoom ? view.getDecimalZoom() : view.getZoom();
405
- if (
406
- rotation != this.lastRotation_ ||
407
- (center &&
408
- this.center_ &&
409
- (center[0] != this.center_[0] || center[1] != this.center_[1])) ||
410
- zoom != this.zoom_
411
- ) {
412
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
413
- if (!(this.getMap() as any).northUp) {
414
- const contains = this.element.classList.contains("disable");
415
- if (!contains && rotation === 0) {
416
- this.element.classList.add("disable");
417
- } else if (contains && rotation !== 0) {
418
- this.element.classList.remove("disable");
419
- }
420
- }
421
-
422
- const layer = this.getMap()!.getLayers().item(0);
423
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
424
- const source = (layer as any).getSource
425
- ? // eslint-disable-next-line @typescript-eslint/no-explicit-any
426
- (layer as any).getSource()
427
- : // eslint-disable-next-line @typescript-eslint/no-explicit-any
428
- (layer as any).getLayers().item(0).getSource();
429
- if (!source) {
430
- const transform = "rotate(0rad)";
431
- this.customLabel_.style.transform = transform;
432
-
433
- return;
434
- }
435
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
436
- if ((source as any).viewpoint2MercsAsync) {
437
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
438
- (source as any).viewpoint2MercsAsync().then((mercs: any) => {
439
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
440
- const direction = (source as any).mercs2MercViewpoint(mercs)[2];
441
- const transform = `rotate(${direction}rad)`;
442
- this.customLabel_.style.transform = transform;
443
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
444
- if ((this.getMap() as any).northUp) {
445
- const contains = this.element.classList.contains("disable");
446
- if (!contains && Math.abs(direction) < 0.1) {
447
- this.element.classList.add("disable");
448
- } else if (contains && Math.abs(direction) >= 0.1) {
449
- this.element.classList.remove("disable");
450
- }
451
- }
452
- });
453
- }
454
- }
455
- this.lastRotation_ = rotation;
456
- this.center_ = center;
457
- this.zoom_ = zoom;
458
- };
459
- super(options);
460
- this.customLabel_ = span;
461
- }
462
- }
463
-
464
- export class Share extends CustomControl {
465
- constructor(optOptions: ControlOptions) {
466
- const options: ControlOptions = optOptions || {};
467
- options.character = control_settings["share"]
468
- ? `<img src="${control_settings["share"]}">`
469
- : getIcon("share-from-square", "far fa-lg");
470
- options.cls = "ol-share";
471
- options.callback = function (this: Control) {
472
- const map = this.getMap();
473
- if (map)
474
- map.dispatchEvent(
475
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
476
- new MapEvent("click_control", map, { control: "share" } as any)
477
- );
478
- };
479
-
480
- super(options);
481
- if (control_settings["share"]) {
482
- const button = this.element.querySelector("button");
483
- if (button) button.style.backgroundColor = "rgba(0,0,0,0)";
484
- }
485
- }
486
- }
487
-
488
- export class Border extends CustomControl {
489
- constructor(optOptions: ControlOptions) {
490
- const options: ControlOptions = optOptions || {};
491
-
492
- options.character = control_settings["border"]
493
- ? `<img src="${control_settings["border"]}">`
494
- : getIcon("layer-group", "far fa-lg");
495
- options.cls = "ol-border";
496
- options.callback = function (this: Control) {
497
- const map = this.getMap();
498
- if (map)
499
- map.dispatchEvent(
500
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
501
- new MapEvent("click_control", map, { control: "border" } as any)
502
- );
503
- };
504
-
505
- super(options);
506
- if (control_settings["border"]) {
507
- const button = this.element.querySelector("button");
508
- if (button) button.style.backgroundColor = "rgba(0,0,0,0)";
509
- }
510
- }
511
- }
512
-
513
- export class Maplat extends CustomControl {
514
- constructor(optOptions: ControlOptions) {
515
- const options: ControlOptions = optOptions || {};
516
- options.character = control_settings["help"]
517
- ? `<img src="${control_settings["help"]}">`
518
- : getIcon("circle-question", "far fa-lg");
519
- options.cls = "ol-maplat";
520
- options.callback = function (this: Control) {
521
- const map = this.getMap();
522
- if (map)
523
- map.dispatchEvent(
524
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
525
- new MapEvent("click_control", map, { control: "help" } as any)
526
- );
527
- };
528
-
529
- super(options);
530
- if (control_settings["help"]) {
531
- const button = this.element.querySelector("button");
532
- if (button) button.style.backgroundColor = "rgba(0,0,0,0)";
533
- }
534
- }
535
- }
536
-
537
- export class Copyright extends CustomControl {
538
- constructor(optOptions: ControlOptions) {
539
- const options: ControlOptions = optOptions || {};
540
- options.character = control_settings["attr"]
541
- ? `<img src="${control_settings["attr"]}">`
542
- : getIcon("circle-info", "far fa-lg");
543
- options.cls = "ol-copyright";
544
- options.callback = function (this: Control) {
545
- const map = this.getMap();
546
- if (map)
547
- map.dispatchEvent(
548
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
549
- new MapEvent("click_control", map, { control: "copyright" } as any)
550
- );
551
- };
552
-
553
- super(options);
554
- if (control_settings["attr"]) {
555
- const button = this.element.querySelector("button");
556
- if (button) button.style.backgroundColor = "rgba(0,0,0,0)";
557
- }
558
- }
559
- }
560
-
561
- export class HideMarker extends CustomControl {
562
- constructor(optOptions: ControlOptions) {
563
- const options: ControlOptions = optOptions || {};
564
- options.character = control_settings["hide_marker"]
565
- ? `<img src="${control_settings["hide_marker"]}">`
566
- : getIcon("map-pin", "far fa-lg");
567
- options.cls = "ol-hide-marker";
568
- options.callback = function (this: Control) {
569
- const map = this.getMap();
570
- if (map)
571
- map.dispatchEvent(
572
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
573
- new MapEvent("click_control", map, { control: "hideMarker" } as any)
574
- );
575
- };
576
-
577
- super(options);
578
- if (control_settings["hide_marker"]) {
579
- const button = this.element.querySelector("button");
580
- if (button) button.style.backgroundColor = "rgba(0,0,0,0)";
581
- }
582
- }
583
- }
584
-
585
- export class MarkerList extends CustomControl {
586
- constructor(optOptions: ControlOptions) {
587
- const options: ControlOptions = optOptions || {};
588
- options.character = control_settings["marker_list"]
589
- ? `<img src="${control_settings["marker_list"]}">`
590
- : getIcon("list", "far fa-lg");
591
- options.cls = "ol-marker-list";
592
- options.callback = function (this: Control) {
593
- const map = this.getMap();
594
- if (map)
595
- map.dispatchEvent(
596
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
597
- new MapEvent("click_control", map, { control: "markerList" } as any)
598
- );
599
- };
600
-
601
- super(options);
602
- if (control_settings["marker_list"]) {
603
- const button = this.element.querySelector("button");
604
- if (button) button.style.backgroundColor = "rgba(0,0,0,0)";
605
- }
606
- }
607
- }
608
-
609
- export class Zoom extends BaseZoom {
610
- constructor(options: ControlOptions = {}) {
611
- if (control_settings["zoom_plus"]) {
612
- options.zoomInLabel = createElement(
613
- `<img src="${control_settings["zoom_plus"]}">`
614
- )[0] as HTMLElement;
615
- }
616
- if (control_settings["zoom_minus"]) {
617
- options.zoomOutLabel = createElement(
618
- `<img src="${control_settings["zoom_minus"]}">`
619
- )[0] as HTMLElement;
620
- }
621
-
622
- super(options);
623
- if (control_settings["compass"]) {
624
- const buttons = this.element.querySelectorAll("button");
625
- buttons.forEach(button => {
626
- button.style.backgroundColor = "rgba(0,0,0,0)";
627
- });
628
- }
629
- }
630
- }
1
+ import { Control, Rotate, Zoom as BaseZoom } from "ol/control";
2
+ import { CLASS_UNSELECTABLE, CLASS_CONTROL } from "ol/css";
3
+ import { MapEvent } from "ol";
4
+
5
+ import pointer from "./pointer_images";
6
+ import { MaplatApp } from "@maplat/core";
7
+ import { createElement } from "./ui_utils";
8
+ import { getIcon } from "./icons";
9
+ import type { MaplatUi } from "./index";
10
+ import type { ControlOptions } from "./types";
11
+
12
+ export let control_settings: Record<string, string> = {};
13
+ const delegator: { [key: string]: string } = {
14
+ compass: "compass.png",
15
+ border: "border.png",
16
+ attr: "attr.png",
17
+ gps: "gps.png",
18
+ zoom_plus: "plus.png",
19
+ zoom_minus: "minus.png",
20
+ help: "help.png",
21
+ home: "home.png",
22
+ hide_marker: "hide_marker.png",
23
+ marker_list: "marker_list.png",
24
+ share: "share.png",
25
+ slider_in_help: "slider.png",
26
+ favicon: "favicon.png"
27
+ };
28
+
29
+ function hexRgb(hex: string) {
30
+ const ret: { red: number; green: number; blue: number } = {
31
+ red: 0,
32
+ green: 0,
33
+ blue: 0
34
+ };
35
+ if (hex.match(/^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i)) {
36
+ ret.red = parseInt(RegExp.$1, 16);
37
+ ret.green = parseInt(RegExp.$2, 16);
38
+ ret.blue = parseInt(RegExp.$3, 16);
39
+ } else if (hex.match(/^#?([0-9A-F])([0-9A-F])([0-9A-F])$/i)) {
40
+ ret.red = parseInt(`${RegExp.$1}${RegExp.$1}`, 16);
41
+ ret.green = parseInt(`${RegExp.$2}${RegExp.$2}`, 16);
42
+ ret.blue = parseInt(`${RegExp.$3}${RegExp.$3}`, 16);
43
+ }
44
+ return ret;
45
+ }
46
+
47
+ export function setControlSettings(options: Record<string, string>) {
48
+ control_settings = options;
49
+ for (const key of Object.keys(control_settings)) {
50
+ if (delegator[key]) {
51
+ (pointer as Record<string, string>)[delegator[key]] =
52
+ control_settings[key];
53
+ }
54
+ }
55
+ }
56
+
57
+ export class SliderNew extends Control {
58
+ constructor(opt_options: ControlOptions) {
59
+ const options = opt_options ? opt_options : {};
60
+ const containerElement = document.createElement("input");
61
+ containerElement.type = "range";
62
+ containerElement.min = "0";
63
+ containerElement.max = "1";
64
+ const initialValue = options.initialValue || 0;
65
+ containerElement.value = `${1 - initialValue}`;
66
+ containerElement.step = "0.01";
67
+ const render = options.render
68
+ ? options.render
69
+ : function (mapEvent: MapEvent) {
70
+ if (!mapEvent.frameState) return;
71
+ };
72
+ super({
73
+ element: containerElement,
74
+ render
75
+ });
76
+ const className =
77
+ options.className !== undefined ? options.className : "ol-slidernew";
78
+ this.set("slidervalue", initialValue);
79
+
80
+ containerElement.title = options.tipLabel || "";
81
+ containerElement.className = `${className} ${CLASS_UNSELECTABLE} ${CLASS_CONTROL}`;
82
+ containerElement.addEventListener("click", ev => {
83
+ ev.stopPropagation();
84
+ });
85
+ containerElement.addEventListener("pointerdown", ev => {
86
+ ev.stopPropagation();
87
+ });
88
+ containerElement.addEventListener("pointerup", ev => {
89
+ ev.stopPropagation();
90
+ });
91
+
92
+ containerElement.addEventListener("input", _ev => {
93
+ this.set(
94
+ "slidervalue",
95
+ 1 - parseFloat((this.element as HTMLInputElement).value)
96
+ );
97
+ });
98
+
99
+ if (control_settings["slider_color"]) {
100
+ const rgb = hexRgb(control_settings["slider_color"]);
101
+ containerElement.classList.add("ol-slider-originalcolor");
102
+ const sheets = document.styleSheets;
103
+ const sheet = sheets[sheets.length - 1] as CSSStyleSheet;
104
+ try {
105
+ sheet.insertRule(
106
+ `.maplat.with-opacity .ol-slider-originalcolor.${className}::-webkit-slider-thumb {
107
+ background: rgba(${rgb.red},${rgb.green},${rgb.blue}, 0.5);
108
+ }`,
109
+ sheet.cssRules.length
110
+ );
111
+
112
+ sheet.insertRule(
113
+ `.maplat.with-opacity .ol-slider-originalcolor.${className}::-moz-range-thumb {
114
+ background: rgba(${rgb.red},${rgb.green},${rgb.blue}, 0.5);
115
+ }`,
116
+ sheet.cssRules.length
117
+ );
118
+
119
+ sheet.insertRule(
120
+ `.maplat.with-opacity .ol-slider-originalcolor.${className}[disabled]::-webkit-slider-thumb {
121
+ background: rgba(${rgb.red},${rgb.green},${rgb.blue}, 0.2);
122
+ }`,
123
+ sheet.cssRules.length
124
+ );
125
+
126
+ sheet.insertRule(
127
+ `.maplat.with-opacity .ol-slider-originalcolor.${className}[disabled]::-moz-range-thumb {
128
+ background: rgba(${rgb.red},${rgb.green},${rgb.blue}, 0.2);
129
+ }`,
130
+ sheet.cssRules.length
131
+ );
132
+
133
+ sheet.insertRule(
134
+ `.maplat.with-opacity .ol-slider-originalcolor.${className}:not([disabled])::-webkit-slider-thumb:hover {
135
+ background: rgba(${rgb.red},${rgb.green},${rgb.blue}, 0.7);
136
+ }`,
137
+ sheet.cssRules.length
138
+ );
139
+
140
+ sheet.insertRule(
141
+ `.maplat.with-opacity .ol-slider-originalcolor.${className}:not([disabled])::-moz-range-thumb:hover {
142
+ background: rgba(${rgb.red},${rgb.green},${rgb.blue}, 0.7);
143
+ }`,
144
+ sheet.cssRules.length
145
+ );
146
+ } catch (e) {
147
+ console.error(e);
148
+ }
149
+ }
150
+ }
151
+
152
+ setMap(map: import("ol").Map) {
153
+ super.setMap(map);
154
+ if (map) {
155
+ map.render();
156
+ }
157
+ }
158
+
159
+ setEnable(cond: boolean) {
160
+ const elem = this.element as HTMLInputElement;
161
+ if (cond) {
162
+ elem.disabled = false;
163
+ } else {
164
+ elem.disabled = true;
165
+ }
166
+ }
167
+
168
+ setValue(res: number) {
169
+ this.set("slidervalue", res);
170
+ (this.element as HTMLInputElement).value = (1 - res).toString();
171
+ }
172
+ }
173
+
174
+ export class CustomControl extends Control {
175
+ center_: import("ol/coordinate").Coordinate | undefined;
176
+ zoom_: number | undefined;
177
+ callResetNorth_: unknown;
178
+ lastRotation_: number = 0;
179
+ label_!: HTMLElement;
180
+ ui!: MaplatUi;
181
+ moveTo_: boolean = false;
182
+
183
+ constructor(optOptions: ControlOptions) {
184
+ const options: ControlOptions = optOptions || {};
185
+ const element = document.createElement("div");
186
+
187
+ super({
188
+ element,
189
+ target: options.target,
190
+ render: options.render
191
+ });
192
+
193
+ const button = document.createElement("button");
194
+ button.setAttribute("type", "button");
195
+ button.title = options.tipLabel || "";
196
+ const span = document.createElement("span");
197
+ span.innerHTML = options.character || "";
198
+ button.appendChild(span);
199
+ let timer: number | null | undefined | boolean;
200
+ let touchstart: boolean;
201
+
202
+ button.addEventListener("click", e => {
203
+ e.stopPropagation();
204
+ });
205
+ button.addEventListener(
206
+ "mouseup",
207
+ e => {
208
+ if (!touchstart) {
209
+ if (timer) {
210
+ if (options.long_callback) {
211
+ clearTimeout(timer as number);
212
+ }
213
+ timer = null;
214
+ if (options.callback) options.callback.apply(this);
215
+ }
216
+ }
217
+ e.stopPropagation();
218
+ },
219
+ false
220
+ );
221
+ button.addEventListener(
222
+ "mousemove",
223
+ e => {
224
+ e.stopPropagation();
225
+ },
226
+ false
227
+ );
228
+ button.addEventListener(
229
+ "mousedown",
230
+ e => {
231
+ if (!touchstart) {
232
+ if (options.long_callback) {
233
+ timer = window.setTimeout(() => {
234
+ timer = null;
235
+ if (options.long_callback) options.long_callback.apply(this);
236
+ }, 1500);
237
+ } else {
238
+ timer = true;
239
+ }
240
+ }
241
+ e.stopPropagation();
242
+ },
243
+ false
244
+ );
245
+ button.addEventListener(
246
+ "touchstart",
247
+ e => {
248
+ touchstart = true;
249
+ if (options.long_callback) {
250
+ timer = window.setTimeout(() => {
251
+ timer = null;
252
+ if (options.long_callback) options.long_callback.apply(this);
253
+ }, 1500);
254
+ } else {
255
+ timer = true;
256
+ }
257
+ e.stopPropagation();
258
+ },
259
+ false
260
+ );
261
+ button.addEventListener(
262
+ "touchend",
263
+ e => {
264
+ if (timer) {
265
+ if (options.long_callback) {
266
+ clearTimeout(timer as number);
267
+ }
268
+ timer = null;
269
+ if (options.callback) options.callback.apply(this);
270
+ }
271
+ e.stopPropagation();
272
+ },
273
+ false
274
+ );
275
+ button.addEventListener(
276
+ "mouseout",
277
+ e => {
278
+ if (options.long_callback && typeof timer === "number") {
279
+ clearTimeout(timer);
280
+ }
281
+ timer = null;
282
+ e.stopPropagation();
283
+ },
284
+ false
285
+ );
286
+ button.addEventListener(
287
+ "dblclick",
288
+ e => {
289
+ e.preventDefault();
290
+ },
291
+ false
292
+ );
293
+
294
+ element.className = `${options.cls} ol-unselectable ol-control`;
295
+ element.appendChild(button);
296
+ }
297
+ }
298
+
299
+ export class GoHome extends CustomControl {
300
+ constructor(optOptions: ControlOptions) {
301
+ const options: ControlOptions = optOptions || {};
302
+ options.character = control_settings["home"]
303
+ ? `<img src="${control_settings["home"]}">`
304
+ : getIcon("house", "far fa-lg");
305
+ options.cls = "home";
306
+ options.callback = function (this: Control) {
307
+ const map = this.getMap();
308
+ if (map) {
309
+ const source = (
310
+ map.getLayers().item(0) as import("ol/layer").Layer
311
+ ).getSource();
312
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
313
+ if (source && (source as any).goHome) {
314
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
315
+ (source as any).goHome();
316
+ }
317
+ }
318
+ };
319
+ super(options);
320
+ if (control_settings["home"]) {
321
+ const button = this.element.querySelector("button");
322
+ if (button) button.style.backgroundColor = "rgba(0,0,0,0)";
323
+ }
324
+ }
325
+ }
326
+
327
+ export class SetGPS extends CustomControl {
328
+ constructor(optOptions: ControlOptions) {
329
+ const options: ControlOptions = optOptions || {};
330
+ options.character = control_settings["gps"]
331
+ ? `<img src="${control_settings["gps"]}">`
332
+ : getIcon("location-crosshairs", "far fa-lg");
333
+ options.cls = "gps";
334
+ options.render = function (this: SetGPS, mapEvent: MapEvent) {
335
+ const frameState = mapEvent.frameState;
336
+ if (!frameState) {
337
+ return;
338
+ }
339
+ const core = this.ui!.core as MaplatApp;
340
+ if (core && core.getGPSEnabled) {
341
+ const enabled = core.getGPSEnabled();
342
+ const isDisabled = this.element.classList.contains("disable");
343
+
344
+ if (enabled && isDisabled) {
345
+ this.element.classList.remove("disable");
346
+ } else if (!enabled && !isDisabled) {
347
+ this.element.classList.add("disable");
348
+ }
349
+ }
350
+ };
351
+ options.callback = function (this: Control) {
352
+ const self = this as SetGPS;
353
+ const core = self.ui.core as MaplatApp;
354
+
355
+ const currentlyEnabled = core.getGPSEnabled();
356
+
357
+ if (core.alwaysGpsOn) {
358
+ core.handleGPS(true);
359
+ if (self.ui.lastGPSError === "gps_out") {
360
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
361
+ self.ui.core!.dispatchEvent(new CustomEvent("outOfMap") as any);
362
+ }
363
+ } else {
364
+ core.handleGPS(!currentlyEnabled);
365
+ }
366
+ };
367
+
368
+ super(options);
369
+
370
+ this.ui = options.ui!;
371
+ this.moveTo_ = false;
372
+
373
+ if (control_settings["gps"]) {
374
+ const button = this.element.querySelector("button");
375
+ if (button) button.style.backgroundColor = "rgba(0,0,0,0)";
376
+ }
377
+ }
378
+ }
379
+
380
+ export class CompassRotate extends Rotate {
381
+ center_?: import("ol/coordinate").Coordinate;
382
+ zoom_?: number;
383
+ customLabel_: HTMLElement;
384
+ lastRotation_: number = 0;
385
+
386
+ constructor(optOptions: ControlOptions) {
387
+ const options: ControlOptions = optOptions || {};
388
+ options.autoHide = false;
389
+ const span = document.createElement("span");
390
+ span.innerHTML = control_settings["compass"]
391
+ ? `<img src="${control_settings["compass"]}">`
392
+ : getIcon("compass", "far fa-lg ol-compass-fa");
393
+ options.label = span;
394
+ options.render = function (this: CompassRotate, mapEvent: MapEvent) {
395
+ const frameState = mapEvent.frameState;
396
+
397
+ if (!frameState) {
398
+ return;
399
+ }
400
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
401
+ const view = (this.getMap() as any).getView();
402
+ const rotation = frameState.viewState.rotation;
403
+ const center = view.getCenter();
404
+ const zoom = view.getDecimalZoom ? view.getDecimalZoom() : view.getZoom();
405
+ if (
406
+ rotation != this.lastRotation_ ||
407
+ (center &&
408
+ this.center_ &&
409
+ (center[0] != this.center_[0] || center[1] != this.center_[1])) ||
410
+ zoom != this.zoom_
411
+ ) {
412
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
413
+ if (!(this.getMap() as any).northUp) {
414
+ const contains = this.element.classList.contains("disable");
415
+ if (!contains && rotation === 0) {
416
+ this.element.classList.add("disable");
417
+ } else if (contains && rotation !== 0) {
418
+ this.element.classList.remove("disable");
419
+ }
420
+ }
421
+
422
+ const layer = this.getMap()!.getLayers().item(0);
423
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
424
+ const source = (layer as any).getSource
425
+ ? // eslint-disable-next-line @typescript-eslint/no-explicit-any
426
+ (layer as any).getSource()
427
+ : // eslint-disable-next-line @typescript-eslint/no-explicit-any
428
+ (layer as any).getLayers().item(0).getSource();
429
+ if (!source) {
430
+ const transform = "rotate(0rad)";
431
+ this.customLabel_.style.transform = transform;
432
+
433
+ return;
434
+ }
435
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
436
+ if ((source as any).viewpoint2MercsAsync) {
437
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
438
+ (source as any).viewpoint2MercsAsync().then((mercs: any) => {
439
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
440
+ const direction = (source as any).mercs2MercViewpoint(mercs)[2];
441
+ const transform = `rotate(${direction}rad)`;
442
+ this.customLabel_.style.transform = transform;
443
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
444
+ if ((this.getMap() as any).northUp) {
445
+ const contains = this.element.classList.contains("disable");
446
+ if (!contains && Math.abs(direction) < 0.1) {
447
+ this.element.classList.add("disable");
448
+ } else if (contains && Math.abs(direction) >= 0.1) {
449
+ this.element.classList.remove("disable");
450
+ }
451
+ }
452
+ });
453
+ }
454
+ }
455
+ this.lastRotation_ = rotation;
456
+ this.center_ = center;
457
+ this.zoom_ = zoom;
458
+ };
459
+ super(options);
460
+ this.customLabel_ = span;
461
+ }
462
+ }
463
+
464
+ export class Share extends CustomControl {
465
+ constructor(optOptions: ControlOptions) {
466
+ const options: ControlOptions = optOptions || {};
467
+ options.character = control_settings["share"]
468
+ ? `<img src="${control_settings["share"]}">`
469
+ : getIcon("share-from-square", "far fa-lg");
470
+ options.cls = "ol-share";
471
+ options.callback = function (this: Control) {
472
+ const map = this.getMap();
473
+ if (map)
474
+ map.dispatchEvent(
475
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
476
+ new MapEvent("click_control", map, { control: "share" } as any)
477
+ );
478
+ };
479
+
480
+ super(options);
481
+ if (control_settings["share"]) {
482
+ const button = this.element.querySelector("button");
483
+ if (button) button.style.backgroundColor = "rgba(0,0,0,0)";
484
+ }
485
+ }
486
+ }
487
+
488
+ export class Border extends CustomControl {
489
+ constructor(optOptions: ControlOptions) {
490
+ const options: ControlOptions = optOptions || {};
491
+
492
+ options.character = control_settings["border"]
493
+ ? `<img src="${control_settings["border"]}">`
494
+ : getIcon("layer-group", "far fa-lg");
495
+ options.cls = "ol-border";
496
+ options.callback = function (this: Control) {
497
+ const map = this.getMap();
498
+ if (map)
499
+ map.dispatchEvent(
500
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
501
+ new MapEvent("click_control", map, { control: "border" } as any)
502
+ );
503
+ };
504
+
505
+ super(options);
506
+ if (control_settings["border"]) {
507
+ const button = this.element.querySelector("button");
508
+ if (button) button.style.backgroundColor = "rgba(0,0,0,0)";
509
+ }
510
+ }
511
+ }
512
+
513
+ export class Maplat extends CustomControl {
514
+ constructor(optOptions: ControlOptions) {
515
+ const options: ControlOptions = optOptions || {};
516
+ options.character = control_settings["help"]
517
+ ? `<img src="${control_settings["help"]}">`
518
+ : getIcon("circle-question", "far fa-lg");
519
+ options.cls = "ol-maplat";
520
+ options.callback = function (this: Control) {
521
+ const map = this.getMap();
522
+ if (map)
523
+ map.dispatchEvent(
524
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
525
+ new MapEvent("click_control", map, { control: "help" } as any)
526
+ );
527
+ };
528
+
529
+ super(options);
530
+ if (control_settings["help"]) {
531
+ const button = this.element.querySelector("button");
532
+ if (button) button.style.backgroundColor = "rgba(0,0,0,0)";
533
+ }
534
+ }
535
+ }
536
+
537
+ export class Copyright extends CustomControl {
538
+ constructor(optOptions: ControlOptions) {
539
+ const options: ControlOptions = optOptions || {};
540
+ options.character = control_settings["attr"]
541
+ ? `<img src="${control_settings["attr"]}">`
542
+ : getIcon("circle-info", "far fa-lg");
543
+ options.cls = "ol-copyright";
544
+ options.callback = function (this: Control) {
545
+ const map = this.getMap();
546
+ if (map)
547
+ map.dispatchEvent(
548
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
549
+ new MapEvent("click_control", map, { control: "copyright" } as any)
550
+ );
551
+ };
552
+
553
+ super(options);
554
+ if (control_settings["attr"]) {
555
+ const button = this.element.querySelector("button");
556
+ if (button) button.style.backgroundColor = "rgba(0,0,0,0)";
557
+ }
558
+ }
559
+ }
560
+
561
+ export class HideMarker extends CustomControl {
562
+ constructor(optOptions: ControlOptions) {
563
+ const options: ControlOptions = optOptions || {};
564
+ options.character = control_settings["hide_marker"]
565
+ ? `<img src="${control_settings["hide_marker"]}">`
566
+ : getIcon("map-pin", "far fa-lg");
567
+ options.cls = "ol-hide-marker";
568
+ options.callback = function (this: Control) {
569
+ const map = this.getMap();
570
+ if (map)
571
+ map.dispatchEvent(
572
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
573
+ new MapEvent("click_control", map, { control: "hideMarker" } as any)
574
+ );
575
+ };
576
+
577
+ super(options);
578
+ if (control_settings["hide_marker"]) {
579
+ const button = this.element.querySelector("button");
580
+ if (button) button.style.backgroundColor = "rgba(0,0,0,0)";
581
+ }
582
+ }
583
+ }
584
+
585
+ export class MarkerList extends CustomControl {
586
+ constructor(optOptions: ControlOptions) {
587
+ const options: ControlOptions = optOptions || {};
588
+ options.character = control_settings["marker_list"]
589
+ ? `<img src="${control_settings["marker_list"]}">`
590
+ : getIcon("list", "far fa-lg");
591
+ options.cls = "ol-marker-list";
592
+ options.callback = function (this: Control) {
593
+ const map = this.getMap();
594
+ if (map)
595
+ map.dispatchEvent(
596
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
597
+ new MapEvent("click_control", map, { control: "markerList" } as any)
598
+ );
599
+ };
600
+
601
+ super(options);
602
+ if (control_settings["marker_list"]) {
603
+ const button = this.element.querySelector("button");
604
+ if (button) button.style.backgroundColor = "rgba(0,0,0,0)";
605
+ }
606
+ }
607
+ }
608
+
609
+ export class Zoom extends BaseZoom {
610
+ constructor(options: ControlOptions = {}) {
611
+ if (control_settings["zoom_plus"]) {
612
+ options.zoomInLabel = createElement(
613
+ `<img src="${control_settings["zoom_plus"]}">`
614
+ )[0] as HTMLElement;
615
+ }
616
+ if (control_settings["zoom_minus"]) {
617
+ options.zoomOutLabel = createElement(
618
+ `<img src="${control_settings["zoom_minus"]}">`
619
+ )[0] as HTMLElement;
620
+ }
621
+
622
+ super(options);
623
+ if (control_settings["compass"]) {
624
+ const buttons = this.element.querySelectorAll("button");
625
+ buttons.forEach(button => {
626
+ button.style.backgroundColor = "rgba(0,0,0,0)";
627
+ });
628
+ }
629
+ }
630
+ }