From 5f037cb297f6d5763263fa4e9bb682fef9527fc5 Mon Sep 17 00:00:00 2001 From: Daniel Wilson Date: Tue, 20 Dec 2016 12:08:18 -0800 Subject: [PATCH 1/5] For excel exports, if cell has a type class (e.g. 'te-number'), set the cell type in the export --- dist/js/tableexport.js | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/dist/js/tableexport.js b/dist/js/tableexport.js index 87f1eac..7412338 100644 --- a/dist/js/tableexport.js +++ b/dist/js/tableexport.js @@ -98,9 +98,9 @@ break; } } - return new Array(total).concat($(val).text()); + return new Array(total).push({'val': $(val).text(), 'type': getTypeFromClass($(val))}); } - return $(val).text(); + return {'val': $(val).text(), 'type': getTypeFromClass($(val))}; }).get()]; }).get(), dataObject = TableExport.prototype.escapeHtml( @@ -149,9 +149,9 @@ break; } } - return new Array(total).concat($(val).text()); + return new Array(total).push({'val': $(val).text(), 'type': getTypeFromClass($(val))}); } - return $(val).text(); + return {'val': $(val).text(), 'type': getTypeFromClass($(val))}; }).get()]; }).get(), dataObject = TableExport.prototype.escapeHtml( @@ -179,7 +179,7 @@ if ($(val).is(emptyCSS)) { return " " } - return $(val).text(); + return {'val': $(val).text(), 'type': getTypeFromClass($(val))}; }).get().join(colD); }).get().join(rdel), dataObject = TableExport.prototype.escapeHtml( @@ -259,6 +259,18 @@ } ); + function getTypeFromClass(cell) { + if (cell.hasClass('te-string')) { + return 's'; + } else if (cell.hasClass('te-number')) { + return 'n'; + } else if (cell.hasClass('te-boolean')) { + return 'b'; + } else { + return ''; + } + } + function checkCaption(exportButton) { var $caption = $el.find('caption:not(.head)'); $caption.length ? $caption.append(exportButton) : $el.prepend('' + exportButton + ''); @@ -418,18 +430,20 @@ if (range.s.c > C) range.s.c = C; if (range.e.r < R) range.e.r = R; if (range.e.c < C) range.e.c = C; - var cell = {v: data[R][C]}; + var cell = {v: data[R][C]['val'], t: data[R][C]['type']}; if (cell.v == null) continue; var cell_ref = XLSX.utils.encode_cell({c: C, r: R}); - if (typeof cell.v === 'number') cell.t = 'n'; - else if (typeof cell.v === 'boolean') cell.t = 'b'; - else if (cell.v instanceof Date) { - cell.t = 'n'; - cell.z = XLSX.SSF._table[14]; - cell.v = this.dateNum(cell.v); + if (!cell.t) { + if (typeof cell.v === 'number') cell.t = 'n'; + else if (typeof cell.v === 'boolean') cell.t = 'b'; + else if (cell.v instanceof Date) { + cell.t = 'n'; + cell.z = XLSX.SSF._table[14]; + cell.v = this.dateNum(cell.v); + } + else cell.t = 's'; } - else cell.t = 's'; ws[cell_ref] = cell; } From e7ab33dfdb9048f19c54df508b22d5b741a46e2c Mon Sep 17 00:00:00 2001 From: Daniel Wilson Date: Mon, 2 Jan 2017 18:12:21 -0800 Subject: [PATCH 2/5] Allow export data to be attached to a custom button, rather than create a button for that type; similar to formats, add a tableExport 'targets' setting (e.g. "targets: {'xlsx': '#exportButton',}"), whose values are jQuery selectors of buttons to which we attach the data and event to trigger file download --- dist/js/tableexport.js | 54 +++++++++++++++++++++++++++++++++--------- 1 file changed, 43 insertions(+), 11 deletions(-) diff --git a/dist/js/tableexport.js b/dist/js/tableexport.js index 87f1eac..87bbde7 100644 --- a/dist/js/tableexport.js +++ b/dist/js/tableexport.js @@ -63,7 +63,7 @@ thAdj = self.settings.headings ? $el.find('thead>tr').length : 0, fileName = self.settings.fileName === "id" ? ($el.attr('id') ? $el.attr('id') : TableExport.prototype.defaultFileName) : self.settings.fileName, exporters = { - xlsx: function (rDel, name) { + xlsx: function (rDel, name, target) { var rcMap = {}, dataURL = $rows.map(function (ir, val) { if (!!~ignoreRows.indexOf(ir - thAdj) || $(val).is(ignoreCSS)) { @@ -112,9 +112,14 @@ })), myContent = TableExport.prototype.xlsx.buttonContent, myClass = TableExport.prototype.xlsx.defaultClass; - createObjButton(dataObject, myContent, myClass); + if (target) { + attachExportToButton(dataObject, target); + } + else { + createObjButton(dataObject, myContent, myClass); + } }, - xlsm: function (rDel, name) { + xlsm: function (rDel, name, target) { var rcMap = {}, dataURL = $rows.map(function (ir, val) { if (!!~ignoreRows.indexOf(ir - thAdj) || $(val).is(ignoreCSS)) { @@ -163,9 +168,14 @@ })), myContent = TableExport.prototype.xls.buttonContent, myClass = TableExport.prototype.xls.defaultClass; - createObjButton(dataObject, myContent, myClass); + if (target) { + attachExportToButton(dataObject, target); + } + else { + createObjButton(dataObject, myContent, myClass); + } }, - xls: function (rdel, name) { + xls: function (rdel, name, target) { var colD = TableExport.prototype.xls.separator, dataURL = $rows.map(function (i, val) { if (!!~ignoreRows.indexOf(i - thAdj) || $(val).is(ignoreCSS)) { @@ -191,9 +201,14 @@ })), myContent = TableExport.prototype.xls.buttonContent, myClass = TableExport.prototype.xls.defaultClass; - createObjButton(dataObject, myContent, myClass); + if (target) { + attachExportToButton(dataObject, target); + } + else { + createObjButton(dataObject, myContent, myClass); + } }, - csv: function (rdel, name) { + csv: function (rdel, name, target) { var colD = TableExport.prototype.csv.separator, dataURL = $rows.map(function (i, val) { if (!!~ignoreRows.indexOf(i - thAdj) || $(val).is(ignoreCSS)) { @@ -219,9 +234,14 @@ })), myContent = TableExport.prototype.csv.buttonContent, myClass = TableExport.prototype.csv.defaultClass; - createObjButton(dataObject, myContent, myClass); + if (target) { + attachExportToButton(dataObject, target); + } + else { + createObjButton(dataObject, myContent, myClass); + } }, - txt: function (rdel, name) { + txt: function (rdel, name, target) { var colD = TableExport.prototype.txt.separator, dataURL = $rows.map(function (i, val) { if (!!~ignoreRows.indexOf(i - thAdj) || $(val).is(ignoreCSS)) { @@ -247,7 +267,12 @@ })), myContent = TableExport.prototype.txt.buttonContent, myClass = TableExport.prototype.txt.defaultClass; - createObjButton(dataObject, myContent, myClass); + if (target) { + attachExportToButton(dataObject, target); + } + else { + createObjButton(dataObject, myContent, myClass); + } } }; @@ -255,7 +280,9 @@ function (key) { XLSX && key === 'xls' ? key = 'xlsm' : false; !XLSX && key === 'xlsx' ? key = null : false; - key && exporters[key](rowD, fileName); + var target; + key in self.settings['targets'] ? target = self.settings['targets'][key] : null; + key && exporters[key](rowD, fileName, target); } ); @@ -268,6 +295,11 @@ var exportButton = ""; checkCaption(exportButton); } + + function attachExportToButton(dataObject, target) { + var exportButton = $(target); + exportButton.attr('data-fileblob', dataObject) + } }); $("button[data-fileblob]") From bb21811607a99e6e27198611bf425b93d6187c9b Mon Sep 17 00:00:00 2001 From: Daniel Wilson Date: Fri, 6 Jan 2017 18:14:24 -0800 Subject: [PATCH 3/5] Only set targets if they are defined --- dist/js/tableexport.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dist/js/tableexport.js b/dist/js/tableexport.js index bbd9a66..1929d64 100644 --- a/dist/js/tableexport.js +++ b/dist/js/tableexport.js @@ -281,7 +281,9 @@ XLSX && key === 'xls' ? key = 'xlsm' : false; !XLSX && key === 'xlsx' ? key = null : false; var target; - key in self.settings['targets'] ? target = self.settings['targets'][key] : null; + if (self.settings['targets']) { + key in self.settings['targets'] ? target = self.settings['targets'][key] : null; + } key && exporters[key](rowD, fileName, target); } ); From 1121f03fc87461e5bc8ff32c0462c7df26148110 Mon Sep 17 00:00:00 2001 From: Daniel Wilson Date: Fri, 6 Jan 2017 18:14:45 -0800 Subject: [PATCH 4/5] Unescape html when adding to an existing button --- dist/js/tableexport.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/dist/js/tableexport.js b/dist/js/tableexport.js index 1929d64..b413892 100644 --- a/dist/js/tableexport.js +++ b/dist/js/tableexport.js @@ -300,6 +300,11 @@ } } + function unescapeHtml(string) { + var doc = new DOMParser().parseFromString(string, "text/html"); + return doc.documentElement.textContent; + } + function checkCaption(exportButton) { var $caption = $el.find('caption:not(.head)'); $caption.length ? $caption.append(exportButton) : $el.prepend('' + exportButton + ''); @@ -312,7 +317,7 @@ function attachExportToButton(dataObject, target) { var exportButton = $(target); - exportButton.attr('data-fileblob', dataObject) + exportButton.attr('data-fileblob', unescapeHtml(dataObject)); } }); From 5d2d8f452931873b099f9f894e0a70113f6067f8 Mon Sep 17 00:00:00 2001 From: Daniel Wilson Date: Tue, 10 Jan 2017 13:14:59 -0800 Subject: [PATCH 5/5] Parse the file blob attributes rather than calling .data(); this ensures that we get the correct object in the event that the button is updated by new table data between downloads --- dist/js/tableexport.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist/js/tableexport.js b/dist/js/tableexport.js index b413892..3559717 100644 --- a/dist/js/tableexport.js +++ b/dist/js/tableexport.js @@ -324,7 +324,7 @@ $("button[data-fileblob]") .off("click") .on("click", function () { - var object = $(this).data("fileblob"), + var object = JSON.parse($(this).attr('data-fileblob')), data = object.data, fileName = object.fileName, mimeType = object.mimeType,