fix: 🐛 Always show vertical scrollbar
Decouple bodyScrollable from header. Now header position is synced based on scrollLeft of bodyScrollable. Also, remove redundant .dt-body container.
This commit is contained in:
parent
1791b30077
commit
fb4370020f
@ -1,5 +1,4 @@
|
||||
import HyperList from 'hyperlist';
|
||||
import $ from './dom';
|
||||
|
||||
export default class BodyRenderer {
|
||||
constructor(instance) {
|
||||
@ -9,7 +8,6 @@ export default class BodyRenderer {
|
||||
this.rowmanager = instance.rowmanager;
|
||||
this.cellmanager = instance.cellmanager;
|
||||
this.bodyScrollable = instance.bodyScrollable;
|
||||
this.bodyDiv = $('.dt-body', this.bodyScrollable);
|
||||
this.footer = this.instance.footer;
|
||||
this.log = instance.log;
|
||||
}
|
||||
@ -39,9 +37,9 @@ export default class BodyRenderer {
|
||||
};
|
||||
|
||||
if (!this.hyperlist) {
|
||||
this.hyperlist = new HyperList(this.bodyDiv, config);
|
||||
this.hyperlist = new HyperList(this.bodyScrollable, config);
|
||||
} else {
|
||||
this.hyperlist.refresh(this.bodyDiv, config);
|
||||
this.hyperlist.refresh(this.bodyScrollable, config);
|
||||
}
|
||||
|
||||
this.renderFooter();
|
||||
@ -113,16 +111,6 @@ export default class BodyRenderer {
|
||||
this.instance.toastMessage.innerHTML = '';
|
||||
}
|
||||
|
||||
getBodyHTML(rows) {
|
||||
return `
|
||||
<div class="dt-body">
|
||||
<div>
|
||||
${rows.map(row => this.rowmanager.getRowHTML(row, row.meta)).join('')}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
getNoDataHTML() {
|
||||
return `<div class="dt-scrollable__no-data">${this.options.noDataMessage}</div>`;
|
||||
}
|
||||
|
||||
@ -69,13 +69,9 @@ class DataTable {
|
||||
prepareDom() {
|
||||
this.wrapper.innerHTML = `
|
||||
<div class="datatable">
|
||||
<div class="dt-header">
|
||||
</div>
|
||||
<div class="dt-scrollable">
|
||||
<div class="dt-body"></div>
|
||||
</div>
|
||||
<div class="dt-footer">
|
||||
</div>
|
||||
<div class="dt-header"></div>
|
||||
<div class="dt-scrollable"></div>
|
||||
<div class="dt-footer"></div>
|
||||
<div class="dt-freeze">
|
||||
<span class="dt-freeze__message">
|
||||
${this.options.freezeMessage}
|
||||
|
||||
@ -26,25 +26,17 @@
|
||||
|
||||
.datatable {
|
||||
position: relative;
|
||||
overflow: auto;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.dt-header {
|
||||
border-collapse: collapse;
|
||||
border-bottom: 1px solid var(--dt-border-color);
|
||||
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.dt-body {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.dt-scrollable {
|
||||
height: 40vw;
|
||||
overflow: auto;
|
||||
border-top: 1px solid var(--dt-border-color);
|
||||
|
||||
&--highlight-all {
|
||||
background-color: var(--dt-selection-highlight-color);
|
||||
|
||||
47
src/style.js
47
src/style.js
@ -23,6 +23,7 @@ export default class Style {
|
||||
this.styleEl = styleEl;
|
||||
|
||||
this.bindResizeWindow();
|
||||
this.bindScrollHeader();
|
||||
}
|
||||
|
||||
get stylesheet() {
|
||||
@ -38,10 +39,27 @@ export default class Style {
|
||||
}
|
||||
}
|
||||
|
||||
bindScrollHeader() {
|
||||
this._settingHeaderPosition = false;
|
||||
|
||||
$.on(this.bodyScrollable, 'scroll', (e) => {
|
||||
if (this._settingHeaderPosition) return;
|
||||
|
||||
this._settingHeaderPosition = true;
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
const scrollLeft = e.target.scrollLeft;
|
||||
$.style(this.header, {
|
||||
transform: `translateX(-${scrollLeft}px)`
|
||||
});
|
||||
this._settingHeaderPosition = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
onWindowResize() {
|
||||
this.distributeRemainingWidth();
|
||||
this.refreshColumnWidth();
|
||||
this.compensateScrollbarWidth();
|
||||
this.setBodyStyle();
|
||||
}
|
||||
|
||||
@ -124,7 +142,6 @@ export default class Style {
|
||||
this.setupColumnWidth();
|
||||
this.distributeRemainingWidth();
|
||||
this.setColumnStyle();
|
||||
this.compensateScrollbarWidth();
|
||||
this.setBodyStyle();
|
||||
}
|
||||
|
||||
@ -224,22 +241,13 @@ export default class Style {
|
||||
}
|
||||
}
|
||||
|
||||
compensateScrollbarWidth() {
|
||||
if (!$.hasVerticalOverflow($('.dt-body', this.bodyScrollable))) return;
|
||||
|
||||
const scrollbarWidth = $.scrollbarWidth();
|
||||
const lastCol = this.datamanager.getColumn(-1);
|
||||
const width = lastCol.width - scrollbarWidth;
|
||||
this.columnmanager.setColumnWidth(lastCol.colIndex, width);
|
||||
}
|
||||
|
||||
distributeRemainingWidth() {
|
||||
if (this.options.layout !== 'fluid') return;
|
||||
|
||||
const wrapperWidth = $.style(this.instance.datatableWrapper, 'width');
|
||||
const headerWidth = $.style(this.header, 'width');
|
||||
const firstRowWidth = $.style($('.dt-row', this.bodyScrollable), 'width');
|
||||
const resizableColumns = this.datamanager.getColumns().filter(col => col.resizable);
|
||||
const deltaWidth = (wrapperWidth - headerWidth) / resizableColumns.length;
|
||||
const deltaWidth = (wrapperWidth - firstRowWidth) / resizableColumns.length;
|
||||
|
||||
resizableColumns.map(col => {
|
||||
const width = $.style(this.getColumnHeaderElement(col.colIndex), 'width');
|
||||
@ -281,8 +289,11 @@ export default class Style {
|
||||
}
|
||||
|
||||
setBodyStyle() {
|
||||
const width = $.style(this.header, 'width');
|
||||
const bodyWidth = $.style(this.datatableWrapper, 'width');
|
||||
const firstRow = $('.dt-row', this.bodyScrollable);
|
||||
const rowWidth = $.style(firstRow, 'width');
|
||||
|
||||
let width = bodyWidth > rowWidth ? rowWidth : bodyWidth;
|
||||
$.style(this.bodyScrollable, {
|
||||
width: width + 'px'
|
||||
});
|
||||
@ -300,9 +311,11 @@ export default class Style {
|
||||
});
|
||||
}
|
||||
|
||||
$.style(this.bodyScrollable, {
|
||||
marginTop: $.style(this.header, 'height') + 'px'
|
||||
});
|
||||
if (this.options.layout === 'fluid') {
|
||||
$.style(this.bodyScrollable, {
|
||||
overflowX: 'hidden'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
getColumnHeaderElement(colIndex) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user