UNPKG

@schukai/monster

Version:

Monster is a simple library for creating fast, robust and lightweight websites.

221 lines (192 loc) 4.63 kB
/** * Copyright © Volker Schukai and all contributing authors, {{copyRightYear}}. All rights reserved. * Node module: @schukai/monster * * This source code is licensed under the GNU Affero General Public License version 3 (AGPLv3). * The full text of the license can be found at: https://www.gnu.org/licenses/agpl-3.0.en.html * * For those who do not wish to adhere to the AGPLv3, a commercial license is available. * Acquiring a commercial license allows you to use this software without complying with the AGPLv3 terms. * For more information about purchasing a commercial license, please contact Volker Schukai. * * SPDX-License-Identifier: AGPL-3.0 */ import { Datasource, dataSourceSymbol } from "../datasource.mjs"; import { DatasourceStyleSheet } from "../stylesheet/datasource.mjs"; import { instanceSymbol } from "../../../constants.mjs"; import { assembleMethodSymbol, registerCustomElement, getSlottedElements, } from "../../../dom/customelement.mjs"; import { isArray } from "../../../types/is.mjs"; export { Dom }; /** * @private * @type {symbol} */ const dataChangeEventHandlerSymbol = Symbol("dataChangeEventHandler"); /** * The Datasource component is a basic class for the datatable component. * * @copyright Volker Schukai * @summary A dom datasource */ class Dom extends Datasource { /** * This method is called by the `instanceof` operator. * @return {symbol} */ static get [instanceSymbol]() { return Symbol.for("@schukai/monster/components/datasource/dom@@instance"); } /** * To set the options via the HTML tag, the attribute `data-monster-options` must be used. * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control} * * The individual configuration values can be found in the table. * * @property {Object} templates Template definitions * @property {string} templates.main Main template * @property {Object} features Feature definitions * @property {boolean} features.autoInit Automatically initializes the component */ get defaults() { return Object.assign({}, super.defaults, { templates: { main: getTemplate(), }, features: { autoInit: true, }, /** @private */ sys: { pagination: { pages: 1, objectsPerPage: 10, currentPage: 1, }, }, }); } /** * @return {void} */ [assembleMethodSymbol]() { super[assembleMethodSymbol](); initEventHandler.call(this); updateDataSource.call(this); } /** * This method set the current page of the pagination * * @param {string} page * @return {Dom} */ setParameters({ page }) { this.setOption("sys.pagination.currentPage", page); return this; } /** * * @return {CSSStyleSheet[]} */ static getCSSStyleSheet() { return [DatasourceStyleSheet]; } /** * @private * @return {string} */ static getTag() { return "monster-datasource-dom"; } /** * Reloads the data * @return {Promise<never>|*} */ reload() {} /** * @return {void} */ connectedCallback() { super.connectedCallback(); if (this.getOption("features.autoInit")) { updateDataSource.call(this); } } /** * @return {int} */ currentPage() { return this.getOption("sys.pagination.currentPage"); } } /** * @private */ function initEventHandler() { /** * @param {Event} event */ this[dataChangeEventHandlerSymbol] = (event) => { updateDataSource.call(this); }; new MutationObserver(this[dataChangeEventHandlerSymbol]).observe(this, { childList: true, subtree: true, characterData: true, }); } /** * @private */ function updateDataSource() { let data = null; getSlottedElements.call(this).forEach((element) => { if (!(element instanceof HTMLScriptElement)) { return; } if (element.type !== "application/json") { return; } const d = JSON.parse(element.textContent); if (data === null) { if (isArray(d)) { data = []; } else { data = {}; } } if (isArray(data) && !isArray(d)) { throw new Error("Type mismatch"); } if (!isArray(data) && isArray(d)) { throw new Error("Type mismatch"); } if (isArray(data)) { data.push(...d); return; } data = Object.assign({}, d); }); if (data === null) { data = []; } // set pagination this.setOption("sys.pagination.objectsPerPage", 1); this.setOption("sys.pagination.pages", data.length); this.setOption("sys.pagination.currentPage", 1); /** call setter */ this.data = data; } /** * @private * @return {string} */ function getTemplate() { // language=HTML return ` <slot data-monster-role="datasource"></slot>`; } registerCustomElement(Dom);