_hookUpStickyHeader()

in js/vnext/layout/table-view.js [249:318]


  _hookUpStickyHeader(listView) {
    const viewport = listView.viewport;
    const isWindow = viewport.$el.get(0) === window;
    const $tableContainer = this.$('.table-container');
    const $stickyHeader = this.$('.sticky-header');
    const $stickyHeaderFiller = this.$('.sticky-header-filler');
    const $table = this.$(stickyHeaderFillerTableSelector[this._props.layout]);
    const viewportSize = { width: 0, height: 0 };

    const adjustStickyHeader = () => {
      if (!this.$el.is(':visible')) {
        return;
      }

      const metricsVP = listView.viewport.getMetrics();
      const topVP = metricsVP.outer.top;
      const offset = _.result(this._props.scrolling.header, 'offset', 0);
      const rectContainer = document.body.contains($tableContainer.get(0)) ?
        $tableContainer.get(0).getBoundingClientRect() :
        { top: 0, left: 0 };
      const topCur = rectContainer.top;

      if (isWindow) {
        const sticky = topCur < topVP + offset;
        $stickyHeaderFiller.css({
          display: sticky ? 'block' : 'none',
          height: sticky ? $stickyHeader.height() : '',
        });

        const style = {
          position: sticky ? 'fixed' : 'static',
          top: sticky ? topVP + offset : '',
          left: sticky ? rectContainer.left : '',
        };

        const deltaWidth = Math.abs(metricsVP.outer.width - viewportSize.width);
        const deltaHeight = Math.abs(metricsVP.outer.height - viewportSize.height);
        const resize = deltaWidth >= 1 || deltaHeight >= 1;

        if (resize) {
          // Update the viewportSize
          viewportSize.width = metricsVP.outer.width;
          viewportSize.height = metricsVP.outer.height;

          // Let the content table layout freely, then sync the width to sticky header
          $stickyHeader.css({ 'width': 'auto', 'min-width': 0 });
          $table.css({ 'width': 'auto', 'min-width': 0 });
          const width = $tableContainer.width();
          style.width = width;
          style['min-width'] = width;
          $table.css({ width, 'min-width': width });
        }

        $stickyHeader.css(style);
      } else {
        $stickyHeaderFiller.css({
          display: 'none',
        });
        $stickyHeader.css({
          position: 'relative',
          top: Math.min(Math.max(topVP + offset - topCur, 0), Math.max(0, $table.height())),
        });
      }
    };
    listView.viewport.on('resize', () => this.trigger('didChangeBound'));
    listView.viewport.on('scroll', () => this.trigger('didChangeBound'));

    this.on('didChangeBound', adjustStickyHeader);
    listView.on('didRedraw', adjustStickyHeader);
  }