UNPKG

bootstrap-table

Version:

An extended table to integration with some of the most widely used CSS frameworks. (Supports Bootstrap, Semantic UI, Bulma, Material Design, Foundation)

318 lines (248 loc) 8.66 kB
/** * @author: Yura Knoxville * @version: v1.1.0 */ const Utils = $.fn.bootstrapTable.utils let initBodyCaller const groupBy = (array, f) => { const tmpGroups = {} array.forEach(o => { const groups = f(o) tmpGroups[groups] = tmpGroups[groups] || [] tmpGroups[groups].push(o) }) return tmpGroups } Object.assign($.fn.bootstrapTable.defaults.icons, { collapseGroup: { bootstrap3: 'glyphicon-chevron-up', bootstrap5: 'bi-chevron-up', materialize: 'arrow_drop_down' }[$.fn.bootstrapTable.theme] || 'fa-angle-up', expandGroup: { bootstrap3: 'glyphicon-chevron-down', bootstrap5: 'bi-chevron-down', materialize: 'arrow_drop_up' }[$.fn.bootstrapTable.theme] || 'fa-angle-down' }) Object.assign($.fn.bootstrapTable.defaults, { groupBy: false, groupByField: '', groupByFormatter: undefined, groupByToggle: false, groupByShowToggleIcon: false, groupByCollapsedGroups: [] }) const BootstrapTable = $.fn.bootstrapTable.Constructor const _initSort = BootstrapTable.prototype.initSort const _initBody = BootstrapTable.prototype.initBody const _updateSelected = BootstrapTable.prototype.updateSelected BootstrapTable.prototype.initSort = function (...args) { _initSort.apply(this, Array.prototype.slice.apply(args)) const that = this this.tableGroups = [] if (this.options.groupBy && this.options.groupByField !== '') { if (this.options.sortName !== this.options.groupByField) { if (this.options.customSort) { Utils.calculateObjectValue(this.options, this.options.customSort, [ this.options.sortName, this.options.sortOrder, this.data ]) } else { this.options.data.sort((a, b) => { const groupByFields = this.getGroupByFields() const fieldValuesA = [] const fieldValuesB = [] $.each(groupByFields, (i, field) => { fieldValuesA.push(a[field]) fieldValuesB.push(b[field]) }) a = fieldValuesA.join() b = fieldValuesB.join() return a.localeCompare(b, undefined, { numeric: true }) }) } } const groups = groupBy(that.data, item => { const groupByFields = this.getGroupByFields() const groupValues = [] $.each(groupByFields, (i, field) => { const value_ = Utils.getItemField(item, field, that.options.escape, item.escape) groupValues.push(value_) }) return groupValues.join(', ') }) let index = 0 $.each(groups, (key, value) => { this.tableGroups.push({ id: index, name: key, data: value }) value.forEach(item => { if (!item._data) { item._data = {} } if (this.isCollapsed(key, value)) { item._class += ' hidden' } item._data['parent-index'] = index }) index++ }) } } BootstrapTable.prototype.initBody = function (...args) { 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 this.columns.forEach(column => { if (column.checkbox) { checkBox = true } else if (column.visible) { visibleColumns += 1 } }) if (this.options.detailView && !this.options.cardView) { visibleColumns += 1 } this.tableGroups.forEach(item => { const html = [] html.push(Utils.sprintf('<tr class="info group-by %s" data-group-index="%s">', this.options.groupByToggle ? 'expanded' : '', item.id)) if (that.options.detailView && !that.options.cardView) { html.push('<td class="detail"></td>') } if (checkBox) { html.push('<td class="bs-checkbox">', '<input name="btSelectGroup" type="checkbox" />', '</td>' ) } let formattedValue = item.name if (that.options.groupByFormatter !== undefined) { formattedValue = Utils.calculateObjectValue(that.options, that.options.groupByFormatter, [item.name, item.id, item.data]) } html.push('<td', Utils.sprintf(' colspan="%s"', visibleColumns), '>', formattedValue ) let icon = this.options.icons.collapseGroup if (this.isCollapsed(item.name, item.data)) { icon = this.options.icons.expandGroup } if (this.options.groupByToggle && this.options.groupByShowToggleIcon) { html.push(`<span class="float-right ${this.options.iconsPrefix} ${icon}"></span>`) } html.push('</td></tr>') 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) that.$selectGroup.push({ group: self, item: that.$selectItem.filter(function () { return $(this).closest('tr').data('parent-index') === self.closest('tr').data('group-index') }) }) }) if (this.options.groupByToggle) { this.$container.off('click', '.group-by') .on('click', '.group-by', function () { const $this = $(this) const groupIndex = $this.closest('tr').data('group-index') const $groupRows = that.$body.find(`tr[data-parent-index=${groupIndex}]`) $this.toggleClass('expanded collapsed') $this.find('span').toggleClass(`${that.options.icons.collapseGroup} ${that.options.icons.expandGroup}`) $groupRows.toggleClass('hidden') $groupRows.each((i, element) => that.collapseRow($(element).data('index'))) }) } 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')) }) } initBodyCaller = false this.updateSelected() } BootstrapTable.prototype.updateSelected = function (...args) { if (!initBodyCaller) { _updateSelected.apply(this, Array.prototype.slice.apply(args)) 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) }) } } } BootstrapTable.prototype.checkGroup = function (index) { this.checkGroup_(index, true) } BootstrapTable.prototype.uncheckGroup = function (index) { this.checkGroup_(index, false) } BootstrapTable.prototype.isCollapsed = function (groupKey, items) { if (this.options.groupByCollapsedGroups) { const collapsedGroups = Utils.calculateObjectValue(this, this.options.groupByCollapsedGroups, [groupKey, items], true) if ($.inArray(groupKey, collapsedGroups) > -1) { return true } } return false } BootstrapTable.prototype.checkGroup_ = function (index, checked) { const rowsBefore = this.getSelections() const filter = function () { return $(this).closest('tr').data('parent-index') === index } this.$selectItem.filter(filter).prop('checked', checked) this.updateRows() this.updateSelected() const rowsAfter = this.getSelections() if (checked) { this.trigger('check-all', rowsAfter, rowsBefore) return } this.trigger('uncheck-all', rowsAfter, rowsBefore) } BootstrapTable.prototype.getGroupByFields = function () { let groupByFields = this.options.groupByField if (!$.isArray(this.options.groupByField)) { groupByFields = [this.options.groupByField] } return groupByFields } $.BootstrapTable = class extends $.BootstrapTable { scrollTo (params) { if (this.options.groupBy) { let options = { unit: 'px', value: 0 } if (typeof params === 'object') { options = Object.assign(options, params) } if (options.unit === 'rows') { let scrollTo = 0 this.$body.find(`> tr:not(.group-by):lt(${options.value})`).each((i, el) => { scrollTo += $(el).outerHeight(true) }) const $targetColumn = this.$body.find(`> tr:not(.group-by):eq(${options.value})`) $targetColumn.prevAll('.group-by').each((i, el) => { scrollTo += $(el).outerHeight(true) }) this.$tableBody.scrollTop(scrollTo) return } } super.scrollTo(params) } }