Subversion-Projekte lars-tiefland.cienc

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
9 lars 1
/*!
2
 * HTML5 export buttons for Buttons and DataTables.
3
 * 2015 SpryMedia Ltd - datatables.net/license
4
 *
5
 * FileSaver.js (2015-05-07.2) - MIT license
6
 * Copyright © 2015 Eli Grey - http://eligrey.com
7
 */
8
 
9
(function($, DataTable) {
10
"use strict";
11
 
12
 
13
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
14
 * FileSaver.js dependency
15
 */
16
 
17
/*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */
18
 
19
var _saveAs = (function(view) {
20
	// IE <10 is explicitly unsupported
21
	if (typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) {
22
		return;
23
	}
24
	var
25
		  doc = view.document
26
		  // only get URL when necessary in case Blob.js hasn't overridden it yet
27
		, get_URL = function() {
28
			return view.URL || view.webkitURL || view;
29
		}
30
		, save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a")
31
		, can_use_save_link = "download" in save_link
32
		, click = function(node) {
33
			var event = doc.createEvent("MouseEvents");
34
			event.initMouseEvent(
35
				"click", true, false, view, 0, 0, 0, 0, 0
36
				, false, false, false, false, 0, null
37
			);
38
			node.dispatchEvent(event);
39
		}
40
		, webkit_req_fs = view.webkitRequestFileSystem
41
		, req_fs = view.requestFileSystem || webkit_req_fs || view.mozRequestFileSystem
42
		, throw_outside = function(ex) {
43
			(view.setImmediate || view.setTimeout)(function() {
44
				throw ex;
45
			}, 0);
46
		}
47
		, force_saveable_type = "application/octet-stream"
48
		, fs_min_size = 0
49
		// See https://code.google.com/p/chromium/issues/detail?id=375297#c7 and
50
		// https://github.com/eligrey/FileSaver.js/commit/485930a#commitcomment-8768047
51
		// for the reasoning behind the timeout and revocation flow
52
		, arbitrary_revoke_timeout = 500 // in ms
53
		, revoke = function(file) {
54
			var revoker = function() {
55
				if (typeof file === "string") { // file is an object URL
56
					get_URL().revokeObjectURL(file);
57
				} else { // file is a File
58
					file.remove();
59
				}
60
			};
61
			if (view.chrome) {
62
				revoker();
63
			} else {
64
				setTimeout(revoker, arbitrary_revoke_timeout);
65
			}
66
		}
67
		, dispatch = function(filesaver, event_types, event) {
68
			event_types = [].concat(event_types);
69
			var i = event_types.length;
70
			while (i--) {
71
				var listener = filesaver["on" + event_types[i]];
72
				if (typeof listener === "function") {
73
					try {
74
						listener.call(filesaver, event || filesaver);
75
					} catch (ex) {
76
						throw_outside(ex);
77
					}
78
				}
79
			}
80
		}
81
		, auto_bom = function(blob) {
82
			// prepend BOM for UTF-8 XML and text/* types (including HTML)
83
			if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) {
84
				return new Blob(["\ufeff", blob], {type: blob.type});
85
			}
86
			return blob;
87
		}
88
		, FileSaver = function(blob, name) {
89
			blob = auto_bom(blob);
90
			// First try a.download, then web filesystem, then object URLs
91
			var
92
				  filesaver = this
93
				, type = blob.type
94
				, blob_changed = false
95
				, object_url
96
				, target_view
97
				, dispatch_all = function() {
98
					dispatch(filesaver, "writestart progress write writeend".split(" "));
99
				}
100
				// on any filesys errors revert to saving with object URLs
101
				, fs_error = function() {
102
					// don't create more object URLs than needed
103
					if (blob_changed || !object_url) {
104
						object_url = get_URL().createObjectURL(blob);
105
					}
106
					if (target_view) {
107
						target_view.location.href = object_url;
108
					} else {
109
						var new_tab = view.open(object_url, "_blank");
110
						if (new_tab === undefined && typeof safari !== "undefined") {
111
							//Apple do not allow window.open, see http://bit.ly/1kZffRI
112
							view.location.href = object_url;
113
						}
114
					}
115
					filesaver.readyState = filesaver.DONE;
116
					dispatch_all();
117
					revoke(object_url);
118
				}
119
				, abortable = function(func) {
120
					return function() {
121
						if (filesaver.readyState !== filesaver.DONE) {
122
							return func.apply(this, arguments);
123
						}
124
					};
125
				}
126
				, create_if_not_found = {create: true, exclusive: false}
127
				, slice
128
			;
129
			filesaver.readyState = filesaver.INIT;
130
			if (!name) {
131
				name = "download";
132
			}
133
			if (can_use_save_link) {
134
				object_url = get_URL().createObjectURL(blob);
135
				save_link.href = object_url;
136
				save_link.download = name;
137
				click(save_link);
138
				filesaver.readyState = filesaver.DONE;
139
				dispatch_all();
140
				revoke(object_url);
141
				return;
142
			}
143
			// Object and web filesystem URLs have a problem saving in Google Chrome when
144
			// viewed in a tab, so I force save with application/octet-stream
145
			// http://code.google.com/p/chromium/issues/detail?id=91158
146
			// Update: Google errantly closed 91158, I submitted it again:
147
			// https://code.google.com/p/chromium/issues/detail?id=389642
148
			if (view.chrome && type && type !== force_saveable_type) {
149
				slice = blob.slice || blob.webkitSlice;
150
				blob = slice.call(blob, 0, blob.size, force_saveable_type);
151
				blob_changed = true;
152
			}
153
			// Since I can't be sure that the guessed media type will trigger a download
154
			// in WebKit, I append .download to the filename.
155
			// https://bugs.webkit.org/show_bug.cgi?id=65440
156
			if (webkit_req_fs && name !== "download") {
157
				name += ".download";
158
			}
159
			if (type === force_saveable_type || webkit_req_fs) {
160
				target_view = view;
161
			}
162
			if (!req_fs) {
163
				fs_error();
164
				return;
165
			}
166
			fs_min_size += blob.size;
167
			req_fs(view.TEMPORARY, fs_min_size, abortable(function(fs) {
168
				fs.root.getDirectory("saved", create_if_not_found, abortable(function(dir) {
169
					var save = function() {
170
						dir.getFile(name, create_if_not_found, abortable(function(file) {
171
							file.createWriter(abortable(function(writer) {
172
								writer.onwriteend = function(event) {
173
									target_view.location.href = file.toURL();
174
									filesaver.readyState = filesaver.DONE;
175
									dispatch(filesaver, "writeend", event);
176
									revoke(file);
177
								};
178
								writer.onerror = function() {
179
									var error = writer.error;
180
									if (error.code !== error.ABORT_ERR) {
181
										fs_error();
182
									}
183
								};
184
								"writestart progress write abort".split(" ").forEach(function(event) {
185
									writer["on" + event] = filesaver["on" + event];
186
								});
187
								writer.write(blob);
188
								filesaver.abort = function() {
189
									writer.abort();
190
									filesaver.readyState = filesaver.DONE;
191
								};
192
								filesaver.readyState = filesaver.WRITING;
193
							}), fs_error);
194
						}), fs_error);
195
					};
196
					dir.getFile(name, {create: false}, abortable(function(file) {
197
						// delete file if it already exists
198
						file.remove();
199
						save();
200
					}), abortable(function(ex) {
201
						if (ex.code === ex.NOT_FOUND_ERR) {
202
							save();
203
						} else {
204
							fs_error();
205
						}
206
					}));
207
				}), fs_error);
208
			}), fs_error);
209
		}
210
		, FS_proto = FileSaver.prototype
211
		, saveAs = function(blob, name) {
212
			return new FileSaver(blob, name);
213
		}
214
	;
215
	// IE 10+ (native saveAs)
216
	if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) {
217
		return function(blob, name) {
218
			return navigator.msSaveOrOpenBlob(auto_bom(blob), name);
219
		};
220
	}
221
 
222
	FS_proto.abort = function() {
223
		var filesaver = this;
224
		filesaver.readyState = filesaver.DONE;
225
		dispatch(filesaver, "abort");
226
	};
227
	FS_proto.readyState = FS_proto.INIT = 0;
228
	FS_proto.WRITING = 1;
229
	FS_proto.DONE = 2;
230
 
231
	FS_proto.error =
232
	FS_proto.onwritestart =
233
	FS_proto.onprogress =
234
	FS_proto.onwrite =
235
	FS_proto.onabort =
236
	FS_proto.onerror =
237
	FS_proto.onwriteend =
238
		null;
239
 
240
	return saveAs;
241
}(window));
242
 
