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

11 years ago
11 years ago
11 years ago
11 years ago
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 text-muted">'
  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. })