Source: modules/popup.js

/*******************************************************************************
 * Handling of PopUps
 ******************************************************************************/
/* global LoadingView */
/* global getId */

var POPUPS = [];

/**
 * Close all popups that have been opened with the popupHandler
 */
/* jshint -W098 */
var closeAllPopUps = function () {
/* jshint +W098 */
    Object.keys(POPUPS).forEach(function (value, index) {
        POPUPS[value].hide();
    });
};

// should be const with ECMASCRIPT6 
var POPUP_FUNCTION_TYPES = {
    FRAME_CREATED: "FRAME_CREATED",
    FRAME_LOADED: "FRAME_LOADED",
    FINISH_FUNCTION: "FINISH_FUNCTION",
    POPUP_CLOSED: "POPUP_CLOSED"
};

/**
 * Opens a URL in a popup / popover
 * This is inteded for login forms and the prompt dialog.
 * 
 * @param   {string}   popupURL       The URL to open
 * @param   {function} finishFunction Function to execute when page has been opened
 * @param   {string}   popUpId        unique popupID if you know it already
 * @param   {boolean}  singular       if true, same popUpId can be reused, meaning addtional dialogs in same container
 * @returns {object}   The popup
 */
/* jshint -W098 */
var popupHandler = function (popupURL, finishFunction, popUpId, singular) {
/* jshint +W098 */

    if (popUpId && POPUPS[popUpId] != null && !singular) {
        return POPUPS[popUpId];
    }

    this.internalID = '_POPUPS' + Math.floor(Math.random() * 1000);
    this.popUpId = popUpId || this.internalID;
    this.popupURL = popupURL;
    this.finishFunction = finishFunction;
    this.formAction = null;
    this.popupContent = null;
    this.popupClose = null;

    // Singular is just for creating unique array entries
    POPUPS[this.internalID] = this;

    var self = this;

    /**
     * Retrieve the element that will hold the popup div.
     * @returns {element} the element that will hold the popup
     */
    this.documentFrameHolder = function() {
        var node = window.jQuery ? jQuery('div.webguicontainer')[0] : getId('__contentwrapper').parentNode;
        return node;
    };

    /**
     * Execute a function defined in the POPUP_FUNCTION_TYPE enumeration
     * This function takes the first argument as the enumeration entry,
     * the following arguments are send to the function as parameter.
     * 
     * @returns {element} result of the executed function
     */
    var executeFunction = function() {
        var functionType = arguments.length > 0 ? arguments[0] : null;
        var args = [].slice.call(arguments, 1);

        if ( self.finishFunction == null ) {
            return null;
        } else if ( typeof self.finishFunction == 'function' ) {
            if ( functionType == POPUP_FUNCTION_TYPES.FINISH_FUNCTION ) {
                return self.finishFunction( args );
            }
        } else if ( self.finishFunction[functionType] != null && typeof self.finishFunction[functionType] == 'function' ) {
            return self.finishFunction[functionType]( args );
        }

        return null;
    };

    /**
     * Show the popup
     */
    this.show = function () {

        var iframe = getId(this.popUpId);
        var dialog = this.showDialog( iframe );
        if ( dialog !== false ) { return dialog; } // Already existing or a simple dialog

        if (!iframe) {
            iframe = document.createElement("iframe");
            iframe.id = this.popUpId;
            iframe.name = iframe.id;
            iframe.addClassName("popup");

            // Firefox is soooooo blazing fast that the iframe is loaded before the
            // onload function is registered
            this.documentFrameHolder().appendChild(iframe);

            // Execute Handler
            executeFunction( POPUP_FUNCTION_TYPES.FRAME_CREATED, self ); 

            var loadEvent = function () {
                (new LoadingView()).hide();
                executeFunction( POPUP_FUNCTION_TYPES.FRAME_LOADED, self ); 
            };

            iframe.addEvent("load", loadEvent);
        }

        // The cover frame goes over the iframe to make the iframes content in-accessible until it is loaded.
        var coverFrame = document.createElement("div");
        coverFrame.id = self.popUpId + "CoverFrame";
        coverFrame.addClassName("popUpCoverFrame");
        this.documentFrameHolder().appendChild(coverFrame);

        iframe.src = this.popupURL;
        return this;
    };

    this.showDialog = function( contentWrapper ) {

        if ( this.popupURL ) {
            // There is a popup url, return nothing to do here.
            return false;
        }

        if ( !contentWrapper ) {

            contentWrapper = document.createElement('div');
            contentWrapper.addClassName('popupWrapper');
            contentWrapper.id = this.popUpId;
            this.documentFrameHolder().appendChild(contentWrapper);

            var contentWrapperBackground = document.createElement('div');
            contentWrapperBackground.addClassName('popupWrapperBackground');
            contentWrapper.appendChild(contentWrapperBackground);
        }

        // save for external access
        this.popupContent = document.createElement('div');
        this.popupContent.addClassName('popup');
        contentWrapper.appendChild(this.popupContent);

        // Save for external access
        this.popupClose = document.createElement("div");
        this.popupClose.appendChild(document.createTextNode("x"));
        this.popupClose.className = "close";
        this.popupContent.appendChild(this.popupClose);
        this.popupClose.addEvent('click', this.hide);

        window.addEvent('keydown', this.__hideByKey);

        return this;
    };

    /**
     * add a header element to the content panel
     * @param {string} header the header string
     */
    this.addHeader = function( header, level ) {
        var h1 = document.createElement('h' + ( level || '1'));
        h1.appendChild(document.createTextNode( header ));
        this.popupContent.appendChild(h1);
    };

    /**
     * Add a body element to the popup content panel
     * @param {Element} body a body element
     */
    this.addBody = function( body ) {
        this.popupContent.appendChild( body );
    };

    /**
     * Add an entry to the detail section. Will open the section if it does not yet exist.
     * @param {string}  label       the label of the detail entry
     * @param {string}  value       a value that will be printed preformatted
     * @param {boolean} showDefault display this value by default
     */
    this.addDetail = function( label, value, showDefault ) {

        if ( !this.popupDetailSection ) {
            this.popupDetailWrapper = document.createElement("div");
            this.popupDetailWrapper.addClassName('details-wrapper');
            this.popupContent.appendChild( this.popupDetailWrapper );

            this.popupDetailSection = document.createElement("div");
            this.popupDetailSection.addClassName('details');
            this.popupDetailWrapper.appendChild( this.popupDetailSection );

            var expanderButton = document.createElement("div");
            expanderButton.appendChild(document.createTextNode(showDefault?"/\\":"\/"));
            expanderButton.className = "expander";
            this.popupContent.appendChild(expanderButton);

            self.popupContent.addRemoveClass('showDetails', showDefault);
            expanderButton.addEvent('click', function () {
                expanderButton.innerHTML = '';
                if (!self.popupContent.hasClassName('showDetails')) {
                    expanderButton.appendChild(document.createTextNode("/\\"));
                    self.popupContent.addClassName('showDetails');
                } else {
                    expanderButton.appendChild(document.createTextNode("\/"));
                    self.popupContent.removeClassName('showDetails');
                }
            });
        }

        var labelElement = document.createElement("label");

        var spanElement = document.createElement("span");
        spanElement.appendChild(document.createTextNode(label + ':'));
        labelElement.appendChild(spanElement);

        var labelDetails = document.createElement("pre");
        labelDetails.appendChild(document.createTextNode(value));
        labelElement.appendChild(labelDetails);

        this.popupDetailSection.appendChild(labelElement);
    };

    this.windowDocument = function() {
        var windowParent = this[self.popUpId] || window.top[self.popUpId] || {};
        return windowParent.document || windowParent.contentDocument || document;
    };

    /**
     * Hide the popup after an amount of time
     * @param {number} timed timout to close the popup
     */
    this.hide = function (timed) {

        var popup = getId(self.popUpId);
        var returnVar = executeFunction( POPUP_FUNCTION_TYPES.FINISH_FUNCTION, popup );

        if ( popup ) {

            // If there are no more errors, remove the error view entirely
            if (popup.childNodes.length > 2) {
                self.popupContent.parentNode.removeChild(self.popupContent);
            } else {

                // Anzeige der Seite, nachdem der Fehler weg ist
                // getId('__contentwrapper').className = '';
                popup.style.display = 'none';
                window.setTimeout(function () {
                    window.setTimeout(function () {
                        if (popup.parentNode) {
                            popup.parentNode.removeChild(popup);
                        }
                    }, 1000);
                    popup.id += '_expose';
                }, timed || 0);
            }

            // Popup has been removed
            executeFunction( POPUP_FUNCTION_TYPES.POPUP_CLOSED, popup);

            window.removeEvent('keydown', self.hide);
            delete POPUPS[self.internalID];
        }

        return returnVar;
    };

    /**
     * Hide the popup by pressing the excape key
     */
    this.__hideByKey = function( event )  {
        let keycode;
        if (event.which) {
            keycode = event.which;
        } else {
            keycode = event.keyCode;
        }

        if ( keycode == 27 ) {
            self.hide();
        }
    };
};