|
@@ -1,251 +0,0 @@
|
|
|
-import { getElements, replaceAll, findFirstAdjacent } from '../util';
|
|
|
|
|
-
|
|
|
|
|
-type ShowHide = 'show' | 'hide';
|
|
|
|
|
-
|
|
|
|
|
-function isShowHide(value: unknown): value is ShowHide {
|
|
|
|
|
- return typeof value === 'string' && ['show', 'hide'].includes(value);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-/**
|
|
|
|
|
- * When this error is thrown, it's an indication that we don't need to manage this table, because
|
|
|
|
|
- * it doesn't contain the required elements.
|
|
|
|
|
- */
|
|
|
|
|
-class TableStateError extends Error {
|
|
|
|
|
- table: HTMLTableElement;
|
|
|
|
|
- constructor(message: string, table: HTMLTableElement) {
|
|
|
|
|
- super(message);
|
|
|
|
|
- this.table = table;
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-/**
|
|
|
|
|
- * Manage the display text of a button element as well as the visibility of its corresponding rows.
|
|
|
|
|
- */
|
|
|
|
|
-class ButtonState {
|
|
|
|
|
- /**
|
|
|
|
|
- * Underlying Button DOM Element
|
|
|
|
|
- */
|
|
|
|
|
- public button: HTMLButtonElement;
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Table rows provided in constructor
|
|
|
|
|
- */
|
|
|
|
|
- private rows: NodeListOf<HTMLTableRowElement>;
|
|
|
|
|
-
|
|
|
|
|
- constructor(button: HTMLButtonElement, rows: NodeListOf<HTMLTableRowElement>) {
|
|
|
|
|
- this.button = button;
|
|
|
|
|
- this.rows = rows;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Remove visibility of button state rows.
|
|
|
|
|
- */
|
|
|
|
|
- private hideRows(): void {
|
|
|
|
|
- for (const row of this.rows) {
|
|
|
|
|
- row.classList.add('d-none');
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Update the DOM element's `data-state` attribute.
|
|
|
|
|
- */
|
|
|
|
|
- public set buttonState(state: Nullable<ShowHide>) {
|
|
|
|
|
- if (isShowHide(state)) {
|
|
|
|
|
- this.button.setAttribute('data-state', state);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Get the DOM element's `data-state` attribute.
|
|
|
|
|
- */
|
|
|
|
|
- public get buttonState(): Nullable<ShowHide> {
|
|
|
|
|
- const state = this.button.getAttribute('data-state');
|
|
|
|
|
- if (isShowHide(state)) {
|
|
|
|
|
- return state;
|
|
|
|
|
- }
|
|
|
|
|
- return null;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Update the DOM element's display text to reflect the action opposite the current state. For
|
|
|
|
|
- * example, if the current state is to hide enabled interfaces, the DOM text should say
|
|
|
|
|
- * "Show Enabled Interfaces".
|
|
|
|
|
- */
|
|
|
|
|
- private toggleButton(): void {
|
|
|
|
|
- if (this.buttonState === 'show') {
|
|
|
|
|
- this.button.innerText = replaceAll(this.button.innerText, 'Show', 'Hide');
|
|
|
|
|
- } else if (this.buttonState === 'hide') {
|
|
|
|
|
- this.button.innerText = replaceAll(this.button.innerHTML, 'Hide', 'Show');
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Toggle the DOM element's `data-state` attribute.
|
|
|
|
|
- */
|
|
|
|
|
- private toggleState(): void {
|
|
|
|
|
- if (this.buttonState === 'show') {
|
|
|
|
|
- this.buttonState = 'hide';
|
|
|
|
|
- } else if (this.buttonState === 'hide') {
|
|
|
|
|
- this.buttonState = 'show';
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Toggle all controlled elements.
|
|
|
|
|
- */
|
|
|
|
|
- private toggle(): void {
|
|
|
|
|
- this.toggleState();
|
|
|
|
|
- this.toggleButton();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * When the button is clicked, toggle all controlled elements and hide rows based on
|
|
|
|
|
- * buttonstate.
|
|
|
|
|
- */
|
|
|
|
|
- public handleClick(event: Event): void {
|
|
|
|
|
- const button = event.currentTarget as HTMLButtonElement;
|
|
|
|
|
- if (button.isEqualNode(this.button)) {
|
|
|
|
|
- this.toggle();
|
|
|
|
|
- }
|
|
|
|
|
- if (this.buttonState === 'hide') {
|
|
|
|
|
- this.hideRows();
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-/**
|
|
|
|
|
- * Manage the state of a table and its elements.
|
|
|
|
|
- */
|
|
|
|
|
-class TableState {
|
|
|
|
|
- /**
|
|
|
|
|
- * Underlying DOM Table Element.
|
|
|
|
|
- */
|
|
|
|
|
-
|
|
|
|
|
- private table: HTMLTableElement;
|
|
|
|
|
- /**
|
|
|
|
|
- * Instance of ButtonState for the 'show/hide enabled rows' button.
|
|
|
|
|
- */
|
|
|
|
|
- // @ts-expect-error null handling is performed in the constructor
|
|
|
|
|
- private enabledButton: ButtonState;
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Instance of ButtonState for the 'show/hide disabled rows' button.
|
|
|
|
|
- */
|
|
|
|
|
- // @ts-expect-error null handling is performed in the constructor
|
|
|
|
|
- private disabledButton: ButtonState;
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Instance of ButtonState for the 'show/hide virtual rows' button.
|
|
|
|
|
- */
|
|
|
|
|
- // @ts-expect-error null handling is performed in the constructor
|
|
|
|
|
- private virtualButton: ButtonState;
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Instance of ButtonState for the 'show/hide virtual rows' button.
|
|
|
|
|
- */
|
|
|
|
|
- // @ts-expect-error null handling is performed in the constructor
|
|
|
|
|
- private disconnectedButton: ButtonState;
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * All table rows in table
|
|
|
|
|
- */
|
|
|
|
|
- private rows: NodeListOf<HTMLTableRowElement>;
|
|
|
|
|
-
|
|
|
|
|
- constructor(table: HTMLTableElement) {
|
|
|
|
|
- this.table = table;
|
|
|
|
|
- this.rows = this.table.querySelectorAll('tr');
|
|
|
|
|
- try {
|
|
|
|
|
- const toggleEnabledButton = findFirstAdjacent<HTMLButtonElement>(
|
|
|
|
|
- this.table,
|
|
|
|
|
- 'button.toggle-enabled',
|
|
|
|
|
- );
|
|
|
|
|
- const toggleDisabledButton = findFirstAdjacent<HTMLButtonElement>(
|
|
|
|
|
- this.table,
|
|
|
|
|
- 'button.toggle-disabled',
|
|
|
|
|
- );
|
|
|
|
|
- const toggleVirtualButton = findFirstAdjacent<HTMLButtonElement>(
|
|
|
|
|
- this.table,
|
|
|
|
|
- 'button.toggle-virtual',
|
|
|
|
|
- );
|
|
|
|
|
- const toggleDisconnectedButton = findFirstAdjacent<HTMLButtonElement>(
|
|
|
|
|
- this.table,
|
|
|
|
|
- 'button.toggle-disconnected',
|
|
|
|
|
- );
|
|
|
|
|
-
|
|
|
|
|
- if (toggleEnabledButton === null) {
|
|
|
|
|
- throw new TableStateError("Table is missing a 'toggle-enabled' button.", table);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (toggleDisabledButton === null) {
|
|
|
|
|
- throw new TableStateError("Table is missing a 'toggle-disabled' button.", table);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (toggleVirtualButton === null) {
|
|
|
|
|
- throw new TableStateError("Table is missing a 'toggle-virtual' button.", table);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (toggleDisconnectedButton === null) {
|
|
|
|
|
- throw new TableStateError("Table is missing a 'toggle-disconnected' button.", table);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Attach event listeners to the buttons elements.
|
|
|
|
|
- toggleEnabledButton.addEventListener('click', event => this.handleClick(event, this));
|
|
|
|
|
- toggleDisabledButton.addEventListener('click', event => this.handleClick(event, this));
|
|
|
|
|
- toggleVirtualButton.addEventListener('click', event => this.handleClick(event, this));
|
|
|
|
|
- toggleDisconnectedButton.addEventListener('click', event => this.handleClick(event, this));
|
|
|
|
|
-
|
|
|
|
|
- // Instantiate ButtonState for each button for state management.
|
|
|
|
|
- this.enabledButton = new ButtonState(
|
|
|
|
|
- toggleEnabledButton,
|
|
|
|
|
- table.querySelectorAll<HTMLTableRowElement>('tr[data-enabled="enabled"]'),
|
|
|
|
|
- );
|
|
|
|
|
- this.disabledButton = new ButtonState(
|
|
|
|
|
- toggleDisabledButton,
|
|
|
|
|
- table.querySelectorAll<HTMLTableRowElement>('tr[data-enabled="disabled"]'),
|
|
|
|
|
- );
|
|
|
|
|
- this.virtualButton = new ButtonState(
|
|
|
|
|
- toggleVirtualButton,
|
|
|
|
|
- table.querySelectorAll<HTMLTableRowElement>('tr[data-type="virtual"]'),
|
|
|
|
|
- );
|
|
|
|
|
- this.disconnectedButton = new ButtonState(
|
|
|
|
|
- toggleDisconnectedButton,
|
|
|
|
|
- table.querySelectorAll<HTMLTableRowElement>('tr[data-connected="disconnected"]'),
|
|
|
|
|
- );
|
|
|
|
|
- } catch (err) {
|
|
|
|
|
- if (err instanceof TableStateError) {
|
|
|
|
|
- // This class is useless for tables that don't have toggle buttons.
|
|
|
|
|
- console.debug('Table does not contain enable/disable toggle buttons');
|
|
|
|
|
- return;
|
|
|
|
|
- } else {
|
|
|
|
|
- throw err;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * When toggle buttons are clicked, reapply visability all rows and
|
|
|
|
|
- * pass the event to all button handlers
|
|
|
|
|
- *
|
|
|
|
|
- * @param event onClick event for toggle buttons.
|
|
|
|
|
- * @param instance Instance of TableState (`this` cannot be used since that's context-specific).
|
|
|
|
|
- */
|
|
|
|
|
- public handleClick(event: Event, instance: TableState): void {
|
|
|
|
|
- for (const row of this.rows) {
|
|
|
|
|
- row.classList.remove('d-none');
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- instance.enabledButton.handleClick(event);
|
|
|
|
|
- instance.disabledButton.handleClick(event);
|
|
|
|
|
- instance.virtualButton.handleClick(event);
|
|
|
|
|
- instance.disconnectedButton.handleClick(event);
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-/**
|
|
|
|
|
- * Initialize table states.
|
|
|
|
|
- */
|
|
|
|
|
-export function initInterfaceTable(): void {
|
|
|
|
|
- for (const element of getElements<HTMLTableElement>('table')) {
|
|
|
|
|
- new TableState(element);
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|