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"}