Skip to content

Commit 0e362fd

Browse files
authored
Scheduler: T1187849 — Fix multi-cell selection on touch monitors (#33501)
1 parent ab7db71 commit 0e362fd

4 files changed

Lines changed: 67 additions & 28 deletions

File tree

packages/devextreme/js/__internal/scheduler/__tests__/__mock__/model/scheduler.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,20 @@ export class SchedulerModel {
7676
return getTexts(cells);
7777
}
7878

79+
getDateTableCell(rowIndex = 0, cellIndex = 0): HTMLElement {
80+
const rowSelector = `.dx-scheduler-date-table-row:nth-child(${rowIndex + 1})`;
81+
const cellSelector = `.dx-scheduler-date-table-cell:nth-child(${cellIndex + 1})`;
82+
const selector = `${rowSelector} ${cellSelector}`;
83+
84+
const result = this.container.querySelector(selector);
85+
86+
if (!result) {
87+
throw new Error(`Date cell in row ${rowIndex} and column ${cellIndex} not found`);
88+
}
89+
90+
return result as HTMLElement;
91+
}
92+
7993
getHeaderPanelContent(): string[] {
8094
const cells = this.container.querySelectorAll('.dx-scheduler-header-panel-cell');
8195
return getTexts(cells);
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import {
2+
afterEach, beforeEach, describe, expect, it,
3+
} from '@jest/globals';
4+
import { fireEvent } from '@testing-library/dom';
5+
import support from '@ts/core/utils/m_support';
6+
7+
import fx from '../../../common/core/animation/fx';
8+
import { createScheduler } from './__mock__/create_scheduler';
9+
import { setupSchedulerTestEnvironment } from './__mock__/m_mock_scheduler';
10+
11+
const defaultOptions = {
12+
currentView: 'week',
13+
views: ['week'],
14+
currentDate: new Date(2024, 0, 1),
15+
startDayHour: 9,
16+
endDayHour: 16,
17+
height: 600,
18+
};
19+
20+
describe('onSelectionEnd', () => {
21+
beforeEach(() => {
22+
fx.off = true;
23+
setupSchedulerTestEnvironment({ height: 600 });
24+
});
25+
26+
afterEach(() => {
27+
fx.off = false;
28+
document.body.innerHTML = '';
29+
});
30+
31+
it('T1187849: should select cells with mouse on touch monitor', async () => {
32+
const originalSupportTouch = support.touch;
33+
support.touch = true;
34+
35+
const { POM, scheduler } = await createScheduler(defaultOptions);
36+
const firstCell = POM.getDateTableCell(0, 0);
37+
const secondCell = POM.getDateTableCell(1, 0);
38+
39+
expect(scheduler.getWorkSpace().getScrollable().option('scrollByContent')).toBe(true);
40+
41+
fireEvent.mouseDown(firstCell, { which: 1 });
42+
fireEvent.mouseMove(secondCell, { which: 1 });
43+
fireEvent.mouseUp(secondCell, { which: 1 });
44+
45+
expect(scheduler.option('selectedCellData')).toHaveLength(2);
46+
expect(firstCell.classList.contains('dx-state-focused')).toBe(true);
47+
expect(secondCell.classList.contains('dx-state-focused')).toBe(true);
48+
49+
support.touch = originalSupportTouch;
50+
});
51+
});

packages/devextreme/js/__internal/scheduler/workspaces/m_work_space.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1217,7 +1217,7 @@ class SchedulerWorkSpace extends Widget<WorkspaceOptionsInternal> {
12171217
(eventsEngine.off as any)(element, SCHEDULER_CELL_DXPOINTERDOWN_EVENT_NAME);
12181218

12191219
eventsEngine.on(element, SCHEDULER_CELL_DXPOINTERDOWN_EVENT_NAME, DRAG_AND_DROP_SELECTOR, (e) => {
1220-
if (isMouseEvent(e) && e.which === 1) {
1220+
if ((isMouseEvent(e) || (e.originalEvent && isMouseEvent(e.originalEvent))) && e.which === 1) {
12211221
isPointerDown = true;
12221222
(this.$element() as any).addClass(WORKSPACE_WITH_MOUSE_SELECTION_CLASS);
12231223
(eventsEngine.off as any)(domAdapter.getDocument(), SCHEDULER_CELL_DXPOINTERUP_EVENT_NAME);
@@ -1229,7 +1229,7 @@ class SchedulerWorkSpace extends Widget<WorkspaceOptionsInternal> {
12291229
});
12301230

12311231
eventsEngine.on(element, SCHEDULER_CELL_DXPOINTERMOVE_EVENT_NAME, DRAG_AND_DROP_SELECTOR, (e) => {
1232-
if (isPointerDown && this._dateTableScrollable && !this._dateTableScrollable.option('scrollByContent')) {
1232+
if (isPointerDown && this._dateTableScrollable) {
12331233
e.preventDefault();
12341234
e.stopPropagation();
12351235
this.moveToCell($(e.target), true);

packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/workSpace.navigation.tests.js

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -779,32 +779,6 @@ module('Workspace navigation', () => {
779779
assert.equal(cells.filter('.dx-state-focused').length, 1, 'right quantity of focused cells');
780780
});
781781

782-
test('It should not be possible to select cells via mouse if scrollable \'scrollByContent\' is true', async function(assert) {
783-
const $element = this.createInstance({
784-
focusStateEnabled: true,
785-
firstDayOfWeek: 1,
786-
currentDate: new Date(2015, 3, 1),
787-
height: 400,
788-
allowMultipleCellSelection: true,
789-
onContentReady: function(e) {
790-
const scrollable = e.component._dateTableScrollable;
791-
scrollable.option('scrollByContent', true);
792-
},
793-
}, 'dxSchedulerWorkSpaceMonth');
794-
const workspace = $element.dxSchedulerWorkSpaceMonth('instance');
795-
796-
const stub = sinon.stub(workspace, 'notifyObserver');
797-
798-
const cells = $element.find('.' + CELL_CLASS);
799-
const cell = cells.eq(23).get(0);
800-
const $table = $element.find('.dx-scheduler-date-table');
801-
802-
pointerMock(cells.eq(2)).start().click();
803-
$($table).trigger($.Event('dxpointermove', { target: cell, toElement: cell, which: 1 }));
804-
805-
assert.notOk(stub.calledOnce, 'Cells weren\'t selected');
806-
});
807-
808782
test('Multiselection with left arrow should work in workspace day', async function(assert) {
809783
const $element = this.createInstance({
810784
focusStateEnabled: true,

0 commit comments

Comments
 (0)