ExportTable.js

解决了避免身份证号导出到excel中显示成科学计数法

  1 (function ($) {
  2     $.fn.extend({
  3         tableExport: function (options) {
  4             var defaults = {
  5                 csvSeparator: ',',
  6                 csvEnclosure: '"',
  7                 consoleLog: false,
  8                 displayTableName: false,
  9                 escape: false,
 10                 excelstyles: ['border-bottom', 'border-top', 'border-left', 'border-right'],
 11                 fileName: 'tableExport',
 12                 htmlContent: false,
 13                 ignoreColumn: [],
 14                 jspdf: {
 15                     orientation: 'p',
 16                     unit: 'pt',
 17                     format: 'a4',
 18                     margins: { left: 20, right: 10, top: 10, bottom: 10 },
 19                     autotable: {
 20                         padding: 2,
 21                         lineHeight: 12,
 22                         fontSize: 8,
 23                         tableExport: {
 24                             onAfterAutotable: null,
 25                             onBeforeAutotable: null,
 26                             onTable: null
 27                         }
 28                     }
 29                 },
 30                 onCellData: null,
 31                 outputMode: 'file',  // file|string|base64
 32                 tbodySelector: 'tr',
 33                 theadSelector: 'tr',
 34                 tableName: 'myTableName',
 35                 type: 'csv',
 36                 worksheetName: 'xlsWorksheetName'
 37             };
 38 
 39             var options = $.extend(true, defaults, options);
 40             var el = this;
 41             var DownloadEvt = null;
 42             var rowspans = [];
 43 
 44             if (defaults.type == 'csv' || defaults.type == 'txt') {
 45 
 46                 // Header
 47                 var tdData = "";
 48                 var rowIndex = 0;
 49                 $(el).find('thead').first().find(defaults.theadSelector).each(function () {
 50                     tdData += "
";
 51                     ForEachVisibleCell(this, 'th,td', rowIndex,
 52                         function (cell, row, col) {
 53                             tdData += csvString(cell, row, col) + defaults.csvSeparator;
 54                         });
 55                     rowIndex++;
 56                     tdData = $.trim(tdData);
 57                     tdData = $.trim(tdData).substring(0, tdData.length - 1);
 58                 });
 59 
 60                 // Row vs Column
 61                 $(el).find('tbody').first().find(defaults.tbodySelector).each(function () {
 62                     trData = "";
 63                     ForEachVisibleCell(this, 'td', rowIndex,
 64                         function (cell, row, col) {
 65                             trData += csvString(cell, row, col) + defaults.csvSeparator;
 66                         });
 67                     if (trData.length > defaults.csvSeparator.length)
 68                         tdData += "
" + trData;
 69                     rowIndex++;
 70                     //tdData = $.trim(tdData);
 71                     tdData = $.trim(tdData).substring(0, tdData.length - 1);
 72                 });
 73 
 74                 tdData += "
";
 75 
 76                 //output
 77                 if (defaults.consoleLog === true)
 78                     console.log(tdData);
 79 
 80                 if (defaults.outputMode == 'string')
 81                     return tdData;
 82 
 83                 if (defaults.outputMode == 'base64')
 84                     return base64encode(tdData);
 85 
 86                 try {
 87                     var blob = new Blob([(defaults.type == 'csv' ? 'ufeff' : '') + tdData], { type: "text/" + (defaults.type == 'csv' ? 'csv' : 'plain') + ";charset=utf-8" });
 88                     saveAs(blob, defaults.fileName + '.' + defaults.type);
 89                 }
 90                 catch (e) {
 91                     downloadFile(defaults.fileName + '.' + defaults.type,
 92                         'data:text/' + (defaults.type == 'csv' ? 'csv' : 'plain') + ';charset=utf-8,' + (defaults.type == 'csv' ? 'ufeff' : '') +
 93                         encodeURIComponent(tdData));
 94                 }
 95 
 96             } else if (defaults.type == 'sql') {
 97 
 98                 // Header
 99                 var rowIndex = 0;
100                 var tdData = "INSERT INTO `" + defaults.tableName + "` (";
101                 $(el).find('thead').first().find(defaults.theadSelector).each(function () {
102 
103                     ForEachVisibleCell(this, 'th,td', rowIndex,
104                         function (cell, row, col) {
105                             tdData += "'" + parseString(cell, row, col) + "',";
106                         });
107                     rowIndex++;
108                     tdData = $.trim(tdData);
109                     tdData = $.trim(tdData).substring(0, tdData.length - 1);
110                 });
111                 tdData += ") VALUES ";
112                 // Row vs Column
113                 $(el).find('tbody').first().find(defaults.tbodySelector).each(function () {
114                     trData = "";
115                     ForEachVisibleCell(this, 'td', rowIndex,
116                         function (cell, row, col) {
117                             trData += "'" + parseString(cell, row, col) + "',";
118                         });
119                     if (trData.length > 3) {
120                         tdData += "(" + trData;
121                         tdData = $.trim(tdData).substring(0, tdData.length - 1);
122                         tdData += "),";
123                     }
124                     rowIndex++;
125                 });
126 
127                 tdData = $.trim(tdData).substring(0, tdData.length - 1);
128                 tdData += ";";
129 
130                 //output
131                 if (defaults.consoleLog === true)
132                     console.log(tdData);
133 
134                 if (defaults.outputMode == 'string')
135                     return tdData;
136 
137                 if (defaults.outputMode == 'base64')
138                     return base64encode(tdData);
139 
140                 try {
141                     var blob = new Blob([tdData], { type: "text/plain;charset=utf-8" });
142                     saveAs(blob, defaults.fileName + '.sql');
143                 }
144                 catch (e) {
145                     downloadFile(defaults.fileName + '.sql', 'data:application/sql;charset=utf-8,' + encodeURIComponent(tdData));
146                 }
147 
148             } else if (defaults.type == 'json') {
149 
150                 var jsonHeaderArray = [];
151                 $(el).find('thead').first().find(defaults.theadSelector).each(function () {
152                     var tdData = "";
153                     var jsonArrayTd = [];
154                     var rowIndex = 0;
155 
156                     ForEachVisibleCell(this, 'th,td', rowIndex,
157                         function (cell, row, col) {
158                             jsonArrayTd.push(parseString(cell, row, col));
159                         });
160                     jsonHeaderArray.push(jsonArrayTd);
161 
162                     rowIndex++;
163                 });
164 
165                 var jsonArray = [];
166                 $(el).find('tbody').first().find(defaults.tbodySelector).each(function () {
167                     var tdData = "";
168                     var jsonArrayTd = [];
169 
170                     ForEachVisibleCell(this, 'td', rowIndex,
171                         function (cell, row, col) {
172                             jsonArrayTd.push(parseString(cell, row, col));
173                         });
174 
175                     if (jsonArrayTd.length > 0 && (jsonArrayTd.length != 1 || jsonArrayTd[0] != ""))
176                         jsonArray.push(jsonArrayTd);
177 
178                     rowIndex++;
179                 });
180 
181                 var jsonExportArray = [];
182                 jsonExportArray.push({ header: jsonHeaderArray, data: jsonArray });
183 
184                 var sdata = JSON.stringify(jsonExportArray);
185 
186                 if (defaults.consoleLog === true)
187                     console.log(sdata);
188 
189                 if (defaults.outputMode == 'string')
190                     return sdata;
191 
192                 var base64data = base64encode(sdata);
193 
194                 if (defaults.outputMode == 'base64')
195                     return base64data;
196 
197                 try {
198                     var blob = new Blob([sdata], { type: "application/json;charset=utf-8" });
199                     saveAs(blob, defaults.fileName + '.json');
200                 }
201                 catch (e) {
202                     downloadFile(defaults.fileName + '.json', 'data:application/json;charset=utf-8;base64,' + base64data);
203                 }
204 
205             } else if (defaults.type == 'xml') {
206 
207                 var rowIndex = 0;
208                 var xml = '<?xml version="1.0" encoding="utf-8"?>';
209                 xml += '<tabledata><fields>';
210 
211                 // Header
212                 $(el).find('thead').first().find(defaults.theadSelector).each(function () {
213 
214                     ForEachVisibleCell(this, 'th,td', rowIndex,
215                         function (cell, row, col) {
216                             xml += "<field>" + parseString(cell, row, col) + "</field>";
217                         });
218                     rowIndex++;
219                 });
220                 xml += '</fields><data>';
221 
222                 // Row Vs Column
223                 var rowCount = 1;
224                 $(el).find('tbody').first().find(defaults.tbodySelector).each(function () {
225                     var colCount = 1;
226                     var rxml = "";
227                     ForEachVisibleCell(this, 'td', rowIndex,
228                         function (cell, row, col) {
229                             rxml += "<column-" + colCount + ">" + parseString(cell, row, col) + "</column-" + colCount + ">";
230                             colCount++;
231                         });
232                     if (rxml != "<column-1></column-1>") {
233                         xml += '<row >;
234                         rowCount++;
235                     }
236 
237                     rowIndex++;
238                 });
239                 xml += '</data></tabledata>'
240 
241                 //output
242                 if (defaults.consoleLog === true)
243                     console.log(xml);
244 
245                 if (defaults.outputMode == 'string')
246                     return xml;
247 
248                 var base64data = base64encode(xml);
249 
250                 if (defaults.outputMode == 'base64')
251                     return base64data;
252 
253                 try {
254                     var blob = new Blob([xml], { type: "application/xml;charset=utf-8" });
255                     saveAs(blob, defaults.fileName + '.xml');
256                 }
257                 catch (e) {
258                     downloadFile(defaults.fileName + '.xml', 'data:application/xml;charset=utf-8;base64,' + base64data);
259                 }
260 
261             } else if (defaults.type == 'excel' || defaults.type == 'doc') {
262                 //console.log($(this).html());
263 
264                 var rowIndex = 0;
265                 var excel = "<table>";
266                 // Header
267                 $(el).find('thead').first().find(defaults.theadSelector).each(function () {
268                     excel += "<tr>";
269                     ForEachVisibleCell(this, 'th,td', rowIndex,
270                         function (cell, row, col) {
271                             if (cell != null) {
272                                 excel += "<td style='";
273                                 for (var styles in defaults.excelstyles) {
274                                     if (defaults.excelstyles.hasOwnProperty(styles)) {
275                                         excel += defaults.excelstyles[styles] + ": " + $(cell).css(defaults.excelstyles[styles]) + ";";
276                                     }
277                                 }
278                                 excel += "'>" + parseString(cell, row, col) + "</td>";
279                             }
280                         });
281                     rowIndex++;
282                     excel += '</tr>';
283                 });
284 
285                 // Row Vs Column
286                 var rowCount = 1;
287                 $(el).find('tbody').first().find(defaults.tbodySelector).each(function () {
288                     excel += "<tr>";
289                     ForEachVisibleCell(this, 'td', rowIndex,
290                         function (cell, row, col) {
291                             if (cell != null) {
292                                 excel += "<td style='mso-number-format:"@";";
293                                 for (var styles in defaults.excelstyles) {
294                                     if (defaults.excelstyles.hasOwnProperty(styles)) {
295                                         excel += defaults.excelstyles[styles] + ": " + $(cell).css(defaults.excelstyles[styles]) + ";";
296                                     }
297                                 }
298                                 if ($(cell).is("[colspan]"))
299                                     excel += "' colspan='" + $(cell).attr('colspan');
300                                 if ($(cell).is("[rowspan]"))
301                                     excel += "' rowspan='" + $(cell).attr('rowspan');
302                                 excel += "'>" + parseString(cell, row, col) + "</td>";
303                             }
304                         });
305                     rowCount++;
306                     rowIndex++;
307                     excel += '</tr>';
308                 });
309 
310                 if (defaults.displayTableName)
311                     excel += "<tr><td></td></tr><tr><td></td></tr><tr><td>" + parseString($('<p>' + defaults.tableName + '</p>')) + "</td></tr>";
312 
313                 excel += '</table>'
314 
315                 if (defaults.consoleLog === true)
316                     console.log(excel);
317 
318                 var excelFile = "<html xmlns:o='urn:schemas-microsoft-com:office:office' xmlns:x='urn:schemas-microsoft-com:office:" + defaults.type + "' xmlns='http://www.w3.org/TR/REC-html40'>";
319                 excelFile += '<meta http-equiv="content-type" content="application/vnd.ms-' + defaults.type + '; charset=UTF-8">';
320                 excelFile += '<meta http-equiv="content-type" content="application/';
321                 excelFile += (defaults.type == 'excel') ? 'vnd.ms-excel' : 'msword';
322                 excelFile += '; charset=UTF-8">';
323                 excelFile += "<head>";
324                 if (defaults.type == 'excel') {
325                     excelFile += "<!--[if gte mso 9]>";
326                     excelFile += "<xml>";
327                     excelFile += "<x:ExcelWorkbook>";
328                     excelFile += "<x:ExcelWorksheets>";
329                     excelFile += "<x:ExcelWorksheet>";
330                     excelFile += "<x:Name>";
331                     excelFile += defaults.worksheetName;
332                     excelFile += "</x:Name>";
333                     excelFile += "<x:WorksheetOptions>";
334                     excelFile += "<x:DisplayGridlines/>";
335                     excelFile += "</x:WorksheetOptions>";
336                     excelFile += "</x:ExcelWorksheet>";
337                     excelFile += "</x:ExcelWorksheets>";
338                     excelFile += "</x:ExcelWorkbook>";
339                     excelFile += "</xml>";
340                     excelFile += "<![endif]-->";
341                 }
342                 excelFile += "</head>";
343                 excelFile += "<body>";
344                 excelFile += excel;
345                 excelFile += "</body>";
346                 excelFile += "</html>";
347 
348                 if (defaults.outputMode == 'string')
349                     return excelFile;
350 
351                 var base64data = base64encode(excelFile);
352 
353                 if (defaults.outputMode == 'base64')
354                     return base64data;
355 
356                 var extension = (defaults.type == 'excel') ? 'xls' : 'doc';
357                 try {
358                     var blob = new Blob([excelFile], { type: 'application/vnd.ms-' + defaults.type });
359                     saveAs(blob, defaults.fileName + '.' + extension);
360                 }
361                 catch (e) {
362                     downloadFile(defaults.fileName + '.' + extension, 'data:application/vnd.ms-' + defaults.type + ';base64,' + base64data);
363                 }
364 
365             } else if (defaults.type == 'png') {
366                 html2canvas($(el), {
367                     onrendered: function (canvas) {
368 
369                         var image = canvas.toDataURL();
370                         image = image.substring(22); // remove data stuff
371 
372                         var byteString = atob(image);
373                         var buffer = new ArrayBuffer(byteString.length);
374                         var intArray = new Uint8Array(buffer);
375 
376                         for (var i = 0; i < byteString.length; i++)
377                             intArray[i] = byteString.charCodeAt(i);
378 
379                         try {
380                             var blob = new Blob([buffer], { type: "image/png" });
381                             saveAs(blob, defaults.fileName + '.png');
382                         }
383                         catch (e) {
384                             downloadFile(defaults.fileName + '.png', 'data:image/png;base64,' + image);
385                         }
386                     }
387                 });
388 
389             } else if (defaults.type == 'pdf') {
390                 if (defaults.jspdf.autotable === false) {
391                     var options = {
392                         dim: {
393                             w: getPropertyUnitValue($(el).first().get(0), 'width', 'mm'),
394                             h: getPropertyUnitValue($(el).first().get(0), 'height', 'mm')
395                         },
396                         pagesplit: false
397                     }
398 
399                     var doc = new jsPDF(defaults.jspdf.orientation, defaults.jspdf.unit, defaults.jspdf.format);
400                     doc.addHTML($(el).first(),
401                         defaults.jspdf.margins.left,
402                         defaults.jspdf.margins.top,
403                         options,
404                         function () {
405                             jsPdfOutput(doc);
406                         });
407                     delete doc;
408                 }
409                 else {
410                     // pdf output using jsPDF AutoTable plugin
411                     // https://github.com/someatoms/jsPDF-AutoTable
412 
413                     var teOptions = defaults.jspdf.autotable.tableExport;
414 
415                     // When setting jspdf.format to 'bestfit' tableExport tries to choose
416                     // the minimum required paper format and orientation in which the table
417                     // (or tables in multitable mode) completely fit without column adjustment
418                     if (typeof defaults.jspdf.format === 'string' && defaults.jspdf.format.toLowerCase() == 'bestfit') {
419                         var pageFormats = {
420                             'a0': [2383.94, 3370.39], 'a1': [1683.78, 2383.94],
421                             'a2': [1190.55, 1683.78], 'a3': [841.89, 1190.55],
422                             'a4': [595.28, 841.89]
423                         };
424                         var rk = '', ro = '';
425                         var mw = 0;
426 
427                         $(el).filter(':visible').each(function () {
428                             if ($(this).css('display') != 'none') {
429                                 var w = getPropertyUnitValue($(this).get(0), 'width', 'pt');
430 
431                                 if (w > mw) {
432                                     if (w > pageFormats['a0'][0]) {
433                                         rk = 'a0';
434                                         ro = 'l';
435                                     }
436                                     for (var key in pageFormats) {
437                                         if (pageFormats[key][1] > w) {
438                                             rk = key;
439                                             ro = 'l';
440                                             if (pageFormats[key][0] > w)
441                                                 ro = 'p';
442                                         }
443                                     }
444                                     mw = w;
445                                 }
446                             }
447                         });
448                         defaults.jspdf.format = (rk == '' ? 'a4' : rk);
449                         defaults.jspdf.orientation = (ro == '' ? 'w' : ro);
450                     }
451 
452                     // The jsPDF doc object is stored in defaults.jspdf.autotable.tableExport,
453                     // thus it can be accessed from any callback function from below
454                     teOptions.doc = new jsPDF(defaults.jspdf.orientation,
455                         defaults.jspdf.unit,
456                         defaults.jspdf.format);
457 
458                     $(el).filter(':visible').each(function () {
459                         if ($(this).css('display') != 'none') {
460                             var rowIndex = 0;
461                             var atOptions = {};
462 
463                             teOptions.columns = [];
464                             teOptions.rows = [];
465 
466                             // onTable: optional callback function for every matching table that can be used
467                             // to modify the tableExport options or to skip the output of a particular table
468                             // when the  table selector targets multiple tables
469                             if (typeof teOptions.onTable === 'function')
470                                 if (teOptions.onTable($(this), defaults) === false)
471                                     return true; // continue to next iteration step (table)
472 
473                             // each table works with an own copy of AutoTable options
474                             Object.keys(defaults.jspdf.autotable).forEach(function (key) {
475                                 atOptions[key] = defaults.jspdf.autotable[key];
476                             });
477                             atOptions.margins = {};
478                             $.extend(true, atOptions.margins, defaults.jspdf.margins);
479 
480                             if (typeof atOptions.renderCell !== 'function') {
481 
482                                 // draw cell text with original <td> alignment
483                                 atOptions.renderCell = function (x, y, width, height, key, value, row, settings) {
484                                     var doc = settings.tableExport.doc;
485                                     var xoffset = 0;
486 
487                                     doc.setFillColor(row % 2 === 0 ? 245 : 255);
488                                     doc.setTextColor(50);
489                                     doc.rect(x, y, width, height, 'F');
490                                     y += settings.lineHeight / 2 + doc.autoTableTextHeight() / 2 - 2.5;
491 
492                                     if (typeof settings.tableExport.columns[key] != 'undefined') {
493                                         var col = settings.tableExport.columns[key];
494 
495                                         if (col.style.align == 'right')
496                                             xoffset = width - doc.getStringUnitWidth(('' + value)) * doc.internal.getFontSize() - settings.padding;
497                                         else if (col.style.align == 'center')
498                                             xoffset = (width - doc.getStringUnitWidth(('' + value)) * doc.internal.getFontSize()) / 2;
499                                     }
500 
501                                     if (xoffset < settings.padding)
502                                         xoffset = settings.padding;
503 
504                                     doc.text(value, x + xoffset, y);
505                                 }
506                             }
507 
508                             // collect header and data rows
509                             $(this).find('thead').find(defaults.theadSelector).each(function () {
510                                 var colKey = 0;
511 
512                                 ForEachVisibleCell(this, 'th,td', rowIndex,
513                                     function (cell, row, col) {
514                                         var obj = {
515                                             title: parseString(cell, row, col),
516                                             key: colKey++,
517                                             style: {
518                                                 align: getStyle(cell, 'text-align'),
519                                                 bcolor: getStyle(cell, 'background-color')
520                                             }
521                                         };
522                                         teOptions.columns.push(obj);
523                                     });
524                                 rowIndex++;
525                                 colKey = 0;
526                             });
527 
528                             $(this).find('tbody').find(defaults.tbodySelector).each(function () {
529                                 var rowData = [];
530 
531                                 ForEachVisibleCell(this, 'td', rowIndex,
532                                     function (cell, row, col) {
533                                         rowData.push(parseString(cell, row, col));
534                                     });
535                                 rowIndex++;
536                                 teOptions.rows.push(rowData);
537                             });
538 
539                             // onBeforeAutotable: optional callback function before calling
540                             // jsPDF AutoTable that can be used to modify the AutoTable options
541                             if (typeof teOptions.onBeforeAutotable === 'function')
542                                 teOptions.onBeforeAutotable($(this), teOptions.columns, teOptions.rows, atOptions);
543 
544                             teOptions.doc.autoTable(teOptions.columns, teOptions.rows, atOptions);
545 
546                             // onAfterAutotable: optional callback function after returning
547                             // from jsPDF AutoTable that can be used to modify the AutoTable options
548                             if (typeof teOptions.onAfterAutotable === 'function')
549                                 teOptions.onAfterAutotable($(this), atOptions);
550 
551                             // set the start position for the next table (in case there is one)
552                             defaults.jspdf.autotable.startY = teOptions.doc.autoTableEndPosY() + atOptions.margins.top;
553                         }
554                     });
555 
556                     jsPdfOutput(teOptions.doc);
557 
558                     teOptions.columns.length = 0;
559                     teOptions.rows.length = 0;
560                     delete teOptions.doc;
561                     teOptions.doc = null;
562                 }
563             }
564 
565             function ForEachVisibleCell(tableRow, selector, rowIndex, cellcallback) {
566 
567                 $(tableRow).filter(':visible').find(selector).each(function (colIndex) {
568                     if ($(this).css('display') != 'none' &&
569                         $(this).data("tableexport-display") != 'none') {
570                         if (defaults.ignoreColumn.indexOf(colIndex) == -1) {
571                             if (typeof (cellcallback) === "function") {
572                                 var cs = 0; // colspan value
573 
574                                 // handle previously detected rowspans
575                                 if (typeof rowspans[rowIndex] != 'undefined' && rowspans[rowIndex].length > 0) {
576                                     for (c = 0; c <= colIndex; c++) {
577                                         if (typeof rowspans[rowIndex][c] != 'undefined') {
578                                             cellcallback(null, rowIndex, c);
579                                             delete rowspans[rowIndex][c];
580                                             colIndex++;
581                                         }
582                                     }
583                                 }
584 
585                                 // output content of current cell
586                                 cellcallback(this, rowIndex, colIndex);
587 
588                                 // handle colspan of current cell
589                                 if ($(this).is("[colspan]")) {
590                                     cs = $(this).attr('colspan');
591                                     for (c = 0; c < cs - 1; c++)
592                                         cellcallback(null, rowIndex, colIndex + c);
593                                 }
594 
595                                 // store rowspan for following rows
596                                 if ($(this).is("[rowspan]")) {
597                                     var rs = parseInt($(this).attr('rowspan'));
598 
599                                     for (r = 1; r < rs; r++) {
600                                         if (typeof rowspans[rowIndex + r] == 'undefined')
601                                             rowspans[rowIndex + r] = [];
602                                         rowspans[rowIndex + r][colIndex] = "";
603 
604                                         for (c = 1; c < cs; c++)
605                                             rowspans[rowIndex + r][colIndex + c] = "";
606                                     }
607                                 }
608 
609                             }
610                         }
611                     }
612                 });
613             }
614 
615             function jsPdfOutput(doc) {
616                 if (defaults.consoleLog === true)
617                     console.log(doc.output());
618 
619                 if (defaults.outputMode == 'string')
620                     return doc.output();
621 
622                 if (defaults.outputMode == 'base64')
623                     return base64encode(doc.output());
624 
625                 try {
626                     var blob = doc.output('blob');
627                     saveAs(blob, defaults.fileName + '.pdf');
628                 }
629                 catch (e) {
630                     downloadFile(defaults.fileName + '.pdf', 'data:application/pdf;base64,' + base64encode(doc.output()));
631                 }
632             }
633 
634             function escapeRegExp(string) {
635                 return string.replace(/([.*+?^=!:${}()|[]/\])/g, "\$1");
636             }
637 
638             function replaceAll(string, find, replace) {
639                 return string.replace(new RegExp(escapeRegExp(find), 'g'), replace);
640             }
641 
642             function csvString(cell, rowIndex, colIndex) {
643                 var result = '';
644 
645                 if (cell != null) {
646                     var dataString = parseString(cell, rowIndex, colIndex);
647 
648                     var csvValue = (dataString === null || dataString == '') ? '' : dataString.toString();
649 
650                     if (dataString instanceof Date)
651                         result = defaults.csvEnclosure + dataString.toLocaleString() + defaults.csvEnclosure;
652                     else {
653                         result = replaceAll(csvValue, defaults.csvEnclosure, defaults.csvEnclosure + defaults.csvEnclosure);
654 
655                         if (result.indexOf(defaults.csvSeparator) >= 0 || /[
 ]/g.test(result))
656                             result = defaults.csvEnclosure + result + defaults.csvEnclosure;
657                     }
658                 }
659 
660                 return result;
661             }
662 
663             function parseString(cell, rowIndex, colIndex) {
664                 var result = '';
665 
666                 if (cell != null) {
667                     var $cell = $(cell);
668 
669                     if (defaults.htmlContent === true) {
670                         result = $cell.html().trim();
671                     } else {
672                         result = $cell.text().trim().replace(/u00AD/g, ""); // remove soft hyphens
673                     }
674 
675                     if (defaults.escape === true) {
676                         result = escape(result);
677                     }
678 
679                     if (typeof defaults.onCellData === 'function') {
680                         result = defaults.onCellData($cell, rowIndex, colIndex, result);
681                     }
682                 }
683 
684                 return result;
685             }
686 
687             function hyphenate(a, b, c) {
688                 return b + "-" + c.toLowerCase();
689             }
690 
691             // get computed style property
692             function getStyle(target, prop) {
693                 if (window.getComputedStyle) { // gecko and webkit
694                     prop = prop.replace(/([a-z])([A-Z])/, hyphenate);  // requires hyphenated, not camel
695                     return window.getComputedStyle(target, null).getPropertyValue(prop);
696                 }
697                 if (target.currentStyle) { // ie
698                     return target.currentStyle[prop];
699                 }
700                 return target.style[prop];
701             }
702 
703             function getPropertyUnitValue(target, prop, unit) {
704                 var baseline = 100;  // any number serves
705 
706                 var value = getStyle(target, prop);  // get the computed style value
707 
708                 var numeric = value.match(/d+/);  // get the numeric component
709                 if (numeric !== null) {
710                     numeric = numeric[0];  // get the string
711 
712                     var temp = document.createElement("div");  // create temporary element
713                     temp.style.overflow = "hidden";  // in case baseline is set too low
714                     temp.style.visibility = "hidden";  // no need to show it
715 
716                     target.parentElement.appendChild(temp); // insert it into the parent for em, ex and %
717 
718                     temp.style.width = baseline + unit;
719                     var factor = baseline / temp.offsetWidth;
720 
721                     target.parentElement.removeChild(temp);  // clean up
722 
723                     return (numeric * factor);
724                 }
725                 return 0;
726             }
727 
728             function downloadFile(filename, data) {
729                 var DownloadLink = document.createElement('a');
730 
731                 if (DownloadLink) {
732                     document.body.appendChild(DownloadLink);
733                     DownloadLink.style = 'display: none';
734                     DownloadLink.download = filename;
735                     DownloadLink.href = data;
736 
737                     if (document.createEvent) {
738                         if (DownloadEvt == null)
739                             DownloadEvt = document.createEvent('MouseEvents');
740 
741                         DownloadEvt.initEvent('click', true, false);
742                         DownloadLink.dispatchEvent(DownloadEvt);
743                     }
744                     else if (document.createEventObject)
745                         DownloadLink.fireEvent('onclick');
746                     else if (typeof DownloadLink.onclick == 'function')
747                         DownloadLink.onclick();
748 
749                     document.body.removeChild(DownloadLink);
750                 }
751             }
752 
753             function utf8Encode(string) {
754                 string = string.replace(/x0dx0a/g, "x0a");
755                 var utftext = "";
756                 for (var n = 0; n < string.length; n++) {
757                     var c = string.charCodeAt(n);
758                     if (c < 128) {
759                         utftext += String.fromCharCode(c);
760                     }
761                     else if ((c > 127) && (c < 2048)) {
762                         utftext += String.fromCharCode((c >> 6) | 192);
763                         utftext += String.fromCharCode((c & 63) | 128);
764                     }
765                     else {
766                         utftext += String.fromCharCode((c >> 12) | 224);
767                         utftext += String.fromCharCode(((c >> 6) & 63) | 128);
768                         utftext += String.fromCharCode((c & 63) | 128);
769                     }
770                 }
771                 return utftext;
772             }
773 
774             function base64encode(input) {
775                 var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
776                 var output = "";
777                 var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
778                 var i = 0;
779                 input = utf8Encode(input);
780                 while (i < input.length) {
781                     chr1 = input.charCodeAt(i++);
782                     chr2 = input.charCodeAt(i++);
783                     chr3 = input.charCodeAt(i++);
784                     enc1 = chr1 >> 2;
785                     enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
786                     enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
787                     enc4 = chr3 & 63;
788                     if (isNaN(chr2)) {
789                         enc3 = enc4 = 64;
790                     } else if (isNaN(chr3)) {
791                         enc4 = 64;
792                     }
793                     output = output +
794                         keyStr.charAt(enc1) + keyStr.charAt(enc2) +
795                         keyStr.charAt(enc3) + keyStr.charAt(enc4);
796                 }
797                 return output;
798             }
799 
800             return this;
801         }
802     });
803 })(jQuery);