import Component from './Component';
import language from '../Helpers/Language';
import validate from '../Helpers/Validate';
import translate from '../Helpers/Translate';
import { isString } from '../Helpers/Functions';
import ConsoleMessages from '../Config/ConsoleMessages';
import { error, kebabCase } from '../Helpers/Functions';
import { swap, createElement } from '../Helpers/Template';
export default class DomComponent extends Component {
/**
* An abstract class that all other DOM components can extend.
*
* @class DomComponent
* @extends Component
* @param {(object|undefined)} [attributes] - The instance attributes.
*/
constructor(attributes) {
super(Object.assign({
parent: null
}, attributes));
if(!this.theme) {
error(`${this.name} does not have a theme defined.`);
}
if(!this.language) {
error(`${this.name} does not have a language defined.`);
}
if(!this.theme[this.name]) {
throw new Error(
`${this.name} cannot be rendered because it has no template.`
);
}
}
/**
* The `className` attribute. Used for CSS.
*
* @type {string}
*/
get className() {
return kebabCase(this.constructor.defineName());
}
/**
* The `el` attribute.
*
* @type {HTMLElement}
*/
get el() {
return this.$el;
}
set el(value) {
if(!validate(value, null, HTMLElement)) {
error(ConsoleMessages.element);
}
this.$el = value;
}
/**
* The `parent` attribute. Parent is set when `DomComponent` instances are
* mounted.
*
* @type {DomComponent}
*/
get parent() {
return this.$parent;
}
set parent(parent) {
this.$parent = parent;
}
/**
* The `theme` attribute.
*
* @type {object}
*/
get theme() {
return this.$theme;
}
set theme(value) {
if(!validate(value, 'object')) {
error(ConsoleMessages.value);
}
this.$theme = value;
}
/**
* Get the language attribute.
*
* @type {object}
*/
get language() {
return this.$language;
}
set language(value) {
if(isString(value)) {
value = language(value);
}
if(!validate(value, 'object')) {
error(ConsoleMessages.language);
}
this.$language = value;
}
/**
* Translate a string.
*
* @param {string} string - The string to translate.
* @return {string} - The translated string. If no tranlation found, the
* untranslated string is returned.
*/
translate(string) {
return translate(string, this.language);
}
/**
* Alias to translate(string);
*
* @alias DomComponent.translate
*/
t(string) {
return this.translate(string);
}
/**
* Render the DOM component.
*
* @return {HTMLElement} - The `el` attribute.
*/
render() {
const el = createElement('div', {
class: this.className === 'flip-clock' ? this.className : 'flip-clock-' + this.className
});
this.theme[this.name](el, this);
if(!this.el) {
this.el = el;
}
else if(this.el.innerHTML !== el.innerHTML) {
this.el = swap(el, this.el);
}
return this.el;
}
/**
* Mount a DOM component to a parent node.
*
* @param {HTMLElement} parent - The parent DOM node.
* @param {(false|HTMLElement)} [before=false] - If `false`, element is
* appended to the parent node. If an instance of an `HTMLElement`,
* the component will be inserted before the specified element.
* @return {HTMLElement} - The `el` attribute.
*/
mount(parent, before = false) {
this.render();
this.parent = parent;
if(!before) {
this.parent.appendChild(this.el);
}
else {
this.parent.insertBefore(this.el, before);
}
return this.el;
}
}