Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

grid.js 10 KiB

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