Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ROU-4649: Fix issue on arrow navigation when a TabHeader is disabled #867

Merged
merged 6 commits into from
Dec 6, 2023
62 changes: 45 additions & 17 deletions src/scripts/OSFramework/OSUI/Pattern/Tabs/Tabs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ namespace OSFramework.OSUI.Patterns.Tabs {
private _tabsContentElement: HTMLElement;
// Store the headerItems wrapper -- osui-tabs__header
private _tabsHeaderElement: HTMLElement;
// Store the tabs header enabled elements
private _tabsHeadersEnabled: Array<Patterns.TabsHeaderItem.ITabsHeaderItem>;
// Store the tabs-indicator element -- osui-tabs_indicator
private _tabsIndicatorElement: HTMLElement;

Expand Down Expand Up @@ -248,44 +250,50 @@ namespace OSFramework.OSUI.Patterns.Tabs {
* @memberof Tabs
*/
private _handleKeypressEvent(e: KeyboardEvent): void {
let currentTabHeader;
let targetHeaderItemIndex;

// Check if target is the header, to do not change tab on x arrow press
if (e.target !== this._activeTabHeaderElement.selfElement) {
return;
}

switch (e.key) {
case GlobalEnum.Keycodes.ArrowRight:
// If is right arrow, navigate to current active tabs + 1 (next item)
targetHeaderItemIndex = this.configs.StartingTab + 1;
// Get the index of active tab header for target index calculation
currentTabHeader = this._tabsHeadersEnabled.indexOf(this._activeTabHeaderElement);

// If in last item, change to the first
if (targetHeaderItemIndex >= this.getChildItems(Enum.ChildTypes.TabsHeaderItem).length) {
targetHeaderItemIndex = 0;
}
// Set the target index element based on enabled tabs header elements
targetHeaderItemIndex =
this._tabsHeadersEnabled[currentTabHeader + 1] === undefined
? this._tabsHeadersEnabled[0].getDataTab()
: this._tabsHeadersEnabled[currentTabHeader + 1].getDataTab();

this.changeTab(targetHeaderItemIndex, undefined, true);

break;
case GlobalEnum.Keycodes.ArrowLeft:
// If is left arrow, navigate to current active tabs - 1 (previous item)
targetHeaderItemIndex = this.configs.StartingTab - 1;
// Get the index of active tab header for target index
currentTabHeader = this._tabsHeadersEnabled.indexOf(this._activeTabHeaderElement);

// To prevent triggering changeTab, if already on first item
if (targetHeaderItemIndex < 0) {
// If in first item, change to the last
targetHeaderItemIndex = this.getChildItems(Enum.ChildTypes.TabsHeaderItem).length - 1;
}
// Set the target index element based on enabled tabs header elements
targetHeaderItemIndex =
this._tabsHeadersEnabled[currentTabHeader - 1] === undefined
? this._tabsHeadersEnabled[this._tabsHeadersEnabled.length - 1].getDataTab()
: this._tabsHeadersEnabled[currentTabHeader - 1].getDataTab();

this.changeTab(targetHeaderItemIndex, undefined, true);
break;
case GlobalEnum.Keycodes.End:
targetHeaderItemIndex = this.getChildItems(Enum.ChildTypes.TabsHeaderItem).length - 1;
// Set the last enabled tabs header
targetHeaderItemIndex = this._tabsHeadersEnabled[this._tabsHeadersEnabled.length - 1].getDataTab();

this.changeTab(targetHeaderItemIndex, undefined, true);

break;
case GlobalEnum.Keycodes.Home:
targetHeaderItemIndex = 0;
// Set the first enabled tabs header
targetHeaderItemIndex = this._tabsHeadersEnabled[0].getDataTab();

this.changeTab(targetHeaderItemIndex, undefined, true);

Expand Down Expand Up @@ -336,8 +344,8 @@ namespace OSFramework.OSUI.Patterns.Tabs {
const _transformValue = _isVertical
? _activeElement.offsetTop
: OutSystems.OSUI.Utils.GetIsRTL()
? -(this._tabsHeaderElement.offsetWidth - _activeElement.offsetLeft - _activeElement.offsetWidth)
: _activeElement.offsetLeft;
? -(this._tabsHeaderElement.offsetWidth - _activeElement.offsetLeft - _activeElement.offsetWidth)
: _activeElement.offsetLeft;

// Get the actual size of the current tabsHeader
const _elementRect = _activeElement.getBoundingClientRect();
Expand Down Expand Up @@ -421,6 +429,9 @@ namespace OSFramework.OSUI.Patterns.Tabs {
// Here setting as false the param, as we don't want to set the data-tab here.
// That will be done by each pattern, as they are created
this._updateItemsConnection(false);

// Set the list of enabled TabsHeaders
this._updateListOfEnabledTabsHeader();
}

/**
Expand Down Expand Up @@ -870,6 +881,18 @@ namespace OSFramework.OSUI.Patterns.Tabs {
);
}

/**
* Function that will update the list of enabled tabs headers
*
* @private
* @memberof Tabs
*/
private _updateListOfEnabledTabsHeader(): void {
this._tabsHeadersEnabled = (
this.getChildItems(Enum.ChildTypes.TabsHeaderItem) as Patterns.TabsHeaderItem.ITabsHeaderItem[]
).filter((element) => !(element.selfElement as HTMLButtonElement).disabled);
}

/**
* Method that adds the necessary attributes and listeners to the Tabs header
*
Expand Down Expand Up @@ -955,21 +978,26 @@ namespace OSFramework.OSUI.Patterns.Tabs {
break;
case Enum.ChildNotifyActionType.AddHeaderItem:
this._addHeaderItem(childItem as Patterns.TabsHeaderItem.TabsHeaderItem);
this._updateListOfEnabledTabsHeader();
break;
case Enum.ChildNotifyActionType.Click:
this._tabHeaderItemHasBeenClicked(childItem.uniqueId);
break;
case Enum.ChildNotifyActionType.DisabledHeaderItem:
this._setTabHeaderItemDisabledStatus(childItem.uniqueId, true);
this._updateListOfEnabledTabsHeader();

break;
case Enum.ChildNotifyActionType.EnabledHeaderItem:
this._setTabHeaderItemDisabledStatus(childItem.uniqueId, false);
this._updateListOfEnabledTabsHeader();
break;
case Enum.ChildNotifyActionType.RemovedContentItem:
this._removeContentItem(childItem.uniqueId);
break;
case Enum.ChildNotifyActionType.RemovedHeaderItem:
this._removeHeaderItem(childItem.uniqueId);
this._updateListOfEnabledTabsHeader();
break;
case Enum.ChildNotifyActionType.UpdateIndicator:
this._handleTabIndicator();
Expand Down
Loading