Source: map/filters/ui/FilterUi.js

import { SidebarElement } from "../../../ui/sidebar/SidebarElement.js";
import { FilterSettings } from "../FilterSettings.js";

export { FilterUi };

/**
 * Abstract class for Filter Ui Elements.
 * @memberof vef.map.filters.ui
 */
class FilterUi extends SidebarElement {

    /**
     * @param {HTMLElement | string} target
     * @param {object} options filter specific options
     * @param {LayerManager} layers Used for included/excluded layers
     * @param {Map} map
     */
    constructor(target, options, layers, map) {
        super(target, {
            "change": [],
            "remove": [],
            "copy": []
        })

        this.map = map || null;
        this.layers_ = layers || null;
        this.options_ = Object.assign({
            title: "Filter",
            active: true,
            layers: [],
            excludeLayers: true,
            deactivatable: true,
            settingsEnabled: true
        }, options || {});

        this.filterSettings_ = null;
        this.settingsClass_ = FilterSettings;

        this.setTitle(this.options_.title);
        this.initPowerButton_();
        this.initSettingsButton_();
    }

    toggleToolVisibility(classname, show) {
        this.query(".sidebar-element-tool." + classname).style.display = (show) ? "inline-block" : "none";
    }

    /**
     * Init the settings button that allows customizing the filter
     * @private
     */
    initSettingsButton_() {
        this.addTool("fas fa-cog btn-settings", (active, e) => this.openSettings({ pointerEvent: e }), "Filter Settings");
        if (!this.options_.settingsEnabled) this.toggleToolVisibility("btn-settings", false);
    }

    /**
     * Init the power button that enables/disables the filter
     * @private
     */
    initPowerButton_() {
        this.addTool("fas fa-power-off btn-power", active => {
            (active) ? this.disable() : this.enable();
        }, "Enable/Disable", true);

        if (!this.options_.active) {
            const tool = this.query(".sidebar-element-tool.btn-power");
            tool.classList.add("enabled");
            this.disable(true);
        }

        if (!this.options_.deactivatable) this.toggleToolVisibility("btn-power", false);
    }

    /**
     * add tool buttons for showing null values.
     * Depends on the filter implementation if this feature is supported
     * @private
     */
    initShowNullButton_() {
        this.addTool("vef vef-not-available btn-show-null", (active) => {
            this.options_.showNullValues = !!active;
            this.fire("change", this);
        }, "include NULL values", true);

        if (this.options_.showNullValues) {
            const tool = this.query(".sidebar-element-tool.btn-show-null");
            tool.classList.add("enabled");
        }

        if (!this.options_.allowShowNullValues) this.toggleToolVisibility("btn-show-null", false);
    }

    /**
     * Get the filter object to pass it
     * on to the Layers. Override this method in child implementations.
     * 
     * @returns {object} filter object
     */
    getActiveFilter() { }

    /**
     * Get an array of excluded layers
     * represented by their uniqueId
     * 
     * @returns {string[]} 
     */
    getExcludedLayers() {
        let excludedLayers = [];
        if (this.options_.excludeLayers) {
            excludedLayers = this.options_.layers;
        } else if (this.layers_) {
            this.layers_.forEach(layer => {
                if (!this.options_.layers.includes(layer.uniqueId)) {
                    excludedLayers.push(layer.uniqueId);
                }
            });
        }
        return excludedLayers;
    }

    /**
     * Helper method to check if the filter is active
     * @returns {boolean} active
     */
    isActive() {
        return (this.options_.active) ? true : false;
    }

    /**
     * disable pointer events and make content transparent
     * 
     * @param {boolean} noEvent
     * @override
     */
    disable(noEvent) {
        super.disable();
        this.options_.active = false;
        if (!noEvent) this.fire("change", this);
    }

    /**
     * enable pointer events and remove transparency of the content
     * 
     * @param {boolean} noEvent
     * @override
     */
    enable(noEvent) {
        super.enable();
        this.options_.active = true;
        if (!noEvent) this.fire("change", this);
    }

    /**
     * @returns {object} options
     */
    getOptions() {
        return JSON.parse(JSON.stringify(this.options_));
    }

    /**
     * method to reload options after applying settings
     * @override
     */
    reloadOptions_() { }

    /**
     * Open the settings for this filter
     * @param {object} windowOptions optional window options to override
     */
    openSettings(windowOptions) {
        if (!this.filterSettings_) {
            this.filterSettings_ = new this.settingsClass_(this);
            this.filterSettings_.on("apply", options => {
                Object.assign(this.options_, options);
                this.reloadOptions_();
            });
        }
        this.filterSettings_.updateFilterOptions();

        const options = Object.assign({
            title: this.options_.title,
            editTitle: true,
            open: true
        }, windowOptions || {});

        this.filterSettings_.setOptions(options);
    }

    setMap(map) {
        this.map = map;
    }

}