Home Reference Source

js/controllers/FullScreenModalController.js

import ViewController from '~/controllers/ViewController';

/**
 * Controls a 'FullScreenModalTemplate' which is used for things like answer UI.
 */
export default class FullScreenModalTemplate extends ViewController {

    static shared = new FullScreenModalTemplate(document.body);

    /**
     * Creates empty instance
     * @param {Element} parent
     */
    constructor(parent) {
        super();

        /**
         * Parent node
         * @type {Element}
         */
        this.parent = parent;

        /**
         * The Active template
         * @type {FullScreenModalTemplate}
         */
        this.activeTemplate = null;

        /**
         * The node of the template
         * @type {Node}
         */
        this.activeNode = null;
    }

    /**
     * Presents
     * @param {FullScreenModalTemplate} template
     * @param {Object} [opts={}]
     * @param {boolean} [opts.animated=true] - If to animate transition
     */
    async present(template, { animated = true } = {}) {
        if (this.activeTemplate) {
            await this.dismiss({ animated: animated });
        }

        const node = template.loadInContext(this.parent);

        if (animated) {
            const { default: anime } = await import('animejs');
            await anime({
                targets: node,
                opacity: [0, 1],
                elasticity: 0,
                easing: 'easeOutQuart',
                marginTop: ['5%', '0%'],
                duration: 200
            }).finished;
        } else {
            node.opacity = 1;
        }

        this.activeTemplate = template;
        this.activeTemplate.controller = this;
        this.activeNode = node;
    }

    /**
     * Hides
     * @param {Object} [opts={}]
     * @param {boolean} [opts.animated=true] - If to animate transition
     */
    async dismiss({ animated = true } = {}) {
        if (!this.activeTemplate) return;

        if (animated) {
            const { default: anime } = await import('animejs');
            await anime({
                targets: this.activeNode,
                opacity: [1, 0],
                elasticity: 0,
                easing: 'easeOutQuart',
                marginTop: ['0%', '5%'],
                duration: 200
            }).finished;
        } else {
            node.opacity = 0;
        }

        this.activeTemplate.removeFromContext();
        this.activeTemplate.controller = null;
        this.activeTemplate = null;
        this.activeNode = null;

    }
}