Source: map/tools/BaselayerSwitcher.js

import { UiElement } from '../../ui/UiElement.js';
import "./BaselayerSwitcher.css";

/**
 * Tool to switch the baselayer and projection of a map
 *
 * @extends UiElement
 * @memberof vef.map.tools
 */
class BaselayerSwitcher extends UiElement {

    /**
     * Creates an instance of BaselayerSwitcher.
     *
     * @constructor
     * @param {Map} map - The map object.
     * @param {string} [position="bottom-left"] - The position of the baselayer switcher on the map.
     * @param {Object} baseLayers - The base layers for the switcher.
     */
    constructor(map, position, baseLayers) {
        super(null, {
            "show_info": []
        });

        this.map = map;
        this.position = position || "bottom-left";
        this.baseLayers = baseLayers;

        this.initElement_();
        this.initEvents_();

        this.map.on("projection_change", () => this.update());
        this.map.on("baselayer_change", () => this.update());
        this.map.addTool(this, this.position);

        this.update();
    }

    /**
     * Initializes the element of the baselayer switcher.
     *
     * @private
     */
    initElement_() {
        // initialize element
        const element = this.getElement();
        element.classList.add("baselayer-switcher");

        let mapList = "";
        for (let key in this.baseLayers) {
            mapList += `
                <div class="list-entry" data-key="${key}">
                    <div class="list-entry-thumbnail" style="background-image:URL(${this.baseLayers[key].thumbnail})"></div>
                    <div class="list-entry-id">${key}</div>
                    <i class="fas fa-info info-button"></i>
                </div>
            `;
        }

        element.innerHTML = `
            <div class="current-map">
                <div class="current-map-thumbnail"></div>
                <div class="current-map-title"><i class="fas fa-layer-group"></i> BASELAYERS</div> 
            </div>
            <div class="map-list" style="display:none;">${mapList}</div>
        `;
    }

    /**
     * Initializes the events of the baselayer switcher.
     *
     * @private
     */
    initEvents_() {
        const element = this.getElement();

        const currentMap = element.querySelector(".current-map");
        const list = element.querySelector(".map-list");
        const entries = list.querySelectorAll(".list-entry");

        currentMap.onclick = e => {
            e.preventDefault();
            e.stopPropagation();
            list.style.display = (list.style.display == "none") ? "flex" : "none";
        }

        for (let i = 0; i < entries.length; ++i) {
            const entry = entries[i];
            const layers = this.baseLayers[entry.dataset.key];
            const codes = Object.keys(layers);

            const thumbnail = codes.indexOf("thumbnail");
            if (thumbnail >= 0) codes.splice(thumbnail, 1);

            entry.querySelector(".info-button").onclick = e => {
                e.preventDefault();
                e.stopPropagation();
                const layer = layers[this.map.options.crs] || layers[codes[0]];
                this.fire("show_info", layer);
            };

            entry.onclick = e => {
                e.preventDefault();
                e.stopPropagation();
                if (!entry.classList.contains("disabled")) {
                    const layer = layers[this.map.options.crs] || layers[codes[0]];
                    this.map.setBaseLayer(layer, null);
                    list.style.display = "none";
                }
            };
        }
    }

    /**
     * Updates the baselayer switcher.
     */
    update() {
        const element = this.getElement();

        const key = this.map.options.baseLayer;
        const crs = this.map.options.crs;

        // set thumbnail of current map
        const thumbnail = element.querySelector(".current-map .current-map-thumbnail");
        thumbnail.style.backgroundImage = "URL(" + this.baseLayers[key].thumbnail + ")";

        // disable list entries
        const list = element.querySelector(".map-list");
        const entries = list.querySelectorAll(".list-entry");
        for (let i = 0; i < entries.length; ++i) {
            const entry = entries[i];
            if (entry.dataset.key == key) {
                entry.classList.add("disabled");
                entry.title = "Layer is already selected.";
            } else if (!(crs in this.baseLayers[entry.dataset.key])) {
                entry.classList.add("disabled");
                entry.title = "Layer does not support the current projection.";
            } else {
                entry.classList.remove("disabled");
                entry.title = entry.dataset.key;
            }
        }
    }

    /**
     * Enables the info button of the baselayer switcher.
     */
    enableInfoButton() {
        this.getElement().classList.add("info-enabled");
    }

}

export { BaselayerSwitcher };