buttons.print.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. /*!
  2. * Print button for Buttons and DataTables.
  3. * 2016 SpryMedia Ltd - datatables.net/license
  4. */
  5. (function( factory ){
  6. if ( typeof define === 'function' && define.amd ) {
  7. // AMD
  8. define( ['jquery', 'datatables.net', 'datatables.net-buttons'], function ( $ ) {
  9. return factory( $, window, document );
  10. } );
  11. }
  12. else if ( typeof exports === 'object' ) {
  13. // CommonJS
  14. module.exports = function (root, $) {
  15. if ( ! root ) {
  16. root = window;
  17. }
  18. if ( ! $ || ! $.fn.dataTable ) {
  19. $ = require('datatables.net')(root, $).$;
  20. }
  21. if ( ! $.fn.dataTable.Buttons ) {
  22. require('datatables.net-buttons')(root, $);
  23. }
  24. return factory( $, root, root.document );
  25. };
  26. }
  27. else {
  28. // Browser
  29. factory( jQuery, window, document );
  30. }
  31. }(function( $, window, document, undefined ) {
  32. 'use strict';
  33. var DataTable = $.fn.dataTable;
  34. var _link = document.createElement( 'a' );
  35. /**
  36. * Clone link and style tags, taking into account the need to change the source
  37. * path.
  38. *
  39. * @param {node} el Element to convert
  40. */
  41. var _styleToAbs = function( el ) {
  42. var url;
  43. var clone = $(el).clone()[0];
  44. var linkHost;
  45. if ( clone.nodeName.toLowerCase() === 'link' ) {
  46. clone.href = _relToAbs( clone.href );
  47. }
  48. return clone.outerHTML;
  49. };
  50. /**
  51. * Convert a URL from a relative to an absolute address so it will work
  52. * correctly in the popup window which has no base URL.
  53. *
  54. * @param {string} href URL
  55. */
  56. var _relToAbs = function( href ) {
  57. // Assign to a link on the original page so the browser will do all the
  58. // hard work of figuring out where the file actually is
  59. _link.href = href;
  60. var linkHost = _link.host;
  61. // IE doesn't have a trailing slash on the host
  62. // Chrome has it on the pathname
  63. if ( linkHost.indexOf('/') === -1 && _link.pathname.indexOf('/') !== 0) {
  64. linkHost += '/';
  65. }
  66. return _link.protocol+"//"+linkHost+_link.pathname+_link.search;
  67. };
  68. DataTable.ext.buttons.print = {
  69. className: 'buttons-print',
  70. text: function ( dt ) {
  71. return dt.i18n( 'buttons.print', 'Print' );
  72. },
  73. action: function ( e, dt, button, config ) {
  74. var data = dt.buttons.exportData(
  75. $.extend( {decodeEntities: false}, config.exportOptions ) // XSS protection
  76. );
  77. var exportInfo = dt.buttons.exportInfo( config );
  78. var columnClasses = dt
  79. .columns( config.exportOptions.columns )
  80. .flatten()
  81. .map( function (idx) {
  82. return dt.settings()[0].aoColumns[dt.column(idx).index()].sClass;
  83. } )
  84. .toArray();
  85. var addRow = function ( d, tag ) {
  86. var str = '<tr>';
  87. for ( var i=0, ien=d.length ; i<ien ; i++ ) {
  88. // null and undefined aren't useful in the print output
  89. var dataOut = d[i] === null || d[i] === undefined ?
  90. '' :
  91. d[i];
  92. var classAttr = columnClasses[i] ?
  93. 'class="'+columnClasses[i]+'"' :
  94. '';
  95. str += '<'+tag+' '+classAttr+'>'+dataOut+'</'+tag+'>';
  96. }
  97. return str + '</tr>';
  98. };
  99. // Construct a table for printing
  100. var html = '<table class="'+dt.table().node().className+'">';
  101. if ( config.header ) {
  102. html += '<thead>'+ addRow( data.header, 'th' ) +'</thead>';
  103. }
  104. html += '<tbody>';
  105. for ( var i=0, ien=data.body.length ; i<ien ; i++ ) {
  106. html += addRow( data.body[i], 'td' );
  107. }
  108. html += '</tbody>';
  109. if ( config.footer && data.footer ) {
  110. html += '<tfoot>'+ addRow( data.footer, 'th' ) +'</tfoot>';
  111. }
  112. html += '</table>';
  113. // Open a new window for the printable table
  114. var win = window.open( '', '' );
  115. if (! win) {
  116. dt.buttons.info(
  117. dt.i18n( 'buttons.printErrorTitle', 'Unable to open print view' ),
  118. dt.i18n( 'buttons.printErrorMsg', 'Please allow popups in your browser for this site to be able to view the print view.' ),
  119. 5000
  120. );
  121. return;
  122. }
  123. win.document.close();
  124. // Inject the title and also a copy of the style and link tags from this
  125. // document so the table can retain its base styling. Note that we have
  126. // to use string manipulation as IE won't allow elements to be created
  127. // in the host document and then appended to the new window.
  128. var head = '<title>'+exportInfo.title+'</title>';
  129. $('style, link').each( function () {
  130. head += _styleToAbs( this );
  131. } );
  132. try {
  133. win.document.head.innerHTML = head; // Work around for Edge
  134. }
  135. catch (e) {
  136. $(win.document.head).html( head ); // Old IE
  137. }
  138. // Inject the table and other surrounding information
  139. win.document.body.innerHTML =
  140. '<h1>'+exportInfo.title+'</h1>'+
  141. '<div>'+(exportInfo.messageTop || '')+'</div>'+
  142. html+
  143. '<div>'+(exportInfo.messageBottom || '')+'</div>';
  144. $(win.document.body).addClass('dt-print-view');
  145. $('img', win.document.body).each( function ( i, img ) {
  146. img.setAttribute( 'src', _relToAbs( img.getAttribute('src') ) );
  147. } );
  148. if ( config.customize ) {
  149. config.customize( win, config, dt );
  150. }
  151. // Allow stylesheets time to load
  152. var autoPrint = function () {
  153. if ( config.autoPrint ) {
  154. win.print(); // blocking - so close will not
  155. win.close(); // execute until this is done
  156. }
  157. };
  158. if ( navigator.userAgent.match(/Trident\/\d.\d/) ) { // IE needs to call this without a setTimeout
  159. autoPrint();
  160. }
  161. else {
  162. win.setTimeout( autoPrint, 1000 );
  163. }
  164. },
  165. title: '*',
  166. messageTop: '*',
  167. messageBottom: '*',
  168. exportOptions: {},
  169. header: true,
  170. footer: false,
  171. autoPrint: true,
  172. customize: null
  173. };
  174. return DataTable.Buttons;
  175. }));