1 | define([ |
---|
2 | "dojo/_base/declare", |
---|
3 | "dojo/_base/html", |
---|
4 | "dojo/_base/Deferred", |
---|
5 | "dojo/_base/lang", |
---|
6 | "dojo/_base/sniff", |
---|
7 | "dojo/_base/xhr", |
---|
8 | "dojo/_base/array", |
---|
9 | "dojo/query", |
---|
10 | "dojo/DeferredList", |
---|
11 | "../_Plugin", |
---|
12 | "../../EnhancedGrid", |
---|
13 | "./exporter/TableWriter" |
---|
14 | ], function(declare, html, Deferred, lang, has, xhr, array, query, DeferredList, _Plugin, EnhancedGrid, TableWriter){ |
---|
15 | |
---|
16 | var Printer = declare("dojox.grid.enhanced.plugins.Printer", _Plugin, { |
---|
17 | // summary: |
---|
18 | // Provide printGrid function to the grid. |
---|
19 | // example: |
---|
20 | // | dojo.require("dojox.grid.enhanced.plugins.Printer"); |
---|
21 | // | dijit.byId("grid1").printGrid("my grid", //A title for the grid,optional |
---|
22 | // | ["cssfile1.css","cssfile2.css"],//An array of css files to decorate the printed gird,optional |
---|
23 | // | {table:"border='border'"} //tagName:"attrbuteList" pairs, optional, |
---|
24 | // | //control the html tags in the generated html |
---|
25 | // | ); |
---|
26 | |
---|
27 | /*===== |
---|
28 | __printArgs: { |
---|
29 | // title: String |
---|
30 | // A title of the printed page can be specified. Optional. |
---|
31 | // If given, it's shown in an <h1> tag at the top of the page. |
---|
32 | // cssFiles: Array|String |
---|
33 | // CSS file paths. Optional. |
---|
34 | // Every row and column is given CSS classes, including: |
---|
35 | // |
---|
36 | // - grid_row_{row-number}, grid_odd_row, grid_even_row, grid_header, |
---|
37 | // grid_col_{col-number}, grid_odd_col, grid_even_col |
---|
38 | // - {row_number} and {col-number} are both integers starting from 1. |
---|
39 | // - Row classes are for <thead> and <tbody> tags. |
---|
40 | // - Column classes are for <th> and <td> tags. |
---|
41 | // - Users can use these classes in the CSS files, but cannot define their own. |
---|
42 | // writerArgs: Object |
---|
43 | // Associative Array, arguments for TableWriter. |
---|
44 | // fetchArgs: object? |
---|
45 | // Any arguments for store.fetch |
---|
46 | }, |
---|
47 | =====*/ |
---|
48 | |
---|
49 | // name: String |
---|
50 | // Plugin name |
---|
51 | name: "printer", |
---|
52 | |
---|
53 | constructor: function(grid){ |
---|
54 | // summary: |
---|
55 | // only newed by _Plugin |
---|
56 | // inGrid: EnhancedGrid |
---|
57 | // The grid to plug in to. |
---|
58 | this.grid = grid; |
---|
59 | this._mixinGrid(grid); |
---|
60 | |
---|
61 | //For print, we usually need the HTML instead of raw data. |
---|
62 | grid.setExportFormatter(function(data, cell, rowIndex, rowItem){ |
---|
63 | return cell.format(rowIndex, rowItem); |
---|
64 | }); |
---|
65 | }, |
---|
66 | _mixinGrid: function(){ |
---|
67 | var g = this.grid; |
---|
68 | g.printGrid = lang.hitch(this, this.printGrid); |
---|
69 | g.printSelected = lang.hitch(this, this.printSelected); |
---|
70 | g.exportToHTML = lang.hitch(this, this.exportToHTML); |
---|
71 | g.exportSelectedToHTML = lang.hitch(this, this.exportSelectedToHTML); |
---|
72 | g.normalizePrintedGrid = lang.hitch(this, this.normalizeRowHeight); |
---|
73 | }, |
---|
74 | printGrid: function(args){ |
---|
75 | // summary: |
---|
76 | // Print all the data in the grid, using title as a title, |
---|
77 | // decorating generated html by cssFiles, |
---|
78 | // using tagName:"attrbuteList" pairs(writerArgs) to control html tags |
---|
79 | // in the generated html string. |
---|
80 | // tags: |
---|
81 | // public |
---|
82 | // args: __printArgs? |
---|
83 | // Arguments for print. |
---|
84 | this.exportToHTML(args, lang.hitch(this, this._print)); |
---|
85 | }, |
---|
86 | printSelected: function(args){ |
---|
87 | // summary: |
---|
88 | // Print selected data. All other features are the same as printGrid. |
---|
89 | // For meaning of arguments see function *printGrid* |
---|
90 | // tags: |
---|
91 | // public |
---|
92 | // args: __printArgs? |
---|
93 | // Arguments for print. |
---|
94 | this.exportSelectedToHTML(args, lang.hitch(this, this._print)); |
---|
95 | }, |
---|
96 | exportToHTML: function(args, onExported){ |
---|
97 | // summary: |
---|
98 | // Export to HTML string, but do NOT print. |
---|
99 | // Users can use this to implement print preview. |
---|
100 | // For meaning of the 1st-3rd arguments see function *printGrid*. |
---|
101 | // tags: |
---|
102 | // public |
---|
103 | // args: __printArgs? |
---|
104 | // Arguments for print. |
---|
105 | // onExported: function(string) |
---|
106 | // call back function |
---|
107 | args = this._formalizeArgs(args); |
---|
108 | var _this = this; |
---|
109 | this.grid.exportGrid("table", args, function(str){ |
---|
110 | _this._wrapHTML(args.title, args.cssFiles, args.titleInBody + str).then(onExported); |
---|
111 | }); |
---|
112 | }, |
---|
113 | exportSelectedToHTML: function(args, onExported){ |
---|
114 | // summary: |
---|
115 | // Export selected rows to HTML string, but do NOT print. |
---|
116 | // Users can use this to implement print preview. |
---|
117 | // For meaning of arguments see function *printGrid* |
---|
118 | // tags: |
---|
119 | // public |
---|
120 | // args: __printArgs? |
---|
121 | // Arguments for print. |
---|
122 | args = this._formalizeArgs(args); |
---|
123 | var _this = this; |
---|
124 | this.grid.exportSelected("table", args.writerArgs, function(str){ |
---|
125 | _this._wrapHTML(args.title, args.cssFiles, args.titleInBody + str).then(onExported); |
---|
126 | }); |
---|
127 | }, |
---|
128 | |
---|
129 | _loadCSSFiles: function(cssFiles){ |
---|
130 | var dl = array.map(cssFiles, function(cssFile){ |
---|
131 | cssFile = lang.trim(cssFile); |
---|
132 | if(cssFile.substring(cssFile.length - 4).toLowerCase() === '.css'){ |
---|
133 | return xhr.get({ |
---|
134 | url: cssFile |
---|
135 | }); |
---|
136 | }else{ |
---|
137 | var d = new Deferred(); |
---|
138 | d.callback(cssFile); |
---|
139 | return d; |
---|
140 | } |
---|
141 | }); |
---|
142 | return DeferredList.prototype.gatherResults(dl); |
---|
143 | }, |
---|
144 | _print: function(/* string */htmlStr){ |
---|
145 | // summary: |
---|
146 | // Do the print job. |
---|
147 | // tags: |
---|
148 | // private |
---|
149 | // htmlStr: String |
---|
150 | // The html content string to be printed. |
---|
151 | // returns: |
---|
152 | // undefined |
---|
153 | var win, _this = this, |
---|
154 | fillDoc = function(w){ |
---|
155 | var doc = w.document; |
---|
156 | doc.open(); |
---|
157 | doc.write(htmlStr); |
---|
158 | doc.close(); |
---|
159 | _this.normalizeRowHeight(doc); |
---|
160 | }; |
---|
161 | if(!window.print){ |
---|
162 | //We don't have a print facility. |
---|
163 | return; |
---|
164 | }else if(has('chrome') || has('opera')){ |
---|
165 | //referred from dijit._editor.plugins.Print._print() |
---|
166 | //In opera and chrome the iframe.contentWindow.print |
---|
167 | //will also print the outside window. So we must create a |
---|
168 | //stand-alone new window. |
---|
169 | win = window.open("javascript: ''", "", |
---|
170 | "status=0,menubar=0,location=0,toolbar=0,width=1,height=1,resizable=0,scrollbars=0"); |
---|
171 | fillDoc(win); |
---|
172 | win.print(); |
---|
173 | //Opera will stop at this point, showing the popping-out window. |
---|
174 | //If the user closes the window, the following codes will not execute. |
---|
175 | //If the user returns focus to the main window, the print function |
---|
176 | // is executed, but still a no-op. |
---|
177 | win.close(); |
---|
178 | }else{ |
---|
179 | //Put private things in deeper namespace to avoid poluting grid namespace. |
---|
180 | var fn = this._printFrame, |
---|
181 | dn = this.grid.domNode; |
---|
182 | if(!fn){ |
---|
183 | var frameId = dn.id + "_print_frame"; |
---|
184 | if(!(fn = html.byId(frameId))){ |
---|
185 | //create an iframe to store the grid data. |
---|
186 | fn = html.create("iframe"); |
---|
187 | fn.id = frameId; |
---|
188 | fn.frameBorder = 0; |
---|
189 | html.style(fn, { |
---|
190 | width: "1px", |
---|
191 | height: "1px", |
---|
192 | position: "absolute", |
---|
193 | right: 0, |
---|
194 | bottom: 0, |
---|
195 | border: "none", |
---|
196 | overflow: "hidden" |
---|
197 | }); |
---|
198 | if(!has('ie')){ |
---|
199 | html.style(fn, "visibility", "hidden"); |
---|
200 | } |
---|
201 | dn.appendChild(fn); |
---|
202 | } |
---|
203 | //Reuse this iframe |
---|
204 | this._printFrame = fn; |
---|
205 | } |
---|
206 | win = fn.contentWindow; |
---|
207 | fillDoc(win); |
---|
208 | //IE requires the frame to be focused for print to work, and it's harmless for FF. |
---|
209 | win.focus(); |
---|
210 | win.print(); |
---|
211 | } |
---|
212 | }, |
---|
213 | _wrapHTML: function(/* string */title, /* Array */cssFiles, /* string */body_content){ |
---|
214 | // summary: |
---|
215 | // Put title, cssFiles, and body_content together into an HTML string. |
---|
216 | // tags: |
---|
217 | // private |
---|
218 | // title: String |
---|
219 | // A title for the html page. |
---|
220 | // cssFiles: Array |
---|
221 | // css file pathes. |
---|
222 | // body_content: String |
---|
223 | // Content to print, not including <head></head> part and <html> tags |
---|
224 | // returns: |
---|
225 | // the wrapped HTML string ready for print |
---|
226 | return this._loadCSSFiles(cssFiles).then(function(cssStrs){ |
---|
227 | var i, sb = ['<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">', |
---|
228 | '<html ', html._isBodyLtr() ? '' : 'dir="rtl"', '><head><title>', title, |
---|
229 | '</title><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>']; |
---|
230 | for(i = 0; i < cssStrs.length; ++i){ |
---|
231 | sb.push('<style type="text/css">', cssStrs[i], '</style>'); |
---|
232 | } |
---|
233 | sb.push('</head>'); |
---|
234 | if(body_content.search(/^\s*<body/i) < 0){ |
---|
235 | body_content = '<body>' + body_content + '</body>'; |
---|
236 | } |
---|
237 | sb.push(body_content, '</html>'); |
---|
238 | return sb.join(''); |
---|
239 | }); |
---|
240 | }, |
---|
241 | normalizeRowHeight: function(doc){ |
---|
242 | var views = query(".grid_view", doc.body); |
---|
243 | var headPerView = array.map(views, function(view){ |
---|
244 | return query(".grid_header", view)[0]; |
---|
245 | }); |
---|
246 | var rowsPerView = array.map(views, function(view){ |
---|
247 | return query(".grid_row", view); |
---|
248 | }); |
---|
249 | var rowCount = rowsPerView[0].length; |
---|
250 | var i, v, h, maxHeight = 0; |
---|
251 | for(v = views.length - 1; v >= 0; --v){ |
---|
252 | h = html.contentBox(headPerView[v]).h; |
---|
253 | if(h > maxHeight){ |
---|
254 | maxHeight = h; |
---|
255 | } |
---|
256 | } |
---|
257 | for(v = views.length - 1; v >= 0; --v){ |
---|
258 | html.style(headPerView[v], "height", maxHeight + "px"); |
---|
259 | } |
---|
260 | for(i = 0; i < rowCount; ++i){ |
---|
261 | maxHeight = 0; |
---|
262 | for(v = views.length - 1; v >= 0; --v){ |
---|
263 | h = html.contentBox(rowsPerView[v][i]).h; |
---|
264 | if(h > maxHeight){ |
---|
265 | maxHeight = h; |
---|
266 | } |
---|
267 | } |
---|
268 | for(v = views.length - 1; v >= 0; --v){ |
---|
269 | html.style(rowsPerView[v][i], "height", maxHeight + "px"); |
---|
270 | } |
---|
271 | } |
---|
272 | var left = 0, ltr = html._isBodyLtr(); |
---|
273 | for(v = 0; v < views.length; ++v){ |
---|
274 | html.style(views[v], ltr ? "left" : "right", left + "px"); |
---|
275 | left += html.marginBox(views[v]).w; |
---|
276 | } |
---|
277 | }, |
---|
278 | _formalizeArgs: function(args){ |
---|
279 | args = (args && lang.isObject(args)) ? args : {}; |
---|
280 | args.title = String(args.title) || ""; |
---|
281 | if(!lang.isArray(args.cssFiles)){ |
---|
282 | args.cssFiles = [args.cssFiles]; |
---|
283 | } |
---|
284 | args.titleInBody = args.title ? ['<h1>', args.title, '</h1>'].join('') : ''; |
---|
285 | return args; //Object |
---|
286 | } |
---|
287 | }); |
---|
288 | |
---|
289 | EnhancedGrid.registerPlugin(Printer/*name:'printer'*/, { |
---|
290 | "dependency": ["exporter"] |
---|
291 | }); |
---|
292 | |
---|
293 | return Printer; |
---|
294 | }); |
---|