otsdaq_utilities  v2_05_02_indev
download.js
1 var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
2 
3 /* Tabulator v4.5.3 (c) Oliver Folkerd */
4 
5 var Download = function Download(table) {
6  this.table = table; //hold Tabulator object
7  this.fields = {}; //hold filed multi dimension arrays
8  this.columnsByIndex = []; //hold columns in their order in the table
9  this.columnsByField = {}; //hold columns with lookup by field name
10  this.config = {};
11  this.active = false;
12 };
13 
14 //trigger file download
15 Download.prototype.download = function (type, filename, options, active, interceptCallback) {
16  var self = this,
17  downloadFunc = false;
18  this.processConfig();
19  this.active = active;
20 
21  function buildLink(data, mime) {
22  if (interceptCallback) {
23  if (interceptCallback === true) {
24  self.triggerDownload(data, mime, type, filename, true);
25  } else {
26  interceptCallback(data);
27  }
28  } else {
29  self.triggerDownload(data, mime, type, filename);
30  }
31  }
32 
33  if (typeof type == "function") {
34  downloadFunc = type;
35  } else {
36  if (self.downloaders[type]) {
37  downloadFunc = self.downloaders[type];
38  } else {
39  console.warn("Download Error - No such download type found: ", type);
40  }
41  }
42 
43  this.processColumns();
44 
45  if (downloadFunc) {
46  downloadFunc.call(this, self.processDefinitions(), self.processData(active || "active"), options || {}, buildLink, this.config);
47  }
48 };
49 
50 Download.prototype.processConfig = function () {
51  var config = { //download config
52  columnGroups: true,
53  rowGroups: true,
54  columnCalcs: true
55  };
56 
57  if (this.table.options.downloadConfig) {
58  for (var key in this.table.options.downloadConfig) {
59  config[key] = this.table.options.downloadConfig[key];
60  }
61  }
62 
63  if (config.rowGroups && this.table.options.groupBy && this.table.modExists("groupRows")) {
64  this.config.rowGroups = true;
65  }
66 
67  if (config.columnGroups && this.table.columnManager.columns.length != this.table.columnManager.columnsByIndex.length) {
68  this.config.columnGroups = true;
69  }
70 
71  if (config.columnCalcs && this.table.modExists("columnCalcs")) {
72  this.config.columnCalcs = true;
73  }
74 };
75 
76 Download.prototype.processColumns = function () {
77  var self = this;
78 
79  self.columnsByIndex = [];
80  self.columnsByField = {};
81 
82  self.table.columnManager.columnsByIndex.forEach(function (column) {
83 
84  if (column.field && column.definition.download !== false && (column.visible || !column.visible && column.definition.download)) {
85  self.columnsByIndex.push(column);
86  self.columnsByField[column.field] = column;
87  }
88  });
89 };
90 
91 Download.prototype.processDefinitions = function () {
92  var self = this,
93  processedDefinitions = [];
94 
95  if (this.config.columnGroups) {
96  self.table.columnManager.columns.forEach(function (column) {
97  var colData = self.processColumnGroup(column);
98 
99  if (colData) {
100  processedDefinitions.push(colData);
101  }
102  });
103  } else {
104  self.columnsByIndex.forEach(function (column) {
105  if (column.download !== false) {
106  //isolate definiton from defintion object
107  processedDefinitions.push(self.processDefinition(column));
108  }
109  });
110  }
111 
112  return processedDefinitions;
113 };
114 
115 Download.prototype.processColumnGroup = function (column) {
116  var _this = this;
117 
118  var subGroups = column.columns,
119  maxDepth = 0;
120  var processedColumn = this.processDefinition(column);
121  var groupData = {
122  type: "group",
123  title: processedColumn.title,
124  depth: 1
125  };
126 
127  if (subGroups.length) {
128  groupData.subGroups = [];
129  groupData.width = 0;
130 
131  subGroups.forEach(function (subGroup) {
132  var subGroupData = _this.processColumnGroup(subGroup);
133 
134  if (subGroupData.depth > maxDepth) {
135  maxDepth = subGroupData.depth;
136  }
137 
138  if (subGroupData) {
139  groupData.width += subGroupData.width;
140  groupData.subGroups.push(subGroupData);
141  }
142  });
143 
144  groupData.depth += maxDepth;
145 
146  if (!groupData.width) {
147  return false;
148  }
149  } else {
150  if (column.field && column.definition.download !== false && (column.visible || !column.visible && column.definition.download)) {
151  groupData.width = 1;
152  groupData.definition = processedColumn;
153  } else {
154  return false;
155  }
156  }
157 
158  return groupData;
159 };
160 
161 Download.prototype.processDefinition = function (column) {
162  var def = {};
163 
164  for (var key in column.definition) {
165  def[key] = column.definition[key];
166  }
167 
168  if (typeof column.definition.downloadTitle != "undefined") {
169  def.title = column.definition.downloadTitle;
170  }
171 
172  return def;
173 };
174 
175 Download.prototype.processData = function (active) {
176  var _this2 = this;
177 
178  var self = this,
179  data = [],
180  groups = [],
181  rows = false,
182  calcs = {};
183 
184  if (this.config.rowGroups) {
185 
186  if (active == "visible") {
187 
188  rows = self.table.rowManager.getRows(active);
189 
190  rows.forEach(function (row) {
191  if (row.type == "row") {
192  var group = row.getGroup();
193 
194  if (groups.indexOf(group) === -1) {
195  groups.push(group);
196  }
197  }
198  });
199  } else {
200  groups = this.table.modules.groupRows.getGroups();
201  }
202 
203  groups.forEach(function (group) {
204  data.push(_this2.processGroupData(group, rows));
205  });
206  } else {
207  data = self.table.rowManager.getData(active, "download");
208  }
209 
210  if (this.config.columnCalcs) {
211  calcs = this.table.getCalcResults();
212 
213  data = {
214  calcs: calcs,
215  data: data
216  };
217  }
218 
219  //bulk data processing
220  if (typeof self.table.options.downloadDataFormatter == "function") {
221  data = self.table.options.downloadDataFormatter(data);
222  }
223 
224  return data;
225 };
226 
227 Download.prototype.processGroupData = function (group, visRows) {
228  var _this3 = this;
229 
230  var subGroups = group.getSubGroups();
231 
232  var groupData = {
233  type: "group",
234  key: group.key
235  };
236 
237  if (subGroups.length) {
238  groupData.subGroups = [];
239 
240  subGroups.forEach(function (subGroup) {
241  groupData.subGroups.push(_this3.processGroupData(subGroup, visRows));
242  });
243  } else {
244  if (visRows) {
245  groupData.rows = [];
246 
247  group.rows.forEach(function (row) {
248  if (visRows.indexOf(row) > -1) {
249  groupData.rows.push(row.getData("download"));
250  }
251  });
252  } else {
253  groupData.rows = group.getData(true, "download");
254  }
255  }
256 
257  return groupData;
258 };
259 
260 Download.prototype.triggerDownload = function (data, mime, type, filename, newTab) {
261  var element = document.createElement('a'),
262  blob = new Blob([data], { type: mime }),
263  filename = filename || "Tabulator." + (typeof type === "function" ? "txt" : type);
264 
265  blob = this.table.options.downloadReady.call(this.table, data, blob);
266 
267  if (blob) {
268 
269  if (newTab) {
270  window.open(window.URL.createObjectURL(blob));
271  } else {
272  if (navigator.msSaveOrOpenBlob) {
273  navigator.msSaveOrOpenBlob(blob, filename);
274  } else {
275  element.setAttribute('href', window.URL.createObjectURL(blob));
276 
277  //set file title
278  element.setAttribute('download', filename);
279 
280  //trigger download
281  element.style.display = 'none';
282  document.body.appendChild(element);
283  element.click();
284 
285  //remove temporary link element
286  document.body.removeChild(element);
287  }
288  }
289 
290  if (this.table.options.downloadComplete) {
291  this.table.options.downloadComplete();
292  }
293  }
294 };
295 
296 //nested field lookup
297 Download.prototype.getFieldValue = function (field, data) {
298  var column = this.columnsByField[field];
299 
300  if (column) {
301  return column.getFieldValue(data);
302  }
303 
304  return false;
305 };
306 
307 Download.prototype.commsReceived = function (table, action, data) {
308  switch (action) {
309  case "intercept":
310  this.download(data.type, "", data.options, data.active, data.intercept);
311  break;
312  }
313 };
314 
315 //downloaders
316 Download.prototype.downloaders = {
317  csv: function csv(columns, data, options, setFileContents, config) {
318  var self = this,
319  titles = [],
320  fields = [],
321  delimiter = options && options.delimiter ? options.delimiter : ",",
322  fileContents,
323  output;
324 
325  //build column headers
326  function parseSimpleTitles() {
327  columns.forEach(function (column) {
328  titles.push('"' + String(column.title).split('"').join('""') + '"');
329  fields.push(column.field);
330  });
331  }
332 
333  function parseColumnGroup(column, level) {
334  if (column.subGroups) {
335  column.subGroups.forEach(function (subGroup) {
336  parseColumnGroup(subGroup, level + 1);
337  });
338  } else {
339  titles.push('"' + String(column.title).split('"').join('""') + '"');
340  fields.push(column.definition.field);
341  }
342  }
343 
344  if (config.columnGroups) {
345  console.warn("Download Warning - CSV downloader cannot process column groups");
346 
347  columns.forEach(function (column) {
348  parseColumnGroup(column, 0);
349  });
350  } else {
351  parseSimpleTitles();
352  }
353 
354  //generate header row
355  fileContents = [titles.join(delimiter)];
356 
357  function parseRows(data) {
358  //generate each row of the table
359  data.forEach(function (row) {
360  var rowData = [];
361 
362  fields.forEach(function (field) {
363  var value = self.getFieldValue(field, row);
364 
365  switch (typeof value === "undefined" ? "undefined" : _typeof(value)) {
366  case "object":
367  value = JSON.stringify(value);
368  break;
369 
370  case "undefined":
371  case "null":
372  value = "";
373  break;
374 
375  default:
376  value = value;
377  }
378 
379  //escape quotation marks
380  rowData.push('"' + String(value).split('"').join('""') + '"');
381  });
382 
383  fileContents.push(rowData.join(delimiter));
384  });
385  }
386 
387  function parseGroup(group) {
388  if (group.subGroups) {
389  group.subGroups.forEach(function (subGroup) {
390  parseGroup(subGroup);
391  });
392  } else {
393  parseRows(group.rows);
394  }
395  }
396 
397  if (config.columnCalcs) {
398  console.warn("Download Warning - CSV downloader cannot process column calculations");
399  data = data.data;
400  }
401 
402  if (config.rowGroups) {
403  console.warn("Download Warning - CSV downloader cannot process row groups");
404 
405  data.forEach(function (group) {
406  parseGroup(group);
407  });
408  } else {
409  parseRows(data);
410  }
411 
412  output = fileContents.join("\n");
413 
414  if (options.bom) {
415  output = "\uFEFF" + output;
416  }
417 
418  setFileContents(output, "text/csv");
419  },
420 
421  json: function json(columns, data, options, setFileContents, config) {
422  var fileContents;
423 
424  if (config.columnCalcs) {
425  console.warn("Download Warning - CSV downloader cannot process column calculations");
426  data = data.data;
427  }
428 
429  fileContents = JSON.stringify(data, null, '\t');
430 
431  setFileContents(fileContents, "application/json");
432  },
433 
434  pdf: function pdf(columns, data, options, setFileContents, config) {
435  var self = this,
436  fields = [],
437  header = [],
438  body = [],
439  calcs = {},
440  headerDepth = 1,
441  table = "",
442  autoTableParams = {},
443  rowGroupStyles = options.rowGroupStyles || {
444  fontStyle: "bold",
445  fontSize: 12,
446  cellPadding: 6,
447  fillColor: 220
448  },
449  rowCalcStyles = options.rowCalcStyles || {
450  fontStyle: "bold",
451  fontSize: 10,
452  cellPadding: 4,
453  fillColor: 232
454  },
455  jsPDFParams = options.jsPDF || {},
456  title = options && options.title ? options.title : "";
457 
458  if (config.columnCalcs) {
459  calcs = data.calcs;
460  data = data.data;
461  }
462 
463  if (!jsPDFParams.orientation) {
464  jsPDFParams.orientation = options.orientation || "landscape";
465  }
466 
467  if (!jsPDFParams.unit) {
468  jsPDFParams.unit = "pt";
469  }
470 
471  //build column headers
472  function parseSimpleTitles() {
473  columns.forEach(function (column) {
474  if (column.field) {
475  header.push(column.title || "");
476  fields.push(column.field);
477  }
478  });
479 
480  header = [header];
481  }
482 
483  function parseColumnGroup(column, level) {
484  var colSpan = column.width,
485  rowSpan = 1,
486  col = {
487  content: column.title || ""
488  };
489 
490  if (column.subGroups) {
491  column.subGroups.forEach(function (subGroup) {
492  parseColumnGroup(subGroup, level + 1);
493  });
494  rowSpan = 1;
495  } else {
496  fields.push(column.definition.field);
497  rowSpan = headerDepth - level;
498  }
499 
500  col.rowSpan = rowSpan;
501  // col.colSpan = colSpan;
502 
503  header[level].push(col);
504 
505  colSpan--;
506 
507  if (rowSpan > 1) {
508  for (var i = level + 1; i < headerDepth; i++) {
509  header[i].push("");
510  }
511  }
512 
513  for (var i = 0; i < colSpan; i++) {
514  header[level].push("");
515  }
516  }
517 
518  if (config.columnGroups) {
519  columns.forEach(function (column) {
520  if (column.depth > headerDepth) {
521  headerDepth = column.depth;
522  }
523  });
524 
525  for (var i = 0; i < headerDepth; i++) {
526  header.push([]);
527  }
528 
529  columns.forEach(function (column) {
530  parseColumnGroup(column, 0);
531  });
532  } else {
533  parseSimpleTitles();
534  }
535 
536  function parseValue(value) {
537  switch (typeof value === "undefined" ? "undefined" : _typeof(value)) {
538  case "object":
539  value = JSON.stringify(value);
540  break;
541 
542  case "undefined":
543  case "null":
544  value = "";
545  break;
546 
547  default:
548  value = value;
549  }
550 
551  return value;
552  }
553 
554  function parseRows(data) {
555  //build table rows
556  data.forEach(function (row) {
557  body.push(parseRow(row));
558  });
559  }
560 
561  function parseRow(row, styles) {
562  var rowData = [];
563 
564  fields.forEach(function (field) {
565  var value = self.getFieldValue(field, row);
566  value = parseValue(value);
567 
568  if (styles) {
569  rowData.push({
570  content: value,
571  styles: styles
572  });
573  } else {
574  rowData.push(value);
575  }
576  });
577 
578  return rowData;
579  }
580 
581  function parseGroup(group, calcObj) {
582  var groupData = [];
583 
584  groupData.push({ content: parseValue(group.key), colSpan: fields.length, styles: rowGroupStyles });
585 
586  body.push(groupData);
587 
588  if (group.subGroups) {
589  group.subGroups.forEach(function (subGroup) {
590  parseGroup(subGroup, calcObj[group.key] ? calcObj[group.key].groups || {} : {});
591  });
592  } else {
593 
594  if (config.columnCalcs) {
595  addCalcRow(calcObj, group.key, "top");
596  }
597 
598  parseRows(group.rows);
599 
600  if (config.columnCalcs) {
601  addCalcRow(calcObj, group.key, "bottom");
602  }
603  }
604  }
605 
606  function addCalcRow(calcs, selector, pos) {
607  var calcData = calcs[selector];
608 
609  if (calcData) {
610  if (pos) {
611  calcData = calcData[pos];
612  }
613 
614  if (Object.keys(calcData).length) {
615  body.push(parseRow(calcData, rowCalcStyles));
616  }
617  }
618  }
619 
620  if (config.rowGroups) {
621  data.forEach(function (group) {
622  parseGroup(group, calcs);
623  });
624  } else {
625  if (config.columnCalcs) {
626  addCalcRow(calcs, "top");
627  }
628 
629  parseRows(data);
630 
631  if (config.columnCalcs) {
632  addCalcRow(calcs, "bottom");
633  }
634  }
635 
636  var doc = new jsPDF(jsPDFParams); //set document to landscape, better for most tables
637 
638  if (options && options.autoTable) {
639  if (typeof options.autoTable === "function") {
640  autoTableParams = options.autoTable(doc) || {};
641  } else {
642  autoTableParams = options.autoTable;
643  }
644  }
645 
646  if (title) {
647  autoTableParams.addPageContent = function (data) {
648  doc.text(title, 40, 30);
649  };
650  }
651 
652  autoTableParams.head = header;
653  autoTableParams.body = body;
654 
655  doc.autoTable(autoTableParams);
656 
657  if (options && options.documentProcessing) {
658  options.documentProcessing(doc);
659  }
660 
661  setFileContents(doc.output("arraybuffer"), "application/pdf");
662  },
663 
664  xlsx: function xlsx(columns, data, options, setFileContents, config) {
665  var self = this,
666  sheetName = options.sheetName || "Sheet1",
667  workbook = XLSX.utils.book_new(),
668  calcs = {},
669  groupRowIndexs = [],
670  groupColumnIndexs = [],
671  calcRowIndexs = [],
672  output;
673 
674  workbook.SheetNames = [];
675  workbook.Sheets = {};
676 
677  if (config.columnCalcs) {
678  calcs = data.calcs;
679  data = data.data;
680  }
681 
682  function generateSheet() {
683  var titles = [],
684  fields = [],
685  rows = [],
686  worksheet;
687 
688  //convert rows to worksheet
689  function rowsToSheet() {
690  var sheet = {};
691  var range = { s: { c: 0, r: 0 }, e: { c: fields.length, r: rows.length } };
692 
693  XLSX.utils.sheet_add_aoa(sheet, rows);
694 
695  sheet['!ref'] = XLSX.utils.encode_range(range);
696 
697  var merges = generateMerges();
698 
699  if (merges.length) {
700  sheet["!merges"] = merges;
701  }
702 
703  return sheet;
704  }
705 
706  function parseSimpleTitles() {
707  //get field lists
708  columns.forEach(function (column) {
709  titles.push(column.title);
710  fields.push(column.field);
711  });
712 
713  rows.push(titles);
714  }
715 
716  function parseColumnGroup(column, level) {
717 
718  if (typeof titles[level] === "undefined") {
719  titles[level] = [];
720  }
721 
722  if (typeof groupColumnIndexs[level] === "undefined") {
723  groupColumnIndexs[level] = [];
724  }
725 
726  if (column.width > 1) {
727 
728  groupColumnIndexs[level].push({
729  type: "hoz",
730  start: titles[level].length,
731  end: titles[level].length + column.width - 1
732  });
733  }
734 
735  titles[level].push(column.title);
736 
737  if (column.subGroups) {
738  column.subGroups.forEach(function (subGroup) {
739  parseColumnGroup(subGroup, level + 1);
740  });
741  } else {
742  fields.push(column.definition.field);
743  padColumnTitles(fields.length - 1, level);
744 
745  groupColumnIndexs[level].push({
746  type: "vert",
747  start: fields.length - 1
748  });
749  }
750  }
751 
752  function padColumnTitles() {
753  var max = 0;
754 
755  titles.forEach(function (title) {
756  var len = title.length;
757  if (len > max) {
758  max = len;
759  }
760  });
761 
762  titles.forEach(function (title) {
763  var len = title.length;
764  if (len < max) {
765  for (var i = len; i < max; i++) {
766  title.push("");
767  }
768  }
769  });
770  }
771 
772  if (config.columnGroups) {
773  columns.forEach(function (column) {
774  parseColumnGroup(column, 0);
775  });
776 
777  titles.forEach(function (title) {
778  rows.push(title);
779  });
780  } else {
781  parseSimpleTitles();
782  }
783 
784  function generateMerges() {
785  var output = [];
786 
787  groupRowIndexs.forEach(function (index) {
788  output.push({ s: { r: index, c: 0 }, e: { r: index, c: fields.length - 1 } });
789  });
790 
791  groupColumnIndexs.forEach(function (merges, level) {
792  merges.forEach(function (merge) {
793  if (merge.type === "hoz") {
794  output.push({ s: { r: level, c: merge.start }, e: { r: level, c: merge.end } });
795  } else {
796  if (level != titles.length - 1) {
797  output.push({ s: { r: level, c: merge.start }, e: { r: titles.length - 1, c: merge.start } });
798  }
799  }
800  });
801  });
802 
803  return output;
804  }
805 
806  //generate each row of the table
807  function parseRows(data) {
808  data.forEach(function (row) {
809  rows.push(parseRow(row));
810  });
811  }
812 
813  function parseRow(row) {
814  var rowData = [];
815 
816  fields.forEach(function (field) {
817  var value = self.getFieldValue(field, row);
818  rowData.push(!(value instanceof Date) && (typeof value === "undefined" ? "undefined" : _typeof(value)) === "object" ? JSON.stringify(value) : value);
819  });
820 
821  return rowData;
822  }
823 
824  function addCalcRow(calcs, selector, pos) {
825  var calcData = calcs[selector];
826 
827  if (calcData) {
828  if (pos) {
829  calcData = calcData[pos];
830  }
831 
832  if (Object.keys(calcData).length) {
833  calcRowIndexs.push(rows.length);
834  rows.push(parseRow(calcData));
835  }
836  }
837  }
838 
839  function parseGroup(group, calcObj) {
840  var groupData = [];
841 
842  groupData.push(group.key);
843 
844  groupRowIndexs.push(rows.length);
845 
846  rows.push(groupData);
847 
848  if (group.subGroups) {
849  group.subGroups.forEach(function (subGroup) {
850  parseGroup(subGroup, calcObj[group.key] ? calcObj[group.key].groups || {} : {});
851  });
852  } else {
853 
854  if (config.columnCalcs) {
855  addCalcRow(calcObj, group.key, "top");
856  }
857 
858  parseRows(group.rows);
859 
860  if (config.columnCalcs) {
861  addCalcRow(calcObj, group.key, "bottom");
862  }
863  }
864  }
865 
866  if (config.rowGroups) {
867  data.forEach(function (group) {
868  parseGroup(group, calcs);
869  });
870  } else {
871  if (config.columnCalcs) {
872  addCalcRow(calcs, "top");
873  }
874 
875  parseRows(data);
876 
877  if (config.columnCalcs) {
878  addCalcRow(calcs, "bottom");
879  }
880  }
881 
882  worksheet = rowsToSheet();
883 
884  return worksheet;
885  }
886 
887  if (options.sheetOnly) {
888  setFileContents(generateSheet());
889  return;
890  }
891 
892  if (options.sheets) {
893  for (var sheet in options.sheets) {
894 
895  if (options.sheets[sheet] === true) {
896  workbook.SheetNames.push(sheet);
897  workbook.Sheets[sheet] = generateSheet();
898  } else {
899 
900  workbook.SheetNames.push(sheet);
901 
902  this.table.modules.comms.send(options.sheets[sheet], "download", "intercept", {
903  type: "xlsx",
904  options: { sheetOnly: true },
905  active: self.active,
906  intercept: function intercept(data) {
907  workbook.Sheets[sheet] = data;
908  }
909  });
910  }
911  }
912  } else {
913  workbook.SheetNames.push(sheetName);
914  workbook.Sheets[sheetName] = generateSheet();
915  }
916 
917  if (options.documentProcessing) {
918  workbook = options.documentProcessing(workbook);
919  }
920 
921  //convert workbook to binary array
922  function s2ab(s) {
923  var buf = new ArrayBuffer(s.length);
924  var view = new Uint8Array(buf);
925  for (var i = 0; i != s.length; ++i) {
926  view[i] = s.charCodeAt(i) & 0xFF;
927  }return buf;
928  }
929 
930  output = XLSX.write(workbook, { bookType: 'xlsx', bookSST: true, type: 'binary' });
931 
932  setFileContents(s2ab(output), "application/octet-stream");
933  },
934 
935  html: function html(columns, data, options, setFileContents, config) {
936  if (this.table.modExists("htmlTableExport", true)) {
937  setFileContents(this.table.modules.htmlTableExport.getHtml(true, options.style, config), "text/html");
938  }
939  }
940 
941 };
942 
943 Tabulator.prototype.registerModule("download", Download);