浏览代码

Merge pull request #4278 from wenzhixin/feature/extensions

Feature/extensions
文翼 6 年之前
父节点
当前提交
cb070eac09
共有 26 个文件被更改,包括 212 次插入372 次删除
  1. 3 0
      site/_data/core-team.yml
  2. 2 0
      site/docs/api/table-options.md
  3. 2 6
      site/docs/extensions/addrbar.md
  4. 19 14
      src/bootstrap-table.js
  5. 6 4
      src/constants/index.js
  6. 13 20
      src/extensions/addrbar/bootstrap-table-addrbar.js
  7. 12 8
      src/extensions/auto-refresh/bootstrap-table-auto-refresh.js
  8. 8 14
      src/extensions/copy-rows/bootstrap-table-copy-rows.js
  9. 47 36
      src/extensions/export/bootstrap-table-export.js
  10. 3 14
      src/extensions/filter-control/bootstrap-table-filter-control.js
  11. 3 14
      src/extensions/print/bootstrap-table-print.js
  12. 3 1
      src/extensions/sticky-header/bootstrap-table-sticky-header.js
  13. 3 3
      src/extensions/toolbar/bootstrap-table-toolbar.js
  14. 0 1
      src/extensions/tree-column/bootstrap-table-tree-column.css
  15. 0 124
      src/extensions/tree-column/bootstrap-table-tree-column.js
  16. 0 43
      src/extensions/tree-column/bootstrap-table-tree-column.less
  17. 0 17
      src/extensions/tree-column/extension.json
  18. 二进制
      src/extensions/tree-column/icon.png
  19. 12 5
      src/themes/bulma/bootstrap-table-bulma.js
  20. 28 17
      src/themes/foundation/bootstrap-table-foundation.js
  21. 13 11
      src/themes/foundation/bootstrap-table-foundation.scss
  22. 18 13
      src/themes/materialize/bootstrap-table-materialize.js
  23. 4 1
      src/themes/materialize/bootstrap-table-materialize.scss
  24. 7 5
      src/themes/semantic/bootstrap-table-semantic.js
  25. 1 1
      src/themes/semantic/bootstrap-table-semantic.scss
  26. 5 0
      src/themes/theme.scss

+ 3 - 0
site/_data/core-team.yml

@@ -3,3 +3,6 @@
 
 - name: Dennis Hernández
   user: djhvscf
+
+- name: Dustin Utecht
+  user: UtechtDustin

+ 2 - 0
site/docs/api/table-options.md

@@ -37,6 +37,8 @@ The table options are defined in `jQuery.fn.bootstrapTable.defaults`.
 
   The height of table, enable fixed header of table.
 
