effective_datatables 3.2.7 → 3.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ef7002186c955ceea81788574da37e926dde317e
4
- data.tar.gz: e4bc57451595479713c11d423d2b21b22629eaae
3
+ metadata.gz: d15e87f91c336f09837c05c1cd19ae3eb109aa5c
4
+ data.tar.gz: 02baa43cac7e7ecb1b0dbdee89d22512e98af70a
5
5
  SHA512:
6
- metadata.gz: 07f99e9baa2ca960349e3fc42949cc14a679109d5156ec8990b7fca81ee24a5abd582a67b07bc2a476da9eb588fc04660944609065c7fc7eaae470d1ed2ebbe1
7
- data.tar.gz: 867adf502935e2db8dec3171e785ee70039d0a15844ebea9a2858584a2f3a27201f5ecd4bf3918ff9c7ef227b7489559f92c0a66965d22ed45cd1a204914a2f9
6
+ metadata.gz: 4df1c018bc13eb6bfe06a9309b52081dfe5f7840fc136a7d9b31d8ac06d8d1fde0c1ea1e66bbee7a3616238fba866f9eb572e3c75d7b8ffb451b33411e1dc4fb
7
+ data.tar.gz: 6daf450e7860fa17e318c1b29e65b3cad892eb3b94fc235186db44b3c31073c9c08621b3c9963b21a3bae29fc602dc54939645946df68ae34be87f7c8e79b4dd
@@ -49,7 +49,9 @@ $.extend( true, DataTable.Buttons.defaults, {
49
49
  className: 'dt-button-collection dropdown-menu',
50
50
  button: {
51
51
  tag: 'li',
52
- className: 'dt-button'
52
+ className: 'dt-button',
53
+ active: 'active',
54
+ disabled: 'disabled'
53
55
  },
54
56
  buttonLiner: {
55
57
  tag: 'a',
@@ -48,7 +48,8 @@ $.extend( DataTable.ext.buttons, {
48
48
  className: 'buttons-colvis',
49
49
  buttons: [ {
50
50
  extend: 'columnsToggle',
51
- columns: conf.columns
51
+ columns: conf.columns,
52
+ columnText: conf.columnText
52
53
  } ]
53
54
  };
54
55
  },
@@ -58,7 +59,8 @@ $.extend( DataTable.ext.buttons, {
58
59
  var columns = dt.columns( conf.columns ).indexes().map( function ( idx ) {
59
60
  return {
60
61
  extend: 'columnToggle',
61
- columns: idx
62
+ columns: idx,
63
+ columnText: conf.columnText
62
64
  };
63
65
  } ).toArray();
64
66
 
@@ -69,7 +71,8 @@ $.extend( DataTable.ext.buttons, {
69
71
  columnToggle: function ( dt, conf ) {
70
72
  return {
71
73
  extend: 'columnVisibility',
72
- columns: conf.columns
74
+ columns: conf.columns,
75
+ columnText: conf.columnText
73
76
  };
74
77
  },
75
78
 
@@ -79,7 +82,8 @@ $.extend( DataTable.ext.buttons, {
79
82
  return {
80
83
  extend: 'columnVisibility',
81
84
  columns: idx,
82
- visibility: conf.visibility
85
+ visibility: conf.visibility,
86
+ columnText: conf.columnText
83
87
  };
84
88
  } ).toArray();
85
89
 
@@ -90,7 +94,7 @@ $.extend( DataTable.ext.buttons, {
90
94
  columnVisibility: {
91
95
  columns: undefined, // column selector
92
96
  text: function ( dt, button, conf ) {
93
- return conf._columnText( dt, conf.columns );
97
+ return conf._columnText( dt, conf );
94
98
  },
95
99
  className: 'buttons-columnVisibility',
96
100
  action: function ( e, dt, button, conf ) {
@@ -107,7 +111,7 @@ $.extend( DataTable.ext.buttons, {
107
111
 
108
112
  dt
109
113
  .on( 'column-visibility.dt'+conf.namespace, function (e, settings) {
110
- if ( ! settings.bDestroying ) {
114
+ if ( ! settings.bDestroying && settings.nTable == dt.settings()[0].nTable ) {
111
115
  that.active( dt.column( conf.columns ).visible() );
112
116
  }
113
117
  } )
@@ -124,7 +128,7 @@ $.extend( DataTable.ext.buttons, {
124
128
 
125
129
  var col = dt.column( conf.columns );
126
130
 
127
- that.text( conf._columnText( dt, conf.columns ) );
131
+ that.text( conf._columnText( dt, conf ) );
128
132
  that.active( col.visible() );
129
133
  } );
130
134
 
@@ -136,16 +140,21 @@ $.extend( DataTable.ext.buttons, {
136
140
  .off( 'column-reorder.dt'+conf.namespace );
137
141
  },
138
142
 
139
- _columnText: function ( dt, col ) {
143
+ _columnText: function ( dt, conf ) {
140
144
  // Use DataTables' internal data structure until this is presented
141
145
  // is a public API. The other option is to use
142
146
  // `$( column(col).node() ).text()` but the node might not have been
143
147
  // populated when Buttons is constructed.
144
- var idx = dt.column( col ).index();
145
- return dt.settings()[0].aoColumns[ idx ].sTitle
148
+ var idx = dt.column( conf.columns ).index();
149
+ var title = dt.settings()[0].aoColumns[ idx ].sTitle
146
150
  .replace(/\n/g," ") // remove new lines
151
+ .replace(/<br\s*\/?>/gi, " ") // replace line breaks with spaces
147
152
  .replace( /<.*?>/g, "" ) // strip HTML
148
153
  .replace(/^\s+|\s+$/g,""); // trim
154
+
155
+ return conf.columnText ?
156
+ conf.columnText( dt, idx, title ) :
157
+ title;
149
158
  }
150
159
  },
151
160
 
@@ -228,35 +228,6 @@ DataTable.fileSave = _saveAs;
228
228
  * Local (private) functions
229
229
  */
230
230
 
231
- /**
232
- * Get the file name for an exported file.
233
- *
234
- * @param {object} config Button configuration
235
- * @param {boolean} incExtension Include the file name extension
236
- */
237
- var _filename = function ( config, incExtension )
238
- {
239
- // Backwards compatibility
240
- var filename = config.filename === '*' && config.title !== '*' && config.title !== undefined ?
241
- config.title :
242
- config.filename;
243
-
244
- if ( typeof filename === 'function' ) {
245
- filename = filename();
246
- }
247
-
248
- if ( filename.indexOf( '*' ) !== -1 ) {
249
- filename = $.trim( filename.replace( '*', $('title').text() ) );
250
- }
251
-
252
- // Strip characters which the OS will object to
253
- filename = filename.replace(/[^a-zA-Z0-9_\u00A1-\uFFFF\.,\-_ !\(\)]/g, "");
254
-
255
- return incExtension === undefined || incExtension === true ?
256
- filename+config.extension :
257
- filename;
258
- };
259
-
260
231
  /**
261
232
  * Get the sheet name for Excel exports.
262
233
  *
@@ -270,25 +241,7 @@ var _sheetname = function ( config )
270
241
  sheetName = config.sheetName.replace(/[\[\]\*\/\\\?\:]/g, '');
271
242
  }
272
243
 
273
- return sheetName;
274
- };
275
-
276
- /**
277
- * Get the title for an exported file.
278
- *
279
- * @param {object} config Button configuration
280
- */
281
- var _title = function ( config )
282
- {
283
- var title = config.title;
284
-
285
- if ( typeof title === 'function' ) {
286
- title = title();
287
- }
288
-
289
- return title.indexOf( '*' ) !== -1 ?
290
- title.replace( '*', $('title').text() || 'Exported data' ) :
291
- title;
244
+ return sheetName;
292
245
  };
293
246
 
294
247
  /**
@@ -473,7 +426,7 @@ function _addToZip( zip, obj ) {
473
426
 
474
427
  // Safari, IE and Edge will put empty name space attributes onto
475
428
  // various elements making them useless. This strips them out
476
- str = str.replace( /<(.*?) xmlns=""(.*?)>/g, '<$1 $2>' );
429
+ str = str.replace( /<([^<>]*?) xmlns=""([^<>]*?)>/g, '<$1 $2>' );
477
430
 
478
431
  zip.file( name, str );
479
432
  }
@@ -498,13 +451,13 @@ function _createNode( doc, nodeName, opts ) {
498
451
  $(tempNode).attr( opts.attr );
499
452
  }
500
453
 
501
- if( opts.children ) {
454
+ if ( opts.children ) {
502
455
  $.each( opts.children, function ( key, value ) {
503
456
  tempNode.appendChild( value );
504
- });
457
+ } );
505
458
  }
506
459
 
507
- if( opts.text ) {
460
+ if ( opts.text !== null && opts.text !== undefined ) {
508
461
  tempNode.appendChild( doc.createTextNode( opts.text ) );
509
462
  }
510
463
  }
@@ -527,7 +480,10 @@ function _excelColWidth( data, col ) {
527
480
  }
528
481
 
529
482
  for ( var i=0, ien=data.body.length ; i<ien ; i++ ) {
530
- str = data.body[i][col].toString();
483
+ var point = data.body[i][col];
484
+ str = point !== null && point !== undefined ?
485
+ point.toString() :
486
+ '';
531
487
 
532
488
  // If there is a newline character, workout the width of the column
533
489
  // based on the longest line in the string
@@ -549,7 +505,7 @@ function _excelColWidth( data, col ) {
549
505
 
550
506
  // Max width rather than having potentially massive column widths
551
507
  if ( max > 40 ) {
552
- break;
508
+ return 52; // 40 * 1.3
553
509
  }
554
510
  }
555
511
 
@@ -602,6 +558,7 @@ var excelStrings = {
602
558
  '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'+
603
559
  '<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">'+
604
560
  '<sheetData/>'+
561
+ '<mergeCells count="0"/>'+
605
562
  '</worksheet>',
606
563
 
607
564
  "xl/styles.xml":
@@ -709,11 +666,11 @@ var excelStrings = {
709
666
  '<xf numFmtId="0" fontId="2" fillId="2" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+
710
667
  '<xf numFmtId="0" fontId="3" fillId="2" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+
711
668
  '<xf numFmtId="0" fontId="4" fillId="2" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+
712
- '<xf numFmtId="0" fontId="0" fillId="4" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+
713
- '<xf numFmtId="0" fontId="1" fillId="4" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+
714
- '<xf numFmtId="0" fontId="2" fillId="4" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+
715
- '<xf numFmtId="0" fontId="3" fillId="4" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+
716
- '<xf numFmtId="0" fontId="4" fillId="4" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+
669
+ '<xf numFmtId="0" fontId="0" fillId="3" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+
670
+ '<xf numFmtId="0" fontId="1" fillId="3" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+
671
+ '<xf numFmtId="0" fontId="2" fillId="3" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+
672
+ '<xf numFmtId="0" fontId="3" fillId="3" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+
673
+ '<xf numFmtId="0" fontId="4" fillId="3" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+
717
674
  '<xf numFmtId="0" fontId="0" fillId="4" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+
718
675
  '<xf numFmtId="0" fontId="1" fillId="4" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+
719
676
  '<xf numFmtId="0" fontId="2" fillId="4" borderId="0" applyFont="1" applyFill="1" applyBorder="1"/>'+
@@ -824,7 +781,12 @@ DataTable.ext.buttons.copyHtml5 = {
824
781
  },
825
782
 
826
783
  action: function ( e, dt, button, config ) {
784
+ this.processing( true );
785
+
786
+ var that = this;
827
787
  var exportData = _exportData( dt, config );
788
+ var info = dt.buttons.exportInfo( config );
789
+ var newline = _newLine(config);
828
790
  var output = exportData.str;
829
791
  var hiddenDiv = $('<div/>')
830
792
  .css( {
@@ -836,6 +798,18 @@ DataTable.ext.buttons.copyHtml5 = {
836
798
  left: 0
837
799
  } );
838
800
 
801
+ if ( info.title ) {
802
+ output = info.title + newline + newline + output;
803
+ }
804
+
805
+ if ( info.messageTop ) {
806
+ output = info.messageTop + newline + newline + output;
807
+ }
808
+
809
+ if ( info.messageBottom ) {
810
+ output = output + newline + newline + info.messageBottom;
811
+ }
812
+
839
813
  if ( config.customize ) {
840
814
  output = config.customize( output, config );
841
815
  }
@@ -863,6 +837,8 @@ DataTable.ext.buttons.copyHtml5 = {
863
837
  }, exportData.rows ),
864
838
  2000
865
839
  );
840
+
841
+ this.processing( false );
866
842
  return;
867
843
  }
868
844
  }
@@ -896,10 +872,12 @@ DataTable.ext.buttons.copyHtml5 = {
896
872
  .on( 'keydown.buttons-copy', function (e) {
897
873
  if ( e.keyCode === 27 ) { // esc
898
874
  close();
875
+ that.processing( false );
899
876
  }
900
877
  } )
901
878
  .on( 'copy.buttons-copy cut.buttons-copy', function () {
902
879
  close();
880
+ that.processing( false );
903
881
  } );
904
882
  },
905
883
 
@@ -911,7 +889,13 @@ DataTable.ext.buttons.copyHtml5 = {
911
889
 
912
890
  header: true,
913
891
 
914
- footer: false
892
+ footer: false,
893
+
894
+ title: '*',
895
+
896
+ messageTop: '*',
897
+
898
+ messageBottom: '*'
915
899
  };
916
900
 
917
901
  //
@@ -931,8 +915,11 @@ DataTable.ext.buttons.csvHtml5 = {
931
915
  },
932
916
 
933
917
  action: function ( e, dt, button, config ) {
918
+ this.processing( true );
919
+
934
920
  // Set the text
935
921
  var output = _exportData( dt, config ).str;
922
+ var info = dt.buttons.exportInfo(config);
936
923
  var charset = config.charset;
937
924
 
938
925
  if ( config.customize ) {
@@ -958,9 +945,11 @@ DataTable.ext.buttons.csvHtml5 = {
958
945
 
959
946
  _saveAs(
960
947
  new Blob( [output], {type: 'text/csv'+charset} ),
961
- _filename( config ),
948
+ info.filename,
962
949
  true
963
950
  );
951
+
952
+ this.processing( false );
964
953
  },
965
954
 
966
955
  filename: '*',
@@ -997,6 +986,9 @@ DataTable.ext.buttons.excelHtml5 = {
997
986
  },
998
987
 
999
988
  action: function ( e, dt, button, config ) {
989
+ this.processing( true );
990
+
991
+ var that = this;
1000
992
  var rowPos = 0;
1001
993
  var getXml = function ( type ) {
1002
994
  var str = excelStrings[ type ];
@@ -1048,7 +1040,10 @@ DataTable.ext.buttons.excelHtml5 = {
1048
1040
  for ( var j=0, jen=_excelSpecials.length ; j<jen ; j++ ) {
1049
1041
  var special = _excelSpecials[j];
1050
1042
 
1051
- if ( row[i].match && row[i].match( special.match ) ) {
1043
+ // TODO Need to provide the ability for the specials to say
1044
+ // if they are returning a string, since at the moment it is
1045
+ // assumed to be a number
1046
+ if ( row[i].match && ! row[i].match(/^0\d+/) && row[i].match( special.match ) ) {
1052
1047
  var val = row[i].replace(/[^\d\.\-]/g, '');
1053
1048
 
1054
1049
  if ( special.fmt ) {
@@ -1124,9 +1119,34 @@ DataTable.ext.buttons.excelHtml5 = {
1124
1119
  config.customizeData( data );
1125
1120
  }
1126
1121
 
1122
+ var mergeCells = function ( row, colspan ) {
1123
+ var mergeCells = $('mergeCells', rels);
1124
+
1125
+ mergeCells[0].appendChild( _createNode( rels, 'mergeCell', {
1126
+ attr: {
1127
+ ref: 'A'+row+':'+createCellPos(colspan)+row
1128
+ }
1129
+ } ) );
1130
+ mergeCells.attr( 'count', mergeCells.attr( 'count' )+1 );
1131
+ $('row:eq('+(row-1)+') c', rels).attr( 's', '51' ); // centre
1132
+ };
1133
+
1134
+ // Title and top messages
1135
+ var exportInfo = dt.buttons.exportInfo( config );
1136
+ if ( exportInfo.title ) {
1137
+ addRow( [exportInfo.title], rowPos );
1138
+ mergeCells( rowPos, data.header.length-1 );
1139
+ }
1140
+
1141
+ if ( exportInfo.messageTop ) {
1142
+ addRow( [exportInfo.messageTop], rowPos );
1143
+ mergeCells( rowPos, data.header.length-1 );
1144
+ }
1145
+
1146
+ // Table itself
1127
1147
  if ( config.header ) {
1128
1148
  addRow( data.header, rowPos );
1129
- $('row c', rels).attr( 's', '2' ); // bold
1149
+ $('row:last c', rels).attr( 's', '2' ); // bold
1130
1150
  }
1131
1151
 
1132
1152
  for ( var n=0, ie=data.body.length ; n<ie ; n++ ) {
@@ -1138,6 +1158,12 @@ DataTable.ext.buttons.excelHtml5 = {
1138
1158
  $('row:last c', rels).attr( 's', '2' ); // bold
1139
1159
  }
1140
1160
 
1161
+ // Below the table
1162
+ if ( exportInfo.messageBottom ) {
1163
+ addRow( [exportInfo.messageBottom], rowPos );
1164
+ mergeCells( rowPos, data.header.length-1 );
1165
+ }
1166
+
1141
1167
  // Set column widths
1142
1168
  var cols = _createNode( rels, 'cols' );
1143
1169
  $('worksheet', rels).prepend( cols );
@@ -1172,15 +1198,17 @@ DataTable.ext.buttons.excelHtml5 = {
1172
1198
  zip
1173
1199
  .generateAsync( zipConfig )
1174
1200
  .then( function ( blob ) {
1175
- _saveAs( blob, _filename( config ) );
1201
+ _saveAs( blob, exportInfo.filename );
1202
+ that.processing( false );
1176
1203
  } );
1177
1204
  }
1178
1205
  else {
1179
1206
  // JSZip 2.5
1180
1207
  _saveAs(
1181
1208
  zip.generate( zipConfig ),
1182
- _filename( config )
1209
+ exportInfo.filename
1183
1210
  );
1211
+ this.processing( false );
1184
1212
  }
1185
1213
  },
1186
1214
 
@@ -1192,7 +1220,13 @@ DataTable.ext.buttons.excelHtml5 = {
1192
1220
 
1193
1221
  header: true,
1194
1222
 
1195
- footer: false
1223
+ footer: false,
1224
+
1225
+ title: '*',
1226
+
1227
+ messageTop: '*',
1228
+
1229
+ messageBottom: '*'
1196
1230
  };
1197
1231
 
1198
1232
  //
@@ -1210,8 +1244,11 @@ DataTable.ext.buttons.pdfHtml5 = {
1210
1244
  },
1211
1245
 
1212
1246
  action: function ( e, dt, button, config ) {
1213
- var newLine = _newLine( config );
1247
+ this.processing( true );
1248
+
1249
+ var that = this;
1214
1250
  var data = dt.buttons.exportData( config.exportOptions );
1251
+ var info = dt.buttons.exportInfo( config );
1215
1252
  var rows = [];
1216
1253
 
1217
1254
  if ( config.header ) {
@@ -1282,17 +1319,25 @@ DataTable.ext.buttons.pdfHtml5 = {
1282
1319
  }
1283
1320
  };
1284
1321
 
1285
- if ( config.message ) {
1286
- doc.content.unshift( {
1287
- text: typeof config.message == 'function' ? config.message(dt, button, config) : config.message,
1288
- style: 'message',
1289
- margin: [ 0, 0, 0, 12 ]
1290
- } );
1322
+ if ( info.messageTop ) {
1323
+ doc.content.unshift( {
1324
+ text: info.messageTop,
1325
+ style: 'message',
1326
+ margin: [ 0, 0, 0, 12 ]
1327
+ } );
1291
1328
  }
1292
1329
 
1293
- if ( config.title ) {
1330
+ if ( info.messageBottom ) {
1331
+ doc.content.push( {
1332
+ text: info.messageBottom,
1333
+ style: 'message',
1334
+ margin: [ 0, 0, 0, 12 ]
1335
+ } );
1336
+ }
1337
+
1338
+ if ( info.title ) {
1294
1339
  doc.content.unshift( {
1295
- text: _title( config, false ),
1340
+ text: info.title,
1296
1341
  style: 'title',
1297
1342
  margin: [ 0, 0, 0, 12 ]
1298
1343
  } );
@@ -1306,12 +1351,14 @@ DataTable.ext.buttons.pdfHtml5 = {
1306
1351
 
1307
1352
  if ( config.download === 'open' && ! _isDuffSafari() ) {
1308
1353
  pdf.open();
1354
+ this.processing( false );
1309
1355
  }
1310
1356
  else {
1311
1357
  pdf.getBuffer( function (buffer) {
1312
1358
  var blob = new Blob( [buffer], {type:'application/pdf'} );
1313
1359
 
1314
- _saveAs( blob, _filename( config ) );
1360
+ _saveAs( blob, info.filename );
1361
+ that.processing( false );
1315
1362
  } );
1316
1363
  }
1317
1364
  },
@@ -1332,7 +1379,9 @@ DataTable.ext.buttons.pdfHtml5 = {
1332
1379
 
1333
1380
  footer: false,
1334
1381
 
1335
- message: null,
1382
+ messageTop: '*',
1383
+
1384
+ messageBottom: '*',
1336
1385
 
1337
1386
  customize: null,
1338
1387
 
@@ -40,30 +40,42 @@ var DataTable = $.fn.dataTable;
40
40
  var _link = document.createElement( 'a' );
41
41
 
42
42
  /**
43
- * Convert a `link` tag's URL from a relative to an absolute address so it will
44
- * work correctly in the popup window which has no base URL.
43
+ * Clone link and style tags, taking into account the need to change the source
44
+ * path.
45
45
  *
46
46
  * @param {node} el Element to convert
47
47
  */
48
- var _relToAbs = function( el ) {
48
+ var _styleToAbs = function( el ) {
49
49
  var url;
50
50
  var clone = $(el).clone()[0];
51
51
  var linkHost;
52
52
 
53
53
  if ( clone.nodeName.toLowerCase() === 'link' ) {
54
- _link.href = clone.href;
55
- linkHost = _link.host;
54
+ clone.href = _relToAbs( clone.href );
55
+ }
56
56
 
57
- // IE doesn't have a trailing slash on the host
58
- // Chrome has it on the pathname
59
- if ( linkHost.indexOf('/') === -1 && _link.pathname.indexOf('/') !== 0) {
60
- linkHost += '/';
61
- }
57
+ return clone.outerHTML;
58
+ };
62
59
 
63
- clone.href = _link.protocol+"//"+linkHost+_link.pathname+_link.search;
60
+ /**
61
+ * Convert a URL from a relative to an absolute address so it will work
62
+ * correctly in the popup window which has no base URL.
63
+ *
64
+ * @param {string} href URL
65
+ */
66
+ var _relToAbs = function( href ) {
67
+ // Assign to a link on the original page so the browser will do all the
68
+ // hard work of figuring out where the file actually is
69
+ _link.href = href;
70
+ var linkHost = _link.host;
71
+
72
+ // IE doesn't have a trailing slash on the host
73
+ // Chrome has it on the pathname
74
+ if ( linkHost.indexOf('/') === -1 && _link.pathname.indexOf('/') !== 0) {
75
+ linkHost += '/';
64
76
  }
65
77
 
66
- return clone.outerHTML;
78
+ return _link.protocol+"//"+linkHost+_link.pathname+_link.search;
67
79
  };
68
80
 
69
81
 
@@ -75,7 +87,11 @@ DataTable.ext.buttons.print = {
75
87
  },
76
88
 
77
89
  action: function ( e, dt, button, config ) {
78
- var data = dt.buttons.exportData( config.exportOptions );
90
+ var data = dt.buttons.exportData(
91
+ $.extend( {decodeEntities: false}, config.exportOptions ) // XSS protection
92
+ );
93
+ var exportInfo = dt.buttons.exportInfo( config );
94
+
79
95
  var addRow = function ( d, tag ) {
80
96
  var str = '<tr>';
81
97
 
@@ -102,28 +118,19 @@ DataTable.ext.buttons.print = {
102
118
  if ( config.footer && data.footer ) {
103
119
  html += '<tfoot>'+ addRow( data.footer, 'th' ) +'</tfoot>';
104
120
  }
121
+ html += '</table>';
105
122
 
106
123
  // Open a new window for the printable table
107
124
  var win = window.open( '', '' );
108
- var title = config.title;
109
-
110
- if ( typeof title === 'function' ) {
111
- title = title();
112
- }
113
-
114
- if ( title.indexOf( '*' ) !== -1 ) {
115
- title= title.replace( '*', $('title').text() );
116
- }
117
-
118
125
  win.document.close();
119
126
 
120
127
  // Inject the title and also a copy of the style and link tags from this
121
128
  // document so the table can retain its base styling. Note that we have
122
129
  // to use string manipulation as IE won't allow elements to be created
123
130
  // in the host document and then appended to the new window.
124
- var head = '<title>'+title+'</title>';
131
+ var head = '<title>'+exportInfo.title+'</title>';
125
132
  $('style, link').each( function () {
126
- head += _relToAbs( this );
133
+ head += _styleToAbs( this );
127
134
  } );
128
135
 
129
136
  try {
@@ -135,32 +142,35 @@ DataTable.ext.buttons.print = {
135
142
 
136
143
  // Inject the table and other surrounding information
137
144
  win.document.body.innerHTML =
138
- '<h1>'+title+'</h1>'+
139
- '<div>'+
140
- (typeof config.message === 'function' ?
141
- config.message( dt, button, config ) :
142
- config.message
143
- )+
144
- '</div>'+
145
- html;
145
+ '<h1>'+exportInfo.title+'</h1>'+
146
+ '<div>'+(exportInfo.messageTop || '')+'</div>'+
147
+ html+
148
+ '<div>'+(exportInfo.messageBottom || '')+'</div>';
146
149
 
147
150
  $(win.document.body).addClass('dt-print-view');
148
151
 
152
+ $('img', win.document.body).each( function ( i, img ) {
153
+ img.setAttribute( 'src', _relToAbs( img.getAttribute('src') ) );
154
+ } );
155
+
149
156
  if ( config.customize ) {
150
157
  config.customize( win );
151
158
  }
152
159
 
160
+ // Allow stylesheets time to load
153
161
  setTimeout( function () {
154
162
  if ( config.autoPrint ) {
155
163
  win.print(); // blocking - so close will not
156
164
  win.close(); // execute until this is done
157
165
  }
158
- }, 250 );
166
+ }, 1000 );
159
167
  },
160
168
 
161
169
  title: '*',
162
170
 
163
- message: '',
171
+ messageTop: '*',
172
+
173
+ messageBottom: '*',
164
174
 
165
175
  exportOptions: {},
166
176