// Copyright (c) 2012 Web Notes Technologies Pvt Ltd (http://erpnext.com) // // MIT License (MIT) // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE // OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // // default print style _p.def_print_style_body = "html, body, div, span, td { font-family: Arial, Helvetica; font-size: 12px; }" + "\npre { margin:0; padding:0;}" _p.def_print_style_other = "\n.simpletable, .noborder { border-collapse: collapse; margin-bottom: 10px;}" +"\n.simpletable td {border: 1pt solid #000; vertical-align: top; padding: 2px; }" +"\n.noborder td { vertical-align: top; }" _p.go = function(html) { var d = document.createElement('div') d.innerHTML = html $(d).printElement(); } _p.preview = function(html) { var w = window.open(''); if(!w) return; w.document.write(html) w.document.close(); } // _p can be referenced as this inside $.extend $.extend(_p, { show_dialog: function() { if(!_p.dialog) { _p.make_dialog(); } _p.dialog.show(); }, make_dialog: function() { // Prepare Dialog Box Layout var d = new Dialog( 360, // w 140, // h 'Print Formats', // title [ // content ['HTML', 'Select'], ['Check', 'No Letterhead'], ['HTML', 'Buttons'] ]); //d.widgets['No Letterhead'].checked = 1; // Print Button $btn(d.widgets.Buttons, 'Print', function() { _p.build( sel_val(cur_frm.print_sel), // fmtname _p.go, // onload d.widgets['No Letterhead'].checked // no_letterhead ); }, { cssFloat: 'right', marginBottom: '16px', marginLeft: '7px' }, 'green'); // Print Preview $btn(d.widgets.Buttons, 'Preview', function() { _p.build( sel_val(cur_frm.print_sel), // fmtname _p.preview, // onload d.widgets['No Letterhead'].checked // no_letterhead ); }, { cssFloat: 'right', marginBottom: '16px' }, ''); // Delete previous print format select list and Reload print format list from current form d.onshow = function() { var c = _p.dialog.widgets['Select']; if(c.cur_sel && c.cur_sel.parentNode == c) { c.removeChild(c.cur_sel); } c.appendChild(cur_frm.print_sel); c.cur_sel = cur_frm.print_sel; } _p.dialog = d; }, // Define formats dict formats: {}, /* args dict can contain: + fmtname --> print format name + onload + no_letterhead + only_body */ build: function(fmtname, onload, no_letterhead, only_body) { args = { fmtname: fmtname, onload: onload, no_letterhead: no_letterhead, only_body: only_body }; if(!cur_frm) { alert('No Document Selected'); return; } // Get current doc (record) var doc = locals[cur_frm.doctype][cur_frm.docname]; if(args.fmtname == 'Standard') { /* Render standard print layout The function passed as args onload is then called using these parameters */ args.onload(_p.render({ body: _p.print_std(args.no_letterhead), style: _p.print_style, doc: doc, title: doc.name, no_letterhead: args.no_letterhead, only_body: args.only_body })); } else { if (!_p.formats[args.fmtname]) { /* If print formats are not loaded, then load them and call the args onload function on callback. I think, this case happens when preview is invoked directly */ var build_args = args; $c( command = 'webnotes.widgets.form.print_format.get', args = { 'name': build_args.fmtname }, fn = function(r, rt) { _p.formats[build_args.fmtname] = r.message; build_args.onload(_p.render({ body: _p.formats[build_args.fmtname], style: '', doc: doc, title: doc.name, no_letterhead: build_args.no_letterhead, only_body: build_args.only_body })); } ); } else { // If print format is already loaded, go ahead with args onload function call args.onload(_p.render({ body: _p.formats[args.fmtname], style: '', doc: doc, title: doc.name, no_letterhead: args.no_letterhead, only_body: args.only_body })); } } }, /* args dict can contain: + body + style + doc + title + no_letterhead + only_body */ render: function(args) { var container = document.createElement('div'); var stat = ''; // if draft/archived, show draft/archived banner stat += _p.show_draft(args); stat += _p.show_archived(args); stat += _p.show_cancelled(args); // Append args.body's content as a child of container container.innerHTML = args.body; // Show letterhead? _p.show_letterhead(container, args); _p.run_embedded_js(container, args.doc); var style = _p.consolidate_css(container, args); _p.render_header_on_break(container, args); return _p.render_final(style, stat, container, args); }, head_banner_format: function() { return "\
\
\ {{HEAD}}\
\ {{DESCRIPTION}}\
" }, /* Check if doc's status is not submitted (docstatus == 0) and submission is pending Display draft in header if true */ show_draft: function(args) { var is_doctype_submittable = 0; var plist = locals['DocPerm']; for(var perm in plist) { var p = plist[perm]; if((p.parent==args.doc.doctype) && (p.submit==1)){ is_doctype_submittable = 1; break; } } if(args.doc && cint(args.doc.docstatus)==0 && is_doctype_submittable) { draft = _p.head_banner_format(); draft = draft.replace("{{HEAD}}", "DRAFT"); draft = draft.replace("{{DESCRIPTION}}", "This box will go away after the document is submitted."); return draft; } else { return ""; } }, /* Check if doc is archived Display archived in header if true */ show_archived: function(args) { if(args.doc && args.doc.__archived) { archived = _p.head_banner_format(); archived = archived.replace("{{HEAD}}", "ARCHIVED"); archived = archived.replace("{{DESCRIPTION}}", "You must restore this document to make it editable."); return archived; } else { return ""; } }, /* Check if doc is cancelled Display cancelled in header if true */ show_cancelled: function(args) { if(args.doc && args.doc.docstatus==2) { cancelled = _p.head_banner_format(); cancelled = cancelled.replace("{{HEAD}}", "CANCELLED"); cancelled = cancelled.replace("{{DESCRIPTION}}", "You must amend this document to make it editable."); return cancelled; } else { return ""; } }, consolidate_css: function(container, args) { // Extract \ \ \n' + header; footer = footer + '\n\n\ '; } var finished = header + stat + container.innerHTML.replace(/
' + (val ? val : '') +
									'
