Skip to content

Commit

Permalink
feat(framework): ItemNavigation cyclic behavior implemented for multi…
Browse files Browse the repository at this point in the history
…ple rows (SAP#2780)
  • Loading branch information
vladitasev authored and NHristov-sap committed Feb 9, 2021
1 parent bccfa3a commit bba680b
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 87 deletions.
154 changes: 67 additions & 87 deletions packages/base/src/delegate/ItemNavigation.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { renderFinished } from "../Render.js";
import {
isDown,
isUp,
Expand Down Expand Up @@ -92,97 +91,101 @@ class ItemNavigation extends EventProvider {
});
}

_horizontalNavigationOn() {
return this.horizontalNavigationOn;
}

_verticalNavigationOn() {
return this.verticalNavigationOn;
}
onkeydown(event) {
if (!this._canNavigate()) {
return;
}

async _onKeyPress(event) {
if (this.currentIndex >= this._getItems().length) {
this.onOverflowBottomEdge();
} else if (this.currentIndex < 0) {
this.onOverflowTopEdge();
if (isUp(event) && this.verticalNavigationOn) {
this._handleUp();
} else if (isDown(event) && this.verticalNavigationOn) {
this._handleDown();
} else if (isLeft(event) && this.horizontalNavigationOn) {
this._handleLeft();
} else if (isRight(event) && this.horizontalNavigationOn) {
this._handleRight();
} else if (isHome(event)) {
this._handleHome();
} else if (isEnd(event)) {
this._handleEnd();
} else {
return; // if none of the supported keys is pressed, we don't want to prevent the event or update the item navigation
}

event.preventDefault();

await renderFinished();

this.update();
this.focusCurrent();
}

onkeydown(event) {
if (isUp(event) && this._verticalNavigationOn()) {
return this._handleUp(event);
}

if (isDown(event) && this._verticalNavigationOn()) {
return this._handleDown(event);
}

if (isLeft(event) && this._horizontalNavigationOn()) {
return this._handleLeft(event);
_handleUp() {
const itemsLength = this._getItems().length;
if (this.currentIndex - this.rowSize >= 0) { // no border reached, just decrease the index by a row
this.currentIndex -= this.rowSize;
return;
}

if (isRight(event) && this._horizontalNavigationOn()) {
return this._handleRight(event);
if (this.behavior === ItemNavigationBehavior.Cyclic) { // if cyclic, go to the **last** item in the **previous** column
const firstItemInThisColumnIndex = this.currentIndex % this.rowSize;
const firstItemInPreviousColumnIndex = firstItemInThisColumnIndex === 0 ? this.rowSize - 1 : firstItemInThisColumnIndex - 1; // find the first item in the previous column (if the current column is the first column -> move to the last column)
const rows = Math.ceil(itemsLength / this.rowSize); // how many rows there are (even if incomplete, f.e. for 14 items and rowSize=4 -> 4 rows total, although only 2 items on the last row)
let lastItemInPreviousColumnIndex = firstItemInPreviousColumnIndex + (rows - 1) * this.rowSize; // multiply rows by columns, and add the column's first item's index
if (lastItemInPreviousColumnIndex > itemsLength - 1) { // for incomplete rows, use the previous row's last item, as for them the last item is missing
lastItemInPreviousColumnIndex -= this.rowSize;
}
this.currentIndex = lastItemInPreviousColumnIndex;
} else { // not cyclic, so just go to the first item
this.currentIndex = 0;
}
}

if (isHome(event)) {
return this._handleHome(event);
_handleDown() {
const itemsLength = this._getItems().length;
if (this.currentIndex + this.rowSize < itemsLength) { // no border reached, just increase the index by a row
this.currentIndex += this.rowSize;
return;
}

if (isEnd(event)) {
return this._handleEnd(event);
if (this.behavior === ItemNavigationBehavior.Cyclic) { // if cyclic, go to the **first** item in the **next** column
const firstItemInThisColumnIndex = this.currentIndex % this.rowSize; // find the first item in the current column first
const firstItemInNextColumnIndex = (firstItemInThisColumnIndex + 1) % this.rowSize; // to get the first item in the next column, just increase the index by 1. The modulo by rows is for the case when we are at the last column
this.currentIndex = firstItemInNextColumnIndex;
} else { // not cyclic, so just go to the last item
this.currentIndex = itemsLength - 1;
}
}

_handleUp(event) {
if (this._canNavigate()) {
this.currentIndex -= this.rowSize;
this._onKeyPress(event);
_handleLeft() {
const itemsLength = this._getItems().length;
if (this.currentIndex > 0) {
this.currentIndex -= 1;
return;
}
}

_handleDown(event) {
if (this._canNavigate()) {
this.currentIndex += this.rowSize;
this._onKeyPress(event);
if (this.behavior === ItemNavigationBehavior.Cyclic) { // go to the first item in the next column
this.currentIndex = itemsLength - 1;
}
}

_handleLeft(event) {
if (this._canNavigate()) {
this.currentIndex -= 1;
this._onKeyPress(event);
_handleRight() {
const itemsLength = this._getItems().length;
if (this.currentIndex < itemsLength - 1) {
this.currentIndex += 1;
return;
}
}

_handleRight(event) {
if (this._canNavigate()) {
this.currentIndex += 1;
this._onKeyPress(event);
if (this.behavior === ItemNavigationBehavior.Cyclic) { // go to the first item in the next column
this.currentIndex = 0;
}
}

_handleHome(event) {
if (this._canNavigate()) {
const homeEndRange = this.rowSize > 1 ? this.rowSize : this._getItems().length;
this.currentIndex -= this.currentIndex % homeEndRange;
this._onKeyPress(event);
}
_handleHome() {
const homeEndRange = this.rowSize > 1 ? this.rowSize : this._getItems().length;
this.currentIndex -= this.currentIndex % homeEndRange;
}

_handleEnd(event) {
if (this._canNavigate()) {
const homeEndRange = this.rowSize > 1 ? this.rowSize : this._getItems().length;
this.currentIndex += (homeEndRange - 1 - this.currentIndex % homeEndRange); // eslint-disable-line
this._onKeyPress(event);
}
_handleEnd() {
const homeEndRange = this.rowSize > 1 ? this.rowSize : this._getItems().length;
this.currentIndex += (homeEndRange - 1 - this.currentIndex % homeEndRange); // eslint-disable-line
}

/**
Expand Down Expand Up @@ -219,8 +222,7 @@ class ItemNavigation extends EventProvider {
}

/**
* @public
* @deprecated
* @private
*/
focusCurrent() {
const currentItem = this._getCurrentItem();
Expand Down Expand Up @@ -286,28 +288,6 @@ class ItemNavigation extends EventProvider {
set current(val) {
this.currentIndex = val;
}

onOverflowBottomEdge(event) {
const items = this._getItems();

if (this.behavior === ItemNavigationBehavior.Cyclic) {
this.currentIndex = 0;
return;
}

this.currentIndex = items.length - 1;
}

onOverflowTopEdge(event) {
const items = this._getItems();

if (this.behavior === ItemNavigationBehavior.Cyclic) {
this.currentIndex = items.length - 1;
return;
}

this.currentIndex = 0;
}
}

export default ItemNavigation;
2 changes: 2 additions & 0 deletions packages/fiori/src/ProductSwitch.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js";
import ItemNavigation from "@ui5/webcomponents-base/dist/delegate/ItemNavigation.js";
import ItemNavigationBehavior from "@ui5/webcomponents-base/dist/types/ItemNavigationBehavior.js";
import ResizeHandler from "@ui5/webcomponents-base/dist/delegate/ResizeHandler.js";
import Integer from "@ui5/webcomponents-base/dist/types/Integer.js";
import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js";
Expand Down Expand Up @@ -64,6 +65,7 @@ class ProductSwitch extends UI5Element {

this._itemNavigation = new ItemNavigation(this, {
rowSize: 4,
behavior: ItemNavigationBehavior.Cyclic,
getItemsCallback: () => this.items,
});
}
Expand Down
2 changes: 2 additions & 0 deletions packages/main/bundle.esm.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ import { getAssetsPath, setAssetsPath } from "@ui5/webcomponents-base/dist/confi
// setAssetsPath("/my-resources/");

import { addCustomCSS, attachThemeLoaded, detachThemeLoaded } from "@ui5/webcomponents-base/dist/Theming";
/*
attachThemeLoaded(theme => {
console.log("Theme load complete: ", theme);
});
*/

// OpenUI5 integration
import "@ui5/webcomponents-base/dist/features/OpenUI5Support.js";
Expand Down

0 comments on commit bba680b

Please sign in to comment.