Skip to content

Commit

Permalink
Fixed #10781 - SlideMenu | Keyboard Support
Browse files Browse the repository at this point in the history
  • Loading branch information
yigitfindikli committed Oct 27, 2021
1 parent 5365533 commit 8f43723
Showing 1 changed file with 73 additions and 10 deletions.
83 changes: 73 additions & 10 deletions src/app/components/slidemenu/slidemenu.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {NgModule,Component,ElementRef,AfterViewChecked,OnDestroy,Input,Renderer2,Inject,forwardRef,ViewChild,Output,EventEmitter,ChangeDetectorRef,ChangeDetectionStrategy, ViewEncapsulation} from '@angular/core';
import {trigger,state,style,transition,animate,AnimationEvent} from '@angular/animations';
import {trigger,style,transition,animate,AnimationEvent} from '@angular/animations';
import {CommonModule} from '@angular/common';
import {DomHandler, ConnectedOverlayScrollHandler} from 'primeng/dom';
import {MenuItem, OverlayService, PrimeNGConfig} from 'primeng/api';
Expand All @@ -10,23 +10,23 @@ import {TooltipModule} from 'primeng/tooltip';
@Component({
selector: 'p-slideMenuSub',
template: `
<ul [ngClass]="{'p-slidemenu-rootlist':root, 'p-submenu-list':!root, 'p-active-submenu': (-slideMenu.left == (index * menuWidth))}"
<ul #sublist [ngClass]="{'p-slidemenu-rootlist':root, 'p-submenu-list':!root, 'p-active-submenu': isActive}"
[style.width.px]="menuWidth" [style.left.px]="root ? slideMenu.left : slideMenu.menuWidth"
[style.transitionProperty]="root ? 'left' : 'none'" [style.transitionDuration]="effectDuration + 'ms'" [style.transitionTimingFunction]="easing">
<ng-template ngFor let-child [ngForOf]="(root ? item : item.items)">
<li *ngIf="child.separator" class="p-menu-separator" [ngClass]="{'p-hidden': child.visible === false}">
<li *ngIf="!child.separator" #listitem [ngClass]="{'p-menuitem':true,'p-menuitem-active':listitem==activeItem,'p-hidden': child.visible === false}" pTooltip [tooltipOptions]="child.tooltipOptions"
[class]="child.styleClass" [ngStyle]="child.style">
<a *ngIf="!child.routerLink" [attr.href]="child.url" class="p-menuitem-link" [attr.target]="child.target" [attr.title]="child.title" [attr.id]="child.id"
[ngClass]="{'p-disabled':child.disabled}" [attr.tabindex]="child.disabled ? null : '0'"
<a *ngIf="!child.routerLink" (keydown)="onItemKeyDown($event)" [attr.href]="child.url" class="p-menuitem-link" [attr.target]="child.target" [attr.title]="child.title" [attr.id]="child.id"
[ngClass]="{'p-disabled':child.disabled}" [attr.tabindex]="child.disabled || !isActive ? null : '0'"
(click)="itemClick($event, child, listitem)">
<span class="p-menuitem-icon" *ngIf="child.icon" [ngClass]="child.icon"></span>
<span class="p-menuitem-text">{{child.label}}</span>
<span class="p-submenu-icon pi pi-fw pi-angle-right" *ngIf="child.items"></span>
</a>
<a *ngIf="child.routerLink" [routerLink]="child.routerLink" [queryParams]="child.queryParams" [routerLinkActive]="'p-menuitem-link-active'"
<a *ngIf="child.routerLink" (keydown)="onItemKeyDown($event)" [routerLink]="child.routerLink" [queryParams]="child.queryParams" [routerLinkActive]="'p-menuitem-link-active'"
[routerLinkActiveOptions]="child.routerLinkActiveOptions||{exact:false}" [href]="child.url" class="p-menuitem-link"
[attr.target]="child.target" [attr.title]="child.title" [attr.id]="child.id" [attr.tabindex]="child.disabled ? null : '0'"
[attr.target]="child.target" [attr.title]="child.title" [attr.id]="child.id" [attr.tabindex]="child.disabled || !isActive ? null : '0'"
[ngClass]="{'p-disabled':child.disabled}"
(click)="itemClick($event, child, listitem)"
[fragment]="child.fragment" [queryParamsHandling]="child.queryParamsHandling" [preserveFragment]="child.preserveFragment" [skipLocationChange]="child.skipLocationChange" [replaceUrl]="child.replaceUrl" [state]="child.state">
Expand Down Expand Up @@ -60,12 +60,15 @@ export class SlideMenuSub implements OnDestroy {

@Input() index: number;

@ViewChild('sublist') sublistViewChild: ElementRef;

slideMenu: SlideMenu;

transitionEndListener: any;

constructor(@Inject(forwardRef(() => SlideMenu)) slideMenu) {
this.slideMenu = slideMenu as SlideMenu;
}

activeItem: any;

itemClick(event, item: MenuItem, listitem: any) {
Expand Down Expand Up @@ -98,8 +101,52 @@ export class SlideMenuSub implements OnDestroy {
}
}

focusNextList(listitem) {
if (!this.slideMenu.animating) {
let focusableElements = DomHandler.getFocusableElements(listitem);

if (focusableElements && focusableElements.length > 0) {
focusableElements[0].focus();
}

this.unbindTransitionEndListener();
}
}

onItemKeyDown(event) {
let listItem = event.currentTarget.parentElement;

switch (event.code) {
case 'Space':
case 'Enter':
if (listItem && !DomHandler.hasClass(listItem, 'p-disabled')) {
listItem.children[0].click();
this.transitionEndListener = this.focusNextList.bind(this,listItem);
this.sublistViewChild.nativeElement.addEventListener('transitionend', this.transitionEndListener);
}

event.preventDefault();
break;

default:
break;
}
}

unbindTransitionEndListener() {
if (this.transitionEndListener && this.sublistViewChild) {
this.sublistViewChild.nativeElement.removeEventListener('transitionend', this.transitionEndListener);
this.transitionEndListener = null;
}
}

ngOnDestroy() {
this.activeItem = null;
this.unbindTransitionEndListener();
}

get isActive() {
return -this.slideMenu.left == (this.index * this.menuWidth)
}
}

Expand All @@ -110,13 +157,13 @@ export class SlideMenuSub implements OnDestroy {
[class]="styleClass" [ngStyle]="style" (click)="onOverlayClick($event)"
[@overlayAnimation]="{value: 'visible', params: {showTransitionParams: showTransitionOptions, hideTransitionParams: hideTransitionOptions}}" [@.disabled]="popup !== true"
(@overlayAnimation.start)="onOverlayAnimationStart($event)" (@overlayAnimation.done)="onOverlayAnimationEnd($event)" *ngIf="!popup || visible">
<div class="p-slidemenu-wrapper" [style.height]="left ? viewportHeight + 'px' : 'auto'">
<div class="p-slidemenu-wrapper" [style.height]="left ? viewportHeight + 'px' : 'auto'" [style.width]="menuWidth + 'px'">
<div #slideMenuContent class="p-slidemenu-content">
<p-slideMenuSub [item]="model" root="root" [index]="0" [menuWidth]="menuWidth" [effectDuration]="effectDuration" [easing]="easing"></p-slideMenuSub>
</div>
<div #backward class="p-slidemenu-backward" [style.display]="left ? 'block' : 'none'" (click)="goBack()">
<a #backward (keydown.enter)="onBackwardKeydown($event)" (keydown.space)="onBackwardKeydown($event)" class="p-slidemenu-backward p-menuitem-link" tabindex="0" [style.display]="left ? 'block' : 'none'" (click)="goBack()">
<span class="p-slidemenu-backward-icon pi pi-fw pi-caret-left"></span><span>{{backLabel}}</span>
</div>
</a>
</div>
</div>
`,
Expand Down Expand Up @@ -312,6 +359,22 @@ export class SlideMenu implements AfterViewChecked, OnDestroy {
this.left += this.menuWidth;
}

onBackwardKeydown(event) {
this.goBack();

if (!this.left) {
setTimeout(() => {
let focusableElements = DomHandler.getFocusableElements(this.el.nativeElement);

if (focusableElements && focusableElements.length > 0) {
focusableElements[0].focus();
}
}, 1);
}

event.preventDefault();
}

bindDocumentClickListener() {
if (!this.documentClickListener) {
const documentTarget: any = this.el ? this.el.nativeElement.ownerDocument : 'document';
Expand Down

0 comments on commit 8f43723

Please sign in to comment.