presentation-components
Version:
The Augmented.js Next - Presentation Components Module.
629 lines (511 loc) • 12 kB
JavaScript
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 };