243
 
244
 
245
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
246
 * Local (private) functions
247
 */
248
 
249
/**
250
 * Get the title / file name for an exported file.
251
 *
252
 * @param {object}  config       Button configuration
253
 * @param {boolean} incExtension Include the file name extension
254
 */
255
var _filename = function ( config, incExtension )
256
{
257
	var title = config.title;
258
 
259
	if ( title.indexOf( '*' ) !== -1 ) {
260
		title = title.replace( '*', $('title').text() );
261
	}
262
 
263
	// Strip characters which the OS will object to
264
	title = title.replace(/[^a-zA-Z0-9_\u00A1-\uFFFF\.,\-_ !\(\)]/g, "");
265
 
266
	return incExtension === undefined || incExtension === true ?
267
		title+config.extension :
268
		title;
269
};
270
 
271
/**
272
 * Get the newline character(s)
273
 *
274
 * @param {object}  config Button configuration
275
 * @return {string}        Newline character
276
 */
277
var _newLine = function ( config )
278
{
279
	return config.newline ?
280
		config.newline :
281
		navigator.userAgent.match(/Windows/) ?
282
			'\r\n' :
283
			'\n';
284
};
285
 
286
/**
287
 * Combine the data from the `buttons.exportData` method into a string that
288
 * will be used in the export file.
289
 *
290
 * @param  {DataTable.Api} dt     DataTables API instance
291
 * @param  {object}        config Button configuration
292
 * @return {object}               The data to export
293
 */
