Compare commits

...

1 Commits

Author SHA1 Message Date
Faris Ansari
91243d525c First cut 2018-05-28 06:51:37 +05:30
7 changed files with 148 additions and 31 deletions

File diff suppressed because one or more lines are too long

View File

@ -10,6 +10,7 @@ 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.datatableWrapperLeft = instance.datatableWrapperLeft;
this.log = instance.log; this.log = instance.log;
this.appendRemainingData = nextTick(this.appendRemainingData, this); this.appendRemainingData = nextTick(this.appendRemainingData, this);
} }
@ -20,6 +21,11 @@ export default class BodyRenderer {
} else { } else {
this.renderBodyHTML(); this.renderBodyHTML();
} }
this.renderLeftColumns();
}
renderLeftColumns() {
$('.dt-scrollable', this.datatableWrapperLeft).innerHTML = this.getLeftBodyHTML();
} }
renderBodyHTML() { renderBodyHTML() {
@ -48,7 +54,7 @@ export default class BodyRenderer {
this.clusterize = new Clusterize({ this.clusterize = new Clusterize({
rows: initialData, rows: initialData,
scrollElem: this.bodyScrollable, scrollElem: this.bodyScrollable,
contentElem: $('tbody', this.bodyScrollable), contentElem: $('.dt-body', this.bodyScrollable),
callbacks: { callbacks: {
clusterChanged: () => this.restoreState() clusterChanged: () => this.restoreState()
}, },
@ -106,6 +112,26 @@ export default class BodyRenderer {
`; `;
} }
getLeftBodyHTML(rows) {
if (!rows) rows = this.datamanager.getRowsForView();
const columns = this.datamanager.getColumns();
const leftColumns = columns.filter(col => {
return (col.id === '_checkbox' || col.id === '_rowIndex' || col.fixed);
}).map(col => col.colIndex);
return `
<table class="dt-body">
<tbody>
${rows.map(row => {
const leftRow = row.filter(cell => leftColumns.includes(cell.colIndex));
return this.rowmanager.getRowHTML(leftRow, row.meta);
}).join('')}
</tbody>
</table>
`;
}
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

@ -17,22 +17,25 @@ export default class ColumnManager {
'style', 'style',
'wrapper', 'wrapper',
'rowmanager', 'rowmanager',
'bodyScrollable' 'bodyScrollable',
'datatableWrapperLeft'
]); ]);
this.bindEvents(); this.bindEvents();
} }
renderHeader() { renderHeader() {
this.header.innerHTML = '<thead></thead>';
this.refreshHeader(); this.refreshHeader();
this.refreshHeaderLeft();
} }
refreshHeader() { refreshHeader() {
const columns = this.datamanager.getColumns(); const columns = this.datamanager.getColumns();
// refresh html // refresh html
$('thead', this.header).innerHTML = this.getHeaderHTML(columns); this.header.innerHTML = `
<thead>${this.getHeaderHTML(columns)}</thead>
`;
this.$filterRow = $('.dt-row[data-is-filter]', this.header); this.$filterRow = $('.dt-row[data-is-filter]', this.header);
if (this.$filterRow) { if (this.$filterRow) {
@ -43,6 +46,16 @@ export default class ColumnManager {
this.bindMoveColumn(); this.bindMoveColumn();
} }
refreshHeaderLeft() {
let columns = this.datamanager.getColumns();
const leftColumns = columns.filter(col => {
return (col.id === '_checkbox' || col.id === '_rowIndex' || col.fixed);
});
$('.dt-header', this.datatableWrapperLeft).innerHTML = this.getHeaderHTML(leftColumns);
}
getHeaderHTML(columns) { getHeaderHTML(columns) {
let html = this.rowmanager.getRowHTML(columns, { let html = this.rowmanager.getRowHTML(columns, {
isHeader: 1 isHeader: 1
@ -315,8 +328,13 @@ export default class ColumnManager {
$column = this.header.querySelector(selector); $column = this.header.querySelector(selector);
this.$columnMap[colIndex] = $column; this.$columnMap[colIndex] = $column;
} }
$column.style.width = width + 'px'; $column.style.width = width + 'px';
// fixed left column
const $leftColumn = $(selector, this.datatableWrapperLeft);
if ($leftColumn) {
$leftColumn.style.width = width + 'px';
}
} }
getColumnMinWidth(colIndex) { getColumnMinWidth(colIndex) {

View File

@ -68,10 +68,18 @@ class DataTable {
prepareDom() { prepareDom() {
this.wrapper.innerHTML = ` this.wrapper.innerHTML = `
<div class="datatable"> <div class="datatable">
<div class="datatable-main">
<table class="dt-header"> <table class="dt-header">
</table> </table>
<div class="dt-scrollable"> <div class="dt-scrollable">
</div> </div>
</div>
<div class="datatable-left">
<table class="dt-header">
</table>
<div class="dt-scrollable">
</div>
</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}
@ -83,11 +91,12 @@ class DataTable {
`; `;
this.datatableWrapper = $('.datatable', this.wrapper); this.datatableWrapper = $('.datatable', this.wrapper);
this.header = $('.dt-header', this.wrapper); this.datatableWrapperLeft = $('.datatable-left', this.wrapper);
this.bodyScrollable = $('.dt-scrollable', this.wrapper); this.header = $('.dt-header', this.datatableWrapper);
this.freezeContainer = $('.dt-freeze', this.wrapper); this.bodyScrollable = $('.dt-scrollable', this.datatableWrapper);
this.toastMessage = $('.dt-toast', this.wrapper); this.freezeContainer = $('.dt-freeze', this.datatableWrapper);
this.pasteTarget = $('.dt-paste-target', this.wrapper); this.toastMessage = $('.dt-toast', this.datatableWrapper);
this.pasteTarget = $('.dt-paste-target', this.datatableWrapper);
} }
refresh(data, columns) { refresh(data, columns) {

View File

@ -3,7 +3,8 @@ import {
makeDataAttributeString, makeDataAttributeString,
nextTick, nextTick,
ensureArray, ensureArray,
linkProperties linkProperties,
throttle
} from './utils'; } from './utils';
export default class RowManager { export default class RowManager {
@ -14,7 +15,8 @@ export default class RowManager {
'fireEvent', 'fireEvent',
'wrapper', 'wrapper',
'bodyScrollable', 'bodyScrollable',
'bodyRenderer' 'bodyRenderer',
'datatableWrapperLeft'
]); ]);
this.bindEvents(); this.bindEvents();
@ -31,6 +33,7 @@ export default class RowManager {
bindEvents() { bindEvents() {
this.bindCheckbox(); this.bindCheckbox();
this.bindScrollSync();
} }
bindCheckbox() { bindCheckbox() {
@ -55,6 +58,36 @@ export default class RowManager {
}); });
} }
bindScrollSync() {
// $.on(this.wrapper, 'scroll', '.dt-scrollable', (e, $el) => {
// console.log(e, $el);
// });
if (!this._$leftBodyScrollable) {
this._$leftBodyScrollable = $('.dt-scrollable', this.datatableWrapperLeft);
}
$.on(this.bodyScrollable, 'scroll', throttle((e) => {
console.log('main scrolled');
requestAnimationFrame(() => {
if (this._$leftBodyScrollable.scrollTop === this.bodyScrollable.scrollTop) {
return;
}
this._$leftBodyScrollable.scrollTop = this.bodyScrollable.scrollTop;
});
}, 16));
$.on(this._$leftBodyScrollable, 'scroll', throttle((e) => {
console.log('left scrolled');
requestAnimationFrame(() => {
if (this._$leftBodyScrollable.scrollTop === this.bodyScrollable.scrollTop) {
return;
}
this.bodyScrollable.scrollTop = this._$leftBodyScrollable.scrollTop;
});
}, 16));
}
refreshRows() { refreshRows() {
this.instance.renderBody(); this.instance.renderBody();
this.instance.setDimensions(); this.instance.setDimensions();

View File

@ -25,16 +25,25 @@
.datatable { .datatable {
position: relative; position: relative;
}
.datatable-main {
overflow: auto; overflow: auto;
} }
.datatable-left {
position: absolute;
left: 0;
top: 0;
z-index: 1;
background-color: white;
}
.dt-header { .dt-header {
border-collapse: collapse; border-collapse: collapse;
border-bottom: 1px solid var(--border-color); border-bottom: 1px solid var(--border-color);
position: absolute; position: relative;
top: 0;
left: 0;
background-color: var(--cell-bg); background-color: var(--cell-bg);
} }
@ -257,3 +266,7 @@
body.dt-resize { body.dt-resize {
cursor: col-resize; cursor: col-resize;
} }
.datatable-left [data-is-filter] {
display: none;
}

View File

@ -12,14 +12,14 @@ export default class Style {
linkProperties(this, this.instance, [ linkProperties(this, this.instance, [
'options', 'datamanager', 'columnmanager', 'options', 'datamanager', 'columnmanager',
'header', 'bodyScrollable', 'datatableWrapper', 'header', 'bodyScrollable', 'datatableWrapper',
'getColumn' 'datatableWrapperLeft', 'getColumn'
]); ]);
this.scopeClass = 'dt-instance-' + instance.constructor.instances; this.scopeClass = 'dt-instance-' + instance.constructor.instances;
instance.datatableWrapper.classList.add(this.scopeClass); instance.datatableWrapper.classList.add(this.scopeClass);
const styleEl = document.createElement('style'); const styleEl = document.createElement('style');
instance.wrapper.insertBefore(styleEl, instance.datatableWrapper); document.head.appendChild(styleEl);
this.styleEl = styleEl; this.styleEl = styleEl;
this.bindResizeWindow(); this.bindResizeWindow();
@ -102,15 +102,17 @@ export default class Style {
this.setDefaultCellHeight(); this.setDefaultCellHeight();
this.setBodyStyle(); this.setBodyStyle();
this.setDatatableLeftStyle();
} }
setHeaderStyle() { setHeaderStyle() {
if (this.options.layout === 'fluid') { if (this.options.layout === 'fluid') {
// setting width as 0 will ensure that the // setting width as 0 will ensure that the
// header doesn't take the available space // header doesn't take the available space
$.style(this.header, { // $.style(this.header, {
width: 0 // width: 0
}); // });
} }
$.style(this.header, { $.style(this.header, {
@ -291,17 +293,33 @@ export default class Style {
}); });
} }
$.style(this.bodyScrollable, { // $.style(this.bodyScrollable, {
marginTop: $.style(this.header, 'height') + 'px' // marginTop: $.style(this.header, 'height') + 'px'
}); // });
$.style($('table', this.bodyScrollable), { $.style($('.dt-body', this.bodyScrollable), {
margin: 0, margin: 0,
width: '100%' width: '100%'
}); });
}); });
} }
setDatatableLeftStyle() {
const wrapperWidth = $.style(this.datatableWrapperLeft, 'width');
$.style(this.datatableWrapperLeft, {
width: wrapperWidth + 'px',
overflow: 'hidden'
});
const scrollable = $('.dt-scrollable', this.datatableWrapperLeft);
const width = $.style(scrollable, 'width');
$.style(scrollable, {
width: (width + 20) + 'px',
paddingRight: '20px'
});
}
getColumnHeaderElement(colIndex) { getColumnHeaderElement(colIndex) {
colIndex = +colIndex; colIndex = +colIndex;
if (colIndex < 0) return null; if (colIndex < 0) return null;