aboutsummaryrefslogtreecommitdiff
path: root/modern/src/map/switcher/switcher.js
blob: a3805f6b3c9caa6396735958a3259d7f5b31477a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
export class SwitcherControl {
  constructor(styles, defaultStyle, beforeSwitch, afterSwitch) {
    this.styles = styles;
    this.defaultStyle = defaultStyle;
    this.beforeSwitch = beforeSwitch;
    this.afterSwitch = afterSwitch;
    this.onDocumentClick = this.onDocumentClick.bind(this);
    this.variables = {};
  }

  getDefaultPosition() {
    return 'top-right';
  }

  setVariable(key, value) {
    this.variables[key] = value;
  }

  onAdd(map) {
    this.map = map;
    this.controlContainer = document.createElement('div');
    this.controlContainer.classList.add('maplibregl-ctrl');
    this.controlContainer.classList.add('maplibregl-ctrl-group');
    this.mapStyleContainer = document.createElement('div');
    this.styleButton = document.createElement('button');
    this.styleButton.type = 'button';
    this.mapStyleContainer.classList.add('maplibregl-style-list');
    for (const style of this.styles) {
      const styleElement = document.createElement('button');
      styleElement.type = 'button';
      styleElement.innerText = style.title;
      styleElement.classList.add(style.title.replace(/[^a-z0-9-]/gi, '_'));
      styleElement.dataset.uri = JSON.stringify(style.uri);
      styleElement.addEventListener('click', (event) => {
        const { srcElement } = event;
        if (srcElement.classList.contains('active')) {
          return;
        }
        this.beforeSwitch();
        let uri = JSON.parse(srcElement.dataset.uri);
        if (typeof uri === 'string') {
          Object.entries(this.variables).forEach(([key, value]) => uri = uri.replaceAll(`$\{${key}}`, value));
        }
        this.map.setStyle(uri);
        this.afterSwitch();
        this.mapStyleContainer.style.display = 'none';
        this.styleButton.style.display = 'block';
        const elms = this.mapStyleContainer.getElementsByClassName('active');
        while (elms[0]) {
          elms[0].classList.remove('active');
        }
        srcElement.classList.add('active');
      });
      if (style.title === this.defaultStyle) {
        styleElement.classList.add('active');
      }
      this.mapStyleContainer.appendChild(styleElement);
    }
    this.styleButton.classList.add('maplibregl-ctrl-icon');
    this.styleButton.classList.add('maplibregl-style-switcher');
    this.styleButton.addEventListener('click', () => {
      this.styleButton.style.display = 'none';
      this.mapStyleContainer.style.display = 'block';
    });
    document.addEventListener('click', this.onDocumentClick);
    this.controlContainer.appendChild(this.styleButton);
    this.controlContainer.appendChild(this.mapStyleContainer);
    return this.controlContainer;
  }

  onRemove() {
    if (!this.controlContainer || !this.controlContainer.parentNode || !this.map || !this.styleButton) {
      return;
    }
    this.styleButton.removeEventListener('click', this.onDocumentClick);
    this.controlContainer.parentNode.removeChild(this.controlContainer);
    document.removeEventListener('click', this.onDocumentClick);
    this.map = undefined;
  }

  onDocumentClick(event) {
    if (this.controlContainer && !this.controlContainer.contains(event.target) && this.mapStyleContainer && this.styleButton) {
      this.mapStyleContainer.style.display = 'none';
      this.styleButton.style.display = 'block';
    }
  }
}