Table component for scrolling through lines of data 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 &gt;= 0) {
        // scroll up but not past first row
        if (Ember.get(this, 'firstRow') &gt; 0) {
          this.decrementProperty('firstRow');
          this.decrementProperty('lastRow');
        }
      } else {
        // scroll down but not past last row
        if (Ember.get(this, 'lastRow') &lt; 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.
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


Isn't that already the default behavior of scrollable divs? Well, except the page doesn't set overflow:hidden on itself. Once your cursor is in a scrollable area, scroll will transfer there. When it reaches the end, the page scroll will pick up the rest of your scroll (really apparent when answering in SE with a really tiny textarea).

So I believe you're preventing that "page picking up after the end" thing. If so, you don't need to disable scrolling for the component. Once you hover over it, just disable the page scroll and enable when you move out.

Now for your code, you're inconsistently doing the "egyptian" (collapsed, K&amp;R) brackets. Well, the problem is the inconsistency, not the fact that you're using one or the other. Just choose one style and stick with it.

maxRow: Ember.computed('content', function () {
  return Ember.get(this, 'content.length');
}),

let TableComponent = Ember.Component.extend({
  tagName: 'table',
  layout: layout,
  ...


To make these checks easier, try configuring your IDE to tell you. I believe most IDEs/text editors have plugins for eslint, jshint, and jslint.