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.
 
 
 
 
 
 

371 line
9.7 KiB

  1. wn.ui.form.Grid = Class.extend({
  2. init: function(opts) {
  3. $.extend(this, opts);
  4. this.fieldinfo = {};
  5. this.docfields = wn.meta.docfield_list[this.df.options];
  6. this.docfields.sort(function(a, b) { return a.idx > b.idx ? 1 : -1 });
  7. },
  8. make: function() {
  9. var me = this;
  10. this.wrapper = $('<div>\
  11. <div class="panel">\
  12. <div class="panel-heading" style="font-size: 15px;"></div>\
  13. <div class="rows"></div>\
  14. <div style="margin-top: 5px; margin-bottom: -5px;">\
  15. <a href="#" class="grid-add-row">+ '+wn._("Add new row")+'.</a>\
  16. <span class="text-muted">Click on row to edit.</span></div>\
  17. </div>\
  18. </div>').appendTo(this.parent);
  19. $(this.wrapper).find(".grid-add-row").click(function() {
  20. wn.model.add_child(me.frm.doc, me.df.options, me.df.fieldname);
  21. me.refresh();
  22. me.wrapper.find(".grid-row:last").data("grid_row").toggle_view(true);
  23. return false;
  24. })
  25. },
  26. make_head: function() {
  27. // labels
  28. new wn.ui.form.GridRow({
  29. parent: $(this.parent).find(".panel-heading"),
  30. parent_df: this.df,
  31. docfields: this.docfields,
  32. frm: this.frm,
  33. grid: this
  34. });
  35. },
  36. refresh: function() {
  37. !this.wrapper && this.make();
  38. var me = this,
  39. $rows = $(me.parent).find(".rows"),
  40. data = this.get_data();
  41. this.display_status = wn.perm.get_field_display_status(this.df, this.frm.doc,
  42. this.perm);
  43. if(this.data_rows_are_same(data)) {
  44. // soft refresh
  45. $.each(this.grid_rows, function(i, g) {
  46. g.refresh();
  47. });
  48. } else {
  49. // redraw
  50. this.wrapper.find(".grid-row").remove();
  51. this.make_head();
  52. this.grid_rows = [];
  53. this.grid_rows_by_docname = {};
  54. $.each(data || [], function(ri, d) {
  55. var grid_row = new wn.ui.form.GridRow({
  56. parent: $rows,
  57. parent_df: me.df,
  58. docfields: me.docfields,
  59. doc: d,
  60. frm: me.frm,
  61. grid: me
  62. });
  63. me.grid_rows.push(grid_row)
  64. me.grid_rows_by_docname[d.name] = grid_row;
  65. });
  66. this.wrapper.find(".grid-add-row").toggle(this.display_status=="Write"
  67. && !this.static_rows);
  68. if(this.display_status=="Write" && !this.static_rows) {
  69. this.make_sortable($rows);
  70. }
  71. this.last_display_status = this.display_status;
  72. this.last_docname = this.frm.docname;
  73. }
  74. },
  75. refresh_row: function(docname) {
  76. this.grid_rows_by_docname[docname] &&
  77. this.grid_rows_by_docname[docname].refresh();
  78. },
  79. data_rows_are_same: function(data) {
  80. if(this.grid_rows) {
  81. var same = data.length==this.grid_rows.length
  82. && this.display_status==this.last_display_status
  83. && this.frm.docname==this.last_docname
  84. && !$.map(this.grid_rows, function(g, i) {
  85. return g.doc.name==data[i].name ? null : true;
  86. }).length;
  87. return same;
  88. }
  89. },
  90. make_sortable: function($rows) {
  91. var me =this;
  92. $rows.sortable({
  93. update: function(event, ui) {
  94. $rows.find(".grid-row").each(function(i, item) {
  95. var doc = $(item).data("doc");
  96. doc.idx = i + 1;
  97. $(this).find(".row-index").html(i + 1);
  98. me.frm.dirty();
  99. })
  100. }
  101. });
  102. },
  103. get_data: function() {
  104. var data = wn.model.get(this.df.options, {
  105. "parenttype": this.frm.doctype,
  106. "parentfield": this.df.fieldname,
  107. "parent": this.frm.docname
  108. });
  109. data.sort(function(a, b) { return a.idx > b.idx ? 1 : -1 });
  110. return data;
  111. },
  112. set_column_disp: function() {
  113. // return
  114. },
  115. get_field: function(fieldname) {
  116. if(!this.fieldinfo[fieldname])
  117. this.fieldinfo[fieldname] = {}
  118. return this.fieldinfo[fieldname];
  119. },
  120. set_value: function(fieldname, value, doc) {
  121. this.grid_rows_by_docname[doc.name].set_value(fieldname, value);
  122. },
  123. add_new_row: function(idx, callback) {
  124. wn.model.add_child(this.frm.doc, this.df.options, this.df.fieldname, idx);
  125. this.refresh();
  126. // show
  127. this.wrapper.find("[data-idx='"+idx+"']").data("grid_row")
  128. .toggle_view(true, callback);
  129. }
  130. });
  131. wn.ui.form.GridRow = Class.extend({
  132. init: function(opts) {
  133. $.extend(this, opts);
  134. this.show = false;
  135. this.make();
  136. },
  137. make: function() {
  138. var me = this;
  139. this.wrapper = $('<div class="grid-row">\
  140. <div class="data-row" style="min-height: 15px;"></div>\
  141. <div class="panel panel-warning" style="display: none;">\
  142. <div class="panel-heading">\
  143. <div class="toolbar" style="height: 36px;">\
  144. Editing Row #<span class="row-index"></span>\
  145. <button class="btn btn-success pull-right" \
  146. title="'+wn._("Close")+'"\
  147. style="margin-left: 7px;">\
  148. <i class="icon-ok"></i></button>\
  149. <button class="btn btn-default pull-right grid-insert-row" \
  150. title="'+wn._("Insert Row")+'"\
  151. style="margin-left: 7px;">\
  152. <i class="icon-plus"></i></button>\
  153. <button class="btn btn-danger pull-right"\
  154. title="'+wn._("Delete Row")+'"\
  155. ><i class="icon-trash"></i></button>\
  156. </div>\
  157. </div>\
  158. <div class="form-area"></div>\
  159. </div>\
  160. <div class="divider row"></div>\
  161. </div>')
  162. .appendTo(this.parent)
  163. .data("grid_row", this);
  164. if(this.doc) {
  165. this.wrapper
  166. .attr("data-idx", this.doc.idx)
  167. .find(".row-index").html(this.doc.idx)
  168. this.wrapper.find(".data-row, .panel-heading")
  169. .click(function() {
  170. me.toggle_view();
  171. return false;
  172. });
  173. this.set_button_events();
  174. }
  175. this.form_panel = this.wrapper.find(".panel");
  176. this.row = this.wrapper.find(".data-row");
  177. this.form_area = this.wrapper.find(".form-area");
  178. this.make_columns();
  179. if(this.doc) {
  180. this.set_data();
  181. }
  182. },
  183. set_button_events: function() {
  184. var me = this;
  185. this.wrapper.find(".btn-danger").click(function() {
  186. me.wrapper.fadeOut(function() {
  187. wn.model.clear_doc(me.doc.doctype, me.doc.name);
  188. me.frm.dirty();
  189. me.grid.refresh();
  190. });
  191. return false;
  192. });
  193. this.wrapper.find(".grid-insert-row").click(function() {
  194. var idx = me.doc.idx;
  195. me.toggle_view(false);
  196. me.grid.add_new_row(idx);
  197. return false;
  198. })
  199. },
  200. refresh: function() {
  201. this.doc = locals[this.doc.doctype][this.doc.name];
  202. // re write columns
  203. this.make_columns();
  204. // refersh form fields
  205. if(this.show) {
  206. $.each(this.fields, function(i, f) {
  207. f.refresh();
  208. });
  209. }
  210. },
  211. make_columns: function() {
  212. var me = this,
  213. total_colsize = 1;
  214. me.row.empty();
  215. col = $('<div class="col col-lg-1 row-index">' + (me.doc ? me.doc.idx : "#")+ '</div>')
  216. .appendTo(me.row)
  217. $.each(me.docfields, function(ci, df) {
  218. if(!df.hidden && !df.print_hide && me.grid.frm.perm[df.permlevel][READ]) {
  219. var colsize = 2,
  220. txt = me.doc ?
  221. wn.format(me.doc[df.fieldname], df, null, me.doc) :
  222. df.label;
  223. switch(df.fieldtype) {
  224. case "Text":
  225. colsize = 3;
  226. break;
  227. case "Check":
  228. colsize = 1;
  229. break;
  230. }
  231. total_colsize += colsize
  232. if(total_colsize > 12)
  233. return false;
  234. $col = $('<div class="col col-lg-'+colsize+'">'
  235. + txt + '</div>')
  236. .css({
  237. "overflow": "hidden",
  238. "text-overflow": "ellipsis",
  239. "white-space": "nowrap",
  240. "padding-right": "0px"
  241. })
  242. .attr("data-fieldname", df.fieldname)
  243. .data("df", df)
  244. .appendTo(me.row)
  245. if(in_list(["Int", "Currency", "Float"], df.fieldtype))
  246. $col.css({"text-align": "right"})
  247. }
  248. });
  249. },
  250. toggle_view: function(show, callback) {
  251. this.doc = locals[this.doc.doctype][this.doc.name];
  252. // hide other
  253. var open_row = $(".grid-row-open").data("grid_row"),
  254. me = this;
  255. this.fields = [];
  256. this.fields_dict = {};
  257. this.show = show===undefined ?
  258. show = !this.show :
  259. show
  260. if(show && open_row) {
  261. if(open_row==this) {
  262. // already open, do nothing
  263. callback();
  264. return;
  265. } else {
  266. // close other views
  267. open_row.toggle_view(false);
  268. }
  269. }
  270. this.make_columns();
  271. this.wrapper.toggleClass("grid-row-open", this.show);
  272. this.show && this.render_form()
  273. this.show && this.row.toggle(false);
  274. this.form_panel.slideToggle(this.show, function() {
  275. if(me.show) {
  276. me.form_area.find(":input:first").focus();
  277. } else {
  278. $(me.form_area).empty();
  279. me.row.toggle(true);
  280. }
  281. callback && callback();
  282. });
  283. },
  284. render_form: function() {
  285. var me = this,
  286. cnt = 0,
  287. row = $('<div class="row">').appendTo(me.form_area),
  288. col1 = $('<div class="col col-lg-6"></div>').appendTo(row),
  289. col2 = $('<div class="col col-lg-6"></div>').appendTo(row),
  290. len = $.map(me.docfields, function(d) {
  291. return !d.hidden ? true : null }).length;
  292. len = (len + len % 2) / 2;
  293. $.each(me.docfields, function(ci, df) {
  294. if(!df.hidden) {
  295. var fieldwrapper = $('<div>')
  296. .appendTo(ci <= len ? col1 : col2)
  297. var fieldobj = make_field(df, me.parent_df.options,
  298. fieldwrapper.get(0), me.frm);
  299. fieldobj.docname = me.doc.name;
  300. fieldobj.refresh();
  301. fieldobj.input &&
  302. $(fieldobj.input).css({"max-height": "100px"});
  303. // set field properties
  304. // used for setting custom get queries in links
  305. if(me.grid.fieldinfo[df.fieldname])
  306. $.extend(fieldobj, me.grid.fieldinfo[df.fieldname]);
  307. me.fields.push(fieldobj);
  308. me.fields_dict[df.fieldname] = fieldobj;
  309. cnt++;
  310. }
  311. });
  312. if(this.grid.display_status!="Write" || this.grid.static_rows) {
  313. this.wrapper.find(".btn-danger, .grid-insert-row").toggle(false);
  314. return;
  315. }
  316. },
  317. set_data: function() {
  318. this.wrapper.data({
  319. "doc": this.doc
  320. })
  321. },
  322. set_value: function(fieldname, value) {
  323. // in row
  324. var $col = this.row.find("[data-fieldname='"+fieldname+"']");
  325. $col.length && $col.html(wn.format(value, $col.data("df"), null, this.doc));
  326. // in form
  327. if(this.fields_dict && this.fields_dict[fieldname]) {
  328. this.fields_dict[fieldname].set_input(value);
  329. }
  330. },
  331. refresh_field: function(fieldname) {
  332. var $col = this.row.find("[data-fieldname='"+fieldname+"']");
  333. if($col.length) {
  334. var value = wn.model.get_value(this.doc.doctype, this.doc.name, fieldname);
  335. $col.html(wn.format(value, $col.data("df"), null, this.doc));
  336. }
  337. // in form
  338. if(this.fields_dict && this.fields_dict[fieldname]) {
  339. this.fields_dict[fieldname].refresh();
  340. }
  341. },
  342. });