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