Skip to content

Commit

Permalink
Merge pull request #433 from Westbrook/upstream
Browse files Browse the repository at this point in the history
Add mapping for left/right and grid specific arrow key interactions
  • Loading branch information
keanulee authored May 9, 2017
2 parents c1c7301 + 1410838 commit 4eed95c
Show file tree
Hide file tree
Showing 8 changed files with 216 additions and 16 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,8 @@ per row are determined automatically based on the size of the list viewport.

`iron-list` automatically manages the focus state for the items. It also provides
a `tabIndex` property within the template scope that can be used for keyboard navigation.
For example, users can press the up and down keys to move to previous and next
items in the list:
For example, users can press the up and down keys, as well as the left and right
keys (the `grid` attribute is present), to move to focus between items in the list:

```html
<iron-list items="[[data]]" as="item">
Expand Down
28 changes: 20 additions & 8 deletions iron-list.html
Original file line number Diff line number Diff line change
Expand Up @@ -425,8 +425,10 @@
],

keyBindings: {
'up': '_didMoveUp',
'down': '_didMoveDown',
'up': '_didMoveBackward',
'down': '_didMoveForward',
'left': '_didMoveLeft',
'right': '_didMoveRight',
'enter': '_didEnter'
},

Expand Down Expand Up @@ -1871,15 +1873,25 @@
}
}
},

_didMoveUp: function() {
this._focusPhysicalItem(this._focusedIndex - 1);
_didMoveBackward: function() {
// When `grid === true` the `downArrow` goes forward `this._itemsPerRow` items
this._focusPhysicalItem(this._focusedIndex - (this.grid ? this._itemsPerRow : 1));
},

_didMoveDown: function(e) {
_didMoveForward: function(e) {
// disable scroll when pressing the down key
e.detail.keyboardEvent.preventDefault();
this._focusPhysicalItem(this._focusedIndex + 1);
// When `grid === true` the `upArrow` goes backward `this._itemsPerRow` items
this._focusPhysicalItem(this._focusedIndex + (this.grid ? this._itemsPerRow : 1));
},
// When in grid mode, the use of `leftArrow` changes the focus based on the text direction
_didMoveLeft: function(e) {
if (!this.grid) return;
this._focusPhysicalItem(this._focusedIndex + (this._isRTL ? 1 : -1));
},
// When in grid mode, the use of `rightArrow` changes the focus based on the text direction
_didMoveRight: function(e) {
if (!this.grid) return;
this._focusPhysicalItem(this._focusedIndex + (this._isRTL ? -1 : 1));
},

_didEnter: function(e) {
Expand Down
38 changes: 37 additions & 1 deletion test/focus.html
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
});

test('should not hide the list', function(done) {
container.useTabIndex = true;
list.items = buildDataSet(100);

flush(function() {
Expand All @@ -104,13 +105,48 @@
});
});

test('list focus change with down arrow', function(done) {
container.useTabIndex = true;
list.items = buildDataSet(100);

flush(function() {
var initialItem = getFirstItemFromList(list);
var itemToFocus = getNthItemFromList(list, 1);
initialItem.focus();
flush(function() {
MockInteractions.pressAndReleaseKeyOn(list, 40); // down
flush(function() {
assert.notEqual(itemToFocus.tabIndex, -1);
done();
});
});
});
});

test('list focus change with up arrow', function(done) {
list.items = buildDataSet(100);

flush(function() {
var initialItem = getNthItemFromList(list, 1);
var itemToFocus = getFirstItemFromList(list);
initialItem.focus();
flush(function() {
MockInteractions.pressAndReleaseKeyOn(list, 38); // up
flush(function() {
assert.notEqual(itemToFocus.tabIndex, -1);
done();
});
});
});
});

test('Issue #411', function(done) {
list.items = buildDataSet(100);

Polymer.dom.flush();

list.scroll(0, getFirstItemFromList(list).offsetHeight * list._physicalCount);

requestAnimationFrame(function() {
setTimeout(function() {
var lastOffscreenFocusedItem = list._offscreenFocusedItem;
Expand Down
37 changes: 37 additions & 0 deletions test/grid-rtl.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">

<script src="../../webcomponentsjs/webcomponents-lite.js"></script>
<script src="../../iron-test-helpers/mock-interactions.js"></script>
<script src="../../web-component-tester/browser.js"></script>

<link rel="import" href="helpers.html">
Expand Down Expand Up @@ -60,6 +61,42 @@
});
});

test('rtl grid focus change with right arrow', function(done) {
container.useTabIndex = true;
container.data = buildDataSet(100);

flush(function() {
var initialItem = getNthItemFromRTLGrid(list, 0);
var itemToFocus = getNthItemFromRTLGrid(list, 1);
initialItem.focus();
flush(function() {
MockInteractions.pressAndReleaseKeyOn(list, 37); // left
flush(function() {
assert.notEqual(itemToFocus.tabIndex, -1);
done();
});
});
});
});

test('rtl grid focus change with left arrow', function(done) {
container.useTabIndex = true;
container.data = buildDataSet(100);

flush(function() {
var initialItem = getNthItemFromRTLGrid(list, 1);
var itemToFocus = getNthItemFromRTLGrid(list, 0);
initialItem.focus();
flush(function() {
MockInteractions.pressAndReleaseKeyOn(list, 39); // right
flush(function() {
assert.notEqual(itemToFocus.tabIndex, -1);
done();
});
});
});
});

});
</script>

Expand Down
90 changes: 90 additions & 0 deletions test/grid.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">

<script src="../../webcomponentsjs/webcomponents-lite.js"></script>
<script src="../../iron-test-helpers/mock-interactions.js"></script>
<script src="../../web-component-tester/browser.js"></script>

<link rel="import" href="helpers.html">
Expand Down Expand Up @@ -52,6 +53,95 @@
});
});

test('grid focus change with right arrow', function(done) {
container.useTabIndex = true;
container.data = buildDataSet(100);

flush(function() {
var initialItem = getNthItemFromGrid(list, 0);
var itemToFocus = getNthItemFromGrid(list, 1);
initialItem.focus();
flush(function() {
MockInteractions.pressAndReleaseKeyOn(list, 39); // right
flush(function() {
assert.notEqual(itemToFocus.tabIndex, -1);
done();
});
});
});
});

test('grid focus change with left arrow', function(done) {
container.useTabIndex = true;
container.data = buildDataSet(100);

flush(function() {
var initialItem = getNthItemFromGrid(list, 1);
var itemToFocus = getNthItemFromGrid(list, 0);
initialItem.focus();
flush(function() {
MockInteractions.pressAndReleaseKeyOn(list, 37); // left
flush(function() {
assert.notEqual(itemToFocus.tabIndex, -1);
done();
});
});
});
});

test('grid focus change with down arrow', function(done) {
container.useTabIndex = true;
container.data = buildDataSet(100);

flush(function() {
var initialItem = getNthItemFromGrid(list, 0);
var itemToFocus = getNthItemFromGrid(list, list._itemsPerRow);
initialItem.focus();
flush(function() {
MockInteractions.pressAndReleaseKeyOn(list, 40); // down
flush(function() {
assert.notEqual(itemToFocus.tabIndex, -1);
done();
});
});
});
});

test('grid focus does not change with down arrow from last row', function(done) {
container.useTabIndex = true;
container.data = buildDataSet(5);

flush(function() {
var initialItem = getNthItemFromGrid(list, 3);
initialItem.focus();
flush(function() {
MockInteractions.pressAndReleaseKeyOn(list, 40); // down
flush(function() {
assert.notEqual(initialItem.tabIndex, -1);
done();
});
});
});
});

test('grid focus change with up arrow', function(done) {
container.useTabIndex = true;
container.data = buildDataSet(100);

flush(function() {
var initialItem = getNthItemFromGrid(list, list._itemsPerRow);
var itemToFocus = getNthItemFromGrid(list, 0);
initialItem.focus();
flush(function() {
MockInteractions.pressAndReleaseKeyOn(list, 38); // up
flush(function() {
assert.notEqual(itemToFocus.tabIndex, -1);
done();
});
});
});
});

test('first visible index', function(done) {
container.data = buildDataSet(100);

Expand Down
16 changes: 16 additions & 0 deletions test/helpers.html
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,27 @@
return document.elementFromPoint(x, y);
}

function getNthItemFromRTLGrid(grid, n, itemSize) {
itemSize = itemSize || 100;
var gridRect = grid.getBoundingClientRect();
var x = gridRect.left + gridRect.width - ((n % grid._itemsPerRow) * itemSize) - (itemSize / 2);
var y = gridRect.top + (Math.floor(n / grid._itemsPerRow) * itemSize) + (itemSize / 2);
return document.elementFromPoint(x, y);
}

function getFirstItemFromList(list) {
var listRect = list.getBoundingClientRect();
return document.elementFromPoint(listRect.left + 100, listRect.top + 1);
}

function getNthItemFromList(list, n, itemHeight) {
itemHeight = itemHeight || 100;
var listRect = list.getBoundingClientRect();
var x = listRect.left + (listRect.width / 2);
var y = listRect.top + (n * itemHeight) + (itemHeight / 2);
return document.elementFromPoint(x, y);
}

function getLastItemFromList(list) {
var listRect = list.getBoundingClientRect();
return document.elementFromPoint(listRect.left + 100, listRect.top + listRect.height - 1);
Expand Down
13 changes: 11 additions & 2 deletions test/x-grid.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@
overflow: hidden;
}
</style>

<iron-list style$="[[_computedListSize(listSize)]]" items="[[data]]" as="item" id="list" grid>
<template>
<div class="item">
<div style$="[[_computeItemSize(item)]]">[[item.index]]</div>
<div style$="[[_computeItemSize(item)]]" tabindex$="[[_computedTabIndex(tabIndex, useTabIndex)]]">[[item.index]]</div>
</div>
</template>
</iron-list>
Expand Down Expand Up @@ -60,6 +60,11 @@
pre: {
type: Boolean
},

useTabIndex: {
value: true,
type: Boolean
}
},

get list() {
Expand All @@ -75,6 +80,10 @@

_computedListSize: function(listHeight) {
return 'height: ' + (listHeight) + 'px;' + 'width: ' + (listHeight) + 'px;';
},

_computedTabIndex: function(tabIndex, useTabIndex) {
return useTabIndex ? tabIndex : undefined;
}
});
</script>
6 changes: 3 additions & 3 deletions test/x-list.html
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@

<iron-list style$="[[_computedListHeight(listHeight)]]" items="[[data]]" as="item" id="list">
<template>
<div class="item" tabindex$="[[_computedTabIndex(tabIndex, useTabIndex)]]">
<div style$="[[_computedItemHeight(item)]]" tabindex="0" hidden$="[[primitive]]">[[item.index]]</div>
<div style$="[[_computedItemHeight(item)]]" tabindex="0" hidden$="[[!primitive]]">[[item]]</div>
<div class="item">
<div style$="[[_computedItemHeight(item)]]" tabindex$="[[_computedTabIndex(tabIndex, useTabIndex)]]" hidden$="[[primitive]]">[[item.index]]</div>
<div style$="[[_computedItemHeight(item)]]" tabindex$="[[_computedTabIndex(tabIndex, useTabIndex)]]" hidden$="[[!primitive]]">[[item]]</div>
</div>
</template>
</iron-list>
Expand Down

0 comments on commit 4eed95c

Please sign in to comment.