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.
 
 
 
 
 
 

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