294
var _exportData = function ( dt, config )
295
{
296
	var newLine = _newLine( config );
297
	var data = dt.buttons.exportData( config.exportOptions );
298
	var join = function ( a ) {
299
		var s = '';
300
		var boundary = config.fieldBoundary;
301
		var separator = config.fieldSeparator;
302
 
303
		// If there is a field boundary, then we might need to escape it in
304
		// the source data
305
		for ( var i=0, ien=a.length ; i<ien ; i++ ) {
306
			if ( i > 0 ) {
307
				s += separator;
308
			}
309
 
310
			s += boundary ?
311
				boundary + a[i].replace( boundary, '\\'+boundary ) + boundary :
312
				a[i];
313
		}
314
 
315
		return s;
316
	};
317
 
318
	var header = config.header ? join( data.header )+newLine : '';
319
	var footer = config.footer ? newLine+join( data.footer ) : '';
320
	var body = [];
321
 
322
	for ( var i=0, ien=data.body.length ; i<ien ; i++ ) {
323
		body.push( join( data.body[i] ) );
324
	}
325
 
326
	return {
327
		str: header + body.join( newLine ) + footer,
328
		rows: body.length
329
	};
330
};
331
 
332
/**
333
 * Safari's data: support for creating and downloading files is really poor, so
334
 * various options need to be disabled in it. See
335
 * https://bugs.webkit.org/show_bug.cgi?id=102914
336
 *
337
 * @return {Boolean} `true` if Safari
338
 */
