Source: vga.primitives.js

/**
 * Clase primitiva de los controles a mostrar en la página
 * @abstract
 */
class ControlPrimitive {
  #name;
  #label;
  #description;

  /**
   * Constructor por defecto
   * @param {string} name Nombre del control
   * @param {string} label Etiqueta del control
   * @param {string} description Descripción del control
   */
  constructor(name, label, description) {
    if (this.constructor == ControlPrimitive) {
      throw new Error(
        "ControlPrimitive es una clase abstracta y no se puede instanciar."
      );
    }
    this.#name = name;
    this.#label = label;
    this.#description = description;
  }

  /**
   * Actualiza el control
   * @abstract
   */
  #updateControl() {
    throw new Error("Método 'updateControl()' debe de ser implementado.");
  }

  /**
   * Obtiene el html del control
   * @return El código html del control
   * @abstract
   */
  getHtmlCode() {
    throw new Error("Método 'getHtmlCode()' debe de ser implementado.");
  }

  /**
   * Lee los datos del control
   * @abstract
   */
  readControl() {
    throw new Error("Método 'readControl()' debe de ser implementado.");
  }

  /**
   * Retorna el nombre del control
   * @returns El nombre del control
   */
  getName() {
    return this.#name;
  }

  /**
   * Establece la etiqueta del control
   * @param {string} label Etiqueta del control
   */
  setLabel(label) {
    this.#label = label;
    this.#updateControl();
  }

  /**
   * Obtiene la etiqueta del control
   * @returns Etiqueta del control
   */
  getLabel() {
    return this.#label;
  }

  /**
   * Establece la descripción del control
   * @param {string} description Descripción del control
   */
  setDescription(description) {
    this.#description = description;
    this.#updateControl();
  }

  /**
   * Obtiene la descripción del control
   * @returns Descripción del control
   */
  getDescription() {
    return this.#description;
  }
}

/**
 * Clase primitiva que representa un control de tipo caja de texto
 * @extends {ControlPrimitive}
 * @abstract
 */
class TextBoxPrimitive extends ControlPrimitive {
  #data;

  /**
   * Constructor por defecto
   * @param {string} name Nombre del control
   * @param {string} label Etiqueta del control
   * @param {string} description Descripción del control
   * @param {object} data Valor del control
   */
  constructor(name, label, description, data) {
    super(name, label, description);
    if (this.constructor == TextBoxPrimitive) {
      throw new Error(
        "TextBoxPrimitive es una clase abstracta y no se puede instanciar."
      );
    }
    this.#data = data;
  }

  /**
   * Actualiza el control
   */
  #updateControl() {
    if (this.getLabel() != undefined) {
      $("#" + this.getName() + "Label").text(this.getLabel());
    }

    if (this.#data != undefined) {
      $("#" + this.getName()).val(this.#data);
    } else {
      $("#" + this.getName()).val("");
    }

    if (this.getDescription() != undefined) {
      $("#" + this.getName() + "Help").text(this.getDescription());
    }
  }

  /**
   * Establece el valor del control
   * @param {object} data Valor del control
   */
  setData(data) {
    this.#data = data;
    this.#updateControl();
  }

  /**
   * Retorna el valor del control
   * @returns Valor del control
   */
  getData() {
    return this.#data;
  }
}

/**
 * Clase primitiva que representa una tabla
 * @extends {ControlPrimitive}
 * @abstract
 */
class TablePrimitive extends ControlPrimitive {
  #columnHeaderType;
  #columnHeaders;
  #rowHeaderType;
  #rowHeaders;
  #rowsTitle;

  #data;

  /**
   * Constructor por defecto
   * @param {string} name Nombre del control
   * @param {string} label Etiqueta del control
   * @param {string} description Descripción del control
   * @param {TABLEHEADERTYPE} columnHeaderType Tipo de cabecera de las columnas
   * @param {string[]} columnHeaders Cabeceras personalizadas de las columnas
   * @param {TABLEHEADERTYPE} rowHeaderType Tipo de cabecera de las filas
   * @param {string[]} rowHeaders Cabeceras personalizadas de las filas
   * @param {object[][]} data Datos de la tabla
   */
  constructor(
    name,
    label,
    description,
    columnHeaderType,
    columnHeaders,
    rowHeaderType,
    rowHeaders,
    data
  ) {
    super(name, label, description);
    if (this.constructor == TablePrimitive) {
      throw new Error(
        "TablePrimitive es una clase abstracta y no se puede instanciar."
      );
    }
    this.#columnHeaderType = columnHeaderType;
    this.#columnHeaders = columnHeaders;
    this.#rowHeaderType = rowHeaderType;
    this.#rowHeaders = rowHeaders;
    this.#data = data;
  }

