Source: components/base-component.js

/**
 * This is the base component
 */
class BaseComponent {
	/**
	 * @constructs
	 */
	constructor() {
		this.isInit = false;
		this.isRendered = false;
		this.isBoundEvent = false;
		/**
		 * Array of child components
		 * @type {Array}
		 * @default []
		 */
		this.children = [];
		/**
		 * The parent component
		 * @type {Component}
		 * @default null
		 */
		this.parent = null;
	};
	/**
	 * Refresh component
	 */
	refresh() {
		this._callAllInit();
		this._callAllRender();
		this._callAllBindEvents();
	};

	/**
	 * Before initialize callback
	 */
	beforeInit() {};

	/**
	 * Initialize component
	 */
	init() {};

	/**
	 * After initialize callback
	 */
	afterInit() {};

	/**
	 * Returns whether or not the childs of a component is refresh
	 */
	isLoopThroughChild() { return true; }

	/**
	 * Returns whether or not the component is rendered
	 */
	isRender() { return true; };

	/**
	 * Before reder component callback
	 */
	beforeRender() {};

	/**
	 * Render compoment
	 */
	render() {};

	/**
	 * After reder component callback
	 */
	afterRender() {};

	/**
	 * Returns whether or not binding the events on a component
	 */
	isBindEvents() { return true; };

	/**
	 * Before bind events on component callback
	 */
	beforeBindEvents() {};
	
	/**
	 * Bind events on the component
	 */
	bindEvents() {};

	/**
	 * After bind evnets on the component
	 */
	afterBindEvents() {};

	/**
	 * Add the child component into a component
	 * @param {Object} childComponent The child component
	 */
	addComponent(childComponent) {
		childComponent.parent = this;
		this.children.push(childComponent);
	};

	/**
	 * Remove a child component of a component
	 * @param {Object} childComponent The child component
	 */
	removeComponent(childComponent) {
		if (this.children && this.children.length > 0){
			var index = this.children.indexOf(childComponent);
			if (index !== -1) {
				this.children.splice(index, 1);
			}
		}
	};

	/**
	 * Initialize the component (include all child-components)
	 */
	_callAllInit() {
		if (!this.isInit) {
			this.beforeInit();
			this.init();
		}
		if (this.children && this.children.length > 0 && this.isLoopThroughChild()) {
			this.children.forEach((child) => {
				child._callAllInit();
			});
		}
		if (!this.isInit) {
			this.afterInit();
			this.isInit = true;
		}
	}

	/**
	 * Render the component (include all child-components)
	 */
	_callAllRender() {
		if (this.isRender()) {
			this.beforeRender();
		}
		if (this.children && this.children.length > 0 && this.isLoopThroughChild()) {
			this.children.forEach((child) => {
				child._callAllRender();
			});
		}
		if (this.isRender()) {
			this.render();
			this.afterRender();
			this.isRendered = true;
		}
	}

	/**
	 * Bind events on the component (include all child-components)
	 */
	_callAllBindEvents() {
		if (this.isBindEvents()) {
			this.beforeBindEvents();
		}
		if (this.children && this.children.length > 0 && this.isLoopThroughChild()) {
			this.children.forEach((child) => {
				child._callAllBindEvents();
			});
		}
		if (this.isBindEvents()) {
			this.bindEvents();
			this.afterBindEvents();
			this.isBoundEvent = true;
		}
	}
};

export default BaseComponent;