Printer.js 9.4 KB

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