Skip to content

Commit

Permalink
Add support for the ability to disable column virtualization (#10599)
Browse files Browse the repository at this point in the history
  • Loading branch information
budnix committed Dec 6, 2023
1 parent 31297ac commit 2526ddd
Show file tree
Hide file tree
Showing 32 changed files with 822 additions and 321 deletions.
8 changes: 8 additions & 0 deletions .changelogs/10599.json
@@ -0,0 +1,8 @@
{
"issuesOrigin": "private",
"title": "Added support for the ability to disable column virtualization via the new `renderAllColumns` option",
"type": "added",
"issueOrPR": 10599,
"breaking": false,
"framework": "none"
}
8 changes: 6 additions & 2 deletions handsontable/src/3rdparty/walkontable/src/calculator/index.js
@@ -1,8 +1,12 @@
import ViewportColumnsCalculator from './viewportColumns';
import ViewportRowsCalculator from './viewportRows';
import { RenderAllColumnsCalculator } from './renderAllColumns';
import { RenderAllRowsCalculator } from './renderAllRows';
import { ViewportColumnsCalculator } from './viewportColumns';
import { ViewportRowsCalculator } from './viewportRows';

export * from './constants';
export {
RenderAllColumnsCalculator,
RenderAllRowsCalculator,
ViewportColumnsCalculator,
ViewportRowsCalculator,
};
@@ -0,0 +1,43 @@
/**
* @typedef {object} RenderAllColumnsCalculatorOptions
* @property {number} totalColumns Total number of columns.
*/
/**
* Holds all calculations needed to perform rendering of the all columns.
*
* @class RenderAllColumnsCalculator
*/
export class RenderAllColumnsCalculator {
/**
* Number of rendered/visible columns.
*
* @type {number}
*/
count = 0;
/**
* Index of the first rendered/visible column.
*
* @type {number}
*/
startColumn = 0;
/**
* Index of the last rendered/visible column.
*
* @type {number}
*/
endColumn = 0;
/**
* Position of the first rendered/visible column (in px).
*
* @type {number}
*/
startPosition = 0;

/**
* @param {RenderAllColumnsCalculatorOptions} options Object with all options specified for column viewport calculation.
*/
constructor(options) {
this.count = options.totalColumns;
this.endColumn = this.count - 1;
}
}
@@ -0,0 +1,43 @@
/**
* @typedef {object} RenderAllRowsCalculatorOptions
* @property {number} totalRows Total number of rows.
*/
/**
* Holds all calculations needed to perform rendering of the all rows.
*
* @class RenderAllRowsCalculator
*/
export class RenderAllRowsCalculator {
/**
* Number of rendered/visible rows.
*
* @type {number}
*/
count = 0;
/**
* Index of the first rendered/visible row.
*
* @type {number}
*/
startRow = 0;
/**
* Index of the last rendered/visible row.
*
* @type {number}
*/
endRow = 0;
/**
* Position of the first rendered/visible row (in px).
*
* @type {number}
*/
startPosition = 0;

/**
* @param {RenderAllRowsCalculatorOptions} options Object with all options specified for row viewport calculation.
*/
constructor(options) {
this.count = options.totalRows;
this.endRow = this.count - 1;
}
}
Expand Up @@ -19,7 +19,7 @@ import { RENDER_TYPE, FULLY_VISIBLE_TYPE } from './constants';
*
* @class ViewportColumnsCalculator
*/
class ViewportColumnsCalculator {
export class ViewportColumnsCalculator {
/**
* Default column width.
*
Expand Down Expand Up @@ -59,26 +59,6 @@ class ViewportColumnsCalculator {
* @type {boolean}
*/
isVisibleInTrimmingContainer = false;
/**
* @type {number}
*/
stretchAllRatio = 0;
/**
* @type {number}
*/
stretchLastWidth = 0;
/**
* @type {number}
*/
#totalTargetWidth = 0;
/**
* @type {boolean}
*/
needVerifyLastColumnWidth = true;
/**
* @type {number[]}
*/
stretchAllColumnsWidth = [];
/**
* The calculator options.
*
Expand All @@ -91,11 +71,6 @@ class ViewportColumnsCalculator {
*/
constructor(options) {
this.#options = options;

if (typeof this.#options.stretchingColumnWidthFn !== 'function') {
this.#options.stretchingColumnWidthFn = width => width;
}

this.calculate();
}

Expand Down Expand Up @@ -213,118 +188,6 @@ class ViewportColumnsCalculator {
}
}

/**
* Recalculate columns stretching.
*
* @param {number} totalWidth The total width of the table.
*/
refreshStretching(totalWidth) {
if (this.#options.stretchMode === 'none') {
return;
}
let totalColumnsWidth = totalWidth;

this.#totalTargetWidth = totalColumnsWidth;

const totalColumns = this.#options.totalColumns;
let sumAll = 0;

for (let i = 0; i < totalColumns; i++) {
const columnWidth = this._getColumnWidth(i);
const permanentColumnWidth = this.#options.stretchingColumnWidthFn(undefined, i);

if (typeof permanentColumnWidth === 'number') {
totalColumnsWidth -= permanentColumnWidth;
} else {
sumAll += columnWidth;
}
}
const remainingSize = totalColumnsWidth - sumAll;

if (this.#options.stretchMode === 'all' && remainingSize > 0) {
this.stretchAllRatio = totalColumnsWidth / sumAll;
this.stretchAllColumnsWidth = [];
this.needVerifyLastColumnWidth = true;

} else if (this.#options.stretchMode === 'last' && totalColumnsWidth !== Infinity) {
const columnWidth = this._getColumnWidth(totalColumns - 1);
const lastColumnWidth = remainingSize + columnWidth;

this.stretchLastWidth = lastColumnWidth >= 0 ? lastColumnWidth : columnWidth;
}
}

/**
* Get stretched column width based on stretchH (all or last) setting passed in handsontable instance.
*
* @param {number} column The visual column index.
* @param {number} baseWidth The default column width.
* @returns {number|null}
*/
getStretchedColumnWidth(column, baseWidth) {
let result = null;

if (this.#options.stretchMode === 'all' && this.stretchAllRatio !== 0) {
result = this._getStretchedAllColumnWidth(column, baseWidth);

} else if (this.#options.stretchMode === 'last' && this.stretchLastWidth !== 0) {
result = this._getStretchedLastColumnWidth(column);
}

return result;
}

/**
* @param {number} column The visual column index.
* @param {number} baseWidth The default column width.
* @returns {number}
* @private
*/
_getStretchedAllColumnWidth(column, baseWidth) {
let sumRatioWidth = 0;
const totalColumns = this.#options.totalColumns;

if (!this.stretchAllColumnsWidth[column]) {
const stretchedWidth = Math.round(baseWidth * this.stretchAllRatio);
const newStretchedWidth = this.#options.stretchingColumnWidthFn(stretchedWidth, column);

if (newStretchedWidth === undefined) {
this.stretchAllColumnsWidth[column] = stretchedWidth;
} else {
this.stretchAllColumnsWidth[column] = isNaN(newStretchedWidth)
? this._getColumnWidth(column) : newStretchedWidth;
}
}

if (this.stretchAllColumnsWidth.length === totalColumns && this.needVerifyLastColumnWidth) {
this.needVerifyLastColumnWidth = false;

for (let i = 0; i < this.stretchAllColumnsWidth.length; i++) {
sumRatioWidth += this.stretchAllColumnsWidth[i];
}
if (sumRatioWidth !== this.#totalTargetWidth) {
this.stretchAllColumnsWidth[this.stretchAllColumnsWidth.length - 1] += this.#totalTargetWidth - sumRatioWidth;
}
}

return this.stretchAllColumnsWidth[column];
}

/**
* @param {number} column The visual column index.
* @returns {number|null}
* @private
*/
_getStretchedLastColumnWidth(column) {
const totalColumns = this.#options.totalColumns;

if (column === totalColumns - 1) {
return this.stretchLastWidth;
}

return null;
}

/**
* @param {number} column The visual column index.
* @returns {number}
Expand All @@ -340,5 +203,3 @@ class ViewportColumnsCalculator {
return width;
}
}

export default ViewportColumnsCalculator;
Expand Up @@ -16,7 +16,7 @@ import { RENDER_TYPE, FULLY_VISIBLE_TYPE } from './constants';
*
* @class ViewportRowsCalculator
*/
class ViewportRowsCalculator {
export class ViewportRowsCalculator {
/**
* Default row height.
*
Expand Down Expand Up @@ -175,5 +175,3 @@ class ViewportRowsCalculator {
}
}
}

export default ViewportRowsCalculator;
6 changes: 4 additions & 2 deletions handsontable/src/3rdparty/walkontable/src/index.js
@@ -1,5 +1,7 @@
import ViewportColumnsCalculator from './calculator/viewportColumns';
import ViewportRowsCalculator from './calculator/viewportRows';
import {
ViewportColumnsCalculator,
ViewportRowsCalculator,
} from './calculator';

import CellCoords from './cell/coords';
import CellRange from './cell/range';
Expand Down
11 changes: 11 additions & 0 deletions handsontable/src/3rdparty/walkontable/src/renderer/colGroup.js
@@ -1,6 +1,10 @@
import BaseRenderer from './_base';
import { warn } from './../../../../helpers/console';
import { toSingleLine } from './../../../../helpers/templateLiteralTag';
import { addClass } from './../../../../helpers/dom/element';

let performanceWarningAppeared = false;

/**
* Colgroup renderer responsible for managing (inserting, tracking, rendering) COL elements.
*
Expand Down Expand Up @@ -43,6 +47,13 @@ export default class ColGroupRenderer extends BaseRenderer {

const { columnsToRender, rowHeadersCount } = this.table;

if (!performanceWarningAppeared && columnsToRender > 1000) {
performanceWarningAppeared = true;
warn(toSingleLine`Performance tip: Handsontable rendered more than 1000 visible columns.\x20
Consider limiting the number of rendered columns by specifying the table width and/or\x20
turning off the "renderAllColumns" option.`);
}

// Render column nodes for row headers
for (let visibleColumnIndex = 0; visibleColumnIndex < rowHeadersCount; visibleColumnIndex++) {
const sourceColumnIndex = this.table.renderedColumnToSource(visibleColumnIndex);
Expand Down
7 changes: 4 additions & 3 deletions handsontable/src/3rdparty/walkontable/src/renderer/rows.js
@@ -1,7 +1,7 @@
import BaseRenderer from './_base';
import { warn } from './../../../../helpers/console';
import { toSingleLine } from './../../../../helpers/templateLiteralTag';
import { OrderView } from './../utils/orderView';
import BaseRenderer from './_base';
import { setAttribute } from '../../../../helpers/dom/element';
import {
A11Y_ROW,
Expand Down Expand Up @@ -59,8 +59,9 @@ export default class RowsRenderer extends BaseRenderer {

if (!performanceWarningAppeared && rowsToRender > 1000) {
performanceWarningAppeared = true;
warn(toSingleLine`Performance tip: Handsontable rendered more than 1000 visible rows. Consider limiting\x20
the number of rendered rows by specifying the table height and/or turning off the "renderAllRows" option.`);
warn(toSingleLine`Performance tip: Handsontable rendered more than 1000 visible rows.\x20
Consider limiting the number of rendered rows by specifying the table height and/or\x20
turning off the "renderAllRows" option.`);
}

if (this.table.isAriaEnabled()) {
Expand Down
2 changes: 2 additions & 0 deletions handsontable/src/3rdparty/walkontable/src/settings.js
Expand Up @@ -29,6 +29,7 @@ import { objectEach } from '../../../helpers/object';
* @property {Option} onBeforeStretchingColumnWidth Option `onBeforeStretchingColumnWidth`.
* @property {Option} preventOverflow Option `preventOverflow`.
* @property {Option} preventWheel Option `preventWheel`.
* @property {Option} renderAllColumns Option `renderAllColumns`.
* @property {Option} renderAllRows Option `renderAllRows`.
* @property {Option} rowHeaders Option `rowHeaders`.
* @property {Option} rowHeight Option `,`.
Expand Down Expand Up @@ -226,6 +227,7 @@ export default class Settings {
onWindowResize: null,
onContainerElementResize: null,

renderAllColumns: false,
renderAllRows: false,
groups: false,
rowHeaderWidth: null,
Expand Down

0 comments on commit 2526ddd

Please sign in to comment.