No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

hace 13 años
hace 13 años
hace 12 años
hace 13 años
hace 13 años
hace 13 años
hace 13 años
hace 13 años
hace 13 años
hace 13 años
hace 13 años
hace 13 años
hace 13 años
hace 12 años
hace 13 años
hace 13 años
hace 12 años
hace 12 años
hace 13 años
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834
  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. /* Form page structure
  23. + this.parent (either FormContainer or Dialog)
  24. + this.wrapper
  25. + this.toolbar
  26. + this.form_wrapper
  27. + this.main
  28. + this.head
  29. + this.body
  30. + this.layout
  31. + this.sidebar
  32. + this.print_wrapper
  33. + this.head
  34. + this.footer
  35. */
  36. wn.provide('_f');
  37. wn.provide('wn.ui.form');
  38. wn.ui.form.Controller = Class.extend({
  39. init: function(opts) {
  40. $.extend(this, opts);
  41. this.setup && this.setup();
  42. }
  43. });
  44. _f.frms = {};
  45. _f.Frm = function(doctype, parent, in_form) {
  46. this.docname = '';
  47. this.doctype = doctype;
  48. this.display = 0;
  49. this.refresh_if_stale_for = 120;
  50. var me = this;
  51. this.last_view_is_edit = {};
  52. this.opendocs = {};
  53. this.sections = [];
  54. this.grids = [];
  55. this.cscript = new wn.ui.form.Controller({frm:this});
  56. this.pformat = {};
  57. this.fetch_dict = {};
  58. this.parent = parent;
  59. this.tinymce_id_list = [];
  60. this.setup_meta(doctype);
  61. // show in form instead of in dialog, when called using url (router.js)
  62. this.in_form = in_form ? true : false;
  63. // notify on rename
  64. var me = this;
  65. $(document).bind('rename', function(event, dt, old_name, new_name) {
  66. if(dt==me.doctype)
  67. me.rename_notify(dt, old_name, new_name)
  68. });
  69. }
  70. _f.Frm.prototype.check_doctype_conflict = function(docname) {
  71. var me = this;
  72. if(this.doctype=='DocType' && docname=='DocType') {
  73. msgprint('Allowing DocType, DocType. Be careful!')
  74. } else if(this.doctype=='DocType') {
  75. if (wn.views.formview[docname] || wn.pages['List/'+docname]) {
  76. msgprint("Cannot open DocType when its instance is open")
  77. throw 'doctype open conflict'
  78. }
  79. } else {
  80. if (wn.views.formview.DocType && wn.views.formview.DocType.frm.opendocs[this.doctype]) {
  81. msgprint("Cannot open instance when its DocType is open")
  82. throw 'doctype open conflict'
  83. }
  84. }
  85. }
  86. _f.Frm.prototype.setup = function() {
  87. var me = this;
  88. this.fields = [];
  89. this.fields_dict = {};
  90. this.state_fieldname = wn.workflow.get_state_fieldname(this.doctype);
  91. // wrapper
  92. this.wrapper = this.parent;
  93. wn.ui.make_app_page({
  94. parent: this.wrapper,
  95. single_column: true
  96. });
  97. this.appframe = this.wrapper.appframe;
  98. this.layout_main = $(this.wrapper).find(".layout-main").get(0);
  99. this.toolbar = new wn.ui.form.Toolbar({
  100. frm: this,
  101. appframe: this.appframe
  102. });
  103. this.frm_head = this.toolbar;
  104. // create area for print fomrat
  105. this.setup_print_layout();
  106. // 2 column layout
  107. this.setup_std_layout();
  108. // client script must be called after "setup" - there are no fields_dict attached to the frm otherwise
  109. this.script_manager = new wn.ui.form.ScriptManager({
  110. frm: this
  111. })
  112. this.watch_model_updates();
  113. this.footer = new wn.ui.form.Footer({
  114. frm: this,
  115. parent: this.layout_main
  116. })
  117. this.setup_done = true;
  118. }
  119. _f.Frm.prototype.watch_model_updates = function() {
  120. // watch model updates
  121. var me = this;
  122. // on main doc
  123. wn.model.on(me.doctype, "*", function(fieldname, value, doc) {
  124. // set input
  125. if(doc.name===me.docname) {
  126. me.fields_dict[fieldname]
  127. && me.fields_dict[fieldname].set_input(value);
  128. me.script_manager.trigger(fieldname, doc.doctype, doc.name);
  129. }
  130. })
  131. // on table fields
  132. $.each(wn.model.get("DocField", {fieldtype:"Table", parent: me.doctype}), function(i, df) {
  133. wn.model.on(df.options, "*", function(fieldname, value, doc) {
  134. if(doc.parent===me.docname) {
  135. me.fields_dict[df.fieldname].grid.set_value(fieldname, value, doc);
  136. me.script_manager.trigger(fieldname, doc.doctype, doc.name);
  137. }
  138. })
  139. })
  140. }
  141. _f.Frm.prototype.setup_print_layout = function() {
  142. var me = this;
  143. this.print_wrapper = $('<div>\
  144. <div class="print-format-area clear-fix" style="min-height: 400px;"></div>\
  145. </div>').appendTo(this.layout_main).get(0);
  146. //appframe.add_ripped_paper_effect(this.print_wrapper);
  147. this.print_body = $(this.print_wrapper).find(".print-format-area").get(0);
  148. }
  149. _f.Frm.prototype.onhide = function() {
  150. if(_f.cur_grid_cell) _f.cur_grid_cell.grid.cell_deselect();
  151. }
  152. _f.Frm.prototype.setup_std_layout = function() {
  153. this.form_wrapper = $('<div></div>').appendTo(this.layout_main).get(0);
  154. $parent = $(this.form_wrapper);
  155. this.head = $parent.find(".layout-appframe").get(0);
  156. this.main = this.form_wrapper;
  157. this.body_header = $a(this.main, 'div');
  158. this.body = $a(this.main, 'div');
  159. if(this.heading) {
  160. this.page_head = new PageHeader(this.head, this);
  161. }
  162. // only tray
  163. this.meta.section_style='Simple'; // always simple!
  164. // layout
  165. this.layout = new wn.ui.form.Layout({
  166. parent: this.body,
  167. doctype: this.doctype,
  168. frm: this,
  169. })
  170. // state
  171. this.states = new wn.ui.form.States({
  172. frm: this
  173. });
  174. }
  175. _f.Frm.prototype.setup_print = function() {
  176. this.print_formats = wn.meta.get_print_formats(this.meta.name);
  177. this.print_sel = $a(null, 'select', '', {width:'160px'});
  178. add_sel_options(this.print_sel, this.print_formats);
  179. this.print_sel.value = this.print_formats[0];
  180. }
  181. _f.Frm.prototype.print_doc = function() {
  182. if(this.doc.docstatus==2) {
  183. msgprint("Cannot Print Cancelled Documents.");
  184. return;
  185. }
  186. _p.show_dialog(); // multiple options
  187. }
  188. // email the form
  189. _f.Frm.prototype.email_doc = function(message) {
  190. new wn.views.CommunicationComposer({
  191. doc: this.doc,
  192. subject: wn._(this.meta.name) + ': ' + this.docname,
  193. recipients: this.doc.email || this.doc.email_id || this.doc.contact_email,
  194. attach_document_print: true,
  195. message: message,
  196. real_name: this.doc.real_name || this.doc.contact_display || this.doc.contact_name
  197. });
  198. }
  199. // email the form
  200. _f.Frm.prototype.rename_doc = function() {
  201. wn.model.rename_doc(this.doctype, this.docname);
  202. }
  203. // notify this form of renamed records
  204. _f.Frm.prototype.rename_notify = function(dt, old, name) {
  205. // from form
  206. if(this.meta.istable)
  207. return;
  208. if(this.docname == old)
  209. this.docname = name;
  210. else
  211. return;
  212. // view_is_edit
  213. this.last_view_is_edit[name] = this.last_view_is_edit[old];
  214. delete this.last_view_is_edit[old];
  215. // cleanup
  216. if(this && this.opendocs[old]) {
  217. // delete docfield copy
  218. wn.meta.docfield_copy[dt][name] = wn.meta.docfield_copy[dt][old];
  219. delete wn.meta.docfield_copy[dt][old];
  220. }
  221. delete this.opendocs[old];
  222. this.opendocs[name] = true;
  223. if(this.meta.in_dialog || !this.in_form) {
  224. return;
  225. }
  226. wn.re_route[window.location.hash] = '#Form/' + encodeURIComponent(this.doctype) + '/' + encodeURIComponent(name);
  227. wn.set_route('Form', this.doctype, name);
  228. }
  229. // SETUP
  230. _f.Frm.prototype.setup_meta = function(doctype) {
  231. this.meta = wn.model.get_doc('DocType',this.doctype);
  232. this.perm = wn.perm.get_perm(this.doctype); // for create
  233. if(this.meta.istable) { this.meta.in_dialog = 1 }
  234. this.setup_print();
  235. }
  236. _f.Frm.prototype.set_intro = function(txt) {
  237. wn.utils.set_intro(this, this.body, txt);
  238. }
  239. _f.Frm.prototype.set_footnote = function(txt) {
  240. wn.utils.set_footnote(this, this.body, txt);
  241. }
  242. _f.Frm.prototype.add_custom_button = function(label, fn, icon) {
  243. this.appframe.add_button(label, fn, icon || "icon-arrow-right", true);
  244. }
  245. _f.Frm.prototype.clear_custom_buttons = function() {
  246. this.toolbar.refresh()
  247. }
  248. _f.Frm.prototype.add_fetch = function(link_field, src_field, tar_field) {
  249. if(!this.fetch_dict[link_field]) {
  250. this.fetch_dict[link_field] = {'columns':[], 'fields':[]}
  251. }
  252. this.fetch_dict[link_field].columns.push(src_field);
  253. this.fetch_dict[link_field].fields.push(tar_field);
  254. }
  255. _f.Frm.prototype.refresh_print_layout = function() {
  256. $ds(this.print_wrapper);
  257. $dh(this.form_wrapper);
  258. var me = this;
  259. var print_callback = function(print_html) {
  260. me.print_body.innerHTML = print_html;
  261. }
  262. // print head
  263. if(cur_frm.doc.select_print_heading)
  264. cur_frm.set_print_heading(cur_frm.doc.select_print_heading)
  265. if(user!='Guest') {
  266. $di(this.view_btn_wrapper);
  267. // archive
  268. if(cur_frm.doc.__archived) {
  269. $dh(this.view_btn_wrapper);
  270. }
  271. } else {
  272. $dh(this.view_btn_wrapper);
  273. $dh(this.print_close_btn);
  274. }
  275. // create print format here
  276. _p.build(this.$print_view_select.val(), print_callback, false, true, true);
  277. }
  278. _f.Frm.prototype.show_the_frm = function() {
  279. // show the dialog
  280. if(this.meta.in_dialog && !this.parent.dialog.display) {
  281. if(!this.meta.istable)
  282. this.parent.table_form = false;
  283. this.parent.dialog.show();
  284. }
  285. }
  286. _f.Frm.prototype.set_print_heading = function(txt) {
  287. this.pformat[cur_frm.docname] = txt;
  288. }
  289. _f.Frm.prototype.defocus_rest = function() {
  290. // deselect others
  291. if(_f.cur_grid_cell) _f.cur_grid_cell.grid.cell_deselect();
  292. }
  293. _f.Frm.prototype.refresh_header = function() {
  294. // set title
  295. // main title
  296. if(!this.meta.in_dialog || this.in_form) {
  297. set_title(this.meta.issingle ? this.doctype : this.docname);
  298. }
  299. if(wn.ui.toolbar.recent)
  300. wn.ui.toolbar.recent.add(this.doctype, this.docname, 1);
  301. // show / hide buttons
  302. if(this.frm_head) {
  303. this.frm_head.refresh();
  304. }
  305. }
  306. _f.Frm.prototype.check_doc_perm = function() {
  307. // get perm
  308. var dt = this.parent_doctype?this.parent_doctype : this.doctype;
  309. var dn = this.parent_docname?this.parent_docname : this.docname;
  310. this.perm = wn.perm.get_perm(dt, dn);
  311. if(!this.perm[0][READ]) {
  312. wn.set_route("403");
  313. return 0;
  314. }
  315. return 1
  316. }
  317. _f.Frm.prototype.refresh = function(docname) {
  318. // record switch
  319. if(docname) {
  320. if(this.docname != docname && (!this.meta.in_dialog || this.in_form) &&
  321. !this.meta.istable)
  322. scroll(0, 0);
  323. this.docname = docname;
  324. }
  325. if(!this.meta.istable) {
  326. cur_frm = this;
  327. this.parent.cur_frm = this;
  328. }
  329. if(this.docname) { // document to show
  330. // check permissions
  331. if(!this.check_doc_perm()) return;
  332. // read only (workflow)
  333. this.read_only = wn.workflow.is_read_only(this.doctype, this.docname);
  334. // set the doc
  335. this.doc = wn.model.get_doc(this.doctype, this.docname);
  336. // check if doctype is already open
  337. if (!this.opendocs[this.docname]) {
  338. this.check_doctype_conflict(this.docname);
  339. } else {
  340. if(this.doc && this.doc.__last_sync_on &&
  341. (new Date() - this.doc.__last_sync_on) > (this.refresh_if_stale_for * 1000)) {
  342. this.reload_doc();
  343. return;
  344. }
  345. }
  346. // do setup
  347. if(!this.setup_done) this.setup();
  348. // load the record for the first time, if not loaded (call 'onload')
  349. cur_frm.cscript.is_onload = false;
  350. if(!this.opendocs[this.docname]) {
  351. cur_frm.cscript.is_onload = true;
  352. this.setnewdoc(this.docname);
  353. }
  354. // view_is_edit
  355. if(this.doc.__islocal)
  356. this.last_view_is_edit[this.docname] = 1; // new is view_is_edit
  357. this.view_is_edit = this.last_view_is_edit[this.docname];
  358. if(this.view_is_edit || (!this.view_is_edit && this.meta.istable)) {
  359. if(this.print_wrapper) {
  360. $dh(this.print_wrapper);
  361. $ds(this.form_wrapper);
  362. }
  363. // header
  364. if(!this.meta.istable) {
  365. this.refresh_header();
  366. }
  367. // call trigger
  368. this.script_manager.trigger("refresh");
  369. // trigger global trigger
  370. // to use this
  371. $(document).trigger('form_refresh');
  372. // fields
  373. this.refresh_fields();
  374. // dependent fields
  375. this.refresh_dependency();
  376. // call onload post render for callbacks to be fired
  377. if(this.cscript.is_onload) {
  378. this.script_manager.trigger("onload_post_render");
  379. }
  380. // focus on first input
  381. if(this.doc.docstatus==0) {
  382. var first = $(this.form_wrapper).find('.form-layout-row :input:first');
  383. if(!in_list(["Date", "Datetime"], first.attr("data-fieldtype"))) {
  384. first.focus();
  385. }
  386. }
  387. } else {
  388. this.refresh_header();
  389. if(this.print_wrapper) {
  390. this.refresh_print_layout();
  391. }
  392. }
  393. $(cur_frm.wrapper).trigger('render_complete');
  394. }
  395. }
  396. _f.Frm.prototype.refresh_field = function(fname) {
  397. cur_frm.fields_dict[fname] && cur_frm.fields_dict[fname].refresh
  398. && cur_frm.fields_dict[fname].refresh();
  399. }
  400. _f.Frm.prototype.refresh_fields = function() {
  401. this.layout.refresh();
  402. // cleanup activities after refresh
  403. this.cleanup_refresh(this);
  404. }
  405. _f.Frm.prototype.cleanup_refresh = function() {
  406. var me = this;
  407. if(me.fields_dict['amended_from']) {
  408. if (me.doc.amended_from) {
  409. unhide_field('amended_from');
  410. if (me.fields_dict['amendment_date']) unhide_field('amendment_date');
  411. } else {
  412. hide_field('amended_from');
  413. if (me.fields_dict['amendment_date']) hide_field('amendment_date');
  414. }
  415. }
  416. if(me.fields_dict['trash_reason']) {
  417. if(me.doc.trash_reason && me.doc.docstatus == 2) {
  418. unhide_field('trash_reason');
  419. } else {
  420. hide_field('trash_reason');
  421. }
  422. }
  423. if(me.meta.autoname && me.meta.autoname.substr(0,6)=='field:' && !me.doc.__islocal) {
  424. var fn = me.meta.autoname.substr(6);
  425. cur_frm.toggle_display(fn, false);
  426. }
  427. if(me.meta.autoname=="naming_series:" && !me.doc.__islocal) {
  428. cur_frm.toggle_display("naming_series", false);
  429. }
  430. }
  431. // Resolve "depends_on" and show / hide accordingly
  432. _f.Frm.prototype.refresh_dependency = function() {
  433. var me = this;
  434. var doc = locals[this.doctype][this.docname];
  435. // build dependants' dictionary
  436. var has_dep = false;
  437. for(fkey in me.fields) {
  438. var f = me.fields[fkey];
  439. f.dependencies_clear = true;
  440. if(f.df.depends_on) {
  441. has_dep = true;
  442. }
  443. }
  444. if(!has_dep)return;
  445. // show / hide based on values
  446. for(var i=me.fields.length-1;i>=0;i--) {
  447. var f = me.fields[i];
  448. f.guardian_has_value = true;
  449. if(f.df.depends_on) {
  450. // evaluate guardian
  451. var v = doc[f.df.depends_on];
  452. if(f.df.depends_on.substr(0,5)=='eval:') {
  453. f.guardian_has_value = eval(f.df.depends_on.substr(5));
  454. } else if(f.df.depends_on.substr(0,3)=='fn:') {
  455. f.guardian_has_value = me.script_manager.trigger(f.df.depends_on.substr(3), me.doctype, me.docname);
  456. } else {
  457. if(!v) {
  458. f.guardian_has_value = false;
  459. }
  460. }
  461. // show / hide
  462. if(f.guardian_has_value) {
  463. f.df.hidden = 0;
  464. f.refresh();
  465. } else {
  466. f.df.hidden = 1;
  467. f.refresh();
  468. }
  469. }
  470. }
  471. }
  472. // setnewdoc is called when a record is loaded for the first time
  473. // ======================================================================================
  474. _f.Frm.prototype.setnewdoc = function(docname) {
  475. // moved this call to refresh function
  476. // this.check_doctype_conflict(docname);
  477. // if loaded
  478. if(this.opendocs[docname]) { // already exists
  479. this.docname=docname;
  480. return;
  481. }
  482. // make a copy of the doctype for client script settings
  483. // each record will have its own client script
  484. wn.meta.make_docfield_copy_for(this.doctype,docname);
  485. this.docname = docname;
  486. var me = this;
  487. var viewname = this.meta.issingle ? this.doctype : docname;
  488. // Client Script
  489. this.script_manager.trigger("onload");
  490. this.last_view_is_edit[docname] = 1;
  491. if(cint(this.meta.read_only_onload)) this.last_view_is_edit[docname] = 0;
  492. this.opendocs[docname] = true;
  493. }
  494. _f.Frm.prototype.edit_doc = function() {
  495. // set fields
  496. this.last_view_is_edit[this.docname] = true;
  497. this.refresh();
  498. }
  499. _f.Frm.prototype.show_doc = function(dn) {
  500. this.refresh(dn);
  501. }
  502. _f.Frm.prototype.runscript = function(scriptname, callingfield, onrefresh) {
  503. var me = this;
  504. if(this.docname) {
  505. // make doc list
  506. var doclist = wn.model.compress(make_doclist(this.doctype, this.docname));
  507. // send to run
  508. if(callingfield)
  509. $(callingfield.input).set_working();
  510. $c('runserverobj', {'docs':doclist, 'method':scriptname },
  511. function(r, rtxt) {
  512. // run refresh
  513. if(onrefresh)
  514. onrefresh(r,rtxt);
  515. // fields
  516. me.refresh_fields();
  517. // dependent fields
  518. me.refresh_dependency();
  519. // enable button
  520. if(callingfield)
  521. $(callingfield.input).done_working();
  522. }
  523. );
  524. }
  525. }
  526. _f.Frm.prototype.copy_doc = function(onload, from_amend) {
  527. if(!this.perm[0][CREATE]) {
  528. msgprint('You are not allowed to create '+this.meta.name);
  529. return;
  530. }
  531. var dn = this.docname;
  532. // copy parent
  533. var newdoc = wn.model.copy_doc(this.doctype, dn, from_amend);
  534. // do not copy attachments
  535. if(this.meta.allow_attach && newdoc.file_list && !from_amend)
  536. newdoc.file_list = null;
  537. // copy chidren
  538. var dl = make_doclist(this.doctype, dn);
  539. // table fields dict - for no_copy check
  540. var tf_dict = {};
  541. for(var d in dl) {
  542. d1 = dl[d];
  543. // get tabel field
  544. if(d1.parentfield && !tf_dict[d1.parentfield]) {
  545. tf_dict[d1.parentfield] = wn.meta.get_docfield(d1.parenttype, d1.parentfield);
  546. }
  547. if(d1.parent==dn && cint(tf_dict[d1.parentfield].no_copy)!=1) {
  548. var ch = wn.model.copy_doc(d1.doctype, d1.name, from_amend);
  549. ch.parent = newdoc.name;
  550. ch.docstatus = 0;
  551. ch.owner = user;
  552. ch.creation = '';
  553. ch.modified_by = user;
  554. ch.modified = '';
  555. }
  556. }
  557. newdoc.__islocal = 1;
  558. newdoc.docstatus = 0;
  559. newdoc.owner = user;
  560. newdoc.creation = '';
  561. newdoc.modified_by = user;
  562. newdoc.modified = '';
  563. if(onload)onload(newdoc);
  564. loaddoc(newdoc.doctype, newdoc.name);
  565. }
  566. _f.Frm.prototype.reload_doc = function() {
  567. this.check_doctype_conflict(this.docname);
  568. var me = this;
  569. var onsave = function(r, rtxt) {
  570. me.refresh();
  571. }
  572. if(!me.doc.__islocal) {
  573. wn.model.remove_from_locals(me.doctype, me.docname);
  574. wn.model.with_doc(me.doctype, me.docname, function() {
  575. me.refresh();
  576. })
  577. }
  578. }
  579. var validated;
  580. _f.Frm.prototype.save = function(save_action, callback, btn, on_error) {
  581. $(document.activeElement).blur();
  582. var me = this;
  583. if((!this.meta.in_dialog || this.in_form) && !this.meta.istable)
  584. scroll(0, 0);
  585. // validate
  586. if(save_action!="Cancel") {
  587. validated = true;
  588. this.script_manager.trigger("validate");
  589. if(!validated) {
  590. if(on_error)
  591. on_error();
  592. return;
  593. }
  594. }
  595. var doclist = new wn.model.DocList(this.doctype, this.docname);
  596. doclist.save(save_action || "Save", function(r) {
  597. if(!r.exc) {
  598. me.refresh();
  599. } else {
  600. if(on_error)
  601. on_error();
  602. }
  603. callback && callback(r);
  604. }, btn);
  605. }
  606. _f.Frm.prototype.savesubmit = function(btn, on_error) {
  607. var me = this;
  608. wn.confirm("Permanently Submit "+this.docname+"?", function() {
  609. me.save('Submit', function(r) {
  610. if(!r.exc) {
  611. me.script_manager.trigger("on_submit");
  612. }
  613. }, btn, on_error);
  614. });
  615. }
  616. _f.Frm.prototype.savecancel = function(btn, on_error) {
  617. var me = this;
  618. wn.confirm("Permanently Cancel "+this.docname+"?", function() {
  619. validated = true;
  620. me.script_manager.trigger("before_cancel");
  621. if(!validated) {
  622. if(on_error)
  623. on_error();
  624. return;
  625. }
  626. var doclist = new wn.model.DocList(me.doctype, me.docname);
  627. doclist.cancel(function(r) {
  628. if(!r.exc) {
  629. me.refresh();
  630. me.script_manager.trigger("after_cancel");
  631. }
  632. }, btn, on_error);
  633. });
  634. }
  635. // delete the record
  636. _f.Frm.prototype.savetrash = function() {
  637. wn.model.delete_doc(this.doctype, this.docname, function(r) {
  638. window.history.back();
  639. })
  640. }
  641. _f.Frm.prototype.amend_doc = function() {
  642. if(!this.fields_dict['amended_from']) {
  643. alert('"amended_from" field must be present to do an amendment.');
  644. return;
  645. }
  646. var me = this;
  647. var fn = function(newdoc) {
  648. newdoc.amended_from = me.docname;
  649. if(me.fields_dict && me.fields_dict['amendment_date'])
  650. newdoc.amendment_date = dateutil.obj_to_str(new Date());
  651. }
  652. this.copy_doc(fn, 1);
  653. }
  654. _f.Frm.prototype.disable_save = function() {
  655. // IMPORTANT: this function should be called in refresh event
  656. cur_frm.save_disabled = true;
  657. cur_frm.footer.hide_save();
  658. cur_frm.appframe.buttons.Save.remove();
  659. delete cur_frm.appframe.buttons.Save
  660. }
  661. _f.get_value = function(dt, dn, fn) {
  662. if(locals[dt] && locals[dt][dn])
  663. return locals[dt][dn][fn];
  664. }
  665. _f.Frm.prototype.set_value_in_locals = function(dt, dn, fn, v) {
  666. var d = locals[dt][dn];
  667. if (!d) return;
  668. var changed = d[fn] != v;
  669. if(changed && (d[fn]==null || v==null) && (cstr(d[fn])==cstr(v)))
  670. changed = false;
  671. if(changed) {
  672. d[fn] = v;
  673. this.dirty();
  674. }
  675. }
  676. _f.Frm.prototype.dirty = function() {
  677. this.doc.__unsaved = 1;
  678. $(this.wrapper).trigger('dirty')
  679. }