扩展BootstapTable支持TreeGrid
(function ($) {
'use strict';
var sprintf = function (str) {
var args = arguments,
flag = true,
i = ;
str = str.replace(/%s/g, function () {
var arg = args[i++];
if (typeof arg === 'undefined') {
flag = false;
return '';
}
return arg;
});
return flag ? str : '';
};
var getFieldIndex = function (columns, field) {
var index = -;
$.each(columns, function (i, column) {
if (column.field === field) {
index = i;
return false;
}
return true;
});
return index;
};
var calculateObjectValue = function (self, name, args, defaultValue) {
var func = name;
if (typeof name === 'string') {
var names = name.split('.');
if (names.length > ) {
func = window;
$.each(names, function (i, f) {
func = func[f];
});
} else {
func = window[name];
}
}
if (typeof func === 'object') {
return func;
}
if (typeof func === 'function') {
return func.apply(self, args);
}
if (!func && typeof name === 'string' && sprintf.apply(this, [name].concat(args))) {
return sprintf.apply(this, [name].concat(args));
}
return defaultValue;
};
var getItemField = function (item, field) {
var value = item;
if (typeof field !== 'string' || item.hasOwnProperty(field)) {
return item[field];
}
var props = field.split('.');
for (var p in props) {
value = value[props[p]];
}
return value;
};
var getParent = function (node, source, field) {
var data = [];
var items = $.grep(source, function (item, index) {
return node.ParentId == item[field];
});
$.each(items, function (index, item) {
data.splice(, , item);
var child = getParent(item, source, field);
$.each(child, function (i, n) {
data.splice(, , n);
});
});
return data;
};
var getChild = function (node, source, field) {
var data = [];
var items = $.grep(source, function (item, index) {
return item.ParentId == node[field];
});
$.each(items, function (index, item) {
data.push(item);
var child = getChild(item, source, field);
$.each(child, function (i, n) {
data.push(n);
});
});
return data;
};
//调用bootstrapTable组件的构造器得到对象
var BootstrapTable = $.fn.bootstrapTable.Constructor,
_initData = BootstrapTable.prototype.initData,
_initPagination = BootstrapTable.prototype.initPagination,
_initBody = BootstrapTable.prototype.initBody;
//重写bootstrapTable的initData方法
BootstrapTable.prototype.initData = function () {
_initData.apply(this, Array.prototype.slice.apply(arguments));
var that = this;
if (that.options.treeView && this.data.length > ) {
var rows = [];
var roots = $.grep(this.data, function (row, index) {
return row.ParentId == that.options.treeRootParentId;
//return row.Level == that.options.treeRootLevel;
});
$.each(roots, function (index, item) {
rows.push(item);
var child = getChild(item, that.data, that.options.treeId);
$.each(child, function (i, n) {
if (that.options.treeCollapseAll) {
n.hidden = true;
}
rows.push(n);
});
});
that.options.data = that.data = rows;
}
};
//重写bootstrapTable的initPagination方法
BootstrapTable.prototype.initPagination = function () {
if (this.options.treeView) {
//理论情况下,treegrid是不支持分页的,所以默认分页参数为false
this.options.pagination = false;
}
//调用“父类”的“虚方法”
_initPagination.apply(this, Array.prototype.slice.apply(arguments));
};
//重写bootstrapTable的initBody方法
BootstrapTable.prototype.initBody = function (fixedScroll) {
var that = this,
html = [],
data = this.getData(),
dataIdOrderList = [];
if (that.options.treeView) {
$.each(data, function (index, value) {
var item = {};
item[that.options.treeId] = value[that.options.treeId];
item.ParentId = value.ParentId;
dataIdOrderList.push(item);
});
dataIdOrderList.sort(function (a, b) {
return a.ParentId > b.ParentId ? : -;
});
var level = ;
var lastParentId = null;
$.each(dataIdOrderList, function (index, value) {
var parentId = value.ParentId;
if (lastParentId != null && parentId != lastParentId) {
$.each(dataIdOrderList, function (index, subItemValue) {
if (subItemValue[that.options.treeId] == parentId) {
level = subItemValue.level + ;
return false;
}
});
}
lastParentId = parentId;
value.level = level;
})
}
this.trigger('pre-body', data);
this.$body = this.$el.find('tbody');
if (!this.$body.length) {
this.$body = $('<tbody></tbody>').appendTo(this.$el);
}
if (!this.options.pagination || this.options.sidePagination === 'server') {
this.pageFrom = ;
this.pageTo = data.length;
}
for (var i = this.pageFrom - ; i < this.pageTo; i++) {
var key,
item = data[i],
style = {},
csses = [],
data_ = '',
attributes = {},
htmlAttributes = [];
if (item.hidden) continue;
style = calculateObjectValue(this.options, this.options.rowStyle, [item, i], style);
if (style && style.css) {
for (key in style.css) {
csses.push(key + ': ' + style.css[key]);
}
}
attributes = calculateObjectValue(this.options,
this.options.rowAttributes, [item, i], attributes);
if (attributes) {
for (key in attributes) {
htmlAttributes.push(sprintf('%s="%s"', key, escapeHTML(attributes[key])));
}
}
if (item._data && !$.isEmptyObject(item._data)) {
$.each(item._data, function (k, v) {
if (k === 'index') {
return;
}
data_ += sprintf(' data-%s="%s"', k, v);
});
}
html.push('<tr',
sprintf(' %s', htmlAttributes.join(' ')),
sprintf(' id="%s"', $.isArray(item) ? undefined : item._id),
sprintf(' class="%s"', style.classes || ($.isArray(item) ? undefined : item._class)),
sprintf(' data-index="%s"', i),
sprintf(' data-uniqueid="%s"', item[this.options.uniqueId]),
sprintf('%s', data_),
'>'
);
if (this.options.cardView) {
html.push(sprintf('<td colspan="%s">', this.header.fields.length));
}
if (!this.options.cardView && this.options.detailView) {
html.push('<td>',
'<a class="detail-icon" href="javascript:">',
sprintf('<i class="%s %s"></i>', this.options.iconsPrefix, this.options.icons.detailOpen),
'</a>',
'</td>');
}
$.each(this.header.fields, function (j, field) {
var text = '',
value = getItemField(item, field),
type = '',
cellStyle = {},
id_ = '',
class_ = that.header.classes[j],
data_ = '',
rowspan_ = '',
title_ = '',
column = that.columns[getFieldIndex(that.columns, field)];
if (!column.visible) {
return;
}
style = sprintf('style="%s"', csses.concat(that.header.styles[j]).join('; '));
value = calculateObjectValue(column,
that.header.formatters[j], [value, item, i], value);
if (item['_' + field + '_id']) {
id_ = sprintf(' id="%s"', item['_' + field + '_id']);
}
if (item['_' + field + '_class']) {
class_ = sprintf(' class="%s"', item['_' + field + '_class']);
}
if (item['_' + field + '_rowspan']) {
rowspan_ = sprintf(' rowspan="%s"', item['_' + field + '_rowspan']);
}
if (item['_' + field + '_title']) {
title_ = sprintf(' title="%s"', item['_' + field + '_title']);
}
cellStyle = calculateObjectValue(that.header,
that.header.cellStyles[j], [value, item, i], cellStyle);
if (cellStyle.classes) {
class_ = sprintf(' class="%s"', cellStyle.classes);
}
if (cellStyle.css) {
var csses_ = [];
for (var key in cellStyle.css) {
csses_.push(key + ': ' + cellStyle.css[key]);
}
style = sprintf('style="%s"', csses_.concat(that.header.styles[j]).join('; '));
}
if (item['_' + field + '_data'] && !$.isEmptyObject(item['_' + field + '_data'])) {
$.each(item['_' + field + '_data'], function (k, v) {
if (k === 'index') {
return;
}
data_ += sprintf(' data-%s="%s"', k, v);
});
}
if (column.checkbox || column.radio) {
type = column.checkbox ? 'checkbox' : type;
type = column.radio ? 'radio' : type;
text = [that.options.cardView ?
'<div class="card-view">' : '<td class="bs-checkbox">',
'<input' +
sprintf(' data-index="%s"', i) +
sprintf(' name="%s"', that.options.selectItemName) +
sprintf(' type="%s"', type) +
sprintf(' value="%s"', item[that.options.idField]) +
sprintf(' checked="%s"', value === true ||
(value && value.checked) ? 'checked' : undefined) +
sprintf(' disabled="%s"', !column.checkboxEnabled ||
(value && value.disabled) ? 'disabled' : undefined) +
' />',
that.header.formatters[j] && typeof value === 'string' ? value : '',
that.options.cardView ? '</div>' : '</td>'
].join('');
item[that.header.stateField] = value === true || (value && value.checked);
} else {
value = typeof value === 'undefined' || value === null ?
that.options.undefinedText : value;
var indent, icon;
if (that.options.treeView && column.field == that.options.treeField) {
var level = ;
$.each(dataIdOrderList, function (index, value) {
if (value[that.options.treeId] == item[that.options.treeId]) {
level = value.level;
return false;
}
});
var indent = item.ParentId == that.options.treeRootParentId ? '' : sprintf('<span style="margin-left: %spx;"></span>', level * );
//var indent = item.Level == that.options.Level ? '' : sprintf('<span style="margin-left: %spx;"></span>', (item.Level - that.options.treeRootLevel) * 15);
var child = $.grep(data, function (d, i) {
return d.ParentId == item[that.options.treeId];
});
var childHidden = $.grep(child, function (d, i) {
return d.hidden;
});
var iconClass = that.options.collapseIcon;
if (child.length == ) {//无子节点
iconClass = that.options.noChildIcon;
}
if (childHidden.length > ) {
iconClass = that.options.expandIcon;
}
icon = sprintf('<span class="tree-icon %s" style="cursor: pointer; margin: 0px 5px;"></span>', iconClass);
//icon = sprintf('<span class="tree-icon %s" style="cursor: pointer; margin: 0px 5px;"></span>', child.length > 0 ? that.options.expandIcon : "");
}
text = that.options.cardView ? ['<div class="card-view">',
that.options.showHeader ? sprintf('<span class="title" %s>%s</span>', style,
getPropertyFromOther(that.columns, 'field', 'title', field)) : '',
sprintf('<span class="value">%s</span>', value),
'</div>'
].join('') : [sprintf('<td%s %s %s %s %s %s>', id_, class_, style, data_, rowspan_, title_),
indent,
icon,
value,
'</td>'
].join('');
if (that.options.cardView && that.options.smartDisplay && value === '') {
text = '';
}
}
html.push(text);
});
if (this.options.cardView) {
html.push('</td>');
}
html.push('</tr>');
}
if (!html.length) {
html.push('<tr class="no-records-found">',
sprintf('<td colspan="%s">%s</td>',
this.$header.find('th').length, this.options.formatNoMatches()),
'</tr>');
}
this.$body.html(html.join(''));
if (!fixedScroll) {
this.scrollTo();
}
this.$body.find('> tr[data-index] > td').off('click dblclick').on('click dblclick', function (e) {
var $td = $(this),
$tr = $td.parent(),
item = that.data[$tr.data('index')],
index = $td[].cellIndex,
field = that.header.fields[that.options.detailView && !that.options.cardView ? index - : index],
column = that.columns[getFieldIndex(that.columns, field)],
value = getItemField(item, field);
if ($td.find('.detail-icon').length) {
return;
}
that.trigger(e.type === 'click' ? 'click-cell' : 'dbl-click-cell', field, value, item, $td);
that.trigger(e.type === 'click' ? 'click-row' : 'dbl-click-row', item, $tr);
if (e.type === 'click' && that.options.clickToSelect && column.clickToSelect) {
var $selectItem = $tr.find(sprintf('[name="%s"]', that.options.selectItemName));
if ($selectItem.length) {
$selectItem[].click();
}
}
});
this.$body.find('> tr[data-index] > td > .detail-icon').off('click').on('click', function () {
var $this = $(this),
$tr = $this.parent().parent(),
index = $tr.data('index'),
row = data[index];
if ($tr.next().is('tr.detail-view')) {
$this.find('i').attr('class', sprintf('%s %s', that.options.iconsPrefix, that.options.icons.detailOpen));
$tr.next().remove();
that.trigger('collapse-row', index, row);
} else {
$this.find('i').attr('class', sprintf('%s %s', that.options.iconsPrefix, that.options.icons.detailClose));
$tr.after(sprintf('<tr class="detail-view"><td colspan="%s">%s</td></tr>',
$tr.find('td').length, calculateObjectValue(that.options,
that.options.detailFormatter, [index, row], '')));
that.trigger('expand-row', index, row, $tr.next().find('td'));
}
that.resetView();
});
this.$body.find('> tr[data-index] > td > .tree-icon').off('click').on('click', function (e) {
e.stopPropagation();
var $this = $(this),
$tr = $this.parent().parent(),
index = $tr.data('index'),
row = data[index];
var icon = $(this);
var child = getChild(data[index], data, that.options.treeId);
$.each(child, function (i, c) {
$.each(that.data, function (index, item) {
if (item[that.options.treeId] == c[that.options.treeId]) {
item.hidden = icon.hasClass(that.options.collapseIcon);
that.uncheck(index);
return;
}
});
});
if (icon.hasClass(that.options.expandIcon)) {
icon.removeClass(that.options.expandIcon).addClass(that.options.collapseIcon);
} else {
icon.removeClass(that.options.collapseIcon).addClass(that.options.expandIcon);
}
that.options.data = that.data;
that.initBody(true);
});
this.$selectItem = this.$body.find(sprintf('[name="%s"]', this.options.selectItemName));
this.$selectItem.off('click').on('click', function (event) {
event.stopImmediatePropagation();
var $this = $(this),
checked = $this.prop('checked'),
row = that.data[$this.data('index')];
if (that.options.maintainSelected && $(this).is(':radio')) {
$.each(that.options.data, function (i, row) {
row[that.header.stateField] = false;
});
}
row[that.header.stateField] = checked;
if (that.options.singleSelect) {
that.$selectItem.not(this).each(function () {
that.data[$(this).data('index')][that.header.stateField] = false;
});
that.$selectItem.filter(':checked').not(this).prop('checked', false);
}
that.updateSelected();
that.trigger(checked ? 'check' : 'uncheck', row, $this);
});
$.each(this.header.events, function (i, events) {
if (!events) {
return;
}
if (typeof events === 'string') {
events = calculateObjectValue(null, events);
}
var field = that.header.fields[i],
fieldIndex = $.inArray(field, that.getVisibleFields());
if (that.options.detailView && !that.options.cardView) {
fieldIndex += ;
}
for (var key in events) {
that.$body.find('tr').each(function () {
var $tr = $(this),
$td = $tr.find(that.options.cardView ? '.card-view' : 'td').eq(fieldIndex),
index = key.indexOf(' '),
name = key.substring(, index),
el = key.substring(index + ),
func = events[key];
$td.find(el).off(name).on(name, function (e) {
var index = $tr.data('index'),
row = that.data[index],
value = row[field];
func.apply(this, [e, value, row, index]);
});
});
}
});
this.updateSelected();
this.resetView();
this.trigger('post-body');
};
//给组件增加默认参数列表
$.extend($.fn.bootstrapTable.defaults, {
treeView: false,//treeView视图
treeField: "id",//treeView视图字段
treeId: "id",
treeRootParentId: -,//根节点的ParentId
//treeRootLevel: 0,//根节点序号
treeCollapseAll: false,//是否全部展开
collapseIcon: "glyphicon glyphicon-chevron-right",//折叠样式
expandIcon: "glyphicon glyphicon-chevron-down",//展开样式
noChildIcon:"glyphicon glyphicon-option-vertical"//无子节点图标
});
})(jQuery);
使用示例:
$(function () {
init();
});
function init() {
$('#table').bootstrapTable({
url:"/ActionName/GetList",
sidePagination: 'client',
pagination: false,
treeView: true,
treeId: "Id",
treeField: "Name",
treeRootParentId: -1,
clickToSelect: true,
//collapseIcon: "glyphicon glyphicon-triangle-right",//折叠样式
//expandIcon: "glyphicon glyphicon-triangle-bottom"//展开样式
});
}
HttpGet返回数组:[{Id:1,ParentId:-1},{Id:2,ParentId:1}]
扩展BootstapTable支持TreeGrid的更多相关文章
- 扩展BootstrapTable的treegrid功能
扩展BootstrapTable的treegrid功能 阅读目录 一.效果预览 二.代码示例 三.组件需要完善的地方 四.总结 正文 前言:上篇 JS组件系列——自己动手封装bootstrap-tr ...
- iframeWin For Easy UI. 为 Easy UI 扩展的支持IFrame插件
iframeWin For Easy UI. 为 Easy UI 扩展的支持IFrame插件 在一个项目中用了Easy UI,但是发现里面的 Dialog .Window.Messager 弹窗都不支 ...
- JS组件系列——自己动手扩展BootstrapTable的treegrid功能
前言:上篇 JS组件系列——自己动手封装bootstrap-treegrid组件 博主自己动手封装了下treegrid的功能,但毕竟那个组件只是一个单独针对树形表格做的,适用性还比较有限.关注博主的 ...
- 爱上MVC~为DisplayNameFor添加扩展,支持PagedList集合
回到目录 DisplayNameFor方法是MVC提供给我们的,它可以将模型的DisplayName特性的值显示到页面上,这对程序员来说很是方便,在进行实体设计时,可以指定它的显示名称,然后MVC引擎 ...
- Mac系统下使用VirtualBox虚拟机安装win7--第四步 安装虚拟机硬件扩展包支持
如 果想要在虚拟机上使用连接在 Mac 上的硬件外设,比如 U 盘,iPhone 等,需要我们在 Virtual Box 官网下载一个硬件支持扩展安装包.同样地,我们先打开虚拟机的下载页面: http ...
- C#中扩展StringBuilder支持链式方法
本篇体验扩展StringBuilder使之支持链式方法. 这里有一个根据键值集合生成select元素的方法. private static string BuilderSelectBox(IDicti ...
- 扩展Log4j支持JNDI数据源
log4j.properties配置文件: log4j.rootLogger=INFO,db #使用log4j扩展支持JNDI数据源 log4j.appender.db=com.qdgswx.log4 ...
- 【Swift 4.0】扩展 WCDB 支持 SQL 语句
前言 入坑 wcdb 有两个月了,整体来说还是很不错的,具体优点可以参考文档说明,由于官方明确说明不支持 SQL 只好自己写一个扩展支持一下了
- .NET MVC扩展UrlHelper支持CDN
0x00.为什么要扩展 因为我的服务器是小水管,加载一个完整的网站往往需要很久,想加速网站加载速度,静态文件最好是分离出来,所有就想到了扩展UrlHelper,用来支持CDN加载文件. 0x01.论引 ...
随机推荐
- url参数+,&,=,/等转义编码
url出现了有+,空格,/,?,%,#,&,= 等特殊符号的时候,可能在服务器端无法获得正确的参数值. 案例: <img src="BarCode39.aspx?barcode ...
- matlab中数组的拼接
matlab中,行拼接用逗号“:”,列拼接用分号“,”.示例如下: >> a=[1,2,3,4] 结果: a = 1 2 3 4 >> b=[1;2;3;4] 结果: b = ...
- ArrayList的实现原理
ArrayList的线性复杂度是1.想确定一个数据,直接通过索引进行访问.实际上这个过程和数组是非常相似的.ArrayList在整个使用过程中,如果想要高效操作,最好设置一个数组的大小.在个数固定的情 ...
- mysql 开发进阶篇系列 41 mysql日志之慢查询日志
一.概述 慢查询日志记录了所有的超过sql语句( 超时参数long_query_time单位 秒),获得表锁定的时间不算作执行时间.慢日志默认写入到参数datadir(数据目录)指定的路径下.默认文件 ...
- 如何在github上搭建一个免费的 无限流量的静态网页博客Github pages
前言: 看到很多相关的教程,但是在实际操作的时候还是遇见了不少问题,这里记录分享一下我的操作流程.免费空间用过很多,博客也用过一些,听说了github后就想试着玩一下这个静态库,感觉挺不错的,操作也比 ...
- Vue 动态加载组件
为什么要动态加载呢?而不是一次性加载呢? 一次性?你能保证你拿的内容不多,那从性能方面说还是OK的.否则,就该什么时候用,就什么时候取. 得出这想法,源于前几天上班赶产品的故事: A组件是父亲,B组件 ...
- ModBus通信协议的【功能码】
Modbus的功能码 ModBus 功能码与数据类型对应表: RTU 方式读取整数据的例子: 解析一下:主机发送指令,访问从站地址为1,使用功能码03(读保持寄存器),起始地址高8位.低8位 ...
- [PHP] 算法-合并两个有序链表为一个有序链表的PHP实现
合并两个有序的链表为一个有序的链表: 类似归并排序中合并两个数组的部分 1.遍历链表1和链表2,比较链表1和2中的元素大小 2.如果链表1结点大于链表2的结点,该结点放入第三方链表 3.链表1往下走一 ...
- 【转】Git 教程之协同开发
前面我们已经介绍过远程仓库的相关概念,不过那时并没有深入探讨,只是讲解了如何创建远程仓库以及推送最新工作成果到远程仓库,实际上远程仓库对于团队协同开发很重要,不仅仅是团队协同开发的基础,也是代码备份的 ...
- 2、买卖股票的最佳时机 II
2.买卖股票的最佳时机 II 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格. 设计一个算法来计算你所能获取的最大利润.你可以尽可能地完成更多的交易(多次买卖一支股票). 注意:你不能 ...