Repository

js/Mobilizing/core/Context.js

import Component from './Component';
import Loader from './util/Loader';
import ComponentProxy from './ComponentProxy';
import EventEmitter from "./util/EventEmitter";
import UserInteractionDone from './util/UserInteractionDone';

export default class Context extends Component {
    /**
    * Mobilizing.js defines a context to enable the use of multiple Mobilizing.js instances in the same webpage.
    */
    constructor() {
        super(...arguments);

        this.components = []; //list of components
        this.loader = new Loader(); //default loader
        //contexts should be able to give their states if needed
        this.events = new EventEmitter({ "scope": this.context });

        this.userInteractionDone = new UserInteractionDone();
    }

    /**
     * Can be used to prepare something (ie : params comming from network server!) after construction but before preLoad
     */
    prepare() {
        this.components.forEach((component) => {
            if (typeof component.prepare === "function") {
                this.chainedCall(component, "prepare");
            }
        });
        this.events.trigger("prepareDone");
    }

    /**
    * preLoad all components
    */
    preLoad() {
        this.components.forEach((component) => {
            component.preLoad(this.loader);
            //this.chainedCall(component, "preLoad", this.loader);
        });
    }

    /**
    * Setup for this Context instance (setup all components that are already instantied)
    */
    setup() {
        this.components.forEach((component) => {
            this.chainedCall(component, "setup");
        });
        super.setup();
    }

    /**
    * Update
    */
    update() {
        //new components pre-update-post
        this.components.forEach((component) => {
            this.chainedCall(component, "preUpdate");
        });

        this.components.forEach((component) => {
            this.chainedCall(component, "update");
        });

        this.components.forEach((component) => {
            this.chainedCall(component, "postUpdate");
        });
    }

    /**
    * @param {Component} component
    * @param {String} method
    * @param {Any} arg
    */
    chainedCall(component, method, arg) {
        component[method](arg); //execute first

        const chained = component.getChainedComponents();

        //recurse then
        if (chained.length > 0) {
            chained.forEach((chainedComponent) => {
                this.chainedCall(chainedComponent, method, arg);
            });
        }
    }

    /**
    * Add a Component to this context
    *
    * @param {Component} component
    * @returns {Component} component
    */
    addComponent(component) {
        //encapsulate class in a component : useful for user script
        if (!(component instanceof Component)) {
            component = new ComponentProxy({
                "targetScript": component,
                "context": this
            });
        }
        this.components.push(component);
        component.context = this;//add the context to the component
        return component;
    }
}