I'm working on a table component that is able to scroll through millions of lines of data. Not bad for the front end. The way I'm doing this is to only render a small table with 10 rows and then, when the user scrolls, I change the data in that table.
The table itself is not in a scrollable div because the entire html element fits on the page. This is working OK, but it means that the scroll on the page is not disabled the way it would be if the table were in a scrollable div.
I really don't like how I have to hide the overflow on the body when the mouse enters the component to stop the scroll event from moving the whole page instead of just the data in the component.
import Ember from 'ember';
import layout from '../templates/components/table';
let TableComponent = Ember.Component.extend(
{
tagName: 'table',
layout: layout,
firstRow: 0,
lastRow: 10,
isScrollEnabled: false,
maxRow: Ember.computed('content',
function () {
return Ember.get(this, 'content.length');
}
),
setup: function () {
this.$().on('mousewheel', Ember.run.bind(this, this._didScroll));
this.$(window).on('focus', Ember.run.bind(this, this._focus));
this.$(window).on('blur', Ember.run.bind(this, this._blur));
}.on('didInsertElement'),
tearDown: function () {
this.$().off('mousewheel', Ember.run.bind(this, this._didScroll));
this.$(window).off('focus', Ember.run.bind(this, this._focus));
this.$(window).off('blur', Ember.run.bind(this, this._blur));
}.on('willDestroyElement'),
visibleContent: Ember.computed('content', 'firstRow', 'lastRow',
function () {
let content = Ember.get(this, 'content');
let firstRow = Ember.get(this, 'firstRow');
let lastRow = Ember.get(this, 'lastRow');
return content.slice(firstRow, lastRow);
}
),
_didScroll(event) {
if (!Ember.get(this, 'isScrollEnabled')) {
return;
}
if (event.originalEvent.wheelDelta >= 0) {
// scroll up but not past first row
if (Ember.get(this, 'firstRow') > 0) {
this.decrementProperty('firstRow');
this.decrementProperty('lastRow');
}
} else {
// scroll down but not past last row
if (Ember.get(this, 'lastRow') < Ember.get(this, 'maxRow')) {
this.incrementProperty('firstRow');
this.incrementProperty('lastRow');
}
}
},
_focus() {
Ember.set(this, 'isScrollEnabled', true);
},
_blur() {
Ember.set(this, 'isScrollEnabled', false);
},
mouseEnter() {
Ember.$('body').css('overflow', 'hidden');
},
mouseLeave() {
Ember.$('body').css('overflow', 'auto');
}
}
);
export default TableComponent;
The mouseEnter
and mouseLeave
functions are my big concerns.