import _ from 'lodash';
import quantize from '../common/quantize';
import NodeListManager from './node-list-manager';

function AxisView(options) {
  _.extend(this, options);
  // The container element is where the individual items are rendered into.
  this.container = this.el.children[0];
  this._createNodeListManager();
}

_.extend(AxisView.prototype, {
  // This intelligently renders the view.
  render({scrollOffset, speed} = {}) {
    // Clear any existing update we might have in store
    clearTimeout(this._deferredUpdate);

    // If the user isn't scrolling too fast, then we do a smart update.
    // Otherwise, we schedule an update for the future, when they might
    // be scrolling a bit slower.
    if (!speed || speed < 6) {
      this._update(scrollOffset);
    } else {
      this._deferredUpdate = window.setTimeout(() => {
        this._update(scrollOffset);
      }, 50);
    }
  },

  // The NodeListManager manages the smart updating of our list.
  _createNodeListManager() {
    this.nodeListManager = new NodeListManager({
      unit: this.unit,
      el: this.container,
      dim: this.dimension,
      formatFn: this.formatFn,
      displayProp: this.displayProp,
      initialPoolSize: this.poolSize
    });
  },

  // Keeps track of whether or not we have a scheduled render. This comes into play
  // when the user is scrolling really fast.
  _deferredUpdate: undefined,

  // Tell the NodeListManager to update the list
  _update(scrollOffset) {
    // If we don't have a scrollOffset, then we use the initial index. This happens
    // when it's an initial render
    if (_.isUndefined(scrollOffset)) {
      scrollOffset = this.initialIndex;
    }
    // Quantize and pad our values
    var quantizedOffset = quantize(scrollOffset, this.unit);
    var quantizedLength = quantize(this.dataContainerDimensions[this.containerDim], this.unit);
    var {firstIndex, lastIndex} = this._getIndices(quantizedOffset, quantizedLength);
    this.nodeListManager.update({
      list: this.list,
      firstIndex,
      lastIndex
    });
  },

  // Gets the right indices given an offset (as an index)
  // and a length (in units of indices)
  _getIndices(offset, length) {
    var endOffset = offset + length;
    var startPadding = Math.min(this.padding, offset);
    var bottomPadding = Math.min(this.padding, this.list.length - endOffset);
    var firstIndex = offset - startPadding;
    var lastIndex = endOffset + bottomPadding;
    return {firstIndex, lastIndex};
  }
});

export default AxisView;

import _ from 'lodash';
import quantize from '../common/quantize';
import NodeListManager from './node-list-manager';

function AxisView(options) {
  _.extend(this, options);
  // The container element is where the individual items are rendered into.
  this.container = this.el.children[0];
  this._createNodeListManager();
}

_.extend(AxisView.prototype, {
  // This intelligently renders the view.
  render({scrollOffset, speed} = {}) {
    // Clear any existing update we might have in store
    clearTimeout(this._deferredUpdate);

    // If the user isn't scrolling too fast, then we do a smart update.
    // Otherwise, we schedule an update for the future, when they might
    // be scrolling a bit slower.
    if (!speed || speed < 6) {
      this._update(scrollOffset);
    } else {
      this._deferredUpdate = window.setTimeout(() => {
        this._update(scrollOffset);
      }, 50);
    }
  },

  // The NodeListManager manages the smart updating of our list.
  _createNodeListManager() {
    this.nodeListManager = new NodeListManager({
      unit: this.unit,
      el: this.container,
      dim: this.dimension,
      formatFn: this.formatFn,
      displayProp: this.displayProp,
      initialPoolSize: this.poolSize
    });
  },

  // Keeps track of whether or not we have a scheduled render. This comes into play
  // when the user is scrolling really fast.
  _deferredUpdate: undefined,

  // Tell the NodeListManager to update the list
  _update(scrollOffset) {
    // If we don't have a scrollOffset, then we use the initial index. This happens
    // when it's an initial render
    if (_.isUndefined(scrollOffset)) {
      scrollOffset = this.initialIndex * this.unit;
    }
    // Quantize and pad our values
    var quantizedOffset = quantize(scrollOffset, this.unit);
    var quantizedLength = quantize(this.dataContainerDimensions[this.containerDim], this.unit);
    var {firstIndex, lastIndex} = this._getIndices(quantizedOffset, quantizedLength);
    this.nodeListManager.update({
      list: this.list,
      firstIndex,
      lastIndex
    });
  },

  // Gets the right indices given an offset (as an index)
  // and a length (in units of indices)
  _getIndices(offset, length) {
    var endOffset = offset + length;
    var startPadding = Math.min(this.padding, offset);
    var bottomPadding = Math.min(this.padding, this.list.length - endOffset);
    var firstIndex = offset - startPadding;
    var lastIndex = endOffset + bottomPadding;
    return {firstIndex, lastIndex};
  }
});

export default AxisView;

Fix bug where axis views would double-render on startup