Skip to content

Commit bb7ccbc

Browse files
List: fix kbn scroll for grouped list and SelectAll item (T1300059) (#30398)
1 parent 81ba962 commit bb7ccbc

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
@@ -162,6 +162,17 @@ export class ListBase extends CollectionWidget<ListBaseProperties> {
162162
return lastItemInDirection.is($(focusedElement));
163163
}
164164

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

178189
while (isItemVisible) {
179-
const $nextItem = $item[direction]();
190+
const $nextItem = this._getNextItem($item, direction);
180191

181192
if (!$nextItem.length) {
182193
break;
@@ -363,7 +374,7 @@ export class ListBase extends CollectionWidget<ListBaseProperties> {
363374
return $items;
364375
}
365376

366-
_getAvailableItems($itemElements) {
377+
_getAvailableItems($itemElements?: dxElementWrapper): dxElementWrapper {
367378
const { collapsibleGroups } = this.option();
368379

369380
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
@@ -4377,6 +4377,123 @@ QUnit.module('keyboard navigation', {
43774377
});
43784378
});
43794379

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

0 commit comments

Comments
 (0)