Hook up scroll APIs to scroll and focus when navigating

This commit is contained in:
Daniel Imms
2018-01-27 18:14:52 -08:00
parent 0bdf1e8265
commit b13826441c
2 changed files with 85 additions and 9 deletions
+68 -6
View File
@@ -103,10 +103,20 @@ export class AccessibilityManager implements IDisposable {
this._rowElements = null;
}
public get isNavigatingRows(): boolean {
return this._rowElements.indexOf(<HTMLElement>document.activeElement) >= 0;
}
private _onBoundaryFocus(e: FocusEvent, position: BoundaryPosition): void {
const boundaryElement = <HTMLElement>e.target;
const beforeBoundaryElement = this._rowElements[position === BoundaryPosition.Top ? 1 : this._rowElements.length - 2];
// Don't scroll when the last focused item was not the second row (focus is going the other
// direction)
if (e.relatedTarget !== beforeBoundaryElement) {
return;
}
// Don't scroll if the buffer top has reached the end in that direction
const posInSet = boundaryElement.getAttribute('aria-posinset');
const lastRowPos = position === BoundaryPosition.Top ? '1' : `${this._terminal.buffer.lines.length}`;
@@ -114,12 +124,6 @@ export class AccessibilityManager implements IDisposable {
return;
}
// Don't scroll when the last focused item was not the second row (focus is going the other
// direction)
if (e.relatedTarget !== beforeBoundaryElement) {
return;
}
// Remove old boundary element from array
let topBoundaryElement: HTMLElement;
let bottomBoundaryElement: HTMLElement;
@@ -163,6 +167,64 @@ export class AccessibilityManager implements IDisposable {
e.stopImmediatePropagation();
}
/**
* Moves the focus of the terminal relatively by a number of rows.
* @param amount The amount of rows to scroll
*/
public moveRowFocus(amount: number): void {
console.log('moveRowFocus', amount);
// Do nothing if not navigating rows or the amount to navigate is 0
if (!this.isNavigatingRows || amount === 0) {
return;
}
// Find and validate the new absolute row position
const buffer = this._terminal.buffer;
const oldRelativeRow = this._rowElements.indexOf(<HTMLElement>document.activeElement);
const oldAbsoluteRow = buffer.ydisp + oldRelativeRow;
const newAbsoluteRow = Math.max(Math.min(oldAbsoluteRow + amount, buffer.lines.length - 1), 0);
if (oldAbsoluteRow === newAbsoluteRow) {
return;
}
// Find the new relative row, this cannot be on a boundary element unless the focused row is the
// top-most or bottom-most row in the buffer.
let newRelativeRow: number;
if (newAbsoluteRow === 0) {
newRelativeRow = 0;
} else if (newAbsoluteRow === buffer.lines.length - 1) {
newRelativeRow = this._terminal.rows - 1;
} else {
newRelativeRow = Math.max(Math.min(oldRelativeRow + amount, this._terminal.rows - 2), 1);
}
// Find the new viewport position
let newYDisp: number;
if (newAbsoluteRow === 0) {
// Start of buffer
newYDisp = 0;
} else if (newAbsoluteRow === buffer.lines.length - 1) {
// End of buffer
newYDisp = buffer.lines.length - 1 - this._terminal.rows;
} else if (newAbsoluteRow > buffer.ydisp && newAbsoluteRow < buffer.ydisp + this._terminal.rows - 1) {
// No scrolling necessary
newYDisp = buffer.ydisp;
} else if (newAbsoluteRow < oldAbsoluteRow) {
// Scrolling up needed
newYDisp = newAbsoluteRow - 1;
} else { // if (newAbsoluteRow > oldAbsoluteRow)
// Scrolling down needed
newYDisp = newAbsoluteRow + this._terminal.rows - 2;
}
// Perform scroll
const scrollAmount = newYDisp - buffer.ydisp;
this._terminal.scrollLines(scrollAmount);
// Focus new row
this._rowElements[newRelativeRow].focus();
}
private _onResize(cols: number, rows: number): void {
// Remove bottom boundary listener
this._rowElements[this._rowElements.length - 1].removeEventListener('focus', this._bottomBoundaryFocusListener);
+17 -3
View File
@@ -1187,26 +1187,40 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
this.refresh(0, this.rows - 1);
}
/**
* Scrolls the viewport by a number of rows when not navigating rows. When
* navigating rows, move focus relatively by a number of rows.
* @param amount The number of lines to scroll.
*/
private _accessibilityAwareScrollLines(amount: number): void {
console.log('_accessibilityAwareScrollLines');
if (this.options.screenReaderMode && this._accessibilityManager.isNavigatingRows) {
this._accessibilityManager.moveRowFocus(amount);
} else {
this.scrollLines(amount);
}
}
/**
* Scroll the display of the terminal by a number of pages.
* @param {number} pageCount The number of pages to scroll (negative scrolls up).
*/
public scrollPages(pageCount: number): void {
this.scrollLines(pageCount * (this.rows - 1));
this._accessibilityAwareScrollLines(pageCount * (this.rows - 1));
}
/**
* Scrolls the display of the terminal to the top.
*/
public scrollToTop(): void {
this.scrollLines(-this.buffer.ydisp);
this._accessibilityAwareScrollLines(-this.buffer.ydisp);
}
/**
* Scrolls the display of the terminal to the bottom.
*/
public scrollToBottom(): void {
this.scrollLines(this.buffer.ybase - this.buffer.ydisp);
this._accessibilityAwareScrollLines(this.buffer.ybase - this.buffer.ydisp);
}
/**