Browse Source

Fixing group by v2 in order to be merged

djhvscf 6 years ago
parent
commit
3c4fd135fb
1 changed files with 199 additions and 157 deletions
  1. 199 157
      src/extensions/group-by-v2/bootstrap-table-group-by.js

+ 199 - 157
src/extensions/group-by-v2/bootstrap-table-group-by.js

@@ -1,217 +1,259 @@
+/* eslint-disable guard-for-in */
 /**
  * @author: Yura Knoxville
  * @version: v1.1.0
  */
+const Utils = $.fn.bootstrapTable.utils
+const UtilsGroupBy = {
+  groupBy (array, f) {
+    const groups = {}
+    array.forEach(o => {
+      const group = f(o)
+      groups[group] = groups[group] || []
+      groups[group].push(o)
+    })
 
-let initBodyCaller
-let tableGroups
+    return groups
+  },
 
-// it only does '%s', and return '' when arguments are undefined
-const sprintf = function (str) {
-  const args = arguments
-  let flag = true
-  let i = 1
+  string2hash (s) {
+    const h = {}
+    if (typeof s === 'string') {
+      s.split(' ').forEach(function (field) {
+        h[field] = 0
+      })
+    }
+    return h
+  },
 
-  str = str.replace(/%s/g, () => {
-    const arg = args[i++]
+  aggr_sum (rows, fields) {
+    for (const field in fields) {
+      rows.forEach(function (row) {
+        fields[field] += isNaN(row[field]) ? 0 : row[field] * 1.0
+      })
+    }
+    return fields
+  },
 
-    if (typeof arg === 'undefined') {
-      flag = false
-      return ''
+  aggr_count (rows, fields) {
+    for (const field in fields) {
+      rows.forEach(function (row) {
+        fields[field] += row[field] ? 1 : 0
+      })
     }
-    return arg
-  })
-  return flag ? str : ''
-}
+    return fields
+  },
+
+  aggr_avg (rows, fields) {
+    let sum = 0
+    let count = 0
+    for (const field in fields) {
+      rows.forEach(function (row) {
+        if (!isNaN(row[field])) {
+          sum += row[field] * 1.0
+          count += 1
+        }
+      })
+      fields[field] = count > 0 ? sum / count : 0
+    }
+    return fields
+  },
+
+  execFunc (self, name, args, defaultValue) {
+    let func = name
 
-const groupBy = (array, f) => {
-  const groups = {}
-  array.forEach(o => {
-    const group = f(o)
-    groups[group] = groups[group] || []
-    groups[group].push(o)
-  })
+    if (typeof name === 'string') {
+      const names = name.split('.')
+
+      if (names.length > 1) {
+        func = window
+        $.each(names, function (i, f) { func = func[f] })
+      } else {
+        func = window[name]
+      }
+    }
 
-  return groups
+    return (typeof func === 'function') ? func.apply(self, args || []) : defaultValue
+  }
 }
+let initBodyCaller
+let tableGroups
 
 $.extend($.fn.bootstrapTable.defaults, {
   groupBy: false,
   groupByField: '',
-  groupByFormatter: undefined
+  groupByFormatter: undefined,
+  groupBySum: '',
+  groupByCount: '',
+  groupByAvg: ''
 })
 
-const BootstrapTable = $.fn.bootstrapTable.Constructor
-const _initSort = BootstrapTable.prototype.initSort
-const _initBody = BootstrapTable.prototype.initBody
-const _updateSelected = BootstrapTable.prototype.updateSelected
+$.BootstrapTable = class extends $.BootstrapTable {
+  initSort () {
+    super.initSort()
 
-BootstrapTable.prototype.initSort = function (...args) {
-  _initSort.apply(this, Array.prototype.slice.apply(args))
-
-  const that = this
-  tableGroups = []
+    const that = this
+    tableGroups = []
 
-  if ((this.options.groupBy) && (this.options.groupByField !== '')) {
+    if ((this.options.groupBy) && (this.options.groupByField !== '')) {
 
-    if ((this.options.sortName !== this.options.groupByField)) {
-      this.data.sort((a, b) => a[that.options.groupByField].localeCompare(b[that.options.groupByField]))
-    }
+      if ((this.options.sortName !== this.options.groupByField)) {
+        this.data.sort((a, b) => a[that.options.groupByField].localeCompare(b[that.options.groupByField]))
+      }
 
-    const groups = groupBy(that.data, item => [item[that.options.groupByField]])
+      const groups = UtilsGroupBy.groupBy(that.data, item => [item[that.options.groupByField]])
+      const fieldsSum = UtilsGroupBy.string2hash(this.options.groupBySum)
+      const fieldsCount = UtilsGroupBy.string2hash(this.options.groupByCount)
+      const fieldsAvg = UtilsGroupBy.string2hash(this.options.groupByAvg)
+      const allFields = Object.keys($.extend({}, fieldsSum, fieldsCount, fieldsAvg))
+
+      let index = 0
+      $.each(groups, (key, value) => {
+        tableGroups.push({
+          id: index,
+          name: key,
+          data: value
+        })
 
-    let index = 0
-    $.each(groups, (key, value) => {
-      tableGroups.push({
-        id: index,
-        name: key,
-        data: value
-      })
+        value.forEach(item => {
+          if (!item._data) {
+            item._data = {}
+          }
 
-      value.forEach(item => {
-        if (!item._data) {
-          item._data = {}
-        }
+          item._data['parent-index'] = index
+        })
 
-        item._data['parent-index'] = index
+        index++
       })
-
-      index++
-    })
+    }
   }
-}
 
-BootstrapTable.prototype.initBody = function (...args) {
-  initBodyCaller = true
+  initBody () {
+    initBodyCaller = true
 
-  _initBody.apply(this, Array.prototype.slice.apply(args))
-
-  if ((this.options.groupBy) && (this.options.groupByField !== '')) {
-    const that = this
-    let checkBox = false
-    let visibleColumns = 0
+    super.initBody()
 
-    this.columns.forEach(column => {
-      if (column.checkbox) {
-        checkBox = true
-      } else {
-        if (column.visible) {
-          visibleColumns += 1
+    if ((this.options.groupBy) && (this.options.groupByField !== '')) {
+      const that = this
+      let checkBox = false
+      let visibleColumns = 0
+
+      this.columns.forEach(column => {
+        if (column.checkbox) {
+          checkBox = true
+        } else {
+          if (column.visible) {
+            visibleColumns += 1
+          }
         }
-      }
-    })
-
-    if (this.options.detailView && !this.options.cardView) {
-      visibleColumns += 1
-    }
+      })
 
-    tableGroups.forEach(item => {
-      const html = []
+      if (this.options.detailView && !this.options.cardView) {
+        visibleColumns += 1
+      }
 
-      html.push(sprintf('<tr class="info groupBy expanded" data-group-index="%s">', item.id))
+      tableGroups.forEach(item => {
+        const html = []
 
-      if (that.options.detailView && !that.options.cardView) {
-        html.push('<td class="detail"></td>')
-      }
+        html.push(Utils.sprintf('<tr class="info groupBy expanded" data-group-index="%s">', item.id))
 
-      if (checkBox) {
-        html.push('<td class="bs-checkbox">',
-          '<input name="btSelectGroup" type="checkbox" />',
-          '</td>'
-        )
-      }
-      let formattedValue = item.name
-      if (typeof(that.options.groupByFormatter) === 'function') {
-        formattedValue = that.options.groupByFormatter(item.name, item.id, item.data)
-      }
-      html.push('<td',
-        sprintf(' colspan="%s"', visibleColumns),
-        '>', formattedValue, '</td>'
-      )
+        if (that.options.detailView && !that.options.cardView) {
+          html.push('<td class="detail"></td>')
+        }
 
-      html.push('</tr>')
+        if (checkBox) {
+          html.push('<td class="bs-checkbox">',
+            '<input name="btSelectGroup" type="checkbox" />',
+            '</td>'
+          )
+        }
+        let formattedValue = item.name
+        if (typeof(that.options.groupByFormatter) === 'function') {
+          formattedValue = that.options.groupByFormatter(item.name, item.id, item.data)
+        }
+        html.push(Utils.sprintf('<td colspan="%s">%s</td>', visibleColumns, formattedValue))
+        html.push('</tr>')
 
-      that.$body.find(`tr[data-parent-index=${item.id}]:first`).before($(html.join('')))
-    })
+        that.$body.find(`tr[data-parent-index=${item.id}]:first`).before($(html.join('')))
+      })
 
-    this.$selectGroup = []
-    this.$body.find('[name="btSelectGroup"]').each(function () {
-      const self = $(this)
+      this.$selectGroup = []
+      this.$body.find('[name="btSelectGroup"]').each(function () {
+        const self = $(this)
 
-      that.$selectGroup.push({
-        group: self,
-        item: that.$selectItem.filter(function () {
-          return ($(this).closest('tr').data('parent-index') ===
-                      self.closest('tr').data('group-index'))
+        that.$selectGroup.push({
+          group: self,
+          item: that.$selectItem.filter(function () {
+            return ($(this).closest('tr').data('parent-index') === self.closest('tr').data('group-index'))
+          })
         })
       })
-    })
 
-    this.$container.off('click', '.groupBy')
-      .on('click', '.groupBy', function () {
-        $(this).toggleClass('expanded')
-        that.$body.find(`tr[data-parent-index=${$(this).closest('tr').data('group-index')}]`).toggleClass('hidden')
-      })
+      this.$container.off('click', '.groupBy')
+        .on('click', '.groupBy', function () {
+          $(this).toggleClass('expanded')
+          that.$body.find(`tr[data-parent-index=${$(this).closest('tr').data('group-index')}]`).toggleClass('hidden')
+        })
 
-    this.$container.off('click', '[name="btSelectGroup"]')
-      .on('click', '[name="btSelectGroup"]', function (event) {
-        event.stopImmediatePropagation()
+      this.$container.off('click', '[name="btSelectGroup"]')
+        .on('click', '[name="btSelectGroup"]', function (event) {
+          event.stopImmediatePropagation()
 
-        const self = $(this)
-        const checked = self.prop('checked')
-        that[checked ? 'checkGroup' : 'uncheckGroup']($(this).closest('tr').data('group-index'))
-      })
-  }
+          const self = $(this)
+          const checked = self.prop('checked')
+          that[checked ? 'checkGroup' : 'uncheckGroup']($(this).closest('tr').data('group-index'))
+        })
+    }
 
-  initBodyCaller = false
-  this.updateSelected()
-}
+    initBodyCaller = false
+    this.updateSelected()
+  }
 
-BootstrapTable.prototype.updateSelected = function (...args) {
-  if (!initBodyCaller) {
-    _updateSelected.apply(this, Array.prototype.slice.apply(args))
+  updateSelected () {
+    if (!initBodyCaller) {
+      super.updateSelected()
 
-    if ((this.options.groupBy) && (this.options.groupByField !== '')) {
-      this.$selectGroup.forEach(item => {
-        const checkGroup = item.item.filter(':enabled').length ===
-                      item.item.filter(':enabled').filter(':checked').length
+      if ((this.options.groupBy) && (this.options.groupByField !== '')) {
+        this.$selectGroup.forEach(item => {
+          const checkGroup = item.item.filter(':enabled').length === item.item.filter(':enabled').filter(':checked').length
 
-        item.group.prop('checked', checkGroup)
-      })
+          item.group.prop('checked', checkGroup)
+        })
+      }
     }
   }
-}
-
-BootstrapTable.prototype.getGroupSelections = function (index) {
-  const that = this
-
-  return this.data.filter(row => row[that.header.stateField] && (row._data['parent-index'] === index))
-}
 
-BootstrapTable.prototype.checkGroup = function (index) {
-  this.checkGroup_(index, true)
-}
+  getGroupSelections (index) {
+    const that = this
 
-BootstrapTable.prototype.uncheckGroup = function (index) {
-  this.checkGroup_(index, false)
-}
+    return this.data.filter(row => row[that.header.stateField] && (row._data['parent-index'] === index))
+  }
 
-BootstrapTable.prototype.checkGroup_ = function (index, checked) {
-  let rows
-  const filter = function () {
-    return ($(this).closest('tr').data('parent-index') === index)
+  checkGroup (index) {
+    this.checkGroup_(index, true)
   }
 
-  if (!checked) {
-    rows = this.getGroupSelections(index)
+  uncheckGroup (index) {
+    this.checkGroup_(index, false)
   }
 
-  this.$selectItem.filter(filter).prop('checked', checked)
+  checkGroup_ (index, checked) {
+    let rows
+    const filter = function () {
+      return ($(this).closest('tr').data('parent-index') === index)
+    }
 
-  this.updateRows()
-  this.updateSelected()
-  if (checked) {
-    rows = this.getGroupSelections(index)
+    if (!checked) {
+      rows = this.getGroupSelections(index)
+    }
+
+    this.$selectItem.filter(filter).prop('checked', checked)
+
+    this.updateRows()
+    this.updateSelected()
+    if (checked) {
+      rows = this.getGroupSelections(index)
+    }
+    this.trigger(checked ? 'check-all' : 'uncheck-all', rows)
   }
-  this.trigger(checked ? 'check-all' : 'uncheck-all', rows)
 }