UNPKG

presentation-components

Version:

The Augmented.js Next - Presentation Components Module.

629 lines (511 loc) 12 kB
import { DecoratorView } from 'presentation-decorator'; import { Mediator } from 'presentation-mediator'; const DEFAULT_TAG = "article"; /** * An article class for setting up a 'page'<br/> * Supported options are:<br/> * <ul> * <li>name - The name of the article view</li> * <li>el - The mount point</li> * <li>style - The style class</li> * <li>header - The header markup</li> * <li>headerEl - The header mount point</li> * <li>footer - The footer markup</li> * <li>footerEl - The footer mount point</li> * <li>body - The body markup</li> * <li>bodyEl - The body mount point (will generate a div)</li> * <li>sections - array of sections to prefill (see addSection API for format)</li> * </ul> * @extends DecoratorView * @param {object} options Options to pass to the constructor * @example * const article = new Presentation.Component.Article( * { "el": "#mount", "header": "html", "footerEl": "#foot" }); */ class Article extends DecoratorView { constructor(options) { if (!options) { options = {}; } if (!options.name) { options.name = DEFAULT_TAG; } // tag should be article options.tagName = DEFAULT_TAG; super(options); if (options && options.header) { this._header = options.header; } else { this._header = ""; } if (options && options.headerEl) { this._headerEl = options.headerEl; } else { this._headerEl = ""; } if (options && options.headerStyle) { this._headerStyle = options.headerStyle; } else { this._headerStyle = ""; } if (options && options.body) { this._body = options.body; } else { this._body = ""; } if (options && options.footer) { this._footer = options.footer; } else { this._footer = ""; } if (options && options.footerEl) { this._footerEl = options.footerEl; } else { this._footerEl = ""; } if (options && options.footerStyle) { this._footerStyle = options.footerStyle; } else { this._footerStyle = ""; } if (options && options.sections) { this._sections = options.sections; } else { this._sections = []; } } /** * Header property * @property {string} header */ set header(header) { this._header = header; } get header() { return this._header; } /** * Footer for the article * @property {string} footer */ set footer(footer) { this._footer = footer; } get footer() { return this._footer; } /** * The body content of the card (supports HTML) * @property {string} body */ set body(body) { this._body = body; } get body() { return this._body; } /** * The section array * @property {array} sections */ set sections(sections) { if (sections && Array.isArray(sections)) { this._sections = sections; } } get sections() { return this._sections; } /** * @private */ _formatSections() { const l = this._sections.length; let sections = "", i = 0; for (i = 0; i < l; i++) { sections += this._formatSection(this._sections[i]); } return sections; } /** * @private */ _formatSection(section) { let sect = ""; if (section && (section.body || section.id || section.class)) { const cls = section.class ? ` class="${section.class}"` : ""; const id = section.id ? ` id="${section.id}"` : ""; const body = section.body ? section.body : ""; sect = `<section${id}${cls}>${body}</section>`; } return sect; } /** * Add a section object to the article * @param {object} section a section object * @example Section Object format: * { * "id" "something", * "body" "html", * "class" "something" * } */ addSection(section) { this._sections.push(section); } /** * Clear the sections */ clearSections() { this._sections.splice(0, this._sections.length); } /** * render - render the article */ render() { if (this.el) { const el = document.querySelector(this.el); if (el) { el.innerHTML = this._template(); } this.delegateEvents(); } return this; } /** * template - sets content of the dialog, handled internally * @private */ _template() { let header = ""; if (this._header) { let hid = "", style = ""; if (this._headerEl) { hid = ` id="${this._headerEl}"`; } if (this._headerStyle) { style = ` class="${this._headerStyle}"`; } header = `<header${hid}${style}>${this._header}</header>`; } let footer = ""; if (this._footer) { let fid = "", style = ""; if (this._footerEl) { fid = ` id="${this._footerEl}"`; } if (this._footerStyle) { style = ` class="${this._footerStyle}"`; } footer = `<footer${fid}${style}>${this._footer}</footer>`; } let body = ""; if (this._body) { if (this._bodyEl) { body = `<div id="${this._bodyEl}">${this._body}</div>`; } else { body = `${this._body}`; } } return `${header}${body}${this._formatSections()}${footer}`; } } /** * A card view - simple panel/dialog-like panel * @extends DecoratorView */ class Card extends DecoratorView { constructor(options) { if (!options) { options = {}; } if (!options.name) { options.name = "card"; } if (!options.style) { options.style = "card"; } else { options.style = `card ${options.style}`; } super(options); if (options && options.body) { this._body = options.body; } else { this._body = ""; } } /** * body property - the body of the card * @property body */ /** * style property - the style * @property style */ set style(style) { this._style = style; } get style() { return this._style; } /** * template - sets content of the dialog, handled internally * @private */ _template() { return this._body; } /** * The body content of the card (supports HTML) * @property body */ set body(body) { this._body = body; } get body() { return this._body; } /** * render - render the card */ render() { if (this.el) { const el = document.querySelector(this.el); if (el) { el.innerHTML = this._template(); } this.delegateEvents(); } return this; } /** * remove */ remove() { this.removeTemplate(this.el, true); return super.remove(); } } /** * A Footer Component * @extends DecoratorView */ class Footer extends DecoratorView { constructor(options) { super(options); if (options && options.body) { this._body = options.body; } else { this._body = ""; } } /** * The body content of the card (supports HTML) * @property body */ set body(body) { this._body = body; } get body() { return this._body; } /** * template - sets content of the footer, handled internally * @private */ _template() { return this._body; } /** * render - render the footer */ render() { if (this.el) { const el = document.querySelector(this.el); if (el) { el.innerHTML = this._template(); } this.delegateEvents(); this.syncAllBoundElements(); } return this; } remove() { this.removeTemplate(this.el, true); return super.remove(); } } /** * A Header Component * @extends DecoratorView */ class Header extends DecoratorView { constructor(options) { super(options); if (options && options.title) { this._title = options.title; } else { this._title = ""; } if (options && options.subTitle) { this._subTitle = options.subTitle; } else { this._subTitle = ""; } } /** * @property {string} title A title property */ set title(title) { this._title = title; } get title() { return this._title; } /** * @property {string} subTitle A subTitle property */ set subTitle(subTitle) { this._subTitle = subTitle; } get subTitle() { return this._subTitle; } /** * render - render the header */ render() { if (this.el) { const el = document.querySelector(this.el); if (el) { el.innerHTML = `${this.template}${this.title ? "<h1>" + this.title + "</h1>" : ""}${this.subTitle ? "<h2>" + this.subTitle + "</h2>" : ""}`; } this.delegateEvents(); this.syncAllBoundElements(); } return this; } /** * Remove the Header * @returns {object} Returns the view context ('this') */ remove() { this.removeTemplate(this.el, true); return super.remove(); } } /** * A Component Manager or Mediator * @extends Mediator * @deprecated Use Mediator */ class Manager extends Mediator { constructor(options) { super(options); } /** * Manages a component (colleague) * @param {View} component A component or view to manage */ manageComponent(component) { return this.observeColleagueAndTrigger(component, component.name, component.name); } /** * Unmanages a component (colleague) * @param {View} component A component or view to manage */ unmanageComponent(component) { return this.dismissColleagueTrigger(component, component.name, component.name); } } /** * A SelectBox * @extends DecoratorView */ class SelectBox extends DecoratorView { constructor(options = {}) { super(options); if (options.options && Array.isArray(options.options)) { this._options = options.options; } else { this._options = []; } if (options.large) { this._large = true; } else { this._large = false; } if (options.label) { this.label = options.label; } } set large(large) { this._large = large; } get large() { return this._large; } /** * Render the SelectBox * @returns {object} Returns the view context ('this') */ async render() { await super.render(); if (this.el) { const el = document.querySelector(this.el); if (el) { el.classList.add("select"); if (this._large) { el.classList.add("large"); } const select = document.createElement("select"); select.dataset[this.name] = `select`; select.name = this.name; select.id = `select_${this.name}_${el.id}`; let i = 0; const l = this._options.length; for (i; i < l; i++) { const option = document.createElement("option"); option.value = this._options[i].value; if (this._options[i].selected) { option.selected = true; } const text = document.createTextNode(this._options[i].label); option.appendChild(text); select.appendChild(option); } el.appendChild(select); const label = document.createElement("label"); const text = document.createTextNode(this.label); label.appendChild(text); label.htmlFor = `select_${this.name}_${el.id}`; el.appendChild(label); } } return this; } /** * remove */ async remove() { await this.removeTemplate(this.el, true); return super.remove(); } /** * Adds an option to the select * @param {string} label label of the option * @param {string} value value of the option * @param {boolean} selected selected or not * @example addOption({"dog", 0, true}); */ addOption(label, value, selected) { this._options.push({ "label": label, "value": value, "selected": selected ? selected : false }); } } export { Article, Card, Footer, Header, Manager, SelectBox };