datagrid-groupview.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. $.extend($.fn.datagrid.defaults, {
  2. groupHeight: 25,
  3. expanderWidth: 30,
  4. groupStyler: function(value,rows){return ''}
  5. });
  6. var groupview = $.extend({}, $.fn.datagrid.defaults.view, {
  7. render: function(target, container, frozen){
  8. var table = [];
  9. var groups = this.groups;
  10. for(var i=0; i<groups.length; i++){
  11. table.push(this.renderGroup.call(this, target, i, groups[i], frozen));
  12. }
  13. $(container).html(table.join(''));
  14. },
  15. renderGroup: function(target, groupIndex, group, frozen){
  16. var state = $.data(target, 'datagrid');
  17. var opts = state.options;
  18. var fields = $(target).datagrid('getColumnFields', frozen);
  19. var hasFrozen = opts.frozenColumns && opts.frozenColumns.length;
  20. if (frozen){
  21. if (!(opts.rownumbers || hasFrozen)){
  22. return '';
  23. }
  24. }
  25. var table = [];
  26. var css = opts.groupStyler.call(target, group.value, group.rows);
  27. var cs = parseCss(css, 'datagrid-group');
  28. table.push('<div group-index=' + groupIndex + ' ' + cs + '>');
  29. if ((frozen && (opts.rownumbers || opts.frozenColumns.length)) ||
  30. (!frozen && !(opts.rownumbers || opts.frozenColumns.length))){
  31. table.push('<span class="datagrid-group-expander">');
  32. table.push('<span class="datagrid-row-expander datagrid-row-collapse">&nbsp;</span>');
  33. table.push('</span>');
  34. }
  35. if ((frozen && hasFrozen) || (!frozen)){
  36. table.push('<span class="datagrid-group-title">');
  37. table.push(opts.groupFormatter.call(target, group.value, group.rows));
  38. table.push('</span>');
  39. }
  40. table.push('</div>');
  41. table.push('<table class="datagrid-btable" cellspacing="0" cellpadding="0" border="0"><tbody>');
  42. var index = group.startIndex;
  43. for(var j=0; j<group.rows.length; j++) {
  44. var css = opts.rowStyler ? opts.rowStyler.call(target, index, group.rows[j]) : '';
  45. var classValue = '';
  46. var styleValue = '';
  47. if (typeof css == 'string'){
  48. styleValue = css;
  49. } else if (css){
  50. classValue = css['class'] || '';
  51. styleValue = css['style'] || '';
  52. }
  53. var cls = 'class="datagrid-row ' + (index % 2 && opts.striped ? 'datagrid-row-alt ' : ' ') + classValue + '"';
  54. var style = styleValue ? 'style="' + styleValue + '"' : '';
  55. var rowId = state.rowIdPrefix + '-' + (frozen?1:2) + '-' + index;
  56. table.push('<tr id="' + rowId + '" datagrid-row-index="' + index + '" ' + cls + ' ' + style + '>');
  57. table.push(this.renderRow.call(this, target, fields, frozen, index, group.rows[j]));
  58. table.push('</tr>');
  59. index++;
  60. }
  61. table.push('</tbody></table>');
  62. return table.join('');
  63. function parseCss(css, cls){
  64. var classValue = '';
  65. var styleValue = '';
  66. if (typeof css == 'string'){
  67. styleValue = css;
  68. } else if (css){
  69. classValue = css['class'] || '';
  70. styleValue = css['style'] || '';
  71. }
  72. return 'class="' + cls + (classValue ? ' '+classValue : '') + '" ' +
  73. 'style="' + styleValue + '"';
  74. }
  75. },
  76. bindEvents: function(target){
  77. var state = $.data(target, 'datagrid');
  78. var dc = state.dc;
  79. var body = dc.body1.add(dc.body2);
  80. var clickHandler = ($.data(body[0],'events')||$._data(body[0],'events')).click[0].handler;
  81. body.unbind('click').bind('click', function(e){
  82. var tt = $(e.target);
  83. var expander = tt.closest('span.datagrid-row-expander');
  84. if (expander.length){
  85. var gindex = expander.closest('div.datagrid-group').attr('group-index');
  86. if (expander.hasClass('datagrid-row-collapse')){
  87. $(target).datagrid('collapseGroup', gindex);
  88. } else {
  89. $(target).datagrid('expandGroup', gindex);
  90. }
  91. } else {
  92. clickHandler(e);
  93. }
  94. e.stopPropagation();
  95. });
  96. },
  97. onBeforeRender: function(target, rows){
  98. var state = $.data(target, 'datagrid');
  99. var opts = state.options;
  100. initCss();
  101. var groups = [];
  102. for(var i=0; i<rows.length; i++){
  103. var row = rows[i];
  104. var group = getGroup(row[opts.groupField]);
  105. if (!group){
  106. group = {
  107. value: row[opts.groupField],
  108. rows: [row]
  109. };
  110. groups.push(group);
  111. } else {
  112. group.rows.push(row);
  113. }
  114. }
  115. var index = 0;
  116. var newRows = [];
  117. for(var i=0; i<groups.length; i++){
  118. var group = groups[i];
  119. group.startIndex = index;
  120. index += group.rows.length;
  121. newRows = newRows.concat(group.rows);
  122. }
  123. state.data.rows = newRows;
  124. this.groups = groups;
  125. var that = this;
  126. setTimeout(function(){
  127. that.bindEvents(target);
  128. },0);
  129. function getGroup(value){
  130. for(var i=0; i<groups.length; i++){
  131. var group = groups[i];
  132. if (group.value == value){
  133. return group;
  134. }
  135. }
  136. return null;
  137. }
  138. function initCss(){
  139. if (!$('#datagrid-group-style').length){
  140. $('head').append(
  141. '<style id="datagrid-group-style">' +
  142. '.datagrid-group{height:'+opts.groupHeight+'px;overflow:hidden;font-weight:bold;border-bottom:1px solid #ccc;white-space:nowrap;word-break:normal;}' +
  143. '.datagrid-group-title,.datagrid-group-expander{display:inline-block;vertical-align:bottom;height:100%;line-height:'+opts.groupHeight+'px;padding:0 4px;}' +
  144. '.datagrid-group-title{position:relative;}' +
  145. '.datagrid-group-expander{width:'+opts.expanderWidth+'px;text-align:center;padding:0}' +
  146. '.datagrid-row-expander{margin:'+Math.floor((opts.groupHeight-16)/2)+'px 0;display:inline-block;width:16px;height:16px;cursor:pointer}' +
  147. '</style>'
  148. );
  149. }
  150. }
  151. },
  152. onAfterRender: function(target){
  153. $.fn.datagrid.defaults.view.onAfterRender.call(this, target);
  154. var view = this;
  155. var state = $.data(target, 'datagrid');
  156. var opts = state.options;
  157. if (!state.onResizeColumn){
  158. state.onResizeColumn = opts.onResizeColumn;
  159. }
  160. if (!state.onResize){
  161. state.onResize = opts.onResize;
  162. }
  163. opts.onResizeColumn = function(field, width){
  164. view.resizeGroup(target);
  165. state.onResizeColumn.call(target, field, width);
  166. }
  167. opts.onResize = function(width, height){
  168. view.resizeGroup(target);
  169. state.onResize.call($(target).datagrid('getPanel')[0], width, height);
  170. }
  171. view.resizeGroup(target);
  172. }
  173. });
  174. $.extend($.fn.datagrid.methods, {
  175. groups:function(jq){
  176. return jq.datagrid('options').view.groups;
  177. },
  178. expandGroup:function(jq, groupIndex){
  179. return jq.each(function(){
  180. var view = $.data(this, 'datagrid').dc.view;
  181. var group = view.find(groupIndex!=undefined ? 'div.datagrid-group[group-index="'+groupIndex+'"]' : 'div.datagrid-group');
  182. var expander = group.find('span.datagrid-row-expander');
  183. if (expander.hasClass('datagrid-row-expand')){
  184. expander.removeClass('datagrid-row-expand').addClass('datagrid-row-collapse');
  185. group.next('table').show();
  186. }
  187. $(this).datagrid('fixRowHeight');
  188. });
  189. },
  190. collapseGroup:function(jq, groupIndex){
  191. return jq.each(function(){
  192. var view = $.data(this, 'datagrid').dc.view;
  193. var group = view.find(groupIndex!=undefined ? 'div.datagrid-group[group-index="'+groupIndex+'"]' : 'div.datagrid-group');
  194. var expander = group.find('span.datagrid-row-expander');
  195. if (expander.hasClass('datagrid-row-collapse')){
  196. expander.removeClass('datagrid-row-collapse').addClass('datagrid-row-expand');
  197. group.next('table').hide();
  198. }
  199. $(this).datagrid('fixRowHeight');
  200. });
  201. },
  202. scrollToGroup: function(jq, groupIndex){
  203. return jq.each(function(){
  204. var state = $.data(this, 'datagrid');
  205. var dc = state.dc;
  206. var grow = dc.body2.children('div.datagrid-group[group-index="'+groupIndex+'"]');
  207. if (grow.length){
  208. var groupHeight = grow.outerHeight();
  209. var headerHeight = dc.view2.children('div.datagrid-header')._outerHeight();
  210. var frozenHeight = dc.body2.outerHeight(true) - dc.body2.outerHeight();
  211. var top = grow.position().top - headerHeight - frozenHeight;
  212. if (top < 0){
  213. dc.body2.scrollTop(dc.body2.scrollTop() + top);
  214. } else if (top + groupHeight > dc.body2.height() - 18){
  215. dc.body2.scrollTop(dc.body2.scrollTop() + top + groupHeight - dc.body2.height() + 18);
  216. }
  217. }
  218. });
  219. }
  220. });
  221. $.extend(groupview, {
  222. refreshGroupTitle: function(target, groupIndex){
  223. var state = $.data(target, 'datagrid');
  224. var opts = state.options;
  225. var dc = state.dc;
  226. var group = this.groups[groupIndex];
  227. var span = dc.body1.add(dc.body2).children('div.datagrid-group[group-index=' + groupIndex + ']').find('span.datagrid-group-title');
  228. span.html(opts.groupFormatter.call(target, group.value, group.rows));
  229. },
  230. resizeGroup: function(target, groupIndex){
  231. var state = $.data(target, 'datagrid');
  232. var dc = state.dc;
  233. var ht = dc.header2.find('table');
  234. var fr = ht.find('tr.datagrid-filter-row').hide();
  235. var ww = ht.width();
  236. if (groupIndex == undefined){
  237. var groupHeader = dc.body2.children('div.datagrid-group');
  238. } else {
  239. var groupHeader = dc.body2.children('div.datagrid-group[group-index=' + groupIndex + ']');
  240. }
  241. groupHeader._outerWidth(ww);
  242. var opts = state.options;
  243. if (opts.frozenColumns && opts.frozenColumns.length){
  244. var width = dc.view1.width() - opts.expanderWidth;
  245. var isRtl = dc.view1.css('direction').toLowerCase()=='rtl';
  246. groupHeader.find('.datagrid-group-title').css(isRtl?'right':'left', -width+'px');
  247. }
  248. fr.show();
  249. },
  250. insertRow: function(target, index, row){
  251. var state = $.data(target, 'datagrid');
  252. var opts = state.options;
  253. var dc = state.dc;
  254. var group = null;
  255. var groupIndex;
  256. if (!state.data.rows.length){
  257. $(target).datagrid('loadData', [row]);
  258. return;
  259. }
  260. for(var i=0; i<this.groups.length; i++){
  261. if (this.groups[i].value == row[opts.groupField]){
  262. group = this.groups[i];
  263. groupIndex = i;
  264. break;
  265. }
  266. }
  267. if (group){
  268. if (index == undefined || index == null){
  269. index = state.data.rows.length;
  270. }
  271. if (index < group.startIndex){
  272. index = group.startIndex;
  273. } else if (index > group.startIndex + group.rows.length){
  274. index = group.startIndex + group.rows.length;
  275. }
  276. $.fn.datagrid.defaults.view.insertRow.call(this, target, index, row);
  277. if (index >= group.startIndex + group.rows.length){
  278. _moveTr(index, true);
  279. _moveTr(index, false);
  280. }
  281. group.rows.splice(index - group.startIndex, 0, row);
  282. } else {
  283. group = {
  284. value: row[opts.groupField],
  285. rows: [row],
  286. startIndex: state.data.rows.length
  287. }
  288. groupIndex = this.groups.length;
  289. dc.body1.append(this.renderGroup.call(this, target, groupIndex, group, true));
  290. dc.body2.append(this.renderGroup.call(this, target, groupIndex, group, false));
  291. this.groups.push(group);
  292. state.data.rows.push(row);
  293. }
  294. this.refreshGroupTitle(target, groupIndex);
  295. this.resizeGroup(target);
  296. function _moveTr(index,frozen){
  297. var serno = frozen?1:2;
  298. var prevTr = opts.finder.getTr(target, index-1, 'body', serno);
  299. var tr = opts.finder.getTr(target, index, 'body', serno);
  300. tr.insertAfter(prevTr);
  301. }
  302. },
  303. updateRow: function(target, index, row){
  304. var opts = $.data(target, 'datagrid').options;
  305. $.fn.datagrid.defaults.view.updateRow.call(this, target, index, row);
  306. var tb = opts.finder.getTr(target, index, 'body', 2).closest('table.datagrid-btable');
  307. var groupIndex = parseInt(tb.prev().attr('group-index'));
  308. this.refreshGroupTitle(target, groupIndex);
  309. },
  310. deleteRow: function(target, index){
  311. var state = $.data(target, 'datagrid');
  312. var opts = state.options;
  313. var dc = state.dc;
  314. var body = dc.body1.add(dc.body2);
  315. var tb = opts.finder.getTr(target, index, 'body', 2).closest('table.datagrid-btable');
  316. var groupIndex = parseInt(tb.prev().attr('group-index'));
  317. $.fn.datagrid.defaults.view.deleteRow.call(this, target, index);
  318. var group = this.groups[groupIndex];
  319. if (group.rows.length > 1){
  320. group.rows.splice(index-group.startIndex, 1);
  321. this.refreshGroupTitle(target, groupIndex);
  322. } else {
  323. body.children('div.datagrid-group[group-index='+groupIndex+']').remove();
  324. for(var i=groupIndex+1; i<this.groups.length; i++){
  325. body.children('div.datagrid-group[group-index='+i+']').attr('group-index', i-1);
  326. }
  327. this.groups.splice(groupIndex, 1);
  328. }
  329. var index = 0;
  330. for(var i=0; i<this.groups.length; i++){
  331. var group = this.groups[i];
  332. group.startIndex = index;
  333. index += group.rows.length;
  334. }
  335. }
  336. });