bootstrap-treetable.js
11.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
/**
* bootstrapTreeTable
*
* @author swifly
*/
(function($) {
"use strict";
$.fn.bootstrapTreeTable = function(options, param) {
var allData = null;//用于存放格式化后的数据
// 如果是调用方法
if (typeof options == 'string') {
return $.fn.bootstrapTreeTable.methods[options](this, param);
}
// 如果是初始化组件
options = $.extend({}, $.fn.bootstrapTreeTable.defaults, options || {});
// 是否有radio或checkbox
var hasSelectItem = false;
var target = $(this);
// 在外层包装一下div,样式用的bootstrap-table的
var _main_div = $("<div class='bootstrap-tree-table fixed-table-container'></div>");
target.before(_main_div);
_main_div.append(target);
target.addClass("table table-hover treetable-table");
if (options.striped) {
target.addClass('table-striped');
}
// 工具条在外层包装一下div,样式用的bootstrap-table的
if(options.toolbar){
var _tool_div = $("<div class='fixed-table-toolbar'></div>");
var _tool_left_div = $("<div class='bs-bars pull-left'></div>");
_tool_left_div.append($(options.toolbar));
_tool_div.append(_tool_left_div);
_main_div.before(_tool_div);
}
// 格式化数据,优化性能
target.formatData=function(data){
var _root = options.rootCodeValue?options.rootCodeValue:null
$.each(data, function(index, item) {
// 添加一个默认属性,用来判断当前节点有没有被显示
item.isShow = false;
// 这里兼容几种常见Root节点写法
// 默认的几种判断
var _defaultRootFlag = item[options.parentCode] == '0'
|| item[options.parentCode] == 0
|| item[options.parentCode] == null
|| item[options.parentCode] == '';
if (!item[options.parentCode] || (_root?(item[options.parentCode] == options.rootCodeValue):_defaultRootFlag)){
if(!allData["_root_"]){allData["_root_"]=[];}
allData["_root_"].push(item);
}else{
if(!allData["_n_"+item[options.parentCode]]){allData["_n_"+item[options.parentCode]]=[];}
allData["_n_"+item[options.parentCode]].push(item);
}
});
data=null;//回收
}
// 得到根节点
target.getRootNodes = function() {
return allData["_root_"];
};
// 递归获取子节点并且设置子节点
target.handleNode = function(parentNode, lv, row_id, p_id, tbody) {
var _ls = allData["_n_"+parentNode[options.code]];
var tr = target.renderRow(parentNode,_ls?true:false,lv,row_id,p_id);
tbody.append(tr);
if(_ls){
$.each(_ls, function(i, item) {
var _row_id = row_id+"_"+i
target.handleNode(item, (lv + 1), _row_id,row_id, tbody)
});
}
};
// 绘制行
target.renderRow = function(item,isP,lv,row_id,p_id){
// 标记已显示
item.isShow = true;
var tr = $('<tr id="'+row_id+'" pid="'+p_id+'"></tr>');
var _icon = options.expanderCollapsedClass;
if(options.expandAll){
tr.css("display","table");
_icon = options.expanderExpandedClass;
}else if(options.expandFirst&&lv<=1){
tr.css("display","table");
_icon=(lv==0)?options.expanderExpandedClass:options.expanderCollapsedClass;
}else{
tr.css("display","none");
_icon = options.expanderCollapsedClass;
}
$.each(options.columns, function(index, column) {
// 判断有没有选择列
if(column.field=='selectItem'){
hasSelectItem = true;
var td = $('<td style="text-align:center;width:36px"></td>');
if(column.radio){
var _ipt = $('<input name="select_item" type="radio" value="'+item[options.id]+'"></input>');
td.append(_ipt);
}
if(column.checkbox){
var _ipt = $('<input name="select_item" type="checkbox" value="'+item[options.id]+'"></input>');
td.append(_ipt);
}
tr.append(td);
}else{
var td = $('<td title="'+item[column.field]+'" name="'+column.field+'" style="text-align:'+column.align+';'+((column.width)?('width:'+column.width):'')+'"></td>');
// 增加formatter渲染
if (column.formatter) {
td = $('<td style="text-align:'+column.align+';'+((column.width)?('width:'+column.width):'')+'"></td>');
td.html(column.formatter.call(this, item[column.field], item, index));
} else {
td.text(item[column.field]);
}
if(options.expandColumn==index){
if(!isP){
td.prepend('<span class="treetable-expander"></span>')
}else{
td.prepend('<span class="treetable-expander '+_icon+'"></span>')
}
for (var int = 0; int < (lv-1); int++) {
td.prepend('<span class="treetable-indent"></span>')
}
}
tr.append(td);
}
});
return tr;
}
// 加载数据
target.load = function(parms){
// 加载数据前先清空
allData = {};
// 加载数据前先清空
target.html("");
// 构造表头
var thr = $('<tr></tr>');
$.each(options.columns, function(i, item) {
var th = null;
// 判断有没有选择列
if(i==0 && item.field=='selectItem'){
hasSelectItem = true;
th = $('<th style="width:36px"></th>');
}else{
th = $('<th style="'+((item.width)?('width:'+item.width):'')+'"></th>');
}
th.text(item.title);
thr.append(th);
});
var thead = $('<thead class="treetable-thead"></thead>');
thead.append(thr);
target.append(thead);
// 构造表体
var tbody = $('<tbody class="treetable-tbody"></tbody>');
target.append(tbody);
// 添加加载loading
var _loading = '<tr><td colspan="'+options.columns.length+'"><div style="display: block;text-align: center;">正在努力地加载数据中,请稍候……</div></td></tr>'
tbody.html(_loading);
// 默认高度
if(options.height){
tbody.css("height",options.height);
}
$.ajax({
type : options.type,
url : options.url,
data : parms?parms:options.ajaxParams,
dataType : "JSON",
success : function(data, textStatus, jqXHR) {
// 加载完数据先清空
tbody.html("");
if(!data||data.length<=0){
var _empty = '<tr><td colspan="'+options.columns.length+'"><div style="display: block;text-align: center;">没有找到匹配的记录</div></td></tr>'
tbody.html(_empty);
return;
}
// 格式化数据
target.formatData(data);
// 开始绘制
var rootNode = target.getRootNodes();
if(rootNode){
$.each(rootNode, function(i, item) {
var _row_id = "row_id_"+i
target.handleNode(item, 1, _row_id,"row_root", tbody);
});
}
// 下边的操作主要是为了查询时让一些没有根节点的节点显示
$.each(data, function(i, item) {
if(!item.isShow){
var tr = target.renderRow(item,false,1);
tbody.append(tr);
}
});
target.append(tbody);
//动态设置表头宽度
thead.css("width", tbody.children(":first").css("width"));
// 行点击选中事件
target.find("tbody").find("tr").click(function(){
if(hasSelectItem){
var _ipt = $(this).find("input[name='select_item']");
if(_ipt.attr("type")=="radio"){
_ipt.prop('checked',true);
target.find("tbody").find("tr").removeClass("treetable-selected");
$(this).addClass("treetable-selected");
}else{
if(_ipt.prop('checked')){
_ipt.prop('checked',false);
$(this).removeClass("treetable-selected");
}else{
_ipt.prop('checked',true);
$(this).addClass("treetable-selected");
}
}
}
});
// 小图标点击事件--展开缩起
target.find("tbody").find("tr").find(".treetable-expander").click(function(){
var _flag = $(this).hasClass(options.expanderExpandedClass);
var tr = $(this).parent().parent();
var row_id = tr.attr("id");
if(_flag){
var _ls = target.find("tbody").find("tr[id^='"+row_id+"_']");//下所有
if(_ls&&_ls.length>0){
$.each(_ls, function(index, item) {
$(item).css("display","none");
var _icon = $(item).children().eq(options.expandColumn).find(".treetable-expander");
if(_icon.hasClass(options.expanderExpandedClass)){
_icon.removeClass(options.expanderExpandedClass)
_icon.addClass(options.expanderCollapsedClass)
}
});
}
$(this).removeClass(options.expanderExpandedClass)
$(this).addClass(options.expanderCollapsedClass)
}else{
var _ls = target.find("tbody").find("tr[pid='"+row_id+"']");//下一级
if(_ls&&_ls.length>0){
$.each(_ls, function(index, item) {
$(item).css("display","table");
});
}
$(this).removeClass(options.expanderCollapsedClass)
$(this).addClass(options.expanderExpandedClass)
}
});
},
error:function(xhr,textStatus){
var _errorMsg = '<tr><td colspan="'+options.columns.length+'"><div style="display: block;text-align: center;">'+xhr.responseText+'</div></td></tr>'
tbody.html(_errorMsg);
debugger;
},
});
}
if (options.url) {
target.load();
} else {
// 也可以通过defaults里面的data属性通过传递一个数据集合进来对组件进行初始化....有兴趣可以自己实现,思路和上述类似
}
return target;
};
// 组件方法封装........
$.fn.bootstrapTreeTable.methods = {
// 返回选中记录的id(返回的id由配置中的id属性指定)
// 为了兼容bootstrap-table的写法,统一返回数组,这里只返回了指定的id
getSelections : function(target, data) {
// 所有被选中的记录input
var _ipt = target.find("tbody").find("tr").find("input[name='select_item']:checked");
var chk_value =[];
// 如果是radio
if(_ipt.attr("type")=="radio"){
var _data = {id:_ipt.val()};
var _tds = _ipt.parent().parent().find("td");
_tds.each(function(_i,_item){
if(_i!=0){
_data[$(_item).attr("name")]=$(_item).attr("title");
}
});
chk_value.push(_data);
}else{
_ipt.each(function(_i,_item){
var _data = {id:$(_item).val()};
var _tds = $(_item).parent().parent().find("td");
_tds.each(function(_ii,_iitem){
if(_ii!=0){
_data[$(_iitem).attr("name")]=$(_iitem).attr("title");
}
});
chk_value.push(_data);
});
}
return chk_value;
},
// 刷新记录
refresh : function(target, parms) {
if(parms){
target.load(parms);
}else{
target.load();
}
},
// 组件的其他方法也可以进行类似封装........
};
$.fn.bootstrapTreeTable.defaults = {
id : 'id',// 选取记录返回的值
code : 'id',// 用于设置父子关系
parentCode : 'parentId',// 用于设置父子关系
rootCodeValue: null,//设置根节点code值----可指定根节点,默认为null,"",0,"0"
data : [], // 构造table的数据集合
type : "GET", // 请求数据的ajax类型
url : null, // 请求数据的ajax的url
ajaxParams : {}, // 请求数据的ajax的data属性
expandColumn : 0,// 在哪一列上面显示展开按钮
expandAll : false, // 是否全部展开
expandFirst : true, // 是否默认第一级展开--expandAll为false时生效
striped : false, // 是否各行渐变色
columns : [],
toolbar: '#toolbar',//顶部工具条
height: 0,
expanderExpandedClass : 'glyphicon glyphicon-chevron-down',// 展开的按钮的图标
expanderCollapsedClass : 'glyphicon glyphicon-chevron-right'// 缩起的按钮的图标
};
})(jQuery);