1class Treasure { 2 3 // requires MapBase.map, Menu.reorderMenu, Settings.some and DOM ready 4 // not idempotent 5 static init() { 6 this.treasuresParentElement = document.querySelector('.menu-option.clickable[data-type=treasure]'); 7 this.treasuresParentElement.classList.toggle('disabled', !this.treasuresOnMap); 8 this.treasuresParentElement.addEventListener('click', () => this.treasuresOnMap = !this.treasuresOnMap); 9 10 this.treasures = []; 11 this.quickParams = []; 12 this.layer = L.layerGroup(); 13 this.layer.addTo(MapBase.map); 14 15 const pane = MapBase.map.createPane('treasureX'); 16 pane.style.zIndex = 450; // X-markers on top of circle, but behind ânormalâ markers/shadows 17 pane.style.pointerEvents = 'none'; 18 19 this.context = document.querySelector('.menu-hidden[data-type=treasure]'); 20 this.context.classList.toggle('disabled', !this.treasuresOnMap); 21 22 this.crossIcon = L.icon({ 23 iconUrl: './assets/images/icons/cross.png', 24 iconSize: [16, 16], 25 iconAnchor: [8, 8], 26 }); 27 28 this.onSettingsChanged(); 29 30 document.querySelectorAll('.menu-hidden[data-type="treasure"] > *:first-child button').forEach((btn) => 31 btn.addEventListener('click', (e) => { 32 e.preventDefault(); 33 const showAll = e.target.getAttribute('data-text') === 'menu.show_all'; 34 Treasure.treasures.forEach(treasure => treasure.onMap = showAll); 35 }) 36 ); 37 38 return Loader.promises['treasures'].consumeJson(data => { 39 data.forEach(item => { 40 this.treasures.push(new Treasure(item)); 41 this.quickParams.push(item.text); 42 }); 43 this.onLanguageChanged(); 44 console.info('%c[Treasures] Loaded!', 'color: #bada55; background: #242424'); 45 }); 46 } 47 48 static onLanguageChanged() { 49 Menu.reorderMenu(this.context); 50 } 51 static onSettingsChanged() { 52 this.treasures.forEach(treasure => treasure.reinitMarker()); 53 } 54 55 // not idempotent (on the environment) 56 constructor(preliminary) { 57 Object.assign(this, preliminary); 58 this._shownKey = `shown.${this.text}`; 59 this.element = document.createElement('div'); 60 this.element.classList.add('collectible-wrapper'); 61 Object.assign(this.element.dataset, { help: 'item', tippyContent: Language.get(this.text) }); 62 this.element.addEventListener('click', () => this.onMap = !this.onMap); 63 this.element.innerHTML = `<p class="collectible" data-text="${this.text}"></p>`; 64 Language.translateDom(this.element); 65 66 this.reinitMarker(); 67 68 Treasure.context.appendChild(this.element); 69 } 70 71 // auto remove marker? from map, recreate marker, auto add? marker 72 // idempotent 73 reinitMarker() { 74 if (this.marker) Treasure.layer.removeLayer(this.marker); 75 this.marker = L.layerGroup(); 76 this.marker.addLayer(L.circle([this.x, this.y], { 77 color: '#f4e98a', 78 fillColor: '#f4e98a', 79 fillOpacity: linear(Settings.overlayOpacity, 0, 1, 0.1, 0.5), 80 radius: this.radius, 81 }) 82 .bindPopup(this.popupContent.bind(this), { minWidth: 300 }) 83 ); 84 this.locations.forEach(cross => 85 this.marker.addLayer(L.marker([cross.x, cross.y], { 86 icon: Treasure.crossIcon, 87 pane: 'treasureX', 88 }) 89 .bindPopup(this.popupContent.bind(this), { minWidth: 300 })) 90 ); 91 this.onMap = this.onMap; 92 } 93 94 popupContent() { 95 const snippet = document.createElement('div'); 96 snippet.classList.add('handover-wrapper-with-no-influence'); 97 snippet.innerHTML = ` 98 <h1 data-text="${this.text}"></h1> 99 <button type="button" class="btn btn-info remove-button treasure-button" data-text="map.remove"></button> 100 `; 101 Language.translateDom(snippet); 102 snippet.querySelector('button').addEventListener('click', () => this.onMap = false); 103 104 return snippet; 105 } 106 107 set onMap(state) { 108 if (state) { 109 if (MapBase.isPreviewMode || Treasure.treasuresOnMap) 110 Treasure.layer.addLayer(this.marker); 111 if (!MapBase.isPreviewMode) 112 localStorage.setItem(`rdo.${this._shownKey}`, 'true'); 113 this.element.classList.remove('disabled'); 114 } else { 115 if (Treasure.treasuresOnMap) 116 Treasure.layer.removeLayer(this.marker); 117 if (!MapBase.isPreviewMode) 118 localStorage.removeItem(`rdo.${this._shownKey}`); 119 this.element.classList.add('disabled'); 120 } 121 } 122 get onMap() { 123 return !!localStorage.getItem(`rdo.${this._shownKey}`); 124 } 125 126 static set treasuresOnMap(state) { 127 if (state) {
128 MapBase.map.addLayer(Treasure.layer); 129 if (!MapBase.isPreviewMode) 130 localStorage.setItem('rdo.treasures', 'true'); 131 132 this.treasures.forEach(_t => { 133 if (_t.onMap) _t.onMap = state; 134 }); 135 } else { 136 Treasure.layer.remove(); 137 if (!MapBase.isPreviewMode) 138 localStorage.removeItem('rdo.treasures'); 139 } 140 141 this.treasuresParentElement.classList.toggle('disabled', !state); 142 this.context.classList.toggle('disabled', !state); 143 } 144 145 static get treasuresOnMap() { 146 return !!localStorage.getItem('rdo.treasures'); 147 } 148}
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.