// 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. // /* Form page structure + this.parent (either FormContainer or Dialog) + this.wrapper + this.content + wn.PageLayout (this.page_layout) + this.wrapper + this.wtab (table) + this.main + this.head + this.body + this.layout + this.footer + this.sidebar + this.print_wrapper + this.head */ wn.provide('_f'); wn.provide('wn.ui.form'); wn.ui.form.Controller = Class.extend({ init: function(opts) { $.extend(this, opts); } }); _f.frms = {}; _f.Frm = function(doctype, parent, in_form) { this.docname = ''; this.doctype = doctype; this.display = 0; this.refresh_if_stale_for = 600; var me = this; this.is_editable = {}; this.opendocs = {}; this.sections = []; this.grids = []; this.cscript = new wn.ui.form.Controller({frm:this}); this.pformat = {}; this.fetch_dict = {}; this.parent = parent; this.tinymce_id_list = []; this.setup_meta(doctype); // show in form instead of in dialog, when called using url (router.js) this.in_form = in_form ? true : false; // notify on rename var me = this; $(document).bind('rename', function(event, dt, old_name, new_name) { if(dt==me.doctype) me.rename_notify(dt, old_name, new_name) }); } // ====================================================================================== _f.Frm.prototype.check_doctype_conflict = function(docname) { var me = this; if(this.doctype=='DocType' && docname=='DocType') { msgprint('Allowing DocType, DocType. Be careful!') } else if(this.doctype=='DocType') { if (wn.views.formview[docname] || wn.pages['List/'+docname]) { msgprint("Cannot open DocType when its instance is open") throw 'doctype open conflict' } } else { if (wn.views.formview.DocType && wn.views.formview.DocType.frm.opendocs[this.doctype]) { msgprint("Cannot open instance when its DocType is open") throw 'doctype open conflict' } } } _f.Frm.prototype.setup = function() { var me = this; this.fields = []; this.fields_dict = {}; // wrapper this.wrapper = this.parent; // create area for print fomrat this.setup_print_layout(); // 2 column layout this.setup_std_layout(); // client script must be called after "setup" - there are no fields_dict attached to the frm otherwise this.setup_client_script(); this.setup_done = true; } // ====================================================================================== _f.Frm.prototype.setup_print_layout = function() { var me = this; this.print_wrapper = $a(this.wrapper, 'div'); wn.ui.make_app_page({ parent: this.print_wrapper, single_column: true, set_document_title: false, title: me.doctype + ": Print View", module: me.meta.module }); var appframe = this.print_wrapper.appframe; appframe.add_button("View Details", function() { me.edit_doc(); }).addClass("btn-success"); appframe.add_button("Print", function() { me.print_doc(); }, 'icon-print'); this.$print_view_select = appframe.add_select("Select Preview", this.print_formats) .css({"float":"right"}) .val(this.print_formats[0]) .change(function() { me.refresh_print_layout(); }) appframe.add_ripped_paper_effect(this.print_wrapper); var layout_main = $(this.print_wrapper).find(".layout-main"); this.print_body = $("
").appendTo(layout_main) .css("min-height", "400px").get(0); } _f.Frm.prototype.onhide = function() { if(_f.cur_grid_cell) _f.cur_grid_cell.grid.cell_deselect(); } // ====================================================================================== _f.Frm.prototype.setup_std_layout = function() { this.page_layout = new wn.PageLayout({ parent: this.wrapper, main_width: (this.meta.in_dialog && !this.in_form) ? '100%' : '75%', sidebar_width: (this.meta.in_dialog && !this.in_form) ? '0%' : '25%' }) // only tray this.meta.section_style='Simple'; // always simple! // layout this.layout = new Layout(this.page_layout.body, '100%'); // sidebar if(this.meta.in_dialog && !this.in_form) { // hide sidebar $(this.page_layout.wrapper).removeClass('layout-wrapper-background'); $(this.page_layout.main).removeClass('layout-main-section'); $(this.page_layout.sidebar_area).toggle(false); } else { // module link this.setup_sidebar(); } // watermark $('
' + this.doctype + '
') .prependTo(this.page_layout.main); // footer this.setup_footer(); // header - no headers for tables and guests if(!(this.meta.istable || (this.meta.in_dialog && !this.in_form))) this.frm_head = new _f.FrmHeader(this.page_layout.head, this); // create fields this.setup_fields_std(); } _f.Frm.prototype.setup_print = function() { this.print_formats = wn.meta.get_print_formats(this.meta.name); this.print_sel = $a(null, 'select', '', {width:'160px'}); add_sel_options(this.print_sel, this.print_formats); this.print_sel.value = this.print_formats[0]; } _f.Frm.prototype.print_doc = function() { if(this.doc.docstatus==2) { msgprint("Cannot Print Cancelled Documents."); return; } _p.show_dialog(); // multiple options } // email the form _f.Frm.prototype.email_doc = function(message) { new wn.views.CommunicationComposer({ doc: this.doc, subject: wn._(this.meta.name) + ': ' + this.docname, recipients: this.doc.email || this.doc.email_id || this.doc.contact_email, attach_document_print: true, message: message, real_name: this.doc.real_name || this.doc.contact_display || this.doc.contact_name }); } // email the form _f.Frm.prototype.rename_doc = function() { wn.model.rename_doc(this.doctype, this.docname); } // notify this form of renamed records _f.Frm.prototype.rename_notify = function(dt, old, name) { // from form if(this.meta.istable) return; if(this.docname == old) this.docname = name; else return; // editable this.is_editable[name] = this.is_editable[old]; delete this.is_editable[old]; // cleanup if(this && this.opendocs[old]) { // delete docfield copy wn.meta.docfield_copy[dt][name] = wn.meta.docfield_copy[dt][old]; delete wn.meta.docfield_copy[dt][old]; } delete this.opendocs[old]; this.opendocs[name] = true; if(this.meta.in_dialog || !this.in_form) { return; } wn.re_route[window.location.hash] = '#Form/' + encodeURIComponent(this.doctype) + '/' + encodeURIComponent(name); wn.set_route('Form', this.doctype, name); } // SETUP _f.Frm.prototype.setup_meta = function(doctype) { this.meta = wn.model.get_doc('DocType',this.doctype); this.perm = wn.perm.get_perm(this.doctype); // for create if(this.meta.istable) { this.meta.in_dialog = 1 } this.setup_print(); } _f.Frm.prototype.setup_sidebar = function() { this.sidebar = new wn.widgets.form.sidebar.Sidebar(this); } _f.Frm.prototype.setup_footer = function() { var me = this; // footer toolbar var f = this.page_layout.footer; // save buttom f.save_area = $a(this.page_layout.footer,'div','',{display:'none', marginTop:'11px'}); f.help_area = $a(this.page_layout.footer,'div'); var b = $("") .click(function() { me.save("Save", null, me); }).appendTo(f.save_area); // show / hide save f.show_save = function() { $ds(me.page_layout.footer.save_area); } f.hide_save = function() { $dh(me.page_layout.footer.save_area); } } _f.Frm.prototype.set_intro = function(txt) { if(!this.intro_area) { this.intro_area = $('
') .insertBefore(this.page_layout.body.firstChild); } if(txt) { if(txt.search(/

