1. 写在开头
一直说要整理一下easyUI的内容的,一直也没时间,最近真的是忙的不可开交,今天正好遇到一个需求,关于datagrid的分组展示问题的,先记录一下,以后有空了在将其他内容补上。
easyUI是曾经比较流行的一个前端框架了,现在很多老的项目都在使用它,作为一位老鸟,我们还是需要对它有一定的认知的,这样在维护一些陈旧的项目的时候,才不会手忙脚乱了!
2. DataGrid - GroupView
其本质上也是一个datagrid,用法与datagrid基本上一致,但是要使用它,需要先引入group_view.js文件
2.1 小demo
2.1.1 方式一:类方式1
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Basic PropertyGrid - jQuery EasyUI Demo</title>
<link rel="stylesheet" type="text/css" href="./easyui.css">
<link rel="stylesheet" type="text/css" href="./icon.css">
<link rel="stylesheet" type="text/css" href="./demo.css">
<script type="text/javascript" src="./jquery.min.js"></script>
<script type="text/javascript" src="./jquery.easyui.min.js"></script>
<script type="text/javascript" src="./group_view.js"></script>
</head>
<body>
<h2>Basic PropertyGrid</h2>
<p>Click on row to change each property value.</p>
<div style="margin:20px 0;">
<a href="javascript:void(0)" class="easyui-linkbutton" onclick="showGroup()">ShowGroup</a>
<a href="javascript:void(0)" class="easyui-linkbutton" onclick="hideGroup()">HideGroup</a>
<a href="javascript:void(0)" class="easyui-linkbutton" onclick="showHeader()">ShowHeader</a>
<a href="javascript:void(0)" class="easyui-linkbutton" onclick="hideHeader()">HideHeader</a>
<a href="javascript:void(0)" class="easyui-linkbutton" onclick="getChanges()">GetChanges</a>
</div>
<table id="pg" class="easyui-propertygrid" style="width:300px" data-options="
url:'http://localhost:8080/easy',
method:'get',
showGroup:true,
scrollbarSize:0
">
</table>
<script type="text/javascript">
function showGroup(){
$('#pg').propertygrid({
showGroup:true
});
}
function hideGroup(){
$('#pg').propertygrid({
showGroup:false
});
}
function showHeader(){
$('#pg').propertygrid({
showHeader:true
});
}
function hideHeader(){
$('#pg').propertygrid({
showHeader:false
});
}
function getChanges(){
var s = '';
var rows = $('#pg').propertygrid('getChanges');
for(var i=0; i<rows.length; i++){
s += rows[i].name + ':' + rows[i].value + ',';
}
alert(s)
}
</script>
</html>
效果图:
2.1.2 类方式2
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Basic PropertyGrid - jQuery EasyUI Demo</title>
<link rel="stylesheet" type="text/css" href="./easyui.css">
<link rel="stylesheet" type="text/css" href="./icon.css">
<link rel="stylesheet" type="text/css" href="./demo.css">
<script type="text/javascript" src="./jquery.min.js"></script>
<script type="text/javascript" src="./jquery.easyui.min.js"></script>
<script type="text/javascript" src="./group_view.js"></script>
</head>
<body>
<h2>Customize Columns of PropertyGrid</h2>
<p>The columns of PropertyGrid can be changed.</p>
<div style="margin:20px 0;"></div>
<table class="easyui-propertygrid" style="width:300px" data-options="
url: 'http://localhost:8080/easy',
method: 'get',
showGroup: true,
scrollbarSize: 0,
columns: mycolumns
">
</table>
<script>
var mycolumns = [[
{field:'name',title:'MyName',width:100,sortable:true},
{field:'value',title:'MyValue',width:100,resizable:false}
]];
</script>
</body>
</html>
效果图:
2.2 方式二:js方式
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Basic PropertyGrid - jQuery EasyUI Demo</title>
<link rel="stylesheet" type="text/css" href="./easyui.css">
<link rel="stylesheet" type="text/css" href="./icon.css">
<link rel="stylesheet" type="text/css" href="./demo.css">
<script type="text/javascript" src="./jquery.min.js"></script>
<script type="text/javascript" src="./jquery.easyui.min.js"></script>
<script type="text/javascript" src="./group_view.js"></script>
<style>
.datagrid-group {
height: 28px;
overflow: hidden;
font-weight: bold;
border-bottom: 1px solid #ccc;
white-space: nowrap;
word-break: normal;
background-color: pink;
}
</style>
<script>
$(function(){
$('#tt').datagrid({
title:'DataGrid - GroupView',
width:500,
height:600,
rownumbers:true,
remoteSort:false,
nowrap:false,
fitColumns:true,
scrollbarSize:0,
url:'http://localhost:8080/easy',
columns:[[
{field:'name',title:'Product ID',width:400,sortable:true},
{field:'value',title:'List Price',width:100,align:'right',sortable:true}
]],
groupField:'group',
view: groupview,
pagination:true,
groupFormatter:function(value, rows){
var count = 0;
rows.forEach(item => {
if(item != null){
count += parseInt(item.value);
}
});
var html = "<table width='500px'><tr>";
html += "<th width='400px' style='align:left;'>Total</th>" ;
html += "<th width='100px' style='align:right;'>"+ count +"</th>" ;
html += "</tr></table>";
return html;
},
groupStyler: function(value,rows){
if (value == 'RP-LI-02'){
return 'background-color:#6293BB;color:#fff;'; // return inline style
// the function can return predefined css class and inline style
// return {class:'r1', style:{'color:#fff'}};
}
},
onLoadSuccess:function(data){
$("#tt").datagrid("collapseGroup");
//$('#tt').datagrid('collapseGroup');
//collapseGroup 折叠一个分组
},
onClickRow:function(rowIndex, rowData){
console.log(JSON.stringify(rowData));
}
});
});
</script>
</head>
<body>
<table id="tt"></table>
</body>
</html>
效果图:
2.1.3 数据格式
{"total":7,"rows":[
{"name":"Name","value":"Bill Smith","group":"ID Settings","editor":"text"},
{"name":"Address","value":"","group":"ID Settings","editor":"text"},
{"name":"Age","value":"40","group":"ID Settings","editor":"numberbox"},
{"name":"Birthday","value":"01/02/2012","group":"ID Settings","editor":"datebox"},
{"name":"SSN","value":"123-456-7890","group":"ID Settings","editor":"text"},
{"name":"Email","value":"bill@gmail.com","group":"Marketing Settings","editor":{
"type":"validatebox",
"options":{
"validType":"email"
}
}},
{"name":"FrequentBuyer","value":"false","group":"Marketing Settings","editor":{
"type":"checkbox",
"options":{
"on":true,
"off":false
}
}}
]}
3. 注意
group_view.js在我们下载的easyUI中是没有的,需要我们自己去下载,这里我将源码贴出来
$.extend($.fn.datagrid.defaults, {
groupHeight: 28,
expanderWidth: 30,
groupSortOrder: null, // 'asc','desc'
groupStyler: function(value,rows){return ''},
groupSorter: function(g1,g2){
var a = g1.value;
var b = g2.value;
return a==b ? 0 : (a>b?1:-1);
}
});
var groupview = $.extend({}, $.fn.datagrid.defaults.view, {
render: function(target, container, frozen){
var table = [];
var groups = this.groups;
for(var i=0; i<groups.length; i++){
table.push(this.renderGroup.call(this, target, i, groups[i], frozen));
}
$(container).html(table.join(''));
},
renderGroup: function(target, groupIndex, group, frozen){
var state = $.data(target, 'datagrid');
var opts = state.options;
var fields = $(target).datagrid('getColumnFields', frozen);
var hasFrozen = opts.frozenColumns && opts.frozenColumns.length;
if (frozen){
if (!(opts.rownumbers || hasFrozen)){
return '';
}
}
var table = [];
var css = opts.groupStyler.call(target, group.value, group.rows);
var cs = parseCss(css, 'datagrid-group');
table.push('<div group-index=' + groupIndex + ' ' + cs + '>');
if ((frozen && (opts.rownumbers || opts.frozenColumns.length)) ||
(!frozen && !(opts.rownumbers || opts.frozenColumns.length))){
table.push('<span class="datagrid-group-expander">');
table.push('<span class="datagrid-row-expander datagrid-row-collapse"> </span>');
table.push('</span>');
}
if ((frozen && hasFrozen) || (!frozen)){
table.push('<span class="datagrid-group-title">');
table.push(opts.groupFormatter.call(target, group.value, group.rows));
table.push('</span>');
}
table.push('</div>');
var groupRows = $.extend([], group.rows);
if (opts.groupFooter){
var footerRow = opts.groupFooter.call(target, group.value, group.rows);
if (footerRow){
footerRow._group_footer = true;
groupRows.push(footerRow);
}
}
table.push('<table class="datagrid-btable" cellspacing="0" cellpadding="0" border="0"><tbody>');
var index = group.startIndex;
for(var j=0; j<groupRows.length; j++) {
var css = opts.rowStyler ? opts.rowStyler.call(target, index, groupRows[j]) : '';
var classValue = '';
var styleValue = '';
if (typeof css == 'string'){
styleValue = css;
} else if (css){
classValue = css['class'] || '';
styleValue = css['style'] || '';
}
var cls = 'class="datagrid-row ' + (index % 2 && opts.striped ? 'datagrid-row-alt ' : ' ') + classValue + '"';
if (groupRows[j]._group_footer){
cls = 'class="datagrid-group-footer"';
styleValue = 'height:'+(opts.editorHeight+1)+'px';
}
var style = styleValue ? 'style="' + styleValue + '"' : '';
var rowId = state.rowIdPrefix + '-' + (frozen?1:2) + '-' + index;
table.push('<tr id="' + rowId + '" datagrid-row-index="' + index + '" ' + cls + ' ' + style + '>');
table.push(this.renderRow.call(this, target, fields, frozen, index, groupRows[j]));
table.push('</tr>');
index++;
}
table.push('</tbody></table>');
return table.join('');
function parseCss(css, cls){
var classValue = '';
var styleValue = '';
if (typeof css == 'string'){
styleValue = css;
} else if (css){
classValue = css['class'] || '';
styleValue = css['style'] || '';
}
return 'class="' + cls + (classValue ? ' '+classValue : '') + '" ' +
'style="' + styleValue + '"';
}
},
bindEvents: function(target){
var state = $.data(target, 'datagrid');
var dc = state.dc;
var body = dc.body1.add(dc.body2);
var clickHandler = ($.data(body[0],'events')||$._data(body[0],'events')).click[0].handler;
body.unbind('click').bind('click', function(e){
var tt = $(e.target);
var expander = tt.closest('span.datagrid-row-expander');
if (expander.length){
var gindex = expander.closest('div.datagrid-group').attr('group-index');
if (expander.hasClass('datagrid-row-collapse')){
$(target).datagrid('collapseGroup', gindex);
} else {
$(target).datagrid('expandGroup', gindex);
}
} else {
clickHandler(e);
}
// e.stopPropagation();
});
},
onBeforeRender: function(target, rows){
var state = $.data(target, 'datagrid');
var opts = state.options;
initCss();
var groups = [];
for(var i=0; i<rows.length; i++){
var row = rows[i];
var group = getGroup(row[opts.groupField]);
if (!group){
group = {
value: row[opts.groupField],
rows: [row]
};
groups.push(group);
} else {
group.rows.push(row);
}
}
if (opts.groupSortOrder){
groups.sort(function(a, b){
var r = opts.groupSorter.call(target, a, b);
return r * (opts.groupSortOrder=='asc'?1:-1);
});
}
var index = 0;
var newRows = [];
for(var i=0; i<groups.length; i++){
var group = groups[i];
group.startIndex = index;
index += group.rows.length;
newRows = newRows.concat(group.rows);
}
state.data.rows = newRows;
this.groups = groups;
var that = this;
setTimeout(function(){
that.bindEvents(target);
},0);
function getGroup(value){
for(var i=0; i<groups.length; i++){
var group = groups[i];
if (group.value == value){
return group;
}
}
return null;
}
function initCss(){
if (!$('#datagrid-group-style').length){
$('head').append(
'<style id="datagrid-group-style">' +
'.datagrid-group{height:'+opts.groupHeight+'px;overflow:hidden;font-weight:bold;border-bottom:1px solid #ccc;white-space:nowrap;word-break:normal;}' +
'.datagrid-group-title,.datagrid-group-expander{display:inline-block;vertical-align:bottom;height:100%;line-height:'+opts.groupHeight+'px;padding:0 4px;}' +
'.datagrid-group-title{position:relative;}' +
'.datagrid-group-expander{width:'+opts.expanderWidth+'px;text-align:center;padding:0}' +
'.datagrid-row-expander{margin:'+Math.floor((opts.groupHeight-16)/2)+'px 0;display:inline-block;width:16px;height:16px;cursor:pointer}' +
'.datagrid-group-footer .datagrid-cell-rownumber{display:none}' +
'</style>'
);
}
}
},
onAfterRender: function(target){
$.fn.datagrid.defaults.view.onAfterRender.call(this, target);
var view = this;
var state = $.data(target, 'datagrid');
var opts = state.options;
if (!state.onResizeColumn){
state.onResizeColumn = opts.onResizeColumn;
}
if (!state.onResize){
state.onResize = opts.onResize;
}
opts.onResizeColumn = function(field, width){
view.resizeGroup(target);
state.onResizeColumn.call(target, field, width);
}
opts.onResize = function(width, height){
view.resizeGroup(target);
state.onResize.call($(target).datagrid('getPanel')[0], width, height);
}
view.resizeGroup(target);
}
});
$.extend($.fn.datagrid.methods, {
groups:function(jq){
return jq.datagrid('options').view.groups;
},
expandGroup:function(jq, groupIndex){
return jq.each(function(){
var opts = $(this).datagrid('options');
var view = $.data(this, 'datagrid').dc.view;
var group = view.find(groupIndex!=undefined ? 'div.datagrid-group[group-index="'+groupIndex+'"]' : 'div.datagrid-group');
var expander = group.find('span.datagrid-row-expander');
if (expander.hasClass('datagrid-row-expand')){
expander.removeClass('datagrid-row-expand').addClass('datagrid-row-collapse');
group.next('table').show();
}
$(this).datagrid('fixRowHeight');
if (opts.onExpandGroup){
opts.onExpandGroup.call(this, groupIndex);
}
});
},
collapseGroup:function(jq, groupIndex){
return jq.each(function(){
var opts = $(this).datagrid('options');
var view = $.data(this, 'datagrid').dc.view;
var group = view.find(groupIndex!=undefined ? 'div.datagrid-group[group-index="'+groupIndex+'"]' : 'div.datagrid-group');
var expander = group.find('span.datagrid-row-expander');
if (expander.hasClass('datagrid-row-collapse')){
expander.removeClass('datagrid-row-collapse').addClass('datagrid-row-expand');
group.next('table').hide();
}
$(this).datagrid('fixRowHeight');
if (opts.onCollapseGroup){
opts.onCollapseGroup.call(this, groupIndex);
}
});
},
scrollToGroup: function(jq, groupIndex){
return jq.each(function(){
var state = $.data(this, 'datagrid');
var dc = state.dc;
var grow = dc.body2.children('div.datagrid-group[group-index="'+groupIndex+'"]');
if (grow.length){
var groupHeight = grow.outerHeight();
var headerHeight = dc.view2.children('div.datagrid-header')._outerHeight();
var frozenHeight = dc.body2.outerHeight(true) - dc.body2.outerHeight();
var top = grow.position().top - headerHeight - frozenHeight;
if (top < 0){
dc.body2.scrollTop(dc.body2.scrollTop() + top);
} else if (top + groupHeight > dc.body2.height() - 18){
dc.body2.scrollTop(dc.body2.scrollTop() + top + groupHeight - dc.body2.height() + 18);
}
}
});
},
refreshGroupTitle: function(jq, groupIndex){
return jq.each(function(){
var opts = $(this).datagrid('options');
opts.view.refreshGroupTitle(this, groupIndex)
})
}
});
$.extend(groupview, {
refreshGroupTitle: function(target, groupIndex){
var state = $.data(target, 'datagrid');
var opts = state.options;
var dc = state.dc;
var group = this.groups[groupIndex];
var span = dc.body1.add(dc.body2).children('div.datagrid-group[group-index=' + groupIndex + ']').find('span.datagrid-group-title');
span.html(opts.groupFormatter.call(target, group.value, group.rows));
},
resizeGroup: function(target, groupIndex){
var state = $.data(target, 'datagrid');
var dc = state.dc;
var ht = dc.header2.find('table');
var fr = ht.find('tr.datagrid-filter-row');
// var fr = ht.find('tr.datagrid-filter-row').hide();
// var ww = ht.width();
var ww = dc.body2.children('table.datagrid-btable:first').width();
if (groupIndex == undefined){
var groupHeader = dc.body2.children('div.datagrid-group');
} else {
var groupHeader = dc.body2.children('div.datagrid-group[group-index=' + groupIndex + ']');
}
groupHeader._outerWidth(ww);
var opts = state.options;
if (opts.frozenColumns && opts.frozenColumns.length){
var width = dc.view1.width() - opts.expanderWidth;
var isRtl = dc.view1.css('direction').toLowerCase()=='rtl';
groupHeader.find('.datagrid-group-title').css(isRtl?'right':'left', -width+'px');
}
if (fr.length){
if (opts.showFilterBar){
fr.show();
}
}
// fr.show();
},
insertRow: function(target, index, row){
var state = $.data(target, 'datagrid');
var opts = state.options;
var dc = state.dc;
var group = null;
var groupIndex;
if (!state.data.rows.length){
$(target).datagrid('loadData', [row]);
return;
}
for(var i=0; i<this.groups.length; i++){
if (this.groups[i].value == row[opts.groupField]){
group = this.groups[i];
groupIndex = i;
break;
}
}
if (group){
if (index == undefined || index == null){
index = state.data.rows.length;
}
if (index < group.startIndex){
index = group.startIndex;
} else if (index > group.startIndex + group.rows.length){
index = group.startIndex + group.rows.length;
}
$.fn.datagrid.defaults.view.insertRow.call(this, target, index, row);
if (index >= group.startIndex + group.rows.length){
_moveTr(index, true);
_moveTr(index, false);
}
group.rows.splice(index - group.startIndex, 0, row);
} else {
group = {
value: row[opts.groupField],
rows: [row],
startIndex: state.data.rows.length
}
groupIndex = this.groups.length;
dc.body1.append(this.renderGroup.call(this, target, groupIndex, group, true));
dc.body2.append(this.renderGroup.call(this, target, groupIndex, group, false));
this.groups.push(group);
state.data.rows.push(row);
}
this.setGroupIndex(target);
this.refreshGroupTitle(target, groupIndex);
this.resizeGroup(target);
function _moveTr(index,frozen){
var serno = frozen?1:2;
var prevTr = opts.finder.getTr(target, index-1, 'body', serno);
var tr = opts.finder.getTr(target, index, 'body', serno);
tr.insertAfter(prevTr);
}
},
updateRow: function(target, index, row){
var opts = $.data(target, 'datagrid').options;
$.fn.datagrid.defaults.view.updateRow.call(this, target, index, row);
var tb = opts.finder.getTr(target, index, 'body', 2).closest('table.datagrid-btable');
var groupIndex = parseInt(tb.prev().attr('group-index'));
this.refreshGroupTitle(target, groupIndex);
},
deleteRow: function(target, index){
var state = $.data(target, 'datagrid');
var opts = state.options;
var dc = state.dc;
var body = dc.body1.add(dc.body2);
var tb = opts.finder.getTr(target, index, 'body', 2).closest('table.datagrid-btable');
var groupIndex = parseInt(tb.prev().attr('group-index'));
$.fn.datagrid.defaults.view.deleteRow.call(this, target, index);
var group = this.groups[groupIndex];
if (group.rows.length > 1){
group.rows.splice(index-group.startIndex, 1);
this.refreshGroupTitle(target, groupIndex);
} else {
body.children('div.datagrid-group[group-index='+groupIndex+']').remove();
for(var i=groupIndex+1; i<this.groups.length; i++){
body.children('div.datagrid-group[group-index='+i+']').attr('group-index', i-1);
}
this.groups.splice(groupIndex, 1);
}
this.setGroupIndex(target);
},
setGroupIndex: function(target){
var index = 0;
for(var i=0; i<this.groups.length; i++){
var group = this.groups[i];
group.startIndex = index;
index += group.rows.length;
}
}
});