Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for the ability to disable column virtualization #10599

Merged
merged 18 commits into from Dec 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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