<commit_before>/**
 * Copyright (c) 2015, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @providesModule FixedDataTableScrollHelper
 * @typechecks
 */

'use strict';

var PrefixIntervalTree = require('PrefixIntervalTree');
var clamp = require('clamp');

var BUFFER_ROWS = 5;

class FixedDataTableScrollHelper {
  constructor(
    /*number*/ rowCount,
    /*number*/ defaultRowHeight,
    /*number*/ viewportHeight,
    /*?function*/ rowHeightGetter
  ) {
    this._rowOffsets = new PrefixIntervalTree(rowCount, defaultRowHeight);
    this._storedHeights = new Array(rowCount);
    for (var i = 0; i < rowCount; ++i) {
      this._storedHeights[i] = defaultRowHeight;
    }
    this._rowCount = rowCount;
    this._position = 0;
    this._contentHeight = rowCount * defaultRowHeight;
    this._defaultRowHeight = defaultRowHeight;
    this._rowHeightGetter = rowHeightGetter ?
      rowHeightGetter :
      () => defaultRowHeight;
    this._viewportHeight = viewportHeight;
    this.scrollRowIntoView = this.scrollRowIntoView.bind(this);
    this.setViewportHeight = this.setViewportHeight.bind(this);
    this.scrollBy = this.scrollBy.bind(this);
    this.scrollTo = this.scrollTo.bind(this);
    this.scrollToRow = this.scrollToRow.bind(this);
    this.setRowHeightGetter = this.setRowHeightGetter.bind(this);
    this.getContentHeight = this.getContentHeight.bind(this);
    this.getRowPosition = this.getRowPosition.bind(this);

    this._updateHeightsInViewport(0, 0);
  }

  setRowHeightGetter(/*function*/ rowHeightGetter) {
    this._rowHeightGetter = rowHeightGetter;
  }

  setViewportHeight(/*number*/ viewportHeight) {
    this._viewportHeight = viewportHeight;
  }

  getContentHeight() /*number*/ {
    return this._contentHeight;
  }

  _updateHeightsInViewport(
    /*number*/ firstRowIndex,
    /*number*/ firstRowOffset
  ) {
    var top = firstRowOffset;
    var index = firstRowIndex;
    while (top <= this._viewportHeight && index < this._rowCount) {
      this._updateRowHeight(index);
      top += this._storedHeights[index];
      index++;
    }
  }

  _updateHeightsAboveViewport(/*number*/ firstRowIndex) {
    var index = firstRowIndex - 1;
    while (index >= 0 && index >= firstRowIndex - BUFFER_ROWS) {
      var delta = this._updateRowHeight(index);
      this._position += delta;
      index--;
    }
  }

  _updateRowHeight(/*number*/ rowIndex) /*number*/ {
    if (rowIndex < 0 || rowIndex >= this._rowCount) {
      return 0;
    }
    var newHeight = this._rowHeightGetter(rowIndex);
    if (newHeight !== this._storedHeights[rowIndex]) {
      var change = newHeight - this._storedHeights[rowIndex];
      this._rowOffsets.set(rowIndex, newHeight);
      this._storedHeights[rowIndex] = newHeight;
      this._contentHeight += change;
      return change;
    }
    return 0;
  }

  getRowPosition(/*number*/ rowIndex) /*number*/ {
    return (
      this._rowOffsets.get(rowIndex).value - this._rowHeightGetter(rowIndex)
    );
  }

