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.
 
 
 
 
 
 

447 lines
13 KiB

  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. //
  23. // Form Input
  24. // ======================================================================================
  25. _f.ColumnBreak = function() {
  26. this.set_input = function() { };
  27. }
  28. _f.ColumnBreak.prototype.make_body = function() {
  29. this.cell = this.frm.layout.addcell(this.df.width);
  30. $y(this.cell.wrapper, {padding: '8px'});
  31. _f.cur_col_break_width = this.df.width;
  32. var fn = this.df.fieldname?this.df.fieldname:this.df.label;
  33. // header
  34. if(this.df&&this.df.label){
  35. this.label = $a(this.cell.wrapper, 'div', '', '', this.df.label);
  36. }
  37. }
  38. _f.ColumnBreak.prototype.refresh = function(layout) {
  39. //if(!this.cell)return; // no perm
  40. var hidden = 0;
  41. // we generate column breaks, but hide it based on perms/hidden value
  42. if((!this.perm[this.df.permlevel]) || (!this.perm[this.df.permlevel][READ]) ||
  43. this.df.hidden) {
  44. // do not display, as no permission
  45. hidden = 1;
  46. }
  47. // hidden
  48. if(this.set_hidden!=hidden) {
  49. if(hidden)
  50. this.cell.hide();
  51. else
  52. this.cell.show();
  53. this.set_hidden = hidden;
  54. }
  55. }
  56. // ======================================================================================
  57. _f.SectionBreak = function() {
  58. this.fields = [];
  59. this.set_input = function() { };
  60. this.make_row = function() {
  61. this.row = this.df.label ? this.frm.layout.addrow() : this.frm.layout.addsubrow();
  62. }
  63. }
  64. _f.SectionBreak.prototype.make_body = function() {
  65. var me = this;
  66. this.make_row();
  67. if(this.df.label) {
  68. if(!this.df.description)
  69. this.df.description = '';
  70. $(this.row.main_head).html(repl('<div class="form-section-head">\
  71. <h3 class="head">%(label)s</h3>\
  72. <div class="help small" \
  73. style="margin-top: 4px; margin-bottom: 8px;">%(description)s</div>\
  74. </div>', this.df));
  75. } else {
  76. // simple
  77. $(this.wrapper).html('<div class="form-section-head"></div>');
  78. }
  79. // collapse section
  80. this.section_collapse = function() {
  81. $(me.row.main_head).find('.head')
  82. .html('<i class="icon-chevron-right"></i> \
  83. <a href="#" onclick="return false;">Show "' + me.df.label + '"</a>');
  84. $(me.row.main_body).toggle(false);
  85. }
  86. // expand section
  87. this.section_expand = function(no_animation) {
  88. $(me.row.main_head).find('.head')
  89. .html('<h3><i class="icon-chevron-down" style="vertical-align: middle; margin-bottom: 2px"></i> '
  90. + me.df.label + '</h3>');
  91. if(no_animation)
  92. $(me.row.main_body).toggle(true);
  93. else
  94. $(me.row.main_body).slideDown();
  95. }
  96. }
  97. _f.SectionBreak.prototype.has_data = function() {
  98. // return true if
  99. // 1. any field in the section is mandatory & not set as default
  100. // 2. any field in the section has data that is not default
  101. // 3. if table, table has rows
  102. var me = this;
  103. for(var i in me.fields) {
  104. var f = me.fields[i];
  105. var v = f.get_value ? f.get_value() : null;
  106. // value that is not default
  107. defaultval = f.df['default'] || sys_defaults[f.fieldname] || user_defaults[f.fieldname];
  108. if(v && v != defaultval) {
  109. return true;
  110. }
  111. // unfilled mandatory field
  112. if(f.df.reqd && !v) {
  113. return true;
  114. }
  115. // filled table
  116. if(f.df.fieldtype=='Table') {
  117. if(f.grid.get_children().length || f.df.reqd) {
  118. return true;
  119. }
  120. }
  121. }
  122. return false;
  123. }
  124. _f.SectionBreak.prototype.refresh = function(from_form) {
  125. var hidden = 0;
  126. // we generate section breaks, but hide it based on perms/hidden value
  127. if((!this.perm[this.df.permlevel]) || (!this.perm[this.df.permlevel][READ]) || this.df.hidden) {
  128. // no display
  129. hidden = 1;
  130. }
  131. if(hidden) {
  132. if(this.row)this.row.hide();
  133. } else {
  134. if(this.row)this.row.show();
  135. }
  136. }
  137. // Image field definition
  138. // ======================================================================================
  139. _f.ImageField = function() { this.images = {}; }
  140. _f.ImageField.prototype = new Field();
  141. _f.ImageField.prototype.onmake = function() {
  142. this.no_img = $a(this.wrapper, 'div','no_img');
  143. this.no_img.innerHTML = "No Image";
  144. $dh(this.no_img);
  145. }
  146. _f.ImageField.prototype.get_image_src = function(doc) {
  147. if(doc.file_list) {
  148. file = doc.file_list.split(',');
  149. // if image
  150. extn = file[0].split('.');
  151. extn = extn[extn.length - 1].toLowerCase();
  152. var img_extn_list = ['gif', 'jpg', 'bmp', 'jpeg', 'jp2', 'cgm', 'ief', 'jpm', 'jpx', 'png', 'tiff', 'jpe', 'tif'];
  153. if(in_list(img_extn_list, extn)) {
  154. var src = wn.request.url + "?cmd=downloadfile&file_id="+file[1];
  155. }
  156. } else {
  157. var src = "";
  158. }
  159. return src;
  160. }
  161. _f.ImageField.prototype.onrefresh = function() {
  162. var me = this;
  163. if(!this.images[this.docname]) this.images[this.docname] = $a(this.wrapper, 'img');
  164. else $di(this.images[this.docname]);
  165. var img = this.images[this.docname]
  166. // hide all other
  167. for(var dn in this.images) if(dn!=this.docname)$dh(this.images[dn]);
  168. var doc = locals[this.frm.doctype][this.frm.docname];
  169. if(!this.df.options) var src = this.get_image_src(doc);
  170. else var src = wn.request.url + '?cmd=get_file&fname='+this.df.options+"&__account="+account_id + (__sid150 ? ("&sid150="+__sid150) : '');
  171. if(src) {
  172. $dh(this.no_img);
  173. if(img.getAttribute('src')!=src) img.setAttribute('src',src);
  174. canvas = this.wrapper;
  175. canvas.img = this.images[this.docname];
  176. canvas.style.overflow = "auto";
  177. $w(canvas, "100%");
  178. if(!this.col_break_width)this.col_break_width = '100%';
  179. var allow_width = cint(1000 * (cint(this.col_break_width)-10) / 100);
  180. if((!img.naturalWidth) || cint(img.naturalWidth)>allow_width)
  181. $w(img, allow_width + 'px');
  182. } else {
  183. $ds(this.no_img);
  184. }
  185. }
  186. _f.ImageField.prototype.set_disp = function (val) { }
  187. _f.ImageField.prototype.set = function (val) { }
  188. // Table
  189. // ======================================================================================
  190. _f.TableField = function() { };
  191. _f.TableField.prototype = new Field();
  192. _f.TableField.prototype.with_label = 0;
  193. _f.TableField.prototype.make_body = function() {
  194. if(this.perm[this.df.permlevel] && this.perm[this.df.permlevel][READ]) {
  195. this.grid = new _f.FormGrid(this);
  196. if(this.frm)this.frm.grids[this.frm.grids.length] = this;
  197. this.grid.make_buttons();
  198. // description
  199. if(this.df.description) {
  200. this.desc_area = $a(this.parent, 'div', 'help small',
  201. {marginBottom:'9px', marginTop:'0px'}, this.df.description)
  202. }
  203. }
  204. }
  205. _f.TableField.prototype.refresh = function() {
  206. if(!this.grid)return;
  207. // hide / show grid
  208. var st = this.get_status();
  209. if(!this.df['default'])
  210. this.df['default']='';
  211. this.grid.can_add_rows = false;
  212. this.grid.can_edit = false
  213. if(st=='Write') {
  214. if(cur_frm.editable && this.perm[this.df.permlevel] && this.perm[this.df.permlevel][WRITE]) {
  215. this.grid.can_edit = true;
  216. if(this.df['default'].toLowerCase()!='no toolbar')
  217. this.grid.can_add_rows = true;
  218. }
  219. // submitted or cancelled
  220. if(cur_frm.editable && cur_frm.doc.docstatus > 0) {
  221. if(this.df.allow_on_submit && cur_frm.doc.docstatus==1) {
  222. this.grid.can_edit = true;
  223. if(this.df['default'].toLowerCase()=='no toolbar') {
  224. this.grid.can_add_rows = false;
  225. } else {
  226. this.grid.can_add_rows = true;
  227. }
  228. } else {
  229. this.grid.can_add_rows = false;
  230. this.grid.can_edit = false;
  231. }
  232. }
  233. if(this.df['default'].toLowerCase()=='no add rows') {
  234. this.grid.can_add_rows = false;
  235. }
  236. }
  237. //if(this.old_status!=st) {
  238. if(st=='Write') {
  239. // nothing
  240. this.grid.show();
  241. } else if(st=='Read') {
  242. this.grid.show();
  243. } else {
  244. this.grid.hide();
  245. }
  246. // this.old_status = st; // save this if next time
  247. //}
  248. this.grid.refresh();
  249. }
  250. _f.TableField.prototype.set = function(v) { }; // nothing
  251. _f.TableField.prototype.set_input = function(v) { }; // nothing
  252. // ==============================================================
  253. _f.CodeField = function() { };
  254. _f.CodeField.prototype = new Field();
  255. _f.CodeField.prototype.make_input = function() {
  256. var me = this;
  257. this.label_span.innerHTML = this.df.label;
  258. if(this.df.fieldtype=='Text Editor') {
  259. this.input = $a(this.input_area, 'text_area', '', {fontSize:'12px'});
  260. this.myid = wn.dom.set_unique_id(this.input);
  261. // setup tiny mce
  262. $(me.input).tinymce({
  263. // Location of TinyMCE script
  264. script_url : 'js/lib/tiny_mce_33/tiny_mce.js',
  265. // General options
  266. theme : "advanced",
  267. plugins : "style,inlinepopups,table",
  268. extended_valid_elements: "div[id|dir|class|align|style]",
  269. // w/h
  270. width: '100%',
  271. height: '360px',
  272. // buttons
  273. theme_advanced_buttons1 : "bold,italic,underline,strikethrough,hr,|,justifyleft,justifycenter,justifyright,|,formatselect,fontselect,fontsizeselect",
  274. theme_advanced_buttons2 : "bullist,numlist,|,outdent,indent,|,undo,redo,|,link,unlink,code,|,forecolor,backcolor,|,tablecontrols",
  275. theme_advanced_buttons3 : "",
  276. theme_advanced_toolbar_location : "top",
  277. theme_advanced_toolbar_align : "left",
  278. content_css: "js/lib/tiny_mce_33/custom_content.css",
  279. oninit: function() { me.init_editor(); }
  280. });
  281. this.input.set_input = function(v) {
  282. if(me.editor) {
  283. me.editor.setContent(v);
  284. } else {
  285. $(me.input).val(v);
  286. }
  287. }
  288. this.input.onchange = function() {
  289. me.set(me.editor.getContent());
  290. me.run_trigger();
  291. }
  292. this.get_value = function() {
  293. return me.editor.getContent(); // tinyMCE
  294. }
  295. } else {
  296. // setup ace
  297. //this.input = $a(this.input_area, 'div', '', {position:'relative', width: '90%', height:'300px'});
  298. wn.require('js/lib/ace/ace.js');
  299. //wn.require('js/lib/ace/theme-twilight.js');
  300. $(this.input_area).css('border','1px solid #aaa');
  301. this.pre = $a(this.input_area, 'pre', '', {
  302. position:'relative', height: '400px', width:'100%'
  303. });
  304. this.input = {};
  305. this.myid = wn.dom.set_unique_id(this.pre);
  306. this.editor = ace.edit(this.myid);
  307. //this.editor.getSession().setUseWrapMode(true);
  308. //this.editor.setTheme("ace/theme/twilight");
  309. if(me.df.options=='Markdown' || me.df.options=='HTML') {
  310. wn.require('js/lib/ace/mode-html.js');
  311. var HTMLMode = require("ace/mode/html").Mode;
  312. me.editor.getSession().setMode(new HTMLMode());
  313. }
  314. else if(me.df.options=='Javascript') {
  315. wn.require('js/lib/ace/mode-javascript.js');
  316. var JavascriptMode = require("ace/mode/javascript").Mode;
  317. me.editor.getSession().setMode(new JavascriptMode());
  318. }
  319. else if(me.df.options=='Python') {
  320. wn.require('js/lib/ace/mode-python.js');
  321. var PythonMode = require("ace/mode/python").Mode;
  322. me.editor.getSession().setMode(new PythonMode());
  323. }
  324. this.input.set_input = function(v) {
  325. me.setting_value = true;
  326. me.editor.getSession().setValue(v);
  327. me.setting_value = false;
  328. }
  329. this.get_value = function() {
  330. return me.editor.getSession().getValue(); // tinyMCE
  331. }
  332. $(cur_frm.wrapper).bind('render_complete', function() {
  333. me.editor.resize();
  334. me.editor.getSession().on('change', function() {
  335. if(me.setting_value) return;
  336. var val = me.get_value();
  337. if(locals[cur_frm.doctype][cur_frm.docname][me.df.fieldname] != val) {
  338. me.set(me.get_value());
  339. me.run_trigger();
  340. }
  341. })
  342. });
  343. }
  344. }
  345. _f.CodeField.prototype.init_editor = function() {
  346. // attach onchange methods
  347. var me = this;
  348. this.editor = tinymce.get(this.myid);
  349. this.editor.onKeyUp.add(function(ed, e) {
  350. me.set(ed.getContent());
  351. });
  352. this.editor.onPaste.add(function(ed, e) {
  353. me.set(ed.getContent());
  354. });
  355. this.editor.onSetContent.add(function(ed, e) {
  356. me.set(ed.getContent());
  357. });
  358. // reset content
  359. var c = locals[cur_frm.doctype][cur_frm.docname][this.df.fieldname];
  360. if(cur_frm && c) {
  361. this.editor.setContent(c);
  362. }
  363. }
  364. _f.CodeField.prototype.set_disp = function(val) {
  365. $y(this.disp_area, {width:'90%'})
  366. if(this.df.fieldtype=='Text Editor') {
  367. this.disp_area.innerHTML = val;
  368. } else {
  369. this.disp_area.innerHTML = '<textarea class="code_text" readonly=1>'+val+'</textarea>';
  370. }
  371. }
  372. // ======================================================================================