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