<template> <div class="basemaps-items ui accordion styled"> <div :class="['basemap-item title', { active }]" @click="activateGroup(basemap)" > {{ basemap.title }} </div> <div v-if="isQueryable(basemap)" :id="`queryable-layers-selector-${basemap.id}`" > <strong>Couche requĂȘtable</strong> <Dropdown :options="getQueryableLayers(basemap)" :selected="selectedQueryLayer" :search="true" @update:selection="onQueryLayerChange($event)" /> </div> <div :id="`list-${basemap.id}`" :class="['content', { active }]" :data-basemap-index="basemap.id" > <div v-for="(layer, index) in basemap.layers" :key="basemap.id + '-' + layer.id + '-' + index" class="layer-item transition visible item list-group-item" :data-id="layer.id" > <!-- layer id is used for retrieving layer when changing order --> <p class="layer-handle-sort"> <i class="th icon" aria-hidden="true" /> {{ layer.title }} </p> <label>OpacitĂ© <span>(%)</span></label> <div class="range-container"> <input type="range" min="0" max="1" :value="layer.opacity" step="0.01" @change="updateOpacity($event, layer)" ><output class="range-output-bubble">{{ getOpacity(layer.opacity) }}</output> </div> <div class="ui divider" /> </div> </div> </div> </template> <script> import Sortable from 'sortablejs'; import Dropdown from '@/components/Dropdown.vue'; import mapService from '@/services/map-service'; export default { name: 'LayerSelector', components: { Dropdown, }, props: { basemap: { type: Object, default: null, }, baseMaps: { type: Array, default: () => [], }, activeBasemap: { type: Object, default: () => {}, }, }, data() { return { selectedQueryLayer: null, }; }, computed: { active() { return this.basemap.active !== undefined && this.basemap.active; }, }, mounted() { setTimeout(this.initSortable.bind(this), 1000); }, methods: { isQueryable(baseMap) { const queryableLayer = baseMap.layers.filter((l) => l.queryable === true); return queryableLayer.length > 0; }, setLocalstorageMapOptions(basemaps) { let mapOptions = localStorage.getItem('geocontrib-map-options') || {}; mapOptions = mapOptions.length ? JSON.parse(mapOptions) : {}; const project = this.$route.params.slug; mapOptions[project] = { ...mapOptions[project], basemaps: basemaps, }; localStorage.setItem( 'geocontrib-map-options', JSON.stringify(mapOptions) ); }, onlayerMove() { // Get the names of the current layers in order. const currentLayersNamesInOrder = Array.from( document.getElementsByClassName('layer-item transition visible') ).map((el) => parseInt(el.attributes['data-id'].value)); // Create an array to put the layers in order. let movedLayers = []; for (const layerName of currentLayersNamesInOrder) { movedLayers.push( this.activeBasemap.layers.filter((el) => el.id === layerName)[0] ); } // Remove existing layers undefined movedLayers = movedLayers.filter(function (x) { return x !== undefined; }); const eventOrder = new CustomEvent('change-layers-order', { detail: { layers: movedLayers, }, }); document.dispatchEvent(eventOrder); // Save the basemaps options into the localstorage this.setLocalstorageMapOptions(this.baseMaps); }, initSortable() { this.baseMaps.forEach((basemap) => { const element = document.getElementById(`list-${basemap.id}`); if (element) { this. sortable = new Sortable(element, { animation: 150, handle: '.layer-handle-sort', // The element that is active to drag ghostClass: 'blue-background-class', dragClass: 'white-opacity-background-class', onEnd: this.onlayerMove.bind(this), }); } else { console.error(`list-${basemap.id} not found in dom`); } }); }, onQueryLayerChange(layer) { this.selectedQueryLayer = layer.name; const baseMap = this.baseMaps[0].layers.find((l) => l.title === layer.name); if (baseMap) { baseMap.query = true; } else { console.error('No such param \'query\' found among basemap[0].layers'); } layer.query = true; }, getQueryableLayers(baseMap) { const queryableLayer = baseMap.layers.filter((l) => l.queryable === true); return queryableLayer.map((x) => { return { name: x.title, value: x, }; }); }, activateGroup(basemap) { this.baseMaps.forEach((basemap) => (basemap.active = false)); basemap.active = true; this.$emit('setActiveBasemap', basemap); basemap.title += ' '; //weird!! Force refresh this.$emit('addLayers', basemap); let mapOptions = localStorage.getItem('geocontrib-map-options') || {}; mapOptions = mapOptions.length ? JSON.parse(mapOptions) : {}; const project = this.$route.params.slug; mapOptions[project] = { ...mapOptions[project], 'current-basemap-index': basemap.id, }; localStorage.setItem( 'geocontrib-map-options', JSON.stringify(mapOptions) ); }, getOpacity(opacity) { return Math.round(parseFloat(opacity) * 100); }, updateOpacity(event, layer) { mapService.updateOpacity(layer.id, event.target.value); layer.opacity = event.target.value; }, } }; </script> <style> .queryable-layers-dropdown { margin-bottom: 1em; } .queryable-layers-dropdown > label { font-weight: bold; } </style>