2 * @class Ext.ux.Printer.BaseRenderer
5 * Abstract base renderer class. Don't use this directly, use a subclass instead
7 Ext.ux.Printer.BaseRenderer = Ext.extend(Object, {
9 * @cfg {String} printStrategy window or iframe
11 printStrategy: 'iframe',
14 * @cfg {Boll} useHtml2Canvas
20 constructor: function(config) {
21 Ext.apply(this, config);
23 Ext.ux.Printer.BaseRenderer.superclass.constructor.call(this, config);
27 * template method to intercept when document is ready
29 * @param {Document} document
30 * @pram {Ext.Component} component
32 onBeforePrint: Ext.emptyFn,
35 * Prints the component
36 * @param {Ext.Component} component The component to print
38 print: function(component) {
39 this.mask = new Ext.LoadMask(Ext.getBody(), {msg: i18n._("Preparing print, please wait...")});
42 return this[this.printStrategy + 'Print'](component);
46 * Prints the component using the new window strategy
47 * @param {Ext.Component} component The component to print
49 windowPrint: function(component) {
50 var name = component && component.getXType
51 ? String.format("print_{0}_{1}", String(component.getXType()).replace(/(\.|-)/g, '_'), component.id.replace(/(\.|-)/g, '_'))
54 var win = window.open('', name);
56 win.document.write(this.generateHTML(component));
59 // gecko looses its document after document.close(). but fortunally waits with printing till css is loaded itself
60 return this.doPrint(win);
62 this.doPrintOnStylesheetLoad.defer(10, this, [win, component]);
66 * Prints the component using the hidden iframe strategy
67 * @param {Ext.Component} component The component to print
69 iframePrint: function(component) {
72 frame = doc.createElement('iframe'),
75 'background-color': '#FFFFFF',
96 doc.body.appendChild(frame);
99 src : Ext.SSL_SECURE_URL
102 var doc = frame.contentWindow.document || frame.contentDocument || WINDOW.frames[id].document;
105 doc.write(this.generateHTML(component));
108 this.doPrintOnStylesheetLoad.defer(10, this, [frame.contentWindow, component]);
112 * check if style is loaded and do print afterwards
114 * @param {window} win
116 doPrintOnStylesheetLoad: function(win, component) {
117 var el = win.document.getElementById('csscheck'),
118 comp = el.currentStyle || getComputedStyle(el, null);
119 if (comp.display !== "none") {
120 return this.doPrintOnStylesheetLoad.defer(10, this, [win, component]);
123 this.onBeforePrint(win.document, component);
128 doPrint: function(win) {
129 if (this.useHtml2Canvas) {
132 var canvas = win.document.createElement("canvas");
133 canvas.width = win.innerWidth;
134 canvas.height = win.innerHeight;
136 me.setDPI(canvas, 300);
138 html2canvas(win.document.body, {
141 onrendered: function (canvas) {
142 var screenshot = canvas.toDataURL();
143 me.useHtml2Canvas = false;
144 win.document.body.innerHTML = '<img style="display: block; width: 100%" />';
145 win.document.body.firstChild.onload = me.doPrint.createDelegate(me, [win]);
146 win.document.body.firstChild.src = screenshot;
158 setDPI: function (canvas, dpi) {
159 // Set up CSS size if it's not set up already
160 if (!canvas.style.width)
161 canvas.style.width = canvas.width + 'px';
162 if (!canvas.style.height)
163 canvas.style.height = canvas.height + 'px';
165 var scaleFactor = dpi / 96;
166 canvas.width = Math.ceil(canvas.width * scaleFactor);
167 canvas.height = Math.ceil(canvas.height * scaleFactor);
168 var ctx = canvas.getContext('2d');
169 ctx.scale(scaleFactor, scaleFactor);
173 * Generates the HTML Markup which wraps whatever this.generateBody produces
174 * @param {Ext.Component} component The component to generate HTML for
175 * @return {String} An HTML fragment to be placed inside the print window
177 generateHTML: function(component) {
178 return new Ext.XTemplate(
179 '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',
182 '<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />',
183 this.getAdditionalHeaders(),
184 '<link href="' + this.stylesheetPath + '?' + new Date().getTime() + '" rel="stylesheet" type="text/css" media="screen,print" />',
185 '<title>' + this.getTitle(component) + '</title>',
188 '<div id="csscheck"></div>',
189 this.generateBody(component),
192 ).apply(this.prepareData(component));
196 * Returns the HTML that will be placed into the <head> element of th print window.
197 * @param {Ext.Component} component The component to render
198 * @return {String} The HTML fragment to place inside the print window's <head> element
200 getAdditionalHeaders: function(component) {
204 * Returns the HTML that will be placed into the print window. This should produce HTML to go inside the
205 * <body> element only, as <head> is generated in the print function
206 * @param {Ext.Component} component The component to render
207 * @return {String} The HTML fragment to place inside the print window's <body> element
209 generateBody: Ext.emptyFn,
212 * Prepares data suitable for use in an XTemplate from the component
213 * @param {Ext.Component} component The component to acquire data from
214 * @return {Array} An empty array (override this to prepare your own data)
216 prepareData: function(component) {
221 * Returns the title to give to the print window
222 * @param {Ext.Component} component The component to be printed
223 * @return {String} The window title
225 getTitle: function(component) {
226 return typeof component.getTitle == 'function' ? component.getTitle() : (component.title || "Printing");
230 * @property stylesheetPath
232 * The path at which the print stylesheet can be found (defaults to 'stylesheets/print.css')
234 stylesheetPath: 'stylesheets/print.css'