|
|
/*
|
|
|
* 功能:依赖bootstrap-table实现treegrid,参照landeanfen例子做了部分修改优化
|
|
|
* 作者:lds2013@163.com
|
|
|
* 日期:2017年10月5日
|
|
|
* 修改:2018年4月20日
|
|
|
* 内容:1、支持自定义收缩、展开图标;
|
|
|
* 2、支持自定义父级ID传入,默认ParentId;
|
|
|
* 3、父级ID最顶层改为0;
|
|
|
* 4、修改最后子级前的小图标;
|
|
|
* 5、支持展开、收缩事件;
|
|
|
* 6、支持定义是否层叠选中状态(选中父级,子级全部选中)的开关;
|
|
|
|
|
|
*用法: $('#tb').bootstrapTable({
|
|
|
method: 'post',
|
|
|
url: '/HR/HrDept/GetList',
|
|
|
singleSelect: true,//单行选择
|
|
|
clickToSelect: true,//点击行时自动选择
|
|
|
striped: true,//是否显示行间隔色
|
|
|
treeView: true,//是否显示树形视图
|
|
|
treeId: "DeptID",//定义关键字段来标识树节点
|
|
|
treeField: "DeptName",//定义树节点字段
|
|
|
treeParentId: "MasterID", //定义父级ID字段
|
|
|
treeRootLevel: 1,//树根的级别
|
|
|
treeCollapseAll: false,//是否全部折叠,默认折叠
|
|
|
uniqueId: "DeptID", //每一行的唯一标识,一般为主键列
|
|
|
columns:
|
|
|
[
|
|
|
{ field: 'ck', checkbox: true },
|
|
|
{ field: 'DeptID', title: '机构ID'},
|
|
|
{ field: 'MasterID', title: '上级ID', visible: false },
|
|
|
{ field: 'DeptName', title: '机构名称' }
|
|
|
]
|
|
|
});
|
|
|
|
|
|
* 注意事项:暂无
|
|
|
*
|
|
|
*/
|
|
|
(function ($) {
|
|
|
'use strict';
|
|
|
|
|
|
var sprintf = function (str) {
|
|
|
var args = arguments,
|
|
|
flag = true,
|
|
|
i = 1;
|
|
|
|
|
|
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 = -1;
|
|
|
|
|
|
$.each(columns, function (i, column) {
|
|
|
if (column.field === field) {
|
|
|
index = i;
|
|
|
return false;
|
|
|
}
|
|
|
return true;
|
|
|
});
|
|
|
return index;
|
|
|
};
|
|
|
var escapeHTML = function (text) {
|
|
|
if (typeof text === 'string') {
|
|
|
return text
|
|
|
.replace(/&/g, '&')
|
|
|
.replace(/</g, '<')
|
|
|
.replace(/>/g, '>')
|
|
|
.replace(/"/g, '"')
|
|
|
.replace(/'/g, ''')
|
|
|
.replace(/`/g, '`');
|
|
|
}
|
|
|
return text;
|
|
|
};
|
|
|
|
|
|
var calculateObjectValue = function (self, name, args, defaultValue) {
|
|
|
var func = name;
|
|
|
|
|
|
if (typeof name === 'string') {
|
|
|
var names = name.split('.');
|
|
|
|
|
|
if (names.length > 1) {
|
|
|
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 (parentId, node, source, field) {
|
|
|
var data = [];
|
|
|
var items = $.grep(source, function (item, index) {
|
|
|
for (var i in item) {
|
|
|
if (i == parentId) {
|
|
|
return item[i] == node[field];
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
$.each(items, function (index, item) {
|
|
|
data.splice(0, 0, item);
|
|
|
var child = getParent(item, source, field);
|
|
|
$.each(child, function (i, n) {
|
|
|
data.splice(0, 0, n);
|
|
|
});
|
|
|
});
|
|
|
return data;
|
|
|
};
|
|
|
|
|
|
var getChild = function (parentId, node, source, field) {
|
|
|
var items = $.grep(source, function (item, index) {
|
|
|
for (var i in item) {
|
|
|
if (i == parentId) {
|
|
|
return item[i] == node[field];
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
return items;
|
|
|
};
|
|
|
|
|
|
var getAllChild = function (parentId, node, source, field) {
|
|
|
var data = [];
|
|
|
var g = function (child) {
|
|
|
$.each(child, function (i, n) {
|
|
|
data.push(n);
|
|
|
var subChild = getChild(parentId, n, source, field);
|
|
|
if (subChild != null && subChild.length > 0) {
|
|
|
g(subChild);
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
var child = getChild(parentId, node, source, field);
|
|
|
g(child);
|
|
|
return data;
|
|
|
};
|
|
|
|
|
|
//调用bootstrapTable组件的构造器得到对象
|
|
|
var BootstrapTable = $.fn.bootstrapTable.Constructor,
|
|
|
_initData = BootstrapTable.prototype.initData,
|
|
|
_initPagination = BootstrapTable.prototype.initPagination;
|
|
|
|
|
|
//重写bootstrapTable的initData方法
|
|
|
BootstrapTable.prototype.initData = function () {
|
|
|
_initData.apply(this, Array.prototype.slice.apply(arguments));
|
|
|
var that = this;
|
|
|
//初始化数据,添加level,isLast 属性
|
|
|
if (that.options.treeView && this.data.length > 0) {
|
|
|
var rows = [], levelStep = 1;
|
|
|
var roots = $.grep(this.data, function (row, index) {
|
|
|
for (var i in row) {
|
|
|
if (i == that.options.treeParentId) {
|
|
|
return row[i] == 0;
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
var g = function (child) {
|
|
|
var childLevel = that.options.treeRootLevel + levelStep;
|
|
|
$.each(child, function (i, n) {
|
|
|
n.level = childLevel;
|
|
|
if (that.options.treeCollapseAll) {
|
|
|
n.hidden = true;
|
|
|
}
|
|
|
var subChild = getChild(that.options.treeParentId, n, that.data, that.options.treeId);
|
|
|
if (subChild == null || subChild.length == 0) {
|
|
|
n.isLast = true;
|
|
|
}
|
|
|
rows.push(n);
|
|
|
if (subChild != null && subChild.length > 0) {
|
|
|
levelStep++;
|
|
|
g(subChild);
|
|
|
} else {
|
|
|
levelStep = 1;
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
$.each(roots, function (index, item) {
|
|
|
item.level = that.options.treeRootLevel;
|
|
|
var child = getChild(that.options.treeParentId, item, that.data, that.options.treeId);
|
|
|
if (child == null || child.length == 0) {
|
|
|
item.isLast = true;
|
|
|
}
|
|
|
rows.push(item);
|
|
|
g(child);
|
|
|
});
|
|
|
that.options.data = that.data = rows;
|
|
|
}
|
|
|
};
|
|
|
|
|
|
//重写bootstrapTable的initPagination方法
|
|
|
BootstrapTable.prototype.initPagination = function () {
|
|
|
//理论情况下,treegrid是不支持分页的,所以默认分页参数为false
|
|
|
if (this.options.treeView) {
|
|
|
//this.options.pagination = false;
|
|
|
}
|
|
|
//调用“父类”的“虚方法”
|
|
|
_initPagination.apply(this, Array.prototype.slice.apply(arguments));
|
|
|
};
|
|
|
|
|
|
//重写bootstrapTable的initRow方法
|
|
|
BootstrapTable.prototype.initRow = function (item, i, data, parentDom) {
|
|
|
var that = this,
|
|
|
key,
|
|
|
html = [],
|
|
|
style = {},
|
|
|
csses = [],
|
|
|
data_ = '',
|
|
|
attributes = {},
|
|
|
htmlAttributes = [];
|
|
|
|
|
|
if ($.inArray(item, this.hiddenRows) > -1) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
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) {
|
|
|
// ignore data-index
|
|
|
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"><div class="card-views">', this.header.fields.length));
|
|
|
}
|
|
|
|
|
|
if (!this.options.cardView && this.options.detailView) {
|
|
|
html.push('<td>',
|
|
|
'<a class="detail-icon" href="#">',
|
|
|
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, that.options.escape),
|
|
|
value = '',
|
|
|
type = '',
|
|
|
cellStyle = {},
|
|
|
id_ = '',
|
|
|
class_ = that.header.classes[j],
|
|
|
data_ = '',
|
|
|
rowspan_ = '',
|
|
|
colspan_ = '',
|
|
|
title_ = '',
|
|
|
column = that.columns[j];
|
|
|
|
|
|
if (that.fromHtml && typeof value_ === 'undefined') {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if (!column.visible) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if (that.options.cardView && (!column.cardVisible)) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if (column.escape) {
|
|
|
value_ = escapeHTML(value_);
|
|
|
}
|
|
|
|
|
|
style = sprintf('style="%s"', csses.concat(that.header.styles[j]).join('; '));
|
|
|
|
|
|
// handle td's id and class
|
|
|
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 + '_colspan']) {
|
|
|
colspan_ = sprintf(' colspan="%s"', item['_' + field + '_colspan']);
|
|
|
}
|
|
|
if (item['_' + field + '_title']) {
|
|
|
title_ = sprintf(' title="%s"', item['_' + field + '_title']);
|
|
|
}
|
|
|
cellStyle = calculateObjectValue(that.header,
|
|
|
that.header.cellStyles[j], [value_, item, i, field], 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('; '));
|
|
|
}
|
|
|
|
|
|
value = calculateObjectValue(column,
|
|
|
that.header.formatters[j], [value_, item, i], value_);
|
|
|
|
|
|
if (item['_' + field + '_data'] && !$.isEmptyObject(item['_' + field + '_data'])) {
|
|
|
$.each(item['_' + field + '_data'], function (k, v) {
|
|
|
// ignore data-index
|
|
|
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 = [sprintf(that.options.cardView ?
|
|
|
'<div class="card-view %s">' : '<td class="bs-checkbox %s">', column['class'] || ''),
|
|
|
'<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 && value.checked) ||
|
|
|
(item && item.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;
|
|
|
//渲染tree展开图标,下面text中添加了indent和icon。
|
|
|
var indent, icon;
|
|
|
if (that.options.treeView && column.field == that.options.treeField) {
|
|
|
var indent = item.level == that.options.treeRootLevel ? '' : sprintf('<span style="margin-left: %spx;"></span>', (item.level - that.options.treeRootLevel) * 15);
|
|
|
var child = $.grep(data, function (d, i) {
|
|
|
for (var i in d) {
|
|
|
if (i == that.options.treeParentId) {
|
|
|
return d[i] == item[that.options.treeId] && !d.hidden;
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
icon = sprintf('<span class="tree-icon %s" style="cursor: pointer; margin: 0px 5px;"></span>', child.length > 0 ? that.options.expandIcon : that.options.collapseIcon);
|
|
|
if (item.isLast) {
|
|
|
icon = sprintf('<span class="tree-icon %s" style="cursor: pointer; margin: 0px 5px;"></span>', that.options.lastIcon);
|
|
|
}
|
|
|
}
|
|
|
//end
|
|
|
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 %s>',
|
|
|
id_, class_, style, data_, rowspan_, colspan_, title_),
|
|
|
indent, icon,
|
|
|
value,
|
|
|
'</td>'
|
|
|
].join('');
|
|
|
|
|
|
// Hide empty data on Card view when smartDisplay is set to true.
|
|
|
if (that.options.cardView && that.options.smartDisplay && value === '') {
|
|
|
// Should set a placeholder for event binding correct fieldIndex
|
|
|
text = '<div class="card-view"></div>';
|
|
|
}
|
|
|
}
|
|
|
|
|
|
html.push(text);
|
|
|
});
|
|
|
|
|
|
if (this.options.cardView) {
|
|
|
html.push('</div></td>');
|
|
|
}
|
|
|
html.push('</tr>');
|
|
|
|
|
|
return html.join(' ');
|
|
|
};
|
|
|
//重写bootstrapTable的initBody方法
|
|
|
BootstrapTable.prototype.initBody = function (fixedScroll) {
|
|
|
var that = this,
|
|
|
html = [],
|
|
|
data = this.getData();
|
|
|
|
|
|
this.trigger('pre-body', data);
|
|
|
|
|
|
this.$body = this.$el.find('>tbody');
|
|
|
if (!this.$body.length) {
|
|
|
this.$body = $('<tbody></tbody>').appendTo(this.$el);
|
|
|
}
|
|
|
|
|
|
//Fix #389 Bootstrap-table-flatJSON is not working
|
|
|
|
|
|
if (!this.options.pagination || this.options.sidePagination === 'server') {
|
|
|
this.pageFrom = 1;
|
|
|
this.pageTo = data.length;
|
|
|
}
|
|
|
|
|
|
var trFragments = $(document.createDocumentFragment());
|
|
|
var hasTr;
|
|
|
|
|
|
for (var i = this.pageFrom - 1; i < this.pageTo; i++) {
|
|
|
var item = data[i];
|
|
|
if (item.hidden) continue;//hidden属性,当前行不渲染
|
|
|
var tr = this.initRow(item, i, data, trFragments);
|
|
|
hasTr = hasTr || !!tr;
|
|
|
if (tr && tr !== true) {
|
|
|
trFragments.append(tr);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// show no records
|
|
|
if (!hasTr) {
|
|
|
trFragments.append('<tr class="no-records-found">' +
|
|
|
sprintf('<td colspan="%s">%s</td>',
|
|
|
this.$header.find('th').length,
|
|
|
this.options.formatNoMatches()) +
|
|
|
'</tr>');
|
|
|
}
|
|
|
|
|
|
this.$body.html(trFragments);
|
|
|
|
|
|
if (!fixedScroll) {
|
|
|
this.scrollTo(0);
|
|
|
}
|
|
|
|
|
|
// click to select by column
|
|
|
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[0].cellIndex,
|
|
|
fields = that.getVisibleFields(),
|
|
|
field = fields[that.options.detailView && !that.options.cardView ? index - 1 : index],
|
|
|
column = that.columns[getFieldIndex(that.columns, field)],
|
|
|
value = getItemField(item, field, that.options.escape);
|
|
|
|
|
|
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, field);
|
|
|
|
|
|
// if click to select - then trigger the checkbox/radio click
|
|
|
if (e.type === 'click' && that.options.clickToSelect && column.clickToSelect) {
|
|
|
var $selectItem = $tr.find(sprintf('[name="%s"]', that.options.selectItemName));
|
|
|
if ($selectItem.length) {
|
|
|
//修复先勾选,再收缩父级,然后再勾选另一个选项,导致原收缩项里还是保持选中状态,最终导致获取选中项的bug
|
|
|
//解决思路:先把已选中的项取消,最后再选中点击的项
|
|
|
$.each(that.data, function (index, item) {
|
|
|
if (item.ck != undefined && item.ck == true) {
|
|
|
item.ck = false;
|
|
|
}
|
|
|
});
|
|
|
$selectItem[0].click(); // #144: .trigger('click') bug
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
|
|
|
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]; // Fix #980 Detail view, when searching, returns wrong row
|
|
|
|
|
|
// remove and update
|
|
|
if ($tr.next().is('tr.detail-view')) {
|
|
|
$this.find('i').attr('class', sprintf('%s %s', that.options.iconsPrefix, that.options.icons.detailOpen));
|
|
|
that.trigger('collapse-row', index, row);
|
|
|
$tr.next().remove();
|
|
|
} 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"></td></tr>', $tr.find('td').length));
|
|
|
var $element = $tr.next().find('td');
|
|
|
var content = calculateObjectValue(that.options, that.options.detailFormatter, [index, row, $element], '');
|
|
|
if ($element.length === 1) {
|
|
|
$element.append(content);
|
|
|
}
|
|
|
that.trigger('expand-row', index, row, $element);
|
|
|
}
|
|
|
that.resetView();
|
|
|
return false;
|
|
|
});
|
|
|
//treeicon点击事件
|
|
|
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);
|
|
|
if (icon.hasClass(that.options.expandIcon)) {
|
|
|
//展开状态
|
|
|
icon.removeClass(that.options.expandIcon).addClass(that.options.collapseIcon);
|
|
|
var child = getAllChild(that.options.treeParentId, 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 = true;
|
|
|
return;
|
|
|
}
|
|
|
});
|
|
|
});
|
|
|
} else {
|
|
|
icon.removeClass(that.options.collapseIcon).addClass(that.options.expandIcon);
|
|
|
var child = getChild(that.options.treeParentId, 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 = false;
|
|
|
return;
|
|
|
}
|
|
|
});
|
|
|
});
|
|
|
}
|
|
|
that.options.data = that.data;
|
|
|
that.initBody(true);
|
|
|
});
|
|
|
//end
|
|
|
|
|
|
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);
|
|
|
}
|
|
|
//层叠选中状态(选中父级,子级全部选中)
|
|
|
if (!that.options.singleSelect && that.options.cascadeCheck) {
|
|
|
var child = getAllChild(that.options.treeParentId, row, that.options.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.checked = checked ? true : false;
|
|
|
return;
|
|
|
}
|
|
|
});
|
|
|
});
|
|
|
}
|
|
|
that.options.data = that.data;
|
|
|
that.initBody(true);
|
|
|
that.updateSelected();
|
|
|
that.trigger(checked ? 'check' : 'uncheck', row, $this);
|
|
|
});
|
|
|
|
|
|
$.each(this.header.events, function (i, events) {
|
|
|
if (!events) {
|
|
|
return;
|
|
|
}
|
|
|
// fix bug, if events is defined with namespace
|
|
|
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 += 1;
|
|
|
}
|
|
|
|
|
|
for (var key in events) {
|
|
|
that.$body.find('>tr:not(.no-records-found)').each(function () {
|
|
|
var $tr = $(this),
|
|
|
$td = $tr.find(that.options.cardView ? '.card-view' : 'td').eq(fieldIndex),
|
|
|
index = key.indexOf(' '),
|
|
|
name = key.substring(0, index),
|
|
|
el = key.substring(index + 1),
|
|
|
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', data);
|
|
|
};
|
|
|
|
|
|
//展开所有树节点
|
|
|
BootstrapTable.prototype.expandAllTree = function () {
|
|
|
var that = this;
|
|
|
var roots = $.grep(this.data, function (row, index) {
|
|
|
for (var i in row) {
|
|
|
if (i == parentId) {
|
|
|
return row[i] == 0;
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
$.each(roots, function (index, item) {
|
|
|
var child = getAllChild(that.options.treeParentId, item, that.options.data, that.options.treeId);
|
|
|
$.each(child, function (i, n) {
|
|
|
n.hidden = false;
|
|
|
});
|
|
|
});
|
|
|
that.initBody(true);
|
|
|
}
|
|
|
|
|
|
//折叠所有树节点
|
|
|
BootstrapTable.prototype.collapseAllTree = function () {
|
|
|
var that = this;
|
|
|
var roots = $.grep(this.data, function (row, index) {
|
|
|
for (var i in row) {
|
|
|
if (i == parentId) {
|
|
|
return row[i] == 0;
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
$.each(roots, function (index, item) {
|
|
|
var child = getAllChild(that.options.treeParentId, item, that.options.data, that.options.treeId);
|
|
|
$.each(child, function (i, n) {
|
|
|
n.hidden = true;
|
|
|
});
|
|
|
});
|
|
|
that.initBody(true);
|
|
|
}
|
|
|
|
|
|
//给组件增加默认参数列表
|
|
|
$.extend($.fn.bootstrapTable.defaults, {
|
|
|
treeView: false,//treeView视图
|
|
|
treeId: "id",
|
|
|
treeField: "name",//treeView视图定义树节点字段
|
|
|
treeParentId: "ParentId",
|
|
|
treeRootLevel: 1,//根节点序号
|
|
|
treeCollapseAll: true,//是否全部折叠,默认折叠
|
|
|
cascadeCheck: true,//是否层叠选中状态(选中父级,子级全部选中)
|
|
|
collapseIcon: "glyphicon glyphicon-plus",//折叠样式
|
|
|
expandIcon: "glyphicon glyphicon-minus",//展开样式
|
|
|
lastIcon: "glyphicon glyphicon-hand-right"//叶子节点样式
|
|
|
});
|
|
|
$.fn.bootstrapTable.methods.push('expandAllTree', 'collapseAllTree');
|
|
|
})(jQuery); |