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.
 
 
 
 
 
 

564 line
14 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. /// Data Table
  23. _r.scroll_head = function(ele) {
  24. var h = ele.childNodes[0];
  25. h.style.top = cint(ele.scrollTop) + 'px';
  26. }
  27. _r.DataTable = function(html_fieldname, dt, repname, hide_toolbar) {
  28. var me = this;
  29. if(html_fieldname.substr) {
  30. var html_field = cur_frm.fields_dict[html_fieldname];
  31. // override onrefresh
  32. html_field.onrefresh = function() {
  33. if(me.docname != cur_frm.docname) {
  34. me.clear_all();
  35. me.docname = cur_frm.docname;
  36. }
  37. }
  38. var parent = html_field.wrapper;
  39. datatables[html_fieldname] = this;
  40. } else {
  41. var parent = html_fieldname;
  42. }
  43. this.start_rec = 1;
  44. this.page_len = 50;
  45. this.repname = repname;
  46. this.dt = dt;
  47. this.no_limit = false;
  48. this.query = '';
  49. this.has_index = 1;
  50. this.has_headings = 1; //this.sort_options = {};
  51. this.disabled_options = {};
  52. this.levels = [];
  53. // make ui
  54. // new link
  55. if(this.dt) {
  56. var tw = $a(parent, 'div');
  57. var t = $a(tw, 'div', 'link_type');
  58. t.style.cssFloat = 'right';
  59. $h(tw, '14px');
  60. t.style.margin = '2px 0px';
  61. t.style.fontSize = '11px';
  62. t.onclick = function() { new_doc(me.dt); }
  63. t.innerHTML = 'New '+ this.dt;
  64. }
  65. // toolbar
  66. if(!hide_toolbar) this.make_toolbar(parent);
  67. this.wrapper = $a(parent, 'div', 'report_tab');
  68. $h(this.wrapper, cint(screen.height * 0.35) + 'px');
  69. this.wrapper.onscroll = function() {_r.scroll_head(this); }
  70. this.hwrapper = $a(this.wrapper, 'div', 'report_head_wrapper');
  71. this.twrapper = $a(this.wrapper, 'div', 'report_tab_wrapper');
  72. this.no_data_tag = $a(this.wrapper, 'div', 'report_no_data');
  73. this.no_data_tag.innerHTML = 'No Records Found';
  74. this.fetching_tag = $a(this.wrapper, 'div', '', {height:'100%', background:'url("lib/images/ui/square_loading.gif") center no-repeat', display:'none'});
  75. }
  76. _r.DataTable.prototype.add_icon = function(parent, imgsrc) {
  77. var i = $a(parent, 'img');
  78. i.style.padding = '2px';
  79. i.style.cursor = 'pointer';
  80. i.setAttribute('src', 'lib/images/icons/'+imgsrc+'.gif');
  81. return i;
  82. }
  83. _r.DataTable.prototype.set_no_limit = function(v) {
  84. if(v) {
  85. this.no_limit = 1;
  86. $dh(this.page_len_sel.wrapper);
  87. } else {
  88. this.no_limit = 0;
  89. $ds(this.page_len_sel.wrapper);
  90. }
  91. }
  92. _r.DataTable.prototype.make_toolbar = function(parent) {
  93. var me = this;
  94. // headbar
  95. this.hbar = $a(parent, 'div', '', {margin:'8px 0px 16px 0px'});
  96. var ht = make_table(this.hbar,1,3,'100%',['40%','40%','20%'],{verticalAlign:'middle'});
  97. var div = $a($td(ht,0,0), 'div');
  98. // sort select
  99. var t = make_table($td(ht,0,1),1,6,null,[null,null,null,'20px',null,null],{verticalAlign:'middle'});
  100. $td(t,0,0).innerHTML = 'Sort By:'; $y($td(t,0,1),{textAlign:'right',paddingRight:'4px'});
  101. this.sort_sel = $a($td(t,0,2), 'select','',{width:'100px'});
  102. this.sort_sel.onchange = function() {
  103. me.start_rec = 1;
  104. me.run();
  105. }
  106. // sort order
  107. this.sort_icon = this.add_icon($td(t,0,3), 'arrow_down');
  108. this.sort_order = 'DESC';
  109. this.sort_icon.onclick = function() {
  110. if(me.sort_order=='ASC') me.set_desc();
  111. else me.set_asc();
  112. me.start_rec = 1;
  113. me.run();
  114. }
  115. // page len
  116. $td(t,0,4).innerHTML = 'Per Page:'; $y($td(t,0,4),{textAlign:'right',paddingRight:'4px'});
  117. var s = new SelectWidget($td(t,0,5), ['50','100','500','1000'], '70px');
  118. s.inp.value = '50';
  119. s.inp.onchange = function() {
  120. me.page_len = flt(this.value);
  121. }
  122. this.page_len_sel = s;
  123. var c1 = $td(ht,0,2);
  124. c1.style.textAlign = 'right';
  125. // first page
  126. var ic = this.add_icon(c1, 'resultset_first');
  127. ic.onclick = function() {
  128. me.start_rec = 1;
  129. me.run();
  130. }
  131. // prev page
  132. var ic = this.add_icon(c1, 'resultset_previous');
  133. ic.onclick = function() {
  134. if(me.start_rec - me.page_len <= 0)return;
  135. me.start_rec = me.start_rec - me.page_len;
  136. me.run();
  137. }
  138. // next page
  139. this.has_next = false;
  140. var ic = this.add_icon(c1, 'resultset_next');
  141. ic.onclick = function() {
  142. if(!me.has_next)return;
  143. me.start_rec = me.start_rec + me.page_len;
  144. me.run();
  145. }
  146. }
  147. _r.DataTable.prototype.set_desc = function() {
  148. this.sort_icon.src = 'lib/images/icons/arrow_down.gif'; this.sort_order='DESC';
  149. }
  150. _r.DataTable.prototype.set_asc = function(icon) {
  151. this.sort_icon.src = 'lib/images/icons/arrow_up.gif'; this.sort_order='ASC';
  152. }
  153. ////
  154. _r.DataTable.prototype.set_sort_option_disabled = function(label, disabled) {
  155. // has bugs due to sequencing
  156. // may not set during load
  157. var s = this.sort_sel;
  158. if(disabled) {
  159. // remove this option
  160. for(var i=0; i<s.options.length; i++) {
  161. if(s.options[i] && s.options[i].text==label) {
  162. this.disabled_options[label] = s.options[i];
  163. s.remove(i);
  164. }
  165. }
  166. } else {
  167. // get it back
  168. if(this.disabled_options[label]) {
  169. try {
  170. s.add(this.disabled_options[label], s.options[s.options.length-1]);
  171. } catch(e) {
  172. try {
  173. s.add(this.disabled_options[label], s.options.length-1);
  174. } catch (e) { }
  175. }
  176. this.disabled_options[label] = null;
  177. }
  178. }
  179. }
  180. _r.DataTable.prototype.add_sort_option = function(label, val) {
  181. var s = this.sort_sel;
  182. s.options[s.options.length] =
  183. new Option(label, val, false, s.options.length==0?true:false);
  184. }
  185. _r.DataTable.prototype.update_query = function(no_limit) {
  186. // add sorting
  187. if((_r.rb_con.cur_rb && _r.rb_con.cur_rb.get_query) || (this.search_criteria && this.search_criteria.custom_query)) {
  188. // no sorting if custom_query or get_query
  189. } else {
  190. if(!sel_val(this.sort_sel)) {
  191. this.sort_sel.selectedIndex = 0; // select the first value (IE)
  192. }
  193. this.query += NEWLINE
  194. + ' ORDER BY ' + sel_val(this.sort_sel)
  195. + ' ' + this.sort_order;
  196. }
  197. if(no_limit || this.no_limit) {
  198. if(this.show_query) alert(this.query);
  199. return;
  200. }
  201. // add paging
  202. this.query += ' LIMIT ' + (this.start_rec-1) + ',' + this.page_len;
  203. if(this.show_query)
  204. alert(this.query);
  205. }
  206. _r.DataTable.prototype._get_query = function(no_limit) {
  207. $dh(this.no_data_tag);
  208. this.show_query = 0;
  209. if(this.make_query)
  210. this.make_query();
  211. this.update_query(no_limit);
  212. }
  213. _r.DataTable.prototype.run = function() {
  214. if(this.validate && !this.validate())
  215. return;
  216. if(_r.rb_con.cur_rb) {
  217. if(_r.rb_con.cur_rb.large_report == 1) {
  218. msgprint("This is a very large report and cannot be shown in the browser as it is likely to make your browser very slow.<br><br>Please click on 'Export' to open in a spreadsheet");
  219. return;
  220. }
  221. _r.rb_con.cur_rb.mytabs.items['Result'].expand();
  222. }
  223. var me = this;
  224. this._get_query();
  225. // preset data
  226. if(this.set_data) {
  227. this.show_result(this.set_data);
  228. this.set_data = null;
  229. return;
  230. }
  231. $ds(this.fetching_tag);
  232. if($.browser.mozilla)this.clear_all();
  233. var args = {
  234. 'query':me.query,
  235. 'report_name': '_r.DataTable',
  236. 'show_deleted':1,
  237. 'sc_id':me.search_criteria ? me.search_criteria.name : '',
  238. 'filter_values':me.filter_vals ? docstring(me.filter_vals) : '',
  239. 'roles':'["'+user_roles.join('","')+'"]'
  240. }
  241. if(this.is_simple) args.is_simple = 1;
  242. $c('webnotes.widgets.query_builder.runquery', args, function(r,rt) {
  243. $dh(me.fetching_tag);
  244. me.show_result(r,rt);
  245. });
  246. }
  247. _r.DataTable.prototype.clear_all = function() {
  248. // clear old
  249. if(this.htab && this.htab.parentNode) {
  250. this.htab.parentNode.removeChild(this.htab); delete this.htab; }
  251. if(this.tab && this.tab.parentNode) {
  252. this.tab.parentNode.removeChild(this.tab); delete this.tab; }
  253. $dh(this.no_data_tag);
  254. }
  255. _r.DataTable.prototype.has_data = function() {
  256. if(this.htab && this.htab.rows.length)return 1;
  257. else return 0;
  258. }
  259. _r.DataTable.prototype.show_result = function(r, rt) {
  260. // clear old
  261. var me = this;
  262. this.clear_all();
  263. this.rset = eval(r.values);
  264. if(this.rset && this.rset.length) {
  265. // add
  266. if(this.has_headings) {
  267. this.htab = $a(this.hwrapper, 'table');
  268. $y(this.twrapper,{top:'25px',borderTop:'0px'});
  269. }
  270. this.tab = $a(this.twrapper, 'table');
  271. this.colwidths = eval(r.colwidths);
  272. this.coltypes = eval(r.coltypes);
  273. this.coloptions = eval(r.coloptions);
  274. this.colnames = eval(r.colnames);
  275. $y(this.tab,{tableLayout:'fixed'});
  276. if(this.beforetableprint)this.beforetableprint(this);
  277. // heading
  278. if(this.has_headings) this.make_head_tab(this.colnames);
  279. // data
  280. var start = this.start_rec;
  281. // show max 1000
  282. var rset_len = this.rset.length;
  283. if(rset_len > 1000) {
  284. msgprint("Showing only 1000 records out of " + rset_len + ". Use 'Export' to see all records");
  285. rset_len = 1000;
  286. }
  287. for(var vi=0; vi<rset_len; vi++) {
  288. var row = this.tab.insertRow(vi);
  289. // for script
  290. if(this.has_index) {
  291. var c0 = row.insertCell(0);
  292. $w(c0, '30px');
  293. $a(c0, 'div', '', {width:'23px'}).innerHTML = start;
  294. }
  295. // cells
  296. start++;
  297. for(var ci=0;ci < this.rset[vi].length;ci++) {
  298. this.make_data_cell(vi, ci, this.rset[vi][ci]);
  299. }
  300. if(this.afterrowprint) {
  301. row.data_cells = {}; row.data = {};
  302. for(var ci=0;ci< this.colnames.length;ci++) {
  303. row.data[this.colnames[ci]] = this.rset[vi][ci];
  304. row.data_cells[this.colnames[ci]] = row.cells[ci+1];
  305. }f
  306. this.afterrowprint(row);
  307. }
  308. }
  309. // has next page?
  310. if(this.rset.length && this.rset.length>=this.page_len)this.has_next = true;
  311. // style
  312. if(r.style) {
  313. for(var i=0;i<r.style.length;i++) {
  314. $yt(this.tab,r.style[i][0],r.style[i][1],r.style[i][2]);
  315. }
  316. }
  317. // after table print
  318. if(this.aftertableprint) this.aftertableprint(this.tab);
  319. } else {
  320. $ds(this.no_data_tag);
  321. }
  322. }
  323. _r.DataTable.prototype.get_col_width = function(i) {
  324. if(this.colwidths
  325. && this.colwidths.length
  326. && this.colwidths[i])
  327. return cint(this.colwidths[i]) +'px';
  328. else return '100px';
  329. }
  330. _r.DataTable.prototype.make_head_tab = function(colnames) {
  331. var r0 = this.htab.insertRow(0);
  332. if(this.has_index) {
  333. var c0 = r0.insertCell(0);
  334. c0.className = 'report_head_cell';
  335. $w(c0, '30px');
  336. $a(c0, 'div').innerHTML = 'Sr';
  337. this.total_width = 30;
  338. }
  339. for(var i=0;i<colnames.length;i++) {
  340. var w = this.get_col_width(i);
  341. this.total_width+=cint(w);
  342. var c = r0.insertCell(r0.cells.length);
  343. c.className = 'report_head_cell';
  344. if(w)$w(c, w);
  345. $a(c,'div').innerHTML = colnames[i];
  346. c.val = colnames[i];
  347. }
  348. $w(this.htab, this.total_width + 'px');
  349. $w(this.tab, this.total_width + 'px');
  350. }
  351. _r.DataTable.prototype.make_data_cell = function(ri, ci, val) {
  352. var row = this.tab.rows[ri];
  353. var c = row.insertCell(row.cells.length);
  354. // row style:
  355. if(row.style.color)
  356. c.style.color = row.style.color;
  357. if(row.style.backgroundColor)
  358. c.style.backgroundColor = row.style.backgroundColor;
  359. if(row.style.fontWeight)
  360. c.style.fontWeight = row.style.fontWeight;
  361. if(row.style.fontSize)
  362. c.style.fontSize = row.style.fontSize;
  363. var w = this.get_col_width(ci);
  364. if(w)$w(c, w);
  365. c.val = val;
  366. var me = this;
  367. c.div = $a(c, 'div', '', {width:(cint(w)-7)+'px'});
  368. $s(c.div, val, this.coltypes[ci], this.coloptions[ci])
  369. }
  370. _r.DataTable.prototype.do_print = function() {
  371. this._get_query(true);
  372. args = {
  373. query : this.query,
  374. title : this.rep_name?this.rep_name:this.dt,
  375. colnames : null,
  376. colwidhts : null,
  377. coltypes : null,
  378. has_index : this.has_index,
  379. has_headings: this.has_headings,
  380. check_limit : 1,
  381. is_simple : (this.is_simple ? 'Yes' : ''),
  382. sc_id : (this.search_criteria ? this.search_criteria.name : ''),
  383. filter_values : docstring(this.filter_vals),
  384. finder: this.finder ? this.finder : null
  385. };
  386. wn.require('lib/js/legacy/widgets/print_query.js');
  387. _p.print_query = new _p.PrintQuery();
  388. _p.print_query.show_dialog(args);
  389. }
  390. _r.DataTable.prototype.do_export = function() {
  391. this._get_query(true);
  392. var me = this;
  393. export_query(this.query, function(q) {
  394. export_csv(q, (me.rep_name?me.rep_name:me.dt), (me.search_criteria?me.search_criteria.name:''), me.is_simple, docstring(me.filter_vals));
  395. });
  396. }
  397. // Calculator
  398. // ----------
  399. _r.DataTable.prototype.do_calc = function() {
  400. _r.show_calc(this.tab, this.colnames, this.coltypes, 1);
  401. }
  402. _r.DataTable.prototype.get_col_data = function(colname) {
  403. var ci = 0;
  404. if(!this.htab) return [];
  405. for(var i=1;i<this.htab.rows[0].cells.length;i++) {
  406. var hc = this.htab.rows[0].cells[i];
  407. if(hc.val == colname) {
  408. ci = i;
  409. break;
  410. }
  411. }
  412. var ret = [];
  413. for(var ri=0;ri<this.tab.rows.length;ri++) {
  414. ret[ret.length] = this.tab.rows[ri].cells[ci].val;
  415. }
  416. return ret;
  417. }
  418. _r.DataTable.prototype.get_html = function() {
  419. var w = document.createElement('div');
  420. w = $a(w, 'div');
  421. w.style.marginTop = '16px';
  422. var tab = $a(w, 'table');
  423. var add_head_style = function(c, w) {
  424. c.style.fontWeight = 'bold';
  425. c.style.border = '1px solid #000';
  426. c.style.padding = '2px';
  427. if(w)$w(c, w);
  428. return c;
  429. }
  430. var add_cell_style = function(c) {
  431. c.style.padding = '2px';
  432. c.style.border = '1px solid #000';
  433. return c;
  434. }
  435. tab.style.borderCollapse = 'collapse';
  436. var hr = tab.insertRow(0);
  437. var c0 = add_head_style(hr.insertCell(0), '30px');
  438. c0.innerHTML = 'Sr';
  439. // heading
  440. for(var i=1;i<this.htab.rows[0].cells.length;i++) {
  441. var hc = this.htab.rows[0].cells[i];
  442. var c = add_head_style(hr.insertCell(i), hc.style.width);
  443. c.innerHTML = hc.innerHTML;
  444. }
  445. // data
  446. for(var ri=0;ri<this.tab.rows.length;ri++) {
  447. var row = this.tab.rows[ri];
  448. var dt_row = tab.insertRow(tab.rows.length);
  449. for(var ci=0;ci<row.cells.length;ci++) {
  450. var c = add_cell_style(dt_row.insertCell(ci));
  451. c.innerHTML = row.cells[ci].innerHTML;
  452. }
  453. }
  454. return w.innerHTML;
  455. }