source: public/vendors/dataTable/Buttons-1.6.1/js/buttons.html5.js@ 7304c7f

develop
Last change on this file since 7304c7f was 7304c7f, checked in by beratkjufliju <kufliju@…>, 3 years ago

added user authentication, create & forgot password methods and blades

  • Property mode set to 100644
File size: 43.0 KB
Line 
1/*!
2 * HTML5 export buttons for Buttons and DataTables.
3 * 2016 SpryMedia Ltd - datatables.net/license
4 *
5 * FileSaver.js (1.3.3) - MIT license
6 * Copyright © 2016 Eli Grey - http://eligrey.com
7 */
8
9(function( factory ){
10 if ( typeof define === 'function' && define.amd ) {
11 // AMD
12 define( ['jquery', 'datatables.net', 'datatables.net-buttons'], function ( $ ) {
13 return factory( $, window, document );
14 } );
15 }
16 else if ( typeof exports === 'object' ) {
17 // CommonJS
18 module.exports = function (root, $, jszip, pdfmake) {
19 if ( ! root ) {
20 root = window;
21 }
22
23 if ( ! $ || ! $.fn.dataTable ) {
24 $ = require('datatables.net')(root, $).$;
25 }
26
27 if ( ! $.fn.dataTable.Buttons ) {
28 require('datatables.net-buttons')(root, $);
29 }
30
31 return factory( $, root, root.document, jszip, pdfmake );
32 };
33 }
34 else {
35 // Browser
36 factory( jQuery, window, document );
37 }
38}(function( $, window, document, jszip, pdfmake, undefined ) {
39'use strict';
40var DataTable = $.fn.dataTable;
41
42// Allow the constructor to pass in JSZip and PDFMake from external requires.
43// Otherwise, use globally defined variables, if they are available.
44function _jsZip () {
45 return jszip || window.JSZip;
46}
47function _pdfMake () {
48 return pdfmake || window.pdfMake;
49}
50
51DataTable.Buttons.pdfMake = function (_) {
52 if ( ! _ ) {
53 return _pdfMake();
54 }
55 pdfmake = m_ake;
56}
57
58DataTable.Buttons.jszip = function (_) {
59 if ( ! _ ) {
60 return _jsZip();
61 }
62 jszip = _;
63}
64
65
66/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
67 * FileSaver.js dependency
68 */
69
70/*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */
71
72var _saveAs = (function(view) {
73 "use strict";
74 // IE <10 is explicitly unsupported
75 if (typeof view === "undefined" || typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) {
76 return;
77 }
78 var
79 doc = view.document
80 // only get URL when necessary in case Blob.js hasn't overridden it yet
81 , get_URL = function() {
82 return view.URL || view.webkitURL || view;
83 }
84 , save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a")
85 , can_use_save_link = "download" in save_link
86 , click = function(node) {
87 var event = new MouseEvent("click");
88 node.dispatchEvent(event);
89 }
90 , is_safari = /constructor/i.test(view.HTMLElement) || view.safari
91 , is_chrome_ios =/CriOS\/[\d]+/.test(navigator.userAgent)
92 , throw_outside = function(ex) {
93 (view.setImmediate || view.setTimeout)(function() {
94 throw ex;
95 }, 0);
96 }
97 , force_saveable_type = "application/octet-stream"
98 // the Blob API is fundamentally broken as there is no "downloadfinished" event to subscribe to
99 , arbitrary_revoke_timeout = 1000 * 40 // in ms
100 , revoke = function(file) {
101 var revoker = function() {
102 if (typeof file === "string") { // file is an object URL
103 get_URL().revokeObjectURL(file);
104 } else { // file is a File
105 file.remove();
106 }
107 };
108 setTimeout(revoker, arbitrary_revoke_timeout);
109 }
110 , dispatch = function(filesaver, event_types, event) {
111 event_types = [].concat(event_types);
112 var i = event_types.length;
113 while (i--) {
114 var listener = filesaver["on" + event_types[i]];
115 if (typeof listener === "function") {
116 try {
117 listener.call(filesaver, event || filesaver);
118 } catch (ex) {
119 throw_outside(ex);
120 }
121 }
122 }
123 }
124 , auto_bom = function(blob) {
125 // prepend BOM for UTF-8 XML and text/* types (including HTML)
126 // note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF
127 if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) {
128 return new Blob([String.fromCharCode(0xFEFF), blob], {type: blob.type});
129 }
130 return blob;
131 }
132 , FileSaver = function(blob, name, no_auto_bom) {
133 if (!no_auto_bom) {
134 blob = auto_bom(blob);
135 }
136 // First try a.download, then web filesystem, then object URLs
137 var
138 filesaver = this
139 , type = blob.type
140 , force = type === force_saveable_type
141 , object_url
142 , dispatch_all = function() {
143 dispatch(filesaver, "writestart progress write writeend".split(" "));
144 }
145 // on any filesys errors revert to saving with object URLs
146 , fs_error = function() {
147 if ((is_chrome_ios || (force && is_safari)) && view.FileReader) {
148 // Safari doesn't allow downloading of blob urls
149 var reader = new FileReader();
150 reader.onloadend = function() {
151 var url = is_chrome_ios ? reader.result : reader.result.replace(/^data:[^;]*;/, 'data:attachment/file;');
152 var popup = view.open(url, '_blank');
153 if(!popup) view.location.href = url;
154 url=undefined; // release reference before dispatching
155 filesaver.readyState = filesaver.DONE;
156 dispatch_all();
157 };
158 reader.readAsDataURL(blob);
159 filesaver.readyState = filesaver.INIT;
160 return;
161 }
162 // don't create more object URLs than needed
163 if (!object_url) {
164 object_url = get_URL().createObjectURL(blob);
165 }
166 if (force) {
167 view.location.href = object_url;
168 } else {
169 var opened = view.open(object_url, "_blank");
170 if (!opened) {
171 // Apple does not allow window.open, see https://developer.apple.com/library/safari/documentation/Tools/Conceptual/SafariExtensionGuide/WorkingwithWindowsandTabs/WorkingwithWindowsandTabs.html
172 view.location.href = object_url;
173 }
174 }
175 filesaver.readyState = filesaver.DONE;
176 dispatch_all();
177 revoke(object_url);
178 }
179 ;
180 filesaver.readyState = filesaver.INIT;
181
182 if (can_use_save_link) {
183 object_url = get_URL().createObjectURL(blob);
184 setTimeout(function() {
185 save_link.href = object_url;
186 save_link.download = name;
187 click(save_link);
188 dispatch_all();
189 revoke(object_url);
190 filesaver.readyState = filesaver.DONE;
191 });
192 return;
193 }
194
195 fs_error();
196 }
197 , FS_proto = FileSaver.prototype
198 , saveAs = function(blob, name, no_auto_bom) {
199 return new FileSaver(blob, name || blob.name || "download", no_auto_bom);
200 }
201 ;
202 // IE 10+ (native saveAs)
203 if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) {
204 return function(blob, name, no_auto_bom) {
205 name = name || blob.name || "download";
206
207 if (!no_auto_bom) {
208 blob = auto_bom(blob);
209 }
210 return navigator.msSaveOrOpenBlob(blob, name);
211 };
212 }
213
214 FS_proto.abort = function(){};
215 FS_proto.readyState = FS_proto.INIT = 0;
216 FS_proto.WRITING = 1;
217 FS_proto.DONE = 2;
218
219 FS_proto.error =
220 FS_proto.onwritestart =
221 FS_proto.onprogress =
222 FS_proto.onwrite =
223 FS_proto.onabort =
224 FS_proto.onerror =
225 FS_proto.onwriteend =
226 null;
227
228 return saveAs;
229}(
230 typeof self !== "undefined" && self
231 || typeof window !== "undefined" && window
232 || this.content
233));
234
235
236// Expose file saver on the DataTables API. Can't attach to `DataTables.Buttons`
237// since this file can be loaded before Button's core!
238DataTable.fileSave = _saveAs;
239
240
241/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
242 * Local (private) functions
243 */
244
245/**
246 * Get the sheet name for Excel exports.
247 *
248 * @param {object} config Button configuration
249 */
250var _sheetname = function ( config )
251{
252 var sheetName = 'Sheet1';
253
254 if ( config.sheetName ) {
255 sheetName = config.sheetName.replace(/[\[\]\*\/\\\?\:]/g, '');
256 }
257
258 return sheetName;
259};
260
261/**
262 * Get the newline character(s)
263 *
264 * @param {object} config Button configuration
265 * @return {string} Newline character
266 */
267var _newLine = function ( config )
268{
269 return config.newline ?
270 config.newline :
271 navigator.userAgent.match(/Windows/) ?
272 '\r\n' :
273 '\n';
274};
275
276/**
277 * Combine the data from the `buttons.exportData` method into a string that
278 * will be used in the export file.
279 *
280 * @param {DataTable.Api} dt DataTables API instance
281 * @param {object} config Button configuration
282 * @return {object} The data to export
283 */
284var _exportData = function ( dt, config )
285{
286 var newLine = _newLine( config );
287 var data = dt.buttons.exportData( config.exportOptions );
288 var boundary = config.fieldBoundary;
289 var separator = config.fieldSeparator;
290 var reBoundary = new RegExp( boundary, 'g' );
291 var escapeChar = config.escapeChar !== undefined ?
292 config.escapeChar :
293 '\\';
294 var join = function ( a ) {
295 var s = '';
296
297 // If there is a field boundary, then we might need to escape it in
298 // the source data
299 for ( var i=0, ien=a.length ; i<ien ; i++ ) {
300 if ( i > 0 ) {
301 s += separator;
302 }
303
304 s += boundary ?
305 boundary + ('' + a[i]).replace( reBoundary, escapeChar+boundary ) + boundary :
306 a[i];
307 }
308
309 return s;
310 };
311
312 var header = config.header ? join( data.header )+newLine : '';
313 var footer = config.footer && data.footer ? newLine+join( data.footer ) : '';
314 var body = [];
315
316 for ( var i=0, ien=data.body.length ; i<ien ; i++ ) {
317 body.push( join( data.body[i] ) );
318 }
319
320 return {
321 str: header + body.join( newLine ) + footer,
322 rows: body.length
323 };
324};
325
326/**
327 * Older versions of Safari (prior to tech preview 18) don't support the
328 * download option required.
329 *
330 * @return {Boolean} `true` if old Safari
331 */
332var _isDuffSafari = function ()
333{
334 var safari = navigator.userAgent.indexOf('Safari') !== -1 &&
335 navigator.userAgent.indexOf('Chrome') === -1 &&
336 navigator.userAgent.indexOf('Opera') === -1;
337
338 if ( ! safari ) {
339 return false;
340 }
341
342 var version = navigator.userAgent.match( /AppleWebKit\/(\d+\.\d+)/ );
343 if ( version && version.length > 1 && version[1]*1 < 603.1 ) {
344 return true;
345 }
346
347 return false;
348};
349
350/**
351 * Convert from numeric position to letter for column names in Excel
352 * @param {int} n Column number
353 * @return {string} Column letter(s) name
354 */
355function createCellPos( n ){
356 var ordA = 'A'.charCodeAt(0);
357 var ordZ = 'Z'.charCodeAt(0);
358 var len = ordZ - ordA + 1;
359 var s = "";
360
361 while( n >= 0 ) {
362 s = String.fromCharCode(n % len + ordA) + s;
363 n = Math.floor(n / len) - 1;
364 }
365
366 return s;
367}
368
369try {
370 var _serialiser = new XMLSerializer();
371 var _ieExcel;
372}
373catch (t) {}
374
375/**
376 * Recursively add XML files from an object's structure to a ZIP file. This
377 * allows the XSLX file to be easily defined with an object's structure matching
378 * the files structure.
379 *
380 * @param {JSZip} zip ZIP package
381 * @param {object} obj Object to add (recursive)
382 */
383function _addToZip( zip, obj ) {
384 if ( _ieExcel === undefined ) {
385 // Detect if we are dealing with IE's _awful_ serialiser by seeing if it
386 // drop attributes
387 _ieExcel = _serialiser
388 .serializeToString(
389 $.parseXML( excelStrings['xl/worksheets/sheet1.xml'] )
390 )
391 .indexOf( 'xmlns:r' ) === -1;
392 }
393
394 $.each( obj, function ( name, val ) {
395 if ( $.isPlainObject( val ) ) {
396 var newDir = zip.folder( name );
397 _addToZip( newDir, val );
398 }
399 else {
400 if ( _ieExcel ) {
401 // IE's XML serialiser will drop some name space attributes from
402 // from the root node, so we need to save them. Do this by
403 // replacing the namespace nodes with a regular attribute that
404 // we convert back when serialised. Edge does not have this
405 // issue
406 var worksheet = val.childNodes[0];
407 var i, ien;
408 var attrs = [];
409
410 for ( i=worksheet.attributes.length-1 ; i>=0 ; i-- ) {
411 var attrName = worksheet.attributes[i].nodeName;
412 var attrValue = worksheet.attributes[i].nodeValue;
413
414 if ( attrName.indexOf( ':' ) !== -1 ) {
415 attrs.push( { name: attrName, value: attrValue } );
416
417 worksheet.removeAttribute( attrName );
418 }
419 }
420
421 for ( i=0, ien=attrs.length ; i<ien ; i++ ) {
422 var attr = val.createAttribute( attrs[i].name.replace( ':', '_dt_b_namespace_token_' ) );
423 attr.value = attrs[i].value;
424 worksheet.setAttributeNode( attr );
425 }
426 }
427
428 var str = _serialiser.serializeToString(val);
429
430 // Fix IE's XML
431 if ( _ieExcel ) {
432 // IE doesn't include the XML declaration
433 if ( str.indexOf( '<?xml' ) === -1 ) {
434 str = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'+str;
435 }
436
437 // Return namespace attributes to being as such
438 str = str.replace( /_dt_b_namespace_token_/g, ':' );
439
440 // Remove testing name space that IE puts into the space preserve attr
441 str = str.replace( /xmlns:NS[\d]+="" NS[\d]+:/g, '' );
442 }
443
444 // Safari, IE and Edge will put empty name space attributes onto
445 // various elements making them useless. This strips them out
446 str = str.replace( /<([^<>]*?) xmlns=""([^<>]*?)>/g, '<$1 $2>' );
447
448 zip.file( name, str );
449 }
450 } );
451}
452
453/**
454 * Create an XML node and add any children, attributes, etc without needing to
455 * be verbose in the DOM.
456 *
457 * @param {object} doc XML document
458 * @param {string} nodeName Node name
459 * @param {object} opts Options - can be `attr` (attributes), `children`
460 * (child nodes) and `text` (text content)
461 * @return {node} Created node
462 */
463function _createNode( doc, nodeName, opts ) {
464 var tempNode = doc.createElement( nodeName );
465
466 if ( opts ) {
467 if ( opts.attr ) {
468 $(tempNode).attr( opts.attr );
469 }
470
471 if ( opts.children ) {
472 $.each( opts.children, function ( key, value ) {
473 tempNode.appendChild( value );
474 } );
475 }
476
477 if ( opts.text !== null && opts.text !== undefined ) {
478 tempNode.appendChild( doc.createTextNode( opts.text ) );
479 }
480 }
481
482 return tempNode;
483}
484
485/**
486 * Get the width for an Excel column based on the contents of that column
487 * @param {object} data Data for export
488 * @param {int} col Column index
489 * @return {int} Column width
490 */
491function _excelColWidth( data, col ) {
492 var max = data.header[col].length;
493 var len, lineSplit, str;
494
495 if ( data.footer && data.footer[col].length > max ) {
496 max = data.footer[col].length;
497 }
498
499 for ( var i=0, ien=data.body.length ; i<ien ; i++ ) {
500 var point = data.body[i][col];
501 str = point !== null && point !== undefined ?
502 point.toString() :
503 '';
504
505 // If there is a newline character, workout the width of the column
506 // based on the longest line in the string
507 if ( str.indexOf('\n') !== -1 ) {
508 lineSplit = str.split('\n');
509 lineSplit.sort( function (a, b) {
510 return b.length - a.length;
511 } );
512
513 len = lineSplit[0].length;
514 }
515 else {
516 len = str.length;
517 }
518
519 if ( len > max ) {
520 max = len;
521 }
522
523 // Max width rather than having potentially massive column widths
524 if ( max > 40 ) {
525 return 54; // 40 * 1.35
526 }
527 }
528
529 max *= 1.35;
530
531 // And a min width
532 return max > 6 ? max : 6;
533}
534
535// Excel - Pre-defined strings to build a basic XLSX file
536var excelStrings = {
537 "_rels/.rels":
538 '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'+
539 '<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">'+
540 '<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/>'+
541 '</Relationships>',
542
543 "xl/_rels/workbook.xml.rels":
544 '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'+
545 '<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">'+
546 '<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet1.xml"/>'+
547 '<Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/>'+
548 '</Relationships>',
549
550 "[Content_Types].xml":
551 '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'+
552 '<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">'+
553 '<Default Extension="xml" ContentType="application/xml" />'+
554 '<Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml" />'+
555 '<Default Extension="jpeg" ContentType="image/jpeg" />'+
556 '<Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml" />'+
557 '<Override PartName="/xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml" />'+
558 '<Override PartName="/xl/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml" />'+
559 '</Types>',
560
561 "xl/workbook.xml":
562 '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'+
563 '<workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">'+
564 '<fileVersion appName="xl" lastEdited="5" lowestEdited="5" rupBuild="24816"/>'+
565 '<workbookPr showInkAnnotation="0" autoCompressPictures="0"/>'+
566 '<bookViews>'+
567 '<workbookView xWindow="0" yWindow="0" windowWidth="25600" windowHeight="19020" tabRatio="500"/>'+
568 '</bookViews>'+
569 '<sheets>'+
570 '<sheet name="Sheet1" sheetId="1" r:id="rId1"/>'+
571 '</sheets>'+
572 '<definedNames/>'+
573 '</workbook>',
574
575 "xl/worksheets/sheet1.xml":
576 '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'+
577 '<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="x14ac" xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac">'+
578 '<sheetData/>'+
579 '<mergeCells count="0"/>'+
580 '</worksheet>',
581
582 "xl/styles.xml":
583 '<?xml version="1.0" encoding="UTF-8"?>'+
584 '<styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="x14ac" xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac">'+
585 '<numFmts count="6">'+
586 '<numFmt numFmtId="164" formatCode="#,##0.00_-\ [$$-45C]"/>'+
587 '<numFmt numFmtId="165" formatCode="&quot;£&quot;#,##0.00"/>'+
588 '<numFmt numFmtId="166" formatCode="[$€-2]\ #,##0.00"/>'+
589 '<numFmt numFmtId="167" formatCode="0.0%"/>'+
590 '<numFmt numFmtId="168" formatCode="#,##0;(#,##0)"/>'+
591 '<numFmt numFmtId="169" formatCode="#,##0.00;(#,##0.00)"/>'+
592 '</numFmts>'+
593 '<fonts count="5" x14ac:knownFonts="1">'+
594 '<font>'+
595 '<sz val="11" />'+
596 '<name val="Calibri" />'+
597 '</font>'+
598 '<font>'+
599 '<sz val="11" />'+
600 '<name val="Calibri" />'+
601 '<color rgb="FFFFFFFF" />'+
602 '</font>'+
603 '<font>'+
604 '<sz val="11" />'+
605 '<name val="Calibri" />'+
606 '<b />'+
607 '</font>'+
608 '<font>'+
609 '<sz val="11" />'+
610 '<name val="Calibri" />'+
611 '<i />'+
612 '</font>'+
613 '<font>'+
614 '<sz val="11" />'+
615 '<name val="Calibri" />'+
616 '<u />'+
617 '</font>'+
618 '</fonts>'+
619 '<fills count="6">'+
620 '<fill>'+
621 '<patternFill patternType="none" />'+
622 '</fill>'+
623 '<fill>'+ // Excel appears to use this as a dotted background regardless of values but
624 '<patternFill patternType="none" />'+ // to be valid to the schema, use a patternFill
625 '</fill>'+
626 '<fill>'+
627 '<patternFill patternType="solid">'+
628 '<fgColor rgb="FFD9D9D9" />'+
629 '<bgColor indexed="64" />'+
630 '</patternFill>'+
631 '</fill>'+
632 '<fill>'+
633 '<patternFill patternType="solid">'+
634 '<fgColor rgb="FFD99795" />'+
635 '<bgColor indexed="64" />'+
636 '</patternFill>'+
637 '</fill>'+
638 '<fill>'+
639 '<patternFill patternType="solid">'+
640 '<fgColor rgb="ffc6efce" />'+
641 '<bgColor indexed="64" />'+
642 '</patternFill>'+
643 '</fill>'+
644 '<fill>'+
645 '<patternFill patternType="solid">'+
646 '<fgColor rgb="ffc6cfef" />'+
647 '<bgColor indexed="64" />'+
648 '</patternFill>'+
649 '</fill>'+
650 '</fills>'+
651 '<borders count="2">'+
652 '<border>'+
653 '<left />'+
654 '<right />'+
655 '<top />'+
656 '<bottom />'+
657 '<diagonal />'+
658 '</border>'+
659 '<border diagonalUp="false" diagonalDown="false">'+
660 '<left style="thin">'+
661 '<color auto="1" />'+
662 '</left>'+
663 '<right style="thin">'+
664 '<color auto="1" />'+
665 '</right>'+
666 '<top style="thin">'+
667 '<color auto="1" />'+
668 '</top>'+
669 '<bottom style="thin">'+
670 '<color auto="1" />'+
671 '</bottom>'+
672 '<diagonal />'+
673 '</border>'+
674 '</borders>'+
675 '<cellStyleXfs count="1">'+
676 '<xf numFmtId="0" fontId="0" fillId="0" borderId="0" />'+
677 '</cellStyleXfs>'+
678 '<cellXfs count="67">'+
679 '<xf numFmtId="0" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+
680 '<xf numFmtId="0" fontId="1" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+
681 '<xf numFmtId="0" fontId="2" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+
682 '<xf numFmtId="0" fontId="3" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+
683 '<xf numFmtId="0" fontId="4" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+
684 '<xf numFmtId="0" fontId="0" fillId="2" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+
685 '<xf numFmtId="0" fontId="1" fillId="2" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+
686 '<xf numFmtId="0" fontId="2" fillId="2" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+
687 '<xf numFmtId="0" fontId="3" fillId="2" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+
688 '<xf numFmtId="0" fontId="4" fillId="2" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+
689 '<xf numFmtId="0" fontId="0" fillId="3" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+
690 '<xf numFmtId="0" fontId="1" fillId="3" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+
691 '<xf numFmtId="0" fontId="2" fillId="3" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+
692 '<xf numFmtId="0" fontId="3" fillId="3" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+
693 '<xf numFmtId="0" fontId="4" fillId="3" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+
694 '<xf numFmtId="0" fontId="0" fillId="4" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+
695 '<xf numFmtId="0" fontId="1" fillId="4" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+
696 '<xf numFmtId="0" fontId="2" fillId="4" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+
697 '<xf numFmtId="0" fontId="3" fillId="4" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+
698 '<xf numFmtId="0" fontId="4" fillId="4" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+
699 '<xf numFmtId="0" fontId="0" fillId="5" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+
700 '<xf numFmtId="0" fontId="1" fillId="5" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+
701 '<xf numFmtId="0" fontId="2" fillId="5" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+
702 '<xf numFmtId="0" fontId="3" fillId="5" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+
703 '<xf numFmtId="0" fontId="4" fillId="5" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+
704 '<xf numFmtId="0" fontId="0" fillId="0" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+
705 '<xf numFmtId="0" fontId="1" fillId="0" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+
706 '<xf numFmtId="0" fontId="2" fillId="0" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+
707 '<xf numFmtId="0" fontId="3" fillId="0" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+
708 '<xf numFmtId="0" fontId="4" fillId="0" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+
709 '<xf numFmtId="0" fontId="0" fillId="2" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+
710 '<xf numFmtId="0" fontId="1" fillId="2" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+
711 '<xf numFmtId="0" fontId="2" fillId="2" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+
712 '<xf numFmtId="0" fontId="3" fillId="2" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+
713 '<xf numFmtId="0" fontId="4" fillId="2" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+
714 '<xf numFmtId="0" fontId="0" fillId="3" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+
715 '<xf numFmtId="0" fontId="1" fillId="3" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+
716 '<xf numFmtId="0" fontId="2" fillId="3" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+
717 '<xf numFmtId="0" fontId="3" fillId="3" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+
718 '<xf numFmtId="0" fontId="4" fillId="3" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+
719 '<xf numFmtId="0" fontId="0" fillId="4" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+
720 '<xf numFmtId="0" fontId="1" fillId="4" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+
721 '<xf numFmtId="0" fontId="2" fillId="4" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+
722 '<xf numFmtId="0" fontId="3" fillId="4" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+
723 '<xf numFmtId="0" fontId="4" fillId="4" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+
724 '<xf numFmtId="0" fontId="0" fillId="5" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+
725 '<xf numFmtId="0" fontId="1" fillId="5" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+
726 '<xf numFmtId="0" fontId="2" fillId="5" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+
727 '<xf numFmtId="0" fontId="3" fillId="5" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+
728 '<xf numFmtId="0" fontId="4" fillId="5" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+
729 '<xf numFmtId="0" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyAlignment="1">'+
730 '<alignment horizontal="left"/>'+
731 '</xf>'+
732 '<xf numFmtId="0" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyAlignment="1">'+
733 '<alignment horizontal="center"/>'+
734 '</xf>'+
735 '<xf numFmtId="0" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyAlignment="1">'+
736 '<alignment horizontal="right"/>'+
737 '</xf>'+
738 '<xf numFmtId="0" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyAlignment="1">'+
739 '<alignment horizontal="fill"/>'+
740 '</xf>'+
741 '<xf numFmtId="0" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyAlignment="1">'+
742 '<alignment textRotation="90"/>'+
743 '</xf>'+
744 '<xf numFmtId="0" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyAlignment="1">'+
745 '<alignment wrapText="1"/>'+
746 '</xf>'+
747 '<xf numFmtId="9" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>'+
748 '<xf numFmtId="164" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>'+
749 '<xf numFmtId="165" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>'+
750 '<xf numFmtId="166" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>'+
751 '<xf numFmtId="167" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>'+
752 '<xf numFmtId="168" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>'+
753 '<xf numFmtId="169" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>'+
754 '<xf numFmtId="3" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>'+
755 '<xf numFmtId="4" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>'+
756 '<xf numFmtId="1" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>'+
757 '<xf numFmtId="2" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>'+
758 '</cellXfs>'+
759 '<cellStyles count="1">'+
760 '<cellStyle name="Normal" xfId="0" builtinId="0" />'+
761 '</cellStyles>'+
762 '<dxfs count="0" />'+
763 '<tableStyles count="0" defaultTableStyle="TableStyleMedium9" defaultPivotStyle="PivotStyleMedium4" />'+
764 '</styleSheet>'
765};
766// Note we could use 3 `for` loops for the styles, but when gzipped there is
767// virtually no difference in size, since the above can be easily compressed
768
769// Pattern matching for special number formats. Perhaps this should be exposed
770// via an API in future?
771// Ref: section 3.8.30 - built in formatters in open spreadsheet
772// https://www.ecma-international.org/news/TC45_current_work/Office%20Open%20XML%20Part%204%20-%20Markup%20Language%20Reference.pdf
773var _excelSpecials = [
774 { match: /^\-?\d+\.\d%$/, style: 60, fmt: function (d) { return d/100; } }, // Precent with d.p.
775 { match: /^\-?\d+\.?\d*%$/, style: 56, fmt: function (d) { return d/100; } }, // Percent
776 { match: /^\-?\$[\d,]+.?\d*$/, style: 57 }, // Dollars
777 { match: /^\-?£[\d,]+.?\d*$/, style: 58 }, // Pounds
778 { match: /^\-?€[\d,]+.?\d*$/, style: 59 }, // Euros
779 { match: /^\-?\d+$/, style: 65 }, // Numbers without thousand separators
780 { match: /^\-?\d+\.\d{2}$/, style: 66 }, // Numbers 2 d.p. without thousands separators
781 { match: /^\([\d,]+\)$/, style: 61, fmt: function (d) { return -1 * d.replace(/[\(\)]/g, ''); } }, // Negative numbers indicated by brackets
782 { match: /^\([\d,]+\.\d{2}\)$/, style: 62, fmt: function (d) { return -1 * d.replace(/[\(\)]/g, ''); } }, // Negative numbers indicated by brackets - 2d.p.
783 { match: /^\-?[\d,]+$/, style: 63 }, // Numbers with thousand separators
784 { match: /^\-?[\d,]+\.\d{2}$/, style: 64 } // Numbers with 2 d.p. and thousands separators
785];
786
787
788
789/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
790 * Buttons
791 */
792
793//
794// Copy to clipboard
795//
796DataTable.ext.buttons.copyHtml5 = {
797 className: 'buttons-copy buttons-html5',
798
799 text: function ( dt ) {
800 return dt.i18n( 'buttons.copy', 'Copy' );
801 },
802
803 action: function ( e, dt, button, config ) {
804 this.processing( true );
805
806 var that = this;
807 var exportData = _exportData( dt, config );
808 var info = dt.buttons.exportInfo( config );
809 var newline = _newLine(config);
810 var output = exportData.str;
811 var hiddenDiv = $('<div/>')
812 .css( {
813 height: 1,
814 width: 1,
815 overflow: 'hidden',
816 position: 'fixed',
817 top: 0,
818 left: 0
819 } );
820
821 if ( info.title ) {
822 output = info.title + newline + newline + output;
823 }
824
825 if ( info.messageTop ) {
826 output = info.messageTop + newline + newline + output;
827 }
828
829 if ( info.messageBottom ) {
830 output = output + newline + newline + info.messageBottom;
831 }
832
833 if ( config.customize ) {
834 output = config.customize( output, config, dt );
835 }
836
837 var textarea = $('<textarea readonly/>')
838 .val( output )
839 .appendTo( hiddenDiv );
840
841 // For browsers that support the copy execCommand, try to use it
842 if ( document.queryCommandSupported('copy') ) {
843 hiddenDiv.appendTo( dt.table().container() );
844 textarea[0].focus();
845 textarea[0].select();
846
847 try {
848 var successful = document.execCommand( 'copy' );
849 hiddenDiv.remove();
850
851 if (successful) {
852 dt.buttons.info(
853 dt.i18n( 'buttons.copyTitle', 'Copy to clipboard' ),
854 dt.i18n( 'buttons.copySuccess', {
855 1: 'Copied one row to clipboard',
856 _: 'Copied %d rows to clipboard'
857 }, exportData.rows ),
858 2000
859 );
860
861 this.processing( false );
862 return;
863 }
864 }
865 catch (t) {}
866 }
867
868 // Otherwise we show the text box and instruct the user to use it
869 var message = $('<span>'+dt.i18n( 'buttons.copyKeys',
870 'Press <i>ctrl</i> or <i>\u2318</i> + <i>C</i> to copy the table data<br>to your system clipboard.<br><br>'+
871 'To cancel, click this message or press escape.' )+'</span>'
872 )
873 .append( hiddenDiv );
874
875 dt.buttons.info( dt.i18n( 'buttons.copyTitle', 'Copy to clipboard' ), message, 0 );
876
877 // Select the text so when the user activates their system clipboard
878 // it will copy that text
879 textarea[0].focus();
880 textarea[0].select();
881
882 // Event to hide the message when the user is done
883 var container = $(message).closest('.dt-button-info');
884 var close = function () {
885 container.off( 'click.buttons-copy' );
886 $(document).off( '.buttons-copy' );
887 dt.buttons.info( false );
888 };
889
890 container.on( 'click.buttons-copy', close );
891 $(document)
892 .on( 'keydown.buttons-copy', function (e) {
893 if ( e.keyCode === 27 ) { // esc
894 close();
895 that.processing( false );
896 }
897 } )
898 .on( 'copy.buttons-copy cut.buttons-copy', function () {
899 close();
900 that.processing( false );
901 } );
902 },
903
904 exportOptions: {},
905
906 fieldSeparator: '\t',
907
908 fieldBoundary: '',
909
910 header: true,
911
912 footer: false,
913
914 title: '*',
915
916 messageTop: '*',
917
918 messageBottom: '*'
919};
920
921//
922// CSV export
923//
924DataTable.ext.buttons.csvHtml5 = {
925 bom: false,
926
927 className: 'buttons-csv buttons-html5',
928
929 available: function () {
930 return window.FileReader !== undefined && window.Blob;
931 },
932
933 text: function ( dt ) {
934 return dt.i18n( 'buttons.csv', 'CSV' );
935 },
936
937 action: function ( e, dt, button, config ) {
938 this.processing( true );
939
940 // Set the text
941 var output = _exportData( dt, config ).str;
942 var info = dt.buttons.exportInfo(config);
943 var charset = config.charset;
944
945 if ( config.customize ) {
946 output = config.customize( output, config, dt );
947 }
948
949 if ( charset !== false ) {
950 if ( ! charset ) {
951 charset = document.characterSet || document.charset;
952 }
953
954 if ( charset ) {
955 charset = ';charset='+charset;
956 }
957 }
958 else {
959 charset = '';
960 }
961
962 if ( config.bom ) {
963 output = '\ufeff' + output;
964 }
965
966 _saveAs(
967 new Blob( [output], {type: 'text/csv'+charset} ),
968 info.filename,
969 true
970 );
971
972 this.processing( false );
973 },
974
975 filename: '*',
976
977 extension: '.csv',
978
979 exportOptions: {},
980
981 fieldSeparator: ',',
982
983 fieldBoundary: '"',
984
985 escapeChar: '"',
986
987 charset: null,
988
989 header: true,
990
991 footer: false
992};
993
994//
995// Excel (xlsx) export
996//
997DataTable.ext.buttons.excelHtml5 = {
998 className: 'buttons-excel buttons-html5',
999
1000 available: function () {
1001 return window.FileReader !== undefined && _jsZip() !== undefined && ! _isDuffSafari() && _serialiser;
1002 },
1003
1004 text: function ( dt ) {
1005 return dt.i18n( 'buttons.excel', 'Excel' );
1006 },
1007
1008 action: function ( e, dt, button, config ) {
1009 this.processing( true );
1010
1011 var that = this;
1012 var rowPos = 0;
1013 var dataStartRow, dataEndRow;
1014 var getXml = function ( type ) {
1015 var str = excelStrings[ type ];
1016
1017 //str = str.replace( /xmlns:/g, 'xmlns_' ).replace( /mc:/g, 'mc_' );
1018
1019 return $.parseXML( str );
1020 };
1021 var rels = getXml('xl/worksheets/sheet1.xml');
1022 var relsGet = rels.getElementsByTagName( "sheetData" )[0];
1023
1024 var xlsx = {
1025 _rels: {
1026 ".rels": getXml('_rels/.rels')
1027 },
1028 xl: {
1029 _rels: {
1030 "workbook.xml.rels": getXml('xl/_rels/workbook.xml.rels')
1031 },
1032 "workbook.xml": getXml('xl/workbook.xml'),
1033 "styles.xml": getXml('xl/styles.xml'),
1034 "worksheets": {
1035 "sheet1.xml": rels
1036 }
1037
1038 },
1039 "[Content_Types].xml": getXml('[Content_Types].xml')
1040 };
1041
1042 var data = dt.buttons.exportData( config.exportOptions );
1043 var currentRow, rowNode;
1044 var addRow = function ( row ) {
1045 currentRow = rowPos+1;
1046 rowNode = _createNode( rels, "row", { attr: {r:currentRow} } );
1047
1048 for ( var i=0, ien=row.length ; i<ien ; i++ ) {
1049 // Concat both the Cell Columns as a letter and the Row of the cell.
1050 var cellId = createCellPos(i) + '' + currentRow;
1051 var cell = null;
1052
1053 // For null, undefined of blank cell, continue so it doesn't create the _createNode
1054 if ( row[i] === null || row[i] === undefined || row[i] === '' ) {
1055 if ( config.createEmptyCells === true ) {
1056 row[i] = '';
1057 }
1058 else {
1059 continue;
1060 }
1061 }
1062
1063 var originalContent = row[i];
1064 row[i] = $.trim( row[i] );
1065
1066 // Special number formatting options
1067 for ( var j=0, jen=_excelSpecials.length ; j<jen ; j++ ) {
1068 var special = _excelSpecials[j];
1069
1070 // TODO Need to provide the ability for the specials to say
1071 // if they are returning a string, since at the moment it is
1072 // assumed to be a number
1073 if ( row[i].match && ! row[i].match(/^0\d+/) && row[i].match( special.match ) ) {
1074 var val = row[i].replace(/[^\d\.\-]/g, '');
1075
1076 if ( special.fmt ) {
1077 val = special.fmt( val );
1078 }
1079
1080 cell = _createNode( rels, 'c', {
1081 attr: {
1082 r: cellId,
1083 s: special.style
1084 },
1085 children: [
1086 _createNode( rels, 'v', { text: val } )
1087 ]
1088 } );
1089
1090 break;
1091 }
1092 }
1093
1094 if ( ! cell ) {
1095 if ( typeof row[i] === 'number' || (
1096 row[i].match &&
1097 row[i].match(/^-?\d+(\.\d+)?$/) &&
1098 ! row[i].match(/^0\d+/) )
1099 ) {
1100 // Detect numbers - don't match numbers with leading zeros
1101 // or a negative anywhere but the start
1102 cell = _createNode( rels, 'c', {
1103 attr: {
1104 t: 'n',
1105 r: cellId
1106 },
1107 children: [
1108 _createNode( rels, 'v', { text: row[i] } )
1109 ]
1110 } );
1111 }
1112 else {
1113 // String output - replace non standard characters for text output
1114 var text = ! originalContent.replace ?
1115 originalContent :
1116 originalContent.replace(/[\x00-\x09\x0B\x0C\x0E-\x1F\x7F-\x9F]/g, '');
1117
1118 cell = _createNode( rels, 'c', {
1119 attr: {
1120 t: 'inlineStr',
1121 r: cellId
1122 },
1123 children:{
1124 row: _createNode( rels, 'is', {
1125 children: {
1126 row: _createNode( rels, 't', {
1127 text: text,
1128 attr: {
1129 'xml:space': 'preserve'
1130 }
1131 } )
1132 }
1133 } )
1134 }
1135 } );
1136 }
1137 }
1138
1139 rowNode.appendChild( cell );
1140 }
1141
1142 relsGet.appendChild(rowNode);
1143 rowPos++;
1144 };
1145
1146 if ( config.customizeData ) {
1147 config.customizeData( data );
1148 }
1149
1150 var mergeCells = function ( row, colspan ) {
1151 var mergeCells = $('mergeCells', rels);
1152
1153 mergeCells[0].appendChild( _createNode( rels, 'mergeCell', {
1154 attr: {
1155 ref: 'A'+row+':'+createCellPos(colspan)+row
1156 }
1157 } ) );
1158 mergeCells.attr( 'count', parseFloat(mergeCells.attr( 'count' ))+1 );
1159 $('row:eq('+(row-1)+') c', rels).attr( 's', '51' ); // centre
1160 };
1161
1162 // Title and top messages
1163 var exportInfo = dt.buttons.exportInfo( config );
1164 if ( exportInfo.title ) {
1165 addRow( [exportInfo.title], rowPos );
1166 mergeCells( rowPos, data.header.length-1 );
1167 }
1168
1169 if ( exportInfo.messageTop ) {
1170 addRow( [exportInfo.messageTop], rowPos );
1171 mergeCells( rowPos, data.header.length-1 );
1172 }
1173
1174
1175 // Table itself
1176 if ( config.header ) {
1177 addRow( data.header, rowPos );
1178 $('row:last c', rels).attr( 's', '2' ); // bold
1179 }
1180
1181 dataStartRow = rowPos;
1182
1183 for ( var n=0, ie=data.body.length ; n<ie ; n++ ) {
1184 addRow( data.body[n], rowPos );
1185 }
1186
1187 dataEndRow = rowPos;
1188
1189 if ( config.footer && data.footer ) {
1190 addRow( data.footer, rowPos);
1191 $('row:last c', rels).attr( 's', '2' ); // bold
1192 }
1193
1194 // Below the table
1195 if ( exportInfo.messageBottom ) {
1196 addRow( [exportInfo.messageBottom], rowPos );
1197 mergeCells( rowPos, data.header.length-1 );
1198 }
1199
1200 // Set column widths
1201 var cols = _createNode( rels, 'cols' );
1202 $('worksheet', rels).prepend( cols );
1203
1204 for ( var i=0, ien=data.header.length ; i<ien ; i++ ) {
1205 cols.appendChild( _createNode( rels, 'col', {
1206 attr: {
1207 min: i+1,
1208 max: i+1,
1209 width: _excelColWidth( data, i ),
1210 customWidth: 1
1211 }
1212 } ) );
1213 }
1214
1215 // Workbook modifications
1216 var workbook = xlsx.xl['workbook.xml'];
1217
1218 $( 'sheets sheet', workbook ).attr( 'name', _sheetname( config ) );
1219
1220 // Auto filter for columns
1221 if ( config.autoFilter ) {
1222 $('mergeCells', rels).before( _createNode( rels, 'autoFilter', {
1223 attr: {
1224 ref: 'A'+dataStartRow+':'+createCellPos(data.header.length-1)+dataEndRow
1225 }
1226 } ) );
1227
1228 $('definedNames', workbook).append( _createNode( workbook, 'definedName', {
1229 attr: {
1230 name: '_xlnm._FilterDatabase',
1231 localSheetId: '0',
1232 hidden: 1
1233 },
1234 text: _sheetname(config)+'!$A$'+dataStartRow+':'+createCellPos(data.header.length-1)+dataEndRow
1235 } ) );
1236 }
1237
1238 // Let the developer customise the document if they want to
1239 if ( config.customize ) {
1240 config.customize( xlsx, config, dt );
1241 }
1242
1243 // Excel doesn't like an empty mergeCells tag
1244 if ( $('mergeCells', rels).children().length === 0 ) {
1245 $('mergeCells', rels).remove();
1246 }
1247
1248 var jszip = _jsZip();
1249 var zip = new jszip();
1250 var zipConfig = {
1251 type: 'blob',
1252 mimeType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
1253 };
1254
1255 _addToZip( zip, xlsx );
1256
1257 if ( zip.generateAsync ) {
1258 // JSZip 3+
1259 zip
1260 .generateAsync( zipConfig )
1261 .then( function ( blob ) {
1262 _saveAs( blob, exportInfo.filename );
1263 that.processing( false );
1264 } );
1265 }
1266 else {
1267 // JSZip 2.5
1268 _saveAs(
1269 zip.generate( zipConfig ),
1270 exportInfo.filename
1271 );
1272 this.processing( false );
1273 }
1274 },
1275
1276 filename: '*',
1277
1278 extension: '.xlsx',
1279
1280 exportOptions: {},
1281
1282 header: true,
1283
1284 footer: false,
1285
1286 title: '*',
1287
1288 messageTop: '*',
1289
1290 messageBottom: '*',
1291
1292 createEmptyCells: false,
1293
1294 autoFilter: false,
1295
1296 sheetName: ''
1297};
1298
1299//
1300// PDF export - using pdfMake - http://pdfmake.org
1301//
1302DataTable.ext.buttons.pdfHtml5 = {
1303 className: 'buttons-pdf buttons-html5',
1304
1305 available: function () {
1306 return window.FileReader !== undefined && _pdfMake();
1307 },
1308
1309 text: function ( dt ) {
1310 return dt.i18n( 'buttons.pdf', 'PDF' );
1311 },
1312
1313 action: function ( e, dt, button, config ) {
1314 this.processing( true );
1315
1316 var that = this;
1317 var data = dt.buttons.exportData( config.exportOptions );
1318 var info = dt.buttons.exportInfo( config );
1319 var rows = [];
1320
1321 if ( config.header ) {
1322 rows.push( $.map( data.header, function ( d ) {
1323 return {
1324 text: typeof d === 'string' ? d : d+'',
1325 style: 'tableHeader'
1326 };
1327 } ) );
1328 }
1329
1330 for ( var i=0, ien=data.body.length ; i<ien ; i++ ) {
1331 rows.push( $.map( data.body[i], function ( d ) {
1332 if ( d === null || d === undefined ) {
1333 d = '';
1334 }
1335 return {
1336 text: typeof d === 'string' ? d : d+'',
1337 style: i % 2 ? 'tableBodyEven' : 'tableBodyOdd'
1338 };
1339 } ) );
1340 }
1341
1342 if ( config.footer && data.footer) {
1343 rows.push( $.map( data.footer, function ( d ) {
1344 return {
1345 text: typeof d === 'string' ? d : d+'',
1346 style: 'tableFooter'
1347 };
1348 } ) );
1349 }
1350
1351 var doc = {
1352 pageSize: config.pageSize,
1353 pageOrientation: config.orientation,
1354 content: [
1355 {
1356 table: {
1357 headerRows: 1,
1358 body: rows
1359 },
1360 layout: 'noBorders'
1361 }
1362 ],
1363 styles: {
1364 tableHeader: {
1365 bold: true,
1366 fontSize: 11,
1367 color: 'white',
1368 fillColor: '#2d4154',
1369 alignment: 'center'
1370 },
1371 tableBodyEven: {},
1372 tableBodyOdd: {
1373 fillColor: '#f3f3f3'
1374 },
1375 tableFooter: {
1376 bold: true,
1377 fontSize: 11,
1378 color: 'white',
1379 fillColor: '#2d4154'
1380 },
1381 title: {
1382 alignment: 'center',
1383 fontSize: 15
1384 },
1385 message: {}
1386 },
1387 defaultStyle: {
1388 fontSize: 10
1389 }
1390 };
1391
1392 if ( info.messageTop ) {
1393 doc.content.unshift( {
1394 text: info.messageTop,
1395 style: 'message',
1396 margin: [ 0, 0, 0, 12 ]
1397 } );
1398 }
1399
1400 if ( info.messageBottom ) {
1401 doc.content.push( {
1402 text: info.messageBottom,
1403 style: 'message',
1404 margin: [ 0, 0, 0, 12 ]
1405 } );
1406 }
1407
1408 if ( info.title ) {
1409 doc.content.unshift( {
1410 text: info.title,
1411 style: 'title',
1412 margin: [ 0, 0, 0, 12 ]
1413 } );
1414 }
1415
1416 if ( config.customize ) {
1417 config.customize( doc, config, dt );
1418 }
1419
1420 var pdf = _pdfMake().createPdf( doc );
1421
1422 if ( config.download === 'open' && ! _isDuffSafari() ) {
1423 pdf.open();
1424 }
1425 else {
1426 pdf.download( info.filename );
1427 }
1428
1429 this.processing( false );
1430 },
1431
1432 title: '*',
1433
1434 filename: '*',
1435
1436 extension: '.pdf',
1437
1438 exportOptions: {},
1439
1440 orientation: 'portrait',
1441
1442 pageSize: 'A4',
1443
1444 header: true,
1445
1446 footer: false,
1447
1448 messageTop: '*',
1449
1450 messageBottom: '*',
1451
1452 customize: null,
1453
1454 download: 'download'
1455};
1456
1457
1458return DataTable.Buttons;
1459}));
Note: See TracBrowser for help on using the repository browser.