Source: ui/modal-overlay.reel/modal-overlay.js

/*global require, exports, console, MontageElement */

/**
 * @module "ui/modal-overlay.reel"
 */
var Overlay = require("../overlay.reel").Overlay,
    Promise = require("../../core/promise").Promise;

var CLASS_PREFIX = "montage-ModalOverlay";

/**
 * @class ModalOverlay
 * @extends Overlay
 */
var ModalOverlay = exports.ModalOverlay = Overlay.specialize(/** @lends ModalOverlay.prototype # */ {

    enterDocument: {
        value: function (firstTime) {
            var body;

            this.super(firstTime);

            if (firstTime) {
                body = this.element.ownerDocument.body;
                body.appendChild(this.modalMaskElement);
            }
        }
    },

    _queue: {
        value: []
    },

    _showPromise: {
        value: null
    },

    _dismissOnExternalInteraction: {
        value: false
    },

    hasModalMask: {
        value: true
    },

    _slotComponent: {
        value: null
    },

    /**
     * Returns a promise for the show of the overlay. A modal overlay might not
     * be immediately shown if another modal overlay is being shown. When this
     * is the case then only after the previous overlay is hidden will the
     * overlay be shown.
     */
    show: {
        value: function (component) {
            var queue = this._queue,
                ix = queue.indexOf(this),
                promise;

            // The overlay is not scheduled to draw so we add it to the queue
            // and return a promise that will be solved when shown.
            // If no overlay is being shown (empty queue) then we show it
            // immediately and return a solved promise.
            if (ix === -1) {
                if (queue.length === 0) {
                    this.super();
                    promise = Promise.resolve();
                } else {
                    promise = this._showPromise = {};
                     this._showPromise.promise = new Promise(function(resolve, reject) {
                         promise.resolve = resolve;
                         promise.reject = reject;
                     });
                    promise = this._showPromise.promise;
                }

                if (component) {
                    this._slotComponent.content = component;
                }

                queue.push(this);

                // The overlay is scheduled to draw so we just return the
                // previously created promise. If the overlay is currently
                // being shown (head of the queue) then we add it again to the
                // queue.
            } else {
                if (ix === 0) {
                    promise = this._showPromise = {};
                     this._showPromise.promise = new Promise(function(resolve, reject) {
                         promise.resolve = resolve;
                         promise.reject = reject;
                     });
                    queue.push(this);
                }
                promise = this._showPromise.promise;
            }

            return promise;
        }
    },

    hide: {
        value: function () {
            var queue = this._queue,
                ix = queue.indexOf(this),
                nextOverlay;

            if (ix === 0) {
                queue.shift();
                this.super();
                if (queue.length > 0) {
                    nextOverlay = queue[0];
                    nextOverlay._showPromise.resolve();
                    Overlay.prototype.show.call(nextOverlay);
                }
            } else if (ix > 0) {
                queue.splice(ix, 1);
                this._showPromise.reject(new Error("Modal Overlay position in the queue is not 0"));
            }
        }
    },

    draw: {
        value: function () {
            this.super();

            if (this._isShown && this.hasModalMask) {
                this.modalMaskElement.classList.add(CLASS_PREFIX + "-modalMask--visible");
            } else {
                this.modalMaskElement.classList.remove(CLASS_PREFIX + "-modalMask--visible");
            }
        }
    }

});

if (window.MontageElement) {
    MontageElement.define("montage-modal-overlay", ModalOverlay);
}