Skip to content

Commit 8265c10

Browse files
List: fix kbn scroll for grouped list and SelectAll item (T1300059) (DevExpress#30397)
1 parent b24f97a commit 8265c10

File tree

3 files changed

+133
-2
lines changed

3 files changed

+133
-2
lines changed

packages/devextreme/js/__internal/ui/list/m_list.base.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,17 @@ export class ListBase extends CollectionWidget<ListBaseProperties> {
164164
return lastItemInDirection.is($(focusedElement));
165165
}
166166

167+
_getNextItem($item: dxElementWrapper, direction: Direction): dxElementWrapper {
168+
const $items = this._getAvailableItems();
169+
const itemIndex = $items.index($item);
170+
171+
if (direction === 'prev') {
172+
return $($items[itemIndex - 1]);
173+
}
174+
175+
return $($items[itemIndex + 1]);
176+
}
177+
167178
_getEdgeVisibleItem(direction: Direction): dxElementWrapper {
168179
const scrollTop = this.scrollTop();
169180
const containerHeight = getHeight(this.$element());
@@ -178,7 +189,7 @@ export class ListBase extends CollectionWidget<ListBaseProperties> {
178189
}
179190

180191
while (isItemVisible) {
181-
const $nextItem = $item[direction]();
192+
const $nextItem = this._getNextItem($item, direction);
182193

183194
if (!$nextItem.length) {
184195
break;
@@ -365,7 +376,7 @@ export class ListBase extends CollectionWidget<ListBaseProperties> {
365376
return $items;
366377
}
367378

368-
_getAvailableItems($itemElements) {
379+
_getAvailableItems($itemElements?: dxElementWrapper): dxElementWrapper {
369380
const { collapsibleGroups } = this.option();
370381

371382
if (collapsibleGroups) {

packages/devextreme/testing/tests/DevExpress.ui.widgets/list.tests.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ QUnit.testStart(() => {
88
.dx-list-item {
99
height: 40px;
1010
}
11+
.dx-list-group-header{
12+
height: 40px;
13+
}
1114
.dx-icon-remove {
1215
width: 20px;
1316
}

packages/devextreme/testing/tests/DevExpress.ui.widgets/listParts/commonTests.js

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4370,6 +4370,123 @@ QUnit.module('keyboard navigation', {
43704370
});
43714371
});
43724372

4373+
[true, false].forEach(useNativeScrolling => {
4374+
QUnit.test(`grouped list scroll to focused item after press pageDown, useNativeScrolling=${useNativeScrolling} (T1300059)`, function(assert) {
4375+
const $list = $('#list').dxList({
4376+
dataSource: [
4377+
{ key: 1, items: [10, 11] },
4378+
{ key: 2, items: [20, 21] },
4379+
],
4380+
grouped: true,
4381+
useNativeScrolling,
4382+
focusStateEnabled: true,
4383+
});
4384+
4385+
const instance = $list.dxList('instance');
4386+
const $items = $list.find(`.${LIST_ITEM_CLASS}`);
4387+
const keyboard = getListKeyboard($list);
4388+
const itemHeight = $items.first().outerHeight();
4389+
4390+
$list.dxList('focus');
4391+
instance.option('height', itemHeight * 3);
4392+
4393+
keyboard.keyDown('pageDown');
4394+
const secondItemFirstGroupIsFocused = $items.eq(1).hasClass(FOCUSED_STATE_CLASS);
4395+
4396+
assert.roughEqual(instance.scrollTop(), 0, 1.0001, 'list is not scrolled, when focusedItem is not last visible item on this page');
4397+
assert.ok(secondItemFirstGroupIsFocused, 'second item in first group is focused');
4398+
4399+
keyboard.keyDown('pageDown');
4400+
const firstItemSecondGroupIsFocused = $items.eq(2).hasClass(FOCUSED_STATE_CLASS);
4401+
4402+
assert.roughEqual(instance.scrollTop(), itemHeight * 2, 1.0001, 'list scrolled to next page');
4403+
assert.ok(firstItemSecondGroupIsFocused, 'last item on new page obtained focus');
4404+
4405+
keyboard.keyDown('pageDown');
4406+
const lastItemIsFocused = $items.eq(3).hasClass(FOCUSED_STATE_CLASS);
4407+
4408+
assert.roughEqual(instance.scrollTop(), itemHeight * 3, 1.0001, 'list scrolled to last page');
4409+
assert.ok(lastItemIsFocused, 'last item on last page obtained focus');
4410+
});
4411+
});
4412+
4413+
[true, false].forEach(useNativeScrolling => {
4414+
QUnit.test(`grouped list with collapsed group scroll to focused item after press pageDown, useNativeScrolling=${useNativeScrolling} (T1300059)`, function(assert) {
4415+
const $list = $('#list').dxList({
4416+
dataSource: [
4417+
{ key: 1, items: [10, 11] },
4418+
{ key: 2, items: [20, 21] },
4419+
],
4420+
grouped: true,
4421+
collapsibleGroups: true,
4422+
useNativeScrolling,
4423+
focusStateEnabled: true,
4424+
});
4425+
4426+
const instance = $list.dxList('instance');
4427+
const $items = $list.find(`.${LIST_ITEM_CLASS}`);
4428+
const firstGroupHeader = $list.find(`.${LIST_GROUP_HEADER_CLASS}`)[0];
4429+
const keyboard = getListKeyboard($list);
4430+
const itemHeight = $items.first().outerHeight();
4431+
4432+
$list.trigger('focusin');
4433+
instance.option('height', itemHeight * 3);
4434+
instance.option('focusedElement', firstGroupHeader);
4435+
$(firstGroupHeader).trigger('dxclick');
4436+
this.clock.tick(300);
4437+
4438+
keyboard.keyDown('pageDown');
4439+
const firstItemSecondGroupIsFocused = $items.eq(2).hasClass(FOCUSED_STATE_CLASS);
4440+
4441+
assert.roughEqual(instance.scrollTop(), 0, 1.0001, 'list is not scrolled, when focusedItem is not last visible item on this page');
4442+
assert.ok(firstItemSecondGroupIsFocused, 'first item in second group is focused');
4443+
4444+
keyboard.keyDown('pageDown');
4445+
const lastItemIsFocused = $items.eq(3).hasClass(FOCUSED_STATE_CLASS);
4446+
4447+
assert.roughEqual(instance.scrollTop(), itemHeight, 1.0001, 'list scrolled to next page');
4448+
assert.ok(lastItemIsFocused, 'last item on last page obtained focus');
4449+
});
4450+
});
4451+
4452+
[true, false].forEach((useNativeScrolling) => {
4453+
QUnit.test(`list scroll to focused item after press pageDown when SelectAll item focused, useNativeScrolling=${useNativeScrolling} (T1300059)`, function(assert) {
4454+
const $list = $('#list').dxList({
4455+
useNativeScrolling,
4456+
focusStateEnabled: true,
4457+
dataSource: [0, 1, 2, 3, 4],
4458+
showSelectionControls: true,
4459+
selectionMode: 'all',
4460+
});
4461+
4462+
const instance = $list.dxList('instance');
4463+
const $items = $list.find(`.${LIST_ITEM_CLASS}`);
4464+
const keyboard = getListKeyboard($list);
4465+
const itemHeight = $items.first().outerHeight();
4466+
4467+
$list.dxList('focus');
4468+
instance.option('height', itemHeight * 3);
4469+
4470+
keyboard.keyDown('pageDown');
4471+
const secondItemIsFocused = $items.eq(1).hasClass(FOCUSED_STATE_CLASS);
4472+
4473+
assert.roughEqual(instance.scrollTop(), 0, 1.0001, 'list is not scrolled, when focusedItem is not last visible item on this page');
4474+
assert.ok(secondItemIsFocused, 'second item in first group is focused');
4475+
4476+
keyboard.keyDown('pageDown');
4477+
const forthItemIsFocused = $items.eq(3).hasClass(FOCUSED_STATE_CLASS);
4478+
4479+
assert.roughEqual(instance.scrollTop(), itemHeight * 2, 1.0001, 'list scrolled to next page');
4480+
assert.ok(forthItemIsFocused, 'last item on new page obtained focus');
4481+
4482+
keyboard.keyDown('pageDown');
4483+
const lastItemIsFocused = $items.eq(4).hasClass(FOCUSED_STATE_CLASS);
4484+
4485+
assert.roughEqual(instance.scrollTop(), itemHeight * 3, 1.0001, 'list scrolled to last page');
4486+
assert.ok(lastItemIsFocused, 'last item on last page obtained focus');
4487+
});
4488+
});
4489+
43734490
QUnit.test('focus should be moved to selectedItem after focusing of grouped list (T1278005)', function(assert) {
43744491
const list = $('#list').dxList({
43754492
selectedItemKeys: [5],

0 commit comments

Comments
 (0)