Skip to content

Commit

Permalink
API Definition: Accessibility
Browse files Browse the repository at this point in the history
Bug fix: Shift + tab opens the target URL for pop-over component
Press Tab to move through components
Press Enter or Space to perform underlying action
  • Loading branch information
soninaren authored and alrod committed Aug 18, 2017
1 parent 71ad8b8 commit 405cd0d
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 22 deletions.
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
<span [class]="popOverClass" [ngClass]="{'pop-over-input-error': isInputError, 'pop-over-input-warning': isInputWarning}">
<span [class]="popOverClass" [ngClass]="{'pop-over-input-error': isInputError, 'pop-over-input-warning': isInputWarning}"
tabindex="-1">
<span *ngIf="message"
class="pop-over-common"
class="pop-over-common"
[class.pop-over]="position!=='bottom'"
[class.pop-over-bottom]="position==='bottom'"
[class.pop-over-visible]="show"
[innerHtml]="message"></span>
[innerHtml]="message" tabindex="-1"></span>

<button id="buttonInfoButton" class="pop-over-button" (focus)="onFocus($event)" (blur)="onBlur($event)" attr.aria-label="{{message}}">
<button id="buttonInfoButton" class="pop-over-button" attr.aria-label="{{message}}" (keydown)="onKeyPress($event)" (blur)="onBlur($event)"
(click)="popUpContent($event)" tabindex="0">
<ng-content></ng-content>
<span *ngIf="isInputError" class="fa fa-exclamation input-error"></span>
<span *ngIf="isInputWarning && !isInputError" class="fa fa-exclamation input-warning"></span>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Component, Input } from '@angular/core';
import { KeyCodes } from '../shared/models/constants';

