jquery.propertygrid.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525
  1. /**
  2. * EasyUI for jQuery 1.5.5.6
  3. *
  4. * Copyright (c) 2009-2018 www.jeasyui.com. All rights reserved.
  5. *
  6. * Licensed under the freeware license: http://www.jeasyui.com/license_freeware.php
  7. * To use it on other terms please contact us: info@jeasyui.com
  8. *
  9. */
  10. /**
  11. * propertygrid - EasyUI for jQuery
  12. *
  13. * Dependencies:
  14. * datagrid
  15. *
  16. */
  17. (function($){
  18. var currTarget;
  19. $(document).unbind('.propertygrid').bind('mousedown.propertygrid', function(e){
  20. var p = $(e.target).closest('div.datagrid-view,div.combo-panel');
  21. if (p.length){return;}
  22. stopEditing(currTarget);
  23. currTarget = undefined;
  24. });
  25. function buildGrid(target){
  26. var state = $.data(target, 'propertygrid');
  27. var opts = $.data(target, 'propertygrid').options;
  28. $(target).datagrid($.extend({}, opts, {
  29. cls:'propertygrid',
  30. view:(opts.showGroup ? opts.groupView : opts.view),
  31. onBeforeEdit:function(index, row){
  32. if (opts.onBeforeEdit.call(target, index, row) == false){return false;}
  33. var dg = $(this);
  34. var row = dg.datagrid('getRows')[index];
  35. var col = dg.datagrid('getColumnOption', 'value');
  36. col.editor = row.editor;
  37. },
  38. onClickCell:function(index, field, value){
  39. if (currTarget != this){
  40. stopEditing(currTarget);
  41. currTarget = this;
  42. }
  43. if (opts.editIndex != index){
  44. stopEditing(currTarget);
  45. $(this).datagrid('beginEdit', index);
  46. var ed = $(this).datagrid('getEditor', {index:index,field:field});
  47. if (!ed){
  48. ed = $(this).datagrid('getEditor', {index:index,field:'value'});
  49. }
  50. if (ed){
  51. var t = $(ed.target);
  52. var input = t.data('textbox') ? t.textbox('textbox') : t;
  53. input.focus();
  54. opts.editIndex = index;
  55. }
  56. }
  57. opts.onClickCell.call(target, index, field, value);
  58. },
  59. loadFilter:function(data){
  60. stopEditing(this);
  61. return opts.loadFilter.call(this, data);
  62. }
  63. }));
  64. }
  65. function stopEditing(target){
  66. var t = $(target);
  67. if (!t.length){return}
  68. var opts = $.data(target, 'propertygrid').options;
  69. opts.finder.getTr(target, null, 'editing').each(function(){
  70. var index = parseInt($(this).attr('datagrid-row-index'));
  71. if (t.datagrid('validateRow', index)){
  72. t.datagrid('endEdit', index);
  73. } else {
  74. t.datagrid('cancelEdit', index);
  75. }
  76. });
  77. opts.editIndex = undefined;
  78. }
  79. $.fn.propertygrid = function(options, param){
  80. if (typeof options == 'string'){
  81. var method = $.fn.propertygrid.methods[options];
  82. if (method){
  83. return method(this, param);
  84. } else {
  85. return this.datagrid(options, param);
  86. }
  87. }
  88. options = options || {};
  89. return this.each(function(){
  90. var state = $.data(this, 'propertygrid');
  91. if (state){
  92. $.extend(state.options, options);
  93. } else {
  94. var opts = $.extend({}, $.fn.propertygrid.defaults, $.fn.propertygrid.parseOptions(this), options);
  95. opts.frozenColumns = $.extend(true, [], opts.frozenColumns);
  96. opts.columns = $.extend(true, [], opts.columns);
  97. $.data(this, 'propertygrid', {
  98. options: opts
  99. });
  100. }
  101. buildGrid(this);
  102. });
  103. }
  104. $.fn.propertygrid.methods = {
  105. options: function(jq){
  106. return $.data(jq[0], 'propertygrid').options;
  107. }
  108. };
  109. $.fn.propertygrid.parseOptions = function(target){
  110. return $.extend({}, $.fn.datagrid.parseOptions(target), $.parser.parseOptions(target,[{showGroup:'boolean'}]));
  111. };
  112. // the group view definition
  113. var groupview = $.extend({}, $.fn.datagrid.defaults.view, {
  114. render: function(target, container, frozen){
  115. var table = [];
  116. var groups = this.groups;
  117. for(var i=0; i<groups.length; i++){
  118. table.push(this.renderGroup.call(this, target, i, groups[i], frozen));
  119. }
  120. $(container).html(table.join(''));
  121. },
  122. renderGroup: function(target, groupIndex, group, frozen){
  123. var state = $.data(target, 'datagrid');
  124. var opts = state.options;
  125. var fields = $(target).datagrid('getColumnFields', frozen);
  126. var hasFrozen = opts.frozenColumns && opts.frozenColumns.length;
  127. if (frozen){
  128. if (!(opts.rownumbers || hasFrozen)){
  129. return '';
  130. }
  131. }
  132. var table = [];
  133. var css = opts.groupStyler.call(target, group.value, group.rows);
  134. var cs = parseCss(css, 'datagrid-group');
  135. table.push('<div group-index=' + groupIndex + ' ' + cs + '>');
  136. if ((frozen && (opts.rownumbers || opts.frozenColumns.length)) ||
  137. (!frozen && !(opts.rownumbers || opts.frozenColumns.length))){
  138. table.push('<span class="datagrid-group-expander">');
  139. table.push('<span class="datagrid-row-expander datagrid-row-collapse">&nbsp;</span>');
  140. table.push('</span>');
  141. }
  142. if ((frozen && hasFrozen) || (!frozen)){
  143. table.push('<span class="datagrid-group-title">');
  144. table.push(opts.groupFormatter.call(target, group.value, group.rows));
  145. table.push('</span>');
  146. }
  147. table.push('</div>');
  148. table.push('<table class="datagrid-btable" cellspacing="0" cellpadding="0" border="0"><tbody>');
  149. var index = group.startIndex;
  150. for(var j=0; j<group.rows.length; j++) {
  151. var css = opts.rowStyler ? opts.rowStyler.call(target, index, group.rows[j]) : '';
  152. var classValue = '';
  153. var styleValue = '';
  154. if (typeof css == 'string'){
  155. styleValue = css;
  156. } else if (css){
  157. classValue = css['class'] || '';
  158. styleValue = css['style'] || '';
  159. }
  160. var cls = 'class="datagrid-row ' + (index % 2 && opts.striped ? 'datagrid-row-alt ' : ' ') + classValue + '"';
  161. var style = styleValue ? 'style="' + styleValue + '"' : '';
  162. var rowId = state.rowIdPrefix + '-' + (frozen?1:2) + '-' + index;
  163. table.push('<tr id="' + rowId + '" datagrid-row-index="' + index + '" ' + cls + ' ' + style + '>');
  164. table.push(this.renderRow.call(this, target, fields, frozen, index, group.rows[j]));
  165. table.push('</tr>');
  166. index++;
  167. }
  168. table.push('</tbody></table>');
  169. return table.join('');
  170. function parseCss(css, cls){
  171. var classValue = '';
  172. var styleValue = '';
  173. if (typeof css == 'string'){
  174. styleValue = css;
  175. } else if (css){
  176. classValue = css['class'] || '';
  177. styleValue = css['style'] || '';
  178. }
  179. return 'class="' + cls + (classValue ? ' '+classValue : '') + '" ' +
  180. 'style="' + styleValue + '"';
  181. }
  182. },
  183. bindEvents: function(target){
  184. var state = $.data(target, 'datagrid');
  185. var dc = state.dc;
  186. var body = dc.body1.add(dc.body2);
  187. var clickHandler = ($.data(body[0],'events')||$._data(body[0],'events')).click[0].handler;
  188. body.unbind('click').bind('click', function(e){
  189. var tt = $(e.target);
  190. var expander = tt.closest('span.datagrid-row-expander');
  191. if (expander.length){
  192. var gindex = expander.closest('div.datagrid-group').attr('group-index');
  193. if (expander.hasClass('datagrid-row-collapse')){
  194. $(target).datagrid('collapseGroup', gindex);
  195. } else {
  196. $(target).datagrid('expandGroup', gindex);
  197. }
  198. } else {
  199. clickHandler(e);
  200. }
  201. e.stopPropagation();
  202. });
  203. },
  204. onBeforeRender: function(target, rows){
  205. var state = $.data(target, 'datagrid');
  206. var opts = state.options;
  207. initCss();
  208. var groups = [];
  209. for(var i=0; i<rows.length; i++){
  210. var row = rows[i];
  211. var group = getGroup(row[opts.groupField]);
  212. if (!group){
  213. group = {
  214. value: row[opts.groupField],
  215. rows: [row]
  216. };
  217. groups.push(group);
  218. } else {
  219. group.rows.push(row);
  220. }
  221. }
  222. var index = 0;
  223. var newRows = [];
  224. for(var i=0; i<groups.length; i++){
  225. var group = groups[i];
  226. group.startIndex = index;
  227. index += group.rows.length;
  228. newRows = newRows.concat(group.rows);
  229. }
  230. state.data.rows = newRows;
  231. this.groups = groups;
  232. var that = this;
  233. setTimeout(function(){
  234. that.bindEvents(target);
  235. },0);
  236. function getGroup(value){
  237. for(var i=0; i<groups.length; i++){
  238. var group = groups[i];
  239. if (group.value == value){
  240. return group;
  241. }
  242. }
  243. return null;
  244. }
  245. function initCss(){
  246. if (!$('#datagrid-group-style').length){
  247. $('head').append(
  248. '<style id="datagrid-group-style">' +
  249. '.datagrid-group{height:'+opts.groupHeight+'px;overflow:hidden;font-weight:bold;border-bottom:1px solid #ccc;white-space:nowrap;word-break:normal;}' +
  250. '.datagrid-group-title,.datagrid-group-expander{display:inline-block;vertical-align:bottom;height:100%;line-height:'+opts.groupHeight+'px;padding:0 4px;}' +
  251. '.datagrid-group-title{position:relative;}' +
  252. '.datagrid-group-expander{width:'+opts.expanderWidth+'px;text-align:center;padding:0}' +
  253. '.datagrid-row-expander{margin:'+Math.floor((opts.groupHeight-16)/2)+'px 0;display:inline-block;width:16px;height:16px;cursor:pointer}' +
  254. '</style>'
  255. );
  256. }
  257. }
  258. },
  259. onAfterRender: function(target){
  260. $.fn.datagrid.defaults.view.onAfterRender.call(this, target);
  261. var view = this;
  262. var state = $.data(target, 'datagrid');
  263. var opts = state.options;
  264. if (!state.onResizeColumn){
  265. state.onResizeColumn = opts.onResizeColumn;
  266. }
  267. if (!state.onResize){
  268. state.onResize = opts.onResize;
  269. }
  270. opts.onResizeColumn = function(field, width){
  271. view.resizeGroup(target);
  272. state.onResizeColumn.call(target, field, width);
  273. }
  274. opts.onResize = function(width, height){
  275. view.resizeGroup(target);
  276. state.onResize.call($(target).datagrid('getPanel')[0], width, height);
  277. }
  278. view.resizeGroup(target);
  279. }
  280. });
  281. $.extend($.fn.datagrid.methods, {
  282. groups:function(jq){
  283. return jq.datagrid('options').view.groups;
  284. },
  285. expandGroup:function(jq, groupIndex){
  286. return jq.each(function(){
  287. var opts = $(this).datagrid('options');
  288. var view = $.data(this, 'datagrid').dc.view;
  289. var group = view.find(groupIndex!=undefined ? 'div.datagrid-group[group-index="'+groupIndex+'"]' : 'div.datagrid-group');
  290. var expander = group.find('span.datagrid-row-expander');
  291. if (expander.hasClass('datagrid-row-expand')){
  292. expander.removeClass('datagrid-row-expand').addClass('datagrid-row-collapse');
  293. group.next('table').show();
  294. }
  295. $(this).datagrid('fixRowHeight');
  296. if (opts.onExpandGroup){
  297. opts.onExpandGroup.call(this, groupIndex);
  298. }
  299. });
  300. },
  301. collapseGroup:function(jq, groupIndex){
  302. return jq.each(function(){
  303. var opts = $(this).datagrid('options');
  304. var view = $.data(this, 'datagrid').dc.view;
  305. var group = view.find(groupIndex!=undefined ? 'div.datagrid-group[group-index="'+groupIndex+'"]' : 'div.datagrid-group');
  306. var expander = group.find('span.datagrid-row-expander');
  307. if (expander.hasClass('datagrid-row-collapse')){
  308. expander.removeClass('datagrid-row-collapse').addClass('datagrid-row-expand');
  309. group.next('table').hide();
  310. }
  311. $(this).datagrid('fixRowHeight');
  312. if (opts.onCollapseGroup){
  313. opts.onCollapseGroup.call(this, groupIndex);
  314. }
  315. });
  316. },
  317. scrollToGroup: function(jq, groupIndex){
  318. return jq.each(function(){
  319. var state = $.data(this, 'datagrid');
  320. var dc = state.dc;
  321. var grow = dc.body2.children('div.datagrid-group[group-index="'+groupIndex+'"]');
  322. if (grow.length){
  323. var groupHeight = grow.outerHeight();
  324. var headerHeight = dc.view2.children('div.datagrid-header')._outerHeight();
  325. var frozenHeight = dc.body2.outerHeight(true) - dc.body2.outerHeight();
  326. var top = grow.position().top - headerHeight - frozenHeight;
  327. if (top < 0){
  328. dc.body2.scrollTop(dc.body2.scrollTop() + top);
  329. } else if (top + groupHeight > dc.body2.height() - 18){
  330. dc.body2.scrollTop(dc.body2.scrollTop() + top + groupHeight - dc.body2.height() + 18);
  331. }
  332. }
  333. });
  334. }
  335. });
  336. $.extend(groupview, {
  337. refreshGroupTitle: function(target, groupIndex){
  338. var state = $.data(target, 'datagrid');
  339. var opts = state.options;
  340. var dc = state.dc;
  341. var group = this.groups[groupIndex];
  342. var span = dc.body1.add(dc.body2).children('div.datagrid-group[group-index=' + groupIndex + ']').find('span.datagrid-group-title');
  343. span.html(opts.groupFormatter.call(target, group.value, group.rows));
  344. },
  345. resizeGroup: function(target, groupIndex){
  346. var state = $.data(target, 'datagrid');
  347. var dc = state.dc;
  348. var ht = dc.header2.find('table');
  349. var fr = ht.find('tr.datagrid-filter-row').hide();
  350. var ww = ht.width();
  351. if (groupIndex == undefined){
  352. var groupHeader = dc.body2.children('div.datagrid-group');
  353. } else {
  354. var groupHeader = dc.body2.children('div.datagrid-group[group-index=' + groupIndex + ']');
  355. }
  356. groupHeader._outerWidth(ww);
  357. var opts = state.options;
  358. if (opts.frozenColumns && opts.frozenColumns.length){
  359. var width = dc.view1.width() - opts.expanderWidth;
  360. var isRtl = dc.view1.css('direction').toLowerCase()=='rtl';
  361. groupHeader.find('.datagrid-group-title').css(isRtl?'right':'left', -width+'px');
  362. }
  363. if (fr.length){
  364. if (opts.showFilterBar){
  365. fr.show();
  366. }
  367. }
  368. // fr.show();
  369. },
  370. insertRow: function(target, index, row){
  371. var state = $.data(target, 'datagrid');
  372. var opts = state.options;
  373. var dc = state.dc;
  374. var group = null;
  375. var groupIndex;
  376. if (!state.data.rows.length){
  377. $(target).datagrid('loadData', [row]);
  378. return;
  379. }
  380. for(var i=0; i<this.groups.length; i++){
  381. if (this.groups[i].value == row[opts.groupField]){
  382. group = this.groups[i];
  383. groupIndex = i;
  384. break;
  385. }
  386. }
  387. if (group){
  388. if (index == undefined || index == null){
  389. index = state.data.rows.length;
  390. }
  391. if (index < group.startIndex){
  392. index = group.startIndex;
  393. } else if (index > group.startIndex + group.rows.length){
  394. index = group.startIndex + group.rows.length;
  395. }
  396. $.fn.datagrid.defaults.view.insertRow.call(this, target, index, row);
  397. if (index >= group.startIndex + group.rows.length){
  398. _moveTr(index, true);
  399. _moveTr(index, false);
  400. }
  401. group.rows.splice(index - group.startIndex, 0, row);
  402. } else {
  403. group = {
  404. value: row[opts.groupField],
  405. rows: [row],
  406. startIndex: state.data.rows.length
  407. }
  408. groupIndex = this.groups.length;
  409. dc.body1.append(this.renderGroup.call(this, target, groupIndex, group, true));
  410. dc.body2.append(this.renderGroup.call(this, target, groupIndex, group, false));
  411. this.groups.push(group);
  412. state.data.rows.push(row);
  413. }
  414. this.setGroupIndex(target);
  415. this.refreshGroupTitle(target, groupIndex);
  416. this.resizeGroup(target);
  417. function _moveTr(index,frozen){
  418. var serno = frozen?1:2;
  419. var prevTr = opts.finder.getTr(target, index-1, 'body', serno);
  420. var tr = opts.finder.getTr(target, index, 'body', serno);
  421. tr.insertAfter(prevTr);
  422. }
  423. },
  424. updateRow: function(target, index, row){
  425. var opts = $.data(target, 'datagrid').options;
  426. $.fn.datagrid.defaults.view.updateRow.call(this, target, index, row);
  427. var tb = opts.finder.getTr(target, index, 'body', 2).closest('table.datagrid-btable');
  428. var groupIndex = parseInt(tb.prev().attr('group-index'));
  429. this.refreshGroupTitle(target, groupIndex);
  430. },
  431. deleteRow: function(target, index){
  432. var state = $.data(target, 'datagrid');
  433. var opts = state.options;
  434. var dc = state.dc;
  435. var body = dc.body1.add(dc.body2);
  436. var tb = opts.finder.getTr(target, index, 'body', 2).closest('table.datagrid-btable');
  437. var groupIndex = parseInt(tb.prev().attr('group-index'));
  438. $.fn.datagrid.defaults.view.deleteRow.call(this, target, index);
  439. var group = this.groups[groupIndex];
  440. if (group.rows.length > 1){
  441. group.rows.splice(index-group.startIndex, 1);
  442. this.refreshGroupTitle(target, groupIndex);
  443. } else {
  444. body.children('div.datagrid-group[group-index='+groupIndex+']').remove();
  445. for(var i=groupIndex+1; i<this.groups.length; i++){
  446. body.children('div.datagrid-group[group-index='+i+']').attr('group-index', i-1);
  447. }
  448. this.groups.splice(groupIndex, 1);
  449. }
  450. this.setGroupIndex(target);
  451. },
  452. setGroupIndex: function(target){
  453. var index = 0;
  454. for(var i=0; i<this.groups.length; i++){
  455. var group = this.groups[i];
  456. group.startIndex = index;
  457. index += group.rows.length;
  458. }
  459. }
  460. });
  461. // end of group view definition
  462. $.fn.propertygrid.defaults = $.extend({}, $.fn.datagrid.defaults, {
  463. groupHeight:28,
  464. expanderWidth:20,
  465. singleSelect:true,
  466. remoteSort:false,
  467. fitColumns:true,
  468. loadMsg:'',
  469. frozenColumns:[[
  470. {field:'f',width:20,resizable:false}
  471. ]],
  472. columns:[[
  473. {field:'name',title:'Name',width:100,sortable:true},
  474. {field:'value',title:'Value',width:100,resizable:false}
  475. ]],
  476. showGroup:false,
  477. groupView:groupview,
  478. groupField:'group',
  479. groupStyler: function(value,rows){return ''},
  480. groupFormatter:function(fvalue,rows){return fvalue}
  481. });
  482. })(jQuery);