  /**
   * Establece la cabecera de las columnas
   * @param {TABLEHEADERTYPE} type Tipo de cabecera
   */
  setColumnHeaderType(type) {
    this.#columnHeaderType = type;
  }

  /**
   * Obtiene el tipo de cabecera de las columnas
   * @returns El tipo de cabecera
   */
  getColumnHeaderType() {
    return this.#columnHeaderType;
  }

  /**
   * Establece la cabecera de las filas
   * @param {TABLEHEADERTYPE} type Tipo de cabecera
   */
  setRowHeaderType(type) {
    this.#rowHeaderType = type;
  }

  /**
   * Obtiene el tipo de cabecera de las filas
   * @returns El tipo de cabecera
   */
  getRowHeaderType() {
    return this.#rowHeaderType;
  }

  /**
   * Establece las cabeceras personalizadas de las columnas
   * @param {string[]} columnHeaders Cabeceras personalizadas de las columnas
   */
  setCustomColumnHeaders(headers) {
    this.#columnHeaders = headers;
  }

  /**
   * Obtiene las cabeceras personalizadas de las columnas
   * @returns Cabeceras personalizadas de las columnas
   */
  getCustomColumnHeaders() {
    return this.#columnHeaders;
  }

  /**
   * Establece las cabeceras personalizadas de las filas
   * @param {string[]} columnHeaders Cabeceras personalizadas de las filas
   */
  setCustomRowHeaders(headers) {
    this.#rowHeaders = headers;
  }

  /**
   * Obtiene las cabeceras personalizadas de las filas
   * @returns Cabeceras personalizadas de las filas
   */
  getCustomRowHeaders() {
    return this.#rowHeaders;
  }

  /**
   * Establece los datos de la tabla
   * @param {object[][]} data Datos de la tabla
   */
  setData(data) {
    this.#data = data;
    if (data != undefined) {
      OutputData.repaintControl(this);
    }
  }

  /**
   * Obtiene los datos de la tabla
   * @returns Datos de la tabla
   */
  getData() {
    return this.#data;
  }

  /**
   * Establece el nombre de la columna de las filas
   * @param {string} rowsTitle El nombre de la columna
   */
  setRowsTitle(rowsTitle) {
    this.#rowsTitle = rowsTitle;
  }

  /**
   * Obtiene el nombre de la columna de las filas
   * @returns El nombre
   */
  getRowsTitle() {
    return this.#rowsTitle;
  }
}

/**
 * Clase contenedora de los contoles
 * @abstract
 */
class ControlsContainer {
  #controls;

  /**
   * Constructor por defecto
   * @constructor
   */
  constructor() {
    if (this.constructor == ControlsContainer) {
      throw new Error(
        "ControlsContainer es una clase abstracta y no se puede instanciar."
      );
    }
  }

  /**
   * Añade un nuevo control
   * @param {ControlPrimitive} control Control a añadir
   */
  addControl(control) {
    if (this.#controls == undefined) {
      this.#controls = [control];
    } else {
      this.#controls.push(control);
    }
  }

  /**
   * Repinta el control indicado
   * @param {ControlPrimitive} control Control a repintar
   */
  repaintControl(control) {
    $("#" + control.getName() + "Div").attr("id", "toDeleteDiv");
    $("#toDeleteDiv").before(control.getHtmlCode());
    $("#toDeleteDiv").remove();
  }

  /**
   * Obtiene el nombre del control indicado
   * @param {string} name Nombre del control
   * @returns El control con nombre inicado
   */
  get(name) {
    if (this.#controls == undefined) {
      return null;
    }

    for (var i = 0; i < this.#controls.length; i++) {
      if (this.#controls[i].getName() == name) {
        return this.#controls[i];
      }
    }
  }

  /**
   * Obtiene todos los controles
   * @returns Controles existentes
   */
  getControls() {
    return this.#controls;
  }
}