PageSourceSearch

https://sacuq.uniquindio.edu.co/app/bower_components/tableexport.js/dist/js/tableexport.js

js uniquindio.edu.co collected 2026-09-24 21:30:04 UTC 49,497 bytes, 1,127 lines download raw bytes

1/*!
2 * TableExport.js v5.0.5 (https://www.travismclarke.com)
3 *
4 * Copyright (c) 2018 - Travis Clarke - https://www.travismclarke.com
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9
10 * http://www.apache.org/licenses/LICENSE-2.0
11
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 */
19
20
21;(function (root, factory) {
22    if (typeof define === 'function' && define.amd) {
23        // AMD
24        define(function (require) {
25            var $;
26            try {
27                $ = require('jquery')
28            } catch (e) {
29            }
30            return factory($, require('blobjs'), require('file-saverjs'), require('xlsx'));
31        });
32    } else if (typeof exports === 'object' && typeof exports.nodeName !== 'string') {
33        // CommonJS
34        var $;
35        try {
36            $ = require('jquery')
37        } catch (e) {
38        }
39        module.exports = factory($, require('blobjs'), require('file-saverjs'), require('xlsx'));
40    } else {
41        // Browser globals
42        root.TableExport = factory(root.jQuery, root.Blob, root.saveAs, root.XLSX);
43    }
44}(this, function ($, Blob, saveAs, XLSX) {
45        'use strict';
46        /**
47         * TableExport main library constructor
48         * @param selectors {jQuery} jQuery selector(s)
49         * @param options {Object} TableExport configuration options
50         * @constructor
51         */
52        var TableExport = function (selectors, options) {
53            var self = this;
54
55            if (!selectors) return _handleError('"selectors" is required. \nUsage: TableExport(selectors, options)');
56            if (!self) return new TableExport(selectors, options);
57
58            /**
59             * TableExport configuration options (user-defined w/ default fallback)
60             */
61            self.settings = _extend({}, self.defaults, options);
62            /**
63             * Selectors (tables) to apply the library to
64             */
65            self.selectors = _nodesArray(selectors);
66
67            var settings = self.settings;
68            settings.ignoreRows = settings.ignoreRows instanceof Array ? settings.ignoreRows : [settings.ignoreRows];
69            settings.ignoreCols = settings.ignoreCols instanceof Array ? settings.ignoreCols : [settings.ignoreCols];
70            settings.ignoreCSS = self.ignoreCSS instanceof Array ? self.ignoreCSS : [self.ignoreCSS];
71            settings.emptyCSS = self.emptyCSS instanceof Array ? self.emptyCSS : [self.emptyCSS];
72            settings.formatValue = self.formatValue.bind(this, settings.trimWhitespace);
73            settings.bootstrapSettings = _getBootstrapSettings(settings.bootstrap, self.bootstrapConfig, self.defaultButton);
74
75            var _exportData = {};
76            self.getExportData = function () {
77                return _exportData;
78            };
79
80            self.selectors.forEach(function (el) {
81                var context = {};
82
83                context.rows = _nodesArray(el.querySelectorAll('tbody > tr'));
84                context.rows = settings.headers ? _nodesArray(el.querySelectorAll('thead > tr')).concat(context.rows) : context.rows;
85                context.rows = settings.footers ? context.rows.concat(_nodesArray(el.querySelectorAll('tfoot > tr'))) : context.rows;
86                context.thAdj = settings.headers ? el.querySelectorAll('thead > tr').length : 0;
87                context.filename = settings.filename === 'id'
88                    ? (el.getAttribute('id') ? el.getAttribute('id') : self.defaultFilename)
89                    : (settings.filename ? settings.filename : self.defaultFilename);
90                context.uuid = _uuid(el);
91
92                /**
93                 * Initializes table caption with export buttons
94                 * @param exportButton {HTMLButtonElement}
95                 */
96                context.checkCaption = function (exportButton) {
97                    var caption = el.querySelectorAll('caption.' + self.defaultCaptionClass);
98                    if (caption.length) {
99                        caption[0].appendChild(exportButton);
100                    } else {
101                        caption = document.createElement('caption');
102                        caption.className = settings.bootstrapSettings.bootstrapSpacing + self.defaultCaptionClass;
103                        caption.style = 'caption-side: ' + settings.position;
104                        caption.appendChild(exportButton);
105                        el.insertBefore(caption, el.firstChild);
106                    }
107                };
108
109                context.setExportData = (function () {
110                    return function (exporter) {
111                        var data = Storage.getInstance().getItem(exporter);
112                        var type = exporter.substring(exporter.indexOf('-') + 1);
113                        _exportData[context.uuid] = _exportData[context.uuid] || {};
114                        _exportData[context.uuid][type] = JSON.parse(data);
115                    };
116                })();
117
118                context.rcMap = new RowColMap().build(context, settings);
119
120                var formatMap = _FORMAT_LIST
121                    .reduce(function (acc, cur) {
122                        acc[cur] = 0;
123                        return acc;
124                    }, {});
125
126                settings.formats.forEach(
127                    function (key) {
128                        if (!_isValidFormat(key)) {
129                            return _handleError('"' + key + '" is not a valid format. \nFormats: ' + _FORMAT_LIST.join(', '))
130                        } else if (!_hasDependencies(key)) {
131                            // TODO: provide a fallback option to XLS?
132                            return _handleError('"' + key + '" requires "js-xlsx".');
133                        } else if (!formatMap[key]) {
134                            context.setExportData(self.exporters.build.call(self, context, key));
135                            formatMap[key]++;
136                        }
137                    }
138                );
139            });
140
141            var exportButton = document.querySelectorAll('button[' + self.storageKey + ']');
142            _on(exportButton, 'click', self.downloadHandler, self);
143
144            return self;
145        };
146
147        TableExport.prototype = {
148            /**
149             * Version.
150             * @memberof TableExport.prototype
151             */
152            version: '5.0.5',
153            /**
154             * Default library options.
155             * @memberof TableExport.prototype
156             */
157            defaults: {
158                headers: true,                              // (Boolean), display table headers (th or td elements) in the <thead>, (default: true)
159                footers: true,                              // (Boolean), display table footers (th or td elements) in the <tfoot>, (default: false)
160                formats: ['xlsx', 'csv', 'txt'],            // (String[]), filetype(s) for the export, (default: ['xlsx', 'csv', 'txt'])
161                filename: 'id',                             // (id, String), filename for the downloaded file, (default: 'id')
162                bootstrap: false,                           // (Boolean), style buttons using bootstrap, (default: true)
163                exportButtons: true,                        // (Boolean), automatically generate the built-in export buttons for each of the specified formats (default: true)
164                position: 'bottom',                         // (top, bottom), position of the caption element relative to table, (default: 'bottom')
165                ignoreRows: null,                           // (Number, Number[]), row indices to exclude from the exported file(s) (default: null)
166                ignoreCols: null,                           // (Number, Number[]), column indices to exclude from the exported file(s) (default: null)
167                trimWhitespace: true                        // (Boolean), remove all leading/trailing newlines, spaces, and tabs from cell text in the exported file(s) (default: false)
168            },
169            /**
170             * Constants
171             * @memberof TableExport.prototype
172             */
173            CONSTANTS: {
174                FORMAT: {
175                    XLSX: 'xlsx',
176                    XLSM: 'xlsm',
177                    XLSB: 'xlsb',
178                    BIFF2: 'biff2',
179                    XLS: 'xls',
180                    CSV: 'csv',
181                    TXT: 'txt'
182                },
183                TYPE: {
184                    STRING: 's',
185                    NUMBER: 'n',
186                    BOOLEAN: 'b',
187                    DATE: 'd'
188                }
189            },
190            /**
191             * Character set (character encoding) of the HTML.
192             * @memberof TableExport.prototype
193             */
194            charset: 'charset=utf-8',
195            /**
196             * Filename fallback for exported files.
197             * @memberof TableExport.prototype
198             */
199            defaultFilename: 'myDownload',
200            /**
201             * Class applied to each export button element.
202             * @memberof TableExport.prototype
203             */
204            defaultButton: 'button-default',
205            /**
206             * Class applied to each table caption.
207             * @memberof TableExport.prototype
208             */
209            defaultCaptionClass: 'tableexport-caption',
210            /**
211             * Namespace (i.e. prefix) applied to each table UUID and Storage key.
212             * @memberof TableExport.prototype
213             */
214            defaultNamespace: 'tableexport-',
215            /**
216             * Attribute applied to each table element used to generate each Storage key.
217             * @memberof TableExport.prototype
218             */
219            tableKey: 'tableexport-key',
220            /**
221             * Attribute applied to each export button element used to reference a Storage key.
222             * @memberof TableExport.prototype
223             */
224            storageKey: 'tableexport-id',
225            /**
226             * CSS selector or selector[] to exclude/remove cells from the exported file(s).
227             * @type {selector|selector[]}
228             * @memberof TableExport.prototype
229             */
230            ignoreCSS: '.tableexport-ignore',
231            /**
232             * CSS selector or selector[] to replace cells with an empty string in the exported file(s).
233             * @type {selector|selector[]}
234             * @memberof TableExport.prototype
235             */
236            emptyCSS: '.tableexport-empty',
237            /**
238             * Bootstrap configuration classes ['base', 'theme', 'container'].
239             * @memberof TableExport.prototype
240             */
241            bootstrapConfig: ['btn', 'btn-default', 'btn-toolbar'],
242            /**
243             * Row delimeter
244             * @memberof TableExport.prototype
245             */
246            rowDel: '\r\n',
247            /**
248             * HTML entity mapping for special characters.
249             * @memberof TableExport.prototype
250             */
251            entityMap: {'&': '&#38;', '<': '&#60;', '>': '&#62;', "'": '&#39;', '/': '&#47;'},
252            /**
253             * Format configuration
254             * @memberof TableExport.prototype
255             */
256            formatConfig: {
257                /**
258                 * XLSX (Open XML spreadsheet) file extension configuration
259                 * @memberof TableExport.prototype
260                 */
261                xlsx: {
262                    defaultClass: 'xlsx',
263                    buttonContent: 'Export to xlsx',
264                    mimeType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
265                    fileExtension: '.xlsx'
266                },
267                xlsm: {
268                    defaultClass: 'xlsm',
269                    buttonContent: 'Export to xlsm',
270                    mimeType: 'application/vnd.ms-excel.sheet.macroEnabled.main+xml',
271                    fileExtension: '.xlsm'
272                },
273                xlsb: {
274                    defaultClass: 'xlsb',
275                    buttonContent: 'Export to xlsb',
276                    mimeType: 'application/vnd.ms-excel.sheet.binary.macroEnabled.main',
277                    fileExtension: '.xlsb'
278                },
279                /**
280                 * XLS (Binary spreadsheet) file extension configuration
281                 * @memberof TableExport.prototype
282                 */
283                xls: {
284                    defaultClass: 'xls',
285                    buttonContent: 'Export to xls',
286                    separator: '\t',
287                    mimeType: 'application/vnd.ms-excel',
288                    fileExtension: '.xls',
289                    enforceStrictRFC4180: false
290                },
291                /**
292                 * CSV (Comma Separated Values) file extension configuration
293                 * @memberof TableExport.prototype
294                 */
295                csv: {
296                    defaultClass: 'csv',
297                    buttonContent: 'Export to csv',
298                    separator: ',',
299                    mimeType: 'text/csv',
300                    fileExtension: '.csv',
301                    enforceStrictRFC4180: true
302                },
303                /**
304                 * TXT (Plain Text) file extension configuration
305                 * @memberof TableExport.prototype
306                 */
307                txt: {
308                    defaultClass: 'txt',
309                    buttonContent: 'Export to txt',
310                    separator: '  ',
311                    mimeType: 'text/plain',
312                    fileExtension: '.txt',
313                    enforceStrictRFC4180: true
314                }
315            },
316            /**
317             * Cell-types override and assertion configuration
318             * @memberof TableExport.prototype
319             */
320            typeConfig: {
321                string: {
322                    defaultClass: 'tableexport-string'
323                },
324                number: {
325                    defaultClass: 'tableexport-number',
326                    assert: function (v) {
327                        return !isNaN(v);
328                    }
329                },
330                boolean: {
331                    defaultClass: 'tableexport-boolean',
332                    assert: function (v) {
333                        return v.toLowerCase() === 'true' || v.toLowerCase() === 'false';
334                    }
335                },
336                date: {
337                    defaultClass: 'tableexport-date',
338                    assert: function (v) {
339                        return !(/.*%/.test(v)) && !isNaN(Date.parse(v))
340                    }
341                }
342            },
343            exporters: {
344                build: function (context, key) {
345                    var self = this;
346                    var settings = self.settings;
347                    var format = self.formatConfig[key];
348                    var colDel = format.separator;
349                    var rcMap = context.rcMap;
350
351                    var getReturn = function (val) {
352                        if (_isEnhanced(key)) {
353                            return {
354                                v: settings.formatValue(val.textContent),
355                                t: self.getType(val.className)
356                            }
357                        }
358                        switch (key) {
359                            case _FORMAT.CSV:
360                                return '"' + settings.formatValue(val.textContent.replace(/"/g, '""')) + '"';
361                            default:
362                                return settings.formatValue(val.textContent);
363                        }
364                    };
365
366                    var dataURI = _nodesArray(context.rows).map(function (val, ir) {
367                        if (rcMap.isIgnore(ir)) {
368                            return rcMap.handleRowColMapProp(rcMap.TYPE.IGNORE);
369                        } else if (rcMap.isEmpty(ir)) {
370                            return rcMap.handleRowColMapProp(rcMap.TYPE.EMPTY);
371                        }
372                        var cols = val.querySelectorAll('th, td');
373                        return _nodesArray(cols).map(function (val, ic) {
374                            var _return = getReturn(val);
375                            if (rcMap.isIgnore(ir, ic)) {
376                                return rcMap.handleRowColMapProp(rcMap.TYPE.IGNORE);
377                            } else if (rcMap.isEmpty(ir, ic)) {
378                                return rcMap.handleRowColMapProp(rcMap.TYPE.EMPTY);
379                            } else {
380                                return rcMap.handleRowColMapProp(rcMap.TYPE.DEFAULT, ir, ic, key, _return, colDel);
381                            }
382                        }).processCols(key, colDel);
383                    }).processRows(key, self.rowDel);
384
385                    var dataObject = JSON.stringify({
386                        data: dataURI,
387                        filename: context.filename,
388                        mimeType: format.mimeType,
389                        fileExtension: format.fileExtension,
390                        merges: rcMap.merges
391                    });
392
393                    var hashKey = _hashCode({uuid: context.uuid, type: key});
394
395                    settings.exportButtons && context.checkCaption(self.createObjButton(
396                        hashKey,
397                        dataObject,
398                        format.buttonContent,
399                        format.defaultClass,
400                        settings.bootstrapSettings
401                    ));
402                    return Storage.getInstance().setItem(hashKey, dataObject, true);
403                }
404            },
405            /**
406             * Creates file export buttons
407             * @param hashKey {String}
408             * @param dataObject {String}
409             * @param myContent {String}
410             * @param myClass {String}
411             * @param bootstrapSettings {Object}
412             * @returns Element
413             */
414            createObjButton: function (hashKey, dataObject, myContent, myClass, bootstrapSettings) {
415                var exportButton = document.createElement('button');
416                exportButton.setAttribute('type', 'button');
417                exportButton.setAttribute(this.storageKey, hashKey);
418                exportButton.className = bootstrapSettings.bootstrapClass + bootstrapSettings.bootstrapTheme + myClass;
419                exportButton.textContent = myContent;
420                return exportButton
421            },
422            /**
423             * Escapes special characters with HTML entities
424             * @memberof TableExport.prototype
425             * @param string {String}
426             * @returns {String} escaped string
427             */
428            escapeHtml: function (string) {
429                var self = this;
430                return String(string).replace(/[&<>'\/]/g, function (s) {
431                    return self.entityMap[s];
432                });
433            },
434            /**
435             * Unescapes HTML entities to special characters
436             * @memberof TableExport.prototype
437             * @param string {String}
438             * @returns {String} unescaped string
439             */
440            unescapeHtml: function (string) {
441                var str = String(string);
442                for (var key in this.entityMap) {
443                    str = str.replace(RegExp(this.entityMap[key], 'g'), key);
444                }
445                return str;
446            },
447            /**
448             * Removes leading/trailing whitespace from cell string
449             * @param isTrimWhitespace {Boolean}
450             * @param string {String}
451             * @returns {String} trimmed string
452             */
453            formatValue: function (isTrimWhitespace, string) {
454                return isTrimWhitespace ? string.trim() : string;
455            },
456            /**
457             * Get cell data-type
458             * @param string {String}
459             * @returns {String} data-type
460             */
461            getType: function (string) {
462                if (!string) return '';
463                var types = this.typeConfig;
464                if (~string.indexOf(types.string.defaultClass)) {
465                    return _TYPE.STRING;
466                } else if (~string.indexOf(types.number.defaultClass)) {
467                    return _TYPE.NUMBER;
468                } else if (~string.indexOf(types.boolean.defaultClass)) {
469                    return _TYPE.BOOLEAN;
470                } else if (~string.indexOf(types.date.defaultClass)) {
471                    return _TYPE.DATE;
472                } else {
473                    return '';
474                }
475            },
476            /**
477             * Formats datetimes for compatibility with Excel
478             * @memberof TableExport.prototype
479             * @param v {Number}
480             * @param date1904 {Date}
481             * @returns {Number} epoch time
482             */
483            dateNum: function (v, date1904) {
484                if (date1904) v += 1462;
485                var epoch = Date.parse(v);
486                var result = (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);
487                return Math.floor(result);
488            },
489            /**
490             * Creates an Excel spreadsheet from a data string
491             * @memberof TableExport.prototype
492             * @param data {String}
493             * @param merges {Object[]}
494             */
495            createSheet: function (data, merges) {
496                var ws = {};
497                var range = {s: {c: 10000000, r: 10000000}, e: {c: 0, r: 0}};
498                var types = this.typeConfig;
499                for (var R = 0; R !== data.length; ++R) {
500                    for (var C = 0; C !== data[R].length; ++C) {
501                        if (range.s.r > R) range.s.r = R;
502                        if (range.s.c > C) range.s.c = C;
503                        if (range.e.r < R) range.e.r = R;
504                        if (range.e.c < C) range.e.c = C;
505                        var cell = data[R][C];
506                        if (!cell || !cell.v) continue;
507                        var cell_ref = XLSX.utils.encode_cell({c: C, r: R});
508
509                        if (!cell.t) {
510                            if (types.number.assert(cell.v)) cell.t = _TYPE.NUMBER;
511                            else if (types.boolean.assert(cell.v)) cell.t = _TYPE.BOOLEAN;
512                            else if (types.date.assert(cell.v)) cell.t = _TYPE.DATE;
513                            else cell.t = _TYPE.STRING;
514                        }
515                        if (cell.t === _TYPE.DATE) {
516                            cell.t = _TYPE.NUMBER;
517                            cell.z = XLSX.SSF._table[14];
518                            cell.v = this.dateNum(cell.v);
519                        }
520                        ws[cell_ref] = cell;
521                    }
522                }
523                ws['!merges'] = merges;
524                if (range.s.c < 10000000) ws['!ref'] = XLSX.utils.encode_range(range);
525                return ws;
526            },
527            /**
528             * Click handler for export button "download"
529             * @memberof TableExport.prototype
530             */
531            downloadHandler: function (event) {
532                var target = event.target;
533                var object = JSON.parse(Storage.getInstance().getItem(target.getAttribute(this.storageKey))),
534                    data = object.data,
535                    filename = object.filename,
536                    mimeType = object.mimeType,
537                    fileExtension = object.fileExtension,
538                    merges = object.merges;
539                this.export2file(data, mimeType, filename, fileExtension, merges);
540            },
541            /**
542             * Excel Workbook constructor
543             * @memberof TableExport.prototype
544             * @constructor
545             */
546            Workbook: function () {
547                this.SheetNames = [];
548                this.Sheets = {};
549            },
550            /**
551             * Converts a string to an arraybuffer
552             * @param s {String}
553             * @memberof TableExport.prototype
554             * @returns {ArrayBuffer}
555             */
556            string2ArrayBuffer: function (s) {
557                var buf = new ArrayBuffer(s.length);
558                var view = new Uint8Array(buf);
559                for (var i = 0; i !== s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
560                return buf;
561            },
562            /**
563             * Exports and downloads the file
564             * @memberof TableExport.prototype
565             * @param data {String}
566             * @param mime {String} mime type
567             * @param name {String} filename
568             * @param extension {String} file extension
569             * @param merges {Object[]}
570             */
571            export2file: function (data, mime, name, extension, merges) {
572                var format = extension.slice(1);
573                data = this.getRawData(data, extension, name, merges);
574
575                if (_isMobile && (format === _FORMAT.CSV || format === _FORMAT.TXT)) {
576                    var dataURI = 'data:' + mime + ';' + this.charset + ',' + data;
577                    this.downloadDataURI(dataURI, name, extension);
578                } else {
579                    // TODO: error and fallback when `saveAs` not available
580                    saveAs(new Blob([data],
581                        {type: mime + ';' + this.charset}),
582                        name + extension, true);
583                }
584            },
585            downloadDataURI: function (dataURI, name, extension) {
586                var encodedUri = encodeURI(dataURI);
587                var link = document.createElement('a');
588                link.setAttribute('href', encodedUri);
589                link.setAttribute('download', name + extension);
590                document.body.appendChild(link);
591                link.click();
592            },
593            getBookType: function (key) {
594                switch (key) {
595                    case _FORMAT.XLS:
596                        return _FORMAT.BIFF2;
597                    default:
598                        return key;
599                }
600            },
601            getRawData: function (data, extension, name, merges) {
602                var key = extension.substring(1);
603
604                if (_isEnhanced(key)) {
605                    var wb = new this.Workbook(),
606                        ws = this.createSheet(data, merges),
607                        bookType = this.getBookType(key);
608
609                    name = name || '';
610                    wb.SheetNames.push(name);
611                    wb.Sheets[name] = ws;
612                    var wopts = {
613                            bookType: bookType,
614                            bookSST: false,
615                            type: 'binary'
616                        },
617                        wbout = XLSX.write(wb, wopts);
618
619                    data = this.string2ArrayBuffer(wbout);
620                }
621                return data;
622            },
623            getFileSize: function (data, extension) {
624                var binary = this.getRawData(data, extension);
625                return binary instanceof ArrayBuffer
626                    ? binary.byteLength
627                    : this.string2ArrayBuffer(binary).byteLength;
628            },
629            /**
630             * Updates the library instance with new/updated options
631             * @param options {Object} TableExport configuration options
632             * @returns {TableExport} updated TableExport instance
633             */
634            update: function (options) {
635                this.remove();
636                return new TableExport(this.selectors, _extend({}, this.defaults, options));
637            },
638            /**
639             * Reset the library instance to its original state
640             * @returns {TableExport} original TableExport instance
641             */
642            reset: function () {
643                this.remove();
644                return new TableExport(this.selectors, this.settings);
645            },
646            /**
647             * Remove the instance (i.e. caption containing the export buttons)
648             */
649            remove: function () {
650                var self = this;
651                this.selectors.forEach(function (el) {
652                    var caption = el.querySelector('caption.' + self.defaultCaptionClass);
653                    caption && el.removeChild(caption);
654                });
655            }
656        };
657
658        /**
659         * Storage main interface constructor
660         * @memberof TableExport.prototype
661         * @constructor
662         */
663        var Storage = function () {
664            this._instance = null;
665
666            this.store = sessionStorage;
667            this.namespace = TableExport.prototype.defaultNamespace;
668            this.getKey = function (key) {
669                return this.namespace + key;
670            };
671            this.setItem = function (_key, value, overwrite) {
672                var key = this.getKey(_key);
673                if (this.exists(_key) && !overwrite) {
674                    return;
675                }
676                if (typeof value !== 'string') return _handleError('"value" must be a string.');
677                this.store.setItem(key, value);
678                return _key;
679            };
680            this.getItem = function (_key) {
681                var key = this.getKey(_key);
682                return this.store.getItem(key);
683            };
684            this.exists = function (_key) {
685                var key = this.getKey(_key);
686                return this.store.getItem(key) !== null;
687            };
688            this.removeItem = function (_key) {
689                var key = this.getKey(_key);
690                return this.store.removeItem(key);
691            };
692        };
693        Storage.getInstance = function () {
694            if (!this._instance) {
695                this._instance = new Storage();
696            }
697            return this._instance;
698        };
699
700        /**
701         * RowColMap main interface constructor
702         * @memberof TableExport.prototype
703         * @constructor
704         */
705        var RowColMap = function () {
706            this.rcMap = [];
707            this.merges = [];
708
709            this.isIgnore = function (ir, ic) {
710                var _ignore = RowColMap.prototype.TYPE.IGNORE;
711                return this.getRowColMapProp(ir, ic, _ignore);
712            };
713            this.isEmpty = function (ir, ic) {
714                var _empty = RowColMap.prototype.TYPE.EMPTY;
715                return this.getRowColMapProp(ir, ic, _empty);
716            };
717            this.isRowSpan = function (ir) {
718                var _rowspan = RowColMap.prototype.TYPE.ROWSPAN;
719                return this.getRowColMapProp(ir, undefined, _rowspan);
720            };
721            this.isColSpan = function (ir) {
722                var _colspan = RowColMap.prototype.TYPE.COLSPAN;
723                return this.getRowColMapProp(ir, undefined, _colspan);
724            };
725            this.isSpan = function (ir) {
726                return this.isRowSpan(ir) || this.isColSpan(ir);
727            };
728            this.isMerge = function (ir) {
729                return this.merges.length > 0;
730            };
731            this.addMerge = function (ir, mergeObj) {
732                var _merge = RowColMap.prototype.TYPE.MERGE;
733                this.merges.push(mergeObj);
734                this.setRowColMapProp(ir, undefined, _merge, this.merges);
735            };
736            this.getRowColMapProp = function (ir, ic, key) {
737                if (this.rcMap[ir]) {
738                    if (typeof key === 'undefined') {
739                        return this.rcMap[ir][ic];
740                    } else if (typeof ic === 'undefined') {
741                        return this.rcMap[ir][key];
742                    } else if (this.rcMap[ir][ic]) {
743                        return this.rcMap[ir][ic][key];
744                    }
745                }
746                return undefined;
747            };
748            this.setRowColMapProp = function (ir, ic, key, value) {
749                this.rcMap[ir] = this.rcMap[ir] || [];
750                if (typeof key === 'undefined') {
751                    return this.rcMap[ir][ic] = value;
752                } else if (typeof ic === 'undefined') {
753                    return this.rcMap[ir][key] = value;
754                } else {
755                    this.rcMap[ir][ic] = this.rcMap[ir][ic] || [];
756                    return this.rcMap[ir][ic][key] = value;
757                }
758            };
759            this.generateTotal = function (ir, ic) {
760                var VALUE = RowColMap.prototype.TYPE.VALUE;
761                var _total = 0;
762
763                if (this.isRowSpan(ir) && this.isColSpan(ir)) {
764                    _total = this.getRowColMapProp(ir, ic, VALUE) || 0;
765                } else if (this.getRowColMapProp(ir, ic, VALUE)) {
766                    _total = this.getRowColMapProp(ir, ic, VALUE);
767                }
768                return _total;
769            };
770            this.convertSpanToArray = function (ir, ic, key, _return, colDel) {
771                if (this.rcMap[ir] && this.isSpan(ir)) {
772                    var total = this.generateTotal(ir, ic);
773
774                    if (_isEnhanced(key)) {
775                        return new Array(total).concat(_return);
776                    } else {
777                        return new Array(total).concat(_return).join(colDel);
778                    }
779                }
780                return _return;
781            };
782            this.handleRowColMapProp = function (type, ir, ic, key, _return, colDel) {
783                switch (type) {
784                    case RowColMap.prototype.TYPE.IGNORE:
785                        return;
786                    case RowColMap.prototype.TYPE.EMPTY:
787                        return ' ';
788                    case RowColMap.prototype.TYPE.DEFAULT:
789                    default:
790                        return this.convertSpanToArray(ir, ic, key, _return, colDel);
791                }
792            };
793        };
794        RowColMap.prototype = {
795            OFFSET: 1,
796            TYPE: {
797                IGNORE: 'ignore',
798                EMPTY: 'empty',
799                MERGE: 'merge',
800                ROWSPAN: 'rowspan',
801                ROWSPANTOTAL: 'rowspantotal',
802                COLSPAN: 'colspan',
803                COLSPANTOTAL: 'colspantotal',
804                DEFAULT: 'default',
805                VALUE: 'value'
806            },
807            build: function (context, settings) {
808                var self = this;
809
810                var OFFSET = self.OFFSET;
811                var rowLength = self.rowLength = context.rows.length;
812                // var colLength = self.colLength = Math.max.apply(null,
813                //     _nodesArray(context.rows).map(function (val) {
814                //         return val.querySelectorAll('th, td').length
815                //     }));
816
817                var handleIgnore = function (ir, ic) {
818                    self.setRowColMapProp(ir, ic, self.TYPE.IGNORE, true);
819                };
820                var handleEmpty = function (ir, ic) {
821                    self.setRowColMapProp(ir, ic, self.TYPE.EMPTY, true);
822                };
823                var handleRowSpan = function (val, ir, ic) {
824                    var rowSpan = +val.getAttribute('rowspan');
825                    var colSpan = +val.getAttribute('colspan');
826                    var handledByColSpan,
827                        countRowSpan, countColSpan,
828                        totalRowSpan, totalColSpan,
829                        irStart, irEnd, icStart, icEnd;
830
831                    for (var _row = 0; _row < rowSpan; _row++) {
832                        if (_row + ir >= rowLength) {
833                            return;
834                        }
835                        colSpan && (handledByColSpan = handleColSpan(val, _row + ir, ic, _row > 0, rowSpan));
836
837                        if (rowSpan <= 1) {
838                            return false;
839                        }
840                        var cur = self.rcMap['c' + (ic - 1)] ? self.rcMap['c' + (ic - 1)][_row + ir] : 0;
841                        if (cur) {
842                            self.rcMap['c' + (ic)] = self.rcMap['c' + (ic)] || [];
843                            self.rcMap['c' + (ic)][_row + ir] = (self.rcMap['c' + (ic)][_row + ir] || 0) + cur;
844                        }
845
846                        if (rowSpan && _row === 0 && colSpan > 1) {
847                            for (var i = 0; i < rowSpan; i++) {
848                                self.rcMap['c' + (ic + 1)] = self.rcMap['c' + (ic + 1)] || [];
849                                self.rcMap['c' + (ic + 1)][_row + ir + i] = (self.rcMap['c' + (ic + 1)][_row + ir + i] || 0) + Math.max(1, colSpan);
850
851                            }
852                        }
853
854                        if (_row >= 1) {
855                            countRowSpan = self.getRowColMapProp(_row + ir, undefined, self.TYPE.ROWSPAN) || 0;
856                            self.setRowColMapProp(_row + ir, undefined, self.TYPE.ROWSPAN, countRowSpan + 1);
857
858                            if (!handledByColSpan) {
859                                totalRowSpan = self.getRowColMapProp(_row + ir, ic - countRowSpan, self.TYPE.VALUE) || 0;
860                                self.setRowColMapProp(_row + ir, ic - countRowSpan, self.TYPE.VALUE, totalRowSpan + 1);
861                                if (rowSpan > 1 && _row === 1) {
862                                    var _re = self.rcMap['c' + (ic)] && self.rcMap['c' + (ic)][_row + ir];
863                                    totalColSpan = self.getRowColMapProp(ir, undefined, self.TYPE.COLSPANTOTAL) || 0;
864                                    countColSpan = self.getRowColMapProp(ir, undefined, self.TYPE.COLSPAN) || 0;
865                                    irStart = ir;
866                                    irEnd = ir + rowSpan - 1;
867                                    icStart = ic + totalColSpan - countColSpan + (_re || 0);
868                                    icEnd = icStart + Math.max(1, colSpan) - 1;
869                                    handleMerge(irStart, icStart, irEnd, icEnd);
870                                }
871                            }
872                        }
873                    }
874                };
875
876                var handleColSpan = function (val, ir, ic, isRowSpan, rowSpan) {
877                    var irStart, irEnd, icStart, icEnd;
878                    var colSpan = +val.getAttribute('colspan');
879                    var countColSpan = self.getRowColMapProp(ir, undefined, self.TYPE.COLSPAN) || 0;
880                    var totalColSpan = self.getRowColMapProp(ir, undefined, self.TYPE.COLSPANTOTAL) || 0;
881
882                    if (colSpan <= 1) {
883                        return false;
884                    }
885
886                    self.setRowColMapProp(ir, undefined, self.TYPE.COLSPAN, countColSpan + 1);
887                    self.setRowColMapProp(ir, undefined, self.TYPE.COLSPANTOTAL, totalColSpan + colSpan);
888
889                    if (isRowSpan) {
890                        self.setRowColMapProp(ir, ic - countColSpan, self.TYPE.VALUE, colSpan);
891                        return true;
892                    } else {
893                        irStart = ir;
894                        irEnd = ir + (rowSpan || 1) - OFFSET;
895                        icStart = ic + totalColSpan - countColSpan;
896                        icEnd = ic + totalColSpan - countColSpan + (colSpan - OFFSET);
897                        self.setRowColMapProp(ir, ic + OFFSET, self.TYPE.VALUE, colSpan - OFFSET);
898                        handleMerge(irStart, icStart, irEnd, icEnd);
899                    }
900                };
901
902                var handleMerge = function (irs, ics, ire, ice) {
903                    var merge = {
904                        s: {r: irs, c: ics},
905                        e: {r: ire, c: ice}
906                    };
907                    return self.addMerge(irs, merge);
908                };
909
910                _nodesArray(context.rows).map(function (val, ir) {
911                    if (!!~settings.ignoreRows.indexOf(ir - context.thAdj) || _matches(val, settings.ignoreCSS)) {
912                        handleIgnore(ir);
913                    }
914                    if (_matches(val, settings.emptyCSS)) {
915                        handleEmpty(ir);
916                    }
917                    var cols = val.querySelectorAll('th, td');
918                    return _nodesArray(cols).map(function (val, ic) {
919                        if (!!~settings.ignoreCols.indexOf(ic) || _matches(val, settings.ignoreCSS)) {
920                            handleIgnore(ir, ic);
921                        }
922                        if (_matches(val, settings.emptyCSS)) {
923                            handleEmpty(ir, ic);
924                        }
925                        if (val.hasAttribute('rowspan')) {
926                            handleRowSpan(val, ir, ic);
927                        } else if (val.hasAttribute('colspan')) {
928                            handleColSpan(val, ir, ic);
929                        }
930                    });
931                });
932
933                return self;
934            }
935        };
936
937        var _isMobile = (function isMobile(ua) {
938            return /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(ua)
939                || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(ua.substring(0, 4))
940        })(navigator.userAgent || navigator.vendor || window.opera);
941
942        var _isEnhanced = (function () {
943            return function (key) {
944                return (
945                    XLSX
946                    && !(TableExport.prototype.formatConfig[key].enforceStrictRFC4180)
947                );
948            }
949        })();
950
951        var _FORMAT = (function () {
952            return TableExport.prototype.CONSTANTS.FORMAT;
953        })();
954
955        var _FORMAT_LIST = (function () {
956            return Object.keys(_FORMAT).map(function (key) {
957                return _FORMAT[key];
958            });
959        })();
960
961        var _TYPE = (function () {
962            return TableExport.prototype.CONSTANTS.TYPE;
963        })();
964
965        Object.defineProperty(Array.prototype, 'processRows', {
966          enumerable: false,
967          value: function (key, rowDel) {
968            if (_isEnhanced(key)) {
969              return this.map(_toArray).filter(_defined);
970            } else {
971              return this.filter(_defined).join(rowDel);
972            }
973          }
974        });
975
976        Object.defineProperty(Array.prototype, 'processCols', {
977          enumerable: false,
978          value: function (key, colDel) {
979            if (_isEnhanced(key)) {
980              return this.filter(_defined);
981            } else {
982              return this.filter(_defined).join(colDel);
983            }
984          }
985        });
986
987        var _uuid = (function () {
988            var uuid = 0;
989
990            return function (el) {
991                var tableKey = el.getAttribute(TableExport.prototype.tableKey);
992
993                if (!tableKey) {
994                    tableKey = el.id
995                        ? el.id
996                        : TableExport.prototype.defaultNamespace + (++uuid);
997                    el.setAttribute(TableExport.prototype.tableKey, tableKey);
998                }
999                return tableKey;
1000            };
1001        })();
1002
1003        var _hashCode = (function () {
1004
1005            return function (hashKey) {
1006                var hash = 0, i, char;
1007
1008                var type = hashKey.type;
1009                hashKey = JSON.stringify(hashKey);
1010                if (hashKey.length === 0) return hash;
1011                for (i = 0; i < hashKey.length; i++) {
1012                    char = hashKey.charCodeAt(i);
1013                    hash = ((hash << 5) - hash) + char;
1014                    hash |= 0;
1015                }
1016                return hash.toString(16).substring(1) + '-' + type;
1017            }
1018        })();
1019
1020        var _on = (function () {
1021            var prevFn = null;
1022
1023            return function (el, event, fn, context) { // , args
1024                var curFn = fn.bind(context);
1025                // var curFn = fn.bind.apply(fn, [context].concat(args)); // OR [].slice.call(arguments[4]))
1026                for (var i = 0; i < el.length; ++i) {
1027                    prevFn && el[i].removeEventListener(event, prevFn, false);
1028                    el[i].addEventListener(event, curFn, false);
1029                }
1030                prevFn = curFn;
1031            }
1032        })();
1033
1034        function _extend() {
1035            var args = arguments;
1036            for (var i = 1; i < args.length; i++)
1037                for (var key in args[i])
1038                    if (args[i].hasOwnProperty(key))
1039                        args[0][key] = args[i][key];
1040            return args[0];
1041        }
1042
1043        function _nodesArray(els) {
1044            return (typeof els.length === 'undefined') ? [].concat(els) : [].slice.call(els);
1045        }
1046
1047        function _hasClass(el, cls) {
1048            return el.classList ? el.classList.contains(cls) : new RegExp('(^| )' + cls + '( |$)', 'gi').test(el.cls);
1049        }
1050
1051        function _matches(el, selectors) {
1052            return selectors.filter(function (selector) {
1053                    return [].indexOf.call(document.querySelectorAll(selector), el) !== -1;
1054                }).length > 0;
1055        }
1056
1057        function _numeric(val) {
1058            return !isNaN(val);
1059        }
1060
1061        function _defined(val) {
1062            return typeof val !== 'undefined';
1063        }
1064
1065        function _toArray(val) {
1066            return val instanceof Array ? [].concat.apply([], val) : val;
1067        }
1068
1069        function _isValidFormat(key) {
1070            return ~_FORMAT_LIST.indexOf(key);
1071        }
1072
1073        function _hasDependencies(key) {
1074            var hasDependencies;
1075
1076            switch (key) {
1077                case _FORMAT.TXT:
1078                case _FORMAT.CSV:
1079                case _FORMAT.XLS:
1080                    hasDependencies = true;
1081                    break;
1082                default:
1083                    hasDependencies = _isEnhanced(key);
1084            }
1085            return hasDependencies
1086        }
1087
1088        function _handleError(msg) {
1089            console.error(msg);
1090            return new Error(msg)
1091        }
1092
1093        function _getBootstrapSettings(bootstrap, bootstrapConfig, defaultButton) {
1094            var config = {};
1095            if (bootstrap) {
1096                config.bootstrapClass = bootstrapConfig[0] + ' ';
1097                config.bootstrapTheme = bootstrapConfig[1] + ' ';
1098                config.bootstrapSpacing = bootstrapConfig[2] + ' ';
1099            } else {
1100                config.bootstrapClass = defaultButton + ' ';
1101                config.bootstrapTheme = '';
1102                config.bootstrapSpacing = '';
1103            }
1104            return config;
1105        }
1106
1107        if ($) {
1108            /**
1109             * jQuery TableExport wrapper
1110             * @param options {Object} TableExport configuration options
1111             * @returns {TableExport} TableExport instance
1112             */
1113            $.fn.tableExport = function (options) {
1114                return TableExport.call(_extend({}, TableExport.prototype, $.fn.tableExport), this, options);
1115            };
1116
1117            // alias the TableExport prototype
1118            for (var prop in TableExport.prototype) {
1119                $.fn.tableExport[prop] = TableExport.prototype[prop];
1120            }
1121        }
1122
1123        TableExport.TableExport = TableExport;
1124
1125        return TableExport;
1126    }
1127));

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.