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:
Faris Ansari 2018-12-13 16:37:50 +05:30
parent 1791b30077
commit fb4370020f
4 changed files with 37 additions and 48 deletions

View File

@ -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>`;
}

View File

@ -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}

View File

@ -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);

View File

@ -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) {