@@ -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 } ;
@@ -240,12 +238,15 @@ export function ExplorerMathDocumentMixin<B extends MathDocumentConstructor<HTML
240238 */
241239 public static OPTIONS : OptionList = {
242240 ...BaseDocument . OPTIONS ,
243- enrichSpeech : 'shallow' , // overrides option in EnrichedMathDocument
244241 enableExplorer : true ,
245242 renderActions : expandable ( {
246243 ...BaseDocument . OPTIONS . renderActions ,
247244 explorable : [ STATE . EXPLORER ]
248245 } ) ,
246+ sre : expandable ( {
247+ ...BaseDocument . OPTIONS . sre ,
248+ speech : 'shallow' , // overrides option in EnrichedMathDocument
249+ } ) ,
249250 a11y : {
250251 align : 'top' , // placement of magnified expression
251252 backgroundColor : 'Blue' , // color for background of selected sub-expression
@@ -260,12 +261,10 @@ export function ExplorerMathDocumentMixin<B extends MathDocumentConstructor<HTML
260261 infoRole : false , // show semantic role on mouse hovering
261262 infoType : false , // show semantic type on mouse hovering
262263 keyMagnifier : false , // switch on magnification via key exploration
263- locale : 'en' , // switch the locale
264264 magnification : 'None' , // type of magnification
265265 magnify : '400%' , // percentage of magnification of zoomed expressions
266266 mouseMagnifier : false , // switch on magnification via mouse hovering
267267 speech : true , // switch on speech output
268- speechRules : 'mathspeak-default' , // speech rules as domain-style pair
269268 subtitles : true , // show speech as a subtitle
270269 treeColoring : false , // tree color expression
271270 viewBraille : false // display Braille output as subtitles
@@ -285,6 +284,7 @@ export function ExplorerMathDocumentMixin<B extends MathDocumentConstructor<HTML
285284 * @constructor
286285 */
287286 constructor ( ...args : any [ ] ) {
287+ processSreOptions ( args [ 2 ] ) ;
288288 super ( ...args ) ;
289289 const ProcessBits = ( this . constructor as typeof BaseDocument ) . ProcessBits ;
290290 if ( ! ProcessBits . has ( 'explorer' ) ) {
@@ -293,6 +293,7 @@ export function ExplorerMathDocumentMixin<B extends MathDocumentConstructor<HTML
293293 const visitor = new SerializedMmlVisitor ( this . mmlFactory ) ;
294294 const toMathML = ( ( node : MmlNode ) => visitor . visitTree ( node ) ) ;
295295 this . options . MathItem = ExplorerMathItemMixin ( this . options . MathItem , toMathML ) ;
296+ // TODO: set backward compatibility options here.
296297 this . explorerRegions = initExplorerRegions ( this ) ;
297298 }
298299
@@ -328,6 +329,33 @@ export function ExplorerMathDocumentMixin<B extends MathDocumentConstructor<HTML
328329
329330}
330331
332+ //
333+ // TODO(v3.2): This is for backward compatibility of old option parameters.
334+ //
335+ /**
336+ * Processes old a11y options for backward compatibility.
337+ * @param {OptionList } options The options to process.
338+ */
339+ function processSreOptions ( options : OptionList ) {
340+ if ( ! options || ! options . a11y ) {
341+ return ;
342+ }
343+ if ( ! options . sre ) {
344+ options . sre = { } ;
345+ }
346+ if ( options . a11y . locale ) {
347+ options . sre . locale = options . a11y . locale ;
348+ delete options . a11y . locale ;
349+ }
350+ if ( options . a11y . speechRules ) {
351+ let [ domain , style ] = ( options . a11y . speechRules as string ) . split ( '-' ) ;
352+ options . sre . domain = domain ;
353+ options . sre . style = style ;
354+ delete options . a11y . speechRules ;
355+ }
356+ }
357+
358+
331359/*==========================================================================*/
332360
333361/**
@@ -392,10 +420,9 @@ let allExplorers: {[options: string]: ExplorerInit} = {
392420 speech : ( doc : ExplorerMathDocument , node : HTMLElement , ...rest : any [ ] ) => {
393421 let explorer = ke . SpeechExplorer . create (
394422 doc , doc . explorerRegions . speechRegion , node , ...rest ) as ke . SpeechExplorer ;
395- let [ domain , style ] = doc . options . a11y . speechRules . split ( '-' ) ;
396423 explorer . speechGenerator . setOptions ( {
397- locale : doc . options . a11y . locale , domain : domain ,
398- style : style , modality : 'speech' , cache : false } ) ;
424+ locale : doc . options . sre . locale , domain : doc . options . sre . domain ,
425+ style : doc . options . sre . style , modality : 'speech' , cache : false } ) ;
399426 explorer . showRegion = 'subtitles' ;
400427 return explorer ;
401428 } ,
@@ -458,9 +485,17 @@ function initExplorers(document: ExplorerMathDocument, node: HTMLElement, mml: s
458485 * @param {{[key: string]: any} } options Association list for a11y option value pairs.
459486 */
460487export function setA11yOptions ( document : HTMLDOCUMENT , options : { [ key : string ] : any } ) {
488+ let sreOptions = SRE . engineSetup ( ) as { [ name : string ] : string } ;
461489 for ( let key in options ) {
462490 if ( document . options . a11y [ key ] !== undefined ) {
463491 setA11yOption ( document , key , options [ key ] ) ;
492+ if ( key === 'locale' ) {
493+ document . options . sre [ key ] = options [ key ] ;
494+ }
495+ continue ;
496+ }
497+ if ( sreOptions [ key ] !== undefined ) {
498+ document . options . sre [ key ] = options [ key ] ;
464499 }
465500 }
466501 // Reinit explorers
@@ -516,6 +551,19 @@ export function setA11yOption(document: HTMLDOCUMENT, option: string, value: str
516551 break ;
517552 }
518553 break ;
554+ //
555+ // TODO(v3.2): These two cases should be handled directly in the menu
556+ // variable actions.
557+ //
558+ case 'speechRules' :
559+ let [ domain , style ] = ( value as string ) . split ( '-' ) ;
560+ document . options . sre . domain = domain ;
561+ document . options . sre . style = style ;
562+ break ;
563+ case 'locale' :
564+ document . options . sre . locale = value ;
565+ SRE . setupEngine ( { locale : value as string } ) ;
566+ break ;
519567 default :
520568 document . options . a11y [ option ] = value ;
521569 }
0 commit comments