bootstrap-table-sticky-header.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. /**
  2. * @author vincent loh <vincent.ml@gmail.com>
  3. * @update J Manuel Corona <jmcg92@gmail.com>
  4. * @update zhixin wen <wenzhixin2010@gmail.com>
  5. */
  6. const Utils = $.fn.bootstrapTable.utils
  7. $.extend($.fn.bootstrapTable.defaults, {
  8. stickyHeader: false,
  9. stickyHeaderOffsetY: 0,
  10. stickyHeaderOffsetLeft: 0,
  11. stickyHeaderOffsetRight: 0
  12. })
  13. $.BootstrapTable = class extends $.BootstrapTable {
  14. initHeader (...args) {
  15. super.initHeader(...args)
  16. if (!this.options.stickyHeader) {
  17. return
  18. }
  19. this.$el.before('<div class="sticky-header-container"></div>')
  20. this.$el.before('<div class="sticky_anchor_begin"></div>')
  21. this.$el.after('<div class="sticky_anchor_end"></div>')
  22. this.$header.addClass('sticky-header')
  23. // clone header just once, to be used as sticky header
  24. // deep clone header, using source header affects tbody>td width
  25. this.$stickyContainer = this.$tableBody.find('.sticky-header-container')
  26. this.$stickyBegin = this.$tableBody.find('.sticky_anchor_begin')
  27. this.$stickyEnd = this.$tableBody.find('.sticky_anchor_end')
  28. this.$stickyHeader = this.$header.clone(true, true)
  29. // render sticky on window scroll or resize
  30. $(window).off('resize.sticky-header-table')
  31. .on('resize.sticky-header-table', () => this.renderStickyHeader())
  32. $(window).off('scroll.sticky-header-table')
  33. .on('scroll.sticky-header-table', () => this.renderStickyHeader())
  34. this.$tableBody.off('scroll').on('scroll', () => this.matchPositionX())
  35. }
  36. onColumnSearch ({currentTarget, keyCode}) {
  37. super.onColumnSearch({currentTarget, keyCode})
  38. this.renderStickyHeader()
  39. }
  40. resetView (...args) {
  41. super.resetView(...args)
  42. $('.bootstrap-table.fullscreen').off('scroll')
  43. .on('scroll', () => this.renderStickyHeader())
  44. }
  45. renderStickyHeader () {
  46. const that = this
  47. this.$stickyHeader = this.$header.clone(true, true)
  48. if (this.options.filterControl) {
  49. $(this.$stickyHeader).off('keyup change mouseup').on('keyup change mouse', function (e) {
  50. const $target = $(e.target)
  51. const value = $target.val()
  52. const field = $target.parents('th').data('field')
  53. const $coreTh = that.$header.find('th[data-field="' + field + '"]')
  54. if ($target.is('input')) {
  55. $coreTh.find('input').val(value)
  56. } else if ($target.is('select')) {
  57. const $select = $coreTh.find('select')
  58. $select.find('option[selected]').removeAttr('selected')
  59. $select.find('option[value="' + value + '"]').attr('selected', true)
  60. }
  61. that.triggerSearch()
  62. })
  63. }
  64. const top = $(window).scrollTop()
  65. // top anchor scroll position, minus header height
  66. const start = this.$stickyBegin.offset().top - this.options.stickyHeaderOffsetY
  67. // bottom anchor scroll position, minus header height, minus sticky height
  68. const end = this.$stickyEnd.offset().top - this.options.stickyHeaderOffsetY - this.$header.height()
  69. // show sticky when top anchor touches header, and when bottom anchor not exceeded
  70. if (top > start && top <= end) {
  71. // ensure clone and source column widths are the same
  72. this.$stickyHeader.find('tr:eq(0)').find('th').each((index, el) => {
  73. $(el).css('min-width', this.$header.find('tr:eq(0)').find('th').eq(index).css('width'))
  74. })
  75. // match bootstrap table style
  76. this.$stickyContainer.show().addClass('fix-sticky fixed-table-container')
  77. // stick it in position
  78. let stickyHeaderOffsetLeft = this.options.stickyHeaderOffsetLeft
  79. let stickyHeaderOffsetRight = this.options.stickyHeaderOffsetRight
  80. if (this.$el.closest('.bootstrap-table').hasClass('fullscreen')) {
  81. stickyHeaderOffsetLeft = 0
  82. stickyHeaderOffsetRight = 0
  83. }
  84. this.$stickyContainer.css('top', `${this.options.stickyHeaderOffsetY}`)
  85. this.$stickyContainer.css('left', `${stickyHeaderOffsetLeft}`)
  86. this.$stickyContainer.css('right', `${stickyHeaderOffsetRight}`)
  87. // create scrollable container for header
  88. this.$stickyTable = $('<table/>')
  89. this.$stickyTable.addClass(this.options.classes)
  90. // append cloned header to dom
  91. this.$stickyContainer.html(this.$stickyTable.append(this.$stickyHeader))
  92. // match clone and source header positions when left-right scroll
  93. this.matchPositionX()
  94. } else {
  95. this.$stickyContainer.removeClass('fix-sticky').hide()
  96. }
  97. }
  98. matchPositionX () {
  99. this.$stickyContainer.scrollLeft(this.$tableBody.scrollLeft())
  100. }
  101. }