'; break; case 'Text Editor': var div = $a(me.layout.cur_cell, 'div'); var val = _f.get_value(doctype, docname, field.fieldname); div.innerHTML = val ? val : ''; break; default: // Add Cell Data _p.print_std_add_field(doctype, docname, field, me.layout); break; } } }); // Then build each field for(var i = 0; i < data.length; i++) { var fieldname = data[i].fieldname ? data[i].fieldname : data[i].label; var field = fieldname ? get_field(doctype, fieldname, docname) : data[i]; if(!field.print_hide) { if(cur_frm.pformat[field.fieldname]) { // If there is a custom method to generate the HTML, then use it this.generate_custom_html(field, doctype, docname); } else { // Do the normal rendering this.render_normal(field, data, i); } } } me.layout.close_borders(); }, build_html: function() { var html = ''; for(var i = 0; i < me.pf_list.length; i++) { if(me.pf_list[i].wrapper) { html += me.pf_list[i].wrapper.innerHTML; } else if(me.pf_list[i].innerHTML) { html += me.pf_list[i].innerHTML; } else { html += me.pf_list[i]; } } this.pf_list = []; return html; } }); this.build_head(doctype, docname); this.build_data(data, doctype, docname); var html = this.build_html(); return html; }, add_layout: function(doctype) { var layout = new Layout(); layout.addrow(); if(locals['DocType'][doctype].print_outline == 'Yes') { layout.with_border = 1 } return layout; }, print_std_add_table: function(t, layout, pf_list, dt, no_letterhead) { if(t.appendChild) { // If only one table is passed layout.cur_cell.appendChild(t); } else { page_break = '\n\
'; // If a list of tables is passed for(var i = 0; i < t.length-1; i++) { // add to current page layout.cur_cell.appendChild(t[i]); layout.close_borders(); pf_list.push(page_break); // Create new page layout = _p.add_layout(dt, no_letterhead); pf_list.push(layout); layout.addrow(); layout.addcell(); var div = $a(layout.cur_cell, 'div'); div.innerHTML = 'Continued from previous page...'; div.style.padding = '4px'; } // Append last table layout.cur_cell.appendChild(t[t.length-1]); } return layout; }, print_std_add_field: function(dt, dn, f, layout) { var val = _f.get_value(dt, dn, f.fieldname); if(f.fieldtype!='Button') { if(val || in_list(['Float', 'Int', 'Currency'], f.fieldtype)) { // If value or a numeric type then proceed // Add field table row = _p.field_tab(layout.cur_cell); // Add label row.cells[0].innerHTML = f.label ? f.label : f.fieldname; $s(row.cells[1], val, f.fieldtype); // left align currency in normal display if(f.fieldtype == 'Currency') { $y(row.cells[1], { textAlign: 'left' }); } } } }, field_tab: function(layout_cell) { var tab = $a(layout_cell, 'table', '', {width:'100%'}); var row = tab.insertRow(0); _p.row = row; // Don't know this line's purpose row.insertCell(0); row.insertCell(1); row.cells[0].className = 'datalabelcell'; row.cells[1].className = 'datainputcell'; return row; } }); print_table = function(dt, dn, fieldname, tabletype, cols, head_labels, widths, condition, cssClass, modifier, hide_empty) { var me = this; $.extend(this, { flist: (function() { var f_list = []; var fl = wn.meta.docfield_list[tabletype]; if(fl) { for(var i=0; i