You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

print_format.js 22 KiB

13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
12 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
13 vuotta sitten
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824
  1. // Copyright (c) 2012 Web Notes Technologies Pvt Ltd (http://erpnext.com)
  2. //
  3. // MIT License (MIT)
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a
  6. // copy of this software and associated documentation files (the "Software"),
  7. // to deal in the Software without restriction, including without limitation
  8. // the rights to use, copy, modify, merge, publish, distribute, sublicense,
  9. // and/or sell copies of the Software, and to permit persons to whom the
  10. // Software is furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
  16. // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  17. // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  18. // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
  19. // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
  20. // OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  21. //
  22. // default print style
  23. _p.def_print_style_body = "html, body, div, span, td { \
  24. font-family: Arial, Helvetica; font-size: 12px; }\
  25. pre { margin:0; padding:0;}"
  26. _p.def_print_style_other = "\n.simpletable, .noborder { \
  27. border-collapse: collapse; margin-bottom: 10px;}\
  28. .simpletable td {border: 1pt solid #777; vertical-align: top; padding: 4px; }\
  29. .noborder td { vertical-align: top; }"
  30. _p.go = function(html) {
  31. var d = document.createElement('div')
  32. d.innerHTML = html
  33. $(d).printElement();
  34. }
  35. _p.preview = function(html) {
  36. var w = window.open('');
  37. if(!w) return;
  38. w.document.write(html)
  39. w.document.close();
  40. }
  41. // _p can be referenced as this inside $.extend
  42. $.extend(_p, {
  43. show_dialog: function() {
  44. if(!_p.dialog) {
  45. _p.make_dialog();
  46. }
  47. _p.dialog.show();
  48. },
  49. make_dialog: function() {
  50. // Prepare Dialog Box Layout
  51. var d = new Dialog(
  52. 360, // w
  53. 140, // h
  54. 'Print Formats', // title
  55. [ // content
  56. ['HTML', 'Select'],
  57. ['Check', 'No Letterhead'],
  58. ['HTML', 'Buttons']
  59. ]);
  60. //d.widgets['No Letterhead'].checked = 1;
  61. // Print Button
  62. $btn(d.widgets.Buttons, 'Print', function() {
  63. _p.build(
  64. sel_val(cur_frm.print_sel), // fmtname
  65. _p.go, // onload
  66. d.widgets['No Letterhead'].checked // no_letterhead
  67. );
  68. },
  69. {
  70. cssFloat: 'right',
  71. marginBottom: '16px',
  72. marginLeft: '7px'
  73. }, 'green');
  74. // Print Preview
  75. $btn(d.widgets.Buttons, 'Preview', function() {
  76. _p.build(
  77. sel_val(cur_frm.print_sel), // fmtname
  78. _p.preview, // onload
  79. d.widgets['No Letterhead'].checked // no_letterhead
  80. );
  81. },
  82. {
  83. cssFloat: 'right',
  84. marginBottom: '16px'
  85. }, '');
  86. // Delete previous print format select list and Reload print format list from current form
  87. d.onshow = function() {
  88. var c = _p.dialog.widgets['Select'];
  89. if(c.cur_sel && c.cur_sel.parentNode == c) {
  90. c.removeChild(c.cur_sel);
  91. }
  92. c.appendChild(cur_frm.print_sel);
  93. c.cur_sel = cur_frm.print_sel;
  94. }
  95. _p.dialog = d;
  96. },
  97. // Define formats dict
  98. formats: {},
  99. /* args dict can contain:
  100. + fmtname --> print format name
  101. + onload
  102. + no_letterhead
  103. + only_body
  104. */
  105. build: function(fmtname, onload, no_letterhead, only_body) {
  106. if(!fmtname) {
  107. fmtname= "Standard";
  108. }
  109. args = {
  110. fmtname: fmtname,
  111. onload: onload,
  112. no_letterhead: no_letterhead,
  113. only_body: only_body
  114. };
  115. if(!cur_frm) {
  116. alert('No Document Selected');
  117. return;
  118. }
  119. // Get current doc (record)
  120. var doc = locals[cur_frm.doctype][cur_frm.docname];
  121. if(args.fmtname == 'Standard') {
  122. args.onload(_p.render({
  123. body: _p.print_std(args.no_letterhead),
  124. style: _p.print_style,
  125. doc: doc,
  126. title: doc.name,
  127. no_letterhead: args.no_letterhead,
  128. only_body: args.only_body
  129. }));
  130. } else {
  131. var print_format_doc = locals["Print Format"][args.fmtname];
  132. if(!print_format_doc) {
  133. msgprint("Unknown Print Format: " + args.fmtname);
  134. return;
  135. }
  136. args.onload(_p.render({
  137. body: print_format_doc.html,
  138. style: '',
  139. doc: doc,
  140. title: doc.name,
  141. no_letterhead: args.no_letterhead,
  142. only_body: args.only_body
  143. }));
  144. }
  145. },
  146. render: function(args) {
  147. var container = document.createElement('div');
  148. var stat = '';
  149. // if draft/archived, show draft/archived banner
  150. stat += _p.show_draft(args);
  151. stat += _p.show_archived(args);
  152. stat += _p.show_cancelled(args);
  153. // Append args.body's content as a child of container
  154. container.innerHTML = args.body;
  155. // Show letterhead?
  156. _p.show_letterhead(container, args);
  157. _p.run_embedded_js(container, args.doc);
  158. var style = _p.consolidate_css(container, args);
  159. _p.render_header_on_break(container, args);
  160. return _p.render_final(style, stat, container, args);
  161. },
  162. head_banner_format: function() {
  163. return "\
  164. <div style = '\
  165. text-align: center; \
  166. padding: 8px; \
  167. background-color: #CCC;'> \
  168. <div style = '\
  169. font-size: 20px; \
  170. font-weight: bold;'>\
  171. {{HEAD}}\
  172. </div>\
  173. {{DESCRIPTION}}\
  174. </div>"
  175. },
  176. /*
  177. Check if doc's status is not submitted (docstatus == 0)
  178. and submission is pending
  179. Display draft in header if true
  180. */
  181. show_draft: function(args) {
  182. var is_doctype_submittable = 0;
  183. var plist = locals['DocPerm'];
  184. for(var perm in plist) {
  185. var p = plist[perm];
  186. if((p.parent==args.doc.doctype) && (p.submit==1)){
  187. is_doctype_submittable = 1;
  188. break;
  189. }
  190. }
  191. if(args.doc && cint(args.doc.docstatus)==0 && is_doctype_submittable) {
  192. draft = _p.head_banner_format();
  193. draft = draft.replace("{{HEAD}}", "DRAFT");
  194. draft = draft.replace("{{DESCRIPTION}}", "This box will go away after the document is submitted.");
  195. return draft;
  196. } else {
  197. return "";
  198. }
  199. },
  200. /*
  201. Check if doc is archived
  202. Display archived in header if true
  203. */
  204. show_archived: function(args) {
  205. if(args.doc && args.doc.__archived) {
  206. archived = _p.head_banner_format();
  207. archived = archived.replace("{{HEAD}}", "ARCHIVED");
  208. archived = archived.replace("{{DESCRIPTION}}", "You must restore this document to make it editable.");
  209. return archived;
  210. } else {
  211. return "";
  212. }
  213. },
  214. /*
  215. Check if doc is cancelled
  216. Display cancelled in header if true
  217. */
  218. show_cancelled: function(args) {
  219. if(args.doc && args.doc.docstatus==2) {
  220. cancelled = _p.head_banner_format();
  221. cancelled = cancelled.replace("{{HEAD}}", "CANCELLED");
  222. cancelled = cancelled.replace("{{DESCRIPTION}}", "You must amend this document to make it editable.");
  223. return cancelled;
  224. } else {
  225. return "";
  226. }
  227. },
  228. consolidate_css: function(container, args) {
  229. // Extract <style> content from container
  230. var body_style = '';
  231. var style_list = container.getElementsByTagName('style');
  232. while(style_list && style_list.length>0) {
  233. for(i in style_list) {
  234. if(style_list[i] && style_list[i].innerHTML) {
  235. body_style += style_list[i].innerHTML;
  236. var parent = style_list[i].parentNode;
  237. if(parent) {
  238. parent.removeChild(style_list[i]);
  239. } else {
  240. container.removeChild(style_list[i]);
  241. }
  242. }
  243. }
  244. style_list = container.getElementsByTagName('style');
  245. }
  246. // Concatenate all styles
  247. //style_concat = _p.def_print_style_other + args.style + body_style;
  248. style_concat = (args.only_body ? '' : _p.def_print_style_body)
  249. + _p.def_print_style_other + args.style + body_style;
  250. return style_concat;
  251. },
  252. // This is used to calculate and substitude values in the HTML
  253. run_embedded_js: function(container, doc) {
  254. var jslist = container.getElementsByTagName('script');
  255. while(jslist && jslist.length > 0) {
  256. for(i in jslist) {
  257. if(jslist[i] && jslist[i].innerHTML) {
  258. var code = jslist[i].innerHTML;
  259. var parent = jslist[i].parentNode;
  260. var span = $a(parent, 'span');
  261. parent.replaceChild(span, jslist[i]);
  262. var val = code ? eval(code) : '';
  263. if(!val || typeof(val)=='object') { val = ''; }
  264. span.innerHTML = val;
  265. }
  266. }
  267. jslist = container.getElementsByTagName('script');
  268. }
  269. },
  270. // Attach letterhead at top of container
  271. show_letterhead: function(container, args) {
  272. if(!(args.no_letterhead || args.only_body)) {
  273. container.innerHTML = '<div>' + _p.get_letter_head() + '</div>'
  274. + container.innerHTML;
  275. }
  276. },
  277. render_header_on_break: function(container, args) {
  278. var page_set = container.getElementsByClassName('page-settings');
  279. if(page_set.length) {
  280. for(var i = 0; i < page_set.length; i++) {
  281. var tmp = '';
  282. // if draft/archived, show draft/archived banner
  283. tmp += _p.show_draft(args);
  284. tmp += _p.show_archived(args);
  285. _p.show_letterhead(page_set[i], args);
  286. page_set[i].innerHTML = tmp + page_set[i].innerHTML;
  287. }
  288. }
  289. },
  290. // called by _p.render for final render of print
  291. render_final: function(style, stat, container, args) {
  292. var header = '<div class="page-settings">\n';
  293. var footer = '\n</div>';
  294. if(!args.only_body) {
  295. header = '<!DOCTYPE html>\n\
  296. <html>\
  297. <head>\
  298. <title>' + args.title + '</title>\
  299. <style>' + style + '</style>\
  300. </head>\
  301. <body>\n' + header;
  302. footer = footer + '\n</body>\n\
  303. </html>';
  304. }
  305. var finished = header
  306. + stat
  307. + container.innerHTML.replace(/<div/g, '\n<div').replace(/<td/g, '\n<td')
  308. + footer;
  309. return finished;
  310. },
  311. // fetches letter head from current doc or control panel
  312. get_letter_head: function() {
  313. var cp = wn.control_panel;
  314. var lh = '';
  315. if(cur_frm.doc.letter_head) {
  316. lh = cstr(wn.boot.letter_heads[cur_frm.doc.letter_head]);
  317. } else if (cp.letter_head) {
  318. lh = cp.letter_head;
  319. }
  320. return lh;
  321. },
  322. // common print style setting
  323. print_style: "\
  324. .datalabelcell { \
  325. padding: 2px 0px; \
  326. width: 38%; \
  327. vertical-align: top; \
  328. } \
  329. .datainputcell { \
  330. padding: 2px 0px; \
  331. width: 62%; \
  332. text-align: left; \
  333. }\
  334. .sectionHeading { \
  335. font-size: 16px; \
  336. font-weight: bold; \
  337. margin: 8px 0px; \
  338. } \
  339. .columnHeading { \
  340. font-size: 14px; \
  341. font-weight: bold; \
  342. margin: 8px 0px; \
  343. }",
  344. print_std: function(no_letterhead) {
  345. // Get doctype, docname, layout for a doctype
  346. var docname = cur_frm.docname;
  347. var doctype = cur_frm.doctype;
  348. var data = getchildren('DocField', doctype, 'fields', 'DocType');
  349. var layout = _p.add_layout(doctype);
  350. this.pf_list = [layout];
  351. var me = this;
  352. me.layout = layout;
  353. $.extend(this, {
  354. build_head: function(data, doctype, docname) {
  355. // Heading
  356. var h1_style = {
  357. fontSize: '22px',
  358. marginBottom: '8px'
  359. }
  360. var h1 = $a(me.layout.cur_row.header, 'h1', '', h1_style);
  361. // Get print heading
  362. if (cur_frm.pformat[docname]) {
  363. // first check in cur_frm.pformat
  364. h1.innerHTML = cur_frm.pformat[docname];
  365. } else {
  366. // then check if select print heading exists and has a value
  367. var val = null;
  368. for (var i = 0; i < data.length; i++) {
  369. if (data[i].fieldname === 'select_print_heading') {
  370. val = _f.get_value(doctype, docname, data[i].fieldname);
  371. break;
  372. }
  373. }
  374. // if not, just have doctype has heading
  375. h1.innerHTML = val ? val : get_doctype_label(doctype);
  376. }
  377. var h2_style = {
  378. fontSize: '16px',
  379. color: '#888',
  380. marginBottom: '8px',
  381. paddingBottom: '8px',
  382. borderBottom: (me.layout.with_border ? '0px' :
  383. '1px solid #000')
  384. }
  385. var h2 = $a(me.layout.cur_row.header, 'div', '', h2_style);
  386. h2.innerHTML = docname;
  387. },
  388. build_data: function(data, doctype, docname) {
  389. // Start with a row and a cell in that row
  390. if(data[0] && data[0].fieldtype != "Section Break") {
  391. me.layout.addrow();
  392. if(data[0].fieldtype != "Column Break") {
  393. me.layout.addcell();
  394. }
  395. }
  396. $.extend(this, {
  397. generate_custom_html: function(field, doctype, docname) {
  398. var container = $a(me.layout.cur_cell, 'div');
  399. container.innerHTML = cur_frm.pformat[field.fieldname](locals[doctype][docname]);
  400. },
  401. render_normal: function(field, data, i) {
  402. switch(field.fieldtype) {
  403. case 'Section Break':
  404. me.layout.addrow();
  405. // Add column if no column break after this field
  406. if(data[i+1] && data[i+1].fieldtype !=
  407. 'Column Break') {
  408. me.layout.addcell();
  409. }
  410. break;
  411. case 'Column Break':
  412. me.layout.addcell(field.width, field.label);
  413. break;
  414. case 'Table':
  415. var table = print_table(
  416. doctype, // dt
  417. docname, // dn
  418. field.fieldname,
  419. field.options, // tabletype
  420. null, // cols
  421. null, // head_labels
  422. null, // widths
  423. null); // condition
  424. me.layout = _p.print_std_add_table(table, me.layout, me.pf_list, doctype, no_letterhead);
  425. break;
  426. case 'HTML':
  427. var div = $a(me.layout.cur_cell, 'div');
  428. div.innerHTML = field.options;
  429. break;
  430. case 'Code':
  431. var div = $a(me.layout.cur_cell, 'div');
  432. var val = _f.get_value(doctype, docname,
  433. field.fieldname);
  434. div.innerHTML = '<div>' + field.label +
  435. ': </div><pre style="font-family: Courier, Fixed;">' + (val ? val : '') +
  436. '</pre>';
  437. break;
  438. case 'Text Editor':
  439. var div = $a(me.layout.cur_cell, 'div');
  440. var val = _f.get_value(doctype, docname,
  441. field.fieldname);
  442. div.innerHTML = val ? val : '';
  443. break;
  444. default:
  445. // Add Cell Data
  446. _p.print_std_add_field(doctype, docname, field, me.layout);
  447. break;
  448. }
  449. }
  450. });
  451. // Then build each field
  452. for(var i = 0; i < data.length; i++) {
  453. var fieldname = data[i].fieldname ? data[i].fieldname :
  454. data[i].label;
  455. var field = fieldname ?
  456. wn.meta.get_docfield(doctype, fieldname, docname) : data[i];
  457. if(!field.print_hide) {
  458. if(cur_frm.pformat[field.fieldname]) {
  459. // If there is a custom method to generate the HTML, then use it
  460. this.generate_custom_html(field, doctype, docname);
  461. } else {
  462. // Do the normal rendering
  463. this.render_normal(field, data, i);
  464. }
  465. }
  466. }
  467. me.layout.close_borders();
  468. },
  469. build_html: function() {
  470. var html = '';
  471. for(var i = 0; i < me.pf_list.length; i++) {
  472. if(me.pf_list[i].wrapper) {
  473. html += me.pf_list[i].wrapper.innerHTML;
  474. } else if(me.pf_list[i].innerHTML) {
  475. html += me.pf_list[i].innerHTML;
  476. } else {
  477. html += me.pf_list[i];
  478. }
  479. }
  480. this.pf_list = [];
  481. return html;
  482. }
  483. });
  484. this.build_head(data, doctype, docname);
  485. this.build_data(data, doctype, docname);
  486. var html = this.build_html();
  487. return html;
  488. },
  489. add_layout: function(doctype) {
  490. var layout = new Layout();
  491. layout.addrow();
  492. if(locals['DocType'][doctype].print_outline == 'Yes') {
  493. layout.with_border = 1
  494. }
  495. return layout;
  496. },
  497. print_std_add_table: function(t, layout, pf_list, dt, no_letterhead) {
  498. if(t.appendChild) {
  499. // If only one table is passed
  500. layout.cur_cell.appendChild(t);
  501. } else {
  502. page_break = '\n\
  503. <div style = "page-break-after: always;" \
  504. class = "page_break"></div><div class="page-settings"></div>';
  505. // If a list of tables is passed
  506. for(var i = 0; i < t.length-1; i++) {
  507. // add to current page
  508. layout.cur_cell.appendChild(t[i]);
  509. layout.close_borders();
  510. pf_list.push(page_break);
  511. // Create new page
  512. layout = _p.add_layout(dt, no_letterhead);
  513. pf_list.push(layout);
  514. layout.addrow();
  515. layout.addcell();
  516. var div = $a(layout.cur_cell, 'div');
  517. div.innerHTML = 'Continued from previous page...';
  518. div.style.padding = '4px';
  519. }
  520. // Append last table
  521. layout.cur_cell.appendChild(t[t.length-1]);
  522. }
  523. return layout;
  524. },
  525. print_std_add_field: function(dt, dn, f, layout) {
  526. var val = _f.get_value(dt, dn, f.fieldname);
  527. if(f.fieldtype!='Button') {
  528. if(val || in_list(['Float', 'Int', 'Currency'], f.fieldtype)) {
  529. // If value or a numeric type then proceed
  530. // Add field table
  531. row = _p.field_tab(layout.cur_cell);
  532. // Add label
  533. row.cells[0].innerHTML = f.label ? f.label : f.fieldname;
  534. $s(row.cells[1], val, f.fieldtype);
  535. // left align currency in normal display
  536. if(f.fieldtype == 'Currency') {
  537. $y(row.cells[1], { textAlign: 'left' });
  538. }
  539. }
  540. }
  541. },
  542. field_tab: function(layout_cell) {
  543. var tab = $a(layout_cell, 'table', '', {width:'100%'});
  544. var row = tab.insertRow(0);
  545. _p.row = row; // Don't know this line's purpose
  546. row.insertCell(0);
  547. row.insertCell(1);
  548. row.cells[0].className = 'datalabelcell';
  549. row.cells[1].className = 'datainputcell';
  550. return row;
  551. }
  552. });
  553. print_table = function(dt, dn, fieldname, tabletype, cols, head_labels, widths, condition, cssClass, modifier, hide_empty) {
  554. var me = this;
  555. $.extend(this, {
  556. flist: (function() {
  557. var f_list = [];
  558. var fl = wn.meta.docfield_list[tabletype];
  559. if(fl) {
  560. for(var i=0; i<fl.length; i++) {
  561. f_list.push(copy_dict(fl[i]));
  562. }
  563. }
  564. return f_list;
  565. })(),
  566. data: function() {
  567. var children = getchildren(
  568. tabletype, // child_dt
  569. dn, // parent
  570. fieldname, // parentfield
  571. dt // parenttype
  572. );
  573. var data = []
  574. for(var i=0; i<children.length; i++) {
  575. data.push(copy_dict(children[i]));
  576. }
  577. return data;
  578. }(),
  579. cell_style: {
  580. border: '1px solid #999',
  581. padding: '3px',
  582. verticalAlign: 'top'
  583. },
  584. head_cell_style: {
  585. border: '1px solid #999',
  586. padding: '3px',
  587. verticalAlign: 'top',
  588. backgroundColor: '#ddd',
  589. fontWeight: 'bold'
  590. },
  591. table_style: {
  592. width: '100%',
  593. borderCollapse: 'collapse',
  594. marginBottom: '10px',
  595. marginTop: '10px'
  596. },
  597. remove_empty_cols: function(flist) {
  598. var non_empty_cols = []
  599. for(var i=0; i<me.data.length; i++) {
  600. for(var c=0; c<flist.length; c++) {
  601. if(flist[c].print_hide || !inList(['', null], me.data[i][flist[c].fieldname])) {
  602. if(!inList(non_empty_cols, flist[c])) {
  603. non_empty_cols.push(flist[c]);
  604. }
  605. }
  606. }
  607. }
  608. for(var c=0; c<flist.length; c++) {
  609. if(!inList(non_empty_cols, flist[c])) {
  610. flist.splice(c, 1);
  611. c = c - 1;
  612. }
  613. }
  614. },
  615. /*
  616. This function prepares a list of columns to be displayed and calls make_print_table to create a table with these columns
  617. */
  618. prepare_col_heads: function(flist) {
  619. var new_flist = [];
  620. if(!cols || (cols && cols.length && hide_empty)) {
  621. me.remove_empty_cols(flist);
  622. }
  623. // Make a list of column headings
  624. if(cols && cols.length) {
  625. // If cols to be displayed are passed in print_table
  626. if(cols[0] == 'SR') { new_flist.push('SR') }
  627. for(var i = 0; i < cols.length; i++) {
  628. for(var j = 0; j < flist.length; j++) {
  629. if(flist[j].fieldname == cols[i]) {
  630. new_flist.push(flist[j]);
  631. break;
  632. }
  633. }
  634. }
  635. } else {
  636. // Default action: remove hidden cols
  637. new_flist.push('SR');
  638. for(var i = 0; i < flist.length; i++) {
  639. if(!flist[i].print_hide) {
  640. new_flist.push(flist[i]);
  641. }
  642. }
  643. }
  644. // Changing me.flist so that it could be used to hide data
  645. me.flist = new_flist;
  646. },
  647. // This function makes a new table with its heading rows
  648. make_print_table: function(flist) {
  649. // Make a table
  650. var wrapper = document.createElement('div');
  651. var table = $a(wrapper, 'table', '', me.table_style);
  652. table.wrapper = wrapper;
  653. // Make Head Row
  654. table.insertRow(0);
  655. var col_start = 0;
  656. // If 'SR' exists in flist, then create its heading column cell
  657. if(flist[0]=='SR') {
  658. var cell = table.rows[0].insertCell(0);
  659. cell.innerHTML = head_labels?head_labels[0]:'<b>SR</b>';
  660. $y(cell, { width: '30px' });
  661. $y(cell, me.head_cell_style);
  662. col_start++;
  663. }
  664. for(var c = col_start; c < flist.length; c++) {
  665. var cell = table.rows[0].insertCell(c);
  666. $y(cell, me.head_cell_style);
  667. cell.innerHTML = head_labels?head_labels[c]:flist[c].label;
  668. if(flist[c].width) { $y(cell, {width: flist[c].width}); }
  669. if(widths) { $y(cell, {width: widths[c]}); }
  670. if(in_list(['Currency', 'Float'], flist[c].fieldtype)) {
  671. $y(cell, { textAlign: 'right' });
  672. }
  673. }
  674. return table;
  675. },
  676. // Populate table with data
  677. populate_table: function(table, data) {
  678. for(var r = 0; r < data.length; r++) {
  679. if((!condition) || (condition(data[r]))) {
  680. // Check for page break
  681. if(data[r].page_break) {
  682. table = me.make_print_table(me.flist);
  683. me.table_list.push(table.wrapper);
  684. }
  685. var row = table.insertRow(table.rows.length);
  686. // Add serial number if required
  687. if(me.flist[0] == 'SR') {
  688. var cell = row.insertCell(0);
  689. cell.innerHTML = r + 1;
  690. $y(cell, me.cell_style);
  691. }
  692. for(var c=me.flist.indexOf('SR')+1; c<me.flist.length; c++){
  693. var cell = row.insertCell(c);
  694. $y(cell, me.cell_style);
  695. if(modifier && me.flist[c].fieldname in modifier) {
  696. data[r][me.flist[c].fieldname] = modifier[me.flist[c].fieldname](data[r]);
  697. }
  698. $s(cell, data[r][me.flist[c].fieldname],
  699. me.flist[c].fieldtype);
  700. if(in_list(['Currency', 'Float'], me.flist[c].fieldtype)) {
  701. cell.style.textAlign = 'right';
  702. }
  703. }
  704. }
  705. }
  706. }
  707. });
  708. // If no data, do not create table
  709. if(!this.data.length) { return document.createElement('div'); }
  710. this.prepare_col_heads(this.flist);
  711. var table = me.make_print_table(this.flist);
  712. this.table_list = [table.wrapper];
  713. this.populate_table(table, this.data);
  714. // If multiple tables exists, send whole list, else send only one table
  715. return (me.table_list.length > 1) ? me.table_list : me.table_list[0];
  716. }