//>>built define("dojox/grid/enhanced/plugins/Printer", [ "dojo/_base/declare", "dojo/_base/html", "dojo/_base/Deferred", "dojo/_base/lang", "dojo/_base/sniff", "dojo/_base/xhr", "dojo/_base/array", "dojo/query", "dojo/DeferredList", "../_Plugin", "../../EnhancedGrid", "./exporter/TableWriter" ], function(declare, html, Deferred, lang, has, xhr, array, query, DeferredList, _Plugin, EnhancedGrid, TableWriter){ var Printer = declare("dojox.grid.enhanced.plugins.Printer", _Plugin, { // summary: // Provide printGrid function to the grid. // example: // | dojo.require("dojox.grid.enhanced.plugins.Printer"); // | dijit.byId("grid1").printGrid("my grid", //A title for the grid,optional // | ["cssfile1.css","cssfile2.css"],//An array of css files to decorate the printed gird,optional // | {table:"border='border'"} //tagName:"attrbuteList" pairs, optional, // | //control the html tags in the generated html // | ); // __printArgs: { // title: String // A title of the printed page can be specified. Optional. // If given, it's shown in an

tag at the top of the page. // cssFiles: Array | String // CSS file paths. Optional. // Every row and column is given CSS classes, including: // grid_row_{row-number}, grid_odd_row, grid_even_row, grid_header, // grid_col_{col-number}, grid_odd_col, grid_even_col // {row_number} and {col-number} are both integers starting from 1. // Row classes are for and tags. // Column classes are for and tags. // Users can use these classes in the CSS files, but cannot define their own. // writerArgs: Object (Association Array) // Arguments for TableWriter. // fetchArgs: object? // Any arguments for store.fetch // } // name: String // Plugin name name: "printer", constructor: function(grid){ // summary: // only newed by _Plugin // inGrid: EnhancedGrid // The grid to plug in to. this.grid = grid; this._mixinGrid(grid); //For print, we usually need the HTML instead of raw data. grid.setExportFormatter(function(data, cell, rowIndex, rowItem){ return cell.format(rowIndex, rowItem); }); }, _mixinGrid: function(){ var g = this.grid; g.printGrid = lang.hitch(this, this.printGrid); g.printSelected = lang.hitch(this, this.printSelected); g.exportToHTML = lang.hitch(this, this.exportToHTML); g.exportSelectedToHTML = lang.hitch(this, this.exportSelectedToHTML); g.normalizePrintedGrid = lang.hitch(this, this.normalizeRowHeight); }, printGrid: function(args){ // summary: // Print all the data in the grid, using title as a title, // decorating generated html by cssFiles, // using tagName:"attrbuteList" pairs(writerArgs) to control html tags // in the generated html string. // tags: // public // args: __printArgs? // Arguments for print. this.exportToHTML(args, lang.hitch(this, this._print)); }, printSelected: function(args){ // summary: // Print selected data. All other features are the same as printGrid. // For meaning of arguments see function *printGrid* // tags: // public // args: __printArgs? // Arguments for print. this.exportSelectedToHTML(args, lang.hitch(this, this._print)); }, exportToHTML: function(args, onExported){ // summary: // Export to HTML string, but do NOT print. // Users can use this to implement print preview. // For meaning of the 1st-3rd arguments see function *printGrid*. // tags: // public // args: __printArgs? // Arguments for print. // onExported: function(string) // call back function args = this._formalizeArgs(args); var _this = this; this.grid.exportGrid("table", args, function(str){ _this._wrapHTML(args.title, args.cssFiles, args.titleInBody + str).then(onExported); }); }, exportSelectedToHTML: function(args, onExported){ // summary: // Export selected rows to HTML string, but do NOT print. // Users can use this to implement print preview. // For meaning of arguments see function *printGrid* // tags: // public // args: __printArgs? // Arguments for print. args = this._formalizeArgs(args); var _this = this; this.grid.exportSelected("table", args.writerArgs, function(str){ _this._wrapHTML(args.title, args.cssFiles, args.titleInBody + str).then(onExported); }); }, _loadCSSFiles: function(cssFiles){ var dl = array.map(cssFiles, function(cssFile){ cssFile = lang.trim(cssFile); if(cssFile.substring(cssFile.length - 4).toLowerCase() === '.css'){ return xhr.get({ url: cssFile }); }else{ var d = new Deferred(); d.callback(cssFile); return d; } }); return DeferredList.prototype.gatherResults(dl); }, _print: function(/* string */htmlStr){ // summary: // Do the print job. // tags: // private // htmlStr: String // The html content string to be printed. // returns: // undefined var win, _this = this, fillDoc = function(w){ var doc = w.document; doc.open(); doc.write(htmlStr); doc.close(); _this.normalizeRowHeight(doc); }; if(!window.print){ //We don't have a print facility. return; }else if(has("chrome") || has("opera")){ //referred from dijit._editor.plugins.Print._print() //In opera and chrome the iframe.contentWindow.print //will also print the outside window. So we must create a //stand-alone new window. win = window.open("javascript: ''", "", "status=0,menubar=0,location=0,toolbar=0,width=1,height=1,resizable=0,scrollbars=0"); fillDoc(win); win.print(); //Opera will stop at this point, showing the popping-out window. //If the user closes the window, the following codes will not execute. //If the user returns focus to the main window, the print function // is executed, but still a no-op. win.close(); }else{ //Put private things in deeper namespace to avoid poluting grid namespace. var fn = this._printFrame, dn = this.grid.domNode; if(!fn){ var frameId = dn.id + "_print_frame"; if(!(fn = html.byId(frameId))){ //create an iframe to store the grid data. fn = html.create("iframe"); fn.id = frameId; fn.frameBorder = 0; html.style(fn, { width: "1px", height: "1px", position: "absolute", right: 0, bottom: 0, border: "none", overflow: "hidden" }); if(!has("ie")){ html.style(fn, "visibility", "hidden"); } dn.appendChild(fn); } //Reuse this iframe this._printFrame = fn; } win = fn.contentWindow; fillDoc(win); //IE requires the frame to be focused for print to work, and it's harmless for FF. win.focus(); win.print(); } }, _wrapHTML: function(/* string */title, /* Array */cssFiles, /* string */body_content){ // summary: // Put title, cssFiles, and body_content together into an HTML string. // tags: // private // title: String // A title for the html page. // cssFiles: Array // css file pathes. // body_content: String // Content to print, not including part and tags // returns: // the wrapped HTML string ready for print return this._loadCSSFiles(cssFiles).then(function(cssStrs){ var i, sb = ['', '', title, '']; for(i = 0; i < cssStrs.length; ++i){ sb.push(''); } sb.push(''); if(body_content.search(/^\s*'; } sb.push(body_content, ''); return sb.join(''); }); }, normalizeRowHeight: function(doc){ var views = query(".grid_view", doc.body); var headPerView = array.map(views, function(view){ return query(".grid_header", view)[0]; }); var rowsPerView = array.map(views, function(view){ return query(".grid_row", view); }); var rowCount = rowsPerView[0].length; var i, v, h, maxHeight = 0; for(v = views.length - 1; v >= 0; --v){ h = html.contentBox(headPerView[v]).h; if(h > maxHeight){ maxHeight = h; } } for(v = views.length - 1; v >= 0; --v){ html.style(headPerView[v], "height", maxHeight + "px"); } for(i = 0; i < rowCount; ++i){ maxHeight = 0; for(v = views.length - 1; v >= 0; --v){ h = html.contentBox(rowsPerView[v][i]).h; if(h > maxHeight){ maxHeight = h; } } for(v = views.length - 1; v >= 0; --v){ html.style(rowsPerView[v][i], "height", maxHeight + "px"); } } var left = 0, ltr = html._isBodyLtr(); for(v = 0; v < views.length; ++v){ html.style(views[v], ltr ? "left" : "right", left + "px"); left += html.marginBox(views[v]).w; } }, _formalizeArgs: function(args){ args = (args && lang.isObject(args)) ? args : {}; args.title = String(args.title) || ""; if(!lang.isArray(args.cssFiles)){ args.cssFiles = [args.cssFiles]; } args.titleInBody = args.title ? ['

', args.title, '

'].join('') : ''; return args; //Object } }); EnhancedGrid.registerPlugin(Printer/*name:'printer'*/, { "dependency": ["exporter"] }); return Printer; });