Source: modules/export.js

/**
 * Enumeration of available menu types for the export menu
 * @readonly
 * @enum {number}
 */

/* global CANSHOWPERMALINK */
/* global SACK */
/* global buildBASEURLForPageFile */
/* global dataAsJson */
/* global dataHasJSONError */
/* global debug */
/* global errorPacketHandler */
/* global generator */
/* global getId */
/* global getTranslation */
/* global menubar */
/* global menubarLoading */
/* global prepareAddParameterToArray */
/* global setInnerText */

var documentExportFormats = {
    SUBMENU: 1,
    INPUT: 2,
    CHECKBOX: 3,
    COLOR: 4
};

/**
 * The Export module functions
 * @namespace
 */
var documentExport = {

    exportMenu: null,

    enabledFormats: [],

    currentFormat: null,

    odsXLSLines: [
        {
            type: documentExportFormats.SUBMENU,
            name: 'export.xls.truncatingBehavior',
            optionName: 'celltruncate',
            list: [{
                    name: 'Default',
                    value: ''
                },
                {
                    name: 'Yes',
                    value: 'true'
                },
                {
                    name: 'No',
                    value: 'false'
                }],
            action: null
            },
        {
            type: documentExportFormats.SUBMENU,
            name: 'export.xls.cellDistribution',
            optionName: 'celldistribution',
            list: [{
                    name: 'Default',
                    value: ''
                },
                {
                    name: 'export.xls.StaticLayout',
                    value: 'staticlayout'
                },
                {
                    name: 'export.xls.OneLine',
                    value: 'oneline'
                },
                {
                    name: 'export.xls.LineBreak',
                    value: 'linebreak'
                },
                {
                    name: 'export.xls.MultiCell',
                    value: 'multicells'
                },
                {
                    name: 'export.xls.MergeCells',
                    value: 'mergecells'
                },
                {
                    name: 'export.xls.SingleCell',
                    value: 'singlecell'
                }],
            action: null
            },
        {
            type: documentExportFormats.SUBMENU,
            name: 'export.xls.newSheetPerTopLevel',
            optionName: 'firstgroupassheets',
            list: [{
                    name: 'No',
                    value: 'false'
                },
                {
                    name: 'Yes',
                    value: 'true'
                }],
            action: null
            },
        {
            type: documentExportFormats.SUBMENU,
            name: 'export.xls.NumberOfGroupLevelOutline',
            optionName: 'grouplevel',
            list: ['0', '1', '2', '3', '4', '5', '6', '7'],
            action: null
		    }
        ],

    imageFormatLines: [
        {
            type: documentExportFormats.COLOR,
            name: 'export.image.backgroundColor',
            optionName: 'background',
            defaultValue: '#ffffff',
            action: null
            },
        {
            type: documentExportFormats.SUBMENU,
            name: 'export.image.zoom',
            list: [{
                    name: 'export.image.Zoom',
                    value: 'zoom'
                },
                {
                    name: 'export.image.Width',
                    value: 'width'
                },
                {
                    name: 'export.image.Height',
                    value: 'height'
                }],
            action: function (value, entry) {

                var checkEntry = documentExport.exportMenu.getEntry(documentExport.exportMenu.numberOfEntries() - 2).object;
                checkEntry = checkEntry && checkEntry.isImageExportSizeValue;

                documentExport.removeLastMenuEntry(checkEntry ? 1 : null);

                var zoomBox = null;

                switch (value.value) {
                case 'width':
                    zoomBox = documentExport.exportMenu.addInputValueElement("export.image.zoomInputValue.width", {
                        optionName: value.value
                    });
                    break;
                case 'height':
                    zoomBox = documentExport.exportMenu.addInputValueElement("export.image.zoomInputValue.height", {
                        optionName: value.value
                    });
                    break;
                case 'zoom':
                    /* fall through */
                default:
                    zoomBox = documentExport.exportMenu.addInputValueElement("export.image.zoomInputValue.zoom", {
                        optionName: value.value,
                        defaultValue: '100%'
                    });
                    break;
                }

                zoomBox.currentValueHolder.focus();

                zoomBox.isImageExportSizeValue = true;
                documentExport.addOKCancel();
            }
            }
        ],

    exportActions: function () {
        var basicActions = [{
            formatName: 'Adobe PDF',
            format: 'pdf',
            menulines: [{
                    type: documentExportFormats.SUBMENU,
                    name: 'export.pdf.navigationPanel',
                    optionName: 'navview',
                    list: [{
                            name: 'None',
                            value: ''
                        },
                        {
                            name: 'export.pdf.Bookmark',
                            value: 'bookmarks'
                        },
                        {
                            name: 'export.pdf.Pages',
                            value: 'pages'
                        }],
                    action: null
				},
                {
                    type: documentExportFormats.SUBMENU,
                    name: 'export.pdf.tags',
                    optionName: 'pdftags',
                    list: [{
                            name: 'Default',
                            value: ''
                        },
                        {
                            name: 'Yes',
                            value: 'true'
                        },
                        {
                            name: 'No',
                            value: 'false'
                        }],
                    action: null
				},
                {
                    type: documentExportFormats.SUBMENU,
                    name: 'export.pdf.extended',
                    optionName: '',
                    list: [{
                            name: 'None',
                            optionName: '',
                            value: 'false'
                        },
                        {
                            name: 'export.pdf.PDFA',
                            optionName: 'pdfa',
                            value: 'true'
                        },
                        {
                            name: 'export.pdf.FastWebView',
                            optionName: 'fastwebview',
                            value: 'true'
                        },
                        {
                            name: 'export.pdf.EncryptedPDFFile',
                            optionName: 'encrypted',
                            value: 'false'
                        }],
                    action: function (value, entry) {

                        var checkEntry = documentExport.exportMenu.getEntry(documentExport.exportMenu.numberOfEntries() - 2).object;
                        checkEntry = checkEntry && checkEntry.isEncryptedPDFFileElement;

                        if (checkEntry) {
                            documentExport.removeLastMenuEntry(2);
                        }

                        entry.object.currentValueHolder.setAttribute("name", value.optionName);

                        if (value.optionName == 'encrypted') {
                            if (!checkEntry) {
                                documentExport.removeLastMenuEntry();
                            }

                            var passwordUser = documentExport.exportMenu.addInputValueElement("export.pdf.extended.password.user", {
                                optionName: "upass"
                            });
                            passwordUser.currentValueHolder.setAttribute("type", "password");
                            passwordUser.currentValueHolder.focus();

                            var passwordOwner = documentExport.exportMenu.addInputValueElement("export.pdf.extended.password.owner", {
                                optionName: "opass"
                            });
                            passwordOwner.currentValueHolder.setAttribute("type", "password");

                            passwordOwner.isEncryptedPDFFileElement = passwordUser.isEncryptedPDFFileElement = true;

                            documentExport.addOKCancel();
                            entry.object.currentValueHolder.removeAttribute("name");
                        } else if (checkEntry) {
                            documentExport.addOKCancel();
                        }
                    }
				}]
			}, {
            formatName: 'HTML ZIP',
            format: 'htm',
            export_fmt: 'htm.zip',
            menulines: [{
                type: documentExportFormats.SUBMENU,
                name: 'export.html.layout',
                optionName: 'layout',
                list: [{
                        name: 'export.html.layout.multiple',
                        value: ''
                    },
                    {
                        name: 'export.html.layout.single.concat',
                        value: 'concat'
                    },
                    {
                        name: 'export.html.layout.single',
                        value: 'single'
                    }],
                action: null
				}]
			}, {
            formatName: 'Excel Spreadsheet (XLS)',
            format: 'xls',
            menulines: documentExport.odsXLSLines
			}, {
            formatName: 'Excel Spreadsheet (XLSX)',
            format: 'xlsx',
            menulines: documentExport.odsXLSLines
			}, {
            formatName: 'Open Document Spreadsheet',
            format: 'ods',
            menulines: documentExport.odsXLSLines
			}, {
            formatName: 'Postscript',
            format: 'ps',
            menulines: [{
                type: documentExportFormats.SUBMENU,
                name: 'export.ps.level',
                optionName: 'export_fmt',
                list: [{
                        name: 'export.ps.Level1',
                        value: 'ps'
                    },
                    {
                        name: 'export.ps.Level2',
                        value: 'ps2'
                    },
                    {
                        name: 'export.ps.Level3',
                        value: 'ps3'
                    }],
                action: null
				}]
			}, {
            formatName: 'Java Report Archive',
            format: 'jra',
            menulines: []
			}, {
            formatName: 'Plain Text',
            format: 'txt',
            menulines: [{
                    type: documentExportFormats.SUBMENU,
                    name: 'LineBreak',
                    optionName: 'newline',
                    list: [{
                            name: 'Default',
                            value: ''
                        },
                        {
                            name: 'export.txt.Windows',
                            value: "\r\n"
                        },
                        {
                            name: 'export.txt.MacOS',
                            value: "\n"
                        },
                        {
                            name: 'export.txt.Unix',
                            value: "\n"
                        }],
                    action: null
				},
                {
                    type: documentExportFormats.INPUT,
                    optionName: 'encoding',
                    name: 'export.csv.codepage',
                    defaultValue: 'UTF8',
                    action: null
				},
                {
                    type: documentExportFormats.SUBMENU,
                    name: 'export.txt.pageBreak',
                    optionName: 'pagebreak',
                    list: [{
                            name: 'export.txt.Line',
                            value: ''
                        },
                        {
                            name: 'export.txt.FormFeed',
                            value: "\f"
                        }, // \f | %0C
                        {
                            name: 'Other',
                            value: 'other'
                        }],
                    action: function (value) {

                        var checkEntry = documentExport.exportMenu.getEntry(documentExport.exportMenu.numberOfEntries() - 2).object;
                        checkEntry = checkEntry && checkEntry.isPageBreakOther;

                        if (checkEntry) {
                            documentExport.removeLastMenuEntry(1);
                        }

                        if (value.value == 'other') {
                            if (!checkEntry) {
                                documentExport.removeLastMenuEntry();
                            }

                            var pageBreak = documentExport.exportMenu.addInputValueElement("export.txt.pageBreakOther.Input", {
                                optionName: "pagebreak"
                            });
                            pageBreak.currentValueHolder.focus();
                            pageBreak.isPageBreakOther = true;

                            documentExport.addOKCancel();
                        } else if (checkEntry) {
                            documentExport.addOKCancel();
                        }
                    }
				}]
			}, {
            formatName: 'Microsoft Word',
            format: 'docx',
            menulines: [{
                type: documentExportFormats.CHECKBOX,
                name: 'export.rtf.editable',
                optionName: 'editable',
                defaultValue: 'true',
                action: null
				}]
			}, {
            formatName: 'Rich Text Format',
            format: 'rtf',
            menulines: [{
                type: documentExportFormats.CHECKBOX,
                name: 'export.rtf.editable',
                optionName: 'editable',
                defaultValue: 'true',
                action: null
				}]
			}, {
            formatName: 'CSV',
            format: function () {

                var returnFormat = 'csv';

                // If the menu is not initialized, this will be null.
                if (documentExport.exportMenu) {
                    documentExport.exportMenu.items.forEach(function (item, index) {
                        if (item.object && item.object.currentValueHolder &&
                            item.object.currentValueHolder.fullValue && item.object.currentValueHolder.fullValue.optionName &&
                            !item.object.currentValueHolder.fullValue.isDelimiter) {
                            returnFormat = item.object.currentValueHolder.fullValue.optionName;
                            return 'break';
                        }
                    });
                }

                return returnFormat;
            },
            menulines: [{
                    type: documentExportFormats.SUBMENU,
                    name: 'export.csv.dataOnly',
                    optionName: 'columnnames',
                    list: [{
                            name: 'export.csv.Everything',
                            optionName: 'csv',
                            value: 'false'
                        },
                        {
                            name: 'export.csv.DataOnly',
                            optionName: 'data',
                            value: 'false'
                        },
                        {
                            name: 'export.csv.DataOnlyWithColumnNames',
                            optionName: 'data',
                            value: 'true'
                        }],
                    action: null
				},
                {
                    type: documentExportFormats.INPUT,
                    optionName: 'quotechar',
                    name: 'export.csv.textQualifier',
                    defaultValue: '"',
                    action: null
				},
                {
                    type: documentExportFormats.INPUT,
                    optionName: 'encoding',
                    name: 'export.csv.codepage',
                    defaultValue: 'UTF8',
                    action: null
				},
                {
                    type: documentExportFormats.SUBMENU,
                    name: 'export.csv.columnDelimiter',
                    optionName: 'delimiter',
                    isDelimiter: true,
                    list: [{
                            name: 'export.csv.Comma',
                            value: ','
                        },
                        {
                            name: 'export.csv.Semicolon',
                            value: ';'
                        },
                        {
                            name: 'export.csv.Tab',
                            value: "\t"
                        },
                        {
                            name: 'Other',
                            optionName: 'delimiter',
                            isDelimiter: true
                        },
                        {
                            name: 'export.csv.FixedWidth',
                            optionName: 'colswidth',
                            isDelimiter: true,
                            labelName: "export.csv.columnDelimiter.FixedWidthInput"
                        }],
                    action: function (value, entry) {

                        var checkEntry = documentExport.exportMenu.getEntry(documentExport.exportMenu.numberOfEntries() - 2).object;
                        checkEntry = checkEntry && checkEntry.isColumnDelimiter;

                        if (checkEntry) {
                            documentExport.removeLastMenuEntry(1);
                        }

                        entry.object.currentValueHolder.setAttribute("name", value.optionName || 'delimiter');

                        if (value.optionName && value.isDelimiter) {
                            if (!checkEntry) {
                                documentExport.removeLastMenuEntry();
                            }

                            var pageBreak = documentExport.exportMenu.addInputValueElement(value.labelName || "export.csv.columnDelimiter.Input", {
                                optionName: value.optionName
                            });
                            entry.object.currentValueHolder.removeAttribute("name");
                            pageBreak.currentValueHolder.focus();
                            pageBreak.isColumnDelimiter = true;

                            documentExport.addOKCancel();
                        } else if (checkEntry) {
                            documentExport.addOKCancel();
                        }
                    }
				}]
			}, {
            formatName: 'JSON',
            format: 'json',
            menulines: []
			}, {
            formatName: 'XML',
            format: 'xml',
            menulines: []
			}, {
            formatName: 'PNG',
            format: 'png',
            menulines: documentExport.imageFormatLines
			}, {
            formatName: 'JPEG',
            format: 'jpg',
            menulines: documentExport.imageFormatLines
			}, {
            formatName: 'GIF',
            format: 'gif',
            menulines: documentExport.imageFormatLines
			}, {
            formatName: 'BMP',
            format: 'bmp',
            menulines: documentExport.imageFormatLines
			}];

        if (documentExport.enabledFormats == null) {
            return basicActions;
        }

        var formats = [];
        basicActions.forEach(function (format) {
            var form = generator.evalValue(format.format);
            if (documentExport.enabledFormats.in_array(form)) {
                formats.push(format);
            }
        });

        return formats;
    },

    /**
     * Attach the export dialog to a button
     * @param {object} button to use as base for the export menu
     * @param {object} element to prepend the new button to
     * @function
     */
    buildExport: function (parentButton, insertBefore) {

        var menu = new generator.submenuContainer(parentButton);
        menu.menuContainer.addClassName('__complexSubmenu');
        menu.submenu.addClassName('hidden-mobile-xs');
        documentExport.exportMenu = menu;

        documentExport.currentFormat = documentExport.exportMenu.addSubmenuSelector("menu.save.format");

        if (typeof insertBefore != 'undefined') {
            getId('__menuBar').insertBefore(menu.submenu, insertBefore);
        } else {
            getId('__menuBar').appendChild(menu.submenu);
        }

        //*
            // Disabled
        /*/
            // Should be part of a plugin
            if ( printListener ) {
                printListener.addFormat('Print via PDF Download', 'Downloads a PDF instead of using the browser print function', documentExport.printPDF);
            }
        //*/
    },

    /**
     * Show the export dialog
     * @function
     */
    showExport: function () {

        var formats = documentExport.exportActions();
        if (formats.length < 1) {
            return;
        }

        var isOpen = documentExport.exportMenu.menuContainer.hasClassName('open');
        if (!isOpen) {

            documentExport.currentFormat.submenu.clear();
            formats.forEach(function (value) {
                var item = documentExport.currentFormat.submenu.addEntry(getTranslation(value.formatName), function (e) {
                    documentExport.setFormat(value);
                }, null, false);
                item.setAttribute('data-format', generator.evalValue(value.format));
            });

            var savedFormatName = $.jStorage.get("format", formats[0].formatName);
            var format = formats.filter(function (value, index) {
                return value.formatName === savedFormatName;
            });

            documentExport.setFormat(format[0] || formats[0]);
        }

        documentExport.exportMenu.menuContainer.addRemoveClass('subMenuOpen', !isOpen && documentExport.currentFormat.submenu.menuContainer.hasClassName('open'));
        documentExport.exportMenu.menuContainer.addRemoveClass('open', !isOpen);
        documentExport.exportMenu.parentElement.setIsCurrent(!isOpen);
        documentExport.exportMenu.show(!isOpen);
    },

    getCurrentFormat: function () {
        return documentExport.currentFormat.currentValueHolder.value;
    },

    getFormatContainer: function (format) {
        var returnValue = null;
        documentExport.exportActions().forEach(function (value) {
            if (generator.evalValue(value.format) == format) {
                returnValue = value;
            }
        });
        return returnValue;
    },

    setFormat: function (format) {

        if (!format) {
            return;
        }
        var currentFormat = this.getCurrentFormat();
        if (currentFormat != null) {

            if (currentFormat == format) {
                return;
            }

            // Allways check and remove
            documentExport.removeLastMenuEntry(documentExport.exportMenu.numberOfEntries() - 2);
        }

        documentExport.currentFormat.currentValueHolder.value = format;
        setInnerText(documentExport.currentFormat.currentValueHolder, format.formatName);

        format.menulines.forEach(function (elem, index) {
            switch (elem.type) {
            case documentExportFormats.SUBMENU:
                documentExport.exportMenu.addSubmenuSelector(elem.name, elem);
                break;
            case documentExportFormats.COLOR:
            case documentExportFormats.INPUT:
                documentExport.exportMenu.addInputValueElement(elem.name, elem);
                break;
            case documentExportFormats.CHECKBOX:
                var entry = documentExport.exportMenu.addInputValueElement(elem.name, elem);
                var item = entry.currentValueHolder;
                item.checked = $.jStorage.get(elem.name + ".checkbox", false);

                item.setAttribute("type", "checkbox");
                item.parentNode.addClassName("checkbox");

                item.addEvent("change", function () {
                    $.jStorage.set(elem.name + ".checkbox", item.checked);
                });

                break;
            }
        });

        $.jStorage.set("format", format.formatName);
        documentExport.addOKCancel();
    },

    removeLastMenuEntry: function (count) {
        if (!count) {
            count = 0;
        }

        var numberOfEntries = documentExport.exportMenu.numberOfEntries();
        if (numberOfEntries > 1 && documentExport.exportMenu.getEntry(numberOfEntries - 1).object.isOKCancelBar) {
            count++;
        }

        while (count-- > 0) {
            documentExport.exportMenu.removeEntry(documentExport.exportMenu.numberOfEntries() - 1);
        }
    },

    addOKCancel: (function () {

        var group = null;

        return function () {
            var numberOfEntries = documentExport.exportMenu.numberOfEntries();
            if (numberOfEntries > 1 && documentExport.exportMenu.getEntry(numberOfEntries - 1).object.isOKCancelBar) {
                return; // already added
            }

            if (!group) {
                group = document.createElement('div');
                group.className = '__menuGroup __buttons right';
                group.style['float'] = 'none';
                group.style.display = 'inline-block';
                group.style.width = '100%';
                group.isOKCancelBar = true;

                (new menubar()).createButton("Cancel", "cancel", getTranslation("cancel"), documentExport.showExport, null, null, group, "");

                if (CANSHOWPERMALINK) {
                    (new menubar()).createButton("Permalink", "permalink", getTranslation("export.permalink.button"), documentExport.getPermaLink, null, null, group, "");
                }

                (new menubar()).createButton("OK", "ok", getTranslation("save"), documentExport.saveReport, null, null, group, "");
            }

            documentExport.exportMenu.addEntry(group);
        };
    })(),

    exportURLForType: function (type, isAttachment, additionalParams) {

        additionalParams = additionalParams || {};

        additionalParams.disposition = (isAttachment ? 'attachment' : 'inline');
        additionalParams.export_fmt = !additionalParams.export_fmt ? type : additionalParams.export_fmt; // May have been set already
        additionalParams.cmd = 'export';
        additionalParams.ts = (new Date()).getTime();

        // Has to send the prompt-params as well
        // But the params we just created should always be encoded. This has to be done separately
        return buildBASEURLForPageFile(null, null, prepareAddParameterToArray({}, additionalParams, true));
    },

    getReportExportURL: function () {

        var parameters = {};
        documentExport.exportMenu.items.forEach(function (value, index) {
            if (value.object && value.object.currentValueHolder) {

                var item = value.object.currentValueHolder;
                if (!item.getAttribute('name') || item.getAttribute('name').length === 0 || !item.value || item.value.length === 0) {
                    return;
                }

                if (item.getAttribute('type') == 'checkbox' && item.checked !== true) {
                    return;
                }

                // Add Parameter
                parameters[item.getAttribute('name')] = item.value;
            }
        });

        var format = generator.evalValue(documentExport.currentFormat.currentValueHolder.value.format);
        if (!parameters.export_fmt) {
            // Check if the export_fmt has been set - then use it.
            parameters.export_fmt = generator.evalValue(documentExport.currentFormat.currentValueHolder.value.export_fmt);
        }

        var URL = documentExport.exportURLForType(format, true, parameters);

        return {
            'format': format,
            'url': URL
        };
    },

    getPermaLink: function () {
        var exportData = documentExport.getReportExportURL();
        var url = exportData.url.replace(new RegExp('vgen=[0-9]+&'), '');
        debug("permalink URL: '" + url + "'");
        window.prompt(getTranslation("export.permalink.hint"), url);
    },

    /**
     * Saves the current Report File
     * @function
     */
    saveReport: function (event) {

        var exportData = documentExport.getReportExportURL();

        if (!getId('__saveReportFrame')) {
            var iframe = document.createElement('iframe');
            iframe.id = '__saveReportFrame';
            iframe.style.display = 'none';
            iframe.style.width = '0px';
            iframe.style.height = '0px';
            getId('__menuBarWrapper').appendChild(iframe);

            iframe.addEvent('load', function () {
                var thisDocument = this.document || this.contentDocument;
                dataHasJSONError(thisDocument.documentElement.innerText || thisDocument.documentElement.textContent);
            });
        }

        if (event) {
            documentExport.showExport();
        } // Only if triggered via the UI

        getId('__saveReportFrame').type = 'application/' + exportData.format;
        getId('__saveReportFrame').src = exportData.url;
        debug("export URL: '" + String(exportData.url) + "'");

			menubarLoading.start('save', true);
		var stopLoading = function() {
			menubarLoading.stop('save', true);
		};

		var checkProgress = function() {

			var ajax = new SACK(exportData.url.replace("cmd=export", "cmd=status"));
			ajax.afterCompletion = function( ) {
		        var data = dataAsJson( ajax.response, ajax.xmlhttp );
		        var status = ajax.responseStatus[0];

				if ( status == 200 && !(data.progress == 100 || data.state == 'NO_CACHE_ENTRY' ) ) {
					window.setTimeout( checkProgress, 1000 );
					return;
				}
				
				stopLoading();
			};
			
		    try {
		        /* If this goes wrong, ignore it */
		        ajax.onLocalFileFunction = stopLoading;
		        ajax.xmlhttp.onerror = stopLoading;
		    } catch (e) {
		    }

			ajax.runAJAX();
		};
		
		window.setTimeout( checkProgress, 100 );
    },
    
    printPDF: function() {
        // too many pages for a browser to handle
        var format = documentExport.getCurrentFormat();
        var pdfFormat = documentExport.getFormatContainer("pdf");
        if (pdfFormat == null) {
            new errorPacketHandler({
                errorHeader: getTranslation("print.toManyPagesWithoutPDF.title"),
                errorMessage: getTranslation("print.toManyPagesWithoutPDF.message")
            });
            return;
        }

        documentExport.setFormat(pdfFormat);
        documentExport.saveReport();
        documentExport.setFormat(format);
        return;
    }
};