source: Dev/trunk/src/client/dojox/grid/enhanced/plugins/Printer.js

Last change on this file was 483, checked in by hendrikvanantwerpen, 11 years ago

Added Dojo 1.9.3 release.

File size: 9.1 KB
Line 
1define([
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
16var 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
289EnhancedGrid.registerPlugin(Printer/*name:'printer'*/, {
290        "dependency": ["exporter"]
291});
292
293return Printer;
294});
Note: See TracBrowser for help on using the repository browser.