Skip to content

Commit 8e0d110

Browse files
authored
Merge pull request #683 from mathjax/a11y_virtual_attached_keyexplorers
A11y virtual attached keyexplorers
2 parents cc3ce70 + e3816d3 commit 8e0d110

File tree

2 files changed

+45
-27
lines changed

2 files changed

+45
-27
lines changed

ts/a11y/explorer.ts

Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -100,12 +100,12 @@ export function ExplorerMathItemMixin<B extends Constructor<HTMLMATHITEM>>(
100100
/**
101101
* The currently attached explorers
102102
*/
103-
protected attached: Explorer[] = [];
103+
protected attached: string[] = [];
104104

105105
/**
106-
* True when a rerendered element should restart the explorer
106+
* True when a rerendered element should restart these explorers
107107
*/
108-
protected restart: boolean = false;
108+
protected restart: string[] = [];
109109

110110
/**
111111
* True when a rerendered element should regain the focus
@@ -146,16 +146,29 @@ export function ExplorerMathItemMixin<B extends Constructor<HTMLMATHITEM>>(
146146
*/
147147
public attachExplorers(document: ExplorerMathDocument) {
148148
this.attached = [];
149+
let keyExplorers = [];
149150
for (let key of Object.keys(this.explorers)) {
150151
let explorer = this.explorers[key];
152+
if (explorer instanceof ke.AbstractKeyExplorer) {
153+
explorer.AddEvents();
154+
explorer.stoppable = false;
155+
keyExplorers.unshift(explorer);
156+
}
151157
if (document.options.a11y[key]) {
152158
explorer.Attach();
153-
this.attached.push(explorer);
159+
this.attached.push(key);
154160
} else {
155161
explorer.Detach();
156162
}
157163
}
158-
this.addExplorers(this.attached);
164+
// Ensure that the last currently attached key explorer stops propagating
165+
// key events.
166+
for (let explorer of keyExplorers) {
167+
if (explorer.attached) {
168+
explorer.stoppable = true;
169+
break;
170+
}
171+
}
159172
}
160173

161174
/**
@@ -164,9 +177,10 @@ export function ExplorerMathItemMixin<B extends Constructor<HTMLMATHITEM>>(
164177
public rerender(document: ExplorerMathDocument, start: number = STATE.RERENDER) {
165178
this.savedId = this.typesetRoot.getAttribute('sre-explorer-id');
166179
this.refocus = (window.document.activeElement === this.typesetRoot);
167-
for (let explorer of this.attached) {
180+
for (let key of this.attached) {
181+
let explorer = this.explorers[key];
168182
if (explorer.active) {
169-
this.restart = true;
183+
this.restart.push(key);
170184
explorer.Stop();
171185
}
172186
}
@@ -179,25 +193,9 @@ export function ExplorerMathItemMixin<B extends Constructor<HTMLMATHITEM>>(
179193
public updateDocument(document: ExplorerMathDocument) {
180194
super.updateDocument(document);
181195
this.refocus && this.typesetRoot.focus();
182-
this.restart && this.attached.forEach(x => x.Start());
183-
this.refocus = this.restart = false;
184-
}
185-
186-
/**
187-
* Adds a list of explorers and makes sure the right one stops propagating.
188-
* @param {Explorer[]} explorers The active explorers to be added.
189-
*/
190-
private addExplorers(explorers: Explorer[]) {
191-
if (explorers.length <= 1) return;
192-
let lastKeyExplorer = null;
193-
for (let explorer of this.attached) {
194-
if (!(explorer instanceof ke.AbstractKeyExplorer)) continue;
195-
explorer.stoppable = false;
196-
lastKeyExplorer = explorer;
197-
}
198-
if (lastKeyExplorer) {
199-
lastKeyExplorer.stoppable = true;
200-
}
196+
this.restart.forEach(x => this.explorers[x].Start());
197+
this.restart = [];
198+
this.refocus = false;
201199
}
202200

203201
};

ts/a11y/explorer/KeyExplorer.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,19 @@ export interface KeyExplorer extends Explorer {
6464
*/
6565
export abstract class AbstractKeyExplorer<T> extends AbstractExplorer<T> implements KeyExplorer {
6666

67+
/**
68+
* Flag indicating if the explorer is attached to an object.
69+
*/
70+
public attached: boolean = false;
71+
6772
/**
6873
* The attached SRE walker.
6974
* @type {sre.Walker}
7075
*/
7176
protected walker: sre.Walker;
7277

78+
private eventsAttached: boolean = false;
79+
7380
/**
7481
* @override
7582
*/
@@ -117,11 +124,22 @@ export abstract class AbstractKeyExplorer<T> extends AbstractExplorer<T> impleme
117124
*/
118125
public Attach() {
119126
super.Attach();
127+
this.attached = true;
120128
this.oldIndex = this.node.tabIndex;
121129
this.node.tabIndex = 1;
122130
this.node.setAttribute('role', 'application');
123131
}
124132

133+
/**
134+
* @override
135+
*/
136+
public AddEvents() {
137+
if (!this.eventsAttached) {
138+
super.AddEvents();
139+
this.eventsAttached = true;
140+
}
141+
}
142+
125143
/**
126144
* @override
127145
*/
@@ -131,7 +149,7 @@ export abstract class AbstractKeyExplorer<T> extends AbstractExplorer<T> impleme
131149
this.oldIndex = null;
132150
this.node.removeAttribute('role');
133151
}
134-
super.Detach();
152+
this.attached = false;
135153
}
136154

137155
/**
@@ -194,6 +212,7 @@ export class SpeechExplorer extends AbstractKeyExplorer<string> {
194212
* @override
195213
*/
196214
public Start() {
215+
if (!this.attached) return;
197216
let options = this.getOptions();
198217
// TODO: Check and set locale not only on init, but on every start.
199218
if (!this.init) {
@@ -354,6 +373,7 @@ export class Magnifier extends AbstractKeyExplorer<HTMLElement> {
354373
*/
355374
public Start() {
356375
super.Start();
376+
if (!this.attached) return;
357377
this.region.Show(this.node, this.highlighter);
358378
this.walker.activate();
359379
this.Update();

0 commit comments

Comments
 (0)