diff --git a/e2e/testcafe-devextreme/tests/dataGrid/common/etalons/column-separator-1 (fluent.blue.light).png b/e2e/testcafe-devextreme/tests/dataGrid/common/columnResizing/etalons/column-separator-1 (fluent.blue.light).png similarity index 100% rename from e2e/testcafe-devextreme/tests/dataGrid/common/etalons/column-separator-1 (fluent.blue.light).png rename to e2e/testcafe-devextreme/tests/dataGrid/common/columnResizing/etalons/column-separator-1 (fluent.blue.light).png diff --git a/e2e/testcafe-devextreme/tests/dataGrid/common/etalons/column-separator-2 (fluent.blue.light).png b/e2e/testcafe-devextreme/tests/dataGrid/common/columnResizing/etalons/column-separator-2 (fluent.blue.light).png similarity index 100% rename from e2e/testcafe-devextreme/tests/dataGrid/common/etalons/column-separator-2 (fluent.blue.light).png rename to e2e/testcafe-devextreme/tests/dataGrid/common/columnResizing/etalons/column-separator-2 (fluent.blue.light).png diff --git a/e2e/testcafe-devextreme/tests/dataGrid/common/etalons/column-separator-3 (fluent.blue.light).png b/e2e/testcafe-devextreme/tests/dataGrid/common/columnResizing/etalons/column-separator-3 (fluent.blue.light).png similarity index 100% rename from e2e/testcafe-devextreme/tests/dataGrid/common/etalons/column-separator-3 (fluent.blue.light).png rename to e2e/testcafe-devextreme/tests/dataGrid/common/columnResizing/etalons/column-separator-3 (fluent.blue.light).png diff --git a/e2e/testcafe-devextreme/tests/dataGrid/common/etalons/column-separator-4 (fluent.blue.light).png b/e2e/testcafe-devextreme/tests/dataGrid/common/columnResizing/etalons/column-separator-4 (fluent.blue.light).png similarity index 100% rename from e2e/testcafe-devextreme/tests/dataGrid/common/etalons/column-separator-4 (fluent.blue.light).png rename to e2e/testcafe-devextreme/tests/dataGrid/common/columnResizing/etalons/column-separator-4 (fluent.blue.light).png diff --git a/e2e/testcafe-devextreme/tests/dataGrid/common/etalons/column-separator-5 (fluent.blue.light).png b/e2e/testcafe-devextreme/tests/dataGrid/common/columnResizing/etalons/column-separator-5 (fluent.blue.light).png similarity index 100% rename from e2e/testcafe-devextreme/tests/dataGrid/common/etalons/column-separator-5 (fluent.blue.light).png rename to e2e/testcafe-devextreme/tests/dataGrid/common/columnResizing/etalons/column-separator-5 (fluent.blue.light).png diff --git a/e2e/testcafe-devextreme/tests/dataGrid/common/etalons/column-separator-6 (fluent.blue.light).png b/e2e/testcafe-devextreme/tests/dataGrid/common/columnResizing/etalons/column-separator-6 (fluent.blue.light).png similarity index 100% rename from e2e/testcafe-devextreme/tests/dataGrid/common/etalons/column-separator-6 (fluent.blue.light).png rename to e2e/testcafe-devextreme/tests/dataGrid/common/columnResizing/etalons/column-separator-6 (fluent.blue.light).png diff --git a/e2e/testcafe-devextreme/tests/dataGrid/common/etalons/column-separator-7 (fluent.blue.light).png b/e2e/testcafe-devextreme/tests/dataGrid/common/columnResizing/etalons/column-separator-7 (fluent.blue.light).png similarity index 100% rename from e2e/testcafe-devextreme/tests/dataGrid/common/etalons/column-separator-7 (fluent.blue.light).png rename to e2e/testcafe-devextreme/tests/dataGrid/common/columnResizing/etalons/column-separator-7 (fluent.blue.light).png diff --git a/e2e/testcafe-devextreme/tests/dataGrid/common/etalons/column-separator-8 (fluent.blue.light).png b/e2e/testcafe-devextreme/tests/dataGrid/common/columnResizing/etalons/column-separator-8 (fluent.blue.light).png similarity index 100% rename from e2e/testcafe-devextreme/tests/dataGrid/common/etalons/column-separator-8 (fluent.blue.light).png rename to e2e/testcafe-devextreme/tests/dataGrid/common/columnResizing/etalons/column-separator-8 (fluent.blue.light).png diff --git a/e2e/testcafe-devextreme/tests/dataGrid/common/etalons/column-separator-9 (fluent.blue.light).png b/e2e/testcafe-devextreme/tests/dataGrid/common/columnResizing/etalons/column-separator-9 (fluent.blue.light).png similarity index 100% rename from e2e/testcafe-devextreme/tests/dataGrid/common/etalons/column-separator-9 (fluent.blue.light).png rename to e2e/testcafe-devextreme/tests/dataGrid/common/columnResizing/etalons/column-separator-9 (fluent.blue.light).png diff --git a/e2e/testcafe-devextreme/tests/dataGrid/common/columnResizing/functional.ts b/e2e/testcafe-devextreme/tests/dataGrid/common/columnResizing/functional.ts new file mode 100644 index 000000000000..4ecc04eea337 --- /dev/null +++ b/e2e/testcafe-devextreme/tests/dataGrid/common/columnResizing/functional.ts @@ -0,0 +1,152 @@ +import DataGrid from 'devextreme-testcafe-models/dataGrid'; + +import { ClientFunction } from 'testcafe'; +import url from '../../../../helpers/getPageUrl'; +import { createWidget } from '../../../../helpers/createWidget'; + +fixture.disablePageReloads`Column resizing` + .page(url(__dirname, '../../../container.html')); + +// T1314667 +test('DataGrid – Resize indicator is moved when resizing a grouped column if showWhenGrouped is set to true', async (t) => { + const dataGrid = new DataGrid('#container'); + + await t.expect(dataGrid.isReady()).ok(); + + await dataGrid.resizeHeader(3, 30, false); + + await t + .expect(dataGrid.getHeaders().getHeaderRow(1).getHeaderCell(0).element.clientWidth) + .within(128, 130); +}).before(async () => { + await createWidget('dxDataGrid', { + dataSource: [{ + ID: 1, + Country: 'Brazil', + Area: 8515767, + Population_Urban: 0.85, + Population_Rural: 0.15, + Population_Total: 205809000, + }], + keyExpr: 'ID', + allowColumnResizing: true, + columnResizingMode: 'widget', + width: 500, + columns: [ + { + dataField: 'ID', + fixed: true, + allowReordering: false, + width: 50, + }, + + { + caption: 'Population', + columns: [ + { + dataField: 'Country', + showWhenGrouped: true, + width: 100, + groupIndex: 0, + }, + { dataField: 'Area' }, + { dataField: 'Population_Total' }, + { dataField: 'Population_Urban' }, + { dataField: 'Population_Rural' }, + ], + }, + ], + }); +}); + +const tryResizeHeaderInBandArea = ( + dataGrid: DataGrid, + columnIndex: number, + offset: number, +): Promise => { + const { getInstance } = dataGrid; + + const triggerPointerEvent = ($element: JQuery, eventName: string, x: number, y: number) => { + $element + .trigger($.Event(eventName, { + pageX: x, + pageY: y, + pointers: [{ pointerId: 1 }], + })); + }; + + return ClientFunction( + () => { + const gridInstance = getInstance() as any; + const $gridElement = $(gridInstance.element()); + const columnHeadersView = gridInstance.getView('columnHeadersView'); + const $header = $(columnHeadersView.getHeaderElement(columnIndex)); + const headerOffset = $header.offset(); + + triggerPointerEvent($(document), 'dxpointermove', headerOffset.left, headerOffset.top - 10); + triggerPointerEvent($gridElement, 'dxpointerdown', headerOffset.left, headerOffset.top - 10); + triggerPointerEvent($(document), 'dxpointermove', headerOffset.left + offset, headerOffset.top - 10); + triggerPointerEvent($(document), 'dxpointerup', headerOffset.left + offset, headerOffset.top - 10); + }, + { + dependencies: { + getInstance, + triggerPointerEvent, + columnIndex, + offset, + }, + }, + )(); +}; + +// T1317039 +test('DataGrid – Columns should not be resized from band area (T1317039)', async (t) => { + const dataGrid = new DataGrid('#container'); + + await t.expect(dataGrid.isReady()).ok(); + + await tryResizeHeaderInBandArea(dataGrid, 3, 30); + + await t + .expect(dataGrid.getHeaders().getHeaderRow(1).getHeaderCell(0).element.clientWidth) + .within(98, 100); +}).before(async () => { + await createWidget('dxDataGrid', { + dataSource: [{ + ID: 1, + Country: 'Brazil', + Area: 8515767, + Population_Urban: 0.85, + Population_Rural: 0.15, + Population_Total: 205809000, + }], + keyExpr: 'ID', + allowColumnResizing: true, + columnResizingMode: 'widget', + width: 500, + columns: [ + { + dataField: 'ID', + fixed: true, + allowReordering: false, + width: 50, + }, + + { + caption: 'Population', + columns: [ + { + dataField: 'Country', + showWhenGrouped: true, + width: 100, + groupIndex: 0, + }, + { dataField: 'Area' }, + { dataField: 'Population_Total' }, + { dataField: 'Population_Urban' }, + { dataField: 'Population_Rural' }, + ], + }, + ], + }); +}); diff --git a/e2e/testcafe-devextreme/tests/dataGrid/common/columnResizing.ts b/e2e/testcafe-devextreme/tests/dataGrid/common/columnResizing/visual.ts similarity index 58% rename from e2e/testcafe-devextreme/tests/dataGrid/common/columnResizing.ts rename to e2e/testcafe-devextreme/tests/dataGrid/common/columnResizing/visual.ts index 763f2faa0ad8..45fb3e18e840 100644 --- a/e2e/testcafe-devextreme/tests/dataGrid/common/columnResizing.ts +++ b/e2e/testcafe-devextreme/tests/dataGrid/common/columnResizing/visual.ts @@ -1,12 +1,12 @@ import { createScreenshotsComparer } from 'devextreme-screenshot-comparer'; import DataGrid from 'devextreme-testcafe-models/dataGrid'; -import url from '../../../helpers/getPageUrl'; -import { createWidget } from '../../../helpers/createWidget'; -import { testScreenshot } from '../../../helpers/themeUtils'; +import url from '../../../../helpers/getPageUrl'; +import { createWidget } from '../../../../helpers/createWidget'; +import { testScreenshot } from '../../../../helpers/themeUtils'; fixture.disablePageReloads`Column resizing` - .page(url(__dirname, '../../container.html')); + .page(url(__dirname, '../../../container.html')); test.meta({ unstable: true })('column separator should starts from the parent', async (t) => { const { takeScreenshot, compareResults } = createScreenshotsComparer(t); @@ -74,55 +74,3 @@ test.meta({ unstable: true })('column separator should starts from the parent', columns: ['GDP_Total', 'Population_Urban'], }, 'Area'], })); - -// T1314667 -test('DataGrid – Resize indicator is moved when resizing a grouped column if showWhenGrouped is set to true', async (t) => { - const dataGrid = new DataGrid('#container'); - - await t.expect(dataGrid.isReady()).ok(); - - await dataGrid.resizeHeader(3, 30, false); - - await t - .expect(dataGrid.getHeaders().getHeaderRow(1).getHeaderCell(0).element.clientWidth) - .within(128, 130); -}).before(async () => { - await createWidget('dxDataGrid', { - dataSource: [{ - ID: 1, - Country: 'Brazil', - Area: 8515767, - Population_Urban: 0.85, - Population_Rural: 0.15, - Population_Total: 205809000, - }], - keyExpr: 'ID', - allowColumnResizing: true, - columnResizingMode: 'widget', - width: 500, - columns: [ - { - dataField: 'ID', - fixed: true, - allowReordering: false, - width: 50, - }, - - { - caption: 'Population', - columns: [ - { - dataField: 'Country', - showWhenGrouped: true, - width: 100, - groupIndex: 0, - }, - { dataField: 'Area' }, - { dataField: 'Population_Total' }, - { dataField: 'Population_Urban' }, - { dataField: 'Population_Rural' }, - ], - }, - ], - }); -}); diff --git a/packages/devextreme/js/__internal/grids/grid_core/column_fixing/m_column_fixing.ts b/packages/devextreme/js/__internal/grids/grid_core/column_fixing/m_column_fixing.ts index 96fa1c78e427..400c9cbb17db 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/column_fixing/m_column_fixing.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/column_fixing/m_column_fixing.ts @@ -23,7 +23,7 @@ import type { DraggingHeaderViewController, } from '../columns_resizing_reordering/m_columns_resizing_reordering'; import type { KeyboardNavigationController } from '../keyboard_navigation/m_keyboard_navigation'; -import type { ModuleType } from '../m_types'; +import type { ColumnPoint, Coordinates, ModuleType } from '../m_types'; import gridCoreUtils from '../m_utils'; import type { ColumnsView } from '../views/m_columns_view'; import { normalizeWidth } from '../views/m_columns_view'; @@ -1130,19 +1130,23 @@ const columnsResizer = (Base: ModuleType) => class } } - protected _getTargetPoint(pointsByColumns, currentX, deltaX) { + protected _getTargetPoint( + pointsByColumns: ColumnPoint[] | null | undefined, + currentPoint: Coordinates, + deltaX: number, + ): ColumnPoint | null { // @ts-expect-error const $transparentColumn = this._columnHeadersView.getTransparentColumnElement(); if ($transparentColumn && $transparentColumn.length) { const boundingRect = getBoundingRect($transparentColumn.get(0)); - if (currentX <= boundingRect.left || currentX >= boundingRect.right) { - return super._getTargetPoint(this._pointsByFixedColumns, currentX, deltaX); + if (currentPoint.x <= boundingRect.left || currentPoint.x >= boundingRect.right) { + return super._getTargetPoint(this._pointsByFixedColumns, currentPoint, deltaX); } } - return super._getTargetPoint(pointsByColumns, currentX, deltaX); + return super._getTargetPoint(pointsByColumns, currentPoint, deltaX); } }; diff --git a/packages/devextreme/js/__internal/grids/grid_core/columns_resizing_reordering/m_columns_resizing_reordering.ts b/packages/devextreme/js/__internal/grids/grid_core/columns_resizing_reordering/m_columns_resizing_reordering.ts index 4f7e1b7206e9..1f4f68678c98 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/columns_resizing_reordering/m_columns_resizing_reordering.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/columns_resizing_reordering/m_columns_resizing_reordering.ts @@ -23,7 +23,7 @@ import { isDefined, isObject, isString } from '@js/core/utils/type'; import swatchContainer from '@ts/core/utils/swatch_container'; import { getDraggingPanelBoundingRects } from '@ts/grids/grid_core/columns_resizing_reordering/utils'; import type { EditorFactory } from '@ts/grids/grid_core/editor_factory/m_editor_factory'; -import type { ColumnPoint, ModuleType } from '@ts/grids/grid_core/m_types'; +import type { ColumnPoint, Coordinates, ModuleType } from '@ts/grids/grid_core/m_types'; import type { RowsView } from '@ts/grids/grid_core/views/m_rows_view'; import type { ColumnChooserView } from '../column_chooser/m_column_chooser'; @@ -640,13 +640,13 @@ export class ColumnsResizerViewController extends modules.ViewController { private _$parentContainer: any; - public _targetPoint: any; + public _targetPoint?: ColumnPoint | null; private _resizingInfo: any; protected _columnsController!: ColumnsController; - private _pointsByColumns: any; + private _pointsByColumns?: ColumnPoint[] | null; private _moveSeparatorHandler: any; @@ -747,13 +747,24 @@ export class ColumnsResizerViewController extends modules.ViewController { /** * @extended: column_fixing */ - protected _getTargetPoint(pointsByColumns, currentX, deltaX) { + protected _getTargetPoint( + pointsByColumns: ColumnPoint[] | null | undefined, + currentPoint: Coordinates, + deltaX: number, + ): ColumnPoint | null { if (pointsByColumns) { - for (let i = 0; i < pointsByColumns.length; i++) { - if (pointsByColumns[i].x === pointsByColumns[0].x && pointsByColumns[i + 1] && pointsByColumns[i].x === pointsByColumns[i + 1].x) { + for (let i = 0; i < pointsByColumns.length; i += 1) { + if (pointsByColumns[i].x === pointsByColumns[0].x + && pointsByColumns[i + 1] + && pointsByColumns[i].x === pointsByColumns[i + 1].x + ) { + // eslint-disable-next-line no-continue continue; } - if (pointsByColumns[i].x - deltaX <= currentX && currentX <= pointsByColumns[i].x + deltaX) { + if (currentPoint.y >= pointsByColumns[i].y + && pointsByColumns[i].x - deltaX <= currentPoint.x + && currentPoint.x <= pointsByColumns[i].x + deltaX + ) { return pointsByColumns[i]; } } @@ -805,7 +816,11 @@ export class ColumnsResizerViewController extends modules.ViewController { } } - that._targetPoint = that._getTargetPoint(that.pointsByColumns(), eventData.x, columnsSeparatorWidth); + that._targetPoint = that._getTargetPoint( + that.pointsByColumns(), + eventData, + columnsSeparatorWidth, + ); that._previousParentOffset = parentOffset; that._isReadyResizing = false; @@ -857,19 +872,21 @@ export class ColumnsResizerViewController extends modules.ViewController { } private _setupResizingInfo(posX) { - const currentColumnIndex = this._targetPoint.columnIndex; - const nextColumnIndex = this._getNextColumnIndex(currentColumnIndex); - const $currentHeader = this._columnHeadersView.getHeaderElement(currentColumnIndex); - const $nextHeader = this._columnHeadersView.getHeaderElement(nextColumnIndex); - - this._resizingInfo = { - startPosX: posX, - currentColumnIndex, - currentColumnWidth: $currentHeader?.length ? getBoundingRect($currentHeader[0]).width : 0, - nextColumnIndex, - nextColumnWidth: $nextHeader?.length ? getBoundingRect($nextHeader[0]).width : 0, - needToInvertResizing: this._needToInvertResizing($currentHeader), - }; + if (this._targetPoint) { + const currentColumnIndex = this._targetPoint.columnIndex; + const nextColumnIndex = this._getNextColumnIndex(currentColumnIndex); + const $currentHeader = this._columnHeadersView.getHeaderElement(currentColumnIndex); + const $nextHeader = this._columnHeadersView.getHeaderElement(nextColumnIndex); + + this._resizingInfo = { + startPosX: posX, + currentColumnIndex, + currentColumnWidth: $currentHeader?.length ? getBoundingRect($currentHeader[0]).width : 0, + nextColumnIndex, + nextColumnWidth: $nextHeader?.length ? getBoundingRect($nextHeader[0]).width : 0, + needToInvertResizing: this._needToInvertResizing($currentHeader), + }; + } } /** @@ -882,7 +899,11 @@ export class ColumnsResizerViewController extends modules.ViewController { if (isTouchEvent(e)) { if (that._isHeadersRowArea(eventData.y)) { - that._targetPoint = that._getTargetPoint(that.pointsByColumns(), eventData.x, COLUMNS_SEPARATOR_TOUCH_TRACKER_WIDTH); + that._targetPoint = that._getTargetPoint( + that.pointsByColumns(), + eventData, + COLUMNS_SEPARATOR_TOUCH_TRACKER_WIDTH, + ); if (that._targetPoint) { that._columnsSeparatorView.moveByX(that._targetPoint.x - that._columnsSeparatorView.width() / 2); that._isReadyResizing = true; @@ -1230,15 +1251,14 @@ export class ColumnsResizerViewController extends modules.ViewController { return this._isResizing; } - private pointsByColumns(value) { + private pointsByColumns(value?: ColumnPoint[] | null): ColumnPoint[] | null | undefined { if (value !== undefined) { this._pointsByColumns = value; - } else { - if (!this._pointsByColumns) { - this._generatePointsByColumns(); - } - return this._pointsByColumns; + } else if (!this._pointsByColumns) { + this._generatePointsByColumns(); } + + return this._pointsByColumns; } } diff --git a/packages/devextreme/js/__internal/grids/grid_core/filter/m_filter_row.ts b/packages/devextreme/js/__internal/grids/grid_core/filter/m_filter_row.ts index 8bf4171823c2..e5f5a04eaaa3 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/filter/m_filter_row.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/filter/m_filter_row.ts @@ -886,22 +886,23 @@ export class ApplyFilterViewController extends modules.ViewController { } const columnsResizer = (Base: ModuleType) => class FilterRowColumnsResizerExtender extends Base { - protected _startResizing() { - const that = this; - + protected _startResizing(): void { // @ts-expect-error - super._startResizing.apply(that, arguments); + super._startResizing.apply(this, arguments); - if (that.isResizing()) { + if (this.isResizing()) { // @ts-expect-error - const overlayInstance = that._columnHeadersView.getFilterRangeOverlayInstance(); + const overlayInstance = this._columnHeadersView.getFilterRangeOverlayInstance(); - if (overlayInstance) { - const cellIndex = overlayInstance.$element().closest('td').index(); + if (!overlayInstance || !this._targetPoint) { + return; + } - if (cellIndex === that._targetPoint.columnIndex || cellIndex === that._targetPoint.columnIndex + 1) { - overlayInstance.$content().hide(); - } + const cellIndex = overlayInstance.$element().closest('td').index(); + const { columnIndex: resizingColumnIndex } = this._targetPoint; + + if (cellIndex === resizingColumnIndex || cellIndex === resizingColumnIndex + 1) { + overlayInstance.$content().hide(); } } } diff --git a/packages/devextreme/js/__internal/grids/grid_core/m_types.ts b/packages/devextreme/js/__internal/grids/grid_core/m_types.ts index 84a12673592e..d70bcda4c6a0 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/m_types.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/m_types.ts @@ -23,6 +23,11 @@ export interface ColumnPoint { y: number; } +export interface Coordinates { + x: number; + y: number; +} + // todo: move to upper .d.ts type OptionsMethod = (() => TOptions) & diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.dataGrid/columnFixing.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.dataGrid/columnFixing.tests.js index 376215cf6ef8..006b56c30ffd 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.dataGrid/columnFixing.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.dataGrid/columnFixing.tests.js @@ -2593,7 +2593,11 @@ QUnit.module('Headers reordering and resizing with fixed columns', { // act that.columnsResizerController._generatePointsByColumns(); - const targetPoint = that.columnsResizerController._getTargetPoint(that.columnsResizerController._pointsByColumns, -9825, 0); + const targetPoint = that.columnsResizerController._getTargetPoint( + that.columnsResizerController._pointsByColumns, + { x: -9825, y: -10000 }, + 0 + ); // assert assert.ok(!targetPoint, 'not has target point'); @@ -2611,7 +2615,11 @@ QUnit.module('Headers reordering and resizing with fixed columns', { // act that.columnsResizerController._generatePointsByColumns(); - const targetPoint = that.columnsResizerController._getTargetPoint(that.columnsResizerController._pointsByColumns, -9775, 0); + const targetPoint = that.columnsResizerController._getTargetPoint( + that.columnsResizerController._pointsByColumns, + { x: -9775, y: -10000 }, + 0 + ); // assert assert.deepEqual(targetPoint, {