Source: modules/tabbar.js

/*******************************************************************************
 * Tab Management
 ******************************************************************************/

/**
 * @class
 */
/* global DEFAULTZOOM */
/* global DRILLDOWNANDSUBREPORTSDISABLED */
/* global KEYBOARD_LISTENER */
/* global MenubarActions */
/* global VARIABLES */
/* global amIOnline */
/* global documentSearch */
/* global errorPacketHandler */
/* global getId */
/* global getPageCount */
/* global getTranslation */
/* global grouptree */
/* global prepareAddParameterToArray */
/* global prepareRemoveParameterFromArray */
/* global setInnerText */

var tabElement = function () {
    this.name = null;
    this.link = null;
    this.id = null;
    this.object = null;
};

var _tabbedPanel = null;

/**
 * The tab bar management
 * Will return a sigleton of the tabbar
 * 
 * @class
 * @returns {object} The tabbar
 */
/* jshint -W098 */
var tabbedPanel = function () {
/* jshint +W098 */
    if (_tabbedPanel != null) {
        return _tabbedPanel;
    }

    _tabbedPanel = this;
    var self = this;

    this.currentlyActiveTab = null;
    this.managedElements = [];
    this.currentTabNumber = 0;

    /**
     * Returns the number of the currently active tab
     * @returns {number} currently active tab
     */
    this.frontMostTab = function () {
        return this.managedElements.indexOf(this.currentlyActiveTab);
    };

    /**
     * Sets the title of the currently front-most tab
     * @param {string} title Title of the tab
     */
    this.setCurrentTitle = function (title) {
        var tab = this.managedElements[this.frontMostTab()]; // -1 for array
        // sanity
        if (tab.subReportData) {
            title = tab.subReportData.name || title;
        }

        if (title) {
            setInnerText(tab.firstChild, title);
            document.title = title;
        }
    };

    /**
     * Create a Tab
     * @param {object}   subreportData  the data of the sub report
     * @param {boolean}  isMainTab      if this is the first tab
     * @param {boolean}  isOnline       if this tab is online activated
     * @param {function} finishFunction what to do when the tab has been created
     */
    this.createTab = function (subreportData, isMainTab, isOnline,
        finishFunction) {

        if (isOnline == null) {
            isOnline = true;
        } else if (DRILLDOWNANDSUBREPORTSDISABLED) {
            isOnline = false; // Deactivate if set - means we're opening the second tab which should be prohibited.
        }

        if (!isOnline) {
            new errorPacketHandler({
                errorHeader: getTranslation("tapBar.subreports.title"),
                errorMessage: DRILLDOWNANDSUBREPORTSDISABLED ? getTranslation("tapBar.subreports.reports") : getTranslation("tapBar.subreports.offline")
            });
            return;
        }

        if (isMainTab == null) {
            isMainTab = false;
        }

        // Check if the tab exists already.
        for (var i = 0; i < self.managedElements.length; i++) {
            if (self.managedElements[i].subReportData.subreport_ondemand == subreportData.subreport_ondemand && self.managedElements[i].subReportData.subreport == subreportData.subreport) {
                // Just activate that tab if it exists.
                this.activateTab(self.managedElements[i], true);
                return;
            }
        }

        var tab = document.createElement('div');
        tab.addClassName('tab');
        tab.addClassName('entering');

        var tabName = document.createElement('span');
        tabName.appendChild(document.createTextNode(subreportData.name != null ? subreportData.name : getTranslation("loadingView.loading")));
        tab.appendChild(tabName);

        if (!isMainTab) {
            var close = document.createElement('a');
            close.addClassName('close');
            close.appendChild(document.createTextNode('X'));
            tab.appendChild(close);

            close.addEvent('click', function (event) {
                KEYBOARD_LISTENER.stopEvent(event);
                self.closeTab(tab);
            });
        } else {
            tab.addClassName('mainTab');
        }

        window.setTimeout(function () {
            tab.removeClassName('entering');
        }, 100);

        tab.addEvent('click', function (event) {
            var source = event.source || event.srcElement || event.originalTarget;
            if (source.tagName.toLowerCase() == 'span') {
                source = source.parentNode;
            }

            switch (event.button) {
            case 0:
                self.activateTab(source, true); // Always activate - never
                // deactive
                break;
            case 1:
                self.closeTab(tab);
                break;
            }
        });

        // Add the tab ...
        self.managedElements.push(tab);

        // Everything is set up, now lets create the content elements
        tab.loaded = false;
        tab.mainTab = isMainTab;
        tab.subReportData = subreportData;
        tab.finishFunction = finishFunction;
        tab.tabNumber = ++this.currentTabNumber;
        tab.style.zIndex = 10000 - tab.tabNumber;

        var tabWrapper = document.createElement('div');
        tabWrapper.addClassName('__tabWrapper');
        tabWrapper.id = '__tabWrapper-' + (Math.max(tab.tabNumber, 1));
        getId('__contentwrapper').appendChild(tabWrapper);
        tab.tabWrapper = tabWrapper;

        // Activate the main tab
        // var oldActiveTab = this.currentlyActiveTab;
        this.activateTab(tab, true);
        tabWrapper.appendChild((new MenubarActions())
            .createInnerContentWrapper());

        // append to TabBar
        getId('__tabBar').appendChild(tab);
    };

    /**
     * Close some Tab by its document element
     * @param {object} tabElement the tab element to close this tab
     */
    this.closeTab = function (tabElement) {
        var index = self.managedElements.indexOf(tabElement);
        if (index <= 0) {
            // That is not a TAB. Or It is the Main Tab
            return;
        }

        tabElement.addClassName('entering');

        // Tab was active?
        if (tabElement.isCurrent()) {
            self.activateTab(self.managedElements[index - 1], true);
        }

        var contentNode = tabElement.tabWrapper;

        if ( documentSearch && documentSearch.clearSearch ) {
            documentSearch.clearSearch();
        }

        // Remove after timeout
        window.setTimeout(function () {
            // Check if this Tab is in the submenu
            self.managedElements.splice(self.managedElements
                .indexOf(tabElement), 1);

            // styles will be removed when a new version is being set in setPageContent in script.js.
            tabElement.parentNode.removeChild(tabElement);
            contentNode.parentNode.removeChild(contentNode);
        }, 100);
    };

    /**
     * activate a tab
     * @param {object}  source the tab to activate or deactivate
     * @param {boolean} active true: active
     */
    this.activateTab = function (source, active) {
        // Nothing to do?
        if (source == null) {
            return;
        }

        // Check if activation or deactivation needed
        if (!active) {

            if (this.currentlyActiveTab == source) {

                let menu = new MenubarActions();
                menu.resetReportPages();
                
                this.currentlyActiveTab = null;

                window.VARIABLES = prepareRemoveParameterFromArray(VARIABLES, source.subReportData);
                source.pageData = getPageCount.DATA;

                if (!source.pageData) {
                    source.pageData = {};
                }

                source.pageData.groupTreeOpenStructure = (new grouptree()).getCurrentOpenTreeStructure();
                source.pageData.currentZoom = menu.currentZoom;
                source.pageData.currentPage = menu.currentPageNumber.get();
                source.pageData.maxPages = menu.maxPages;
                source.pageData.scrollTop = getId('__contentwrapper').scrollTop;
            }

            // Deactivate
            source.setIsCurrent(false);
            if (source.tabWrapper) {
                source.tabWrapper.setIsCurrent(false);
                if ( documentSearch && documentSearch.clearSearch ) {
                    documentSearch.clearSearch( true );
                }
            }
        } else if (source != this.currentlyActiveTab && !source.isCurrent()) {

            this.activateTab(this.currentlyActiveTab, false);

            source.setIsCurrent(true);
            if (source.tabWrapper) {
                source.tabWrapper.setIsCurrent(true);
            }

            this.currentlyActiveTab = source;

            // Now load the page!
            // Reset menubaractions
            let menu = new MenubarActions();
            window.VARIABLES = prepareAddParameterToArray(VARIABLES, source.subReportData, true); /* 2018-06-21 encode all parameters except specific ones too. */

            if (!source.loaded && !source.mainTab) {
                menu.currentZoom = DEFAULTZOOM;
                menu.currentPageNumber.set(1);
                menu.maxPages = '';

                // Reset the GroupTree
                // what if multiple ?
                menu.refreshReport(null, function (nestedScript) {

                    getPageCount.supplyWithData(function (data) {
                        source.loaded = true;
                        menu.zoom(0);

                        if (nestedScript) {
                            nestedScript();
                        }

                        if (source.finishFunction) {
                            source.finishFunction();
                        }
                    });
                });
            } else if (source.pageData) {

                menu.currentZoom = source.pageData.currentZoom;
                menu.maxPages = source.pageData.maxPages;

                var hasNoGroupTreeEntries = (source.pageData.grouptreeData || {}).length === 0;
                menu.currentPageNumber.set(source.pageData.currentPage); // Prepare page that will be set

                menu.refreshReport(hasNoGroupTreeEntries, function (nestedScript) {

                    if (!hasNoGroupTreeEntries) {
                        // Reset the GroupTree
                        getPageCount.DATA = source.pageData;
                        getPageCount.preliminaryDATA = null;
                        (new grouptree()).reset(false).init();
                        source.pageData.groupTreeOpenStructure = null;
                    }

                    if (nestedScript) {
                        nestedScript();
                    }

                    // Finally set the page and execute the finish function.
                    menu.setPage(source.pageData.currentPage, source.finishFunction);
                });
            }
        }
    };

    /**
     * Checks if we are in online mode before creating a tab
     * Especially for subreport tabs as they need to be online
     * 
     * @param {object}   subreportData  data of this tab for a subreport
     * @param {boolean}  isMainTab      if this is the main tab of the report
     * @param {function} finishFunction function to execute when the creation is finished
     */
    this.createOnlineOnlyTab = function (subreportData, isMainTab,
        finishFunction) {
        amIOnline.check(function (isOnline) {
            self.createTab(subreportData, isMainTab, isOnline, finishFunction);
        });
    };

    this.updateTabBarTop = function () {
        var wrapper = getId('__menuBarWrapper');
        if ( !wrapper || wrapper.hasClassName('navigationentry') ) { return; }
        //var top = wrapper.offsetHeight||"";
        //(getId('__tabBarWrapper')||{style:{}}).style.top = top + 'px';
        //(getId('__contentwrapper')||{style:{}}).style.top = top + 'px';
    };

    /**
     * Create the TapBar if none exists - also add the main tab
     * This will only be called once
     */
    this.createTabBar = function () {

        // HTMLViewer not really there ...
        if (!getId('__contentwrapper')) {
            return;
        }

        // Already inited
        if (this.managedElements.length > 0) {
            return;
        }

        var tabBarWrapper = document.createElement('div');
        tabBarWrapper.id = '__tabBarWrapper';
        getId('__contentwrapper').appendChild(tabBarWrapper);

        var tabBar = document.createElement('div');
        tabBarWrapper.appendChild(tabBar);
        tabBar.id = '__tabBar';

        // Create tab for very First Entry, which is the main report
        var element = new tabElement();
        element.name = null;
        this.createTab(element, true);

        this.updateTabBarTop();
        window.addEvent('resize', this.updateTabBarTop);
    };
};