From 08e0ecc186e243cceae4d5fa16dc4a65dabe9564 Mon Sep 17 00:00:00 2001 From: ghiscoding Date: Fri, 1 Dec 2023 19:15:45 -0500 Subject: [PATCH 1/2] fix: revamp all cell selection range with key combos, fixes #935 the previous key combo were incorrect, the new combo is the following - `Shift+Home` will select from left most (index 0) to current cell position horizontally - `Shift+End` will select from current cell position until the last cell horizontally - `Ctrl+Shift+Home` will select everything that is on the left side of current cell position and everything on top current position (horizontally left until first cell & vertically left until first row) - `Ctrl+Shift+End` will select everything that is on the right side of current cell position and everything on bottom current position (horizontally right until last cell & vertically right until last row) --- src/plugins/slick.cellselectionmodel.ts | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/plugins/slick.cellselectionmodel.ts b/src/plugins/slick.cellselectionmodel.ts index 6040647d..4c325513 100644 --- a/src/plugins/slick.cellselectionmodel.ts +++ b/src/plugins/slick.cellselectionmodel.ts @@ -154,8 +154,8 @@ export class SlickCellSelectionModel { protected handleKeyDown(e: KeyboardEvent) { let ranges: SlickRange_[], last: SlickRange_; + const colLn = this._grid.getColumns().length; const active = this._grid.getActiveCell(); - const metaKey = e.ctrlKey || e.metaKey; let dataLn = 0; if (this._dataView) { dataLn = this._dataView?.getPagingInfo().pageSize || this._dataView.getLength(); @@ -163,8 +163,7 @@ export class SlickCellSelectionModel { dataLn = this._grid.getDataLength(); } - if (active && e.shiftKey && !metaKey && !e.altKey && this.isKeyAllowed(e.key)) { - + if (active && (e.shiftKey || e.ctrlKey) && !e.altKey && this.isKeyAllowed(e.key)) { ranges = this.getSelectedRanges().slice(); if (!ranges.length) { ranges.push(new SlickRange(active.row, active.cell)); @@ -184,9 +183,10 @@ export class SlickCellSelectionModel { const dirRow = active.row === last.fromRow ? 1 : -1; const dirCell = active.cell === last.fromCell ? 1 : -1; const isSingleKeyMove = e.key.startsWith('Arrow'); + let toCell: undefined | number = undefined; let toRow = 0; - if (isSingleKeyMove) { + if (isSingleKeyMove && !e.ctrlKey) { // single cell move: (Arrow{Up/ArrowDown/ArrowLeft/ArrowRight}) if (e.key === 'ArrowLeft') { dCell -= dirCell; @@ -207,9 +207,17 @@ export class SlickCellSelectionModel { this._prevSelectedRow = active.row; } - if (e.key === 'Home') { + if (e.shiftKey && !e.ctrlKey && e.key === 'Home') { + toCell = 0; + toRow = active.row; + } else if (e.shiftKey && !e.ctrlKey && e.key === 'End') { + toCell = colLn - 1; + toRow = active.row; + } else if (e.ctrlKey && e.shiftKey && e.key === 'Home') { + toCell = 0; toRow = 0; - } else if (e.key === 'End') { + } else if (e.ctrlKey && e.shiftKey && e.key === 'End') { + toCell = colLn - 1; toRow = dataLn - 1; } else if (e.key === 'PageUp') { if (this._prevSelectedRow >= 0) { @@ -230,7 +238,8 @@ export class SlickCellSelectionModel { } // define new selection range - const new_last = new SlickRange(active.row, active.cell, toRow, active.cell + dirCell * dCell); + toCell ??= active.cell + dirCell * dCell; + const new_last = new SlickRange(active.row, active.cell, toRow, toCell); if (this.removeInvalidRanges([new_last]).length) { ranges.push(new_last); const viewRow = dirRow > 0 ? new_last.toRow : new_last.fromRow; From 373d361283a578f76ab10beb8d55869a03333c66 Mon Sep 17 00:00:00 2001 From: ghiscoding Date: Sat, 2 Dec 2023 00:03:10 -0500 Subject: [PATCH 2/2] chore: add & fix Cypress test for cell range selections --- .../example-auto-scroll-when-dragging.cy.ts | 8 +- .../e2e/example-spreadsheet-dataview.cy.ts | 74 ++++++++++++------- cypress/e2e/example-spreadsheet.cy.ts | 40 ++++++++-- cypress/support/commands.ts | 13 +++- cypress/support/drag.ts | 10 +-- ...e-frozen-columns-and-rows-spreadsheet.html | 2 +- examples/example-spreadsheet-dataview.html | 2 +- examples/example-spreadsheet.html | 2 +- src/plugins/slick.cellselectionmodel.ts | 7 +- src/slick.grid.ts | 2 +- 10 files changed, 110 insertions(+), 50 deletions(-) diff --git a/cypress/e2e/example-auto-scroll-when-dragging.cy.ts b/cypress/e2e/example-auto-scroll-when-dragging.cy.ts index 31a3c7da..3f3bc2a9 100644 --- a/cypress/e2e/example-auto-scroll-when-dragging.cy.ts +++ b/cypress/e2e/example-auto-scroll-when-dragging.cy.ts @@ -28,7 +28,7 @@ describe('Example - Auto scroll when dragging', { retries: 1 }, () => { }); it('should select border shown in cell selection model, and hidden in row selection model when dragging', { scrollBehavior: false }, function () { - cy.getCell(0, 1, '', { parentSelector: "#myGrid", rowHeight: cellHeight }) + cy.getNthCell(0, 1, '', { parentSelector: "#myGrid", rowHeight: cellHeight }) .as('cell1') .dragStart(); @@ -39,7 +39,7 @@ describe('Example - Auto scroll when dragging', { retries: 1 }, () => { cy.get('#myGrid .slick-range-decorator').should('not.be.exist'); cy.get('#myGrid .slick-cell.selected').should('have.length', 6); - cy.getCell(0, 1, '', { parentSelector: "#myGrid2", rowHeight: cellHeight }) + cy.getNthCell(0, 1, '', { parentSelector: "#myGrid2", rowHeight: cellHeight }) .as('cell2') .dragStart(); cy.get('#myGrid2 .slick-range-decorator').should('be.exist').and('have.css', 'border-style').and('equal', 'none'); @@ -89,7 +89,7 @@ describe('Example - Auto scroll when dragging', { retries: 1 }, () => { function getIntervalUntilRow16Displayed(selector, px) { const viewportSelector = (selector + ' .slick-viewport:first'); - cy.getCell(0, 1, '', { parentSelector: selector, rowHeight: cellHeight }) + cy.getNthCell(0, 1, '', { parentSelector: selector, rowHeight: cellHeight }) .dragStart(); return cy.get(viewportSelector).invoke('scrollTop').then(scrollBefore => { cy.dragOutside('bottom', 0, px, { parentSelector: selector, rowHeight: cellHeight }); @@ -275,7 +275,7 @@ describe('Example - Auto scroll when dragging', { retries: 1 }, () => { }); function testDragInGrouping(selector) { - cy.getCell(7, 0, 'bottomRight', { parentSelector: selector, rowHeight: cellHeight }) + cy.getNthCell(7, 0, 'bottomRight', { parentSelector: selector, rowHeight: cellHeight }) .dragStart(); cy.get(selector + ' .slick-viewport:last').as('viewport').invoke('scrollTop').then(scrollBefore => { cy.dragOutside('bottom', 400, 300, { parentSelector: selector, rowHeight: cellHeight }); diff --git a/cypress/e2e/example-spreadsheet-dataview.cy.ts b/cypress/e2e/example-spreadsheet-dataview.cy.ts index 0ef94dc3..1bd28e01 100644 --- a/cypress/e2e/example-spreadsheet-dataview.cy.ts +++ b/cypress/e2e/example-spreadsheet-dataview.cy.ts @@ -61,7 +61,7 @@ describe('Example - Spreadsheet with DataView and Cell Selection', { retries: 0 .should('have.text', '{"fromRow":10,"fromCell":4,"toCell":4,"toRow":46}'); }); - it('should click on cell E12 then End key w/selection E46-E99', () => { + it('should click on cell E46 then Shift+End key with full row horizontal selection E46-CV46', () => { cy.getCell(46, 5, '', { parentSelector: "#myGrid", rowHeight: cellHeight }) .as('cell_E46') .click(); @@ -70,19 +70,43 @@ describe('Example - Spreadsheet with DataView and Cell Selection', { retries: 0 .type('{shift}{end}'); cy.get('#selectionRange') - .should('have.text', '{"fromRow":46,"fromCell":5,"toCell":5,"toRow":99}'); + .should('have.text', '{"fromRow":46,"fromCell":5,"toCell":100,"toRow":46}'); }); - it('should click on cell C85 then End key w/selection C0-C85', () => { - cy.getCell(85, 3, '', { parentSelector: "#myGrid", rowHeight: cellHeight }) - .as('cell_C85') + it('should click on cell CP54 then Ctrl+Shift+End keys with selection E46-CV99', () => { + cy.getCell(54, 94, '', { parentSelector: "#myGrid", rowHeight: cellHeight }) + .as('cell_CP54') .click(); - cy.get('@cell_C85') - .type('{shift}{home}'); + cy.get('@cell_CP54') + .type('{ctrl}{shift}{end}'); + + cy.get('#selectionRange') + .should('have.text', '{"fromRow":54,"fromCell":94,"toCell":100,"toRow":99}'); + }); + + it('should click on cell CP95 then Ctrl+Shift+Home keys with selection C0-CP95', () => { + cy.getCell(95, 98, '', { parentSelector: "#myGrid", rowHeight: cellHeight }) + .as('cell_CP95') + .click(); + + cy.get('@cell_CP95') + .type('{ctrl}{shift}{home}'); + + cy.get('#selectionRange') + .should('have.text', '{"fromRow":0,"fromCell":0,"toCell":98,"toRow":95}'); + }); + + it('should click on cell CR5 then Ctrl+Home keys and expect to scroll back to cell A0 without any selection range', () => { + cy.getCell(5, 95, '', { parentSelector: "#myGrid", rowHeight: cellHeight }) + .as('cell_CR95') + .click(); + + cy.get('@cell_CR95') + .type('{ctrl}{home}'); cy.get('#selectionRange') - .should('have.text', '{"fromRow":0,"fromCell":3,"toCell":3,"toRow":85}'); + .should('have.text', ''); }); }); @@ -92,7 +116,7 @@ describe('Example - Spreadsheet with DataView and Cell Selection', { retries: 0 cy.get('[data-val="25"]').click(); }); - it('should click on cell B14 then Shift+End w/selection B14-24', () => { + it('should click on cell B14 then Shift+End with selection B14-24', () => { cy.getCell(14, 2, '', { parentSelector: "#myGrid", rowHeight: cellHeight }) .as('cell_B14') .click(); @@ -101,45 +125,45 @@ describe('Example - Spreadsheet with DataView and Cell Selection', { retries: 0 .type('{shift}{end}'); cy.get('#selectionRange') - .should('have.text', '{"fromRow":14,"fromCell":2,"toCell":2,"toRow":24}'); + .should('have.text', '{"fromRow":14,"fromCell":2,"toCell":100,"toRow":14}'); }); - it('should click on cell C19 then Shift+End w/selection C0-19', () => { - cy.getCell(19, 2, '', { parentSelector: "#myGrid", rowHeight: cellHeight }) - .as('cell_C19') + it('should click on cell CS14 then Shift+Home with selection A14-CS14', () => { + cy.getCell(14, 97, '', { parentSelector: "#myGrid", rowHeight: cellHeight }) + .as('cell_CS14') .click(); - cy.get('@cell_C19') + cy.get('@cell_CS14') .type('{shift}{home}'); cy.get('#selectionRange') - .should('have.text', '{"fromRow":0,"fromCell":2,"toCell":2,"toRow":19}'); + .should('have.text', '{"fromRow":14,"fromCell":0,"toCell":97,"toRow":14}'); }); - it('should click on cell E3 then Shift+PageDown multiple times with current page selection starting at E3 w/selection E3-24', () => { - cy.getCell(3, 5, '', { parentSelector: "#myGrid", rowHeight: cellHeight }) - .as('cell_E3') + it('should click on cell CN3 then Shift+PageDown multiple times with current page selection starting at E3 w/selection E3-24', () => { + cy.getCell(3, 95, '', { parentSelector: "#myGrid", rowHeight: cellHeight }) + .as('cell_CN3') .click(); - cy.get('@cell_E3') + cy.get('@cell_CN3') .type('{shift}{pagedown}{pagedown}{pagedown}'); cy.get('#selectionRange') - .should('have.text', '{"fromRow":3,"fromCell":5,"toCell":5,"toRow":24}'); + .should('have.text', '{"fromRow":3,"fromCell":95,"toCell":95,"toRow":24}'); }); - it('should change to 2nd page then click on cell D41 then Shift+PageUp multiple times with current page selection w/selection D25-41', () => { + it('should change to 2nd page then click on cell CN41 then Shift+PageUp multiple times with current page selection w/selection D25-41', () => { cy.get('.slick-pager .sgi-chevron-right').click(); - cy.getCell(15, 4, '', { parentSelector: "#myGrid", rowHeight: cellHeight }) - .as('cell_D41') + cy.getCell(15, 92, '', { parentSelector: "#myGrid", rowHeight: cellHeight }) + .as('cell_CN41') .click(); - cy.get('@cell_D41') + cy.get('@cell_CN41') .type('{shift}{pageup}{pageup}{pageup}'); cy.get('#selectionRange') - .should('have.text', '{"fromRow":0,"fromCell":4,"toCell":4,"toRow":15}'); + .should('have.text', '{"fromRow":0,"fromCell":92,"toCell":92,"toRow":15}'); }); }); }); diff --git a/cypress/e2e/example-spreadsheet.cy.ts b/cypress/e2e/example-spreadsheet.cy.ts index fc709639..166b1c5d 100644 --- a/cypress/e2e/example-spreadsheet.cy.ts +++ b/cypress/e2e/example-spreadsheet.cy.ts @@ -60,7 +60,7 @@ describe('Example - Spreadsheet and Cell Selection', { retries: 0 }, () => { .should('have.text', '{"fromRow":10,"fromCell":4,"toCell":4,"toRow":46}'); }); - it('should click on cell E12 then End key w/selection E46-E99', () => { + it('should click on cell E46 then Shift+End key with full row horizontal selection E46-CV46', () => { cy.getCell(46, 5, '', { parentSelector: "#myGrid", rowHeight: cellHeight }) .as('cell_E46') .click(); @@ -69,18 +69,42 @@ describe('Example - Spreadsheet and Cell Selection', { retries: 0 }, () => { .type('{shift}{end}'); cy.get('#selectionRange') - .should('have.text', '{"fromRow":46,"fromCell":5,"toCell":5,"toRow":99}'); + .should('have.text', '{"fromRow":46,"fromCell":5,"toCell":100,"toRow":46}'); }); - it('should click on cell C85 then End key w/selection C0-C85', () => { - cy.getCell(85, 3, '', { parentSelector: "#myGrid", rowHeight: cellHeight }) - .as('cell_C85') + it('should click on cell CP54 then Ctrl+Shift+End keys with selection E46-CV99', () => { + cy.getCell(54, 94, '', { parentSelector: "#myGrid", rowHeight: cellHeight }) + .as('cell_CP54') .click(); - cy.get('@cell_C85') - .type('{shift}{home}'); + cy.get('@cell_CP54') + .type('{ctrl}{shift}{end}'); cy.get('#selectionRange') - .should('have.text', '{"fromRow":0,"fromCell":3,"toCell":3,"toRow":85}'); + .should('have.text', '{"fromRow":54,"fromCell":94,"toCell":100,"toRow":99}'); + }); + + it('should click on cell CP95 then Ctrl+Shift+Home keys with selection C0-CP95', () => { + cy.getCell(95, 98, '', { parentSelector: "#myGrid", rowHeight: cellHeight }) + .as('cell_CP95') + .click(); + + cy.get('@cell_CP95') + .type('{ctrl}{shift}{home}'); + + cy.get('#selectionRange') + .should('have.text', '{"fromRow":0,"fromCell":0,"toCell":98,"toRow":95}'); + }); + + it('should click on cell CR5 then Ctrl+Home keys and expect to scroll back to cell A0 without any selection range', () => { + cy.getCell(5, 95, '', { parentSelector: "#myGrid", rowHeight: cellHeight }) + .as('cell_CR95') + .click(); + + cy.get('@cell_CR95') + .type('{ctrl}{home}'); + + cy.get('#selectionRange') + .should('have.text', ''); }); }); diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts index a6135edd..308078b7 100644 --- a/cypress/support/commands.ts +++ b/cypress/support/commands.ts @@ -33,6 +33,7 @@ declare global { // triggerHover: (elements: NodeListOf) => void; convertPosition(viewport: string): Chainable | { x: string; y: string; }>; getCell(row: number, col: number, viewport?: string, options?: { parentSelector?: string, rowHeight?: number; }): Chainable>; + getNthCell(row: number, nthCol: number, viewport?: string, options?: { parentSelector?: string, rowHeight?: number; }): Chainable>; restoreLocalStorage(): Chainable>; saveLocalStorage(): Chainable>; } @@ -40,14 +41,22 @@ declare global { } // convert position like 'topLeft' to the object { x: 'left|right', y: 'top|bottom' } -Cypress.Commands.add('convertPosition', (viewport = 'topLeft') => cy.wrap(convertPosition(viewport))) +Cypress.Commands.add('convertPosition', (viewport = 'topLeft') => cy.wrap(convertPosition(viewport))); Cypress.Commands.add('getCell', (row, col, viewport = 'topLeft', { parentSelector = '', rowHeight = 25 } = {}) => { const position = convertPosition(viewport); const canvasSelectorX = position.x ? `.grid-canvas-${position.x}` : ''; const canvasSelectorY = position.y ? `.grid-canvas-${position.y}` : ''; - return cy.get(`${parentSelector} ${canvasSelectorX}${canvasSelectorY} [style="top: ${row * rowHeight}px;"] > .slick-cell:nth(${col})`); + return cy.get(`${parentSelector} ${canvasSelectorX}${canvasSelectorY} [style="top: ${row * rowHeight}px;"] > .slick-cell.l${col}.r${col}`); +}); + +Cypress.Commands.add('getNthCell', (row, nthCol, viewport = 'topLeft', { parentSelector = '', rowHeight = 25 } = {}) => { + const position = convertPosition(viewport); + const canvasSelectorX = position.x ? `.grid-canvas-${position.x}` : ''; + const canvasSelectorY = position.y ? `.grid-canvas-${position.y}` : ''; + + return cy.get(`${parentSelector} ${canvasSelectorX}${canvasSelectorY} [style="top: ${row * rowHeight}px;"] > .slick-cell:nth(${nthCol})`); }); const LOCAL_STORAGE_MEMORY = {}; diff --git a/cypress/support/drag.ts b/cypress/support/drag.ts index f00d010b..94881118 100644 --- a/cypress/support/drag.ts +++ b/cypress/support/drag.ts @@ -18,13 +18,13 @@ Cypress.Commands.add('dragStart', { prevSubject: true }, (subject, { cellWidth = return cy.wrap(subject).click({ force: true }) .trigger('mousedown', { which: 1 }) .trigger('mousemove', cellWidth / 3, cellHeight / 3); -}) +}); // use a different command name than "drag" so that it doesn't conflict with the "@4tw/cypress-drag-drop" lib // @ts-ignore Cypress.Commands.add('dragCell', { prevSubject: true }, (subject, addRow, addCell, { cellWidth = 80, cellHeight = 25 } = {}) => { return cy.wrap(subject).trigger('mousemove', cellWidth * (addCell + 0.5), cellHeight * (addRow + 0.5), { force: true }); -}) +}); Cypress.Commands.add('dragOutside', (viewport = 'topLeft', ms = 0, px = 0, { parentSelector = 'div[class^="slickgrid_"]', scrollbarDimension = 17 } = {}) => { const $parent = cy.$$(parentSelector); @@ -49,17 +49,17 @@ Cypress.Commands.add('dragOutside', (viewport = 'topLeft', ms = 0, px = 0, { par cy.wait(ms); } return; -}) +}); Cypress.Commands.add('dragEnd', { prevSubject: 'optional' }, (subject, gridSelector = 'div[class^="slickgrid_"]') => { cy.get(gridSelector).trigger('mouseup', { force: true }); return; -}) +}); export function getScrollDistanceWhenDragOutsideGrid(selector, viewport, dragDirection, fromRow, fromCol, px = 100) { return (cy as any).convertPosition(viewport).then((_viewportPosition: { x: number; y: number; }) => { const viewportSelector = `${selector} .slick-viewport-${_viewportPosition.x}.slick-viewport-${_viewportPosition.y}`; - (cy as any).getCell(fromRow, fromCol, viewport, { parentSelector: selector }) + (cy as any).getNthCell(fromRow, fromCol, viewport, { parentSelector: selector }) .dragStart(); return cy.get(viewportSelector).then($viewport => { const scrollTopBefore = $viewport.scrollTop(); diff --git a/examples/example-frozen-columns-and-rows-spreadsheet.html b/examples/example-frozen-columns-and-rows-spreadsheet.html index 341d57d6..6ac7fb56 100644 --- a/examples/example-frozen-columns-and-rows-spreadsheet.html +++ b/examples/example-frozen-columns-and-rows-spreadsheet.html @@ -39,7 +39,7 @@

  • Use Ctrl-C and Ctrl-V keyboard shortcuts to cut and paste cells
  • Use Esc to cancel a copy and paste operation
  • Edit the cell and select a cell range to paste the range
  • -
  • Cell Selection using "Shift+{key}" where "key" can be any of:
  • +
  • Cell Selection using "Shift+{key}" or "Ctrl+Shift+{key}" where "key" can be any of:
    • Arrow Up/Down/Left/Right
    • Page Up/Down
    • diff --git a/examples/example-spreadsheet-dataview.html b/examples/example-spreadsheet-dataview.html index ff103de5..a05be377 100644 --- a/examples/example-spreadsheet-dataview.html +++ b/examples/example-spreadsheet-dataview.html @@ -40,7 +40,7 @@

    • Use Ctrl-C and Ctrl-V keyboard shortcuts to cut and paste cells
    • Use Esc to cancel a copy and paste operation
    • Edit the cell and select a cell range to paste the range
    • -
    • Cell Selection using "Shift+{key}" where "key" can be any of:
    • +
    • Cell Selection using "Shift+{key}" or "Ctrl+Shift+{key}" where "key" can be any of:
      • Arrow Up/Down/Left/Right
      • Page Up/Down
      • diff --git a/examples/example-spreadsheet.html b/examples/example-spreadsheet.html index 0b18910c..394a51de 100644 --- a/examples/example-spreadsheet.html +++ b/examples/example-spreadsheet.html @@ -38,7 +38,7 @@

      • Use Ctrl-C and Ctrl-V keyboard shortcuts to cut and paste cells
      • Use Esc to cancel a copy and paste operation
      • Edit the cell and select a cell range to paste the range
      • -
      • Cell Selection using "Shift+{key}" where "key" can be any of:
      • +
      • Cell Selection using "Shift+{key}" or "Ctrl+Shift+{key}" where "key" can be any of:
        • Arrow Up/Down/Left/Right
        • Page Up/Down
        • diff --git a/src/plugins/slick.cellselectionmodel.ts b/src/plugins/slick.cellselectionmodel.ts index 4c325513..ff09f8b4 100644 --- a/src/plugins/slick.cellselectionmodel.ts +++ b/src/plugins/slick.cellselectionmodel.ts @@ -140,9 +140,12 @@ export class SlickCellSelectionModel { protected handleActiveCellChange(_e: Event, args: OnActiveCellChangedEventArgs) { this._prevSelectedRow = undefined; - if (this._options?.selectActiveCell && Utils.isDefined(args.row) && Utils.isDefined(args.cell)) { + const isCellDefined = Utils.isDefined(args.cell); + const isRowDefined = Utils.isDefined(args.row); + + if (this._options?.selectActiveCell && isRowDefined && isCellDefined) { this.setSelectedRanges([new SlickRange(args.row, args.cell)]); - } else if (!this._options?.selectActiveCell) { + } else if (!this._options?.selectActiveCell || (!isRowDefined && !isCellDefined)) { // clear the previous selection once the cell changes this.setSelectedRanges([]); } diff --git a/src/slick.grid.ts b/src/slick.grid.ts index 62331dc3..965b0a8a 100644 --- a/src/slick.grid.ts +++ b/src/slick.grid.ts @@ -5688,7 +5688,7 @@ export class SlickGrid = Column, O e } protected setActiveCellInternal(newCell: HTMLDivElement | null, opt_editMode?: boolean | null, preClickModeOn?: boolean | null, suppressActiveCellChangedEvent?: boolean, e?: Event | SlickEvent_) { - if (this.activeCellNode !== null) { + if (Utils.isDefined(this.activeCellNode)) { this.makeActiveCellNormal(); this.activeCellNode.classList.remove('active'); this.rowsCache[this.activeRow]?.rowNode?.forEach((node) => node.classList.remove('active'));