339
var _isSafari = function ()
340
{
341
	return navigator.userAgent.indexOf('Safari') !== -1 &&
342
		navigator.userAgent.indexOf('Chrome') === -1 &&
343
		navigator.userAgent.indexOf('Opera') === -1;
344
};
345
 
346
 
347
// Excel - Pre-defined strings to build a minimal XLSX file
348
var excelStrings = {
349
	"_rels/.rels": '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\
350
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">\
351
	<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/>\
352
</Relationships>',
353
 
354
	"xl/_rels/workbook.xml.rels": '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\
355
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">\
356
	<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet1.xml"/>\
357
</Relationships>',
358
 
359
	"[Content_Types].xml": '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\
360
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">\
361
	<Default Extension="xml" ContentType="application/xml"/>\
362
	<Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>\
363
	<Default Extension="jpeg" ContentType="image/jpeg"/>\
364
	<Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/>\
365
	<Override PartName="/xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/>\
366
</Types>',
367
 
368
	"xl/workbook.xml": '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\
369
<workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">\
370
	<fileVersion appName="xl" lastEdited="5" lowestEdited="5" rupBuild="24816"/>\
371
	<workbookPr showInkAnnotation="0" autoCompressPictures="0"/>\
372
	<bookViews>\
373
		<workbookView xWindow="0" yWindow="0" windowWidth="25600" windowHeight="19020" tabRatio="500"/>\
374
	</bookViews>\
375
	<sheets>\
376
		<sheet name="Sheet1" sheetId="1" r:id="rId1"/>\
377
	</sheets>\
378
</workbook>',
379
 
380
	"xl/worksheets/sheet1.xml": '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\
381
<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">\
382
	<sheetData>\
383
		__DATA__\
384
	</sheetData>\
385
</worksheet>'
386
};
387
 
388
 
389
 
390
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
391
 * Buttons
392
 */
393
 
394
//
395
// Copy to clipboard
396
//
397
DataTable.ext.buttons.copyHtml5 = {
398
	className: 'buttons-copy buttons-html5',
399
 
400
	text: function ( dt ) {
401
		return dt.i18n( 'buttons.copy', 'Copy' );
402
	},
403
 
404
	action: function ( e, dt, button, config ) {
405
		// This button is slightly sneaky as there is no HTML API to copy text
406
		// to a clipboard, so what it does is use the buttons information
407
		// element with an also completely hidden textarea that contains the
408
		// data to be copied. That is pre-selected so the user just needs to
409
		// activate their system clipboard.
410
		var newLine = _newLine( config );
411
		var output = _exportData( dt, config ).str;
412
		var message = $('<span>'+dt.i18n( 'buttons.copyKeys',
413
				'Press <i>ctrl</i> or <i>\u2318</i> + <i>C</i> to copy the table data<br>to your system clipboard.<br><br>'+
414
				'To cancel, click this message or press escape.' )+'</span>'
415
			)
416
			.append( $('<div/>')
417
				.css( {
418
					height: 1,
419
					width: 1,
420
					overflow: 'hidden'
421
				} )
422
				.append(
423
					$('<textarea readonly/>').val( output )
424
				)
425
		);
426
 
427
		dt.buttons.info( dt.i18n( 'buttons.copyTitle', 'Copy to clipboard' ), message, 0 );
428
 
429
		// Select the text so when the user activates their system clipboard
430
		// it will copy that text
431
		message.find('textarea')[0].focus();
432
		message.find('textarea')[0].select();
433
 
434
		// Event to hide the message when the user is done
435
		var container = $(message).closest('.dt-button-info');
436
		var close = function () {
437
			container.off( 'click.buttons-copy' );
438
			$(document).off( '.buttons-copy' );
439
			dt.buttons.info( false );
440
		};
441
 
442
		container.on( 'click.buttons-copy', close );
443
		$(document)
444
			.on( 'keydown.buttons-copy', function (e) {
445
				if ( e.keyCode === 27 ) { // esc
446
					close();
447
				}
448
			} )
449
			.on( 'copy.buttons-copy cut.buttons-copy', function () {
450
				close();
451
			} );
452
	},
453
 
454
	exportOptions: {},
455
 
456
	fieldSeparator: '\t',
457
 
458
	fieldBoundary: '',
459
 
460
	header: true,
461
 
462
	footer: false
463
};
464
 
