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)

156 lines (128 loc) 5.63 kB
/** * @author vincent loh <vincent.ml@gmail.com> * @update J Manuel Corona <jmcg92@gmail.com> * @update zhixin wen <wenzhixin2010@gmail.com> */ const Utils = $.fn.bootstrapTable.utils $.extend($.fn.bootstrapTable.defaults, { stickyHeader: false, stickyHeaderOffsetY: 0, stickyHeaderOffsetLeft: 0, stickyHeaderOffsetRight: 0 }) $.BootstrapTable = class extends $.BootstrapTable { initHeader (...args) { super.initHeader(...args) if (!this.options.stickyHeader) { return } this.$tableBody.find('.sticky-header-container,.sticky_anchor_begin,.sticky_anchor_end').remove() this.$el.before('<div class="sticky-header-container"></div>') this.$el.before('<div class="sticky_anchor_begin"></div>') this.$el.after('<div class="sticky_anchor_end"></div>') this.$header.addClass('sticky-header') // clone header just once, to be used as sticky header // deep clone header, using source header affects tbody>td width this.$stickyContainer = this.$tableBody.find('.sticky-header-container') this.$stickyBegin = this.$tableBody.find('.sticky_anchor_begin') this.$stickyEnd = this.$tableBody.find('.sticky_anchor_end') this.$stickyHeader = this.$header.clone(true, true) // render sticky on window scroll or resize const resizeEvent = Utils.getEventName('resize.sticky-header-table', this.$el.attr('id')) const scrollEvent = Utils.getEventName('scroll.sticky-header-table', this.$el.attr('id')) $(window).off(resizeEvent).on(resizeEvent, () => this.renderStickyHeader()) $(window).off(scrollEvent).on(scrollEvent, () => this.renderStickyHeader()) this.$tableBody.off('scroll').on('scroll', () => this.matchPositionX()) } onColumnSearch ({ currentTarget, keyCode }) { super.onColumnSearch({ currentTarget, keyCode }) this.renderStickyHeader() } resetView (...args) { super.resetView(...args) $('.bootstrap-table.fullscreen').off('scroll') .on('scroll', () => this.renderStickyHeader()) } getCaret (...args) { super.getCaret(...args) if (this.$stickyHeader) { const $ths = this.$stickyHeader.find('th') this.$header.find('th').each((i, th) => { $ths.eq(i).find('.sortable').attr('class', $(th).find('.sortable').attr('class')) }) } } horizontalScroll () { super.horizontalScroll() this.$tableBody.on('scroll', () => this.matchPositionX()) } renderStickyHeader () { const that = this this.$stickyHeader = this.$header.clone(true, true) if (this.options.filterControl) { $(this.$stickyHeader).off('keyup change mouseup').on('keyup change mouse', function (e) { const $target = $(e.target) const value = $target.val() const field = $target.parents('th').data('field') const $coreTh = that.$header.find(`th[data-field="${ field }"]`) if ($target.is('input')) { $coreTh.find('input').val(value) } else if ($target.is('select')) { const $select = $coreTh.find('select') $select.find('option[selected]').removeAttr('selected') $select.find(`option[value="${ value }"]`).attr('selected', true) } that.triggerSearch() }) } const top = $(window).scrollTop() // top anchor scroll position, minus header height const start = this.$stickyBegin.offset().top - this.options.stickyHeaderOffsetY // bottom anchor scroll position, minus header height, minus sticky height const end = this.$stickyEnd.offset().top - this.options.stickyHeaderOffsetY - this.$header.height() // show sticky when top anchor touches header, and when bottom anchor not exceeded if (top > start && top <= end) { // ensure clone and source column widths are the same this.$stickyHeader.find('tr').each((indexRows, rows) => { const columns = $(rows).find('th') columns.each((indexColumns, celd) => { $(celd).css('min-width', this.$header.find(`tr:eq(${indexRows})`).find(`th:eq(${indexColumns})`).css('width')) }) }) // match bootstrap table style this.$stickyContainer.show().addClass('fix-sticky fixed-table-container') // stick it in position const coords = this.$tableBody[0].getBoundingClientRect() let width = '100%' let stickyHeaderOffsetLeft = this.options.stickyHeaderOffsetLeft let stickyHeaderOffsetRight = this.options.stickyHeaderOffsetRight if (!stickyHeaderOffsetLeft) { stickyHeaderOffsetLeft = coords.left } if (!stickyHeaderOffsetRight) { width = `${coords.width}px` } if (this.$el.closest('.bootstrap-table').hasClass('fullscreen')) { stickyHeaderOffsetLeft = 0 stickyHeaderOffsetRight = 0 width = '100%' } this.$stickyContainer.css('top', `${this.options.stickyHeaderOffsetY}px`) this.$stickyContainer.css('left', `${stickyHeaderOffsetLeft}px`) this.$stickyContainer.css('right', `${stickyHeaderOffsetRight}px`) this.$stickyContainer.css('width', `${width}`) // create scrollable container for header this.$stickyTable = $('<table/>') this.$stickyTable.addClass(this.options.classes) // append cloned header to dom this.$stickyContainer.html(this.$stickyTable.append(this.$stickyHeader)) // match clone and source header positions when left-right scroll this.matchPositionX() } else { this.$stickyContainer.removeClass('fix-sticky').hide() } } matchPositionX () { this.$stickyContainer.scrollLeft(this.$tableBody.scrollLeft()) } }