UNPKG

ui-framework-jps

Version:

A simple UI framework for state management and UI components

256 lines 12.7 kB
import { EXTRA_ACTION_ATTRIBUTE_NAME } from "../ConfigurationTypes"; import debug from 'debug'; import browserUtil from "../../util/BrowserUtil"; const logger = debug('tabular-view-container'); export class TabularViewContainer { constructor(config) { this.viewListeners = []; this.currentTabId = ''; this.isVisible = false; this.config = config; this.views = []; this.tabs = []; this.listeners = []; this.tabElements = []; this.tabViewElements = []; this.handleTabClicked = this.handleTabClicked.bind(this); } addListener(listener) { this.listeners.push(listener); } addVisibilityListener(listener) { this.viewListeners.push(listener); } addViewToTab(tabId, view) { logger(`Adding view to tabular view, with containing tab of ${tabId}`); const foundIndex = this.config.tabs.findIndex((tab) => tab.id === tabId); if (foundIndex >= 0) { this.views.push({ tabId: tabId, view: view }); } } onDocumentLoaded() { logger(`On document loaded`); const containedByEl = document.getElementById(this.config.containedById); if (containedByEl === null) return; logger(`Found contained by ${this.config.containedById} constructing elements`); // construct the tab view container and sub containers let tabViewContainerEl = document.createElement(this.config.tabularViewContainer.type); browserUtil.addAttributes(tabViewContainerEl, this.config.tabularViewContainer.attributes); browserUtil.addClasses(tabViewContainerEl, this.config.tabularViewContainer.classes); browserUtil.addAttributes(tabViewContainerEl, [{ name: 'id', value: this.config.containerId }]); // construct the titlebar container let titleBarContainerEl = document.createElement(this.config.titleBarContainer.type); browserUtil.addAttributes(titleBarContainerEl, this.config.titleBarContainer.attributes); browserUtil.addClasses(titleBarContainerEl, this.config.titleBarContainer.classes); tabViewContainerEl.append(titleBarContainerEl); // construct the item description container this.descriptionElement = document.createElement(this.config.itemDescriptionContainer.type); browserUtil.addAttributes(this.descriptionElement, this.config.itemDescriptionContainer.attributes); browserUtil.addClasses(this.descriptionElement, this.config.itemDescriptionContainer.classes); browserUtil.addAttributes(this.descriptionElement, [{ name: 'id', value: `${this.config.containerId}.description` }]); titleBarContainerEl.append(this.descriptionElement); // extra actions? if (this.config.titleBarActions) { let buttonContainerEl = titleBarContainerEl; if (this.config.titleBarActionsContainer) { let titleBarActionsContainerEl = document.createElement(this.config.titleBarActionsContainer.type); browserUtil.addAttributes(titleBarActionsContainerEl, this.config.titleBarActionsContainer.attributes); browserUtil.addClasses(titleBarActionsContainerEl, this.config.titleBarActionsContainer.classes); titleBarContainerEl.append(titleBarActionsContainerEl); buttonContainerEl = titleBarActionsContainerEl; } this.config.titleBarActions.forEach((extraAction) => { let action = document.createElement('button'); action.setAttribute('type', 'button'); browserUtil.addClasses(action, extraAction.button.classes); browserUtil.addAttributes(action, extraAction.button.attributes); if (extraAction.button.text) { action.innerHTML = extraAction.button.text; } if (extraAction.button.iconClasses) { let iconEl = document.createElement('i'); browserUtil.addClasses(iconEl, extraAction.button.iconClasses); iconEl.setAttribute(EXTRA_ACTION_ATTRIBUTE_NAME, extraAction.name); action.appendChild(iconEl); } action.setAttribute(EXTRA_ACTION_ATTRIBUTE_NAME, extraAction.name); action.addEventListener('click', (event) => { event.preventDefault(); event.stopPropagation(); this.listeners.forEach((listener) => listener.titleBarAction(this, extraAction.name)); }); buttonContainerEl.appendChild(action); }); } // construct the tabs let tabBarContainerEl = document.createElement(this.config.tabBarContainer.type); browserUtil.addAttributes(tabBarContainerEl, this.config.tabBarContainer.attributes); browserUtil.addClasses(tabBarContainerEl, this.config.tabBarContainer.classes); tabViewContainerEl.append(tabBarContainerEl); let tabBarEl = document.createElement(this.config.tabBarElement.type); browserUtil.addAttributes(tabBarEl, this.config.tabBarElement.attributes); browserUtil.addClasses(tabBarEl, this.config.tabBarElement.classes); tabBarContainerEl.appendChild(tabBarEl); // create each item and add event handlers this.config.tabs.forEach((tab) => { logger(`Constructing tab ${tab.id} `); let tabEl = document.createElement(tab.element.type); browserUtil.addAttributes(tabEl, tab.element.attributes); browserUtil.addClasses(tabEl, tab.element.classes); tabBarEl.appendChild(tabEl); if (tab.subElement) { let subTabEl = document.createElement(tab.subElement.type); browserUtil.addAttributes(subTabEl, tab.subElement.attributes); browserUtil.addClasses(subTabEl, tab.subElement.classes); browserUtil.addAttributes(subTabEl, [{ name: 'id', value: `${this.config.containerId}.tab.${tab.id}` }]); tabEl.appendChild(subTabEl); if (tab.subElement.innerHTML) subTabEl.innerHTML = tab.subElement.innerHTML; subTabEl.addEventListener('click', this.handleTabClicked); if (tab.isDefaultActive) { browserUtil.addAttributes(subTabEl, [{ name: 'active', value: 'true' }]); browserUtil.addClasses(subTabEl, 'active'); } else { browserUtil.removeAttributes(subTabEl, ['active']); browserUtil.removeClasses(subTabEl, 'active'); } this.tabElements.push(subTabEl); this.tabs.push({ tabId: tab.id, tabElement: subTabEl }); } else { if (tab.element.innerHTML) tabEl.innerHTML = tab.element.innerHTML; browserUtil.addAttributes(tabEl, [{ name: 'id', value: `${this.config.containerId}.tab.${tab.id}` }]); tabEl.addEventListener('click', this.handleTabClicked); if (tab.isDefaultActive) { browserUtil.addAttributes(tabEl, [{ name: 'active', value: 'true' }]); browserUtil.addClasses(tabEl, 'active'); } else { browserUtil.removeAttributes(tabEl, ['active']); browserUtil.removeClasses(tabEl, 'active'); } this.tabElements.push(tabEl); this.tabs.push({ tabId: tab.id, tabElement: tabEl }); } }); containedByEl.appendChild(tabViewContainerEl); // create the view containers and let the views know what contains them this.config.tabs.forEach((tab) => { logger(`Constructing tab ${tab.id} view`); // find the view and let it know about the containing element const foundIndex = this.views.findIndex((tabView) => tabView.tabId === tab.id); let view = null; if (foundIndex >= 0) { view = this.views[foundIndex].view; } let tabViewEl = document.createElement(this.config.tabViewContainer.type); browserUtil.addAttributes(tabViewEl, this.config.tabViewContainer.attributes); browserUtil.addClasses(tabViewEl, this.config.tabViewContainer.classes); browserUtil.addAttributes(tabViewEl, [{ name: 'id', value: `${this.config.containerId}.view.${tab.id}` }]); tabViewContainerEl.appendChild(tabViewEl); if (view) { view.setContainedBy(tabViewEl); view.onDocumentLoaded(); } if (tab.isDefaultActive) { browserUtil.removeClasses(tabViewEl, 'd-none'); if (view) view.show(); this.currentTabId = tab.id; } else { browserUtil.addClasses(tabViewEl, 'd-none'); if (view) view.hide(); } this.tabViewElements.push(tabViewEl); }); } setDescription(description) { if (this.descriptionElement) { this.descriptionElement.innerHTML = description; } } selectTab(tabId) { this.currentTabId = tabId; this.tabElements.forEach((tabElement, index) => { const tabViewElement = this.tabViewElements[index]; let tabElementId = tabElement.getAttribute('id'); if (tabElementId) { const idComponents = tabElementId.split('.'); const tabIdForTabElement = idComponents[idComponents.length - 1]; const foundIndex = this.views.findIndex((tabView) => tabView.tabId === tabIdForTabElement); let view = null; if (foundIndex >= 0) { view = this.views[foundIndex].view; } if (tabElementId) { if (tabIdForTabElement === tabId) { // mark the tab as active and let the view know browserUtil.addAttributes(tabElement, [{ name: 'active', value: 'true' }]); browserUtil.removeClasses(tabViewElement, 'd-none'); browserUtil.addClasses(tabElement, 'active'); if (view) view.show(); } else { browserUtil.removeAttributes(tabElement, ['active']); browserUtil.addClasses(tabViewElement, 'd-none'); browserUtil.removeClasses(tabElement, 'active'); if (view) view.hide(); } } } }); } show() { logger('TVC show'); this.isVisible = true; this.selectTab(this.currentTabId); this.viewListeners.forEach((listener) => listener.nowShowing(this)); } hide() { logger('TVC hide'); this.isVisible = false; this.views.forEach((view) => { view.view.hide(); }); this.viewListeners.forEach((listener) => listener.nowHidden(this)); } isShowing() { return false; } handleTabClicked(event) { logger(`handling tab clicked`); event.stopPropagation(); event.preventDefault(); if (event.target) { const targetEl = (event.target); const targetId = targetEl.getAttribute('id'); const targetActive = targetEl.getAttribute('active'); logger(`Tab ${targetId} with active status ${targetActive}`); if (targetId) { const idComponents = targetId.split('.'); const tabId = idComponents[idComponents.length - 1]; logger(`tab id ${tabId} has been clicked`); if (targetActive) { logger(`tab ${targetId} is already active - doing nothing`); } else { logger(`tab ${targetId} is not active - setting active and letting the views know`); this.selectTab(tabId); } // let the listeners know this.listeners.forEach((listener) => listener.tabChanged(this, tabId)); } } } } //# sourceMappingURL=TabularViewContainer.js.map