465
//
466
// CSV export
467
//
468
DataTable.ext.buttons.csvHtml5 = {
469
	className: 'buttons-csv buttons-html5',
470
 
471
	available: function () {
472
		return window.FileReader !== undefined && window.Blob;
473
	},
474
 
475
	text: function ( dt ) {
476
		return dt.i18n( 'buttons.csv', 'CSV' );
477
	},
478
 
479
	action: function ( e, dt, button, config ) {
480
		// Set the text
481
		var newLine = _newLine( config );
482
		var output = _exportData( dt, config ).str;
483
 
484
		_saveAs(
485
			new Blob( [output], {type : 'text/csv'} ),
486
			_filename( config )
487
		);
488
	},
489
 
490
	title: '*',
491
 
492
	extension: '.csv',
493
 
494
	exportOptions: {},
495
 
496
	fieldSeparator: ',',
497
 
498
	fieldBoundary: '"',
499
 
500
	header: true,
501
 
502
	footer: false
503
};
504
 
505
//
506
// Excel (xlsx) export
507
//
508
DataTable.ext.buttons.excelHtml5 = {
509
	className: 'buttons-excel buttons-html5',
510
 
511
	available: function () {
512
		return window.FileReader !== undefined && window.JSZip !== undefined && ! _isSafari();
513
	},
514
 
515
	text: function ( dt ) {
516
		return dt.i18n( 'buttons.excel', 'Excel' );
517
	},
518
 
519
	action: function ( e, dt, button, config ) {
520
		// Set the text
521
		var xml = '';
522
		var data = dt.buttons.exportData( config.exportOptions );
523
		var addRow = function ( row ) {
524
			var cells = [];
525
 
526
			for ( var i=0, ien=row.length ; i<ien ; i++ ) {
527
				cells.push( $.isNumeric( row[i] ) ?
528
					'<c t="n"><v>'+row[i]+'</v></c>' :
529
					'<c t="inlineStr"><is><t>'+
530
						row[i].replace(/&(?!amp;)/g, '&amp;')+
531
					'</t></is></c>'
532
				);
533
			}
534
 
535
			return '<row>'+cells.join('')+'</row>';
536
		};
537
 
538
		if ( config.header ) {
539
			xml += addRow( data.header );
540
		}
541
 
542
		for ( var i=0, ien=data.body.length ; i<ien ; i++ ) {
543
			xml += addRow( data.body[i] );
544
		}
545
 
546
		if ( config.footer ) {
547
			xml += addRow( data.footer );
548
		}
549
 
550
		var zip           = new window.JSZip();
551
		var _rels         = zip.folder("_rels");
552
		var xl            = zip.folder("xl");
553
		var xl_rels       = zip.folder("xl/_rels");
554
		var xl_worksheets = zip.folder("xl/worksheets");
555
 
556
		zip.file(           '[Content_Types].xml', excelStrings['[Content_Types].xml'] );
557
		_rels.file(         '.rels',               excelStrings['_rels/.rels'] );
558
		xl.file(            'workbook.xml',        excelStrings['xl/workbook.xml'] );
559
		xl_rels.file(       'workbook.xml.rels',   excelStrings['xl/_rels/workbook.xml.rels'] );
560
		xl_worksheets.file( 'sheet1.xml',          excelStrings['xl/worksheets/sheet1.xml'].replace( '__DATA__', xml ) );
561
 
562
		_saveAs(
563
			zip.generate( {type:"blob"} ),
564
			_filename( config )
565
		);
566
	},
567
 
568
	title: '*',
569
 
570
	extension: '.xlsx',
571
 
572
	exportOptions: {},
573
 
574
	header: true,
575
 
576
	footer: false
577
};
578
 
