Dev Tools console is now keyboard accessible (#13946)

* Remove redundant kbn-accessible-click

* Make history in console accessible, fix #13937
This commit is contained in:
Tim Roes 2017-09-19 12:15:02 +02:00 committed by GitHub
parent 199e5c3623
commit 821bd96d32
6 changed files with 95 additions and 4 deletions

View file

@ -5,7 +5,6 @@
<div id="editor_actions">
<kbn-tooltip text="click to send request">
<button
kbn-accessible-click
class="editor_action"
ng-click="sendSelected()"
data-test-subj="send-request-button">

View file

@ -1,15 +1,26 @@
<div class="kuiLocalDropdownTitle">History</div>
<div class="history-body">
<ul class="list-group history-reqs">
<ul
class="list-group history-reqs"
tabindex="0"
role="listbox"
aria-activedescendant="historyReq{{ history.selectedIndex }}"
scrollto-activedescendant
ng-keydown="history.onKeyDown($event)"
aria-label="History of sent requests"
>
<li
role="option"
ng-repeat="req in history.reqs"
id="historyReq{{$index}}"
ng-class="{ selected: history.viewingReq === req }"
ng-click="history.selectedReq = req; history.viewingReq = req"
ng-click="history.selectedReq = req; history.viewingReq = req; history.selectedIndex = $index"
ng-mouseenter="history.viewingReq = req"
ng-mouseleave="history.viewingReq = history.selectedReq"
ng-dblclick="history.restore(req)"
aria-label="{{:: 'Request: ' + history.describeReq(req) }}"
aria-selected="{{ history.selectedReq === req }}"
class="list-group-item history-req"
>
{{ history.describeReq(req) }}

View file

@ -1,3 +1,5 @@
import { keyCodes } from 'ui_framework/services';
var { memoize } = require('lodash');
let moment = require('moment');
@ -13,7 +15,8 @@ require('ui/modules')
controllerAs: 'history',
controller: function ($scope, $element) {
this.reqs = history.getHistory();
this.selectedReq = this.reqs[0];
this.selectedIndex = 0;
this.selectedReq = this.reqs[this.selectedIndex];
this.viewingReq = this.selectedReq;
// calculate the text description of a request
@ -40,6 +43,25 @@ require('ui/modules')
history.restoreFromHistory(req);
$scope.kbnTopNav.close();
};
this.onKeyDown = (ev) => {
if (ev.keyCode === keyCodes.ENTER) {
this.restore();
return;
}
if (ev.keyCode === keyCodes.UP) {
ev.preventDefault();
this.selectedIndex--;
} else if (ev.keyCode === keyCodes.DOWN) {
ev.preventDefault();
this.selectedIndex++;
}
this.selectedIndex = Math.min(Math.max(0, this.selectedIndex), this.reqs.length - 1);
this.selectedReq = this.reqs[this.selectedIndex];
this.viewingReq = this.reqs[this.selectedIndex];
};
}
};
});

View file

@ -0,0 +1,36 @@
import sinon from 'sinon';
import expect from 'expect.js';
import ngMock from 'ng_mock';
import '../scrollto_activedescendant';
describe('scrolltoActivedescendant directive', () => {
let $compile;
let $rootScope;
beforeEach(ngMock.module('kibana'));
beforeEach(ngMock.inject((_$compile_, _$rootScope_) => {
$compile = _$compile_;
$rootScope = _$rootScope_;
}));
it('should call scrollIntoView on aria-activedescendant changes', () => {
const scope = $rootScope.$new();
scope.ad = '';
const element = $compile(`<div aria-activedescendant="{{ad}}" scrollto-activedescendant>
<span id="child1"></span>
<span id="child2"></span>
</div>`)(scope);
const child1 = element.find('#child1');
const child2 = element.find('#child2');
sinon.spy(child1[0], 'scrollIntoView');
sinon.spy(child2[0], 'scrollIntoView');
scope.ad = 'child1';
scope.$digest();
expect(child1[0].scrollIntoView.calledOnce).to.be.eql(true);
scope.ad = 'child2';
scope.$digest();
expect(child2[0].scrollIntoView.calledOnce).to.be.eql(true);
});
});

View file

@ -1 +1,2 @@
import './kbn_accessible_click';
import './scrollto_activedescendant';

View file

@ -0,0 +1,22 @@
/**
* This directive can be applied to an element, that has also aria-activedescendant applied.
* It will make sure, that whenever aria-activedescendant changes, the new element
* referenced by it, will be scrolled into visible view, by calling its `scrollIntoView`
* method.
*/
import { uiModules } from 'ui/modules';
uiModules.get('kibana')
.directive('scrolltoActivedescendant', () => ({
link(scope, element, attrs) {
scope.$watch(() => attrs.ariaActivedescendant, (val) => {
if (val) {
const activeDescendant = element.find(`#${val}`);
if (activeDescendant.length) {
activeDescendant[0].scrollIntoView();
}
}
});
}
}));