ckt的看板部分
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2305 lines
88 KiB

4 years ago
  1. /**
  2. * @preserve tableExport.jquery.plugin
  3. *
  4. * Version 1.10.3
  5. *
  6. * Copyright (c) 2015-2019 hhurz, https://github.com/hhurz
  7. *
  8. * Original Work Copyright (c) 2014 Giri Raj
  9. *
  10. * Licensed under the MIT License
  11. **/
  12. 'use strict';
  13. (function ($) {
  14. $.fn.tableExport = function (options) {
  15. var defaults = {
  16. csvEnclosure: '"',
  17. csvSeparator: ',',
  18. csvUseBOM: true,
  19. displayTableName: false,
  20. escape: false,
  21. exportHiddenCells: false, // true = speed up export of large tables with hidden cells (hidden cells will be exported !)
  22. fileName: 'tableExport',
  23. htmlContent: false,
  24. ignoreColumn: [],
  25. ignoreRow: [],
  26. jsonScope: 'all', // head, data, all
  27. jspdf: { // jsPDF / jsPDF-AutoTable related options
  28. orientation: 'p',
  29. unit: 'pt',
  30. format: 'a4', // One of jsPDF page formats or 'bestfit' for autmatic paper format selection
  31. margins: {left: 20, right: 10, top: 10, bottom: 10},
  32. onDocCreated: null,
  33. autotable: {
  34. styles: {
  35. cellPadding: 2,
  36. rowHeight: 12,
  37. fontSize: 8,
  38. fillColor: 255, // Color value or 'inherit' to use css background-color from html table
  39. textColor: 50, // Color value or 'inherit' to use css color from html table
  40. fontStyle: 'normal', // normal, bold, italic, bolditalic or 'inherit' to use css font-weight and fonst-style from html table
  41. overflow: 'ellipsize', // visible, hidden, ellipsize or linebreak
  42. halign: 'inherit', // left, center, right or 'inherit' to use css horizontal cell alignment from html table
  43. valign: 'middle' // top, middle, bottom
  44. },
  45. headerStyles: {
  46. fillColor: [52, 73, 94],
  47. textColor: 255,
  48. fontStyle: 'bold',
  49. halign: 'inherit', // left, center, right or 'inherit' to use css horizontal header cell alignment from html table
  50. valign: 'middle' // top, middle, bottom
  51. },
  52. alternateRowStyles: {
  53. fillColor: 245
  54. },
  55. tableExport: {
  56. doc: null, // jsPDF doc object. If set, an already created doc will be used to export to
  57. onAfterAutotable: null,
  58. onBeforeAutotable: null,
  59. onAutotableText: null,
  60. onTable: null,
  61. outputImages: true
  62. }
  63. }
  64. },
  65. mso: { // MS Excel and MS Word related options
  66. fileFormat: 'xlshtml', // xlshtml = Excel 2000 html format
  67. // xmlss = XML Spreadsheet 2003 file format (XMLSS)
  68. // xlsx = Excel 2007 Office Open XML format
  69. onMsoNumberFormat: null, // Excel 2000 html format only. See readme.md for more information about msonumberformat
  70. pageFormat: 'a4', // Page format used for page orientation
  71. pageOrientation: 'portrait', // portrait, landscape (xlshtml format only)
  72. rtl: false, // true = Set worksheet option 'DisplayRightToLeft'
  73. styles: [], // E.g. ['border-bottom', 'border-top', 'border-left', 'border-right']
  74. worksheetName: ''
  75. },
  76. numbers: {
  77. html: {
  78. decimalMark: '.',
  79. thousandsSeparator: ','
  80. },
  81. output: { // Use 'output: false' to keep number format in exported output
  82. decimalMark: '.',
  83. thousandsSeparator: ','
  84. }
  85. },
  86. onAfterSaveToFile: null,
  87. onBeforeSaveToFile: null, // Return false as result to abort save process
  88. onCellData: null,
  89. onCellHtmlData: null,
  90. onIgnoreRow: null, // onIgnoreRow($tr, rowIndex): function should return true to not export a row
  91. outputMode: 'file', // 'file', 'string', 'base64' or 'window' (experimental)
  92. pdfmake: {
  93. enabled: false, // true: use pdfmake instead of jspdf and jspdf-autotable (experimental)
  94. docDefinition: {
  95. pageOrientation: 'portrait', // 'portrait' or 'landscape'
  96. defaultStyle: {
  97. font: 'Roboto' // Default is 'Roboto', for arabic font set this option to 'Mirza' and include mirza_fonts.js
  98. }
  99. },
  100. fonts: {}
  101. },
  102. preserve: {
  103. leadingWS: false, // preserve leading white spaces
  104. trailingWS: false // preserve trailing white spaces
  105. },
  106. preventInjection: true, // Prepend a single quote to cell strings that start with =,+,- or @ to prevent formula injection
  107. tbodySelector: 'tr',
  108. tfootSelector: 'tr', // Set empty ('') to prevent export of tfoot rows
  109. theadSelector: 'tr',
  110. tableName: 'Table',
  111. type: 'csv' // 'csv', 'tsv', 'txt', 'sql', 'json', 'xml', 'excel', 'doc', 'png' or 'pdf'
  112. };
  113. var pageFormats = { // Size in pt of various paper formats. Adopted from jsPDF.
  114. 'a0': [2383.94, 3370.39], 'a1': [1683.78, 2383.94], 'a2': [1190.55, 1683.78],
  115. 'a3': [841.89, 1190.55], 'a4': [595.28, 841.89], 'a5': [419.53, 595.28],
  116. 'a6': [297.64, 419.53], 'a7': [209.76, 297.64], 'a8': [147.40, 209.76],
  117. 'a9': [104.88, 147.40], 'a10': [73.70, 104.88],
  118. 'b0': [2834.65, 4008.19], 'b1': [2004.09, 2834.65], 'b2': [1417.32, 2004.09],
  119. 'b3': [1000.63, 1417.32], 'b4': [708.66, 1000.63], 'b5': [498.90, 708.66],
  120. 'b6': [354.33, 498.90], 'b7': [249.45, 354.33], 'b8': [175.75, 249.45],
  121. 'b9': [124.72, 175.75], 'b10': [87.87, 124.72],
  122. 'c0': [2599.37, 3676.54],
  123. 'c1': [1836.85, 2599.37], 'c2': [1298.27, 1836.85], 'c3': [918.43, 1298.27],
  124. 'c4': [649.13, 918.43], 'c5': [459.21, 649.13], 'c6': [323.15, 459.21],
  125. 'c7': [229.61, 323.15], 'c8': [161.57, 229.61], 'c9': [113.39, 161.57],
  126. 'c10': [79.37, 113.39],
  127. 'dl': [311.81, 623.62],
  128. 'letter': [612, 792], 'government-letter': [576, 756], 'legal': [612, 1008],
  129. 'junior-legal': [576, 360], 'ledger': [1224, 792], 'tabloid': [792, 1224],
  130. 'credit-card': [153, 243]
  131. };
  132. var FONT_ROW_RATIO = 1.15;
  133. var el = this;
  134. var DownloadEvt = null;
  135. var $hrows = [];
  136. var $rows = [];
  137. var rowIndex = 0;
  138. var trData = '';
  139. var colNames = [];
  140. var ranges = [];
  141. var blob;
  142. var $hiddenTableElements = [];
  143. var checkCellVisibilty = false;
  144. $.extend(true, defaults, options);
  145. // Adopt deprecated options
  146. if (defaults.type === 'xlsx') {
  147. defaults.mso.fileFormat = defaults.type;
  148. defaults.type = 'excel';
  149. }
  150. if (typeof defaults.excelFileFormat !== 'undefined' && defaults.mso.fileFormat === 'undefined')
  151. defaults.mso.fileFormat = defaults.excelFileFormat;
  152. if (typeof defaults.excelPageFormat !== 'undefined' && defaults.mso.pageFormat === 'undefined')
  153. defaults.mso.pageFormat = defaults.excelPageFormat;
  154. if (typeof defaults.excelPageOrientation !== 'undefined' && defaults.mso.pageOrientation === 'undefined')
  155. defaults.mso.pageOrientation = defaults.excelPageOrientation;
  156. if (typeof defaults.excelRTL !== 'undefined' && defaults.mso.rtl === 'undefined')
  157. defaults.mso.rtl = defaults.excelRTL;
  158. if (typeof defaults.excelstyles !== 'undefined' && defaults.mso.styles === 'undefined')
  159. defaults.mso.styles = defaults.excelstyles;
  160. if (typeof defaults.onMsoNumberFormat !== 'undefined' && defaults.mso.onMsoNumberFormat === 'undefined')
  161. defaults.mso.onMsoNumberFormat = defaults.onMsoNumberFormat;
  162. if (typeof defaults.worksheetName !== 'undefined' && defaults.mso.worksheetName === 'undefined')
  163. defaults.mso.worksheetName = defaults.worksheetName;
  164. // Check values of some options
  165. defaults.mso.pageOrientation = (defaults.mso.pageOrientation.substr(0, 1) === 'l') ? 'landscape' : 'portrait';
  166. colNames = GetColumnNames(el);
  167. if ( defaults.type === 'csv' || defaults.type === 'tsv' || defaults.type === 'txt' ) {
  168. var csvData = "";
  169. var rowlength = 0;
  170. ranges = [];
  171. rowIndex = 0;
  172. var csvString = function (cell, rowIndex, colIndex) {
  173. var result = '';
  174. if ( cell !== null ) {
  175. var dataString = parseString(cell, rowIndex, colIndex);
  176. var csvValue = (dataString === null || dataString === '') ? '' : dataString.toString();
  177. if ( defaults.type === 'tsv' ) {
  178. if ( dataString instanceof Date )
  179. dataString.toLocaleString();
  180. // According to http://www.iana.org/assignments/media-types/text/tab-separated-values
  181. // are fields that contain tabs not allowable in tsv encoding
  182. result = replaceAll(csvValue, '\t', ' ');
  183. }
  184. else {
  185. // Takes a string and encapsulates it (by default in double-quotes) if it
  186. // contains the csv field separator, spaces, or linebreaks.
  187. if ( dataString instanceof Date )
  188. result = defaults.csvEnclosure + dataString.toLocaleString() + defaults.csvEnclosure;
  189. else {
  190. result = preventInjection(csvValue);
  191. result = replaceAll(result, defaults.csvEnclosure, defaults.csvEnclosure + defaults.csvEnclosure);
  192. if ( result.indexOf(defaults.csvSeparator) >= 0 || /[\r\n ]/g.test(result) )
  193. result = defaults.csvEnclosure + result + defaults.csvEnclosure;
  194. }
  195. }
  196. }
  197. return result;
  198. };
  199. var CollectCsvData = function ($rows, rowselector, length) {
  200. $rows.each(function () {
  201. trData = "";
  202. ForEachVisibleCell(this, rowselector, rowIndex, length + $rows.length,
  203. function (cell, row, col) {
  204. trData += csvString(cell, row, col) + (defaults.type === 'tsv' ? '\t' : defaults.csvSeparator);
  205. });
  206. trData = $.trim(trData).substring(0, trData.length - 1);
  207. if ( trData.length > 0 ) {
  208. if ( csvData.length > 0 )
  209. csvData += "\n";
  210. csvData += trData;
  211. }
  212. rowIndex++;
  213. });
  214. return $rows.length;
  215. };
  216. rowlength += CollectCsvData($(el).find('thead').first().find(defaults.theadSelector), 'th,td', rowlength);
  217. findTableElements($(el),'tbody').each(function () {
  218. rowlength += CollectCsvData(findTableElements($(this), defaults.tbodySelector), 'td,th', rowlength);
  219. });
  220. if ( defaults.tfootSelector.length )
  221. CollectCsvData($(el).find('tfoot').first().find(defaults.tfootSelector), 'td,th', rowlength);
  222. csvData += "\n";
  223. //output
  224. if ( defaults.outputMode === 'string' )
  225. return csvData;
  226. if ( defaults.outputMode === 'base64' )
  227. return base64encode(csvData);
  228. if ( defaults.outputMode === 'window' ) {
  229. downloadFile(false, 'data:text/' + (defaults.type === 'csv' ? 'csv' : 'plain') + ';charset=utf-8,', csvData);
  230. return;
  231. }
  232. saveToFile ( csvData,
  233. defaults.fileName + '.' + defaults.type,
  234. "text/" + (defaults.type === 'csv' ? 'csv' : 'plain'),
  235. "utf-8",
  236. "",
  237. (defaults.type === 'csv' && defaults.csvUseBOM) );
  238. } else if ( defaults.type === 'sql' ) {
  239. // Header
  240. rowIndex = 0;
  241. ranges = [];
  242. var tdData = "INSERT INTO `" + defaults.tableName + "` (";
  243. $hrows = collectHeadRows ($(el));
  244. $($hrows).each(function () {
  245. ForEachVisibleCell(this, 'th,td', rowIndex, $hrows.length,
  246. function (cell, row, col) {
  247. tdData += "'" + parseString(cell, row, col) + "',";
  248. });
  249. rowIndex++;
  250. tdData = $.trim(tdData).substring(0, tdData.length - 1);
  251. });
  252. tdData += ") VALUES ";
  253. // Data
  254. $rows = collectRows ($(el));
  255. $($rows).each(function () {
  256. trData = "";
  257. ForEachVisibleCell(this, 'td,th', rowIndex, $hrows.length + $rows.length,
  258. function (cell, row, col) {
  259. trData += "'" + parseString(cell, row, col) + "',";
  260. });
  261. if ( trData.length > 3 ) {
  262. tdData += "(" + trData;
  263. tdData = $.trim(tdData).substring(0, tdData.length - 1);
  264. tdData += "),";
  265. }
  266. rowIndex++;
  267. });
  268. tdData = $.trim(tdData).substring(0, tdData.length - 1);
  269. tdData += ";";
  270. // Output
  271. if ( defaults.outputMode === 'string' )
  272. return tdData;
  273. if ( defaults.outputMode === 'base64' )
  274. return base64encode(tdData);
  275. saveToFile ( tdData, defaults.fileName + '.sql', "application/sql", "utf-8", "", false );
  276. } else if ( defaults.type === 'json' ) {
  277. var jsonHeaderArray = [];
  278. ranges = [];
  279. $hrows = collectHeadRows ($(el));
  280. $($hrows).each(function () {
  281. var jsonArrayTd = [];
  282. ForEachVisibleCell(this, 'th,td', rowIndex, $hrows.length,
  283. function (cell, row, col) {
  284. jsonArrayTd.push(parseString(cell, row, col));
  285. });
  286. jsonHeaderArray.push(jsonArrayTd);
  287. });
  288. // Data
  289. var jsonArray = [];
  290. $rows = collectRows ($(el));
  291. $($rows).each(function () {
  292. var jsonObjectTd = {};
  293. var colIndex = 0;
  294. ForEachVisibleCell(this, 'td,th', rowIndex, $hrows.length + $rows.length,
  295. function (cell, row, col) {
  296. if ( jsonHeaderArray.length ) {
  297. jsonObjectTd[jsonHeaderArray[jsonHeaderArray.length - 1][colIndex]] = parseString(cell, row, col);
  298. } else {
  299. jsonObjectTd[colIndex] = parseString(cell, row, col);
  300. }
  301. colIndex++;
  302. });
  303. if ( $.isEmptyObject(jsonObjectTd) === false )
  304. jsonArray.push(jsonObjectTd);
  305. rowIndex++;
  306. });
  307. var sdata = "";
  308. if ( defaults.jsonScope === 'head' )
  309. sdata = JSON.stringify(jsonHeaderArray);
  310. else if ( defaults.jsonScope === 'data' )
  311. sdata = JSON.stringify(jsonArray);
  312. else // all
  313. sdata = JSON.stringify({header: jsonHeaderArray, data: jsonArray});
  314. if ( defaults.outputMode === 'string' )
  315. return sdata;
  316. if ( defaults.outputMode === 'base64' )
  317. return base64encode(sdata);
  318. saveToFile ( sdata, defaults.fileName + '.json', "application/json", "utf-8", "base64", false );
  319. } else if ( defaults.type === 'xml' ) {
  320. rowIndex = 0;
  321. ranges = [];
  322. var xml = '<?xml version="1.0" encoding="utf-8"?>';
  323. xml += '<tabledata><fields>';
  324. // Header
  325. $hrows = collectHeadRows ($(el));
  326. $($hrows).each(function () {
  327. ForEachVisibleCell(this, 'th,td', rowIndex, $hrows.length,
  328. function (cell, row, col) {
  329. xml += "<field>" + parseString(cell, row, col) + "</field>";
  330. });
  331. rowIndex++;
  332. });
  333. xml += '</fields><data>';
  334. // Data
  335. var rowCount = 1;
  336. $rows = collectRows ($(el));
  337. $($rows).each(function () {
  338. var colCount = 1;
  339. trData = "";
  340. ForEachVisibleCell(this, 'td,th', rowIndex, $hrows.length + $rows.length,
  341. function (cell, row, col) {
  342. trData += "<column-" + colCount + ">" + parseString(cell, row, col) + "</column-" + colCount + ">";
  343. colCount++;
  344. });
  345. if ( trData.length > 0 && trData !== "<column-1></column-1>" ) {
  346. xml += '<row id="' + rowCount + '">' + trData + '</row>';
  347. rowCount++;
  348. }
  349. rowIndex++;
  350. });
  351. xml += '</data></tabledata>';
  352. // Output
  353. if ( defaults.outputMode === 'string' )
  354. return xml;
  355. if ( defaults.outputMode === 'base64' )
  356. return base64encode(xml);
  357. saveToFile ( xml, defaults.fileName + '.xml', "application/xml", "utf-8", "base64", false );
  358. }
  359. else if ( defaults.type === 'excel' && defaults.mso.fileFormat === 'xmlss' ) {
  360. var docDatas = [];
  361. var docNames = [];
  362. $(el).filter(function () {
  363. return isVisible($(this));
  364. }).each(function () {
  365. var $table = $(this);
  366. var ssName = '';
  367. if ( typeof defaults.mso.worksheetName === 'string' && defaults.mso.worksheetName.length )
  368. ssName = defaults.mso.worksheetName + ' ' + (docNames.length + 1);
  369. else if ( typeof defaults.mso.worksheetName[docNames.length] !== 'undefined' )
  370. ssName = defaults.mso.worksheetName[docNames.length];
  371. if ( ! ssName.length )
  372. ssName = $table.find('caption').text() || '';
  373. if ( ! ssName.length )
  374. ssName = 'Table ' + (docNames.length + 1);
  375. ssName = $.trim(ssName.replace(/[\\\/[\]*:?'"]/g,'').substring(0,31));
  376. docNames.push($('<div />').text(ssName).html());
  377. if ( defaults.exportHiddenCells === false ) {
  378. $hiddenTableElements = $table.find("tr, th, td").filter(":hidden");
  379. checkCellVisibilty = $hiddenTableElements.length > 0;
  380. }
  381. rowIndex = 0;
  382. colNames = GetColumnNames(this);
  383. docData = '<Table>\r';
  384. function CollectXmlssData ($rows, rowselector, length) {
  385. var spans = [];
  386. $($rows).each(function () {
  387. var ssIndex = 0;
  388. var nCols = 0;
  389. trData = "";
  390. ForEachVisibleCell(this, 'td,th', rowIndex, length + $rows.length,
  391. function (cell, row, col) {
  392. if ( cell !== null ) {
  393. var style = "";
  394. var data = parseString(cell, row, col);
  395. var type = "String";
  396. if ( jQuery.isNumeric(data) !== false ) {
  397. type = "Number";
  398. }
  399. else {
  400. var number = parsePercent(data);
  401. if ( number !== false ) {
  402. data = number;
  403. type = "Number";
  404. style += ' ss:StyleID="pct1"';
  405. }
  406. }
  407. if ( type !== "Number" )
  408. data = data.replace(/\n/g, '<br>');
  409. var colspan = getColspan (cell);
  410. var rowspan = getRowspan (cell);
  411. // Skip spans
  412. $.each(spans, function () {
  413. var range = this;
  414. if ( rowIndex >= range.s.r && rowIndex <= range.e.r && nCols >= range.s.c && nCols <= range.e.c ) {
  415. for ( var i = 0; i <= range.e.c - range.s.c; ++i ) {
  416. nCols++;
  417. ssIndex++;
  418. }
  419. }
  420. });
  421. // Handle Row Span
  422. if ( rowspan || colspan ) {
  423. rowspan = rowspan || 1;
  424. colspan = colspan || 1;
  425. spans.push({
  426. s: {r: rowIndex, c: nCols},
  427. e: {r: rowIndex + rowspan - 1, c: nCols + colspan - 1}
  428. });
  429. }
  430. // Handle Colspan
  431. if ( colspan > 1 ) {
  432. style += ' ss:MergeAcross="' + (colspan-1) + '"';
  433. nCols += (colspan - 1);
  434. }
  435. if ( rowspan > 1 ) {
  436. style += ' ss:MergeDown="' + (rowspan-1) + '" ss:StyleID="rsp1"';
  437. }
  438. if ( ssIndex > 0 ) {
  439. style += ' ss:Index="' + (nCols+1) + '"';
  440. ssIndex = 0;
  441. }
  442. trData += '<Cell' + style + '><Data ss:Type="' + type + '">' +
  443. $('<div />').text(data).html() +
  444. '</Data></Cell>\r';
  445. nCols++;
  446. }
  447. });
  448. if ( trData.length > 0 )
  449. docData += '<Row ss:AutoFitHeight="0">\r' + trData + '</Row>\r';
  450. rowIndex++;
  451. });
  452. return $rows.length;
  453. }
  454. var rowLength = CollectXmlssData (collectHeadRows ($table), 'th,td', rowLength);
  455. CollectXmlssData (collectRows ($table), 'td,th', rowLength);
  456. docData += '</Table>\r';
  457. docDatas.push(docData);
  458. });
  459. var count = {};
  460. var firstOccurences = {};
  461. var item, itemCount;
  462. for (var n = 0, c = docNames.length; n < c; n++)
  463. {
  464. item = docNames[n];
  465. itemCount = count[item];
  466. itemCount = count[item] = (itemCount == null ? 1 : itemCount + 1);
  467. if( itemCount === 2 )
  468. docNames[firstOccurences[item]] = docNames[firstOccurences[item]].substring(0,29) + "-1";
  469. if( count[ item ] > 1 )
  470. docNames[n] = docNames[n].substring(0,29) + "-" + count[item];
  471. else
  472. firstOccurences[item] = n;
  473. }
  474. var CreationDate = new Date().toISOString();
  475. var xmlssDocFile = '<?xml version="1.0" encoding="UTF-8"?>\r' +
  476. '<?mso-application progid="Excel.Sheet"?>\r' +
  477. '<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"\r' +
  478. ' xmlns:o="urn:schemas-microsoft-com:office:office"\r' +
  479. ' xmlns:x="urn:schemas-microsoft-com:office:excel"\r' +
  480. ' xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"\r' +
  481. ' xmlns:html="http://www.w3.org/TR/REC-html40">\r' +
  482. '<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">\r' +
  483. ' <Created>' + CreationDate + '</Created>\r' +
  484. '</DocumentProperties>\r' +
  485. '<OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office">\r' +
  486. ' <AllowPNG/>\r' +
  487. '</OfficeDocumentSettings>\r' +
  488. '<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">\r' +
  489. ' <WindowHeight>9000</WindowHeight>\r' +
  490. ' <WindowWidth>13860</WindowWidth>\r' +
  491. ' <WindowTopX>0</WindowTopX>\r' +
  492. ' <WindowTopY>0</WindowTopY>\r' +
  493. ' <ProtectStructure>False</ProtectStructure>\r' +
  494. ' <ProtectWindows>False</ProtectWindows>\r' +
  495. '</ExcelWorkbook>\r' +
  496. '<Styles>\r' +
  497. ' <Style ss:ID="Default" ss:Name="Normal">\r' +
  498. ' <Alignment ss:Vertical="Bottom"/>\r' +
  499. ' <Borders/>\r' +
  500. ' <Font/>\r' +
  501. ' <Interior/>\r' +
  502. ' <NumberFormat/>\r' +
  503. ' <Protection/>\r' +
  504. ' </Style>\r' +
  505. ' <Style ss:ID="rsp1">\r' +
  506. ' <Alignment ss:Vertical="Center"/>\r' +
  507. ' </Style>\r' +
  508. ' <Style ss:ID="pct1">\r' +
  509. ' <NumberFormat ss:Format="Percent"/>\r' +
  510. ' </Style>\r' +
  511. '</Styles>\r';
  512. for ( var j = 0; j < docDatas.length; j++ ) {
  513. xmlssDocFile += '<Worksheet ss:Name="' + docNames[j] + '" ss:RightToLeft="' + (defaults.mso.rtl ? '1' : '0') + '">\r' +
  514. docDatas[j];
  515. if (defaults.mso.rtl) {
  516. xmlssDocFile += '<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">\r' +
  517. '<DisplayRightToLeft/>\r' +
  518. '</WorksheetOptions>\r';
  519. }
  520. else
  521. xmlssDocFile += '<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel"/>\r';
  522. xmlssDocFile += '</Worksheet>\r';
  523. }
  524. xmlssDocFile += '</Workbook>\r';
  525. if ( defaults.outputMode === 'string' )
  526. return xmlssDocFile;
  527. if ( defaults.outputMode === 'base64' )
  528. return base64encode(xmlssDocFile);
  529. saveToFile ( xmlssDocFile, defaults.fileName + '.xml', "application/xml", "utf-8", "base64", false );
  530. }
  531. else if ( defaults.type === 'excel' && defaults.mso.fileFormat === 'xlsx' ) {
  532. var docNames = [];
  533. var workbook = XLSX.utils.book_new();
  534. // Multiple worksheets and .xlsx file extension #202
  535. $(el).filter(function () {
  536. return isVisible($(this));
  537. }).each(function () {
  538. var $table = $(this);
  539. var ws = XLSX.utils.table_to_sheet(this);
  540. var sheetName = '';
  541. if ( typeof defaults.mso.worksheetName === 'string' && defaults.mso.worksheetName.length )
  542. sheetName = defaults.mso.worksheetName + ' ' + (docNames.length + 1);
  543. else if ( typeof defaults.mso.worksheetName[docNames.length] !== 'undefined' )
  544. sheetName = defaults.mso.worksheetName[docNames.length];
  545. if ( ! sheetName.length )
  546. sheetName = $table.find('caption').text() || '';
  547. if ( ! sheetName.length )
  548. sheetName = 'Table ' + (docNames.length + 1);
  549. sheetName = $.trim(sheetName.replace(/[\\\/[\]*:?'"]/g,'').substring(0,31));
  550. docNames.push(sheetName);
  551. XLSX.utils.book_append_sheet(workbook, ws, sheetName);
  552. });
  553. // add worksheet to workbook
  554. var wbout = XLSX.write(workbook, {type: 'binary', bookType: defaults.mso.fileFormat, bookSST: false});
  555. saveToFile ( jx_s2ab(wbout),
  556. defaults.fileName + '.' + defaults.mso.fileFormat,
  557. "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  558. "UTF-8", "", false );
  559. }
  560. else if ( defaults.type === 'excel' || defaults.type === 'xls' || defaults.type === 'word' || defaults.type === 'doc' ) {
  561. var MSDocType = (defaults.type === 'excel' || defaults.type === 'xls') ? 'excel' : 'word';
  562. var MSDocExt = (MSDocType === 'excel') ? 'xls' : 'doc';
  563. var MSDocSchema = 'xmlns:x="urn:schemas-microsoft-com:office:' + MSDocType + '"';
  564. var docData = '';
  565. var docName = '';
  566. $(el).filter(function () {
  567. return isVisible($(this));
  568. }).each(function () {
  569. var $table = $(this);
  570. if (docName === '') {
  571. docName = defaults.mso.worksheetName || $table.find('caption').text() || 'Table';
  572. docName = $.trim(docName.replace(/[\\\/[\]*:?'"]/g, '').substring(0, 31));
  573. }
  574. if ( defaults.exportHiddenCells === false ) {
  575. $hiddenTableElements = $table.find("tr, th, td").filter(":hidden");
  576. checkCellVisibilty = $hiddenTableElements.length > 0;
  577. }
  578. rowIndex = 0;
  579. ranges = [];
  580. colNames = GetColumnNames(this);
  581. // Header
  582. docData += '<table><thead>';
  583. $hrows = collectHeadRows ($table);
  584. $($hrows).each(function () {
  585. var $row = $(this);
  586. trData = "";
  587. ForEachVisibleCell(this, 'th,td', rowIndex, $hrows.length,
  588. function (cell, row, col) {
  589. if ( cell !== null ) {
  590. var thstyle = '';
  591. var cellstyles = document.defaultView.getComputedStyle(cell, null);
  592. var rowstyles = document.defaultView.getComputedStyle($row[0], null);
  593. trData += '<th';
  594. for ( var cssStyle in defaults.mso.styles ) {
  595. var thcss = cellstyles[defaults.mso.styles[cssStyle]];
  596. if ( thcss === '' )
  597. thcss = rowstyles[defaults.mso.styles[cssStyle]];
  598. if ( thcss !== '' && thcss !== '0px none rgb(0, 0, 0)' && thcss !== 'rgba(0, 0, 0, 0)' ) {
  599. thstyle += (thstyle === '') ? 'style="' : ';';
  600. thstyle += defaults.mso.styles[cssStyle] + ':' + thcss;
  601. }
  602. }
  603. if ( thstyle !== '' )
  604. trData += ' ' + thstyle + '"';
  605. var tdcolspan = getColspan (cell);
  606. if ( tdcolspan > 0 )
  607. trData += ' colspan="' + tdcolspan + '"';
  608. var tdrowspan = getRowspan (cell);
  609. if ( tdrowspan > 0 )
  610. trData += ' rowspan="' + tdrowspan + '"';
  611. trData += '>' + parseString(cell, row, col) + '</th>';
  612. }
  613. });
  614. if ( trData.length > 0 )
  615. docData += '<tr>' + trData + '</tr>';
  616. rowIndex++;
  617. });
  618. docData += '</thead><tbody>';
  619. // Data
  620. $rows = collectRows ($table);
  621. $($rows).each(function () {
  622. var $row = $(this);
  623. trData = "";
  624. ForEachVisibleCell(this, 'td,th', rowIndex, $hrows.length + $rows.length,
  625. function (cell, row, col) {
  626. if ( cell !== null ) {
  627. var tdvalue = parseString(cell, row, col);
  628. var tdstyle = '';
  629. var tdcss = $(cell).data("tableexport-msonumberformat");
  630. var cellstyles = document.defaultView.getComputedStyle(cell, null);
  631. var rowstyles = document.defaultView.getComputedStyle($row[0], null);
  632. if ( typeof tdcss === 'undefined' && typeof defaults.mso.onMsoNumberFormat === 'function' )
  633. tdcss = defaults.mso.onMsoNumberFormat(cell, row, col);
  634. if ( typeof tdcss !== 'undefined' && tdcss !== '' )
  635. tdstyle = 'style="mso-number-format:\'' + tdcss + '\'';
  636. for ( var cssStyle in defaults.mso.styles ) {
  637. tdcss = cellstyles[defaults.mso.styles[cssStyle]];
  638. if ( tdcss === '' )
  639. tdcss = rowstyles[defaults.mso.styles[cssStyle]];
  640. if ( tdcss !== '' && tdcss !== '0px none rgb(0, 0, 0)' && tdcss !== 'rgba(0, 0, 0, 0)' ) {
  641. tdstyle += (tdstyle === '') ? 'style="' : ';';
  642. tdstyle += defaults.mso.styles[cssStyle] + ':' + tdcss;
  643. }
  644. }
  645. trData += '<td';
  646. if ( tdstyle !== '' )
  647. trData += ' ' + tdstyle + '"';
  648. var tdcolspan = getColspan (cell);
  649. if ( tdcolspan > 0 )
  650. trData += ' colspan="' + tdcolspan + '"';
  651. var tdrowspan = getRowspan (cell);
  652. if ( tdrowspan > 0 )
  653. trData += ' rowspan="' + tdrowspan + '"';
  654. if ( typeof tdvalue === 'string' && tdvalue !== '' ) {
  655. tdvalue = preventInjection(tdvalue);
  656. tdvalue = tdvalue.replace(/\n/g, '<br>');
  657. }
  658. trData += '>' + tdvalue + '</td>';
  659. }
  660. });
  661. if ( trData.length > 0 )
  662. docData += '<tr>' + trData + '</tr>';
  663. rowIndex++;
  664. });
  665. if ( defaults.displayTableName )
  666. docData += '<tr><td></td></tr><tr><td></td></tr><tr><td>' + parseString($('<p>' + defaults.tableName + '</p>')) + '</td></tr>';
  667. docData += '</tbody></table>';
  668. });
  669. //noinspection XmlUnusedNamespaceDeclaration
  670. var docFile = '<html xmlns:o="urn:schemas-microsoft-com:office:office" ' + MSDocSchema + ' xmlns="http://www.w3.org/TR/REC-html40">';
  671. docFile += '<meta http-equiv="content-type" content="application/vnd.ms-' + MSDocType + '; charset=UTF-8">';
  672. docFile += "<head>";
  673. if (MSDocType === 'excel') {
  674. docFile += "<!--[if gte mso 9]>";
  675. docFile += "<xml>";
  676. docFile += "<x:ExcelWorkbook>";
  677. docFile += "<x:ExcelWorksheets>";
  678. docFile += "<x:ExcelWorksheet>";
  679. docFile += "<x:Name>";
  680. docFile += docName;
  681. docFile += "</x:Name>";
  682. docFile += "<x:WorksheetOptions>";
  683. docFile += "<x:DisplayGridlines/>";
  684. if (defaults.mso.rtl)
  685. docFile += "<x:DisplayRightToLeft/>";
  686. docFile += "</x:WorksheetOptions>";
  687. docFile += "</x:ExcelWorksheet>";
  688. docFile += "</x:ExcelWorksheets>";
  689. docFile += "</x:ExcelWorkbook>";
  690. docFile += "</xml>";
  691. docFile += "<![endif]-->";
  692. }
  693. docFile += "<style>";
  694. docFile += "@page { size:" + defaults.mso.pageOrientation + "; mso-page-orientation:" + defaults.mso.pageOrientation + "; }";
  695. docFile += "@page Section1 {size:" + pageFormats[defaults.mso.pageFormat][0] + "pt " + pageFormats[defaults.mso.pageFormat][1] + "pt";
  696. docFile += "; margin:1.0in 1.25in 1.0in 1.25in;mso-header-margin:.5in;mso-footer-margin:.5in;mso-paper-source:0;}";
  697. docFile += "div.Section1 {page:Section1;}";
  698. docFile += "@page Section2 {size:" + pageFormats[defaults.mso.pageFormat][1] + "pt " + pageFormats[defaults.mso.pageFormat][0] + "pt";
  699. docFile += ";mso-page-orientation:" + defaults.mso.pageOrientation + ";margin:1.25in 1.0in 1.25in 1.0in;mso-header-margin:.5in;mso-footer-margin:.5in;mso-paper-source:0;}";
  700. docFile += "div.Section2 {page:Section2;}";
  701. docFile += "br {mso-data-placement:same-cell;}";
  702. docFile += "</style>";
  703. docFile += "</head>";
  704. docFile += "<body>";
  705. docFile += "<div class=\"Section" + ((defaults.mso.pageOrientation === 'landscape') ? "2" : "1") + "\">";
  706. docFile += docData;
  707. docFile += "</div>";
  708. docFile += "</body>";
  709. docFile += "</html>";
  710. if ( defaults.outputMode === 'string' )
  711. return docFile;
  712. if ( defaults.outputMode === 'base64' )
  713. return base64encode(docFile);
  714. saveToFile ( docFile, defaults.fileName + '.' + MSDocExt, "application/vnd.ms-" + MSDocType, "", "base64", false );
  715. }
  716. else if ( defaults.type === 'png' ) {
  717. html2canvas($(el)[0]).then(
  718. function (canvas) {
  719. var image = canvas.toDataURL();
  720. var byteString = atob(image.substring(22)); // remove data stuff
  721. var buffer = new ArrayBuffer(byteString.length);
  722. var intArray = new Uint8Array(buffer);
  723. for ( var i = 0; i < byteString.length; i++ )
  724. intArray[i] = byteString.charCodeAt(i);
  725. if ( defaults.outputMode === 'string' )
  726. return byteString;
  727. if ( defaults.outputMode === 'base64' )
  728. return base64encode(image);
  729. if ( defaults.outputMode === 'window' ) {
  730. window.open(image);
  731. return;
  732. }
  733. saveToFile ( buffer, defaults.fileName + '.png', "image/png", "", "", false );
  734. });
  735. } else if ( defaults.type === 'pdf' ) {
  736. if ( defaults.pdfmake.enabled === true ) {
  737. // pdf output using pdfmake
  738. // https://github.com/bpampuch/pdfmake
  739. var widths = [];
  740. var body = [];
  741. rowIndex = 0;
  742. ranges = [];
  743. /**
  744. * @return {number}
  745. */
  746. var CollectPdfmakeData = function ($rows, colselector, length) {
  747. var rlength = 0;
  748. $($rows).each(function () {
  749. var r = [];
  750. ForEachVisibleCell(this, colselector, rowIndex, length,
  751. function (cell, row, col) {
  752. if ( typeof cell !== 'undefined' && cell !== null ) {
  753. var colspan = getColspan (cell);
  754. var rowspan = getRowspan (cell);
  755. var cellValue = parseString(cell, row, col) || " ";
  756. if ( colspan > 1 || rowspan > 1 ) {
  757. colspan = colspan || 1;
  758. rowspan = rowspan || 1;
  759. r.push({colSpan: colspan, rowSpan: rowspan, text: cellValue});
  760. }
  761. else
  762. r.push(cellValue);
  763. }
  764. else
  765. r.push(" ");
  766. });
  767. if ( r.length )
  768. body.push(r);
  769. if ( rlength < r.length )
  770. rlength = r.length;
  771. rowIndex++;
  772. });
  773. return rlength;
  774. };
  775. $hrows = collectHeadRows ($(this));
  776. var colcount = CollectPdfmakeData($hrows, 'th,td', $hrows.length);
  777. for ( var i = widths.length; i < colcount; i++ )
  778. widths.push("*");
  779. // Data
  780. $rows = collectRows ($(this));
  781. CollectPdfmakeData($rows, 'th,td', $hrows.length + $rows.length);
  782. var docDefinition = {
  783. content: [{
  784. table: {
  785. headerRows: $hrows.length,
  786. widths: widths,
  787. body: body
  788. }
  789. }]
  790. };
  791. $.extend(true, docDefinition, defaults.pdfmake.docDefinition);
  792. pdfMake.fonts = {
  793. Roboto: {
  794. normal: 'Roboto-Regular.ttf',
  795. bold: 'Roboto-Medium.ttf',
  796. italics: 'Roboto-Italic.ttf',
  797. bolditalics: 'Roboto-MediumItalic.ttf'
  798. }
  799. };
  800. $.extend(true, pdfMake.fonts, defaults.pdfmake.fonts);
  801. pdfMake.createPdf(docDefinition).getBuffer(function (buffer) {
  802. saveToFile ( buffer, defaults.fileName + '.pdf', "application/pdf", "", "", false );
  803. });
  804. }
  805. else if ( defaults.jspdf.autotable === false ) {
  806. // pdf output using jsPDF's core html support
  807. var addHtmlOptions = {
  808. dim: {
  809. w: getPropertyUnitValue($(el).first().get(0), 'width', 'mm'),
  810. h: getPropertyUnitValue($(el).first().get(0), 'height', 'mm')
  811. },
  812. pagesplit: false
  813. };
  814. var doc = new jsPDF(defaults.jspdf.orientation, defaults.jspdf.unit, defaults.jspdf.format);
  815. doc.addHTML($(el).first(),
  816. defaults.jspdf.margins.left,
  817. defaults.jspdf.margins.top,
  818. addHtmlOptions,
  819. function () {
  820. jsPdfOutput(doc, false);
  821. });
  822. //delete doc;
  823. }
  824. else {
  825. // pdf output using jsPDF AutoTable plugin
  826. // https://github.com/simonbengtsson/jsPDF-AutoTable
  827. var teOptions = defaults.jspdf.autotable.tableExport;
  828. // When setting jspdf.format to 'bestfit' tableExport tries to choose
  829. // the minimum required paper format and orientation in which the table
  830. // (or tables in multitable mode) completely fits without column adjustment
  831. if ( typeof defaults.jspdf.format === 'string' && defaults.jspdf.format.toLowerCase() === 'bestfit' ) {
  832. var rk = '', ro = '';
  833. var mw = 0;
  834. $(el).each(function () {
  835. if ( isVisible($(this)) ) {
  836. var w = getPropertyUnitValue($(this).get(0), 'width', 'pt');
  837. if ( w > mw ) {
  838. if ( w > pageFormats.a0[0] ) {
  839. rk = 'a0';
  840. ro = 'l';
  841. }
  842. for ( var key in pageFormats ) {
  843. if ( pageFormats.hasOwnProperty(key) ) {
  844. if ( pageFormats[key][1] > w ) {
  845. rk = key;
  846. ro = 'l';
  847. if ( pageFormats[key][0] > w )
  848. ro = 'p';
  849. }
  850. }
  851. }
  852. mw = w;
  853. }
  854. }
  855. });
  856. defaults.jspdf.format = (rk === '' ? 'a4' : rk);
  857. defaults.jspdf.orientation = (ro === '' ? 'w' : ro);
  858. }
  859. // The jsPDF doc object is stored in defaults.jspdf.autotable.tableExport,
  860. // thus it can be accessed from any callback function
  861. if ( teOptions.doc == null ) {
  862. teOptions.doc = new jsPDF(defaults.jspdf.orientation,
  863. defaults.jspdf.unit,
  864. defaults.jspdf.format);
  865. teOptions.wScaleFactor = 1;
  866. teOptions.hScaleFactor = 1;
  867. if ( typeof defaults.jspdf.onDocCreated === 'function' )
  868. defaults.jspdf.onDocCreated(teOptions.doc);
  869. }
  870. if ( teOptions.outputImages === true )
  871. teOptions.images = {};
  872. if ( typeof teOptions.images !== 'undefined' ) {
  873. $(el).filter(function () {
  874. return isVisible($(this));
  875. }).each(function () {
  876. var rowCount = 0;
  877. ranges = [];
  878. if ( defaults.exportHiddenCells === false ) {
  879. $hiddenTableElements = $(this).find("tr, th, td").filter(":hidden");
  880. checkCellVisibilty = $hiddenTableElements.length > 0;
  881. }
  882. $hrows = collectHeadRows ($(this));
  883. $rows = collectRows ($(this));
  884. $($rows).each(function () {
  885. ForEachVisibleCell(this, 'td,th', $hrows.length + rowCount, $hrows.length + $rows.length,
  886. function (cell) {
  887. collectImages(cell, $(cell).children(), teOptions);
  888. });
  889. rowCount++;
  890. });
  891. });
  892. $hrows = [];
  893. $rows = [];
  894. }
  895. loadImages(teOptions, function () {
  896. $(el).filter(function () {
  897. return isVisible($(this));
  898. }).each(function () {
  899. var colKey;
  900. rowIndex = 0;
  901. ranges = [];
  902. if ( defaults.exportHiddenCells === false ) {
  903. $hiddenTableElements = $(this).find("tr, th, td").filter(":hidden");
  904. checkCellVisibilty = $hiddenTableElements.length > 0;
  905. }
  906. colNames = GetColumnNames(this);
  907. teOptions.columns = [];
  908. teOptions.rows = [];
  909. teOptions.teCells = {};
  910. // onTable: optional callback function for every matching table that can be used
  911. // to modify the tableExport options or to skip the output of a particular table
  912. // if the table selector targets multiple tables
  913. if ( typeof teOptions.onTable === 'function' )
  914. if ( teOptions.onTable($(this), defaults) === false )
  915. return true; // continue to next iteration step (table)
  916. // each table works with an own copy of AutoTable options
  917. defaults.jspdf.autotable.tableExport = null; // avoid deep recursion error
  918. var atOptions = $.extend(true, {}, defaults.jspdf.autotable);
  919. defaults.jspdf.autotable.tableExport = teOptions;
  920. atOptions.margin = {};
  921. $.extend(true, atOptions.margin, defaults.jspdf.margins);
  922. atOptions.tableExport = teOptions;
  923. // Fix jsPDF Autotable's row height calculation
  924. if ( typeof atOptions.beforePageContent !== 'function' ) {
  925. atOptions.beforePageContent = function (data) {
  926. if ( data.pageCount === 1 ) {
  927. var all = data.table.rows.concat(data.table.headerRow);
  928. $.each(all, function () {
  929. var row = this;
  930. if ( row.height > 0 ) {
  931. row.height += (2 - FONT_ROW_RATIO) / 2 * row.styles.fontSize;
  932. data.table.height += (2 - FONT_ROW_RATIO) / 2 * row.styles.fontSize;
  933. }
  934. });
  935. }
  936. };
  937. }
  938. if ( typeof atOptions.createdHeaderCell !== 'function' ) {
  939. // apply some original css styles to pdf header cells
  940. atOptions.createdHeaderCell = function (cell, data) {
  941. // jsPDF AutoTable plugin v2.0.14 fix: each cell needs its own styles object
  942. cell.styles = $.extend({}, data.row.styles);
  943. if ( typeof teOptions.columns [data.column.dataKey] !== 'undefined' ) {
  944. var col = teOptions.columns [data.column.dataKey];
  945. if ( typeof col.rect !== 'undefined' ) {
  946. var rh;
  947. cell.contentWidth = col.rect.width;
  948. if ( typeof teOptions.heightRatio === 'undefined' || teOptions.heightRatio === 0 ) {
  949. if ( data.row.raw [data.column.dataKey].rowspan )
  950. rh = data.row.raw [data.column.dataKey].rect.height / data.row.raw [data.column.dataKey].rowspan;
  951. else
  952. rh = data.row.raw [data.column.dataKey].rect.height;
  953. teOptions.heightRatio = cell.styles.rowHeight / rh;
  954. }
  955. rh = data.row.raw [data.column.dataKey].rect.height * teOptions.heightRatio;
  956. if ( rh > cell.styles.rowHeight )
  957. cell.styles.rowHeight = rh;
  958. }
  959. cell.styles.halign = (atOptions.headerStyles.halign === 'inherit') ? 'center' : atOptions.headerStyles.halign;
  960. cell.styles.valign = atOptions.headerStyles.valign;
  961. if ( typeof col.style !== 'undefined' && col.style.hidden !== true ) {
  962. if ( atOptions.headerStyles.halign === 'inherit' )
  963. cell.styles.halign = col.style.align;
  964. if ( atOptions.styles.fillColor === 'inherit' )
  965. cell.styles.fillColor = col.style.bcolor;
  966. if ( atOptions.styles.textColor === 'inherit' )
  967. cell.styles.textColor = col.style.color;
  968. if ( atOptions.styles.fontStyle === 'inherit' )
  969. cell.styles.fontStyle = col.style.fstyle;
  970. }
  971. }
  972. };
  973. }
  974. if ( typeof atOptions.createdCell !== 'function' ) {
  975. // apply some original css styles to pdf table cells
  976. atOptions.createdCell = function (cell, data) {
  977. var tecell = teOptions.teCells [data.row.index + ":" + data.column.dataKey];
  978. cell.styles.halign = (atOptions.styles.halign === 'inherit') ? 'center' : atOptions.styles.halign;
  979. cell.styles.valign = atOptions.styles.valign;
  980. if ( typeof tecell !== 'undefined' && typeof tecell.style !== 'undefined' && tecell.style.hidden !== true ) {
  981. if ( atOptions.styles.halign === 'inherit' )
  982. cell.styles.halign = tecell.style.align;
  983. if ( atOptions.styles.fillColor === 'inherit' )
  984. cell.styles.fillColor = tecell.style.bcolor;
  985. if ( atOptions.styles.textColor === 'inherit' )
  986. cell.styles.textColor = tecell.style.color;
  987. if ( atOptions.styles.fontStyle === 'inherit' )
  988. cell.styles.fontStyle = tecell.style.fstyle;
  989. }
  990. };
  991. }
  992. if ( typeof atOptions.drawHeaderCell !== 'function' ) {
  993. atOptions.drawHeaderCell = function (cell, data) {
  994. var colopt = teOptions.columns [data.column.dataKey];
  995. if ( (colopt.style.hasOwnProperty("hidden") !== true || colopt.style.hidden !== true) &&
  996. colopt.rowIndex >= 0 )
  997. return prepareAutoTableText(cell, data, colopt);
  998. else
  999. return false; // cell is hidden
  1000. };
  1001. }
  1002. if ( typeof atOptions.drawCell !== 'function' ) {
  1003. atOptions.drawCell = function (cell, data) {
  1004. var tecell = teOptions.teCells [data.row.index + ":" + data.column.dataKey];
  1005. var draw2canvas = (typeof tecell !== 'undefined' && tecell.isCanvas);
  1006. if ( draw2canvas !== true ) {
  1007. if ( prepareAutoTableText(cell, data, tecell) ) {
  1008. teOptions.doc.rect(cell.x, cell.y, cell.width, cell.height, cell.styles.fillStyle);
  1009. if ( typeof tecell !== 'undefined' &&
  1010. typeof tecell.elements !== 'undefined' && tecell.elements.length ) {
  1011. var hScale = cell.height / tecell.rect.height;
  1012. if ( hScale > teOptions.hScaleFactor )
  1013. teOptions.hScaleFactor = hScale;
  1014. teOptions.wScaleFactor = cell.width / tecell.rect.width;
  1015. var ySave = cell.textPos.y;
  1016. drawAutotableElements(cell, tecell.elements, teOptions);
  1017. cell.textPos.y = ySave;
  1018. drawAutotableText(cell, tecell.elements, teOptions);
  1019. }
  1020. else
  1021. drawAutotableText(cell, {}, teOptions);
  1022. }
  1023. }
  1024. else {
  1025. var container = tecell.elements[0];
  1026. var imgId = $(container).attr("data-tableexport-canvas");
  1027. var r = container.getBoundingClientRect();
  1028. cell.width = r.width * teOptions.wScaleFactor;
  1029. cell.height = r.height * teOptions.hScaleFactor;
  1030. data.row.height = cell.height;
  1031. jsPdfDrawImage (cell, container, imgId, teOptions);
  1032. }
  1033. return false;
  1034. };
  1035. }
  1036. // collect header and data rows
  1037. teOptions.headerrows = [];
  1038. $hrows = collectHeadRows ($(this));
  1039. $($hrows).each(function () {
  1040. colKey = 0;
  1041. teOptions.headerrows[rowIndex] = [];
  1042. ForEachVisibleCell(this, 'th,td', rowIndex, $hrows.length,
  1043. function (cell, row, col) {
  1044. var obj = getCellStyles(cell);
  1045. obj.title = parseString(cell, row, col);
  1046. obj.key = colKey++;
  1047. obj.rowIndex = rowIndex;
  1048. teOptions.headerrows[rowIndex].push(obj);
  1049. });
  1050. rowIndex++;
  1051. });
  1052. if ( rowIndex > 0 ) {
  1053. // iterate through last row
  1054. var lastrow = rowIndex - 1;
  1055. while ( lastrow >= 0 ) {
  1056. $.each(teOptions.headerrows[lastrow], function () {
  1057. var obj = this;
  1058. if ( lastrow > 0 && this.rect === null )
  1059. obj = teOptions.headerrows[lastrow - 1][this.key];
  1060. if ( obj !== null && obj.rowIndex >= 0 &&
  1061. (obj.style.hasOwnProperty("hidden") !== true || obj.style.hidden !== true) )
  1062. teOptions.columns.push(obj);
  1063. });
  1064. lastrow = (teOptions.columns.length > 0) ? -1 : lastrow - 1;
  1065. }
  1066. }
  1067. var rowCount = 0;
  1068. $rows = [];
  1069. $rows = collectRows ($(this));
  1070. $($rows).each(function () {
  1071. var rowData = [];
  1072. colKey = 0;
  1073. ForEachVisibleCell(this, 'td,th', rowIndex, $hrows.length + $rows.length,
  1074. function (cell, row, col) {
  1075. var obj;
  1076. if ( typeof teOptions.columns[colKey] === 'undefined' ) {
  1077. // jsPDF-Autotable needs columns. Thus define hidden ones for tables without thead
  1078. obj = {
  1079. title: '',
  1080. key: colKey,
  1081. style: {
  1082. hidden: true
  1083. }
  1084. };
  1085. teOptions.columns.push(obj);
  1086. }
  1087. if ( typeof cell !== 'undefined' && cell !== null ) {
  1088. obj = getCellStyles(cell);
  1089. obj.isCanvas = cell.hasAttribute("data-tableexport-canvas");
  1090. obj.elements = obj.isCanvas ? $(cell) : $(cell).children();
  1091. teOptions.teCells [rowCount + ":" + colKey++] = obj;
  1092. }
  1093. else {
  1094. obj = $.extend(true, {}, teOptions.teCells [rowCount + ":" + (colKey - 1)]);
  1095. obj.colspan = -1;
  1096. teOptions.teCells [rowCount + ":" + colKey++] = obj;
  1097. }
  1098. rowData.push(parseString(cell, row, col));
  1099. });
  1100. if ( rowData.length ) {
  1101. teOptions.rows.push(rowData);
  1102. rowCount++;
  1103. }
  1104. rowIndex++;
  1105. });
  1106. // onBeforeAutotable: optional callback function before calling
  1107. // jsPDF AutoTable that can be used to modify the AutoTable options
  1108. if ( typeof teOptions.onBeforeAutotable === 'function' )
  1109. teOptions.onBeforeAutotable($(this), teOptions.columns, teOptions.rows, atOptions);
  1110. teOptions.doc.autoTable(teOptions.columns, teOptions.rows, atOptions);
  1111. // onAfterAutotable: optional callback function after returning
  1112. // from jsPDF AutoTable that can be used to modify the AutoTable options
  1113. if ( typeof teOptions.onAfterAutotable === 'function' )
  1114. teOptions.onAfterAutotable($(this), atOptions);
  1115. // set the start position for the next table (in case there is one)
  1116. defaults.jspdf.autotable.startY = teOptions.doc.autoTableEndPosY() + atOptions.margin.top;
  1117. });
  1118. jsPdfOutput(teOptions.doc, (typeof teOptions.images !== 'undefined' && jQuery.isEmptyObject(teOptions.images) === false));
  1119. if ( typeof teOptions.headerrows !== 'undefined' )
  1120. teOptions.headerrows.length = 0;
  1121. if ( typeof teOptions.columns !== 'undefined' )
  1122. teOptions.columns.length = 0;
  1123. if ( typeof teOptions.rows !== 'undefined' )
  1124. teOptions.rows.length = 0;
  1125. delete teOptions.doc;
  1126. teOptions.doc = null;
  1127. });
  1128. }
  1129. }
  1130. function collectHeadRows ($table) {
  1131. var result = [];
  1132. findTableElements($table,'thead').each(function () {
  1133. result.push.apply(result, findTableElements($(this), defaults.theadSelector).toArray());
  1134. });
  1135. return result;
  1136. }
  1137. function collectRows ($table) {
  1138. var result = [];
  1139. findTableElements($table,'tbody').each(function () {
  1140. result.push.apply(result, findTableElements($(this), defaults.tbodySelector).toArray());
  1141. });
  1142. if ( defaults.tfootSelector.length ) {
  1143. findTableElements($table,'tfoot').each(function () {
  1144. result.push.apply(result, findTableElements($(this), defaults.tfootSelector).toArray());
  1145. });
  1146. }
  1147. return result;
  1148. }
  1149. function findTableElements ($parent, selector) {
  1150. var parentSelector = $parent[0].tagName;
  1151. var parentLevel = $parent.parents(parentSelector).length;
  1152. return $parent.find(selector).filter (function () {
  1153. return parentLevel === $(this).closest(parentSelector).parents(parentSelector).length;
  1154. });
  1155. }
  1156. function GetColumnNames (table) {
  1157. var result = [];
  1158. $(table).find('thead').first().find('th').each(function (index, el) {
  1159. if ( $(el).attr("data-field") !== undefined )
  1160. result[index] = $(el).attr("data-field");
  1161. else
  1162. result[index] = index.toString();
  1163. });
  1164. return result;
  1165. }
  1166. function isVisible ($element) {
  1167. var isCell = typeof $element[0].cellIndex !== 'undefined';
  1168. var isRow = typeof $element[0].rowIndex !== 'undefined';
  1169. var isElementVisible = (isCell || isRow) ? isTableElementVisible($element) : $element.is(':visible');
  1170. var tableexportDisplay = $element.data("tableexport-display");
  1171. if (isCell && tableexportDisplay !== 'none' && tableexportDisplay !== 'always') {
  1172. $element = $($element[0].parentNode);
  1173. isRow = typeof $element[0].rowIndex !== 'undefined';
  1174. tableexportDisplay = $element.data("tableexport-display");
  1175. }
  1176. if (isRow && tableexportDisplay !== 'none' && tableexportDisplay !== 'always') {
  1177. tableexportDisplay = $element.closest('table').data("tableexport-display");
  1178. }
  1179. return tableexportDisplay !== 'none' && (isElementVisible === true || tableexportDisplay === 'always');
  1180. }
  1181. function isTableElementVisible ($element) {
  1182. var hiddenEls = [];
  1183. if ( checkCellVisibilty ) {
  1184. hiddenEls = $hiddenTableElements.filter (function () {
  1185. var found = false;
  1186. if (this.nodeType === $element[0].nodeType) {
  1187. if (typeof this.rowIndex !== 'undefined' && this.rowIndex === $element[0].rowIndex)
  1188. found = true;
  1189. else if (typeof this.cellIndex !== 'undefined' && this.cellIndex === $element[0].cellIndex &&
  1190. typeof this.parentNode.rowIndex !== 'undefined' &&
  1191. typeof $element[0].parentNode.rowIndex !== 'undefined' &&
  1192. this.parentNode.rowIndex === $element[0].parentNode.rowIndex)
  1193. found = true;
  1194. }
  1195. return found;
  1196. });
  1197. }
  1198. return (checkCellVisibilty === false || hiddenEls.length === 0);
  1199. }
  1200. function isColumnIgnored ($cell, rowLength, colIndex) {
  1201. var result = false;
  1202. if (isVisible($cell)) {
  1203. if ( defaults.ignoreColumn.length > 0 ) {
  1204. if ( $.inArray(colIndex, defaults.ignoreColumn) !== -1 ||
  1205. $.inArray(colIndex - rowLength, defaults.ignoreColumn) !== -1 ||
  1206. (colNames.length > colIndex && typeof colNames[colIndex] !== 'undefined' &&
  1207. $.inArray(colNames[colIndex], defaults.ignoreColumn) !== -1) )
  1208. result = true;
  1209. }
  1210. }
  1211. else
  1212. result = true;
  1213. return result;
  1214. }
  1215. function ForEachVisibleCell (tableRow, selector, rowIndex, rowCount, cellcallback) {
  1216. if ( typeof (cellcallback) === 'function' ) {
  1217. var ignoreRow = false;
  1218. if (typeof defaults.onIgnoreRow === 'function')
  1219. ignoreRow = defaults.onIgnoreRow($(tableRow), rowIndex);
  1220. if (ignoreRow === false &&
  1221. $.inArray(rowIndex, defaults.ignoreRow) === -1 &&
  1222. $.inArray(rowIndex - rowCount, defaults.ignoreRow) === -1 &&
  1223. isVisible($(tableRow))) {
  1224. var $cells = findTableElements($(tableRow), selector);
  1225. var cellCount = 0;
  1226. $cells.each(function (colIndex) {
  1227. var $cell = $(this);
  1228. var c;
  1229. var colspan = getColspan (this);
  1230. var rowspan = getRowspan (this);
  1231. // Skip ranges
  1232. $.each(ranges, function () {
  1233. var range = this;
  1234. if ( rowIndex >= range.s.r && rowIndex <= range.e.r && cellCount >= range.s.c && cellCount <= range.e.c ) {
  1235. for ( c = 0; c <= range.e.c - range.s.c; ++c )
  1236. cellcallback(null, rowIndex, cellCount++);
  1237. }
  1238. });
  1239. if ( isColumnIgnored($cell, $cells.length, colIndex) === false ) {
  1240. // Handle Row Span
  1241. if ( rowspan || colspan ) {
  1242. rowspan = rowspan || 1;
  1243. colspan = colspan || 1;
  1244. ranges.push({
  1245. s: {r: rowIndex, c: cellCount},
  1246. e: {r: rowIndex + rowspan - 1, c: cellCount + colspan - 1}
  1247. });
  1248. }
  1249. // Handle Value
  1250. cellcallback(this, rowIndex, cellCount++);
  1251. }
  1252. // Handle Colspan
  1253. if ( colspan )
  1254. for ( c = 0; c < colspan - 1; ++c )
  1255. cellcallback(null, rowIndex, cellCount++);
  1256. });
  1257. // Skip ranges
  1258. $.each(ranges, function () {
  1259. var range = this;
  1260. if ( rowIndex >= range.s.r && rowIndex <= range.e.r && cellCount >= range.s.c && cellCount <= range.e.c ) {
  1261. for ( c = 0; c <= range.e.c - range.s.c; ++c )
  1262. cellcallback(null, rowIndex, cellCount++);
  1263. }
  1264. });
  1265. }
  1266. }
  1267. }
  1268. function jsPdfDrawImage (cell, container, imgId, teOptions) {
  1269. if ( typeof teOptions.images !== 'undefined' ) {
  1270. var image = teOptions.images[imgId];
  1271. if ( typeof image !== 'undefined' ) {
  1272. var r = container.getBoundingClientRect();
  1273. var arCell = cell.width / cell.height;
  1274. var arImg = r.width / r.height;
  1275. var imgWidth = cell.width;
  1276. var imgHeight = cell.height;
  1277. var px2pt = 0.264583 * 72 / 25.4;
  1278. var uy = 0;
  1279. if ( arImg <= arCell ) {
  1280. imgHeight = Math.min(cell.height, r.height);
  1281. imgWidth = r.width * imgHeight / r.height;
  1282. }
  1283. else if ( arImg > arCell ) {
  1284. imgWidth = Math.min(cell.width, r.width);
  1285. imgHeight = r.height * imgWidth / r.width;
  1286. }
  1287. imgWidth *= px2pt;
  1288. imgHeight *= px2pt;
  1289. if ( imgHeight < cell.height )
  1290. uy = (cell.height - imgHeight) / 2;
  1291. try {
  1292. teOptions.doc.addImage(image.src, cell.textPos.x, cell.y + uy, imgWidth, imgHeight);
  1293. }
  1294. catch (e) {
  1295. // TODO: IE -> convert png to jpeg
  1296. }
  1297. cell.textPos.x += imgWidth;
  1298. }
  1299. }
  1300. }
  1301. function jsPdfOutput (doc, hasimages) {
  1302. if ( defaults.outputMode === 'string' )
  1303. return doc.output();
  1304. if ( defaults.outputMode === 'base64' )
  1305. return base64encode(doc.output());
  1306. if ( defaults.outputMode === 'window' ) {
  1307. window.URL = window.URL || window.webkitURL;
  1308. window.open(window.URL.createObjectURL(doc.output("blob")));
  1309. return;
  1310. }
  1311. try {
  1312. var blob = doc.output('blob');
  1313. saveAs(blob, defaults.fileName + '.pdf');
  1314. }
  1315. catch (e) {
  1316. downloadFile(defaults.fileName + '.pdf',
  1317. 'data:application/pdf' + (hasimages ? '' : ';base64') + ',',
  1318. hasimages ? doc.output('blob') : doc.output());
  1319. }
  1320. }
  1321. function prepareAutoTableText (cell, data, cellopt) {
  1322. var cs = 0;
  1323. if ( typeof cellopt !== 'undefined' )
  1324. cs = cellopt.colspan;
  1325. if ( cs >= 0 ) {
  1326. // colspan handling
  1327. var cellWidth = cell.width;
  1328. var textPosX = cell.textPos.x;
  1329. var i = data.table.columns.indexOf(data.column);
  1330. for ( var c = 1; c < cs; c++ ) {
  1331. var column = data.table.columns[i + c];
  1332. cellWidth += column.width;
  1333. }
  1334. if ( cs > 1 ) {
  1335. if ( cell.styles.halign === 'right' )
  1336. textPosX = cell.textPos.x + cellWidth - cell.width;
  1337. else if ( cell.styles.halign === 'center' )
  1338. textPosX = cell.textPos.x + (cellWidth - cell.width) / 2;
  1339. }
  1340. cell.width = cellWidth;
  1341. cell.textPos.x = textPosX;
  1342. if ( typeof cellopt !== 'undefined' && cellopt.rowspan > 1 )
  1343. cell.height = cell.height * cellopt.rowspan;
  1344. // fix jsPDF's calculation of text position
  1345. if ( cell.styles.valign === 'middle' || cell.styles.valign === 'bottom' ) {
  1346. var splittedText = typeof cell.text === 'string' ? cell.text.split(/\r\n|\r|\n/g) : cell.text;
  1347. var lineCount = splittedText.length || 1;
  1348. if ( lineCount > 2 )
  1349. cell.textPos.y -= ((2 - FONT_ROW_RATIO) / 2 * data.row.styles.fontSize) * (lineCount - 2) / 3;
  1350. }
  1351. return true;
  1352. }
  1353. else
  1354. return false; // cell is hidden (colspan = -1), don't draw it
  1355. }
  1356. function collectImages (cell, elements, teOptions) {
  1357. if ( typeof cell !== 'undefined' && cell !== null ) {
  1358. if ( cell.hasAttribute("data-tableexport-canvas") ) {
  1359. var imgId = new Date().getTime();
  1360. $(cell).attr("data-tableexport-canvas", imgId);
  1361. teOptions.images[imgId] = {
  1362. url: '[data-tableexport-canvas="'+imgId+'"]',
  1363. src: null
  1364. };
  1365. }
  1366. else if (elements !== 'undefined' && elements != null) {
  1367. elements.each(function () {
  1368. if ($(this).is("img")) {
  1369. var imgId = strHashCode(this.src);
  1370. teOptions.images[imgId] = {
  1371. url: this.src,
  1372. src: this.src
  1373. };
  1374. }
  1375. collectImages(cell, $(this).children(), teOptions);
  1376. });
  1377. }
  1378. }
  1379. }
  1380. function loadImages (teOptions, callback) {
  1381. var imageCount = 0;
  1382. var pendingCount = 0;
  1383. function done () {
  1384. callback(imageCount);
  1385. }
  1386. function loadImage (image) {
  1387. if (image.url) {
  1388. if (!image.src) {
  1389. var $imgContainer = $(image.url);
  1390. if ($imgContainer.length) {
  1391. imageCount = ++pendingCount;
  1392. html2canvas($imgContainer[0]).then(function(canvas) {
  1393. image.src = canvas.toDataURL("image/png");
  1394. if ( !--pendingCount )
  1395. done();
  1396. });
  1397. }
  1398. }
  1399. else {
  1400. var img = new Image();
  1401. imageCount = ++pendingCount;
  1402. img.crossOrigin = 'Anonymous';
  1403. img.onerror = img.onload = function () {
  1404. if ( img.complete ) {
  1405. if ( img.src.indexOf('data:image/') === 0 ) {
  1406. img.width = image.width || img.width || 0;
  1407. img.height = image.height || img.height || 0;
  1408. }
  1409. if ( img.width + img.height ) {
  1410. var canvas = document.createElement("canvas");
  1411. var ctx = canvas.getContext("2d");
  1412. canvas.width = img.width;
  1413. canvas.height = img.height;
  1414. ctx.drawImage(img, 0, 0);
  1415. image.src = canvas.toDataURL("image/png");
  1416. }
  1417. }
  1418. if ( !--pendingCount )
  1419. done();
  1420. };
  1421. img.src = image.url;
  1422. }
  1423. }
  1424. }
  1425. if ( typeof teOptions.images !== 'undefined' ) {
  1426. for ( var i in teOptions.images )
  1427. if ( teOptions.images.hasOwnProperty(i) )
  1428. loadImage(teOptions.images[i]);
  1429. }
  1430. return pendingCount || done();
  1431. }
  1432. function drawAutotableElements (cell, elements, teOptions) {
  1433. elements.each(function () {
  1434. if ( $(this).is("div") ) {
  1435. var bcolor = rgb2array(getStyle(this, 'background-color'), [255, 255, 255]);
  1436. var lcolor = rgb2array(getStyle(this, 'border-top-color'), [0, 0, 0]);
  1437. var lwidth = getPropertyUnitValue(this, 'border-top-width', defaults.jspdf.unit);
  1438. var r = this.getBoundingClientRect();
  1439. var ux = this.offsetLeft * teOptions.wScaleFactor;
  1440. var uy = this.offsetTop * teOptions.hScaleFactor;
  1441. var uw = r.width * teOptions.wScaleFactor;
  1442. var uh = r.height * teOptions.hScaleFactor;
  1443. teOptions.doc.setDrawColor.apply(undefined, lcolor);
  1444. teOptions.doc.setFillColor.apply(undefined, bcolor);
  1445. teOptions.doc.setLineWidth(lwidth);
  1446. teOptions.doc.rect(cell.x + ux, cell.y + uy, uw, uh, lwidth ? "FD" : "F");
  1447. }
  1448. else if ( $(this).is("img") ) {
  1449. var imgId = strHashCode(this.src);
  1450. jsPdfDrawImage (cell, this, imgId, teOptions);
  1451. }
  1452. drawAutotableElements(cell, $(this).children(), teOptions);
  1453. });
  1454. }
  1455. function drawAutotableText (cell, texttags, teOptions) {
  1456. if ( typeof teOptions.onAutotableText === 'function' ) {
  1457. teOptions.onAutotableText(teOptions.doc, cell, texttags);
  1458. }
  1459. else {
  1460. var x = cell.textPos.x;
  1461. var y = cell.textPos.y;
  1462. var style = {halign: cell.styles.halign, valign: cell.styles.valign};
  1463. if ( texttags.length ) {
  1464. var tag = texttags[0];
  1465. while ( tag.previousSibling )
  1466. tag = tag.previousSibling;
  1467. var b = false, i = false;
  1468. while ( tag ) {
  1469. var txt = tag.innerText || tag.textContent || "";
  1470. var leadingspace = (txt.length && txt[0] === " ") ? " " : "";
  1471. var trailingspace = (txt.length > 1 && txt[txt.length - 1] === " ") ? " " : "";
  1472. if (defaults.preserve.leadingWS !== true)
  1473. txt = leadingspace + trimLeft(txt);
  1474. if (defaults.preserve.trailingWS !== true)
  1475. txt = trimRight(txt) + trailingspace;
  1476. if ( $(tag).is("br") ) {
  1477. x = cell.textPos.x;
  1478. y += teOptions.doc.internal.getFontSize();
  1479. }
  1480. if ( $(tag).is("b") )
  1481. b = true;
  1482. else if ( $(tag).is("i") )
  1483. i = true;
  1484. if ( b || i )
  1485. teOptions.doc.setFontType((b && i) ? "bolditalic" : b ? "bold" : "italic");
  1486. var w = teOptions.doc.getStringUnitWidth(txt) * teOptions.doc.internal.getFontSize();
  1487. if ( w ) {
  1488. if ( cell.styles.overflow === 'linebreak' &&
  1489. x > cell.textPos.x && (x + w) > (cell.textPos.x + cell.width) ) {
  1490. var chars = ".,!%*;:=-";
  1491. if ( chars.indexOf(txt.charAt(0)) >= 0 ) {
  1492. var s = txt.charAt(0);
  1493. w = teOptions.doc.getStringUnitWidth(s) * teOptions.doc.internal.getFontSize();
  1494. if ( (x + w) <= (cell.textPos.x + cell.width) ) {
  1495. teOptions.doc.autoTableText(s, x, y, style);
  1496. txt = txt.substring(1, txt.length);
  1497. }
  1498. w = teOptions.doc.getStringUnitWidth(txt) * teOptions.doc.internal.getFontSize();
  1499. }
  1500. x = cell.textPos.x;
  1501. y += teOptions.doc.internal.getFontSize();
  1502. }
  1503. if ( cell.styles.overflow !== 'visible' ) {
  1504. while ( txt.length && (x + w) > (cell.textPos.x + cell.width) ) {
  1505. txt = txt.substring(0, txt.length - 1);
  1506. w = teOptions.doc.getStringUnitWidth(txt) * teOptions.doc.internal.getFontSize();
  1507. }
  1508. }
  1509. teOptions.doc.autoTableText(txt, x, y, style);
  1510. x += w;
  1511. }
  1512. if ( b || i ) {
  1513. if ( $(tag).is("b") )
  1514. b = false;
  1515. else if ( $(tag).is("i") )
  1516. i = false;
  1517. teOptions.doc.setFontType((!b && !i) ? "normal" : b ? "bold" : "italic");
  1518. }
  1519. tag = tag.nextSibling;
  1520. }
  1521. cell.textPos.x = x;
  1522. cell.textPos.y = y;
  1523. }
  1524. else {
  1525. teOptions.doc.autoTableText(cell.text, cell.textPos.x, cell.textPos.y, style);
  1526. }
  1527. }
  1528. }
  1529. function escapeRegExp (string) {
  1530. return string == null ? "" : string.toString().replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
  1531. }
  1532. function replaceAll (string, find, replace) {
  1533. return string == null ? "" : string.toString().replace(new RegExp(escapeRegExp(find), 'g'), replace);
  1534. }
  1535. function trimLeft (string) {
  1536. return string == null ? "" : string.toString().replace(/^\s+/, "");
  1537. }
  1538. function trimRight (string) {
  1539. return string == null ? "" : string.toString().replace(/\s+$/, "");
  1540. }
  1541. function parseNumber (value) {
  1542. value = value || "0";
  1543. value = replaceAll(value, defaults.numbers.html.thousandsSeparator, '');
  1544. value = replaceAll(value, defaults.numbers.html.decimalMark, '.');
  1545. return typeof value === "number" || jQuery.isNumeric(value) !== false ? value : false;
  1546. }
  1547. function parsePercent (value) {
  1548. if ( value.indexOf("%") > -1 ) {
  1549. value = parseNumber(value.replace(/%/g, ""));
  1550. if ( value !== false )
  1551. value = value / 100;
  1552. }
  1553. else
  1554. value = false;
  1555. return value;
  1556. }
  1557. function parseString (cell, rowIndex, colIndex) {
  1558. var result = '';
  1559. if ( cell !== null ) {
  1560. var $cell = $(cell);
  1561. var htmlData;
  1562. if ( $cell[0].hasAttribute("data-tableexport-canvas") ) {
  1563. htmlData = '';
  1564. }
  1565. else if ( $cell[0].hasAttribute("data-tableexport-value") ) {
  1566. htmlData = $cell.data("tableexport-value");
  1567. htmlData = htmlData ? htmlData + '' : '';
  1568. }
  1569. else {
  1570. htmlData = $cell.html();
  1571. if ( typeof defaults.onCellHtmlData === 'function' )
  1572. htmlData = defaults.onCellHtmlData($cell, rowIndex, colIndex, htmlData);
  1573. else if ( htmlData !== '' ) {
  1574. var html = $.parseHTML(htmlData);
  1575. var inputidx = 0;
  1576. var selectidx = 0;
  1577. htmlData = '';
  1578. $.each(html, function () {
  1579. if ( $(this).is("input") )
  1580. htmlData += $cell.find('input').eq(inputidx++).val();
  1581. else if ( $(this).is("select") )
  1582. htmlData += $cell.find('select option:selected').eq(selectidx++).text();
  1583. else if ( $(this).is("br") )
  1584. htmlData += "<br>";
  1585. else {
  1586. if ( typeof $(this).html() === 'undefined' )
  1587. htmlData += $(this).text();
  1588. else if ( jQuery().bootstrapTable === undefined ||
  1589. ($(this).hasClass('filterControl') !== true &&
  1590. $(cell).parents('.detail-view').length === 0) )
  1591. htmlData += $(this).html();
  1592. }
  1593. });
  1594. }
  1595. }
  1596. if ( defaults.htmlContent === true ) {
  1597. result = $.trim(htmlData);
  1598. }
  1599. else if ( htmlData && htmlData !== '' ) {
  1600. var cellFormat = $(cell).data("tableexport-cellformat");
  1601. if ( cellFormat !== '' ) {
  1602. var text = htmlData.replace(/\n/g, '\u2028').replace(/(<\s*br([^>]*)>)/gi, '\u2060');
  1603. var obj = $('<div/>').html(text).contents();
  1604. var number = false;
  1605. text = '';
  1606. $.each(obj.text().split("\u2028"), function (i, v) {
  1607. if ( i > 0 )
  1608. text += " ";
  1609. if (defaults.preserve.leadingWS !== true)
  1610. v = trimLeft(v);
  1611. text += (defaults.preserve.trailingWS !== true) ? trimRight(v) : v;
  1612. });
  1613. $.each(text.split("\u2060"), function (i, v) {
  1614. if ( i > 0 )
  1615. result += "\n";
  1616. if (defaults.preserve.leadingWS !== true)
  1617. v = trimLeft(v);
  1618. if (defaults.preserve.trailingWS !== true)
  1619. v = trimRight(v);
  1620. result += v.replace(/\u00AD/g, ""); // remove soft hyphens
  1621. });
  1622. result = result.replace(/\u00A0/g, " "); // replace nbsp's with spaces
  1623. if ( defaults.type === 'json' ||
  1624. (defaults.type === 'excel' && defaults.mso.fileFormat === 'xmlss') ||
  1625. defaults.numbers.output === false ) {
  1626. number = parseNumber(result);
  1627. if ( number !== false )
  1628. result = Number(number);
  1629. }
  1630. else if ( defaults.numbers.html.decimalMark !== defaults.numbers.output.decimalMark ||
  1631. defaults.numbers.html.thousandsSeparator !== defaults.numbers.output.thousandsSeparator ) {
  1632. number = parseNumber(result);
  1633. if ( number !== false ) {
  1634. var frac = ("" + number.substr(number < 0 ? 1 : 0)).split('.');
  1635. if ( frac.length === 1 )
  1636. frac[1] = "";
  1637. var mod = frac[0].length > 3 ? frac[0].length % 3 : 0;
  1638. result = (number < 0 ? "-" : "") +
  1639. (defaults.numbers.output.thousandsSeparator ? ((mod ? frac[0].substr(0, mod) + defaults.numbers.output.thousandsSeparator : "") + frac[0].substr(mod).replace(/(\d{3})(?=\d)/g, "$1" + defaults.numbers.output.thousandsSeparator)) : frac[0]) +
  1640. (frac[1].length ? defaults.numbers.output.decimalMark + frac[1] : "");
  1641. }
  1642. }
  1643. }
  1644. else
  1645. result = htmlData;
  1646. }
  1647. if ( defaults.escape === true ) {
  1648. //noinspection JSDeprecatedSymbols
  1649. result = escape(result);
  1650. }
  1651. if ( typeof defaults.onCellData === 'function' ) {
  1652. result = defaults.onCellData($cell, rowIndex, colIndex, result);
  1653. }
  1654. }
  1655. return result;
  1656. }
  1657. function preventInjection (string) {
  1658. if ( string.length > 0 && defaults.preventInjection === true ) {
  1659. var chars = "=+-@";
  1660. if ( chars.indexOf(string.charAt(0)) >= 0 )
  1661. return ( "'" + string );
  1662. }
  1663. return string;
  1664. }
  1665. //noinspection JSUnusedLocalSymbols
  1666. function hyphenate (a, b, c) {
  1667. return b + "-" + c.toLowerCase();
  1668. }
  1669. function rgb2array (rgb_string, default_result) {
  1670. var re = /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/;
  1671. var bits = re.exec(rgb_string);
  1672. var result = default_result;
  1673. if ( bits )
  1674. result = [parseInt(bits[1]), parseInt(bits[2]), parseInt(bits[3])];
  1675. return result;
  1676. }
  1677. function getCellStyles (cell) {
  1678. var a = getStyle(cell, 'text-align');
  1679. var fw = getStyle(cell, 'font-weight');
  1680. var fs = getStyle(cell, 'font-style');
  1681. var f = '';
  1682. if ( a === 'start' )
  1683. a = getStyle(cell, 'direction') === 'rtl' ? 'right' : 'left';
  1684. if ( fw >= 700 )
  1685. f = 'bold';
  1686. if ( fs === 'italic' )
  1687. f += fs;
  1688. if ( f === '' )
  1689. f = 'normal';
  1690. var result = {
  1691. style: {
  1692. align: a,
  1693. bcolor: rgb2array(getStyle(cell, 'background-color'), [255, 255, 255]),
  1694. color: rgb2array(getStyle(cell, 'color'), [0, 0, 0]),
  1695. fstyle: f
  1696. },
  1697. colspan: getColspan (cell),
  1698. rowspan: getRowspan (cell)
  1699. };
  1700. if ( cell !== null ) {
  1701. var r = cell.getBoundingClientRect();
  1702. result.rect = {
  1703. width: r.width,
  1704. height: r.height
  1705. };
  1706. }
  1707. return result;
  1708. }
  1709. function getColspan (cell) {
  1710. var result = $(cell).data("tableexport-colspan");
  1711. if ( typeof result === 'undefined' && $(cell).is("[colspan]") )
  1712. result = $(cell).attr('colspan');
  1713. return (parseInt(result) || 0);
  1714. }
  1715. function getRowspan (cell) {
  1716. var result = $(cell).data("tableexport-rowspan");
  1717. if ( typeof result === 'undefined' && $(cell).is("[rowspan]") )
  1718. result = $(cell).attr('rowspan');
  1719. return (parseInt(result) || 0);
  1720. }
  1721. // get computed style property
  1722. function getStyle (target, prop) {
  1723. try {
  1724. if ( window.getComputedStyle ) { // gecko and webkit
  1725. prop = prop.replace(/([a-z])([A-Z])/, hyphenate); // requires hyphenated, not camel
  1726. return window.getComputedStyle(target, null).getPropertyValue(prop);
  1727. }
  1728. if ( target.currentStyle ) { // ie
  1729. return target.currentStyle[prop];
  1730. }
  1731. return target.style[prop];
  1732. }
  1733. catch (e) {
  1734. }
  1735. return "";
  1736. }
  1737. function getUnitValue (parent, value, unit) {
  1738. var baseline = 100; // any number serves
  1739. var temp = document.createElement("div"); // create temporary element
  1740. temp.style.overflow = "hidden"; // in case baseline is set too low
  1741. temp.style.visibility = "hidden"; // no need to show it
  1742. parent.appendChild(temp); // insert it into the parent for em, ex and %
  1743. temp.style.width = baseline + unit;
  1744. var factor = baseline / temp.offsetWidth;
  1745. parent.removeChild(temp); // clean up
  1746. return (value * factor);
  1747. }
  1748. function getPropertyUnitValue (target, prop, unit) {
  1749. var value = getStyle(target, prop); // get the computed style value
  1750. var numeric = value.match(/\d+/); // get the numeric component
  1751. if ( numeric !== null ) {
  1752. numeric = numeric[0]; // get the string
  1753. return getUnitValue(target.parentElement, numeric, unit);
  1754. }
  1755. return 0;
  1756. }
  1757. function jx_Workbook () {
  1758. if ( !(this instanceof jx_Workbook) ) {
  1759. //noinspection JSPotentiallyInvalidConstructorUsage
  1760. return new jx_Workbook();
  1761. }
  1762. this.SheetNames = [];
  1763. this.Sheets = {};
  1764. }
  1765. function jx_s2ab (s) {
  1766. var buf = new ArrayBuffer(s.length);
  1767. var view = new Uint8Array(buf);
  1768. for ( var i = 0; i !== s.length; ++i ) view[i] = s.charCodeAt(i) & 0xFF;
  1769. return buf;
  1770. }
  1771. function jx_datenum (v, date1904) {
  1772. if ( date1904 ) v += 1462;
  1773. var epoch = Date.parse(v);
  1774. return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);
  1775. }
  1776. function jx_createSheet (data) {
  1777. var ws = {};
  1778. var range = {s: {c: 10000000, r: 10000000}, e: {c: 0, r: 0}};
  1779. for ( var R = 0; R !== data.length; ++R ) {
  1780. for ( var C = 0; C !== data[R].length; ++C ) {
  1781. if ( range.s.r > R ) range.s.r = R;
  1782. if ( range.s.c > C ) range.s.c = C;
  1783. if ( range.e.r < R ) range.e.r = R;
  1784. if ( range.e.c < C ) range.e.c = C;
  1785. var cell = {v: data[R][C]};
  1786. if ( cell.v === null ) continue;
  1787. var cell_ref = XLSX.utils.encode_cell({c: C, r: R});
  1788. if ( typeof cell.v === 'number' ) cell.t = 'n';
  1789. else if ( typeof cell.v === 'boolean' ) cell.t = 'b';
  1790. else if ( cell.v instanceof Date ) {
  1791. cell.t = 'n';
  1792. cell.z = XLSX.SSF._table[14];
  1793. cell.v = jx_datenum(cell.v);
  1794. }
  1795. else cell.t = 's';
  1796. ws[cell_ref] = cell;
  1797. }
  1798. }
  1799. if ( range.s.c < 10000000 ) ws['!ref'] = XLSX.utils.encode_range(range);
  1800. return ws;
  1801. }
  1802. function strHashCode (str) {
  1803. var hash = 0, i, chr, len;
  1804. if ( str.length === 0 ) return hash;
  1805. for ( i = 0, len = str.length; i < len; i++ ) {
  1806. chr = str.charCodeAt(i);
  1807. hash = ((hash << 5) - hash) + chr;
  1808. hash |= 0; // Convert to 32bit integer
  1809. }
  1810. return hash;
  1811. }
  1812. function saveToFile (data, fileName, type, charset, encoding, bom) {
  1813. var saveIt = true;
  1814. if ( typeof defaults.onBeforeSaveToFile === 'function' ) {
  1815. saveIt = defaults.onBeforeSaveToFile(data, fileName, type, charset, encoding);
  1816. if ( typeof saveIt !== 'boolean' )
  1817. saveIt = true;
  1818. }
  1819. if (saveIt) {
  1820. try {
  1821. blob = new Blob([data], {type: type + ';charset=' + charset});
  1822. saveAs (blob, fileName, bom === false);
  1823. if ( typeof defaults.onAfterSaveToFile === 'function' )
  1824. defaults.onAfterSaveToFile(data, fileName);
  1825. }
  1826. catch (e) {
  1827. downloadFile (fileName,
  1828. 'data:' + type +
  1829. (charset.length ? ';charset=' + charset : '') +
  1830. (encoding.length ? ';' + encoding : '') + ',' + (bom ? '\ufeff' : ''),
  1831. data);
  1832. }
  1833. }
  1834. }
  1835. function downloadFile (filename, header, data) {
  1836. var ua = window.navigator.userAgent;
  1837. if ( filename !== false && window.navigator.msSaveOrOpenBlob ) {
  1838. //noinspection JSUnresolvedFunction
  1839. window.navigator.msSaveOrOpenBlob(new Blob([data]), filename);
  1840. }
  1841. else if ( filename !== false && (ua.indexOf("MSIE ") > 0 || !!ua.match(/Trident.*rv\:11\./)) ) {
  1842. // Internet Explorer (<= 9) workaround by Darryl (https://github.com/dawiong/tableExport.jquery.plugin)
  1843. // based on sampopes answer on http://stackoverflow.com/questions/22317951
  1844. // ! Not working for json and pdf format !
  1845. var frame = document.createElement("iframe");
  1846. if ( frame ) {
  1847. document.body.appendChild(frame);
  1848. frame.setAttribute("style", "display:none");
  1849. frame.contentDocument.open("txt/plain", "replace");
  1850. frame.contentDocument.write(data);
  1851. frame.contentDocument.close();
  1852. frame.contentDocument.focus();
  1853. var extension = filename.substr((filename.lastIndexOf('.') +1));
  1854. switch(extension) {
  1855. case 'doc': case 'json': case 'png': case 'pdf': case 'xls': case 'xlsx':
  1856. filename += ".txt";
  1857. break;
  1858. }
  1859. frame.contentDocument.execCommand("SaveAs", true, filename);
  1860. document.body.removeChild(frame);
  1861. }
  1862. }
  1863. else {
  1864. var DownloadLink = document.createElement('a');
  1865. if ( DownloadLink ) {
  1866. var blobUrl = null;
  1867. DownloadLink.style.display = 'none';
  1868. if ( filename !== false )
  1869. DownloadLink.download = filename;
  1870. else
  1871. DownloadLink.target = '_blank';
  1872. if ( typeof data === 'object' ) {
  1873. window.URL = window.URL || window.webkitURL;
  1874. var binaryData = [];
  1875. binaryData.push(data);
  1876. blobUrl = window.URL.createObjectURL(new Blob(binaryData, {type: header}));
  1877. DownloadLink.href = blobUrl;
  1878. }
  1879. else if ( header.toLowerCase().indexOf("base64,") >= 0 )
  1880. DownloadLink.href = header + base64encode(data);
  1881. else
  1882. DownloadLink.href = header + encodeURIComponent(data);
  1883. document.body.appendChild(DownloadLink);
  1884. if ( document.createEvent ) {
  1885. if ( DownloadEvt === null )
  1886. DownloadEvt = document.createEvent('MouseEvents');
  1887. DownloadEvt.initEvent('click', true, false);
  1888. DownloadLink.dispatchEvent(DownloadEvt);
  1889. }
  1890. else if ( document.createEventObject )
  1891. DownloadLink.fireEvent('onclick');
  1892. else if ( typeof DownloadLink.onclick === 'function' )
  1893. DownloadLink.onclick();
  1894. setTimeout(function(){
  1895. if ( blobUrl )
  1896. window.URL.revokeObjectURL(blobUrl);
  1897. document.body.removeChild(DownloadLink);
  1898. if ( typeof defaults.onAfterSaveToFile === 'function' )
  1899. defaults.onAfterSaveToFile(data, filename);
  1900. }, 100);
  1901. }
  1902. }
  1903. }
  1904. function utf8Encode (text) {
  1905. if (typeof text === 'string') {
  1906. text = text.replace(/\x0d\x0a/g, "\x0a");
  1907. var utftext = "";
  1908. for ( var n = 0; n < text.length; n++ ) {
  1909. var c = text.charCodeAt(n);
  1910. if ( c < 128 ) {
  1911. utftext += String.fromCharCode(c);
  1912. }
  1913. else if ( (c > 127) && (c < 2048) ) {
  1914. utftext += String.fromCharCode((c >> 6) | 192);
  1915. utftext += String.fromCharCode((c & 63) | 128);
  1916. }
  1917. else {
  1918. utftext += String.fromCharCode((c >> 12) | 224);
  1919. utftext += String.fromCharCode(((c >> 6) & 63) | 128);
  1920. utftext += String.fromCharCode((c & 63) | 128);
  1921. }
  1922. }
  1923. return utftext;
  1924. }
  1925. return text;
  1926. }
  1927. function base64encode (input) {
  1928. var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
  1929. var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
  1930. var output = "";
  1931. var i = 0;
  1932. input = utf8Encode(input);
  1933. while ( i < input.length ) {
  1934. chr1 = input.charCodeAt(i++);
  1935. chr2 = input.charCodeAt(i++);
  1936. chr3 = input.charCodeAt(i++);
  1937. enc1 = chr1 >> 2;
  1938. enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
  1939. enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
  1940. enc4 = chr3 & 63;
  1941. if ( isNaN(chr2) ) {
  1942. enc3 = enc4 = 64;
  1943. } else if ( isNaN(chr3) ) {
  1944. enc4 = 64;
  1945. }
  1946. output = output +
  1947. keyStr.charAt(enc1) + keyStr.charAt(enc2) +
  1948. keyStr.charAt(enc3) + keyStr.charAt(enc4);
  1949. }
  1950. return output;
  1951. }
  1952. return this;
  1953. }
  1954. })(jQuery);