ui/lib/shared/addon/mixins/sticky-table-header.js

169 lines
4.4 KiB
JavaScript

import Mixin from '@ember/object/mixin';
import { throttle } from '@ember/runloop';
import $ from 'jquery';
import ThrottledResize from 'shared/mixins/throttled-resize';
const tableProps = {
actionsHeight: 60,
fixedHeaderHeight: 40,
};
export default Mixin.create(ThrottledResize, {
stickyHeader: true,
subRow: false,
init() {
this._super(...arguments);
},
didInsertElement() {
this._super(...arguments);
this.buildTableWidths();
if (this.get('showHeader')) {
$(this.element).find('> table > thead > .fixed-header-actions, > table > thead > .fixed-header').css('width', $(this.element).find('> table').outerWidth());
}
// Removing the sticket header functionality for now
// if ( !this.get('stickyHeader') ) {
// return;
// }
// this.set('_boundScroll', this._scroll.bind(this));
// $(window).on('scroll', this.get('_boundScroll'));
},
_boundScroll: null,
_scroll() {
throttle(() => {
this.updateHeaders();
}, 30);
},
willDestroyElement() {
this._super(...arguments);
// Removing the sticket header functionality for now
// if ( !this.get('stickyHeader') ) {
// return;
// }
// $(window).off('scroll', this.get('_boundScroll'));
},
onResize() {
this._super(...arguments);
this.buildTableWidths();
},
buildTableWidths() {
if ($(this.element).is(':visible')) {
let ths = $(this.element).find('> table > thead > tr.fixed-header > th');
let $fixHdr = $(this.element).find('> table > thead > .fixed-header-actions, > table > thead > .fixed-header');
$(this.element).find('> table > thead > tr.fixed-header-placeholder > th').each((idx, th) => {
$(ths[idx]).attr('width', $(th).outerWidth());
});
if (this.get('showHeader')) {
$fixHdr.css({ 'width': $(this.element).find('> table').width(), });
if ($fixHdr.is(':visible')) {
$(this.element).find('.search-group').show(1, 'linear');
}
}
}
},
tearDownTableWidths() {
if ( !this.get('stickyHeader') ) {
return;
}
$(this.element).find('> table > thead > tr.fixed-header > th').each((idx, td) => {
$(td).removeAttr('width');
});
},
positionHeaders() {
if ( !this.get('stickyHeader') ) {
return;
}
let elem = $(this.element);
let $table = elem.find('> table');
let $actionRow = $table.find('> thead > .fixed-header-actions');
let $fixedHeader = $table.find('> thead > tr.fixed-header');
let showHeader = this.get('showHeader');
let fudge = (this.get('subRow') ? 100 : 0);
if (showHeader) {
$actionRow.css({
'position': 'fixed',
'top': fudge,
'height': `${ tableProps.actionsHeight }px`,
});
}
$fixedHeader.css({
'position': 'fixed',
'top': `${ showHeader && this.get('bulkActions') ? fudge + tableProps.actionsHeight : 0 }px`,
'height': `${ tableProps.fixedHeaderHeight }px`,
});
elem.css({ 'padding-top': `${ tableProps.actionsHeight + tableProps.fixedHeaderHeight }px` });
},
removePositions() {
if ( !this.get('stickyHeader') ) {
return;
}
let elem = $(this.element);
let $table = elem.find('> table');
let $actionRow = $table.find('> thead > .fixed-header-actions');
let $fixedHeader = $table.find('> thead > tr.fixed-header');
if (this.get('showHeader')) {
$actionRow.css({
'position': 'relative',
'top': '',
});
}
$fixedHeader.css({
'position': '',
'top': '',
});
elem.css({ 'padding-top': '' });
this.buildTableWidths();
},
updateHeaders() {
if ( !this.get('stickyHeader') ) {
return;
}
let elem = $(this.element);
let $table = elem.find('> table');
let $floatingHeader = $table.find('> thead > tr.fixed-header');
let $scrollTop = $(window).scrollTop();
let containerBottom = $table.height() + $table.offset().top;
let offset = elem.find('> table > thead > tr').offset().top - parseInt(elem.css('padding-top'), 10);
if ($scrollTop < containerBottom && $scrollTop > offset) {
if ($floatingHeader.css('position') !== 'fixed') {
this.buildTableWidths();
this.positionHeaders();
}
} else {
if ($floatingHeader.css('position') === 'fixed') {
this.tearDownTableWidths();
this.removePositions();
}
}
}
});