JSDoc: Source: popup.js

# Source: popup.js

    /*************************************************************
     *
     *  Copyright (c) 2015-2016 The MathJax Consortium
     *
     *  Licensed under the Apache License, Version 2.0 (the "License");
     *  you may not use this file except in compliance with the License.
     *  You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     *  Unless required by applicable law or agreed to in writing, software
     *  distributed under the License is distributed on an "AS IS" BASIS,
     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     *  See the License for the specific language governing permissions and
     *  limitations under the License.
     */
    /**
     * @fileoverview Class of popup windows. Each object can actually spawn multiple
     *      windows.
     *
     * @author v.sorge@mathjax.org (Volker Sorge)
     */
    /// <reference path="context_menu.ts" />
    /// <reference path="menu_util.ts" />
    var ContextMenu;
    (function (ContextMenu) {
        class Popup extends ContextMenu.AbstractPostable {
            /**
             * @constructor
             * @extends {AbstractPostable}
             * @param {string} title The title of the popup window.
             * @param {Function} content Function generating the content.
             */
            constructor(title, content) {
                super();
                this.title = '';
                /**
                 * The last opened window.
                 * @type {Window}
                 */
                this.window = null;
                /**
                 * The list of all windows opened by this object.
                 * @type {Array.<Window>}
                 */
                this.windowList = [];
                this.mobileFlag = false;
                this.active = null;
                this.title = title;
                this.content = content || function () { return ''; };
            }
            /**
             * Attaches the widget to a context menu.
             * @param {ContextMenu} menu The parent menu.
             */
            attachMenu(menu) {
                this.menu = menu;
            }
            /**
             * @override
             */
            post() {
                this.display();
            }
            /**
             * @override
             */
            display() {
                this.active = this.menu.getStore().getActive();
                let settings = [];
                for (let setting in Popup.popupSettings) {
                    settings.push(setting + '=' + Popup.popupSettings[setting]);
                }
                this.window = window.open('', '_blank', settings.join(','));
                this.windowList.push(this.window);
                let doc = this.window.document;
                if (this.mobileFlag) {
                    doc.open();
                    doc.write('<html><head><meta name="viewport" ' +
                        'content="width=device-width, initial-scale=1.0" /><title>' +
                        this.title +
                        '</title></head><body style="font-size:85%">');
                    doc.write('<pre>' + this.generateContent() + '</pre>');
                    doc.write('<hr><input type="button" value="' +
                        //// TODO: Localise
                        'Close' + '" onclick="window.close()" />');
                    doc.write('</body></html>');
                    doc.close();
                }
                else {
                    doc.open();
                    doc.write('<html><head><title>' + this.title +
                        '</title></head><body style="font-size:85%">');
                    doc.write('<table><tr><td><pre>' + this.generateContent() +
                        '</pre></td></tr></table>');
                    doc.write('</body></html>');
                    doc.close();
                    setTimeout(this.resize.bind(this), 50);
                }
            }
            /**
             * @override
             */
            unpost() {
                this.windowList.forEach(x => x.close());
                this.window = null;
            }
            /**
             * Generates the content of the window.
             * @return {string} The generated content.
             */
            generateContent() {
                return this.content(this.active);
            }
            /**
             * Resizes the window so it fits snuggly around the content.
             * @private
             */
            resize() {
                let table = this.window.document.body.firstChild;
                let H = (this.window.outerHeight - this.window.innerHeight) || 30;
                let W = (this.window.outerWidth - this.window.innerWidth) || 30;
                W = Math.max(140, Math.min(Math.floor(.5 * screen.width), table.offsetWidth + W + 25));
                H = Math.max(40, Math.min(Math.floor(.5 * screen.height), table.offsetHeight + H + 25));
                this.window.resizeTo(W, H);
                let bb = this.active.getBoundingClientRect();
                if (bb) {
                    let x = Math.max(0, Math.min(bb.right - Math.floor(W / 2), screen.width - W - 20));
                    let y = Math.max(0, Math.min(bb.bottom - Math.floor(H / 2), screen.height - H - 20));
                    this.window.moveTo(x, y);
                }
                this.active = null;
            }
        }
        Popup.popupSettings = {
            status: 'no',
            toolbar: 'no',
            locationbar: 'no',
            menubar: 'no',
            directories: 'no',
            personalbar: 'no',
            resizable: 'yes',
            scrollbars: 'yes',
            width: 400,
            height: 300,
            left: Math.round((screen.width - 400) / 2),
            top: Math.round((screen.height - 300) / 3)
        };
        ContextMenu.Popup = Popup;
    })(ContextMenu || (ContextMenu = {}));