| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463 | /*! * HTML5 export buttons for Buttons and DataTables. * 2016 SpryMedia Ltd - datatables.net/license * * FileSaver.js (1.3.3) - MIT license * Copyright © 2016 Eli Grey - http://eligrey.com */(function( factory ){	if ( typeof define === 'function' && define.amd ) {		// AMD		define( ['jquery', 'datatables.net', 'datatables.net-buttons'], function ( $ ) {			return factory( $, window, document );		} );	}	else if ( typeof exports === 'object' ) {		// CommonJS		module.exports = function (root, $, jszip, pdfmake) {			if ( ! root ) {				root = window;			}			if ( ! $ || ! $.fn.dataTable ) {				$ = require('datatables.net')(root, $).$;			}			if ( ! $.fn.dataTable.Buttons ) {				require('datatables.net-buttons')(root, $);			}			return factory( $, root, root.document, jszip, pdfmake );		};	}	else {		// Browser		factory( jQuery, window, document );	}}(function( $, window, document, jszip, pdfmake, undefined ) {'use strict';var DataTable = $.fn.dataTable;// Allow the constructor to pass in JSZip and PDFMake from external requires.// Otherwise, use globally defined variables, if they are available.function _jsZip () {	return jszip || window.JSZip;}function _pdfMake () {	return pdfmake || window.pdfMake;}DataTable.Buttons.pdfMake = function (_) {	if ( ! _ ) {		return _pdfMake();	}	pdfmake = _;}DataTable.Buttons.jszip = function (_) {	if ( ! _ ) {		return _jsZip();	}	jszip = _;}/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * FileSaver.js dependency *//*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */var _saveAs = (function(view) {	"use strict";	// IE <10 is explicitly unsupported	if (typeof view === "undefined" || typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) {		return;	}	var		  doc = view.document		  // only get URL when necessary in case Blob.js hasn't overridden it yet		, get_URL = function() {			return view.URL || view.webkitURL || view;		}		, save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a")		, can_use_save_link = "download" in save_link		, click = function(node) {			var event = new MouseEvent("click");			node.dispatchEvent(event);		}		, is_safari = /constructor/i.test(view.HTMLElement) || view.safari		, is_chrome_ios =/CriOS\/[\d]+/.test(navigator.userAgent)		, throw_outside = function(ex) {			(view.setImmediate || view.setTimeout)(function() {				throw ex;			}, 0);		}		, force_saveable_type = "application/octet-stream"		// the Blob API is fundamentally broken as there is no "downloadfinished" event to subscribe to		, arbitrary_revoke_timeout = 1000 * 40 // in ms		, revoke = function(file) {			var revoker = function() {				if (typeof file === "string") { // file is an object URL					get_URL().revokeObjectURL(file);				} else { // file is a File					file.remove();				}			};			setTimeout(revoker, arbitrary_revoke_timeout);		}		, dispatch = function(filesaver, event_types, event) {			event_types = [].concat(event_types);			var i = event_types.length;			while (i--) {				var listener = filesaver["on" + event_types[i]];				if (typeof listener === "function") {					try {						listener.call(filesaver, event || filesaver);					} catch (ex) {						throw_outside(ex);					}				}			}		}		, auto_bom = function(blob) {			// prepend BOM for UTF-8 XML and text/* types (including HTML)			// note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF			if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) {				return new Blob([String.fromCharCode(0xFEFF), blob], {type: blob.type});			}			return blob;		}		, FileSaver = function(blob, name, no_auto_bom) {			if (!no_auto_bom) {				blob = auto_bom(blob);			}			// First try a.download, then web filesystem, then object URLs			var				  filesaver = this				, type = blob.type				, force = type === force_saveable_type				, object_url				, dispatch_all = function() {					dispatch(filesaver, "writestart progress write writeend".split(" "));				}				// on any filesys errors revert to saving with object URLs				, fs_error = function() {					if ((is_chrome_ios || (force && is_safari)) && view.FileReader) {						// Safari doesn't allow downloading of blob urls						var reader = new FileReader();						reader.onloadend = function() {							var url = is_chrome_ios ? reader.result : reader.result.replace(/^data:[^;]*;/, 'data:attachment/file;');							var popup = view.open(url, '_blank');							if(!popup) view.location.href = url;							url=undefined; // release reference before dispatching							filesaver.readyState = filesaver.DONE;							dispatch_all();						};						reader.readAsDataURL(blob);						filesaver.readyState = filesaver.INIT;						return;					}					// don't create more object URLs than needed					if (!object_url) {						object_url = get_URL().createObjectURL(blob);					}					if (force) {						view.location.href = object_url;					} else {						var opened = view.open(object_url, "_blank");						if (!opened) {							// Apple does not allow window.open, see https://developer.apple.com/library/safari/documentation/Tools/Conceptual/SafariExtensionGuide/WorkingwithWindowsandTabs/WorkingwithWindowsandTabs.html							view.location.href = object_url;						}					}					filesaver.readyState = filesaver.DONE;					dispatch_all();					revoke(object_url);				}			;			filesaver.readyState = filesaver.INIT;			if (can_use_save_link) {				object_url = get_URL().createObjectURL(blob);				setTimeout(function() {					save_link.href = object_url;					save_link.download = name;					click(save_link);					dispatch_all();					revoke(object_url);					filesaver.readyState = filesaver.DONE;				});				return;			}			fs_error();		}		, FS_proto = FileSaver.prototype		, saveAs = function(blob, name, no_auto_bom) {			return new FileSaver(blob, name || blob.name || "download", no_auto_bom);		}	;	// IE 10+ (native saveAs)	if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) {		return function(blob, name, no_auto_bom) {			name = name || blob.name || "download";			if (!no_auto_bom) {				blob = auto_bom(blob);			}			return navigator.msSaveOrOpenBlob(blob, name);		};	}	FS_proto.abort = function(){};	FS_proto.readyState = FS_proto.INIT = 0;	FS_proto.WRITING = 1;	FS_proto.DONE = 2;	FS_proto.error =	FS_proto.onwritestart =	FS_proto.onprogress =	FS_proto.onwrite =	FS_proto.onabort =	FS_proto.onerror =	FS_proto.onwriteend =		null;	return saveAs;}(	   typeof self !== "undefined" && self	|| typeof window !== "undefined" && window	|| this.content));// Expose file saver on the DataTables API. Can't attach to `DataTables.Buttons`// since this file can be loaded before Button's core!DataTable.fileSave = _saveAs;/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Local (private) functions *//** * Get the sheet name for Excel exports. * * @param {object}	config Button configuration */var _sheetname = function ( config ){	var sheetName = 'Sheet1';	if ( config.sheetName ) {		sheetName = config.sheetName.replace(/[\[\]\*\/\\\?\:]/g, '');	}	return sheetName;};/** * Get the newline character(s) * * @param {object}	config Button configuration * @return {string}				Newline character */var _newLine = function ( config ){	return config.newline ?		config.newline :		navigator.userAgent.match(/Windows/) ?			'\r\n' :			'\n';};/** * Combine the data from the `buttons.exportData` method into a string that * will be used in the export file. * * @param	{DataTable.Api} dt		 DataTables API instance * @param	{object}				config Button configuration * @return {object}							 The data to export */var _exportData = function ( dt, config ){	var newLine = _newLine( config );	var data = dt.buttons.exportData( config.exportOptions );	var boundary = config.fieldBoundary;	var separator = config.fieldSeparator;	var reBoundary = new RegExp( boundary, 'g' );	var escapeChar = config.escapeChar !== undefined ?		config.escapeChar :		'\\';	var join = function ( a ) {		var s = '';		// If there is a field boundary, then we might need to escape it in		// the source data		for ( var i=0, ien=a.length ; i<ien ; i++ ) {			if ( i > 0 ) {				s += separator;			}			s += boundary ?				boundary + ('' + a[i]).replace( reBoundary, escapeChar+boundary ) + boundary :				a[i];		}		return s;	};	var header = config.header ? join( data.header )+newLine : '';	var footer = config.footer && data.footer ? newLine+join( data.footer ) : '';	var body = [];	for ( var i=0, ien=data.body.length ; i<ien ; i++ ) {		body.push( join( data.body[i] ) );	}	return {		str: header + body.join( newLine ) + footer,		rows: body.length	};};/** * Older versions of Safari (prior to tech preview 18) don't support the * download option required. * * @return {Boolean} `true` if old Safari */var _isDuffSafari = function (){	var safari = navigator.userAgent.indexOf('Safari') !== -1 &&		navigator.userAgent.indexOf('Chrome') === -1 &&		navigator.userAgent.indexOf('Opera') === -1;	if ( ! safari ) {		return false;	}	var version = navigator.userAgent.match( /AppleWebKit\/(\d+\.\d+)/ );	if ( version && version.length > 1 && version[1]*1 < 603.1 ) {		return true;	}	return false;};/** * Convert from numeric position to letter for column names in Excel * @param  {int} n Column number * @return {string} Column letter(s) name */function createCellPos( n ){	var ordA = 'A'.charCodeAt(0);	var ordZ = 'Z'.charCodeAt(0);	var len = ordZ - ordA + 1;	var s = "";	while( n >= 0 ) {		s = String.fromCharCode(n % len + ordA) + s;		n = Math.floor(n / len) - 1;	}	return s;}try {	var _serialiser = new XMLSerializer();	var _ieExcel;}catch (t) {}/** * Recursively add XML files from an object's structure to a ZIP file. This * allows the XSLX file to be easily defined with an object's structure matching * the files structure. * * @param {JSZip} zip ZIP package * @param {object} obj Object to add (recursive) */function _addToZip( zip, obj ) {	if ( _ieExcel === undefined ) {		// Detect if we are dealing with IE's _awful_ serialiser by seeing if it		// drop attributes		_ieExcel = _serialiser			.serializeToString(				( new window.DOMParser() ).parseFromString( excelStrings['xl/worksheets/sheet1.xml'], 'text/xml' )			)			.indexOf( 'xmlns:r' ) === -1;	}	$.each( obj, function ( name, val ) {		if ( $.isPlainObject( val ) ) {			var newDir = zip.folder( name );			_addToZip( newDir, val );		}		else {			if ( _ieExcel ) {				// IE's XML serialiser will drop some name space attributes from				// from the root node, so we need to save them. Do this by				// replacing the namespace nodes with a regular attribute that				// we convert back when serialised. Edge does not have this				// issue				var worksheet = val.childNodes[0];				var i, ien;				var attrs = [];				for ( i=worksheet.attributes.length-1 ; i>=0 ; i-- ) {					var attrName = worksheet.attributes[i].nodeName;					var attrValue = worksheet.attributes[i].nodeValue;					if ( attrName.indexOf( ':' ) !== -1 ) {						attrs.push( { name: attrName, value: attrValue } );						worksheet.removeAttribute( attrName );					}				}				for ( i=0, ien=attrs.length ; i<ien ; i++ ) {					var attr = val.createAttribute( attrs[i].name.replace( ':', '_dt_b_namespace_token_' ) );					attr.value = attrs[i].value;					worksheet.setAttributeNode( attr );				}			}			var str = _serialiser.serializeToString(val);			// Fix IE's XML			if ( _ieExcel ) {				// IE doesn't include the XML declaration				if ( str.indexOf( '<?xml' ) === -1 ) {					str = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'+str;				}				// Return namespace attributes to being as such				str = str.replace( /_dt_b_namespace_token_/g, ':' );				// Remove testing name space that IE puts into the space preserve attr				str = str.replace( /xmlns:NS[\d]+="" NS[\d]+:/g, '' );			}			// Safari, IE and Edge will put empty name space attributes onto			// various elements making them useless. This strips them out			str = str.replace( /<([^<>]*?) xmlns=""([^<>]*?)>/g, '<$1 $2>' );			zip.file( name, str );		}	} );}/** * Create an XML node and add any children, attributes, etc without needing to * be verbose in the DOM. * * @param  {object} doc      XML document * @param  {string} nodeName Node name * @param  {object} opts     Options - can be `attr` (attributes), `children` *   (child nodes) and `text` (text content) * @return {node}            Created node */function _createNode( doc, nodeName, opts ) {	var tempNode = doc.createElement( nodeName );	if ( opts ) {		if ( opts.attr ) {			$(tempNode).attr( opts.attr );		}		if ( opts.children ) {			$.each( opts.children, function ( key, value ) {				tempNode.appendChild( value );			} );		}		if ( opts.text !== null && opts.text !== undefined ) {			tempNode.appendChild( doc.createTextNode( opts.text ) );		}	}	return tempNode;}/** * Get the width for an Excel column based on the contents of that column * @param  {object} data Data for export * @param  {int}    col  Column index * @return {int}         Column width */function _excelColWidth( data, col ) {	var max = data.header[col].length;	var len, lineSplit, str;	if ( data.footer && data.footer[col].length > max ) {		max = data.footer[col].length;	}	for ( var i=0, ien=data.body.length ; i<ien ; i++ ) {		var point = data.body[i][col];		str = point !== null && point !== undefined ?			point.toString() :			'';		// If there is a newline character, workout the width of the column		// based on the longest line in the string		if ( str.indexOf('\n') !== -1 ) {			lineSplit = str.split('\n');			lineSplit.sort( function (a, b) {				return b.length - a.length;			} );			len = lineSplit[0].length;		}		else {			len = str.length;		}		if ( len > max ) {			max = len;		}		// Max width rather than having potentially massive column widths		if ( max > 40 ) {			return 54; // 40 * 1.35		}	}	max *= 1.35;	// And a min width	return max > 6 ? max : 6;}// Excel - Pre-defined strings to build a basic XLSX filevar excelStrings = {	"_rels/.rels":		'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'+		'<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">'+			'<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/>'+		'</Relationships>',	"xl/_rels/workbook.xml.rels":		'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'+		'<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">'+			'<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet1.xml"/>'+			'<Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/>'+		'</Relationships>',	"[Content_Types].xml":		'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'+		'<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">'+			'<Default Extension="xml" ContentType="application/xml" />'+			'<Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml" />'+			'<Default Extension="jpeg" ContentType="image/jpeg" />'+			'<Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml" />'+			'<Override PartName="/xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml" />'+			'<Override PartName="/xl/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml" />'+		'</Types>',	"xl/workbook.xml":		'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'+		'<workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">'+			'<fileVersion appName="xl" lastEdited="5" lowestEdited="5" rupBuild="24816"/>'+			'<workbookPr showInkAnnotation="0" autoCompressPictures="0"/>'+			'<bookViews>'+				'<workbookView xWindow="0" yWindow="0" windowWidth="25600" windowHeight="19020" tabRatio="500"/>'+			'</bookViews>'+			'<sheets>'+				'<sheet name="Sheet1" sheetId="1" r:id="rId1"/>'+			'</sheets>'+			'<definedNames/>'+		'</workbook>',	"xl/worksheets/sheet1.xml":		'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'+		'<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">'+			'<sheetData/>'+			'<mergeCells count="0"/>'+		'</worksheet>',	"xl/styles.xml":		'<?xml version="1.0" encoding="UTF-8"?>'+		'<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">'+			'<numFmts count="6">'+				'<numFmt numFmtId="164" formatCode="#,##0.00_-\ [$$-45C]"/>'+				'<numFmt numFmtId="165" formatCode=""£"#,##0.00"/>'+				'<numFmt numFmtId="166" formatCode="[$€-2]\ #,##0.00"/>'+				'<numFmt numFmtId="167" formatCode="0.0%"/>'+				'<numFmt numFmtId="168" formatCode="#,##0;(#,##0)"/>'+				'<numFmt numFmtId="169" formatCode="#,##0.00;(#,##0.00)"/>'+			'</numFmts>'+			'<fonts count="5" x14ac:knownFonts="1">'+				'<font>'+					'<sz val="11" />'+					'<name val="Calibri" />'+				'</font>'+				'<font>'+					'<sz val="11" />'+					'<name val="Calibri" />'+					'<color rgb="FFFFFFFF" />'+				'</font>'+				'<font>'+					'<sz val="11" />'+					'<name val="Calibri" />'+					'<b />'+				'</font>'+				'<font>'+					'<sz val="11" />'+					'<name val="Calibri" />'+					'<i />'+				'</font>'+				'<font>'+					'<sz val="11" />'+					'<name val="Calibri" />'+					'<u />'+				'</font>'+			'</fonts>'+			'<fills count="6">'+				'<fill>'+					'<patternFill patternType="none" />'+				'</fill>'+				'<fill>'+ // Excel appears to use this as a dotted background regardless of values but					'<patternFill patternType="none" />'+ // to be valid to the schema, use a patternFill				'</fill>'+				'<fill>'+					'<patternFill patternType="solid">'+						'<fgColor rgb="FFD9D9D9" />'+						'<bgColor indexed="64" />'+					'</patternFill>'+				'</fill>'+				'<fill>'+					'<patternFill patternType="solid">'+						'<fgColor rgb="FFD99795" />'+						'<bgColor indexed="64" />'+					'</patternFill>'+				'</fill>'+				'<fill>'+					'<patternFill patternType="solid">'+						'<fgColor rgb="ffc6efce" />'+						'<bgColor indexed="64" />'+					'</patternFill>'+				'</fill>'+				'<fill>'+					'<patternFill patternType="solid">'+						'<fgColor rgb="ffc6cfef" />'+						'<bgColor indexed="64" />'+					'</patternFill>'+				'</fill>'+			'</fills>'+			'<borders count="2">'+				'<border>'+					'<left />'+					'<right />'+					'<top />'+					'<bottom />'+					'<diagonal />'+				'</border>'+				'<border diagonalUp="false" diagonalDown="false">'+					'<left style="thin">'+						'<color auto="1" />'+					'</left>'+					'<right style="thin">'+						'<color auto="1" />'+					'</right>'+					'<top style="thin">'+						'<color auto="1" />'+					'</top>'+					'<bottom style="thin">'+						'<color auto="1" />'+					'</bottom>'+					'<diagonal />'+				'</border>'+			'</borders>'+			'<cellStyleXfs count="1">'+				'<xf numFmtId="0" fontId="0" fillId="0" borderId="0" />'+			'</cellStyleXfs>'+			'<cellXfs count="68">'+				'<xf numFmtId="0" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="1" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="2" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="3" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="4" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="0" fillId="2" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="1" fillId="2" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="2" fillId="2" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="3" fillId="2" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="4" fillId="2" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="0" fillId="3" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="1" fillId="3" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="2" fillId="3" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="3" fillId="3" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="4" fillId="3" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="0" fillId="4" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="1" fillId="4" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="2" fillId="4" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="3" fillId="4" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="4" fillId="4" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="0" fillId="5" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="1" fillId="5" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="2" fillId="5" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="3" fillId="5" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="4" fillId="5" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="0" fillId="0" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="1" fillId="0" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="2" fillId="0" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="3" fillId="0" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="4" fillId="0" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="0" fillId="2" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="1" fillId="2" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="2" fillId="2" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="3" fillId="2" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="4" fillId="2" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="0" fillId="3" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="1" fillId="3" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="2" fillId="3" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="3" fillId="3" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="4" fillId="3" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="0" fillId="4" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="1" fillId="4" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="2" fillId="4" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="3" fillId="4" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="4" fillId="4" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="0" fillId="5" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="1" fillId="5" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="2" fillId="5" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="3" fillId="5" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="4" fillId="5" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/>'+				'<xf numFmtId="0" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyAlignment="1">'+					'<alignment horizontal="left"/>'+				'</xf>'+				'<xf numFmtId="0" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyAlignment="1">'+					'<alignment horizontal="center"/>'+				'</xf>'+				'<xf numFmtId="0" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyAlignment="1">'+					'<alignment horizontal="right"/>'+				'</xf>'+				'<xf numFmtId="0" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyAlignment="1">'+					'<alignment horizontal="fill"/>'+				'</xf>'+				'<xf numFmtId="0" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyAlignment="1">'+					'<alignment textRotation="90"/>'+				'</xf>'+				'<xf numFmtId="0" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyAlignment="1">'+					'<alignment wrapText="1"/>'+				'</xf>'+				'<xf numFmtId="9"   fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>'+				'<xf numFmtId="164" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>'+				'<xf numFmtId="165" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>'+				'<xf numFmtId="166" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>'+				'<xf numFmtId="167" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>'+				'<xf numFmtId="168" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>'+				'<xf numFmtId="169" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>'+				'<xf numFmtId="3" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>'+				'<xf numFmtId="4" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>'+				'<xf numFmtId="1" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>'+				'<xf numFmtId="2" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>'+				'<xf numFmtId="14" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyNumberFormat="1"/>'+			'</cellXfs>'+			'<cellStyles count="1">'+				'<cellStyle name="Normal" xfId="0" builtinId="0" />'+			'</cellStyles>'+			'<dxfs count="0" />'+			'<tableStyles count="0" defaultTableStyle="TableStyleMedium9" defaultPivotStyle="PivotStyleMedium4" />'+		'</styleSheet>'};// Note we could use 3 `for` loops for the styles, but when gzipped there is// virtually no difference in size, since the above can be easily compressed// Pattern matching for special number formats. Perhaps this should be exposed// via an API in future?// Ref: section 3.8.30 - built in formatters in open spreadsheet//   https://www.ecma-international.org/news/TC45_current_work/Office%20Open%20XML%20Part%204%20-%20Markup%20Language%20Reference.pdfvar _excelSpecials = [	{ match: /^\-?\d+\.\d%$/,               style: 60, fmt: function (d) { return d/100; } }, // Precent with d.p.	{ match: /^\-?\d+\.?\d*%$/,             style: 56, fmt: function (d) { return d/100; } }, // Percent	{ match: /^\-?\$[\d,]+.?\d*$/,          style: 57 }, // Dollars	{ match: /^\-?£[\d,]+.?\d*$/,           style: 58 }, // Pounds	{ match: /^\-?€[\d,]+.?\d*$/,           style: 59 }, // Euros	{ match: /^\-?\d+$/,                    style: 65 }, // Numbers without thousand separators	{ match: /^\-?\d+\.\d{2}$/,             style: 66 }, // Numbers 2 d.p. without thousands separators	{ match: /^\([\d,]+\)$/,                style: 61, fmt: function (d) { return -1 * d.replace(/[\(\)]/g, ''); } },  // Negative numbers indicated by brackets	{ match: /^\([\d,]+\.\d{2}\)$/,         style: 62, fmt: function (d) { return -1 * d.replace(/[\(\)]/g, ''); } },  // Negative numbers indicated by brackets - 2d.p.	{ match: /^\-?[\d,]+$/,                 style: 63 }, // Numbers with thousand separators	{ match: /^\-?[\d,]+\.\d{2}$/,          style: 64 },	{ match: /^[\d]{4}\-[\d]{2}\-[\d]{2}$/, style: 67, fmt: function (d) {return Math.round(25569 + (Date.parse(d) / (86400 * 1000)));}} //Date yyyy-mm-dd];/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Buttons *///// Copy to clipboard//DataTable.ext.buttons.copyHtml5 = {	className: 'buttons-copy buttons-html5',	text: function ( dt ) {		return dt.i18n( 'buttons.copy', 'Copy' );	},	action: function ( e, dt, button, config ) {		this.processing( true );		var that = this;		var exportData = _exportData( dt, config );		var info = dt.buttons.exportInfo( config );		var newline = _newLine(config);		var output = exportData.str;		var hiddenDiv = $('<div/>')			.css( {				height: 1,				width: 1,				overflow: 'hidden',				position: 'fixed',				top: 0,				left: 0			} );		if ( info.title ) {			output = info.title + newline + newline + output;		}		if ( info.messageTop ) {			output = info.messageTop + newline + newline + output;		}		if ( info.messageBottom ) {			output = output + newline + newline + info.messageBottom;		}		if ( config.customize ) {			output = config.customize( output, config, dt );		}		var textarea = $('<textarea readonly/>')			.val( output )			.appendTo( hiddenDiv );		// For browsers that support the copy execCommand, try to use it		if ( document.queryCommandSupported('copy') ) {			hiddenDiv.appendTo( dt.table().container() );			textarea[0].focus();			textarea[0].select();			try {				var successful = document.execCommand( 'copy' );				hiddenDiv.remove();				if (successful) {					dt.buttons.info(						dt.i18n( 'buttons.copyTitle', 'Copy to clipboard' ),						dt.i18n( 'buttons.copySuccess', {							1: 'Copied one row to clipboard',							_: 'Copied %d rows to clipboard'						}, exportData.rows ),						2000					);					this.processing( false );					return;				}			}			catch (t) {}		}		// Otherwise we show the text box and instruct the user to use it		var message = $('<span>'+dt.i18n( 'buttons.copyKeys',				'Press <i>ctrl</i> or <i>\u2318</i> + <i>C</i> to copy the table data<br>to your system clipboard.<br><br>'+				'To cancel, click this message or press escape.' )+'</span>'			)			.append( hiddenDiv );		dt.buttons.info( dt.i18n( 'buttons.copyTitle', 'Copy to clipboard' ), message, 0 );		// Select the text so when the user activates their system clipboard		// it will copy that text		textarea[0].focus();		textarea[0].select();		// Event to hide the message when the user is done		var container = $(message).closest('.dt-button-info');		var close = function () {			container.off( 'click.buttons-copy' );			$(document).off( '.buttons-copy' );			dt.buttons.info( false );		};		container.on( 'click.buttons-copy', close );		$(document)			.on( 'keydown.buttons-copy', function (e) {				if ( e.keyCode === 27 ) { // esc					close();					that.processing( false );				}			} )			.on( 'copy.buttons-copy cut.buttons-copy', function () {				close();				that.processing( false );			} );	},	exportOptions: {},	fieldSeparator: '\t',	fieldBoundary: '',	header: true,	footer: false,	title: '*',	messageTop: '*',	messageBottom: '*'};//// CSV export//DataTable.ext.buttons.csvHtml5 = {	bom: false,	className: 'buttons-csv buttons-html5',	available: function () {		return window.FileReader !== undefined && window.Blob;	},	text: function ( dt ) {		return dt.i18n( 'buttons.csv', 'CSV' );	},	action: function ( e, dt, button, config ) {		this.processing( true );		// Set the text		var output = _exportData( dt, config ).str;		var info = dt.buttons.exportInfo(config);		var charset = config.charset;		if ( config.customize ) {			output = config.customize( output, config, dt );		}		if ( charset !== false ) {			if ( ! charset ) {				charset = document.characterSet || document.charset;			}			if ( charset ) {				charset = ';charset='+charset;			}		}		else {			charset = '';		}		if ( config.bom ) {			output = '\ufeff' + output;		}		_saveAs(			new Blob( [output], {type: 'text/csv'+charset} ),			info.filename,			true		);		this.processing( false );	},	filename: '*',	extension: '.csv',	exportOptions: {},	fieldSeparator: ',',	fieldBoundary: '"',	escapeChar: '"',	charset: null,	header: true,	footer: false};//// Excel (xlsx) export//DataTable.ext.buttons.excelHtml5 = {	className: 'buttons-excel buttons-html5',	available: function () {		return window.FileReader !== undefined && _jsZip() !== undefined && ! _isDuffSafari() && _serialiser;	},	text: function ( dt ) {		return dt.i18n( 'buttons.excel', 'Excel' );	},	action: function ( e, dt, button, config ) {		this.processing( true );		var that = this;		var rowPos = 0;		var dataStartRow, dataEndRow;		var getXml = function ( type ) {			var str = excelStrings[ type ];			//str = str.replace( /xmlns:/g, 'xmlns_' ).replace( /mc:/g, 'mc_' );			return $.parseXML( str );		};		var rels = getXml('xl/worksheets/sheet1.xml');		var relsGet = rels.getElementsByTagName( "sheetData" )[0];		var xlsx = {			_rels: {				".rels": getXml('_rels/.rels')			},			xl: {				_rels: {					"workbook.xml.rels": getXml('xl/_rels/workbook.xml.rels')				},				"workbook.xml": getXml('xl/workbook.xml'),				"styles.xml": getXml('xl/styles.xml'),				"worksheets": {					"sheet1.xml": rels				}			},			"[Content_Types].xml": getXml('[Content_Types].xml')		};		var data = dt.buttons.exportData( config.exportOptions );		var currentRow, rowNode;		var addRow = function ( row ) {			currentRow = rowPos+1;			rowNode = _createNode( rels, "row", { attr: {r:currentRow} } );			for ( var i=0, ien=row.length ; i<ien ; i++ ) {				// Concat both the Cell Columns as a letter and the Row of the cell.				var cellId = createCellPos(i) + '' + currentRow;				var cell = null;				// For null, undefined of blank cell, continue so it doesn't create the _createNode				if ( row[i] === null || row[i] === undefined || row[i] === '' ) {					if ( config.createEmptyCells === true ) {						row[i] = '';					}					else {						continue;					}				}				var originalContent = row[i];				row[i] = typeof row[i].trim === 'function'					? row[i].trim()					: row[i];				// Special number formatting options				for ( var j=0, jen=_excelSpecials.length ; j<jen ; j++ ) {					var special = _excelSpecials[j];					// TODO Need to provide the ability for the specials to say					// if they are returning a string, since at the moment it is					// assumed to be a number					if ( row[i].match && ! row[i].match(/^0\d+/) && row[i].match( special.match ) ) {						var val = row[i].replace(/[^\d\.\-]/g, '');						if ( special.fmt ) {							val = special.fmt( val );						}						cell = _createNode( rels, 'c', {							attr: {								r: cellId,								s: special.style							},							children: [								_createNode( rels, 'v', { text: val } )							]						} );						break;					}				}				if ( ! cell ) {					if ( typeof row[i] === 'number' || (						row[i].match &&						row[i].match(/^-?\d+(\.\d+)?$/) &&						! row[i].match(/^0\d+/) )					) {						// Detect numbers - don't match numbers with leading zeros						// or a negative anywhere but the start						cell = _createNode( rels, 'c', {							attr: {								t: 'n',								r: cellId							},							children: [								_createNode( rels, 'v', { text: row[i] } )							]						} );					}					else {						// String output - replace non standard characters for text output						var text = ! originalContent.replace ?							originalContent :							originalContent.replace(/[\x00-\x09\x0B\x0C\x0E-\x1F\x7F-\x9F]/g, '');						cell = _createNode( rels, 'c', {							attr: {								t: 'inlineStr',								r: cellId							},							children:{								row: _createNode( rels, 'is', {									children: {										row: _createNode( rels, 't', {											text: text,											attr: {												'xml:space': 'preserve'											}										} )									}								} )							}						} );					}				}				rowNode.appendChild( cell );			}			relsGet.appendChild(rowNode);			rowPos++;		};		if ( config.customizeData ) {			config.customizeData( data );		}		var mergeCells = function ( row, colspan ) {			var mergeCells = $('mergeCells', rels);			mergeCells[0].appendChild( _createNode( rels, 'mergeCell', {				attr: {					ref: 'A'+row+':'+createCellPos(colspan)+row				}			} ) );			mergeCells.attr( 'count', parseFloat(mergeCells.attr( 'count' ))+1 );			$('row:eq('+(row-1)+') c', rels).attr( 's', '51' ); // centre		};		// Title and top messages		var exportInfo = dt.buttons.exportInfo( config );		if ( exportInfo.title ) {			addRow( [exportInfo.title], rowPos );			mergeCells( rowPos, data.header.length-1 );		}		if ( exportInfo.messageTop ) {			addRow( [exportInfo.messageTop], rowPos );			mergeCells( rowPos, data.header.length-1 );		}		// Table itself		if ( config.header ) {			addRow( data.header, rowPos );			$('row:last c', rels).attr( 's', '2' ); // bold		}			dataStartRow = rowPos;		for ( var n=0, ie=data.body.length ; n<ie ; n++ ) {			addRow( data.body[n], rowPos );		}			dataEndRow = rowPos;		if ( config.footer && data.footer ) {			addRow( data.footer, rowPos);			$('row:last c', rels).attr( 's', '2' ); // bold		}		// Below the table		if ( exportInfo.messageBottom ) {			addRow( [exportInfo.messageBottom], rowPos );			mergeCells( rowPos, data.header.length-1 );		}		// Set column widths		var cols = _createNode( rels, 'cols' );		$('worksheet', rels).prepend( cols );		for ( var i=0, ien=data.header.length ; i<ien ; i++ ) {			cols.appendChild( _createNode( rels, 'col', {				attr: {					min: i+1,					max: i+1,					width: _excelColWidth( data, i ),					customWidth: 1				}			} ) );		}		// Workbook modifications		var workbook = xlsx.xl['workbook.xml'];		$( 'sheets sheet', workbook ).attr( 'name', _sheetname( config ) );		// Auto filter for columns		if ( config.autoFilter ) {			$('mergeCells', rels).before( _createNode( rels, 'autoFilter', {				attr: {					ref: 'A'+dataStartRow+':'+createCellPos(data.header.length-1)+dataEndRow				}			} ) );			$('definedNames', workbook).append( _createNode( workbook, 'definedName', {				attr: {					name: '_xlnm._FilterDatabase',					localSheetId: '0',					hidden: 1				},				text: _sheetname(config)+'!$A$'+dataStartRow+':'+createCellPos(data.header.length-1)+dataEndRow			} ) );		}		// Let the developer customise the document if they want to		if ( config.customize ) {			config.customize( xlsx, config, dt );		}		// Excel doesn't like an empty mergeCells tag		if ( $('mergeCells', rels).children().length === 0 ) {			$('mergeCells', rels).remove();		}		var jszip = _jsZip();		var zip = new jszip();		var zipConfig = {			type: 'blob',			mimeType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'		};		_addToZip( zip, xlsx );		if ( zip.generateAsync ) {			// JSZip 3+			zip				.generateAsync( zipConfig )				.then( function ( blob ) {					_saveAs( blob, exportInfo.filename );					that.processing( false );				} );		}		else {			// JSZip 2.5			_saveAs(				zip.generate( zipConfig ),				exportInfo.filename			);			this.processing( false );		}	},	filename: '*',	extension: '.xlsx',	exportOptions: {},	header: true,	footer: false,	title: '*',	messageTop: '*',	messageBottom: '*',	createEmptyCells: false,	autoFilter: false,	sheetName: ''};//// PDF export - using pdfMake - http://pdfmake.org//DataTable.ext.buttons.pdfHtml5 = {	className: 'buttons-pdf buttons-html5',	available: function () {		return window.FileReader !== undefined && _pdfMake();	},	text: function ( dt ) {		return dt.i18n( 'buttons.pdf', 'PDF' );	},	action: function ( e, dt, button, config ) {		this.processing( true );		var that = this;		var data = dt.buttons.exportData( config.exportOptions );		var info = dt.buttons.exportInfo( config );		var rows = [];		if ( config.header ) {			rows.push( $.map( data.header, function ( d ) {				return {					text: typeof d === 'string' ? d : d+'',					style: 'tableHeader'				};			} ) );		}		for ( var i=0, ien=data.body.length ; i<ien ; i++ ) {			rows.push( $.map( data.body[i], function ( d ) {				if ( d === null || d === undefined ) {					d = '';				}				return {					text: typeof d === 'string' ? d : d+'',					style: i % 2 ? 'tableBodyEven' : 'tableBodyOdd'				};			} ) );		}		if ( config.footer && data.footer) {			rows.push( $.map( data.footer, function ( d ) {				return {					text: typeof d === 'string' ? d : d+'',					style: 'tableFooter'				};			} ) );		}		var doc = {			pageSize: config.pageSize,			pageOrientation: config.orientation,			content: [				{					table: {						headerRows: 1,						body: rows					},					layout: 'noBorders'				}			],			styles: {				tableHeader: {					bold: true,					fontSize: 11,					color: 'white',					fillColor: '#2d4154',					alignment: 'center'				},				tableBodyEven: {},				tableBodyOdd: {					fillColor: '#f3f3f3'				},				tableFooter: {					bold: true,					fontSize: 11,					color: 'white',					fillColor: '#2d4154'				},				title: {					alignment: 'center',					fontSize: 15				},				message: {}			},			defaultStyle: {				fontSize: 10			}		};		if ( info.messageTop ) {			doc.content.unshift( {				text: info.messageTop,				style: 'message',				margin: [ 0, 0, 0, 12 ]			} );		}		if ( info.messageBottom ) {			doc.content.push( {				text: info.messageBottom,				style: 'message',				margin: [ 0, 0, 0, 12 ]			} );		}		if ( info.title ) {			doc.content.unshift( {				text: info.title,				style: 'title',				margin: [ 0, 0, 0, 12 ]			} );		}		if ( config.customize ) {			config.customize( doc, config, dt );		}		var pdf = _pdfMake().createPdf( doc );		if ( config.download === 'open' && ! _isDuffSafari() ) {			pdf.open();		}		else {			pdf.download( info.filename );		}		this.processing( false );	},	title: '*',	filename: '*',	extension: '.pdf',	exportOptions: {},	orientation: 'portrait',	pageSize: 'A4',	header: true,	footer: false,	messageTop: '*',	messageBottom: '*',	customize: null,	download: 'download'};return DataTable.Buttons;}));
 |