@Component({
selector: 'pop-over',
Expand All @@ -13,6 +14,7 @@ export class PopOverComponent {
@Input() isInputWarning: boolean;
@Input() popOverClass = 'pop-over-container';
@Input() position: string;
@Input() isShiftTabPressed: boolean;

public show: boolean;

Expand All @@ -25,24 +27,35 @@ export class PopOverComponent {
if (!this.hideAfter) {
this.show = false;
}
if (event.relatedTarget && this.validURL(event.relatedTarget)) {

// Pressing Shift + Tab causes the links to open
if (!this.isShiftTabPressed && event.relatedTarget && this.validURL(event.relatedTarget)) {
window.open(
event.relatedTarget.toString(),
'_blank' // <- This is what makes it open in a new window.
);
}
this.isShiftTabPressed = false;
}

onFocus(_: Event) {
popUpContent() {
this.show = true;

if (this.hideAfter) {
setTimeout(() => {
this.show = false;
}, this.hideAfter);
}
}

onKeyPress(event: KeyboardEvent) {
if (event.keyCode === KeyCodes.tab && event.shiftKey === true) {
this.isShiftTabPressed = true;
}
if (event.keyCode === KeyCodes.enter) {
this.popUpContent();
}
}

// http://stackoverflow.com/questions/5717093/check-if-a-javascript-string-is-an-url
private validURL(str): boolean {
const pattern = new RegExp('^(https?:\\/\\/)?' + // protocol
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div class="wrapper">
<div class="wrapper">
<div>
<div class="section-left full-height" [class.collapse]="isFullscreen">
<div>
Expand All @@ -9,48 +9,49 @@
<div [class.collapse]="!swaggerEnabled">
<label class="setting-title">{{'swaggerDefinition_useAPIdefinition' | translate}}</label>
<pop-over [position]="'bottom'" [message]="'swaggerDefinition_exporthelp' | translate">
<span class="glyphicon glyphicon-info-sign button-title"></span>
<span class="glyphicon glyphicon-info-sign button-title" tabindex="-1"></span>
</pop-over>
<div class="setting-wrapper">
<!--<button class="custom-button medium">Download Function Keys</button>-->
<button class="custom-button medium" style="margin-left:0px;" (click)='openBlade("ExportToPowerApps")'>{{'swaggerDefinition_powerAppsFlow' | translate}}</button>
<button class="custom-button medium" style="margin-left:0px;" (click)='openBlade("ExportToPowerApps")' tabindex="0">{{'swaggerDefinition_powerAppsFlow' | translate}}</button>
</div>
</div>
<div [class.collapse]="!swaggerEnabled">
<label class="setting-title">{{'swaggerDefinition_url' | translate}}</label>
<pop-over [position]="'bottom'" [message]="'swaggerDefinition_urlHelp' | translate">
<span class="glyphicon glyphicon-info-sign button-title"></span>
<span class="glyphicon glyphicon-info-sign button-title" tabindex="-1"></span>
</pop-over>
<div class="setting-wrapper">
<copy-pre [content]="swaggerURL"></copy-pre>
<copy-pre [content]="swaggerURL" tabindex="-1"></copy-pre>
</div>

</div>
<div [class.collapse]="!swaggerEnabled">
<div style="padding-left: 6px;">
<i class="fa clickable link" [class.fa-plus]="!keyVisible" [class.fa-minus]="keyVisible" (click)="toggleKeyVisibility()"></i>
<i class="fa clickable link" [class.fa-plus]="!keyVisible" [class.fa-minus]="keyVisible" (click)="toggleKeyVisibility()"
tabindex="0" (keydown)="apiDefinitionKeyDown($event)"></i>
<label class="setting-title-collapsible link" (click)="toggleKeyVisibility()">{{'swaggerDefinition_key' | translate}}</label>
<pop-over [position]="'bottom'" [message]="'swaggerDefinition_keyHelp' | translate">
<span class="glyphicon glyphicon-info-sign button-title"></span>
<span class="glyphicon glyphicon-info-sign button-title" tabindex="-1"></span>
</pop-over>
</div>
<div [class.collapse]="!keyVisible">
<div class="setting-wrapper" style="padding-bottom:0px;">
<copy-pre [content]="swaggerKey"></copy-pre>
<copy-pre [content]="swaggerKey" tabindex="-1"></copy-pre>
</div>
<div class="setting-wrapper operation link">
<span (click)="renewSwaggerSecret()"><i class="fa fa-refresh"></i> {{'swaggerDefinition_renew' | translate}}</span>
<span (click)="renewSwaggerSecret()"><i class="fa fa-refresh" tabindex="0" (keydown)="renewKeyDown($event)"></i> {{'swaggerDefinition_renew' | translate}}</span>
</div>
</div>
</div>
<div>
<label class="setting-title">{{'swaggerDefinition_source' | translate}}</label>
<pop-over [position]="'bottom'" [message]="'swaggerDefinition_sourceHelp' | translate">
<span class="glyphicon glyphicon-info-sign button-title"></span>
<span class="glyphicon glyphicon-info-sign button-title" tabindex="-1"></span>
</pop-over>
<div class="setting-wrapper">
<div style="min-width: 270px">
<radio-selector [options]="swaggerStatusOptions" [defaultValue]="swaggerEnabled" (value)="valueChange.next($event)"></radio-selector>
<radio-selector [options]="swaggerStatusOptions" [defaultValue]="swaggerEnabled" (value)="valueChange.next($event)" tabindex="0" (keydown)="apiDefinitionSourceKeyDown($event)"></radio-selector>
</div>
</div>
<div class="setting-wrapper column">
Expand All @@ -59,7 +60,8 @@
</div>
<div>
<div style="padding-left: 6px;">
<i class="fa clickable link" [class.fa-plus]="!documentationVisible" [class.fa-minus]="documentationVisible" (click)="toggleDocumentationVisibility()"></i>
<i class="fa clickable link" [class.fa-plus]="!documentationVisible" [class.fa-minus]="documentationVisible" (click)="toggleDocumentationVisibility()"
tabindex="0" (keydown)="documentKeyDown($event)"></i>
<label class="setting-title-collapsible link" (click)="toggleDocumentationVisibility()">{{'swaggerDefinition_documentation' | translate}}</label>
</div>
<div [class.collapse]="!documentationVisible" (click)="toggleDocumentationVisibility()">
Expand All @@ -83,15 +85,15 @@
<button class="custom-button-invert left medium" (click)="resetEditor()">{{ 'swaggerDefinition_revert' | translate }}</button>
<button class="custom-button left medium" (click)='LoadGeneratedDataInEditor()'>{{'swaggerDefinition_loadGeneratedDefinition' | translate}}</button>
<pop-over [position]="'bottom'" style="padding:5px;" [message]="'swaggerDefinition_generateHelp' | translate">
<span class="glyphicon glyphicon-info-sign button-title"></span>
<span class="glyphicon glyphicon-info-sign button-title" tabindex="-1"></span>
</pop-over>
</div>
<div class="header right">
<span class="link" *ngIf="!isFullscreen" (click)="isFullscreen = true">
<span class="link" *ngIf="!isFullscreen" (click)="isFullscreen = true" tabindex="0" (keydown)="expandCollapseKeyDown($event)">
<i class="fa fa-expand"></i>
{{'swaggerDefinition_expand' | translate}}
</span>
<span class="link" *ngIf="isFullscreen" (click)="isFullscreen = false">
<span class="link" *ngIf="isFullscreen" (click)="isFullscreen = false" tabindex="0" (keydown)="expandCollapseKeyDown($event)">
<i class="fa fa-compress"></i>
{{'swaggerDefinition_collapse' | translate}}
</span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import { TreeViewInfo, SiteData } from './../../tree-view/models/tree-view-info'
import { AppNode } from './../../tree-view/app-node';
import { ArmObj } from './../../shared/models/arm/arm-obj';
import { Site } from './../../shared/models/arm/site';
import { KeyCodes } from '../../shared/models/constants';

@Component({
selector: 'swaggerdefinition',
Expand Down Expand Up @@ -192,6 +193,38 @@ export class SwaggerDefinitionComponent implements OnDestroy {
}, name);
}

apiDefinitionKeyDown(event: KeyboardEvent) {
if (event.keyCode === KeyCodes.enter || event.keyCode === KeyCodes.space) {
console.log(event.keyCode);
this.toggleKeyVisibility();
}
}

apiDefinitionSourceKeyDown(event: KeyboardEvent) {
if (event.keyCode === KeyCodes.enter || event.keyCode === KeyCodes.space) {
this.valueChange.next(!this.swaggerEnabled);
}
}

renewKeyDown(event: KeyboardEvent) {
if (event.keyCode === KeyCodes.enter || event.keyCode === KeyCodes.space) {
this.renewSwaggerSecret();
}
}

documentKeyDown(event: KeyboardEvent) {
if (event.keyCode === KeyCodes.enter || event.keyCode === KeyCodes.space) {
console.log(event.keyCode);
this.toggleDocumentationVisibility();
}
}

expandCollapseKeyDown(event: KeyboardEvent) {
if (event.keyCode === KeyCodes.enter || event.keyCode === KeyCodes.space) {
this.isFullscreen = !this.isFullscreen;
}
}

private setSwaggerEndpointState(swaggerEnabled: boolean) {
return this.functionApp.getHostJson()
.mergeMap(jsonObj => {
Expand Down

0 comments on commit 405cd0d

Please sign in to comment.