Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.
 
 
 
 
 
 

496 rindas
13 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. // _f.Grid
  23. _f.cur_grid_cell = null;
  24. _f.Grid = function(parent) { }
  25. _f.Grid.prototype.init = function(parent, row_height) {
  26. var me = this;
  27. this.col_idx_by_name = {}
  28. this.alt_row_bg = '#F2F2FF';
  29. this.row_height = row_height;
  30. // make the grid
  31. if(!row_height)this.row_height = '26px';
  32. this.make_ui(parent);
  33. // Sr No
  34. this.insert_column('', '', 'Int', 'Sr', '50px', '', [1,0,0]);
  35. if(this.oninit)this.oninit();
  36. // bind clicks
  37. $(this.wrapper).bind('keydown', function(e) {
  38. me.notify_keypress(e, e.which);
  39. })
  40. // reset grid heights after complete is triggerd on the form
  41. $(cur_frm.wrapper).bind('render_complete', function() {
  42. me.set_ht();
  43. });
  44. }
  45. _f.Grid.prototype.make_ui = function(parent) {
  46. var ht = make_table($a(parent, 'div'), 1, 2, '100%', ['55%','45%']);
  47. this.main_title = $td(ht,0,0); this.main_title.className = 'columnHeading';
  48. $td(ht,0,1).style.textAlign = 'right';
  49. this.tbar_div = $a($td(ht,0,1), 'div', 'grid_tbarlinks');
  50. this.tbar_tab = make_table(this.tbar_div,1,4,'100%',['25%','25%','25%','25%']);
  51. this.wrapper = $a(parent, 'div', 'grid_wrapper round');
  52. this.head_wrapper = $a(this.wrapper, 'div', 'grid_head_wrapper');
  53. this.head_tab = $a(this.head_wrapper, 'table', 'grid_head_table');
  54. this.head_row = this.head_tab.insertRow(0);
  55. this.tab_wrapper = $a(this.wrapper, 'div', 'grid_tab_wrapper');
  56. this.tab = $a(this.tab_wrapper, 'table', 'grid_table');
  57. var me = this;
  58. this.wrapper.onscroll = function() { me.head_wrapper.style.top = me.wrapper.scrollTop+'px'; }
  59. }
  60. _f.Grid.prototype.show = function() {
  61. if(this.can_edit && this.field.df['default'].toLowerCase()!='no toolbar') {
  62. $ds(this.tbar_div);
  63. if(this.can_add_rows) {
  64. $td(this.tbar_tab, 0, 0).style.display = 'table-cell';
  65. $td(this.tbar_tab, 0, 1).style.display = 'table-cell';
  66. } else {
  67. $td(this.tbar_tab, 0, 0).style.display = 'none';
  68. $td(this.tbar_tab, 0, 1).style.display = 'none';
  69. }
  70. } else {
  71. $dh(this.tbar_div);
  72. }
  73. $ds(this.wrapper);
  74. }
  75. _f.Grid.prototype.hide = function() {
  76. $dh(this.wrapper); $dh(this.tbar_div);
  77. }
  78. _f.Grid.prototype.insert_column = function(doctype, fieldname, fieldtype, label, width, options, perm, reqd, df) {
  79. var idx = this.head_row.cells.length;
  80. if(!width)width = '100px';
  81. if(fieldtype=="Currency" && cint(width) < 100) width = "100px";
  82. width= cint(width) + 'px';
  83. var col = this.head_row.insertCell(idx);
  84. col.df = df;
  85. col.doctype = doctype; // for report (fields may be from diff doctypes)
  86. col.fieldname = fieldname;
  87. col.fieldtype = fieldtype;
  88. $(col).attr("data-grid-fieldname", doctype + "-" + fieldname);
  89. col.innerHTML = wn._(label);
  90. col.title = label;
  91. col.label = label;
  92. if(reqd)
  93. col.style.color = "#D22";
  94. col.style.width = width;
  95. col.options = options;
  96. col.perm = perm;
  97. this.col_idx_by_name[fieldname] = idx;
  98. }
  99. _f.Grid.prototype.reset_table_width = function() {
  100. var w = 0;
  101. $.each(this.head_row.cells, function(i, cell) {
  102. if((cell.style.display || '').toLowerCase()!='none')
  103. w += cint(cell.style.width);
  104. })
  105. this.head_tab.style.width = w + 'px';
  106. this.tab.style.width = w + 'px';
  107. }
  108. _f.Grid.prototype.set_column_disp = function(fieldname, show) {
  109. var cidx = this.col_idx_by_name[fieldname];
  110. if(!cidx) {
  111. msgprint('Trying to hide unknown column: ' + fieldname);
  112. return;
  113. }
  114. var disp = show ? 'table-cell' : 'none';
  115. // head
  116. this.head_row.cells[cidx].style.display = disp;
  117. // body
  118. for(var i=0, len=this.tab.rows.length; i<len; i++) {
  119. var cell = this.tab.rows[i].cells[cidx];
  120. cell.style.display = disp;
  121. }
  122. // reset table width
  123. this.reset_table_width();
  124. }
  125. _f.Grid.prototype.toggle_reqd = function(fieldname, reqd) {
  126. // IMPORTANT: this should be called in refresh event
  127. var grid_field = this.get_field(fieldname);
  128. grid_field.df.reqd = reqd ? true : false;
  129. grid_field.refresh();
  130. $(grid_field.grid.head_row).find('[data-grid-fieldname="' + grid_field.grid.doctype
  131. + '-' + fieldname + '"]').css({ color: reqd ? "#D22" : "black" });
  132. }
  133. _f.Grid.prototype.append_row = function(idx, docname) {
  134. if(!idx)idx = this.tab.rows.length;
  135. var row = this.tab.insertRow(idx);
  136. row.docname = docname;
  137. if(idx % 2)var odd=true; else var odd=false;
  138. var me = this;
  139. // make cells
  140. for(var i=0; i<this.head_row.cells.length; i++){
  141. var cell = row.insertCell(i);
  142. var hc = this.head_row.cells[i];
  143. // ape style of head
  144. cell.style.width = hc.style.width;
  145. cell.style.display = hc.style.display;
  146. cell.row = row;
  147. cell.grid = this;
  148. cell.className = 'grid_cell';
  149. cell.div = $a(cell, 'div', 'grid_cell_div');
  150. if(this.row_height) {
  151. cell.div.style.height = this.row_height; }
  152. cell.div.cell = cell;
  153. $(cell.div).click(function(e) {
  154. me.cell_select(this.cell);
  155. // cell selected, don't do anything else
  156. // like deselect it
  157. e.stopPropagation();
  158. });
  159. if(odd) {
  160. $bg(cell, this.alt_row_bg); cell.is_odd = 1;
  161. cell.div.style.border = '2px solid ' + this.alt_row_bg;
  162. } else $bg(cell,'#FFF');
  163. if(!hc.fieldname) cell.div.style.cursor = 'default'; // Index
  164. }
  165. this.set_ht();
  166. return row;
  167. }
  168. _f.Grid.prototype.refresh_cell = function(docname, fieldname) {
  169. for(var r=0;r<this.tab.rows.length;r++) {
  170. if(this.tab.rows[r].docname==docname) {
  171. for(var c=0;c<this.head_row.cells.length;c++) {
  172. var hc = this.head_row.cells[c];
  173. if(hc.fieldname==fieldname) {
  174. this.set_cell_value(this.tab.rows[r].cells[c]);
  175. }
  176. }
  177. }
  178. }
  179. }
  180. // for form edit
  181. _f.cur_grid;
  182. _f.cur_grid_ridx;
  183. _f.Grid.prototype.set_cell_value = function(cell) {
  184. // if newrow
  185. if(cell.row.is_newrow)return;
  186. // show static
  187. var hc = this.head_row.cells[cell.cellIndex];
  188. if(hc.fieldname)
  189. var doc = locals[hc.doctype][cell.row.docname];
  190. if(hc.fieldname && doc) {
  191. var v = locals[hc.doctype][cell.row.docname][hc.fieldname];
  192. } else {
  193. var v = (cell.row.rowIndex + 1); // Index
  194. }
  195. if(v==null){ v=''; }
  196. var me = this;
  197. // variations
  198. if(cell.cellIndex) {
  199. $(cell.div).html(wn.format(v, hc.df, {for_print:
  200. ((doc && doc.docstatus==0 && !cint(hc.df ? hc.df.read_only : 1)) ? true : false)}));
  201. } else {
  202. // Index column
  203. cell.div.style.padding = '2px';
  204. cell.div.style.textAlign = 'left';
  205. cell.div.innerHTML = '';
  206. var t = make_table(cell.div,1,3,'60px',['20px','20px','20px'],{verticalAlign: 'middle', padding:'2px'});
  207. $y($td(t,0,0),{paddingLeft:'4px'});
  208. $td(t,0,0).innerHTML = cell.row.rowIndex + 1;
  209. $(cell.div).click(function() {
  210. if(me.can_edit) {
  211. me.cell_deselect();
  212. cell.div.style.border = '2px solid #88F';
  213. _f.cur_grid_cell = cell;
  214. }
  215. });
  216. if(this.can_edit) {
  217. $("<a title='Edit Row'><i class='icon-edit'></i></a>")
  218. .click(function() {
  219. _f.cur_grid = me;
  220. _f.cur_grid_ridx = cell.row.rowIndex;
  221. _f.edit_record(me.doctype, cell.row.docname, 1);
  222. })
  223. .appendTo($td(t,0,1))
  224. } else {
  225. cell.div.innerHTML = (cell.row.rowIndex + 1);
  226. cell.div.style.cursor = 'default';
  227. cell.div.onclick = function() { }
  228. }
  229. }
  230. }
  231. // if clicked on whitespace
  232. // and a grid cell is selected
  233. // deselect the cell
  234. $(document).bind('click', function(e) {
  235. var me = this;
  236. var is_target_toolbar = function() {
  237. return $(e.target).parents('.grid_tbarlinks').length;
  238. }
  239. var is_target_input = function() {
  240. // select opened
  241. if(e.target.tagName.toLowerCase()=='option') return true;
  242. // autosuggest openend
  243. //if(wn._autosugg_open) return true;
  244. return $(e.target).parents().get().indexOf(_f.cur_grid_cell)!=-1;
  245. }
  246. if(_f.cur_grid_cell && !is_target_input() && !is_target_toolbar()) {
  247. if(!(text_dialog && text_dialog.display)
  248. && !datepicker_active && !(selector && selector.display)) {
  249. setTimeout('_f.cur_grid_cell.grid.cell_deselect()', 500);
  250. return false;
  251. }
  252. }
  253. });
  254. _f.Grid.prototype.cell_deselect = function() {
  255. if(_f.cur_grid_cell) {
  256. var c = _f.cur_grid_cell;
  257. c.grid.remove_template(c);
  258. c.div.className = 'grid_cell_div';
  259. if(c.is_odd) c.div.style.border = '2px solid ' + c.grid.alt_row_bg;
  260. else c.div.style.border = '2px solid #FFF';
  261. _f.cur_grid_cell = null;
  262. }
  263. }
  264. _f.Grid.prototype.cell_select = function(cell, ri, ci) {
  265. if(cell && _f.cur_grid_cell==cell && cell.hc) return;
  266. if(ri!=null && ci!=null)
  267. cell = this.tab.rows[ri].cells[ci];
  268. var hc = this.head_row.cells[cell.cellIndex];
  269. if(!hc.doctype) return;
  270. if(!hc.template) {
  271. this.make_template(hc);
  272. }
  273. hc.template.perm = this.field ? this.field.perm : hc.perm; // get latest permissions
  274. if(hc.fieldname && hc.template.get_status()=='Write') {
  275. this.cell_deselect();
  276. cell.div.style.border = '2px solid #88F';
  277. _f.cur_grid_cell = cell;
  278. this.add_template(cell);
  279. }
  280. }
  281. _f.Grid.prototype.add_template = function(cell) {
  282. if(!cell.row.docname && this.add_newrow) { // activate new row here
  283. this.add_newrow();
  284. this.cell_select(cell);
  285. } else {
  286. var hc = this.head_row.cells[cell.cellIndex];
  287. cell.div.innerHTML = '';
  288. cell.div.appendChild(hc.template.wrapper);
  289. hc.template.activate(cell.row.docname);
  290. hc.template.activated=1;
  291. cell.hc = hc;
  292. if(hc.template.input && hc.template.input.set_width) {
  293. hc.template.input.set_width($(cell).width());
  294. }
  295. }
  296. }
  297. _f.Grid.prototype.get_field = function(fieldname) { // get template
  298. for(var i=0;i<this.head_row.cells.length;i++) {
  299. var hc = this.head_row.cells[i];
  300. if(hc.fieldname == fieldname) {
  301. if(!hc.template) {
  302. this.make_template(hc);
  303. }
  304. return hc.template;
  305. }
  306. }
  307. return {} // did not find, return empty object not to throw error in get_query
  308. }
  309. _f.grid_date_cell = '';
  310. _f.grid_refresh_date = function() {
  311. _f.grid_date_cell.grid.set_cell_value(_f.grid_date_cell);
  312. }
  313. _f.grid_refresh_field = function(temp, input) {
  314. if($(input).val() != _f.get_value(temp.doctype, temp.docname, temp.df.fieldname))
  315. $(input).trigger('change');
  316. }
  317. _f.Grid.prototype.remove_template = function(cell) {
  318. var hc = this.head_row.cells[cell.cellIndex];
  319. if(!hc.template)return;
  320. if(!hc.template.activated)return;
  321. if(hc.template && hc.template.wrapper.parentNode)
  322. cell.div.removeChild(hc.template.wrapper);
  323. this.set_cell_value(cell);
  324. hc.template.activated=0;
  325. }
  326. _f.Grid.prototype.notify_keypress = function(e, keycode) {
  327. if(keycode>=37 && keycode<=40 && e.shiftKey) {
  328. if(text_dialog && text_dialog.display) {
  329. return;
  330. }
  331. } else
  332. return;
  333. if(!_f.cur_grid_cell) return;
  334. if(_f.cur_grid_cell.grid != this) return;
  335. var ri = _f.cur_grid_cell.row.rowIndex;
  336. var ci = _f.cur_grid_cell.cellIndex;
  337. switch(keycode) {
  338. case 38: // up
  339. if (ri > 0) {
  340. this.cell_select('', ri - 1, ci);
  341. } break;
  342. case 40: // down
  343. if (ri < (this.tab.rows.length - 1)) {
  344. this.cell_select('', ri + 1, ci);
  345. } break;
  346. case 39: // right
  347. if (ci < (this.head_row.cells.length - 1)) {
  348. this.cell_select('', ri, ci + 1);
  349. } break;
  350. case 37: // left
  351. if (ci > 1) {
  352. this.cell_select('', ri, ci - 1);
  353. } break;
  354. }
  355. }
  356. _f.Grid.prototype.make_template = function(hc) {
  357. hc.template = make_field(wn.meta.get_docfield(hc.doctype, hc.fieldname), hc.doctype,
  358. '', this.field.frm, true);
  359. hc.template.grid = this;
  360. }
  361. _f.Grid.prototype.append_rows = function(n) {
  362. for(var i=0;i<n;i++) this.append_row();
  363. }
  364. _f.Grid.prototype.truncate_rows = function(n) {
  365. for(var i=0;i<n;i++) this.tab.deleteRow(this.tab.rows.length-1);
  366. }
  367. _f.Grid.prototype.set_data = function(data) {
  368. // deselect if not done yet
  369. this.cell_deselect();
  370. // set table widths
  371. this.reset_table_width();
  372. // append if reqd
  373. if(data.length > this.tab.rows.length)
  374. this.append_rows(data.length - this.tab.rows.length);
  375. // truncate if reqd
  376. if(data.length < this.tab.rows.length)
  377. this.truncate_rows(this.tab.rows.length - data.length);
  378. // set data
  379. for(var ridx=0;ridx<data.length;ridx++) {
  380. this.refresh_row(ridx, data[ridx]);
  381. }
  382. if(this.can_add_rows && this.make_newrow) {
  383. this.make_newrow();
  384. }
  385. if(this.wrapper.onscroll)this.wrapper.onscroll();
  386. }
  387. _f.Grid.prototype.set_ht = function() {
  388. var max_ht = cint(0.37 * screen.width);
  389. var ht = $(this.tab).height() + $(this.head_tab).height() + 30;
  390. if(ht < 100)
  391. ht=100;
  392. if(ht > max_ht) ht = max_ht;
  393. ht += 4;
  394. $y(this.wrapper,{height:ht+'px'});
  395. }
  396. _f.Grid.prototype.refresh_row = function(ridx, docname) {
  397. var row = this.tab.rows[ridx];
  398. row.docname = docname;
  399. row.is_newrow = false;
  400. for(var cidx=0; cidx<row.cells.length; cidx++) {
  401. this.set_cell_value(row.cells[cidx]);
  402. }
  403. }