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

fix(core): frozen grid w/hidden column should remove from DOM #1372

Merged
merged 1 commit into from
Jan 27, 2024
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 56 additions & 43 deletions packages/common/src/core/__tests__/slickGrid.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2424,11 +2424,12 @@ describe('SlickGrid core file', () => {
jest.advanceTimersByTime(10);

expect(columnElms[1].classList.contains('slick-header-column-active')).toBeFalsy();
expect(onColumnsResizedSpy).toHaveBeenCalledWith({ triggeredByColumn: columns[1].id, grid }, expect.anything(), grid);
expect(onColumnsResizedSpy).toHaveBeenCalledWith({ triggeredByColumn: 'lastName', grid }, expect.anything(), grid);
expect(columns[0].width).toBe(80);
expect(columns[1].width).toBe(30);
expect(columns[2].width).toBe(80);
expect(columns[1].width).toBe(0);
expect(columns[2].width).toBe(65);
expect(columns[3].width).toBe(86);
expect(columns[4].width).toBe(80);
});

it('should resize 3rd column that has a "minWidth" defined using default sizing grid options', () => {
Expand Down Expand Up @@ -2466,11 +2467,12 @@ describe('SlickGrid core file', () => {
jest.advanceTimersByTime(10);

expect(columnElms[2].classList.contains('slick-header-column-active')).toBeFalsy();
expect(onColumnsResizedSpy).toHaveBeenCalledWith({ triggeredByColumn: columns[2].id, grid }, expect.anything(), grid);
expect(onColumnsResizedSpy).toHaveBeenCalledWith({ triggeredByColumn: 'age', grid }, expect.anything(), grid);
expect(columns[0].width).toBe(80);
expect(columns[1].width).toBe(0);
expect(columns[2].width).toBe(65);
expect(columns[3].width).toBe(86);
expect(columns[2].width).toBe(59);
expect(columns[3].width).toBe(88);
expect(columns[4].width).toBe(80);
});

it('should resize 3rd column that has a "minWidth" defined using default sizing grid options with a frozen column', () => {
Expand Down Expand Up @@ -2508,11 +2510,12 @@ describe('SlickGrid core file', () => {
jest.advanceTimersByTime(10);

expect(columnElms[2].classList.contains('slick-header-column-active')).toBeFalsy();
expect(onColumnsResizedSpy).toHaveBeenCalledWith({ triggeredByColumn: columns[2].id, grid }, expect.anything(), grid);
expect(onColumnsResizedSpy).toHaveBeenCalledWith({ triggeredByColumn: 'age', grid }, expect.anything(), grid);
expect(columns[0].width).toBe(80);
expect(columns[1].width).toBe(0);
expect(columns[2].width).toBe(65);
expect(columns[3].width).toBe(86);
expect(columns[2].width).toBe(59);
expect(columns[3].width).toBe(88);
expect(columns[4].width).toBe(80);
});

it('should resize 3rd column that has a "minWidth" with a frozen column that is greater than available columns', () => {
Expand Down Expand Up @@ -2550,11 +2553,12 @@ describe('SlickGrid core file', () => {
jest.advanceTimersByTime(10);

expect(columnElms[2].classList.contains('slick-header-column-active')).toBeFalsy();
expect(onColumnsResizedSpy).toHaveBeenCalledWith({ triggeredByColumn: columns[2].id, grid }, expect.anything(), grid);
expect(onColumnsResizedSpy).toHaveBeenCalledWith({ triggeredByColumn: 'age', grid }, expect.anything(), grid);
expect(columns[0].width).toBe(80);
expect(columns[1].width).toBe(0);
expect(columns[2].width).toBe(65);
expect(columns[3].width).toBe(86);
expect(columns[2].width).toBe(59);
expect(columns[3].width).toBe(88);
expect(columns[4].width).toBe(80);
});

it('should resize 2nd column with forceFitColumns option enabled', () => {
Expand Down Expand Up @@ -2597,11 +2601,12 @@ describe('SlickGrid core file', () => {
// end resizing
document.body.dispatchEvent(bodyMouseUpEvent);
expect(columnElms[1].classList.contains('slick-header-column-active')).toBeFalsy();
expect(onColumnsResizedSpy).toHaveBeenCalledWith({ triggeredByColumn: columns[1].id, grid }, expect.anything(), grid);
expect(onColumnsResizedSpy).toHaveBeenCalledWith({ triggeredByColumn: 'lastName', grid }, expect.anything(), grid);
expect(columns[0].width).toBe(0);
expect(columns[1].width).toBe(74);
expect(columns[2].width).toBe(133);
expect(columns[3].width).toBe(198);
expect(columns[1].width).toBe(0);
expect(columns[2].width).toBe(74);
expect(columns[3].width).toBe(133);
expect(columns[4].width).toBe(198);
});

it('should resize 2nd column without forceFitColumns option', () => {
Expand Down Expand Up @@ -2644,11 +2649,12 @@ describe('SlickGrid core file', () => {
// end resizing
document.body.dispatchEvent(bodyMouseUpEvent);
expect(columnElms[1].classList.contains('slick-header-column-active')).toBeFalsy();
expect(onColumnsResizedSpy).toHaveBeenCalledWith({ triggeredByColumn: columns[1].id, grid }, expect.anything(), grid);
expect(onColumnsResizedSpy).toHaveBeenCalledWith({ triggeredByColumn: 'lastName', grid }, expect.anything(), grid);
expect(columns[0].width).toBe(0);
expect(columns[1].width).toBe(74);
expect(columns[2].width).toBe(399);
expect(columns[1].width).toBe(0);
expect(columns[2].width).toBe(74);
expect(columns[3].width).toBe(88);
expect(columns[4].width).toBe(467);
});

it('should resize 2nd column with forceFitColumns option enabled', () => {
Expand Down Expand Up @@ -2687,11 +2693,12 @@ describe('SlickGrid core file', () => {
// end resizing
document.body.dispatchEvent(bodyMouseUpEvent);
expect(columnElms[1].classList.contains('slick-header-column-active')).toBeFalsy();
expect(onColumnsResizedSpy).toHaveBeenCalledWith({ triggeredByColumn: columns[1].id, grid }, expect.anything(), grid);
expect(onColumnsResizedSpy).toHaveBeenCalledWith({ triggeredByColumn: 'lastName', grid }, expect.anything(), grid);
expect(columns[0].width).toBe(0);
expect(columns[1].width).toBe(73);
expect(columns[2].width).toBe(134);
expect(columns[3].width).toBe(198);
expect(columns[1].width).toBe(0);
expect(columns[2].width).toBe(73);
expect(columns[3].width).toBe(88);
expect(columns[4].width).toBe(244);
});

it('should resize 3rd column with forceFitColumns option enabled', () => {
Expand Down Expand Up @@ -2730,11 +2737,12 @@ describe('SlickGrid core file', () => {
// end resizing
document.body.dispatchEvent(bodyMouseUpEvent);
expect(columnElms[2].classList.contains('slick-header-column-active')).toBeFalsy();
expect(onColumnsResizedSpy).toHaveBeenCalledWith({ triggeredByColumn: columns[2].id, grid }, expect.anything(), grid);
expect(onColumnsResizedSpy).toHaveBeenCalledWith({ triggeredByColumn: 'age', grid }, expect.anything(), grid);
expect(columns[0].width).toBe(0);
expect(columns[1].width).toBe(74);
expect(columns[2].width).toBe(132);
expect(columns[3].width).toBe(88);
expect(columns[1].width).toBe(0);
expect(columns[2].width).toBe(74);
expect(columns[3].width).toBe(132);
expect(columns[4].width).toBe(199);
});

it('should resize 3rd column with forceFitColumns option enabled with a frozen column', () => {
Expand Down Expand Up @@ -2773,11 +2781,12 @@ describe('SlickGrid core file', () => {
// end resizing
document.body.dispatchEvent(bodyMouseUpEvent);
expect(columnElms[2].classList.contains('slick-header-column-active')).toBeFalsy();
expect(onColumnsResizedSpy).toHaveBeenCalledWith({ triggeredByColumn: columns[2].id, grid }, expect.anything(), grid);
expect(onColumnsResizedSpy).toHaveBeenCalledWith({ triggeredByColumn: 'age', grid }, expect.anything(), grid);
expect(columns[0].width).toBe(0);
expect(columns[1].width).toBe(74);
expect(columns[2].width).toBe(132);
expect(columns[3].width).toBe(88);
expect(columns[1].width).toBe(0);
expect(columns[2].width).toBe(74);
expect(columns[3].width).toBe(132);
expect(columns[4].width).toBe(199);
});

it('should resize 3rd column without forceFitColumns option but with a frozen column', () => {
Expand Down Expand Up @@ -2816,11 +2825,12 @@ describe('SlickGrid core file', () => {
// end resizing
document.body.dispatchEvent(bodyMouseUpEvent);
expect(columnElms[2].classList.contains('slick-header-column-active')).toBeFalsy();
expect(onColumnsResizedSpy).toHaveBeenCalledWith({ triggeredByColumn: columns[2].id, grid }, expect.anything(), grid);
expect(onColumnsResizedSpy).toHaveBeenCalledWith({ triggeredByColumn: 'age', grid }, expect.anything(), grid);
expect(columns[0].width).toBe(0);
expect(columns[1].width).toBe(74);
expect(columns[2].width).toBe(132);
expect(columns[3].width).toBe(88);
expect(columns[1].width).toBe(0);
expect(columns[2].width).toBe(74);
expect(columns[3].width).toBe(132);
expect(columns[4].width).toBe(468);
});

it('should resize 4th column with forceFitColumns option enabled and a column with maxWidth and a frozen column', () => {
Expand All @@ -2831,7 +2841,8 @@ describe('SlickGrid core file', () => {
const onColumnsDragSpy = jest.spyOn(grid.onColumnsDrag, 'notify');
const onColumnsResizedSpy = jest.spyOn(grid.onColumnsResized, 'notify');
const columnElms = container.querySelectorAll('.slick-header-column');
const resizeHandleElm = columnElms[3].querySelector('.slick-resizable-handle') as HTMLDivElement;
const column3 = columnElms[3 - 1]; // -1 because hidden column is removed from DOM
const resizeHandleElm = column3.querySelector('.slick-resizable-handle') as HTMLDivElement;

const cMouseDownEvent = new CustomEvent('mousedown');
const bodyMouseMoveEvent = new CustomEvent('mousemove');
Expand All @@ -2849,29 +2860,31 @@ describe('SlickGrid core file', () => {
resizeHandleElm.dispatchEvent(cMouseDownEvent);
container.dispatchEvent(cMouseDownEvent);
document.body.dispatchEvent(bodyMouseMoveEvent);
expect(columnElms[3].classList.contains('slick-header-column-active')).toBeTruthy();
expect(column3.classList.contains('slick-header-column-active')).toBeTruthy();
expect(onColumnsDragSpy).toHaveBeenCalledWith(
{ triggeredByColumn: columnElms[3], resizeHandle: resizeHandleElm, grid },
{ triggeredByColumn: column3, resizeHandle: resizeHandleElm, grid },
expect.anything(),
grid
);

// end resizing
document.body.dispatchEvent(bodyMouseUpEvent);
expect(columnElms[3].classList.contains('slick-header-column-active')).toBeFalsy();
expect(column3.classList.contains('slick-header-column-active')).toBeFalsy();
expect(onColumnsResizedSpy).toHaveBeenCalledWith({ triggeredByColumn: columns[3].id, grid }, expect.anything(), grid);
expect(columns[0].width).toBe(0);
expect(columns[1].width).toBe(74);
expect(columns[2].width).toBe(133);
expect(columns[3].width).toBe(168);
expect(columns[1].width).toBe(0);
expect(columns[2].width).toBe(74);
expect(columns[3].width).toBe(132);
expect(columns[4].width).toBe(199);
});

it('should expect the last column to never be resizable', () => {
grid = new SlickGrid<any, Column>(container, data, columns, { ...defaultOptions, forceFitColumns: true });
grid.init();

const columnElms = container.querySelectorAll('.slick-header-column');
const resizeHandleElm = columnElms[4].querySelector('.slick-resizable-handle') as HTMLDivElement;
const column4 = columnElms[4 - 1]; // -1 because hidden column is removed from DOM
const resizeHandleElm = column4.querySelector('.slick-resizable-handle') as HTMLDivElement;

expect(resizeHandleElm).toBeNull();
});
Expand Down
55 changes: 29 additions & 26 deletions packages/common/src/core/slickGrid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1584,6 +1584,8 @@ export class SlickGrid<TData = any, C extends Column<TData> = Column<TData>, O e

for (let i = 0; i < this.columns.length; i++) {
const m: C = this.columns[i];
if (m.hidden) { continue; }

const headerTarget = this.hasFrozenColumns() ? ((i <= this._options.frozenColumn!) ? this._headerL : this._headerR) : this._headerL;
const headerRowTarget = this.hasFrozenColumns() ? ((i <= this._options.frozenColumn!) ? this._headerRowL : this._headerRowR) : this._headerRowL;

Expand Down Expand Up @@ -1875,16 +1877,17 @@ export class SlickGrid<TData = any, C extends Column<TData> = Column<TData>, O e
let frozenLeftColMaxWidth = 0;

const children: HTMLElement[] = this.getHeaderChildren();
const vc = this.getVisibleColumns();
for (let i = 0; i < children.length; i++) {
const child = children[i];
const handles = child.querySelectorAll('.slick-resizable-handle');
handles.forEach((handle) => handle.remove());

if (i >= this.columns.length || !this.columns[i] || this.columns[i].hidden) {
if (i >= vc.length || !vc[i]) {
continue;
}

if (this.columns[i].resizable) {
if (vc[i].resizable) {
if (firstResizable === undefined) {
firstResizable = i;
}
Expand All @@ -1899,7 +1902,7 @@ export class SlickGrid<TData = any, C extends Column<TData> = Column<TData>, O e
for (let i = 0; i < children.length; i++) {
const colElm = children[i];

if (i >= this.columns.length || !this.columns[i] || this.columns[i].hidden) {
if (i >= vc.length || !vc[i]) {
continue;
}
if (i < firstResizable || (this._options.forceFitColumns && i >= lastResizable)) {
Expand All @@ -1925,18 +1928,18 @@ export class SlickGrid<TData = any, C extends Column<TData> = Column<TData>, O e
let stretchLeewayOnRight: number | null = null;
// lock each column's width option to current width
for (let pw = 0; pw < children.length; pw++) {
if (pw >= this.columns.length || !this.columns[pw] || this.columns[pw].hidden) {
if (pw >= vc.length || !vc[pw]) {
continue;
}
this.columns[pw].previousWidth = children[pw].offsetWidth;
vc[pw].previousWidth = children[pw].offsetWidth;
}
if (this._options.forceFitColumns) {
shrinkLeewayOnRight = 0;
stretchLeewayOnRight = 0;
// colums on right affect maxPageX/minPageX
for (j = i + 1; j < this.columns.length; j++) {
c = this.columns[j];
if (c && c.resizable && !c.hidden) {
for (j = i + 1; j < vc.length; j++) {
c = vc[j];
if (c?.resizable) {
if (stretchLeewayOnRight !== null) {
if (c.maxWidth) {
stretchLeewayOnRight += c.maxWidth - (c.previousWidth || 0);
Expand All @@ -1952,8 +1955,8 @@ export class SlickGrid<TData = any, C extends Column<TData> = Column<TData>, O e
let stretchLeewayOnLeft: number | null = 0;
for (j = 0; j <= i; j++) {
// columns on left only affect minPageX
c = this.columns[j];
if (c && c.resizable && !c.hidden) {
c = vc[j];
if (c?.resizable) {
if (stretchLeewayOnLeft !== null) {
if (c.maxWidth) {
stretchLeewayOnLeft += c.maxWidth - (c.previousWidth || 0);
Expand Down Expand Up @@ -1993,7 +1996,7 @@ export class SlickGrid<TData = any, C extends Column<TData> = Column<TData>, O e
x = d;

for (j = i; j >= 0; j--) {
c = this.columns[j];
c = vc[j];
if (c && c.resizable && !c.hidden) {
actualMinWidth = Math.max(c.minWidth || 0, this.absoluteColumnMinWidth);
if (x && (c.previousWidth || 0) + x < actualMinWidth) {
Expand All @@ -2007,7 +2010,7 @@ export class SlickGrid<TData = any, C extends Column<TData> = Column<TData>, O e
}

for (k = 0; k <= i; k++) {
c = this.columns[k];
c = vc[k];
if (!c || c.hidden) { continue; }

if (this.hasFrozenColumns() && (k > this._options.frozenColumn!)) {
Expand All @@ -2019,8 +2022,8 @@ export class SlickGrid<TData = any, C extends Column<TData> = Column<TData>, O e

if (this._options.forceFitColumns) {
x = -d;
for (j = i + 1; j < this.columns.length; j++) {
c = this.columns[j];
for (j = i + 1; j < vc.length; j++) {
c = vc[j];
if (!c || c.hidden) { continue; }
if (c.resizable) {
if (x && c.maxWidth && (c.maxWidth - (c.previousWidth || 0) < x)) {
Expand All @@ -2039,8 +2042,8 @@ export class SlickGrid<TData = any, C extends Column<TData> = Column<TData>, O e
}
}
} else {
for (j = i + 1; j < this.columns.length; j++) {
c = this.columns[j];
for (j = i + 1; j < vc.length; j++) {
c = vc[j];
if (!c || c.hidden) { continue; }

if (this.hasFrozenColumns() && (j > this._options.frozenColumn!)) {
Expand All @@ -2053,8 +2056,8 @@ export class SlickGrid<TData = any, C extends Column<TData> = Column<TData>, O e

if (this._options.forceFitColumns) {
x = -d;
for (j = i + 1; j < this.columns.length; j++) {
c = this.columns[j];
for (j = i + 1; j < vc.length; j++) {
c = vc[j];
if (!c || c.hidden) { continue; }
if (c.resizable) {
if (x && c.maxWidth && (c.maxWidth - (c.previousWidth || 0) < x)) {
Expand All @@ -2074,7 +2077,7 @@ export class SlickGrid<TData = any, C extends Column<TData> = Column<TData>, O e
newCanvasWidthR = 0;

for (j = i; j >= 0; j--) {
c = this.columns[j];
c = vc[j];
if (!c || c.hidden) { continue; }
if (c.resizable) {
if (x && c.maxWidth && (c.maxWidth - (c.previousWidth || 0) < x)) {
Expand All @@ -2099,7 +2102,7 @@ export class SlickGrid<TData = any, C extends Column<TData> = Column<TData>, O e
}

for (k = 0; k <= i; k++) {
c = this.columns[k];
c = vc[k];
if (!c || c.hidden) { continue; }

if (this.hasFrozenColumns() && (k > this._options.frozenColumn!)) {
Expand All @@ -2111,8 +2114,8 @@ export class SlickGrid<TData = any, C extends Column<TData> = Column<TData>, O e

if (this._options.forceFitColumns) {
x = -d;
for (j = i + 1; j < this.columns.length; j++) {
c = this.columns[j];
for (j = i + 1; j < vc.length; j++) {
c = vc[j];
if (!c || c.hidden) { continue; }
if (c.resizable) {
actualMinWidth = Math.max(c.minWidth || 0, this.absoluteColumnMinWidth);
Expand All @@ -2132,8 +2135,8 @@ export class SlickGrid<TData = any, C extends Column<TData> = Column<TData>, O e
}
}
} else {
for (j = i + 1; j < this.columns.length; j++) {
c = this.columns[j];
for (j = i + 1; j < vc.length; j++) {
c = vc[j];
if (!c || c.hidden) { continue; }

if (this.hasFrozenColumns() && (j > this._options.frozenColumn!)) {
Expand Down Expand Up @@ -2168,8 +2171,8 @@ export class SlickGrid<TData = any, C extends Column<TData> = Column<TData>, O e
this.applyColumnHeaderWidths();
}
let newWidth;
for (j = 0; j < this.columns.length; j++) {
c = this.columns[j];
for (j = 0; j < vc.length; j++) {
c = vc[j];
if (!c || c.hidden || !children[j]) { continue; }
newWidth = children[j].offsetWidth;

Expand Down
Loading