/)==-1) txt = '

' + txt + '

'; this.intro_area.html(txt); } else { this.intro_area.remove(); this.intro_area = null; } } _f.Frm.prototype.set_footnote = function(txt) { if(!this.footnote_area) { this.footnote_area = $('
') .insertAfter(this.page_layout.body.lastChild); } if(txt) { if(txt.search(/

/)==-1) txt = '

' + txt + '

'; this.footnote_area.html(txt); } else { this.footnote_area.remove(); this.footnote_area = null; } } _f.Frm.prototype.setup_fields_std = function() { var fl = wn.meta.docfield_list[this.doctype]; fl.sort(function(a,b) { return a.idx - b.idx}); if(fl[0]&&fl[0].fieldtype!="Section Break" || get_url_arg('embed')) { this.layout.addrow(); // default section break if(fl[0].fieldtype!="Column Break") {// without column too var c = this.layout.addcell(); $y(c.wrapper, {padding: '8px'}); } } var sec; for(var i=0;i this.refresh_if_stale_for) { this.reload_doc(); return; } } // do setup if(!this.setup_done) this.setup(); // set customized permissions for this record this.runclientscript('set_perm',this.doctype, this.docname); // load the record for the first time, if not loaded (call 'onload') cur_frm.cscript.is_onload = false; if(!this.opendocs[this.docname]) { cur_frm.cscript.is_onload = true; this.setnewdoc(this.docname); } // editable if(this.doc.__islocal) this.is_editable[this.docname] = 1; // new is editable this.editable = this.is_editable[this.docname]; if(this.editable || (!this.editable && this.meta.istable)) { // show form layout (with fields etc) // ---------------------------------- if(this.print_wrapper) { $dh(this.print_wrapper); $ds(this.page_layout.wrapper); } // header if(!this.meta.istable) { this.refresh_header(); this.sidebar && this.sidebar.refresh(); } // call trigger this.runclientscript('refresh'); // trigger global trigger // to use this $(document).trigger('form_refresh'); // fields this.refresh_fields(); // dependent fields this.refresh_dependency(); // footer this.refresh_footer(); // layout if(this.layout) this.layout.show(); // call onload post render for callbacks to be fired if(this.cscript.is_onload) { this.runclientscript('onload_post_render', this.doctype, this.docname); } // focus on first input if(this.doc.docstatus==0) { $(this.wrapper).find('.form-layout-row :input:first').focus(); } } else { // show print layout // ---------------------------------- this.refresh_header(); if(this.print_wrapper) { this.refresh_print_layout(); } this.runclientscript('edit_status_changed'); } $(cur_frm.wrapper).trigger('render_complete'); } } _f.Frm.prototype.refresh_footer = function() { var f = this.page_layout.footer; if(f.save_area) { if(this.editable && (!this.meta.in_dialog || this.in_form) && this.doc.docstatus==0 && !this.meta.istable && this.perm[0][WRITE] && (this.fields && this.fields.length > 7) && !this.save_disabled) { f.show_save(); } else { f.hide_save(); } } } _f.Frm.prototype.refresh_field = function(fname) { cur_frm.fields_dict[fname] && cur_frm.fields_dict[fname].refresh && cur_frm.fields_dict[fname].refresh(); } _f.Frm.prototype.refresh_fields = function() { // refresh fields for(var i=0; i=0;i--) { var f = me.fields[i]; f.guardian_has_value = true; if(f.df.depends_on) { // evaluate guardian var v = doc[f.df.depends_on]; if(f.df.depends_on.substr(0,5)=='eval:') { f.guardian_has_value = eval(f.df.depends_on.substr(5)); } else if(f.df.depends_on.substr(0,3)=='fn:') { f.guardian_has_value = me.runclientscript(f.df.depends_on.substr(3), me.doctype, me.docname); } else { if(!v) { f.guardian_has_value = false; } } // show / hide if(f.guardian_has_value) { f.df.hidden = 0; f.refresh(); } else { f.df.hidden = 1; f.refresh(); } } } } // setnewdoc is called when a record is loaded for the first time // ====================================================================================== _f.Frm.prototype.setnewdoc = function(docname) { // moved this call to refresh function // this.check_doctype_conflict(docname); // if loaded if(this.opendocs[docname]) { // already exists this.docname=docname; return; } // make a copy of the doctype for client script settings // each record will have its own client script wn.meta.make_docfield_copy_for(this.doctype,docname); this.docname = docname; var me = this; var viewname = this.meta.issingle ? this.doctype : docname; // Client Script this.runclientscript('onload', this.doctype, this.docname); this.is_editable[docname] = 1; if(cint(this.meta.read_only_onload)) this.is_editable[docname] = 0; this.opendocs[docname] = true; } _f.Frm.prototype.edit_doc = function() { // set fields this.is_editable[this.docname] = true; this.refresh(); } _f.Frm.prototype.show_doc = function(dn) { this.refresh(dn); } _f.Frm.prototype.runscript = function(scriptname, callingfield, onrefresh) { var me = this; if(this.docname) { // make doc list var doclist = wn.model.compress(make_doclist(this.doctype, this.docname)); // send to run if(callingfield) $(callingfield.input).set_working(); $c('runserverobj', {'docs':doclist, 'method':scriptname }, function(r, rtxt) { // run refresh if(onrefresh) onrefresh(r,rtxt); // fields me.refresh_fields(); // dependent fields me.refresh_dependency(); // enable button if(callingfield) $(callingfield.input).done_working(); } ); } } _f.Frm.prototype.runclientscript = function(caller, cdt, cdn) { if(!cdt)cdt = this.doctype; if(!cdn)cdn = this.docname; var ret = null; var doc = locals[cur_frm.doc.doctype][cur_frm.doc.name]; try { if(this.cscript[caller]) ret = this.cscript[caller](doc, cdt, cdn); if(this.cscript['custom_'+caller]) ret += this.cscript['custom_'+caller](doc, cdt, cdn); } catch(e) { validated = false; console.log(e); } if(caller && caller.toLowerCase()=='setup') { var doctype = wn.model.get_doc('DocType', this.doctype); // js var cs = doctype.__js || (doctype.client_script_core + doctype.client_script); if(cs) { try { var tmp = eval(cs); } catch(e) { console.log(e); } } // css if(doctype.__css) set_style(doctype.__css) // ---Client String---- if(doctype.client_string) { // split client string this.cstring = {}; var elist = doctype.client_string.split('---'); for(var i=1;i