  scrollBy(/*number*/ delta) /*object*/ {
    var firstRow = this._rowOffsets.upperBound(this._position);
    var firstRowPosition =
      firstRow.value - this._storedHeights[firstRow.index];
    var rowIndex = firstRow.index;
    var position = this._position;

    var rowHeightChange = this._updateRowHeight(rowIndex);
    if (firstRowPosition !== 0) {
      position += rowHeightChange;
    }<commit_msg>Fixed bug with rows positioning for variable height rows.<commit_after>/**
 * Copyright (c) 2015, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @providesModule FixedDataTableScrollHelper
 * @typechecks
 */

'use strict';

var PrefixIntervalTree = require('PrefixIntervalTree');
var clamp = require('clamp');

var BUFFER_ROWS = 5;

class FixedDataTableScrollHelper {
  constructor(
    /*number*/ rowCount,
    /*number*/ defaultRowHeight,
    /*number*/ viewportHeight,
    /*?function*/ rowHeightGetter
  ) {
    this._rowOffsets = new PrefixIntervalTree(rowCount, defaultRowHeight);
    this._storedHeights = new Array(rowCount);
    for (var i = 0; i < rowCount; ++i) {
      this._storedHeights[i] = defaultRowHeight;
    }
    this._rowCount = rowCount;
    this._position = 0;
    this._contentHeight = rowCount * defaultRowHeight;
    this._defaultRowHeight = defaultRowHeight;
    this._rowHeightGetter = rowHeightGetter ?
      rowHeightGetter :
      () => defaultRowHeight;
    this._viewportHeight = viewportHeight;
    this.scrollRowIntoView = this.scrollRowIntoView.bind(this);
    this.setViewportHeight = this.setViewportHeight.bind(this);
    this.scrollBy = this.scrollBy.bind(this);
    this.scrollTo = this.scrollTo.bind(this);
    this.scrollToRow = this.scrollToRow.bind(this);
    this.setRowHeightGetter = this.setRowHeightGetter.bind(this);
    this.getContentHeight = this.getContentHeight.bind(this);
    this.getRowPosition = this.getRowPosition.bind(this);

    this._updateHeightsInViewport(0, 0);
  }

  setRowHeightGetter(/*function*/ rowHeightGetter) {
    this._rowHeightGetter = rowHeightGetter;
  }

  setViewportHeight(/*number*/ viewportHeight) {
    this._viewportHeight = viewportHeight;
  }

  getContentHeight() /*number*/ {
    return this._contentHeight;
  }

  _updateHeightsInViewport(
    /*number*/ firstRowIndex,
    /*number*/ firstRowOffset
  ) {
    var top = firstRowOffset;
    var index = firstRowIndex;
    while (top <= this._viewportHeight && index < this._rowCount) {
      this._updateRowHeight(index);
      top += this._storedHeights[index];
      index++;
    }
  }

  _updateHeightsAboveViewport(/*number*/ firstRowIndex) {
    var index = firstRowIndex - 1;
    while (index >= 0 && index >= firstRowIndex - BUFFER_ROWS) {
      var delta = this._updateRowHeight(index);
      this._position += delta;
      index--;
    }
  }

  _updateRowHeight(/*number*/ rowIndex) /*number*/ {
    if (rowIndex < 0 || rowIndex >= this._rowCount) {
      return 0;
    }
    var newHeight = this._rowHeightGetter(rowIndex);
    if (newHeight !== this._storedHeights[rowIndex]) {
      var change = newHeight - this._storedHeights[rowIndex];
      this._rowOffsets.set(rowIndex, newHeight);
      this._storedHeights[rowIndex] = newHeight;
      this._contentHeight += change;
      return change;
    }
    return 0;
  }

  getRowPosition(/*number*/ rowIndex) /*number*/ {
    this._updateRowHeight(rowIndex);
    return (
      this._rowOffsets.get(rowIndex).value - this._rowHeightGetter(rowIndex)
    );
  }

  scrollBy(/*number*/ delta) /*object*/ {
    var firstRow = this._rowOffsets.upperBound(this._position);
    var firstRowPosition =
      firstRow.value - this._storedHeights[firstRow.index];
    var rowIndex = firstRow.index;
    var position = this._position;

    var rowHeightChange = this._updateRowHeight(rowIndex);
    if (firstRowPosition !== 0) {
      position += rowHeightChange;
    }
{'fraction_non_alphanumeric': 0.11604329360186327, 'fraction_numerical': 0.004110152075626798, 'mean_word_length': 3.429611650485437, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4533578', 'n_tokens_mistral': 2267, 'n_tokens_neox': 2226, 'n_words': 473}