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.

layout.js 6.7 KiB

12 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. // Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
  2. // MIT License. See license.txt
  3. wn.provide("wn.ui.form");
  4. wn.ui.form.Layout = Class.extend({
  5. init: function(opts) {
  6. this.views = {};
  7. this.sections = [];
  8. this.fields_list = [];
  9. this.fields_dict = {};
  10. this.labelled_section_count = 0;
  11. this.ignore_types = ["Section Break", "Column Break"];
  12. $.extend(this, opts);
  13. },
  14. make: function() {
  15. if(!this.parent && this.body)
  16. this.parent = this.body;
  17. this.wrapper = $('<div class="form-layout">').appendTo(this.parent);
  18. if(!this.fields)
  19. this.fields = wn.meta.sort_docfields(wn.meta.docfield_map[this.doctype]);
  20. this.setup_tabbing();
  21. this.render();
  22. },
  23. add_view: function(label) {
  24. var view = $('<div class="form-add-view">').appendTo(this.parent).toggle(false);
  25. this.views[label] = view;
  26. },
  27. set_view: function(label) {
  28. if(this.cur_view) this.cur_view.toggle(false);
  29. if(label) {
  30. this.wrapper.toggle(false);
  31. if(!this.views[label])
  32. this.add_view(label);
  33. this.cur_view = this.views[label].toggle(true);
  34. } else {
  35. this.wrapper.toggle(true);
  36. }
  37. },
  38. refresh: function(doc) {
  39. var me = this;
  40. if(doc) this.doc = doc;
  41. $.each(this.fields_list, function(i, fieldobj) {
  42. if(me.doc) {
  43. fieldobj.doctype = me.doc.doctype;
  44. fieldobj.docname = me.doc.name;
  45. fieldobj.df = wn.meta.get_docfield(me.doc.doctype,
  46. fieldobj.df.fieldname, me.doc.name);
  47. // on form change, permissions can change
  48. fieldobj.perm = me.frm.perm;
  49. };
  50. fieldobj.refresh && fieldobj.refresh();
  51. });
  52. if(this.frm)
  53. $(this.frm.wrapper).trigger("refresh-fields");
  54. },
  55. render: function() {
  56. var me = this;
  57. this.section = null;
  58. this.column = null;
  59. if(this.fields[0] && this.fields[0].fieldtype!="Section Break") {
  60. this.make_section();
  61. }
  62. $.each(this.fields, function(i, df) {
  63. switch(df.fieldtype) {
  64. case "Section Break":
  65. me.make_section(df);
  66. break;
  67. case "Column Break":
  68. me.make_column(df);
  69. break;
  70. default:
  71. me.make_field(df);
  72. }
  73. });
  74. },
  75. make_column: function(df) {
  76. this.column = $('<div class="form-column">\
  77. <form>\
  78. </form>\
  79. </div>').appendTo(this.section.body)
  80. .find("form")
  81. .on("submit", function() { return false; })
  82. // distribute all columns equally
  83. var colspan = cint(12 / this.section.find(".form-column").length);
  84. this.section.find(".form-column").removeClass()
  85. .addClass("form-column")
  86. .addClass("col-md-" + colspan);
  87. },
  88. make_field: function(df, colspan) {
  89. !this.column && this.make_column();
  90. var fieldobj = make_field(df, this.doctype, this.column.get(0), this.frm);
  91. fieldobj.layout = this;
  92. this.fields_list.push(fieldobj);
  93. this.fields_dict[df.fieldname] = fieldobj;
  94. if(this.frm) {
  95. fieldobj.perm = this.frm.perm;
  96. }
  97. },
  98. make_section: function(df) {
  99. if(this.section) {
  100. //$("<hr>").appendTo(this.wrapper);
  101. }
  102. this.section = $('<div class="row">')
  103. .appendTo(this.wrapper);
  104. this.sections.push(this.section);
  105. var section = this.section[0];
  106. section.df = df;
  107. if(df) {
  108. if(df.label) {
  109. this.labelled_section_count++;
  110. var head = $('<h4 class="col-md-12">'
  111. + (df.options ? (' <i class="icon-in-circle '+df.options+'"></i> ') : "")
  112. + '<span class="section-count-label">' + this.labelled_section_count + "</span>. "
  113. + wn._(df.label)
  114. + "</h4>")
  115. .appendTo(this.section);
  116. if(df && df.idx===1)
  117. head.css({"margin-top": "0px"})
  118. if(this.sections.length > 1)
  119. this.section.css({
  120. "margin-top": "15px",
  121. "border-top": "1px solid #c7c7c7"
  122. });
  123. }
  124. if(df.description) {
  125. $('<div class="col-md-12 small text-muted">' + df.description + '</div>')
  126. .css("padding-left", "40px")
  127. .appendTo(this.section);
  128. }
  129. if(df.label || df.description) {
  130. // spacer
  131. $('<div class="col-md-12"></div>')
  132. .appendTo(this.section)
  133. .css({"height": "10px"});
  134. }
  135. this.fields_dict[df.fieldname] = section;
  136. this.fields_list.push(section);
  137. }
  138. // for bc
  139. this.section.body = $('<div>').appendTo(this.section);
  140. // if(this.frm)
  141. // this.section.body.css({"padding":"0px 3%"})
  142. section.row = {
  143. wrapper: section
  144. };
  145. section.refresh = function() {
  146. if(!this.df) return;
  147. $(this).toggle(this.df.hidden || this.df.hidden_due_to_dependency
  148. ? false : (cur_frm ? !!cur_frm.get_perm(this.df.permlevel, "read") : true))
  149. }
  150. this.column = null;
  151. section.refresh.call(section);
  152. return this.section;
  153. },
  154. refresh_section_count: function() {
  155. this.wrapper.find(".section-count-label:visible").each(function(i) {
  156. $(this).html(i+1);
  157. });
  158. },
  159. setup_tabbing: function() {
  160. var me = this;
  161. this.wrapper.on("keydown", function(ev) {
  162. if(ev.which==9) {
  163. var current = $(ev.target),
  164. doctype = current.attr("data-doctype"),
  165. fieldname = current.attr("data-fieldname");
  166. if(doctype)
  167. return me.handle_tab(doctype, fieldname, ev.shiftKey);
  168. }
  169. })
  170. },
  171. handle_tab: function(doctype, fieldname, shift) {
  172. var me = this,
  173. grid_row = null;
  174. prev = null,
  175. fields = me.fields,
  176. in_grid = false;
  177. // in grid
  178. if(doctype != me.doctype) {
  179. grid_row =me.get_open_grid_row()
  180. fields = grid_row.fields;
  181. }
  182. for(var i=0, len=fields.length; i < len; i++) {
  183. if(fields[i].df.fieldname==fieldname) {
  184. if(shift) {
  185. if(prev) {
  186. this.set_focus(prev)
  187. } else {
  188. $(this.primary_button).focus();
  189. }
  190. break;
  191. }
  192. if(i==len-1) {
  193. // last field in this group
  194. if(grid_row) {
  195. // in grid
  196. if(grid_row.doc.idx==grid_row.grid.grid_rows.length) {
  197. // last row, close it and find next field
  198. grid_row.toggle_view(false, function() {
  199. me.handle_tab(grid_row.grid.df.parent, grid_row.grid.df.fieldname);
  200. })
  201. } else {
  202. // next row
  203. grid_row.grid.grid_rows[grid_row.doc.idx].toggle_view(true);
  204. }
  205. } else {
  206. $(this.primary_button).focus();
  207. }
  208. } else {
  209. me.focus_on_next_field(i, fields);
  210. }
  211. break;
  212. }
  213. if(fields[i].disp_status==="Write")
  214. prev = fields[i];
  215. }
  216. return false;
  217. },
  218. focus_on_next_field: function(start_idx, fields) {
  219. // loop to find next eligible fields
  220. for(var i= start_idx + 1, len = fields.length; i < len; i++) {
  221. if(fields[i].disp_status==="Write" && !in_list(wn.model.no_value_type, fields[i].df.fieldtype)) {
  222. this.set_focus(fields[i]);
  223. break;
  224. }
  225. }
  226. },
  227. set_focus: function(field) {
  228. // next is table, show the table
  229. if(field.df.fieldtype=="Table") {
  230. if(!field.grid.grid_rows.length) {
  231. field.grid.add_new_row(1);
  232. } else {
  233. field.grid.grid_rows[0].toggle_view(true);
  234. }
  235. }
  236. else if(field.editor) {
  237. field.editor.set_focus();
  238. }
  239. else if(field.$input) {
  240. field.$input.focus();
  241. }
  242. },
  243. get_open_grid_row: function() {
  244. return $(".grid-row-open").data("grid_row");
  245. },
  246. })