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 HyperList from 'hyperlist';
import $ from './dom';
export default class BodyRenderer { export default class BodyRenderer {
constructor(instance) { constructor(instance) {
@ -9,7 +8,6 @@ export default class BodyRenderer {
this.rowmanager = instance.rowmanager; this.rowmanager = instance.rowmanager;
this.cellmanager = instance.cellmanager; this.cellmanager = instance.cellmanager;
this.bodyScrollable = instance.bodyScrollable; this.bodyScrollable = instance.bodyScrollable;
this.bodyDiv = $('.dt-body', this.bodyScrollable);
this.footer = this.instance.footer; this.footer = this.instance.footer;
this.log = instance.log; this.log = instance.log;
} }
@ -39,9 +37,9 @@ export default class BodyRenderer {
}; };
if (!this.hyperlist) { if (!this.hyperlist) {
this.hyperlist = new HyperList(this.bodyDiv, config); this.hyperlist = new HyperList(this.bodyScrollable, config);
} else { } else {
this.hyperlist.refresh(this.bodyDiv, config); this.hyperlist.refresh(this.bodyScrollable, config);
} }
this.renderFooter(); this.renderFooter();
@ -113,16 +111,6 @@ export default class BodyRenderer {
this.instance.toastMessage.innerHTML = ''; 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() { getNoDataHTML() {
return `<div class="dt-scrollable__no-data">${this.options.noDataMessage}</div>`; return `<div class="dt-scrollable__no-data">${this.options.noDataMessage}</div>`;
} }

View File

@ -69,13 +69,9 @@ class DataTable {
prepareDom() { prepareDom() {
this.wrapper.innerHTML = ` this.wrapper.innerHTML = `
<div class="datatable"> <div class="datatable">
<div class="dt-header"> <div class="dt-header"></div>
</div> <div class="dt-scrollable"></div>
<div class="dt-scrollable"> <div class="dt-footer"></div>
<div class="dt-body"></div>
</div>
<div class="dt-footer">
</div>
<div class="dt-freeze"> <div class="dt-freeze">
<span class="dt-freeze__message"> <span class="dt-freeze__message">
${this.options.freezeMessage} ${this.options.freezeMessage}

View File

@ -26,25 +26,17 @@
.datatable { .datatable {
position: relative; position: relative;
overflow: auto; overflow: hidden;
} }
.dt-header { .dt-header {
border-collapse: collapse; border-collapse: collapse;
border-bottom: 1px solid var(--dt-border-color);
position: absolute;
top: 0;
left: 0;
}
.dt-body {
border-collapse: collapse;
} }
.dt-scrollable { .dt-scrollable {
height: 40vw; height: 40vw;
overflow: auto; overflow: auto;
border-top: 1px solid var(--dt-border-color);
&--highlight-all { &--highlight-all {
background-color: var(--dt-selection-highlight-color); background-color: var(--dt-selection-highlight-color);

View File

@ -23,6 +23,7 @@ export default class Style {
this.styleEl = styleEl; this.styleEl = styleEl;
this.bindResizeWindow(); this.bindResizeWindow();
this.bindScrollHeader();
} }
get stylesheet() { 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() { onWindowResize() {
this.distributeRemainingWidth(); this.distributeRemainingWidth();
this.refreshColumnWidth(); this.refreshColumnWidth();
this.compensateScrollbarWidth();
this.setBodyStyle(); this.setBodyStyle();
} }
@ -124,7 +142,6 @@ export default class Style {
this.setupColumnWidth(); this.setupColumnWidth();
this.distributeRemainingWidth(); this.distributeRemainingWidth();
this.setColumnStyle(); this.setColumnStyle();
this.compensateScrollbarWidth();
this.setBodyStyle(); 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() { distributeRemainingWidth() {
if (this.options.layout !== 'fluid') return; if (this.options.layout !== 'fluid') return;
const wrapperWidth = $.style(this.instance.datatableWrapper, 'width'); 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 resizableColumns = this.datamanager.getColumns().filter(col => col.resizable);
const deltaWidth = (wrapperWidth - headerWidth) / resizableColumns.length; const deltaWidth = (wrapperWidth - firstRowWidth) / resizableColumns.length;
resizableColumns.map(col => { resizableColumns.map(col => {
const width = $.style(this.getColumnHeaderElement(col.colIndex), 'width'); const width = $.style(this.getColumnHeaderElement(col.colIndex), 'width');
@ -281,8 +289,11 @@ export default class Style {
} }
setBodyStyle() { 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, { $.style(this.bodyScrollable, {
width: width + 'px' width: width + 'px'
}); });
@ -300,9 +311,11 @@ export default class Style {
}); });
} }
$.style(this.bodyScrollable, { if (this.options.layout === 'fluid') {
marginTop: $.style(this.header, 'height') + 'px' $.style(this.bodyScrollable, {
}); overflowX: 'hidden'
});
}
} }
getColumnHeaderElement(colIndex) { getColumnHeaderElement(colIndex) {