Source: search/FacetsUi.js

import { Facets } from "./Facets.js";
import { UiElement } from "../ui/UiElement.js";
import { createElement } from "../utils/utils.js";
import { resolveTemplate } from "../utils/template/resolveTemplate.js";
import "./FacetsUi.css";

export { FacetsUi };

/**
 * Handling of defined and selected facets with an additional Ui Element.
 * Listen to the "change" event to add it to the SearchRequest
 * 
 * @author rkoppe <roland.koppe@awi.de>
 * @author rhess <roland.koppe@awi.de>
 * @memberof vef.search
 */
class FacetsUi extends Facets {

    facetsElement = null;
    selectedElement = null;

    facets = {};

    options = {
        facetTitle:
            `<h2>{title}</h2>`,
        facetTemplate:
            `<li>{label} <span>({value})</span></li>`,
        selectTemplate:
            `<li>{label} <span>X</span></li>`
    };

    /**
     * options = {
     *   facetTitle: "<h2>{title}</h2>",
     *   facetTemplate: "<li>{label} <span>({value})</span></li>",
     *   selectTemplate: "<li>{label} <span>X</span></li>"
     * }
     * 
     * @param {string | HTMLElement} facetsTarget 
     * @param {string | HTMLElement} selectedTarget 
     * @param {object} options 
     */
    constructor(facetsTarget, selectedTarget, options) {
        super();

        if (options) this.options = Object.assign(this.options, options);
        this.initElement_(facetsTarget, selectedTarget);
    }

    /**
     * Init the HTML Ui Element
     * @private
     */
    initElement_(facetsTarget, selectedTarget) {
        this.facetsElement = new UiElement(facetsTarget);
        this.facetsElement.getElement().classList.add('facets-ui', 'facets-available');

        this.selectedElement = new UiElement(selectedTarget);
        this.selectedElement.getElement().classList.add('facets-ui', 'facets-selected');
    }

    /**
     * Defines the given title for the given path.
     * This is useful for root facet entries.
     * 
     * @param {string} path 
     * @param {string} title 
     */
    defineFacet(path, title) {
        this.facets[path] = title;
        return this;
    }

    /**
     * Selects a facet for restriction.
     *
     * @param {string} path
     * @param {boolean} triggerEvents default=true
     */
    selectFacet(facet, triggerEvents = true) {
        if (!super.selectFacet(facet, triggerEvents)) return false;

        const html = resolveTemplate(this.options.selectTemplate, facet);
        const element = createElement(html);
        element.data = facet;
        element.setAttribute('path', facet.path);

        element.addEventListener("click", () => this.deselectFacet(facet.path));

        this.selectedElement.getElement().appendChild(element);

        return facet;
    }

    /**
     * Removes the facet identified by path from selected facets.
     *
     * @param {string | object} path path or facet
     * @param {boolean} triggerEvents default=true
     */
    deselectFacet(facet, triggerEvents = true) {
        facet = super.deselectFacet(facet, triggerEvents);
        if (!facet) return false;

        const element = this.selectedElement.getElement().querySelector('[path = "' + facet.path + '"]');
        element.remove();

        return facet;
    }

    /**
     * Sets all available facets.
     *
     * @param {Object} facets
     */
    setAvailableFacets(facets) {
        super.setAvailableFacets(facets);

        // clear ui element
        const container = this.facetsElement.getElement();
        container.innerHTML = "";

        for (let i = 0; i < facets.length; ++i) {
            const facet = facets[i];

            if (facet.children && facet.children.length) {
                facet.title = this.facets[facet.path];
                const html = resolveTemplate(this.options.facetTitle, facet);
                const element = createElement(html);
                container.appendChild(element);

                // facet list container
                const ul = createElement('<ul>');
                container.appendChild(ul);

                for (let j = 0; j < facet.children.length; ++j) {
                    const child = facet.children[j];
                    const html = resolveTemplate(this.options.facetTemplate, child);
                    const element = createElement(html);
                    element.data = child;
                    element.setAttribute('path', child.path);
                    element.addEventListener("click", () => this.selectFacet(child));
                    ul.appendChild(element);
                }

            }
        }

    }

    getFacetsElement() {
        return this.facetsElement;
    }

    getSelectedElement() {
        return this.selectedElement;
    }

}