扩展BootstrapTable的treegrid功能

阅读目录

  • 一、效果预览
  • 二、代码示例
  • 三、组件需要完善的地方
  • 四、总结

正文

前言:上篇  JS组件系列——自己动手封装bootstrap-treegrid组件 博主自己动手封装了下treegrid的功能,但毕竟那个组件只是一个单独针对树形表格做的,适用性还比较有限。关注博主的园友应该知道,博主的博客里面写了很多bootstrapTable的扩展,今天打算在直接在bootstrapTable的基础上扩展一个treegrid的功能,很多长期关注博主博客的园友一直在问我怎么在bootstrapTable里面直接使用treegrid的功能,所以今天还是带来点福利。有兴趣的可以捧个人场!

本文原创地址:http://www.cnblogs.com/landeanfen/p/6924895.html

回到顶部

一、效果预览

全部折叠

展开一级

全部展开

回到顶部

二、代码示例

怎么样?效果还行吧。给出js的源码供大家参考。

(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 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 (node, source, field) {var data = [];var items = $.grep(source, function (item, index) {return node.ParentId == item[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 (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 > 0) {var rows = [];var roots = $.grep(this.data, function (row, index) {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 () {//理论情况下,treegrid是不支持分页的,所以默认分页参数为falsethis.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();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 = 1;this.pageTo = data.length;}for (var i = this.pageFrom - 1; 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 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] && !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);//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(0);}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,field = that.header.fields[that.options.detailView && !that.options.cardView ? index - 1 : 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[0].click();}}});this.$body.find('> tr[data-index] > td > .detail-icon').off('click').on('click', function () {debugger;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) {debugger;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.expandIcon);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 += 1;}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(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');};//给组件增加默认参数列表$.extend($.fn.bootstrapTable.defaults, {treeView: false,//treeView视图treeField: "id",//treeView视图字段treeId: "id",treeRootLevel: 0,//根节点序号treeCollapseAll: false,//是否全部展开collapseIcon: "glyphicon glyphicon-chevron-right",//折叠样式expandIcon: "glyphicon glyphicon-chevron-down"//展开样式});
})(jQuery);

组件的使用如下:

1、首先引用这个js文件。

2、然后初始化组件

         $('#tb').bootstrapTable({url: ActionUrl + 'GetMenuList',toolbar: '#toolbar',sidePagination: 'client',pagination: false,treeView: true,treeId: "Id",treeField: "Name",treeRootLevel: 1,clickToSelect: true,//collapseIcon: "glyphicon glyphicon-triangle-right",//折叠样式//expandIcon: "glyphicon glyphicon-triangle-bottom"//展开样式});

treeView:true表示启用树表格模式;

treeId:'Id'表示每一行tree的id;

treeField:'Name'表示要对那一列进行展开;

treeRootLevel:1表示树根的级别。

还有一个地方需要注意,要建立记录之间的父子级关系,必然后有一个ParentId的概念,所以在从后端返回的结果集里面,每条记录势必有一个ParentId的属性,如果是根节点,ParentId为null。比如我们后台得到的结果集的json格式如下:

[{Id: 1, Name: "系统设置", Url: null, ParentId: null, Level: 1, CreateTime: null, Status: 1, SortOrder: 1,…},{Id: 2, Name: "菜单管理", Url: "/Systems/Menu/Index", ParentId: 1, Level: 2, CreateTime: null, Status: 1,…},{Id: 3, Name: "订单管理", Url: null, ParentId: null, Level: 1, CreateTime: "2017-05-31 17:05:27",…},{Id: 4, Name: "基础数据", Url: null, ParentId: null, Level: 1, CreateTime: "2017-05-31 17:05:55",…},{Id: 5, Name: "新增订单", Url: "/order/add", ParentId: 3, Level: 2, CreateTime: "2017-05-31 17:07:03",…}]

回到顶部

三、组件需要完善的地方

上述封装给大家提供一个扩展bootstrapTable组件treeview功能,还有很多地方需要完善,比如:

1、我们的叶子节点前面的图标可以去掉;

2、增加展开所有、折叠所有的功能;

3、Level字段可以去掉,通过ParentId为null来确定根节点。

有兴趣的园友可以自己试试。

回到顶部

四、总结

至此本文就结束了,这篇针对上篇做了一个补充,使得我们可以根据项目的需求自己选择用哪种方式,如果我们项目使用的是bootstrapTable作为数据展示的组件,可以考虑上述扩展;如果没有使用bootstrapTable,可以试试上篇的组件。如果你觉得本文能够帮助你,可以右边随意 打赏 博主,打赏后可以获得博主永久免费的技术支持。

本文原创出处:http://www.cnblogs.com/landeanfen/

转载于:https://www.cnblogs.com/telwanggs/p/7111945.html

扩展BootstrapTable的treegrid功能相关推荐

  1. 实现WebMvcConfigurer接口扩展Spring MVC的功能

    前言: 先查看WebMvcConfigurer接口中都定义了哪些内容 public interface WebMvcConfigurer {default void configurePathMatc ...

  2. php mcript(),PHP基于mcript扩展实现对称加密功能

    本文实例讲述了PHP基于mcript扩展实现对称加密功能,结合实例形式简单分析了php使用mcript扩展进行加密与解密相关操作技巧,分享给大家供大家参考,具体如下: 1.对称加密主要利用相同的密钥来 ...

  3. python 自动化办公 uibot_使用 Python 扩展丰富 UiBot 的功能及在 UiBot 中引用 Python 模块...

    前言 UiBot除了自带的强大功能外,还允许有编程经验的RPA开发人员对功能进行自由扩展,目前UiBot支持以下四种扩展方式: Python插件.Lua插件.Lua Mod插件.COM插件(.Net也 ...

  4. 从头认识Spring-3.4 简单的AOP日志实现-扩展添加检查订单功能,以便记录并检測输入的參数...

    这一章节我们再上一个章节的基础上加上一个检查订单功能 1.domain 蛋糕类: package com.raylee.my_new_spring.my_new_spring.ch03.topic_1 ...

  5. JS组件系列——自己动手扩展BootstrapTable的 冻结列 功能:彻底解决高度问题

    阅读目录 一.问题追踪 二.效果预览 三.源码解析 1.源码各个方法解释 2.对于上述抛出的ie和谷歌的兼容性问题的解析 3.项目中的使用 4.扩展 四.总结 正文 前言:一年前,博主分享过一篇关于b ...

  6. 扩展 日历_日历功能的拓展:Apple Watch能在屏幕上显示年日历

    集微网消息,之前从网上看见许多苹果的粉丝希望Apple Watch的日历功能可以得到扩展,以便在某个时间点向用户显示年度日历视图. 而本周苹果公布的一项专利正为我们提供了一个扩展的日历视图,使用数字表 ...

  7. plc单片机组态软件php_STC8单片机扩展WiFi通信实现功能与组态王组态软件详细组态...

    STC8单片机扩展WiFi通信模块和组态王组态软件实现Modbus TCP以太网通信 一.通信实现功能: 1.Modbus TCP Client:组态王组态软件 2.Modbus TCP Server ...

  8. joomla tab 扩展_如何使用扩展功能扩展Joomla网站的功能

    joomla tab 扩展 Joomla被独立评论网站CMS Critic评为2018年度最佳免费CMS ,它是全球最受欢迎的网站内容管理系统(CMSes)之一. 与WordPress一样, Joom ...

  9. 扩展log4j2日志归档功能预研

    背景 因项目日志管理不够规范,日志文件需人为维护,这将会因人为原因导致日志误删的情况,现为了规范日志归档因此现对log4j2日志归档功能进行扩展预研,如有问题欢迎指正. 软件版本 log4j2 2.1 ...

最新文章

  1. 6大设计原则之依赖倒置原则
  2. DayDayUp:《机器崛起前传》第二十二章【蹒跚而来】读后感(文章源自网络)—听课笔记
  3. linuxoracle静默安装应答文件修改_Oracle 19c的examples静默安装
  4. python 如何判断一个函数执行完成_三步搞定 Python 中的文件操作
  5. mysql是一个_Mysql
  6. 带父节点的平衡二叉树_平衡二叉树 通俗易懂
  7. Repeater OnItemCommand 失效
  8. stringify中文乱码?
  9. 毛玻璃效果 php,CSS3打造磨砂玻璃背景效果
  10. Python练习题10:斐波那契数列计算
  11. 使用Java操纵Excel表格
  12. python学习之路day06
  13. 下一轮人工智能泡沫,或将由消费机器人引发
  14. Initializing Spring FrameworkServlet ‘uaa‘
  15. 各种常用的JSON接口,天气,手机归属地,IP地理位置,QQ空间,优酷,微博,等
  16. Satellite-derived land surface temperature: Current status and perspectives卫星衍生的地表温度
  17. buuctf_Misc-喵喵喵
  18. 第二章 进程管理-操作系统原理和实践
  19. Android中的视频压缩包含图片压缩工具
  20. 基于Frangi滤波的视网膜静脉血管检测算法matlab仿真

热门文章

  1. docker网络--理解linux底层实现机制、docker网络模式
  2. DataStorage分析
  3. (72)FPGA约束效率(防止过约束)
  4. ISE14.7逻辑综合与实现工作过程
  5. Qgis3.2编译移植成功文档完整版
  6. 数据结构之栈与递归的应用(全排列递归解法)
  7. [设计模式] - Proxy代理模式
  8. 计算机编程竞赛怎么入门,acm编程比赛入门题目集..pdf
  9. vuex express mysql_基于Vue2.0+Vuex+Axios+NodeJs+Express+MySQL实现京东移动web商城
  10. 抢红包概率是随机的吗_顺丰发5亿红包给员工:管理学的随机奖励还能这么玩...