MDL-72776 theme_boost: new editing progress effect
[moodle.git] / lib / amd / build / local / reactive / basecomponent.min.js.map
bloba984216cb2d5810ecbe7eaf91ebcc0aa896c1033
1 {"version":3,"sources":["../../../src/local/reactive/basecomponent.js"],"names":["descriptor","element","HTMLElement","Error","eventHandlers","Map","eventListeners","selectors","events","constructor","getEvents","create","addSelectors","reactive","dispatchEvent","CustomEvent","bubbles","detail","component","registerComponent","addEventListener","event","stopPropagation","registerChildComponent","query","dataId","dataSelector","selector","querySelector","querySelectorAll","newSelectors","Object","entries","selectorName","eventName","target","file","data","Promise","resolve","reject","Templates","renderForPromise","then","html","js","replaceNodeContents","catch","error","type","listener","bindListener","get","bind","set","push","removeEventListener","forEach","unregister","remove","unregisterComponent","removeAllEventListeners","destroy","parentNode","locked","dataset","style","pointerEvents","userSelect","hasAttribute","setAttribute","setElementLocked","getElementLocked"],"mappings":"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","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.\n\nimport Templates from 'core/templates';\n\n/**\n * Reactive UI component base class.\n *\n * Each UI reactive component should extend this class to interact with a reactive state.\n *\n * @module     core/local/reactive/basecomponent\n * @class     core/local/reactive/basecomponent\n * @copyright  2020 Ferran Recio <ferran@moodle.com>\n * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nexport default class {\n\n    /**\n     * The component descriptor data structure.\n     *\n     * This structure is used by any component and init method to define the way the component will interact\n     * with the interface and whith reactive instance operates. The logic behind this object is to avoid\n     * unnecessary dependancies between the final interface and the state logic.\n     *\n     * Any component interacts with a single main DOM element (description.element) but it can use internal\n     * selector to select elements within this main element (descriptor.selectors). By default each component\n     * will provide it's own default selectors, but those can be overridden by the \"descriptor.selectors\"\n     * property in case the mustache wants to reuse the same component logic but with a different interface.\n     *\n     * @typedef {object} descriptor\n     * @property {Reactive} reactive an optional reactive module to register in\n     * @property {DOMElement} element all components needs an element to anchor events\n     * @property {object} [selectors] an optional object to override query selectors\n     */\n\n    /**\n     * The class constructor.\n     *\n     * The only param this method gets is a constructor with all the mandatory\n     * and optional component data. Component will receive the same descriptor\n     * as create method param.\n     *\n     * This method will call the \"create\" method before registering the component into\n     * the reactive module. This way any component can add default selectors and events.\n     *\n     * @param {descriptor} descriptor data to create the object.\n     */\n    constructor(descriptor) {\n\n        if (descriptor.element === undefined || !(descriptor.element instanceof HTMLElement)) {\n            throw Error(`Reactive components needs a main DOM element to dispatch events`);\n        }\n\n        this.element = descriptor.element;\n\n        // Variable to track event listeners.\n        this.eventHandlers = new Map([]);\n        this.eventListeners = [];\n\n        // Empty default component selectors.\n        this.selectors = {};\n\n        // Empty default event list from the static method.\n        this.events = this.constructor.getEvents();\n\n        // Call create function to get the component defaults.\n        this.create(descriptor);\n\n        // Overwrite the components selectors if necessary.\n        if (descriptor.selectors !== undefined) {\n            this.addSelectors(descriptor.selectors);\n        }\n\n        // Register into a reactive instance.\n        if (descriptor.reactive === undefined) {\n            // Ask parent components for registration.\n            this.element.dispatchEvent(new CustomEvent(\n                'core/reactive:requestRegistration',\n                {\n                    bubbles: true,\n                    detail: {component: this},\n                }\n            ));\n        } else {\n            this.reactive = descriptor.reactive;\n            this.reactive.registerComponent(this);\n            // Add a listener to register child components.\n            this.addEventListener(\n                this.element,\n                'core/reactive:requestRegistration',\n                (event) => {\n                    if (event?.detail?.component) {\n                        event.stopPropagation();\n                        this.registerChildComponent(event.detail.component);\n                    }\n                }\n            );\n        }\n    }\n\n    /**\n     * Return the component custom event names.\n     *\n     * Components may override this method to provide their own events.\n     *\n     * Component custom events is an important part of component reusability. This function\n     * is static because is part of the component definition and should be accessible from\n     * outsite the instances. However, values will be available at instance level in the\n     * this.events object.\n     *\n     * @returns {Object} the component events.\n     */\n    static getEvents() {\n        return {};\n    }\n\n    /**\n     * Component create function.\n     *\n     * Default init method will call \"create\" when all internal attributes are set\n     * but before the component is not yet registered in the reactive module.\n     *\n     * In this method any component can define its own defaults such as:\n     * - this.selectors {object} the default query selectors of this component.\n     * - this.events {object} a list of event names this component dispatch\n     * - extract any data from the main dom element (this.element)\n     * - set any other data the component uses\n     *\n     * @param {descriptor} descriptor the component descriptor\n     */\n    // eslint-disable-next-line no-unused-vars\n    create(descriptor) {\n        // Components may override this method to initialize selects, events or other data.\n    }\n\n    /**\n     * Component destroy hook.\n     *\n     * BaseComponent call this method when a component is unregistered or removed.\n     *\n     * Components may override this method to clean the HTML or do some action when the\n     * component is unregistered or removed.\n     */\n    destroy() {\n        // Components can override this method.\n    }\n\n    /**\n     * Return the list of watchers that component has.\n     *\n     * Each watcher is represented by an object with two attributes:\n     * - watch (string) the specific state event to watch. Example 'section.visible:updated'\n     * - handler (function) the function to call when the watching state change happens\n     *\n     * Any component shoudl override this method to define their state watchers.\n     *\n     * @returns {array} array of watchers.\n     */\n    getWatchers() {\n        return [];\n    }\n\n    /**\n     * Reactive module will call this method when the state is ready.\n     *\n     * Component can override this method to update/load the component HTML or to bind\n     * listeners to HTML entities.\n     */\n    stateReady() {\n        // Components can override this method.\n    }\n\n    /**\n     * Get the main DOM element of this component or a subelement.\n     *\n     * @param {string|undefined} query optional subelement query\n     * @param {string|undefined} dataId optional data-id value\n     * @returns {element|undefined} the DOM element (if any)\n     */\n    getElement(query, dataId) {\n        if (query === undefined && dataId === undefined) {\n            return this.element;\n        }\n        const dataSelector = (dataId) ? `[data-id='${dataId}']` : '';\n        const selector = `${query ?? ''}${dataSelector}`;\n        return this.element.querySelector(selector);\n    }\n\n    /**\n     * Get the all subelement that match a query selector.\n     *\n     * @param {string|undefined} query optional subelement query\n     * @param {string|undefined} dataId optional data-id value\n     * @returns {NodeList} the DOM elements\n     */\n    getElements(query, dataId) {\n        const dataSelector = (dataId) ? `[data-id='${dataId}']` : '';\n        const selector = `${query ?? ''}${dataSelector}`;\n        return this.element.querySelectorAll(selector);\n    }\n\n    /**\n     * Add or update the component selectors.\n     *\n     * @param {Object} newSelectors an object of new selectors.\n     */\n    addSelectors(newSelectors) {\n        for (const [selectorName, selector] of Object.entries(newSelectors)) {\n            this.selectors[selectorName] = selector;\n        }\n    }\n\n    /**\n     * Return a component selector.\n     *\n     * @param {string} selectorName the selector name\n     * @return {string|undefined} the query selector\n     */\n    getSelector(selectorName) {\n        return this.selectors[selectorName];\n    }\n\n    /**\n     * Dispatch a custom event on this.element.\n     *\n     * This is just a convenient method to dispatch custom events from within a component.\n     * Components are free to use an alternative function to dispatch custom\n     * events. The only restriction is that it should be dispatched on this.element\n     * and specify \"bubbles:true\" to alert any component listeners.\n     *\n     * @param {string} eventName the event name\n     * @param {*} detail event detail data\n     */\n    dispatchEvent(eventName, detail) {\n        this.element.dispatchEvent(new CustomEvent(eventName, {\n            bubbles: true,\n            detail: detail,\n        }));\n    }\n\n    /**\n     * Render a new Component using a mustache file.\n     *\n     * It is important to note that this method should NOT be used for loading regular mustache files\n     * as it returns a Promise that will only be resolved if the mustache registers a component instance.\n     *\n     * @param {element} target the DOM element that contains the component\n     * @param {string} file the component mustache file to render\n     * @param {*} data the mustache data\n     * @return {Promise} a promise of the resulting component instance\n     */\n    renderComponent(target, file, data) {\n        return new Promise((resolve, reject) => {\n            target.addEventListener('ComponentRegistration:Success', ({detail}) => {\n                resolve(detail.component);\n            });\n            target.addEventListener('ComponentRegistration:Fail', () => {\n                reject(`Registration of ${file} fails.`);\n            });\n            Templates.renderForPromise(\n                file,\n                data\n            ).then(({html, js}) => {\n                Templates.replaceNodeContents(target, html, js);\n                return true;\n            }).catch(error => {\n                reject(`Rendering of ${file} throws an error.`);\n                throw error;\n            });\n        });\n    }\n\n    /**\n     * Add and bind an event listener to a target and keep track of all event listeners.\n     *\n     * The native element.addEventListener method is not object oriented friently as the\n     * \"this\" represents the element that triggers the event and not the listener class.\n     * As components can be unregister and removed at any time, the BaseComponent provides\n     * this method to keep track of all component listeners and do all of the bind stuff.\n     *\n     * @param {Element} target the event target\n     * @param {string} type the event name\n     * @param {function} listener the class method that recieve the event\n     */\n    addEventListener(target, type, listener) {\n\n        // Check if we have the bind version of that listener.\n        let bindListener = this.eventHandlers.get(listener);\n\n        if (bindListener === undefined) {\n            bindListener = listener.bind(this);\n            this.eventHandlers.set(listener, bindListener);\n        }\n\n        target.addEventListener(type, bindListener);\n\n        // Keep track of all component event listeners in case we need to remove them.\n        this.eventListeners.push({\n            target,\n            type,\n            bindListener,\n        });\n\n    }\n\n    /**\n     * Remove an event listener from a component.\n     *\n     * This method allows components to remove listeners without keeping track of the\n     * listeners bind versions of the method. Both addEventListener and removeEventListener\n     * keeps internally the relation between the original class method and the bind one.\n     *\n     * @param {Element} target the event target\n     * @param {string} type the event name\n     * @param {function} listener the class method that recieve the event\n     */\n    removeEventListener(target, type, listener) {\n        // Check if we have the bind version of that listener.\n        let bindListener = this.eventHandlers.get(listener);\n\n        if (bindListener === undefined) {\n            // This listener has not been added.\n            return;\n        }\n\n        target.removeEventListener(type, bindListener);\n    }\n\n    /**\n     * Remove all event listeners from this component.\n     *\n     * This method is called also when the component is unregistered or removed.\n     *\n     * Note that only listeners registered with the addEventListener method\n     * will be removed. Other manual listeners will keep active.\n     */\n    removeAllEventListeners() {\n        this.eventListeners.forEach(({target, type, bindListener}) => {\n            target.removeEventListener(type, bindListener);\n        });\n        this.eventListeners = [];\n    }\n\n    /**\n     * Remove a previously rendered component instance.\n     *\n     * This method will remove the component HTML and unregister it from the\n     * reactive module.\n     */\n    remove() {\n        this.unregister();\n        this.element.remove();\n    }\n\n    /**\n     * Unregister the component from the reactive module.\n     *\n     * This method will disable the component logic, event listeners and watchers\n     * but it won't remove any HTML created by the component. However, it will trigger\n     * the destroy hook to allow the component to clean parts of the interface.\n     */\n    unregister() {\n        this.reactive.unregisterComponent(this);\n        this.removeAllEventListeners();\n        this.destroy();\n    }\n\n    /**\n     * Dispatch a component registration event to inform the parent node.\n     *\n     * The registration event is different from the rest of the component events because\n     * is the only way in which components can communicate its existence to a possible parent.\n     * Most components will be created by including a mustache file, child components\n     * must emit a registration event to the parent DOM element to alert about the registration.\n     */\n    dispatchRegistrationSuccess() {\n        // The registration event does not bubble because we just want to comunicate with the parentNode.\n        // Otherwise, any component can get multiple registrations events and could not differentiate\n        // between child components and grand child components.\n        if (this.element.parentNode === undefined) {\n            return;\n        }\n        // This custom element is captured by renderComponent method.\n        this.element.parentNode.dispatchEvent(new CustomEvent(\n            'ComponentRegistration:Success',\n            {\n                bubbles: false,\n                detail: {component: this},\n            }\n        ));\n    }\n\n    /**\n     * Dispatch a component registration fail event to inform the parent node.\n     *\n     * As dispatchRegistrationSuccess, this method will communicate the registration fail to the\n     * parent node to inform the possible parent component.\n     */\n    dispatchRegistrationFail() {\n        if (this.element.parentNode === undefined) {\n            return;\n        }\n        // This custom element is captured only by renderComponent method.\n        this.element.parentNode.dispatchEvent(new CustomEvent(\n            'ComponentRegistration:Fail',\n            {\n                bubbles: false,\n                detail: {component: this},\n            }\n        ));\n    }\n\n    /**\n     * Register a child component into the reactive instance.\n     *\n     * @param {self} component the component to register.\n     */\n    registerChildComponent(component) {\n        component.reactive = this.reactive;\n        this.reactive.registerComponent(component);\n    }\n\n    /**\n     * Set the lock value and locks or unlocks the element.\n     *\n     * @param {boolean} locked the new locked value\n     */\n    set locked(locked) {\n        this.setElementLocked(this.element, locked);\n    }\n\n    /**\n     * Get the current locked value from the element.\n     *\n     * @return {boolean}\n     */\n    get locked() {\n        return this.getElementLocked(this.element);\n    }\n\n    /**\n     * Lock/unlock an element.\n     *\n     * @param {Element} target the event target\n     * @param {boolean} locked the new locked value\n     */\n    setElementLocked(target, locked) {\n        target.dataset.locked = locked ?? false;\n        if (locked) {\n            // Disable interactions.\n            target.style.pointerEvents = 'none';\n            target.style.userSelect = 'none';\n            // Check if it is draggable.\n            if (target.hasAttribute('draggable')) {\n                target.setAttribute('draggable', false);\n            }\n            target.setAttribute('aria-busy', true);\n        } else {\n            // Enable interactions.\n            target.style.pointerEvents = null;\n            target.style.userSelect = null;\n            // Check if it was draggable.\n            if (target.hasAttribute('draggable')) {\n                target.setAttribute('draggable', true);\n            }\n            target.setAttribute('aria-busy', false);\n        }\n    }\n\n    /**\n     * Get the current locked value from the element.\n     *\n     * @param {Element} target the event target\n     * @return {boolean}\n     */\n    getElementLocked(target) {\n        return target.dataset.locked ?? false;\n    }\n}\n"],"file":"basecomponent.min.js"}