tableExport.js 85 KB

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