datagrid-detailview.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. var detailview = $.extend({}, $.fn.datagrid.defaults.view, {
  2. render: function(target, container, frozen){
  3. var state = $.data(target, 'datagrid');
  4. var opts = state.options;
  5. if (frozen){
  6. if (!(opts.rownumbers || (opts.frozenColumns && opts.frozenColumns.length))){
  7. return;
  8. }
  9. }
  10. var rows = state.data.rows;
  11. var fields = $(target).datagrid('getColumnFields', frozen);
  12. var table = [];
  13. table.push('<table class="datagrid-btable" cellspacing="0" cellpadding="0" border="0"><tbody>');
  14. for(var i=0; i<rows.length; i++) {
  15. // get the class and style attributes for this row
  16. var css = opts.rowStyler ? opts.rowStyler.call(target, i, rows[i]) : '';
  17. var classValue = '';
  18. var styleValue = '';
  19. if (typeof css == 'string'){
  20. styleValue = css;
  21. } else if (css){
  22. classValue = css['class'] || '';
  23. styleValue = css['style'] || '';
  24. }
  25. var cls = 'class="datagrid-row ' + (i % 2 && opts.striped ? 'datagrid-row-alt ' : ' ') + classValue + '"';
  26. var style = styleValue ? 'style="' + styleValue + '"' : '';
  27. var rowId = state.rowIdPrefix + '-' + (frozen?1:2) + '-' + i;
  28. table.push('<tr id="' + rowId + '" datagrid-row-index="' + i + '" ' + cls + ' ' + style + '>');
  29. table.push(this.renderRow.call(this, target, fields, frozen, i, rows[i]));
  30. table.push('</tr>');
  31. table.push('<tr style="display:none;">');
  32. if (frozen){
  33. table.push('<td colspan=' + (fields.length+(opts.rownumbers?1:0)) + ' style="border-right:0">');
  34. } else {
  35. table.push('<td colspan=' + (fields.length) + '>');
  36. }
  37. table.push('<div class="datagrid-row-detail">');
  38. if (frozen){
  39. table.push('&nbsp;');
  40. } else {
  41. table.push(opts.detailFormatter.call(target, i, rows[i]));
  42. }
  43. table.push('</div>');
  44. table.push('</td>');
  45. table.push('</tr>');
  46. }
  47. table.push('</tbody></table>');
  48. $(container).html(table.join(''));
  49. },
  50. renderRow: function(target, fields, frozen, rowIndex, rowData){
  51. var opts = $.data(target, 'datagrid').options;
  52. var cc = [];
  53. if (frozen && opts.rownumbers){
  54. var rownumber = rowIndex + 1;
  55. if (opts.pagination){
  56. rownumber += (opts.pageNumber-1)*opts.pageSize;
  57. }
  58. cc.push('<td class="datagrid-td-rownumber"><div class="datagrid-cell-rownumber">'+rownumber+'</div></td>');
  59. }
  60. for(var i=0; i<fields.length; i++){
  61. var field = fields[i];
  62. var col = $(target).datagrid('getColumnOption', field);
  63. if (col){
  64. var value = rowData[field]; // the field value
  65. var css = col.styler ? (col.styler(value, rowData, rowIndex)||'') : '';
  66. var classValue = '';
  67. var styleValue = '';
  68. if (typeof css == 'string'){
  69. styleValue = css;
  70. } else if (cc){
  71. classValue = css['class'] || '';
  72. styleValue = css['style'] || '';
  73. }
  74. var cls = classValue ? 'class="' + classValue + '"' : '';
  75. var style = col.hidden ? 'style="display:none;' + styleValue + '"' : (styleValue ? 'style="' + styleValue + '"' : '');
  76. cc.push('<td field="' + field + '" ' + cls + ' ' + style + '>');
  77. if (col.checkbox){
  78. style = '';
  79. } else if (col.expander){
  80. style = "text-align:center;height:16px;";
  81. } else {
  82. style = styleValue;
  83. if (col.align){style += ';text-align:' + col.align + ';'}
  84. if (!opts.nowrap){
  85. style += ';white-space:normal;height:auto;';
  86. } else if (opts.autoRowHeight){
  87. style += ';height:auto;';
  88. }
  89. }
  90. cc.push('<div style="' + style + '" ');
  91. if (col.checkbox){
  92. cc.push('class="datagrid-cell-check ');
  93. } else {
  94. cc.push('class="datagrid-cell ' + col.cellClass);
  95. }
  96. cc.push('">');
  97. if (col.checkbox){
  98. cc.push('<input type="checkbox" name="' + field + '" value="' + (value!=undefined ? value : '') + '">');
  99. } else if (col.expander) {
  100. //cc.push('<div style="text-align:center;width:16px;height:16px;">');
  101. cc.push('<span class="datagrid-row-expander datagrid-row-expand" style="display:inline-block;width:16px;height:16px;cursor:pointer;" />');
  102. //cc.push('</div>');
  103. } else if (col.formatter){
  104. cc.push(col.formatter(value, rowData, rowIndex));
  105. } else {
  106. cc.push(value);
  107. }
  108. cc.push('</div>');
  109. cc.push('</td>');
  110. }
  111. }
  112. return cc.join('');
  113. },
  114. insertRow: function(target, index, row){
  115. var opts = $.data(target, 'datagrid').options;
  116. var dc = $.data(target, 'datagrid').dc;
  117. var panel = $(target).datagrid('getPanel');
  118. var view1 = dc.view1;
  119. var view2 = dc.view2;
  120. var isAppend = false;
  121. var rowLength = $(target).datagrid('getRows').length;
  122. if (rowLength == 0){
  123. $(target).datagrid('loadData',{total:1,rows:[row]});
  124. return;
  125. }
  126. if (index == undefined || index == null || index >= rowLength) {
  127. index = rowLength;
  128. isAppend = true;
  129. this.canUpdateDetail = false;
  130. }
  131. $.fn.datagrid.defaults.view.insertRow.call(this, target, index, row);
  132. _insert(true);
  133. _insert(false);
  134. this.canUpdateDetail = true;
  135. function _insert(frozen){
  136. var v = frozen ? view1 : view2;
  137. var tr = v.find('tr[datagrid-row-index='+index+']');
  138. if (isAppend){
  139. var newDetail = tr.next().clone();
  140. tr.insertAfter(tr.next());
  141. } else {
  142. var newDetail = tr.next().next().clone();
  143. }
  144. newDetail.insertAfter(tr);
  145. newDetail.hide();
  146. if (!frozen){
  147. newDetail.find('div.datagrid-row-detail').html(opts.detailFormatter.call(target, index, row));
  148. }
  149. }
  150. },
  151. deleteRow: function(target, index){
  152. var opts = $.data(target, 'datagrid').options;
  153. var dc = $.data(target, 'datagrid').dc;
  154. var tr = opts.finder.getTr(target, index);
  155. tr.next().remove();
  156. $.fn.datagrid.defaults.view.deleteRow.call(this, target, index);
  157. dc.body2.triggerHandler('scroll');
  158. },
  159. updateRow: function(target, rowIndex, row){
  160. var dc = $.data(target, 'datagrid').dc;
  161. var opts = $.data(target, 'datagrid').options;
  162. var cls = $(target).datagrid('getExpander', rowIndex).attr('class');
  163. $.fn.datagrid.defaults.view.updateRow.call(this, target, rowIndex, row);
  164. $(target).datagrid('getExpander', rowIndex).attr('class',cls);
  165. // update the detail content
  166. if (this.canUpdateDetail){
  167. var row = $(target).datagrid('getRows')[rowIndex];
  168. var detail = $(target).datagrid('getRowDetail', rowIndex);
  169. detail.html(opts.detailFormatter.call(target, rowIndex, row));
  170. }
  171. },
  172. bindEvents: function(target){
  173. var state = $.data(target, 'datagrid');
  174. if (state.ss.bindDetailEvents){return;}
  175. state.ss.bindDetailEvents = true;
  176. var dc = state.dc;
  177. var opts = state.options;
  178. var body = dc.body1.add(dc.body2);
  179. var clickHandler = ($.data(body[0],'events')||$._data(body[0],'events')).click[0].handler;
  180. body.unbind('click').bind('click', function(e){
  181. var tt = $(e.target);
  182. var tr = tt.closest('tr.datagrid-row');
  183. if (!tr.length){return}
  184. if (tt.hasClass('datagrid-row-expander')){
  185. var rowIndex = parseInt(tr.attr('datagrid-row-index'));
  186. if (tt.hasClass('datagrid-row-expand')){
  187. $(target).datagrid('expandRow', rowIndex);
  188. } else {
  189. $(target).datagrid('collapseRow', rowIndex);
  190. }
  191. $(target).datagrid('fixRowHeight');
  192. } else {
  193. clickHandler(e);
  194. }
  195. e.stopPropagation();
  196. });
  197. },
  198. onBeforeRender: function(target){
  199. var state = $.data(target, 'datagrid');
  200. var opts = state.options;
  201. var dc = state.dc;
  202. var t = $(target);
  203. var hasExpander = false;
  204. var fields = t.datagrid('getColumnFields',true).concat(t.datagrid('getColumnFields'));
  205. for(var i=0; i<fields.length; i++){
  206. var col = t.datagrid('getColumnOption', fields[i]);
  207. if (col.expander){
  208. hasExpander = true;
  209. break;
  210. }
  211. }
  212. if (!hasExpander){
  213. if (opts.frozenColumns && opts.frozenColumns.length){
  214. opts.frozenColumns[0].splice(0,0,{field:'_expander',expander:true,width:24,resizable:false,fixed:true});
  215. } else {
  216. opts.frozenColumns = [[{field:'_expander',expander:true,width:24,resizable:false,fixed:true}]];
  217. }
  218. var t = dc.view1.children('div.datagrid-header').find('table');
  219. var td = $('<td rowspan="'+opts.frozenColumns.length+'"><div class="datagrid-header-expander" style="width:24px;"></div></td>');
  220. if ($('tr',t).length == 0){
  221. td.wrap('<tr></tr>').parent().appendTo($('tbody',t));
  222. } else if (opts.rownumbers){
  223. td.insertAfter(t.find('td:has(div.datagrid-header-rownumber)'));
  224. } else {
  225. td.prependTo(t.find('tr:first'));
  226. }
  227. }
  228. // if (!state.bindDetailEvents){
  229. // state.bindDetailEvents = true;
  230. // var that = this;
  231. // setTimeout(function(){
  232. // that.bindEvents(target);
  233. // },0);
  234. // }
  235. },
  236. onAfterRender: function(target){
  237. var that = this;
  238. var state = $.data(target, 'datagrid');
  239. var dc = state.dc;
  240. var opts = state.options;
  241. var panel = $(target).datagrid('getPanel');
  242. $.fn.datagrid.defaults.view.onAfterRender.call(this, target);
  243. if (!state.onResizeColumn){
  244. state.onResizeColumn = opts.onResizeColumn;
  245. }
  246. if (!state.onResize){
  247. state.onResize = opts.onResize;
  248. }
  249. function resizeDetails(){
  250. var ht = dc.header2.find('table');
  251. var fr = ht.find('tr.datagrid-filter-row').hide();
  252. var ww = ht.width()-1;
  253. var details = dc.body2.find('>table.datagrid-btable>tbody>tr>td>div.datagrid-row-detail:visible')._outerWidth(ww);
  254. // var details = dc.body2.find('div.datagrid-row-detail:visible')._outerWidth(ww);
  255. details.find('.easyui-fluid').trigger('_resize');
  256. fr.show();
  257. }
  258. opts.onResizeColumn = function(field, width){
  259. if (!opts.fitColumns){
  260. resizeDetails();
  261. }
  262. var rowCount = $(target).datagrid('getRows').length;
  263. for(var i=0; i<rowCount; i++){
  264. $(target).datagrid('fixDetailRowHeight', i);
  265. }
  266. // call the old event code
  267. state.onResizeColumn.call(target, field, width);
  268. };
  269. opts.onResize = function(width, height){
  270. if (opts.fitColumns){
  271. resizeDetails();
  272. }
  273. state.onResize.call(panel, width, height);
  274. };
  275. this.canUpdateDetail = true; // define if to update the detail content when 'updateRow' method is called;
  276. var footer = dc.footer1.add(dc.footer2);
  277. footer.find('span.datagrid-row-expander').css('visibility', 'hidden');
  278. $(target).datagrid('resize');
  279. this.bindEvents(target);
  280. var detail = dc.body1.add(dc.body2).find('div.datagrid-row-detail');
  281. detail.unbind().bind('mouseover mouseout click dblclick contextmenu scroll', function(e){
  282. e.stopPropagation();
  283. });
  284. }
  285. });
  286. $.extend($.fn.datagrid.methods, {
  287. fixDetailRowHeight: function(jq, index){
  288. return jq.each(function(){
  289. var opts = $.data(this, 'datagrid').options;
  290. if (!(opts.rownumbers || (opts.frozenColumns && opts.frozenColumns.length))){
  291. return;
  292. }
  293. var dc = $.data(this, 'datagrid').dc;
  294. var tr1 = opts.finder.getTr(this, index, 'body', 1).next();
  295. var tr2 = opts.finder.getTr(this, index, 'body', 2).next();
  296. // fix the detail row height
  297. if (tr2.is(':visible')){
  298. tr1.css('height', '');
  299. tr2.css('height', '');
  300. var height = Math.max(tr1.height(), tr2.height());
  301. tr1.css('height', height);
  302. tr2.css('height', height);
  303. }
  304. dc.body2.triggerHandler('scroll');
  305. });
  306. },
  307. getExpander: function(jq, index){ // get row expander object
  308. var opts = $.data(jq[0], 'datagrid').options;
  309. return opts.finder.getTr(jq[0], index).find('span.datagrid-row-expander');
  310. },
  311. // get row detail container
  312. getRowDetail: function(jq, index){
  313. var opts = $.data(jq[0], 'datagrid').options;
  314. var tr = opts.finder.getTr(jq[0], index, 'body', 2);
  315. // return tr.next().find('div.datagrid-row-detail');
  316. return tr.next().find('>td>div.datagrid-row-detail');
  317. },
  318. expandRow: function(jq, index){
  319. return jq.each(function(){
  320. var opts = $(this).datagrid('options');
  321. var dc = $.data(this, 'datagrid').dc;
  322. var expander = $(this).datagrid('getExpander', index);
  323. if (expander.hasClass('datagrid-row-expand')){
  324. expander.removeClass('datagrid-row-expand').addClass('datagrid-row-collapse');
  325. var tr1 = opts.finder.getTr(this, index, 'body', 1).next();
  326. var tr2 = opts.finder.getTr(this, index, 'body', 2).next();
  327. tr1.show();
  328. tr2.show();
  329. $(this).datagrid('fixDetailRowHeight', index);
  330. if (opts.onExpandRow){
  331. var row = $(this).datagrid('getRows')[index];
  332. opts.onExpandRow.call(this, index, row);
  333. }
  334. }
  335. });
  336. },
  337. collapseRow: function(jq, index){
  338. return jq.each(function(){
  339. var opts = $(this).datagrid('options');
  340. var dc = $.data(this, 'datagrid').dc;
  341. var expander = $(this).datagrid('getExpander', index);
  342. if (expander.hasClass('datagrid-row-collapse')){
  343. expander.removeClass('datagrid-row-collapse').addClass('datagrid-row-expand');
  344. var tr1 = opts.finder.getTr(this, index, 'body', 1).next();
  345. var tr2 = opts.finder.getTr(this, index, 'body', 2).next();
  346. tr1.hide();
  347. tr2.hide();
  348. dc.body2.triggerHandler('scroll');
  349. if (opts.onCollapseRow){
  350. var row = $(this).datagrid('getRows')[index];
  351. opts.onCollapseRow.call(this, index, row);
  352. }
  353. }
  354. });
  355. }
  356. });
  357. $.extend($.fn.datagrid.methods, {
  358. subgrid: function(jq, conf){
  359. return jq.each(function(){
  360. createGrid(this, conf);
  361. function createGrid(target, conf, prow){
  362. var queryParams = $.extend({}, conf.options.queryParams||{});
  363. queryParams[conf.options.foreignField] = prow ? prow[conf.options.foreignField] : undefined;
  364. $(target).datagrid($.extend({}, conf.options, {
  365. subgrid: conf.subgrid,
  366. view: (conf.subgrid ? detailview : undefined),
  367. queryParams: queryParams,
  368. detailFormatter: function(index, row){
  369. return '<div><table class="datagrid-subgrid"></table></div>';
  370. },
  371. onExpandRow: function(index, row){
  372. var opts = $(this).datagrid('options');
  373. var rd = $(this).datagrid('getRowDetail', index);
  374. var dg = getSubGrid(rd);
  375. if (!dg.data('datagrid')){
  376. createGrid(dg[0], opts.subgrid, row);
  377. }
  378. rd.find('.easyui-fluid').trigger('_resize');
  379. setHeight(this, index);
  380. if (conf.options.onExpandRow){
  381. conf.options.onExpandRow.call(this, index, row);
  382. }
  383. },
  384. onCollapseRow: function(index, row){
  385. setHeight(this, index);
  386. if (conf.options.onCollapseRow){
  387. conf.options.onCollapseRow.call(this, index, row);
  388. }
  389. },
  390. onResize: function(){
  391. var dg = $(this).children('div.datagrid-view').children('table')
  392. setParentHeight(this);
  393. },
  394. onResizeColumn: function(field, width){
  395. setParentHeight(this);
  396. if (conf.options.onResizeColumn){
  397. conf.options.onResizeColumn.call(this, field, width);
  398. }
  399. },
  400. onLoadSuccess: function(data){
  401. setParentHeight(this);
  402. if (conf.options.onLoadSuccess){
  403. conf.options.onLoadSuccess.call(this, data);
  404. }
  405. }
  406. }));
  407. }
  408. function getSubGrid(rowDetail){
  409. var div = $(rowDetail).children('div');
  410. if (div.children('div.datagrid').length){
  411. return div.find('>div.datagrid>div.panel-body>div.datagrid-view>table.datagrid-subgrid');
  412. } else {
  413. return div.find('>table.datagrid-subgrid');
  414. }
  415. }
  416. function setParentHeight(target){
  417. var tr = $(target).closest('div.datagrid-row-detail').closest('tr').prev();
  418. if (tr.length){
  419. var index = parseInt(tr.attr('datagrid-row-index'));
  420. var dg = tr.closest('div.datagrid-view').children('table');
  421. setHeight(dg[0], index);
  422. }
  423. }
  424. function setHeight(target, index){
  425. $(target).datagrid('fixDetailRowHeight', index);
  426. $(target).datagrid('fixRowHeight', index);
  427. var tr = $(target).closest('div.datagrid-row-detail').closest('tr').prev();
  428. if (tr.length){
  429. var index = parseInt(tr.attr('datagrid-row-index'));
  430. var dg = tr.closest('div.datagrid-view').children('table');
  431. setHeight(dg[0], index);
  432. }
  433. }
  434. });
  435. },
  436. getParentGrid: function(jq){
  437. var detail = jq.closest('div.datagrid-row-detail');
  438. if (detail.length){
  439. return detail.closest('.datagrid-view').children('.datagrid-f');
  440. } else {
  441. return null;
  442. }
  443. },
  444. getParentRowIndex: function(jq){
  445. var detail = jq.closest('div.datagrid-row-detail');
  446. if (detail.length){
  447. var tr = detail.closest('tr').prev();
  448. return parseInt(tr.attr('datagrid-row-index'));
  449. } else {
  450. return -1;
  451. }
  452. }
  453. });