UNPKG

tabulator-tables

Version:

Interactive table generation JavaScript library

904 lines (707 loc) 19.9 kB
var Download = function(table){ this.table = table; //hold Tabulator object this.fields = {}; //hold filed multi dimension arrays this.columnsByIndex = []; //hold columns in their order in the table this.columnsByField = {}; //hold columns with lookup by field name this.config = {}; }; //trigger file download Download.prototype.download = function(type, filename, options, interceptCallback){ var self = this, downloadFunc = false; this.processConfig(); function buildLink(data, mime){ if(interceptCallback){ if(interceptCallback === true){ self.triggerDownload(data, mime, type, filename, true); }else{ interceptCallback(data); } }else{ self.triggerDownload(data, mime, type, filename); } } if(typeof type == "function"){ downloadFunc = type; }else{ if(self.downloaders[type]){ downloadFunc = self.downloaders[type]; }else{ console.warn("Download Error - No such download type found: ", type); } } this.processColumns(); if(downloadFunc){ downloadFunc.call(this, self.processDefinitions(), self.processData() , options || {}, buildLink, this.config); } }; Download.prototype.processConfig = function(){ var config = { //download config columnGroups:true, rowGroups:true, columnCalcs:true, }; if(this.table.options.downloadConfig){ for(var key in this.table.options.downloadConfig){ config[key] = this.table.options.downloadConfig[key]; } } if (config.rowGroups && this.table.options.groupBy && this.table.modExists("groupRows")){ this.config.rowGroups = true; } if (config.columnGroups && this.table.columnManager.columns.length != this.table.columnManager.columnsByIndex.length){ this.config.columnGroups = true; } if (config.columnCalcs && this.table.modExists("columnCalcs")){ this.config.columnCalcs = true; } }; Download.prototype.processColumns = function () { var self = this; self.columnsByIndex = []; self.columnsByField = {}; self.table.columnManager.columnsByIndex.forEach(function (column) { if (column.field && column.definition.download !== false && (column.visible || (!column.visible && column.definition.download))) { self.columnsByIndex.push(column); self.columnsByField[column.field] = column; } }); }; Download.prototype.processDefinitions = function(){ var self = this, processedDefinitions = []; if(this.config.columnGroups){ self.table.columnManager.columns.forEach(function(column){ var colData = self.processColumnGroup(column); if(colData){ processedDefinitions.push(colData); } }); }else{ self.columnsByIndex.forEach(function(column){ if(column.download !== false){ //isolate definiton from defintion object processedDefinitions.push(self.processDefinition(column)); } }); } return processedDefinitions; }; Download.prototype.processColumnGroup = function(column){ var subGroups = column.columns, maxDepth = 0; var processedColumn = this.processDefinition(column); var groupData = { type:"group", title:processedColumn.title, depth:1, }; if(subGroups.length){ groupData.subGroups = []; groupData.width = 0; subGroups.forEach((subGroup) => { var subGroupData = this.processColumnGroup(subGroup); if(subGroupData.depth > maxDepth){ maxDepth = subGroupData.depth; } if(subGroupData){ groupData.width += subGroupData.width; groupData.subGroups.push(subGroupData); } }); groupData.depth += maxDepth; if(!groupData.width){ return false; } }else{ if(column.field && column.definition.download !== false && (column.visible || (!column.visible && column.definition.download))){ groupData.width = 1; groupData.definition = processedColumn; }else{ return false; } } return groupData; }; Download.prototype.processDefinition = function(column){ var def = {}; for(var key in column.definition){ def[key] = column.definition[key]; } if(typeof column.definition.downloadTitle != "undefined"){ def.title = column.definition.downloadTitle; } return def; }; Download.prototype.processData = function(){ var self = this, data = [], groups = [], calcs = {}; if(this.config.rowGroups){ groups = this.table.modules.groupRows.getGroups(); groups.forEach((group) => { data.push(this.processGroupData(group)); }); }else{ data = self.table.rowManager.getData(true, "download"); } if(this.config.columnCalcs){ calcs = this.table.getCalcResults(); data = { calcs: calcs, data: data, }; } //bulk data processing if(typeof self.table.options.downloadDataFormatter == "function"){ data = self.table.options.downloadDataFormatter(data); } return data; }; Download.prototype.processGroupData = function(group){ var subGroups = group.getSubGroups(); var groupData = { type:"group", key:group.key }; if(subGroups.length){ groupData.subGroups = []; subGroups.forEach((subGroup) => { groupData.subGroups.push(this.processGroupData(subGroup)); }); }else{ groupData.rows = group.getData(true, "download"); } return groupData; }; Download.prototype.triggerDownload = function(data, mime, type, filename, newTab){ var element = document.createElement('a'), blob = new Blob([data],{type:mime}), filename = filename || "Tabulator." + (typeof type === "function" ? "txt" : type); blob = this.table.options.downloadReady.call(this.table, data, blob); if(blob){ if(newTab){ window.open(window.URL.createObjectURL(blob)); }else{ if(navigator.msSaveOrOpenBlob){ navigator.msSaveOrOpenBlob(blob, filename); }else{ element.setAttribute('href', window.URL.createObjectURL(blob)); //set file title element.setAttribute('download', filename); //trigger download element.style.display = 'none'; document.body.appendChild(element); element.click(); //remove temporary link element document.body.removeChild(element); } } if(this.table.options.downloadComplete){ this.table.options.downloadComplete(); } } }; //nested field lookup Download.prototype.getFieldValue = function(field, data){ var column = this.columnsByField[field]; if(column){ return column.getFieldValue(data); } return false; }; Download.prototype.commsReceived = function(table, action, data){ switch(action){ case "intercept": this.download(data.type, "", data.options, data.intercept); break; } }; //downloaders Download.prototype.downloaders = { csv:function(columns, data, options, setFileContents, config){ var self = this, titles = [], fields = [], delimiter = options && options.delimiter ? options.delimiter : ",", fileContents, output; //build column headers function parseSimpleTitles(){ columns.forEach(function(column){ titles.push('"' + String(column.title).split('"').join('""') + '"'); fields.push(column.field); }); } function parseColumnGroup(column, level){ if(column.subGroups){ column.subGroups.forEach(function(subGroup){ parseColumnGroup(subGroup, level+1); }); }else{ titles.push('"' + String(column.title).split('"').join('""') + '"'); fields.push(column.definition.field); } } if(config.columnGroups){ console.warn("Download Warning - CSV downloader cannot process column groups"); columns.forEach(function(column){ parseColumnGroup(column,0); }); }else{ parseSimpleTitles(); } //generate header row fileContents = [titles.join(delimiter)]; function parseRows(data){ //generate each row of the table data.forEach(function(row){ var rowData = []; fields.forEach(function(field){ var value = self.getFieldValue(field, row); switch(typeof value){ case "object": value = JSON.stringify(value); break; case "undefined": case "null": value = ""; break; default: value = value; } //escape quotation marks rowData.push('"' + String(value).split('"').join('""') + '"'); }); fileContents.push(rowData.join(delimiter)); }); } function parseGroup(group){ if(group.subGroups){ group.subGroups.forEach(function(subGroup){ parseGroup(subGroup); }); }else{ parseRows(group.rows); } } if(config.columnCalcs){ console.warn("Download Warning - CSV downloader cannot process column calculations"); data = data.data; } if(config.rowGroups){ console.warn("Download Warning - CSV downloader cannot process row groups"); data.forEach(function(group){ parseGroup(group); }); }else{ parseRows(data); } output = fileContents.join("\n"); if(options.bom){ output = "\ufeff" + output; } setFileContents(output, "text/csv"); }, json:function(columns, data, options, setFileContents, config){ var fileContents; if(config.columnCalcs){ console.warn("Download Warning - CSV downloader cannot process column calculations"); data = data.data; } fileContents = JSON.stringify(data, null, '\t'); setFileContents(fileContents, "application/json"); }, pdf:function(columns, data, options, setFileContents, config){ var self = this, fields = [], header = [], body = [], calcs = {}, headerDepth = 1, table = "", autoTableParams = {}, rowGroupStyles = options.rowGroupStyles || { fontStyle: "bold", fontSize: 12, cellPadding: 6, fillColor: 220, }, rowCalcStyles = options.rowCalcStyles || { fontStyle: "bold", fontSize: 10, cellPadding: 4, fillColor: 232, }, jsPDFParams = options.jsPDF || {}, title = options && options.title ? options.title : ""; if(config.columnCalcs){ calcs = data.calcs; data = data.data; } if(!jsPDFParams.orientation){ jsPDFParams.orientation = options.orientation || "landscape"; } if(!jsPDFParams.unit){ jsPDFParams.unit = "pt"; } //build column headers function parseSimpleTitles(){ columns.forEach(function(column){ if(column.field){ header.push(column.title || ""); fields.push(column.field); } }); header = [header]; } function parseColumnGroup(column, level){ var colSpan = column.width, rowSpan = 1, col = { content:column.title || "", }; if(column.subGroups){ column.subGroups.forEach(function(subGroup){ parseColumnGroup(subGroup, level+1); }); rowSpan = 1; }else{ fields.push(column.definition.field); rowSpan = headerDepth - level; } col.rowSpan = rowSpan; // col.colSpan = colSpan; header[level].push(col); colSpan--; if(rowSpan > 1){ for(var i = level + 1; i < headerDepth; i++){ header[i].push(""); } } for(var i = 0; i < colSpan; i++){ header[level].push(""); } } if(config.columnGroups){ columns.forEach(function(column){ if(column.depth > headerDepth){ headerDepth = column.depth; } }); for(var i=0; i < headerDepth; i++){ header.push([]); } columns.forEach(function(column){ parseColumnGroup(column,0); }); }else{ parseSimpleTitles(); } function parseValue(value){ switch(typeof value){ case "object": value = JSON.stringify(value); break; case "undefined": case "null": value = ""; break; default: value = value; } return value; } function parseRows(data){ //build table rows data.forEach(function(row){ body.push(parseRow(row)); }); } function parseRow(row, styles){ var rowData = []; fields.forEach(function(field){ var value = self.getFieldValue(field, row); value = parseValue(value); if(styles){ rowData.push({ content:value, styles:styles, }); }else{ rowData.push(value); } }); return rowData; } function parseGroup(group, calcObj){ var groupData = []; groupData.push({content:parseValue(group.key), colSpan:fields.length, styles:rowGroupStyles}); body.push(groupData); if(group.subGroups){ group.subGroups.forEach(function(subGroup){ parseGroup(subGroup, calcObj[group.key] ? calcObj[group.key].groups || {} : {}); }); }else{ if(config.columnCalcs){ addCalcRow(calcObj, group.key, "top"); } parseRows(group.rows); if(config.columnCalcs){ addCalcRow(calcObj, group.key, "bottom"); } } } function addCalcRow(calcs, selector, pos){ var calcData = calcs[selector]; if(calcData){ if(pos){ calcData = calcData[pos]; } if(Object.keys(calcData).length){ body.push(parseRow(calcData, rowCalcStyles)); } } } if(config.rowGroups){ data.forEach(function(group){ parseGroup(group, calcs); }); }else{ if(config.columnCalcs){ addCalcRow(calcs, "top"); } parseRows(data); if(config.columnCalcs){ addCalcRow(calcs, "bottom"); } } var doc = new jsPDF(jsPDFParams); //set document to landscape, better for most tables if(options && options.autoTable){ if(typeof options.autoTable === "function"){ autoTableParams = options.autoTable(doc) || {}; }else{ autoTableParams = options.autoTable; } } if(title){ autoTableParams.addPageContent = function(data) { doc.text(title, 40, 30); }; } autoTableParams.head = header; autoTableParams.body = body; doc.autoTable(autoTableParams); if(options && options.documentProcessing){ options.documentProcessing(doc); } setFileContents(doc.output("arraybuffer"), "application/pdf"); }, xlsx:function(columns, data, options, setFileContents, config){ var self = this, sheetName = options.sheetName || "Sheet1", workbook = {SheetNames:[], Sheets:{}}, calcs = {}, groupRowIndexs = [], groupColumnIndexs = [], calcRowIndexs = [], output; if(config.columnCalcs){ calcs = data.calcs; data = data.data; } function generateSheet(){ var titles = [], fields = [], rows = [], worksheet; //convert rows to worksheet function rowsToSheet(){ var sheet = {}; var range = {s: {c:0, r:0}, e: {c:fields.length, r:rows.length }}; XLSX.utils.sheet_add_aoa(sheet, rows); sheet['!ref'] = XLSX.utils.encode_range(range); var merges = generateMerges(); if(merges.length){ sheet["!merges"] = merges; } return sheet; } function parseSimpleTitles(){ //get field lists columns.forEach(function(column){ titles.push(column.title); fields.push(column.field); }); rows.push(titles); } function parseColumnGroup(column, level){ if(typeof titles[level] === "undefined"){ titles[level] = []; } if(typeof groupColumnIndexs[level] === "undefined"){ groupColumnIndexs[level] = []; } if(column.width > 1){ groupColumnIndexs[level].push({ type:"hoz", start:titles[level].length, end:titles[level].length + column.width - 1, }); } titles[level].push(column.title); if(column.subGroups){ column.subGroups.forEach(function(subGroup){ parseColumnGroup(subGroup, level+1); }); }else{ fields.push(column.definition.field); padColumnTitles(fields.length - 1, level); groupColumnIndexs[level].push({ type:"vert", start:fields.length - 1, }); } } function padColumnTitles(){ var max = 0; titles.forEach(function(title){ var len = title.length; if(len > max){ max = len; } }); titles.forEach(function(title){ var len = title.length; if(len < max){ for(var i = len; i < max; i++){ title.push(""); } } }); } if(config.columnGroups){ columns.forEach(function(column){ parseColumnGroup(column,0); }); titles.forEach(function(title){ rows.push(title); }); }else{ parseSimpleTitles(); } function generateMerges(){ var output = []; groupRowIndexs.forEach(function(index){ output.push({s:{r:index,c:0},e:{r:index,c:fields.length - 1}}); }); groupColumnIndexs.forEach(function(merges, level){ merges.forEach(function(merge){ if(merge.type === "hoz"){ output.push({s:{r:level,c:merge.start},e:{r:level,c:merge.end}}); }else{ if(level != titles.length - 1){ output.push({s:{r:level,c:merge.start},e:{r:titles.length - 1,c:merge.start}}); } } }); }); return output; } //generate each row of the table function parseRows(data){ data.forEach(function(row){ rows.push(parseRow(row)); }); } function parseRow(row){ var rowData = []; fields.forEach(function(field){ var value = self.getFieldValue(field, row); rowData.push(!(value instanceof Date) && typeof value === "object" ? JSON.stringify(value) : value); }); return rowData; } function addCalcRow(calcs, selector, pos){ var calcData = calcs[selector]; if(calcData){ if(pos){ calcData = calcData[pos]; } if(Object.keys(calcData).length){ calcRowIndexs.push(rows.length); rows.push(parseRow(calcData)); } } } function parseGroup(group, calcObj){ var groupData = []; groupData.push(group.key); groupRowIndexs.push(rows.length); rows.push(groupData); if(group.subGroups){ group.subGroups.forEach(function(subGroup){ parseGroup(subGroup, calcObj[group.key] ? calcObj[group.key].groups || {} : {}); }); }else{ if(config.columnCalcs){ addCalcRow(calcObj, group.key, "top"); } parseRows(group.rows); if(config.columnCalcs){ addCalcRow(calcObj, group.key, "bottom"); } } } if(config.rowGroups){ data.forEach(function(group){ parseGroup(group, calcs); }); }else{ if(config.columnCalcs){ addCalcRow(calcs, "top"); } parseRows(data); if(config.columnCalcs){ addCalcRow(calcs, "bottom"); } } worksheet = rowsToSheet(); return worksheet; } if(options.sheetOnly){ setFileContents(generateSheet()); return; } if(options.sheets){ for(var sheet in options.sheets){ if(options.sheets[sheet] === true){ workbook.SheetNames.push(sheet); workbook.Sheets[sheet] = generateSheet(); }else{ workbook.SheetNames.push(sheet); this.table.modules.comms.send(options.sheets[sheet], "download", "intercept",{ type:"xlsx", options:{sheetOnly:true}, intercept:function(data){ workbook.Sheets[sheet] = data; } }); } } }else{ workbook.SheetNames.push(sheetName); workbook.Sheets[sheetName] = generateSheet(); } //convert workbook to binary array function s2ab(s) { var buf = new ArrayBuffer(s.length); var view = new Uint8Array(buf); for (var i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF; return buf; } output = XLSX.write(workbook, {bookType:'xlsx', bookSST:true, type: 'binary'}); setFileContents(s2ab(output), "application/octet-stream"); }, }; Tabulator.prototype.registerModule("download", Download);