Repository

js/Mobilizing/core/Component.js

import EventEmitter from './util/EventEmitter';
import { uuid } from './util/Misc';

/**
* The generic componment class.
* Used for all Mobilizing components such as input helpers, renderers, etc.
*/
export default class Component {
    /**
    * @param {Object} params Parameters object, given by the constructor.
    * @param {Context} params.context The Mobilizing Context
    * @param {String} params.name The component's name
    * @param {String} [params.id=uuid()] The component's ID
    */
    constructor({
        context,
        name,
        id = uuid(),
    } = {}) {

        this.context = context;
        this.name = (name !== undefined ? name : this.constructor.name);
        this.id = id;

        this.active = false;
        this.events = new EventEmitter({ "scope": this });

        this._setupDone = false;

        /*
        * Array of all the children component attached to this component.
        * Used to conceive component chains for easy management
        */
        this._nexts = [];
    }

    /**
    * prepare the component
    * This empty method is usually overriden to perform preparation actions for the component, from external process as a server.
    * The prepare function is designed to be called before any other method, even preLoad.
    * It is called automatically by an internal Mobilizing mechanism and should thus not be called directly
    */
    prepare() {
    }

    /**
    * preLoad the component
    * This empty method is usually overriden to perform preLoad actions for the component.
    * The preLoad is designed to be called before any other method, even setup, except prepare.
    * In the case of user scripts, it is used to preload all needed datas before the setup (pictures, font, etc.)
    * It is called automatically by an internal Mobilizing mechanism and should thus not be called directly
    */
    preLoad() {
    }

    /**
    * Set's up the component
    * This empty method is usually overriden to perform setup actions for the component
    * This is where all the initialization (such as adding event listeners)should be done
    * It is called automatically by an internal Mobilizing mechanism and should thus not be called directly
    */
    setup() {
        if (!this._setupDone) {
            //chainning process for setup when Context can't do it for code execution order reasons (use super.setup() in the class extending Component)

            const chainedComponents = this.getChainedComponents();

            chainedComponents.forEach((component) => {
                component.setup();
            });

            this._setupDone = true;
        }
    }

    /**
    * Activate the component
    * A call to this method calls the setup method if it has not been run yet
    */
    on() {
        this.active = true;
    }

    /**
    * Deactivate the component
    */
    off() {
        this.active = false;
    }

    /**
    * @TODO
    */
    byPass() {
        //how to bypass ?
    }

    /**
    * Run code before the update of all components is run
    * This empty method is usually overriden to perform pre-update actions for the component
    * It is called once per component by an internal Mobilizing mechanism
    */
    preUpdate() {
    }

    /**
    * Update the component
    * This empty method is usually overriden to perform update actions for the component
    * It is called periodically by an internal Mobilizing mechanism
    */
    update() {
    }

    /**
    * Run code after the update of all components is run
    * This empty method is usually overriden to perform post-update actions for the component
    * It is called periodically by an internal Mobilizing mechanism
    */
    postUpdate() {
    }

    /**
    * Adds a component to this chained component array
    * @param {Component} component the component to chain
    */
    chain(component) {
        this._nexts.push(component);
    }

    /**
    * Returns the array of attached children components
    * @return {Array} children arrays
    */
    getChainedComponents() {
        return this._nexts;
    }
}