579
//
580
// PDF export - using pdfMake - http://pdfmake.org
581
//
582
DataTable.ext.buttons.pdfHtml5 = {
583
	className: 'buttons-pdf buttons-html5',
584
 
585
	available: function () {
586
		return window.FileReader !== undefined && window.pdfMake;
587
	},
588
 
589
	text: function ( dt ) {
590
		return dt.i18n( 'buttons.pdf', 'PDF' );
591
	},
592
 
593
	action: function ( e, dt, button, config ) {
594
		var newLine = _newLine( config );
595
		var data = dt.buttons.exportData( config.exportOptions );
596
		var rows = [];
597
 
598
		if ( config.header ) {
599
			rows.push( $.map( data.header, function ( d ) {
600
				return {
601
					text: d,
602
					style: 'tableHeader'
603
				};
604
			} ) );
605
		}
606
 
607
		for ( var i=0, ien=data.body.length ; i<ien ; i++ ) {
608
			rows.push( $.map( data.body[i], function ( d ) {
609
				return {
610
					text: d,
611
					style: i % 2 ? 'tableBodyEven' : 'tableBodyOdd'
612
				};
613
			} ) );
614
		}
615
 
616
		if ( config.footer ) {
617
			rows.push( $.map( data.footer, function ( d ) {
618
				return {
619
					text: d,
620
					style: 'tableFooter'
621
				};
622
			} ) );
623
		}
624
 
625
		var doc = {
626
			pageSize: config.pageSize,
627
			pageOrientation: config.orientation,
628
			content: [
629
				{
630
					table: {
631
						headerRows: 1,
632
						body: rows
633
					},
634
					layout: 'noBorders'
635
				}
636
			],
637
			styles: {
638
				tableHeader: {
639
					bold: true,
640
					fontSize: 11,
641
					color: 'white',
642
					fillColor: '#2d4154',
643
					alignment: 'center'
644
				},
645
				tableBodyEven: {},
646
				tableBodyOdd: {
647
					fillColor: '#f3f3f3'
648
				},
649
				tableFooter: {
650
					bold: true,
651
					fontSize: 11,
652
					color: 'white',
653
					fillColor: '#2d4154'
654
				},
655
				title: {
656
					alignment: 'center',
657
					fontSize: 15
658
				},
659
				message: {}
660
			},
661
			defaultStyle: {
662
				fontSize: 10
663
			}
664
		};
665
 
666
		if ( config.message ) {
667
			doc.content.unshift( {
668
				text: config.message,
669
				style: 'message',
670
				margin: [ 0, 0, 0, 12 ]
671
			} );
672
		}
673
 
674
		if ( config.title ) {
675
			doc.content.unshift( {
676
				text: _filename( config, false ),
677
				style: 'title',
678
				margin: [ 0, 0, 0, 12 ]
679
			} );
680
		}
681
 
682
		if ( config.customize ) {
683
			config.customize( doc );
684
		}
685
 
686
		var pdf = window.pdfMake.createPdf( doc );
687
 
688
		if ( config.download === 'open' && ! _isSafari() ) {
689
			pdf.open();
690
		}
691
		else {
692
			pdf.getBuffer( function (buffer) {
693
				var blob = new Blob( [buffer], {type:'application/pdf'} );
694
 
695
				_saveAs( blob, _filename( config ) );
696
			} );
697
		}
698
	},
699
 
700
	title: '*',
701
 
702
	extension: '.pdf',
703
 
704
	exportOptions: {},
705
 
706
	orientation: 'portrait',
707
 
708
	pageSize: 'A4',
709
 
710
	header: true,
711
 
712
	footer: false,
713
 
714
	message: null,
715
 
716
	customize: null,
717
 
718
	download: 'download'
719
};
720
 
721
 
722
})(jQuery, jQuery.fn.dataTable);