+  Note that if there are multiple tables on a page and the height option is set at the same time, you need to add the `id` attribute to each table, otherwise, the window resize will not work properly.
+
 - **Default:** `undefined`
 
 - **Example:** [Table Height](https://examples.bootstrap-table.com/#options/table-height.html)

+ 2 - 6
site/docs/extensions/addrbar.md

@@ -43,7 +43,7 @@ Every time when changing page, sorting and searching operation, it will change t
   There are 5 parameters in default. They are
 
   * `page`: page number
-  * `limit`: page size
+  * `size`: page size
   * `order`: asc/dsc
   * `sort`: the sort keyword
   * `search`: search keyword
@@ -54,8 +54,4 @@ Every time when changing page, sorting and searching operation, it will change t
 
 ## Note
 
-* Can not use in client pagination.
-
-* The example page doesn't handle the sort and search operation, you need do it yourself.
-
-* While search field appeared, the page number will return to 1 when refresh, you can read [同时设置 pageNumber 和 searchText 初始值会冲突](https://github.com/wenzhixin/bootstrap-table/issues/2580).
+* Only support server side pagination.

+ 19 - 14
src/bootstrap-table.js

@@ -37,6 +37,7 @@ class BootstrapTable {
   initConstants () {
     const o = this.options
     this.constants = Constants.CONSTANTS
+    this.constants.theme = $.fn.bootstrapTable.theme
 
     const buttonsPrefix = o.buttonsPrefix ? `${o.buttonsPrefix}-` : ''
     this.constants.buttonsClass = [
@@ -333,7 +334,8 @@ class BootstrapTable {
       }
     })
 
-    $(window).off('resize.bootstrap-table')
+    const resizeEvent = `resize.bootstrap-table${this.$el.attr('id') || ''}`
+    $(window).off(resizeEvent)
     if (!this.options.showHeader || this.options.cardView) {
       this.$header.hide()
       this.$tableHeader.hide()
@@ -344,7 +346,7 @@ class BootstrapTable {
       this.$tableLoading.css('top', this.$header.outerHeight() + 1)
       // Assign the correct sortable arrow
       this.getCaret()
-      $(window).on('resize.bootstrap-table', e => this.resetWidth(e))
+      $(window).on(resizeEvent, e => this.resetWidth(e))
     }
 
     this.$selectAll = this.$header.find('[name="btSelectAll"]')
@@ -1939,15 +1941,9 @@ class BootstrapTable {
     this.$selectAll.prop('checked', this.$selectItem.length > 0 &&
       this.$selectItem.length === this.$selectItem.filter(':checked').length)
 
-    if (this.options.cardView) {
-      // remove the element css
-      this.$el.css('margin-top', '0')
-      this.$tableContainer.css('padding-bottom', '0')
-      this.$tableFooter.hide()
-      return
-    }
+    this.$tableContainer.toggleClass('has-card-view', this.options.cardView)
 
-    if (this.options.showHeader && this.options.height) {
+    if (!this.options.cardView && this.options.showHeader && this.options.height) {
       this.$tableHeader.show()
       this.resetHeader()
       padding += this.$header.outerHeight(true)
@@ -1956,7 +1952,7 @@ class BootstrapTable {
       this.trigger('post-header')
     }
 
-    if (this.options.showFooter) {
+    if (!this.options.cardView && this.options.showFooter) {
       this.$tableFooter.show()
       this.fitFooter()
       if (this.options.height) {
@@ -1973,9 +1969,17 @@ class BootstrapTable {
       this.$tableBorder && this.$tableBorder.css('height', `${height - tableHeight - padding - 1}px`)
     }
 
-    // Assign the correct sortable arrow
-    this.getCaret()
-    this.$tableContainer.css('padding-bottom', `${padding}px`)
+    if (this.options.cardView) {
+      // remove the element css
+      this.$el.css('margin-top', '0')
+      this.$tableContainer.css('padding-bottom', '0')
+      this.$tableFooter.hide()
+    } else {
+      // Assign the correct sortable arrow
+      this.getCaret()
+      this.$tableContainer.css('padding-bottom', `${padding}px`)
+    }
+
     this.trigger('reset-view')
   }
 
@@ -2776,6 +2780,7 @@ $.fn.bootstrapTable = function (option, ...args) {
 }
 
 $.fn.bootstrapTable.Constructor = BootstrapTable
+$.fn.bootstrapTable.theme = Constants.THEME
 $.fn.bootstrapTable.defaults = BootstrapTable.DEFAULTS
 $.fn.bootstrapTable.columnDefaults = BootstrapTable.COLUMN_DEFAULTS
 $.fn.bootstrapTable.locales = BootstrapTable.LOCALES

+ 6 - 4
src/constants/index.js

@@ -13,7 +13,6 @@ try {
 
 const CONSTANTS = {
   3: {
-    theme: 'bootstrap3',
     iconsPrefix: 'glyphicon',
     icons: {
       paginationSwitchDown: 'glyphicon-collapse-down icon-chevron-down',
@@ -37,7 +36,8 @@ const CONSTANTS = {
       paginationDropdown: 'btn-group dropdown',
       dropup: 'dropup',
       dropdownActive: 'active',
-      paginationActive: 'active'
+      paginationActive: 'active',
+      buttonActive: 'active'
     },
     html: {
       toobarDropdow: ['<ul class="dropdown-menu" role="menu">', '</ul>'],
@@ -51,7 +51,6 @@ const CONSTANTS = {
     }
   },
   4: {
-    theme: 'bootstrap4',
     iconsPrefix: 'fa',
     icons: {
       paginationSwitchDown: 'fa-caret-square-down',
@@ -75,7 +74,8 @@ const CONSTANTS = {
       paginationDropdown: 'btn-group dropdown',
       dropup: 'dropup',
       dropdownActive: 'active',
-      paginationActive: 'active'
+      paginationActive: 'active',
+      buttonActive: 'active'
     },
     html: {
       toobarDropdow: ['<div class="dropdown-menu dropdown-menu-right">', '</div>'],
@@ -401,6 +401,8 @@ const EVENTS = {
 Object.assign(DEFAULTS, EN)
 
 export default {
+  THEME: `bootstrap${bootstrapVersion}`,
+
   CONSTANTS,
 
   DEFAULTS,

+ 13 - 20
src/extensions/addrbar/bootstrap-table-addrbar.js

@@ -64,29 +64,22 @@ function _buildUrl (dict, url = window.location.search) {
 }
 
 $.BootstrapTable = class extends $.BootstrapTable {
-  init () {
-    // 拥有addrbar选项并且其值为true的才会继续执行
-    if (this.options.addrbar) {
+  init (...args) {
+    if (
+      this.options.pagination &&
+      this.options.sidePagination === 'server' &&
+      this.options.addrbar
+    ) {
       // 标志位, 初始加载后关闭
       this.addrbarInit = true
       const _prefix = this.options.addrPrefix || ''
 
       // 优先级排序: 用户指定值最优先, 未指定时从地址栏获取, 未获取到时采用默认值
-      this.options.pageSize = this.options.pageSize || (
-        _GET(`${_prefix}limit`) ? parseInt(_GET(`${_prefix}limit`)) : $.BootstrapTable.DEFAULTS.pageSize
-      )
-      this.options.pageNumber = this.options.pageNumber || (
-        _GET(`${_prefix}page`) ? parseInt(_GET(`${_prefix}page`)) : $.BootstrapTable.DEFAULTS.pageNumber
-      )
-      this.options.sortOrder = this.options.sortOrder || (
-        _GET(`${_prefix}order`) ? _GET(`${_prefix}order`) : $.BootstrapTable.DEFAULTS.sortOrder
-      )
-      this.options.sortName = this.options.sortName || (
-        _GET(`${_prefix}sort`) ? _GET(`${_prefix}sort`) : 'id'
-      )
-      this.options.searchText = this.options.searchText || (
-        _GET(`${_prefix}search`) ? _GET(`${_prefix}search`) : $.BootstrapTable.DEFAULTS.searchText
-      )
+      this.options.pageNumber = +_GET(`${_prefix}page`) || $.BootstrapTable.DEFAULTS.pageNumber
+      this.options.pageSize = +_GET(`${_prefix}size`) || $.BootstrapTable.DEFAULTS.pageSize
+      this.options.sortOrder = _GET(`${_prefix}order`) || $.BootstrapTable.DEFAULTS.sortOrder
+      this.options.sortName = _GET(`${_prefix}sort`) || $.BootstrapTable.DEFAULTS.sortName
+      this.options.searchText = _GET(`${_prefix}search`) || $.BootstrapTable.DEFAULTS.searchText
 
       const _onLoadSuccess = this.options.onLoadSuccess
 
@@ -96,7 +89,7 @@ $.BootstrapTable = class extends $.BootstrapTable {
         } else {
           const params = {}
           params[`${_prefix}page`] = this.options.pageNumber,
-          params[`${_prefix}limit`] = this.options.pageSize,
+          params[`${_prefix}size`] = this.options.pageSize,
           params[`${_prefix}order`] = this.options.sortOrder,
           params[`${_prefix}sort`] = this.options.sortName,
           params[`${_prefix}search`] = this.options.searchText
@@ -109,6 +102,6 @@ $.BootstrapTable = class extends $.BootstrapTable {
         }
       }
     }
-    super.init()
+    super.init(...args)
   }
 }

+ 12 - 8
src/extensions/auto-refresh/bootstrap-table-auto-refresh.js

@@ -15,7 +15,10 @@ $.extend($.fn.bootstrapTable.defaults, {
 })
 
 $.extend($.fn.bootstrapTable.defaults.icons, {
-  autoRefresh: Utils.bootstrapVersion === 4 ? 'fa-clock' : 'glyphicon-time icon-time'
+  autoRefresh: {
+    bootstrap3: 'glyphicon-time icon-time',
+    materialize: 'access_time'
+  }[$.fn.bootstrapTable.theme] || 'fa-clock'
 })
 
 $.extend($.fn.bootstrapTable.locales, {
@@ -41,16 +44,15 @@ $.BootstrapTable = class extends $.BootstrapTable {
     super.initToolbar(...args)
 
     if (this.options.autoRefresh) {
-      const $btnGroup = this.$toolbar.find('>.btn-group')
+      const $btnGroup = this.$toolbar.find('>.columns')
       let $btnAutoRefresh = $btnGroup.find('.auto-refresh')
 
       if (!$btnAutoRefresh.length) {
         $btnAutoRefresh = $(`
-          <button class="auto-refresh btn${Utils.sprintf(' btn-%s', this.options.buttonsClass)}
-          ${Utils.sprintf(' btn-%s', this.options.iconSize)}
-          ${this.options.autoRefreshStatus ? 'active' : ''}"
+          <button class="auto-refresh ${this.constants.buttonsClass}
+          ${this.options.autoRefreshStatus ? ` ${this.constants.classes.buttonActive}` : ''}"
           type="button" title="${this.options.formatAutoRefresh()}">
-          <i class="${this.options.iconsPrefix} ${this.options.icons.autoRefresh}"></i>
+          ${Utils.sprintf(this.constants.html.icon, this.options.iconsPrefix, this.options.icons.autoRefresh)}
           </button>
         `).appendTo($btnGroup)
 
@@ -63,12 +65,14 @@ $.BootstrapTable = class extends $.BootstrapTable {
     if (this.options.autoRefresh) {
       if (this.options.autoRefreshStatus) {
         clearInterval(this.options.autoRefreshFunction)
-        this.$toolbar.find('>.btn-group').find('.auto-refresh').removeClass('active')
+        this.$toolbar.find('>.columns').find('.auto-refresh')
+          .removeClass(this.constants.classes.buttonActive)
       } else {
         this.options.autoRefreshFunction = setInterval(() => {
           this.refresh({silent: this.options.autoRefreshSilent})
         }, this.options.autoRefreshInterval * 1000)
-        this.$toolbar.find('>.btn-group').find('.auto-refresh').addClass('active')
+        this.$toolbar.find('>.columns').find('.auto-refresh')
+          .addClass(this.constants.classes.buttonActive)
       }
       this.options.autoRefreshStatus = !this.options.autoRefreshStatus
     }

+ 8 - 14
src/extensions/copy-rows/bootstrap-table-copy-rows.js

@@ -5,18 +5,12 @@
 
 const Utils = $.fn.bootstrapTable.utils
 
-const constants = {
-  3: {
-    icons: {
-      copy: 'glyphicon-copy icon-pencil'
-    }
-  },
-  4: {
-    icons: {
-      copy: 'fa-copy'
-    }
-  }
-}[Utils.bootstrapVersion]
+$.extend($.fn.bootstrapTable.defaults.icons, {
+  copy: {
+    bootstrap3: 'glyphicon-copy icon-pencil',
+    materialize: 'content_copy'
+  }[$.fn.bootstrapTable.theme] || 'fa-copy'
+})
 
 const copyText = text => {
   const textField = document.createElement('textarea')
@@ -49,12 +43,12 @@ $.BootstrapTable = class extends $.BootstrapTable {
   initToolbar (...args) {
     super.initToolbar(...args)
 
-    const $btnGroup = this.$toolbar.find('>.btn-group')
+    const $btnGroup = this.$toolbar.find('>.columns')
 
     if (this.options.showCopyRows && this.header.stateField) {
       this.$copyButton = $(`
         <button class="${this.constants.buttonsClass}">
-        <i class="${this.options.iconsPrefix} ${constants.icons.copy}"></i>
+        ${Utils.sprintf(this.constants.html.icon, this.options.iconsPrefix, this.options.icons.copy)}
         </button>
       `)
       $btnGroup.append(this.$copyButton)

+ 47 - 36
src/extensions/export/bootstrap-table-export.js

@@ -5,27 +5,6 @@
 
 const Utils = $.fn.bootstrapTable.utils
 
-const bootstrap = {
-  3: {
-    icons: {
-      export: 'glyphicon-export icon-share'
-    },
-    html: {
-      dropmenu: '<ul class="dropdown-menu" role="menu"></ul>',
-      dropitem: '<li role="menuitem" data-type="%s"><a href="javascript:">%s</a></li>'
-    }
-  },
-  4: {
-    icons: {
-      export: 'fa-download'
-    },
-    html: {
-      dropmenu: '<div class="dropdown-menu dropdown-menu-right"></div>',
-      dropitem: '<a class="dropdown-item" data-type="%s" href="javascript:">%s</a>'
-    }
-  }
-}[Utils.bootstrapVersion]
-
 const TYPE_NAME = {
   json: 'JSON',
   xml: 'XML',
@@ -57,7 +36,10 @@ $.extend($.fn.bootstrapTable.defaults, {
 })
 
 $.extend($.fn.bootstrapTable.defaults.icons, {
-  export: bootstrap.icons.export
+  export: {
+    bootstrap3: 'glyphicon-export icon-share',
+    materialize: 'file_download'
+  }[$.fn.bootstrapTable.theme] || 'fa-download'
 })
 
 $.extend($.fn.bootstrapTable.locales, {
@@ -90,44 +72,56 @@ $.BootstrapTable = class extends $.BootstrapTable {
     if (!this.options.showExport) {
       return
     }
-    const $btnGroup = this.$toolbar.find('>.btn-group')
+    const $btnGroup = this.$toolbar.find('>.columns')
     this.$export = $btnGroup.find('div.export')
 
     if (this.$export.length) {
       this.updateExportButton()
       return
     }
+
+    let $menu = $(this.constants.html.pageDropdown.join(''))
+
     this.$export = $(`
-      <div class="export btn-group">
+      <div class="export ${this.constants.classes.buttonsDropdown}">
       <button class="${this.constants.buttonsClass} dropdown-toggle"
-        aria-label="export type"
-        title="${o.formatExport()}"
-        data-toggle="dropdown"
-        type="button">
-        <i class="${o.iconsPrefix} ${o.icons.export}"></i>
-        <span class="caret"></span>
+      aria-label="Export"
+      data-toggle="dropdown"
+      type="button"
+      title="${o.formatExport()}">
+      ${Utils.sprintf(this.constants.html.icon, o.iconsPrefix, o.icons.export)}
+      ${this.constants.html.dropdownCaret}
       </button>
-      ${bootstrap.html.dropmenu}
       </div>
     `).appendTo($btnGroup)
+    this.$export.append($menu)
 
     this.updateExportButton()
 
-    const $menu = this.$export.find('.dropdown-menu')
     let exportTypes = o.exportTypes
 
     if (typeof exportTypes === 'string') {
       const types = exportTypes.slice(1, -1).replace(/ /g, '').split(',')
       exportTypes = types.map(t => t.slice(1, -1))
     }
+
+    // themes support
+    if ($menu.children().length) {
+      $menu = $menu.children().eq(0)
+    }
     for (const type of exportTypes) {
       if (TYPE_NAME.hasOwnProperty(type)) {
-        $menu.append(Utils.sprintf(bootstrap.html.dropitem, type, TYPE_NAME[type]))
+        const $item = $(Utils.sprintf(this.constants.html.pageDropdownItem,
+          '', TYPE_NAME[type]))
+        $item.attr('data-type', type)
+        $menu.append($item)
       }
     }
 
-    $menu.find('>li, >a').click(({currentTarget}) => {
-      const type = $(currentTarget).data('type')
+    $menu.children().click(e => {
+      e.preventDefault()
+
+      const type = $(e.currentTarget).data('type')
       const exportOptions = {
         type,
         escape: false
@@ -135,6 +129,23 @@ $.BootstrapTable = class extends $.BootstrapTable {
 
       this.exportTable(exportOptions)
     })
+    this.handleToolbar()
+  }
+
+  handleToolbar () {
+    if (!this.$export) {
+      return
+    }
+
+    if ($.fn.bootstrapTable.theme === 'foundation') {
+      this.$export.find('.dropdown-pane').attr('id', 'toolbar-export-id')
+    } else if ($.fn.bootstrapTable.theme === 'materialize') {
+      this.$export.find('.dropdown-content').attr('id', 'toolbar-export-id')
+    }
+
+    if (super.handleToolbar) {
+      super.handleToolbar()
+    }
   }
 
   exportTable (options) {
@@ -186,7 +197,7 @@ $.BootstrapTable = class extends $.BootstrapTable {
             this.toggleView()
           }
 
-          callback()
+          if (callback) callback()
         }
       }, o.exportOptions, options))
     }

+ 3 - 14
src/extensions/filter-control/bootstrap-table-filter-control.js

@@ -505,19 +505,6 @@ const filterDataMethods = {
   }
 }
 
-const bootstrap = {
-  3: {
-    icons: {
-      clear: 'glyphicon-trash icon-clear'
-    }
-  },
-  4: {
-    icons: {
-      clear: 'fa-trash icon-clear'
-    }
-  }
-}[Utils.bootstrapVersion]
-
 $.extend($.fn.bootstrapTable.defaults, {
   filterControl: false,
   onColumnSearch (field, text) {
@@ -576,7 +563,9 @@ $.extend($.fn.bootstrapTable.Constructor.EVENTS, {
 })
 
 $.extend($.fn.bootstrapTable.defaults.icons, {
-  clear: bootstrap.icons.clear
+  clear: {
+    bootstrap3: 'glyphicon-trash icon-clear'
+  }[$.fn.bootstrapTable.theme] || 'fa-trash'
 })
 
 $.extend($.fn.bootstrapTable.locales, {

+ 3 - 14
src/extensions/print/bootstrap-table-print.js

@@ -4,19 +4,6 @@
 
 const Utils = $.fn.bootstrapTable.utils
 
-const bootstrap = {
-  3: {
-    icons: {
-      print: 'glyphicon-print icon-share'
-    }
-  },
-  4: {
-    icons: {
-      print: 'fa-print'
-    }
-  }
-}[Utils.bootstrapVersion]
-
 function printPageBuilderDefault (table) {
   return `
   <html>
@@ -78,7 +65,9 @@ $.extend($.fn.bootstrapTable.COLUMN_DEFAULTS, {
 })
 
 $.extend($.fn.bootstrapTable.defaults.icons, {
-  print: bootstrap.icons.print
+  print: {
+    bootstrap3: 'glyphicon-print icon-share'
+  }[$.fn.bootstrapTable.theme] || 'fa-print'
 })
 
 $.BootstrapTable = class extends $.BootstrapTable {

+ 3 - 1
src/extensions/sticky-header/bootstrap-table-sticky-header.js

@@ -11,7 +11,9 @@ $.extend($.fn.bootstrapTable.defaults, {
   stickyHeaderOffsetY: 0
 })
 
-const hiddenClass = Utils.bootstrapVersion === 4 ? 'd-none' : 'hidden'
+const hiddenClass = {
+  bootstrap3: 'hidden'
+}[$.fn.bootstrapTable.theme] || 'd-none'
 
 $.BootstrapTable = class extends $.BootstrapTable {
   initHeader (...args) {

+ 3 - 3
src/extensions/toolbar/bootstrap-table-toolbar.js

@@ -9,7 +9,7 @@
 const Utils = $.fn.bootstrapTable.utils
 
 const bootstrap = {
-  3: {
+  bootstrap3: {
     icons: {
       advancedSearchIcon: 'glyphicon-chevron-down'
     },
@@ -24,7 +24,7 @@ const bootstrap = {
       `
     }
   },
-  4: {
+  bootstrap4: {
     icons: {
       advancedSearchIcon: 'fa-chevron-down'
     },
@@ -39,7 +39,7 @@ const bootstrap = {
       `
     }
   }
-}[Utils.bootstrapVersion]
+}[$.fn.bootstrapTable.theme]
 
 $.extend($.fn.bootstrapTable.defaults, {
   advancedSearch: false,

文件差异内容过多而无法显示
+ 0 - 1
src/extensions/tree-column/bootstrap-table-tree-column.css


+ 0 - 124
src/extensions/tree-column/bootstrap-table-tree-column.js

@@ -1,124 +0,0 @@
-/**
- * @author: KingYang
- * @webSite: https://github.com/kingyang
- * @version: v1.0.0
- */
-
-$.extend($.fn.bootstrapTable.defaults, {
-  treeShowField: null,
-  idField: 'id',
-  parentIdField: 'pid',
-  treeVerticalcls: 'vertical',
-  treeVerticalLastcls: 'vertical last',
-  treeSpacecls: 'space',
-  treeNodecls: 'node',
-  treeCellcls: 'treenode',
-  treeTextcls: 'text',
-  onTreeFormatter (row) {
-    const that = this
-    const options = that.options
-    const level = row._level || 0
-    const plevel = row._parent && row._parent._level || 0
-    const paddings = []
-    for (var i = 0; i < plevel; i++) {
-      paddings.push(`<i class="${options.treeVerticalcls}"></i>`)
-      paddings.push(`<i class="${options.treeSpacecls}"></i>`)
-    }
-
-    for (let i = plevel; i < level; i++) {
-      if (row._last && i === (level - 1)) {
-        paddings.push(`<i class="${options.treeVerticalLastcls}"></i>`)
-      } else {
-        paddings.push(`<i class="${options.treeVerticalcls}"></i>`)
-      }
-      paddings.push(`<i class="${options.treeNodecls}"></i>`)
-    }
-    return paddings.join('')
-  }, onGetNodes (row, data) {
-    const that = this
-    const nodes = []
-    $.each(data, (i, item) => {
-      if (row[that.options.idField] === item[that.options.parentIdField]) {
-        nodes.push(item)
-      }
-    })
-    return nodes
-  },
-  onCheckLeaf (row, data) {
-    if (row.isLeaf !== undefined) {
-      return row.isLeaf
-    }
-    return !row._nodes || !row._nodes.length
-  }, onCheckRoot (row, data) {
-    const that = this
-    return !row[that.options.parentIdField]
-  }
-})
-
-const BootstrapTable = $.fn.bootstrapTable.Constructor
-const _initRow = BootstrapTable.prototype.initRow
-const _initHeader = BootstrapTable.prototype.initHeader
-
-BootstrapTable.prototype.initHeader = function (...args) {
-  const that = this
-  _initHeader.apply(that, Array.prototype.slice.apply(args))
-  const treeShowField = that.options.treeShowField
-  if (treeShowField) {
-    $.each(this.header.fields, (i, field) => {
-      if (treeShowField === field) {
-        that.treeEnable = true
-        const _formatter = that.header.formatters[i]
-        const _class = [that.options.treeCellcls]
-        if (that.header.classes[i]) {
-          _class.push(that.header.classes[i].split('"')[1] || '')
-        }
-        that.header.classes[i] = ` class="${_class.join(' ')}"`
-        that.header.formatters[i] = function (value, row, index) {
-          const colTree = [that.options.onTreeFormatter.apply(that, [row])]
-          colTree.push(`<span class="${that.options.treeTextcls}">`)
-          if (_formatter) {
-            colTree.push(_formatter.apply(this, Array.prototype.slice.apply(arguments)))
-          } else {
-            colTree.push(value)
-          }
-          colTree.push('</span>')
-          return colTree.join('')
-        }
-        return false
-      }
-    })
-  }
-}
-
-const initNode = function (item, idx, data, parentDom) {
-  const that = this
-  const nodes = that.options.onGetNodes.apply(that, [item, data])
-  item._nodes = nodes
-  parentDom.append(_initRow.apply(that, [item, idx, data, parentDom]))
-  const len = nodes.length - 1
-  for (let i = 0; i <= len; i++) {
-    const node = nodes[i]
-    node._level = item._level + 1
-    node._parent = item
-    if (i === len)
-      node._last = 1
-    initNode.apply(that, [node, $.inArray(node, data), data, parentDom])
-  }
-}
-
-
-BootstrapTable.prototype.initRow = function (item, idx, data, parentDom) {
-  const that = this
-  if (that.treeEnable) {
-    if (that.options.onCheckRoot.apply(that, [item, data])) {
-      if (item._level === undefined) {
-        item._level = 0
-      }
-      initNode.apply(that, [item, idx, data, parentDom])
-      return true
-    }
-    return false
-
-  }
-  return _initRow.apply(that, Array.prototype.slice.apply(arguments))
-}

+ 0 - 43
src/extensions/tree-column/bootstrap-table-tree-column.less

@@ -1,43 +0,0 @@
- .table:not(.table-condensed) > tbody > tr > td.treenode {
-     padding-top: 0;
-     padding-bottom: 0;
-     border-bottom: solid #fff 1px;
- }
- 
- .table:not(.table-condensed) > tbody > tr:last-child > td.treenode {
-     border-bottom: none;
- }
- 
- .treenode {
-     .text {
-         float: left;
-         display: block;
-         padding-top: 6px;
-         padding-bottom: 6px;
-     }
-     .vertical,
-     .vertical.last {
-         float: left;
-         display: block;
-         width: 1px;
-         border-left: dashed silver 1px;
-         height: 38px;
-         margin-left: 8px;
-     }
-     .vertical.last {
-         height: 15px;
-     }
-     
-     .space,
-     .node {
-         float: left;
-         display: block;
-         width: 15px;
-         height: 5px;
-         margin-top: 15px;
-     }
-     
-     .node {
-         border-top: dashed silver 1px;
-     }
- }

+ 0 - 17
src/extensions/tree-column/extension.json

@@ -1,17 +0,0 @@
-{
-  "name": "Tree column",
-  "version": "1.0.0",
-  "description": "Plugin to  support display tree data column.",
-  "url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/tree-column",
-  "example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/tree-column.html",
-
-  "plugins": [{
-    "name": "bootstrap-table-reorder-rows",
-    "url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/tree-column"
-  }],
-
-  "author": {
-    "name": "KingYang",
-    "image": "https://avatars3.githubusercontent.com/u/1540211"
-  }
-}

二进制
src/extensions/tree-column/icon.png


+ 12 - 5
src/themes/bulma/bootstrap-table-bulma.js

@@ -10,12 +10,12 @@ $.extend($.fn.bootstrapTable.defaults, {
   buttonsClass: 'button'
 })
 
+$.fn.bootstrapTable.theme = 'bulma'
+
 $.BootstrapTable = class extends $.BootstrapTable {
   initConstants () {
     super.initConstants()
 
-    this.constants.theme = 'bulma'
-
     this.constants.classes.buttonsGroup = 'buttons has-addons'
     this.constants.classes.buttonsDropdown = 'button dropdown is-right'
     this.constants.classes.input = 'input'
@@ -23,6 +23,7 @@ $.BootstrapTable = class extends $.BootstrapTable {
     this.constants.classes.dropup = 'is-up'
     this.constants.classes.dropdownActive = 'is-active'
     this.constants.classes.paginationActive = 'is-current'
+    this.constants.classes.buttonActive = 'is-active'
 
     this.constants.html.toobarDropdow = ['<div class="dropdown-menu"><div class="dropdown-content">', '</div></div>']
     this.constants.html.toobarDropdowItem = '<label class="dropdown-item">%s</label>'
@@ -35,7 +36,11 @@ $.BootstrapTable = class extends $.BootstrapTable {
 
   initToolbar () {
     super.initToolbar()
-    if (this.options.showColumns) {
+    this.handleToolbar()
+  }
+
+  handleToolbar () {
+    if (this.$toolbar.find('.dropdown').length) {
       this._initDropdown()
     }
   }
@@ -47,12 +52,14 @@ $.BootstrapTable = class extends $.BootstrapTable {
     }
   }
 
-  _initDropdown ($el) {
+  _initDropdown () {
     const $dropdowns = this.$container.find('.dropdown:not(.is-hoverable)')
 
     $dropdowns.off('click').on('click', e => {
+      const $this = $(e.currentTarget)
       e.stopPropagation()
-      $(e.currentTarget).toggleClass('is-active')
+      $dropdowns.not($this).removeClass('is-active')
+      $this.toggleClass('is-active')
     })
 
     $(document).off('click.bs.dropdown.bulma').on('click.bs.dropdown.bulma', () => {

+ 28 - 17
src/themes/foundation/bootstrap-table-foundation.js

@@ -10,21 +10,22 @@ $.extend($.fn.bootstrapTable.defaults, {
   buttonsClass: 'button'
 })
 
+$.fn.bootstrapTable.theme = 'foundation'
+
 $.BootstrapTable = class extends $.BootstrapTable {
   initConstants () {
     super.initConstants()
 
-    this.constants.theme = 'foundation'
-
     this.constants.classes.buttonsGroup = 'button-group'
     this.constants.classes.buttonsDropdown = 'dropdown-container'
     this.constants.classes.paginationDropdown = ''
     this.constants.classes.dropdownActive = 'is-active'
     this.constants.classes.paginationActive = 'current'
+    this.constants.classes.buttonActive = 'success'
 
-    this.constants.html.toobarDropdow = ['<ul class="dropdown-pane" id="toolbar-dropdown" data-dropdown><ul class="vertical menu">', '</ul></div>']
+    this.constants.html.toobarDropdow = ['<ul class="dropdown-pane" id="toolbar-columns-id" data-dropdown><ul class="vertical menu">', '</ul></div>']
     this.constants.html.toobarDropdowItem = '<li><label class="dropdown-item">%s</label></li>'
-    this.constants.html.pageDropdown = ['<ul class="dropdown-pane" id="page-list-dropdown" data-dropdown><ul class="vertical menu">', '</ul></ul>']
+    this.constants.html.pageDropdown = ['<div class="dropdown-pane" id="pagination-list-id" data-dropdown><ul class="vertical menu">', '</ul></div>']
     this.constants.html.pageDropdownItem = '<li class="dropdown-item %s"><a href="#">%s</a></li>'
     this.constants.html.dropdownCaret = '<i class="fa fa-angle-down"></i>'
     this.constants.html.pagination = ['<ul class="pagination%s">', '</ul>'],
@@ -33,14 +34,19 @@ $.BootstrapTable = class extends $.BootstrapTable {
 
   initToolbar () {
     super.initToolbar()
+    this.handleToolbar()
+  }
+
+  handleToolbar () {
+    if (this.$toolbar.find('.dropdown-toggle').length) {
+      this.$toolbar.find('.dropdown-toggle').each((i, el) => {
+        $(el).attr('data-toggle', $(el).next().attr('id'))
+        const $pane = $(el).next()
+          .attr('data-position', 'bottom')
+          .attr('data-alignment', 'right')
+        new window.Foundation.Dropdown($pane)
+      })
 
-    if (this.options.showColumns) {
-      this.$toolbar.find('.keep-open')
-        .attr('data-toggle', 'toolbar-dropdown')
-      const $pane = this.$toolbar.find('.dropdown-pane')
-        .attr('data-position', 'bottom')
-        .attr('data-alignment', 'right')
-      new window.Foundation.Dropdown($pane)
       this._initDropdown()
     }
   }
@@ -49,25 +55,30 @@ $.BootstrapTable = class extends $.BootstrapTable {
     super.initPagination()
 
     if (this.options.pagination && !this.options.onlyInfoPagination) {
-      this.$pagination.find('.dropdown-toggle')
-        .attr('data-toggle', 'page-list-dropdown')
+      const $el = this.$pagination.find('.dropdown-toggle')
+      $el.attr('data-toggle', $el.next().attr('id'))
+
       const $pane = this.$pagination.find('.dropdown-pane')
         .attr('data-position', 'top')
         .attr('data-alignment', 'left')
       new window.Foundation.Dropdown($pane)
+
+      this._initDropdown()
     }
   }
 
-  _initDropdown ($el) {
-    const $dropdowns = this.$container.find('.dropdown-container')
+  _initDropdown () {
+    const $dropdowns = this.$container.find('.dropdown-toggle')
 
     $dropdowns.off('click').on('click', e => {
+      const $this = $(e.currentTarget)
       e.stopPropagation()
-      $dropdowns.find('.dropdown-pane').foundation('toggle')
+      $dropdowns.not($this).next().foundation('close')
+      $this.next().foundation('toggle')
     })
 
     $(document).off('click.bs.dropdown.foundation').on('click.bs.dropdown.foundation', () => {
-      $dropdowns.find('.dropdown-pane').foundation('close')
+      $dropdowns.next().foundation('close')
     })
   }
 }

+ 13 - 11
src/themes/foundation/bootstrap-table-foundation.scss

@@ -21,20 +21,22 @@
       height: 2.5293rem;
     }
 
-    .dropdown-container {
-      .button {
-        &:hover .menu {
-          background: #fff;
+    .keep-open {
+      .dropdown-container {
+        .button {
+          &:hover .menu {
+            background: #fff;
+          }
         }
-      }
 
-      .menu {
-        li {
-          padding: 5px 0;
+        .menu {
+          li {
+            padding: 5px 0;
 
-          label {
-            white-space: nowrap;
-            text-align: left;
+            label {
+              white-space: nowrap;
+              text-align: left;
+            }
           }
         }
       }

+ 18 - 13
src/themes/materialize/bootstrap-table-materialize.js

@@ -22,21 +22,22 @@ $.extend($.fn.bootstrapTable.defaults, {
   }
 })
 
+$.fn.bootstrapTable.theme = 'materialize'
+
 $.BootstrapTable = class extends $.BootstrapTable {
   initConstants () {
     super.initConstants()
 
-    this.constants.theme = 'materialize'
-
     this.constants.classes.buttonsGroup = ''
     this.constants.classes.buttonsDropdown = ''
     this.constants.classes.input = 'input-field'
     this.constants.classes.input = ''
     this.constants.classes.paginationDropdown = ''
+    this.constants.classes.buttonActive = 'green'
 
-    this.constants.html.toobarDropdow = ['<ul id="toolbar-dropdown" class="dropdown-content">', '</ul>']
+    this.constants.html.toobarDropdow = ['<ul id="toolbar-columns-id" class="dropdown-content">', '</ul>']
     this.constants.html.toobarDropdowItem = '<li><label>%s</label></li>'
-    this.constants.html.pageDropdown = ['<ul id="page-list-dropdown" class="dropdown-content">', '</ul>']
+    this.constants.html.pageDropdown = ['<ul id="pagination-list-id" class="dropdown-content">', '</ul>']
     this.constants.html.pageDropdownItem = '<li><a class="%s" href="#">%s</a></li>'
     this.constants.html.dropdownCaret = '<i class="material-icons">arrow_drop_down</i>'
     this.constants.html.pagination = ['<ul class="pagination%s">', '</ul>'],
@@ -46,15 +47,19 @@ $.BootstrapTable = class extends $.BootstrapTable {
 
   initToolbar () {
     super.initToolbar()
+    this.handleToolbar()
+  }
 
-    if (this.options.showColumns) {
-      this.$toolbar.find('.dropdown-toggle')
-        .attr('data-target', 'toolbar-dropdown')
-        .dropdown({
-          alignment: 'right',
-          constrainWidth: false,
-          closeOnClick: false
-        })
+  handleToolbar () {
+    if (this.$toolbar.find('.dropdown-toggle').length) {
+      this.$toolbar.find('.dropdown-toggle').each((i, el) => {
+        $(el).attr('data-target', $(el).next().attr('id'))
+          .dropdown({
+            alignment: 'right',
+            constrainWidth: false,
+            closeOnClick: false
+          })
+      })
     }
   }
 
@@ -63,7 +68,7 @@ $.BootstrapTable = class extends $.BootstrapTable {
 
     if (this.options.pagination && !this.options.onlyInfoPagination) {
       this.$pagination.find('.dropdown-toggle')
-        .attr('data-target', 'page-list-dropdown')
+        .attr('data-target', this.$pagination.find('.dropdown-content').attr('id'))
         .dropdown()
     }
   }

+ 4 - 1
src/themes/materialize/bootstrap-table-materialize.scss

@@ -21,8 +21,11 @@
       margin-left: 3px;
     }
 
-    .keep-open {
+    .columns > div {
       display: inline;
+    }
+
+    .keep-open {
 
       li label {
         padding-top: 13px;

+ 7 - 5
src/themes/semantic/bootstrap-table-semantic.js

@@ -10,12 +10,12 @@ $.extend($.fn.bootstrapTable.defaults, {
   buttonsClass: 'ui button'
 })
 
+$.fn.bootstrapTable.theme = 'semantic'
+
 $.BootstrapTable = class extends $.BootstrapTable {
   initConstants () {
     super.initConstants()
 
-    this.constants.theme = 'semantic'
-
     this.constants.classes.buttonsGroup = 'ui buttons'
     this.constants.classes.buttonsDropdown = 'ui button dropdown'
     this.constants.classes.inputGroup = 'ui input'
@@ -32,9 +32,11 @@ $.BootstrapTable = class extends $.BootstrapTable {
 
   initToolbar () {
     super.initToolbar()
-    if (this.options.showColumns) {
-      this.$toolbar.find('.button.dropdown').dropdown()
-    }
+    this.handleToolbar()
+  }
+
+  handleToolbar () {
+    this.$toolbar.find('.button.dropdown').dropdown()
   }
 
   initPagination () {

+ 1 - 1
src/themes/semantic/bootstrap-table-semantic.scss

@@ -28,7 +28,7 @@
       padding-bottom: 0.60714286rem;
     }
 
-    .keep-open.button.dropdown {
+    .button.dropdown {
       padding: 0;
 
       .button {

+ 5 - 0
src/themes/theme.scss

@@ -72,6 +72,11 @@
         border-bottom: 1px solid $border-color;
       }
 
+      &.has-card-view {
+        border-top: 1px solid $border-color;
+        border-bottom: 1px solid $border-color;
+      }
+
       .fixed-table-border {
         border-left: 1px solid $border-color;
         border-right: 1px solid $border-color;