From f85358f167e0fff5693e34b026ac85eb27441aff Mon Sep 17 00:00:00 2001 From: zorkow Date: Mon, 24 Jun 2019 11:00:19 +0100 Subject: [PATCH 01/12] Integrates a11y settings into menu. --- mathjax3-ts/a11y/explorer.ts | 77 ++++++++++++++++++++++++++++++++++++ mathjax3-ts/ui/menu/Menu.ts | 38 +++++++++++++++--- 2 files changed, 109 insertions(+), 6 deletions(-) diff --git a/mathjax3-ts/a11y/explorer.ts b/mathjax3-ts/a11y/explorer.ts index 0c06ecf6e..e499790cf 100644 --- a/mathjax3-ts/a11y/explorer.ts +++ b/mathjax3-ts/a11y/explorer.ts @@ -313,3 +313,80 @@ export function ExplorerHandler(handler: HANDLER, MmlJax: MATHML = null) { handler.documentClass = ExplorerMathDocumentMixin(handler.documentClass as any); return handler; } + + +/** + * Map for names of menu variables to option variables. + * @type {Map} + */ +const menuMap: Map = new Map([ + ['explorer', 'explorer'], + ['highlight', 'highlight'], + ['background', 'backgroundColor'], + ['foreground', 'foregroundColor'], + ['speech', 'speech'], + ['subtitles', 'subtitles'], + ['braille', 'braille'], + ['viewbraille', 'viewbraille'], + ['speechrules', 'speechrules'], + ['autocollapse', 'autocollapse'], + ['collapsible', 'collapsible'], + ['inTabOrder', 'inTabOrder'] +]); + +const optionsMap: Map = new Map( + [...menuMap].map(([x, y]) => [y, x]) as [string, string][] +); + + +/** + * Copies options from the explorer option names into menu variable names. + * @param {[key: string]: string} src Source structure. + * @param {[key: string]: string} dst Destination structure. + */ +export function optionSettings(src: {[key: string]: string}, dst: {[key: string]: string}) { + copySettings(optionsMap, src, dst); +}; + + +/** + * Copies options from the menu variable names into explorer option names. + * @param {[key: string]: string} src Source structure. + * @param {[key: string]: string} dst Destination structure. + */ +export function menuSettings(src: {[key: string]: string}, dst: {[key: string]: string}) { + copySettings(menuMap, src, dst); +}; + + +/** + * Sets a single a11y option for a menu name. + * @param {HTMLDOCUMENT} document The current document. + * @param {string} option The option name in the menu. + * @param {string|boolean} value The new value. + */ +export function setA11yOption(document: HTMLDOCUMENT, option: string, value: string|boolean) { + let key = menuMap.get(option); + if (key) { + document.options.a11y[key] = value; + } +} + + +/** + * Copies options from one name set into another. + * @param {Map} map The name map. + * @param {[key: string]: string} src Source structure. + * @param {[key: string]: string} dst Destination structure. + * @private + */ +function copySettings(map: Map, + src: {[key: string]: string}, + dst: {[key: string]: string}) { + for (let key of map.keys()) { + let option = src[key]; + if (src[key] !== undefined) { + dst[map.get(key)] = option; + } + } +}; diff --git a/mathjax3-ts/ui/menu/Menu.ts b/mathjax3-ts/ui/menu/Menu.ts index 41749c2f3..124f8358b 100644 --- a/mathjax3-ts/ui/menu/Menu.ts +++ b/mathjax3-ts/ui/menu/Menu.ts @@ -72,6 +72,8 @@ export interface MenuSettings { foreground: string; speech: boolean; subtitles: boolean; + braille: boolean; + viewbraille: boolean; speechrules: string; autocollapse: boolean; collapsible: boolean; @@ -108,12 +110,15 @@ export class Menu { ctrl: false, shift: false, scale: 1, + // A11y options explorer: false, highlight: 'None', background: 'Blue', foreground: 'Black', speech: true, subtitles: false, + braille: true, + viewbraille: false, speechrules: 'mathspeak-default', autocollapse: false, collapsible: false, @@ -360,6 +365,10 @@ export class Menu { const jax = this.document.outputJax; this.jax[jax.name] = jax; this.settings.renderer = jax.name; + if (window.MathJax._.a11y && window.MathJax._.a11y.explorer) { + window.MathJax._.a11y.explorer_ts.optionSettings( + this.document.options.a11y, this.settings); + } this.settings.scale = jax.options.scale; this.defaultSettings = Object.assign({}, this.settings); } @@ -385,13 +394,19 @@ export class Menu { this.variable('explorer', (explore: boolean) => this.setExplorer(explore)), this.variable ('highlight'), this.variable ('background', (background: string) => - this.document.options.a11y.backgroundColor = background), + this.setA11y('background', background)), this.variable ('foreground', (foreground: string) => - this.document.options.a11y.foregroundColor = foreground), - this.variable('speech'), + this.setA11y('foreground', foreground)), + this.variable('speech', (speech: boolean) => + this.setA11y('speech', speech)), this.variable('subtitles', (subtitles: boolean) => - this.document.options.a11y.subtitles = subtitles), - this.variable ('speechrules'), + this.setA11y('subtitles', subtitles)), + this.variable('braille', (braille: boolean) => + this.setA11y('braille', braille)), + this.variable('viewbraille', (viewbraille: boolean) => + this.setA11y('viewbraille', viewbraille)), + this.variable ('speechrules', (speechrules: boolean) => + this.setA11y('speechrules', speechrules)), this.variable('autocollapse'), this.variable('collapsible', (collapse: boolean) => this.setCollapsible(collapse)), this.variable('inTabOrder', (tab: boolean) => this.setTabOrder(tab)) @@ -451,6 +466,8 @@ export class Menu { this.rule(), this.checkbox('Speech', 'Speech Output', 'speech'), this.checkbox('Subtitles', 'Subtities', 'subtitles'), + this.checkbox('Braille', 'Braille', 'braille'), + this.checkbox('View Braille', 'View Braille', 'viewbraille'), this.rule(), this.submenu('Mathspeak', 'Mathspeak Rules', this.radioGroup('speechrules', [ ['mathspeak-default', 'Verbose'], @@ -545,6 +562,10 @@ export class Menu { const settings = localStorage.getItem(Menu.MENU_STORAGE); if (!settings) return; Object.assign(this.settings, JSON.parse(settings)); + if (window.MathJax._.a11y && window.MathJax._.a11y.explorer) { + window.MathJax._.a11y.explorer_ts.menuSettings( + this.settings, this.document.options.a11y); + } } catch (err) { console.log('MathJax localStorage error: ' + err.message); } @@ -760,6 +781,11 @@ export class Menu { }); } + protected setA11y(option: string, value: string|boolean) { + if (window.MathJax._.a11y && window.MathJax._.a11y.explorer) { + window.MathJax._.a11y.explorer_ts.setA11yOption(this.document, option, value); + } + /** * @param {MenuMathDocument} document The original document whose list is to be transferred */ @@ -903,7 +929,7 @@ export class Menu { /*======================================================================*/ /** - * Create JSON for a variable constrolling a menu setting + * Create JSON for a variable controlling a menu setting * * @param {keyof MenuSettings} name The setting for which to make a variable * @param {(T) => void} action Optional function to perform after setting the value From 6a999dba84c9d6ce9dbab29552b50dd8b974119b Mon Sep 17 00:00:00 2001 From: zorkow Date: Tue, 25 Jun 2019 13:06:49 +0100 Subject: [PATCH 02/12] Partial integration into Menu. --- mathjax3-ts/a11y/explorer.ts | 278 ++++++++++++++--------- mathjax3-ts/a11y/explorer/KeyExplorer.ts | 10 +- mathjax3-ts/a11y/sre_browser.d.ts | 4 + mathjax3-ts/ui/menu/Menu.ts | 143 ++++++++---- 4 files changed, 276 insertions(+), 159 deletions(-) diff --git a/mathjax3-ts/a11y/explorer.ts b/mathjax3-ts/a11y/explorer.ts index e499790cf..c0615d8fe 100644 --- a/mathjax3-ts/a11y/explorer.ts +++ b/mathjax3-ts/a11y/explorer.ts @@ -32,8 +32,8 @@ import {BitField} from '../util/BitField.js'; import {SerializedMmlVisitor} from '../core/MmlTree/SerializedMmlVisitor.js'; import {Explorer} from './explorer/Explorer.js'; -import {AbstractKeyExplorer, Magnifier, SpeechExplorer} from './explorer/KeyExplorer.js'; -import {FlameHoverer} from './explorer/MouseExplorer.js'; +import * as ke from './explorer/KeyExplorer.js'; +import * as me from './explorer/MouseExplorer.js'; import {LiveRegion, ToolTip, HoverRegion} from './explorer/Region.js'; /** @@ -118,33 +118,12 @@ export function ExplorerMathItemMixin>( this.savedId = null; } this.addExplorers( - SpeechExplorer.create(document, document.explorerObjects.region, node, mml), - SpeechExplorer.create(document, document.explorerObjects.region2, node, mml), - Magnifier.create(document, document.explorerObjects.magnifier, node, mml), - FlameHoverer.create(document, null, node) + initExplorers(document, node, mml) ); this.state(STATE.EXPLORER); } - /** - * Adds a list of explorers and makes sure the right one stops propagating. - * @param {Explorer[]} ...explorers - */ - private addExplorers(...explorers: Explorer[]) { - this.explorers = explorers; - if (explorers.length <= 1) return; - let lastKeyExplorer = null; - for (let explorer of this.explorers) { - if (!(explorer instanceof AbstractKeyExplorer)) continue; - if (lastKeyExplorer) { - lastKeyExplorer.stoppable = false; - } - lastKeyExplorer = explorer; - } - } - - /** * @override */ @@ -170,22 +149,27 @@ export function ExplorerMathItemMixin>( this.refocus = this.restart = false; } - }; -} + /** + * Adds a list of explorers and makes sure the right one stops propagating. + * @param {Explorer[]} explorers The active explorers to be added. + */ + private addExplorers(explorers: Explorer[]) { + // this.explorers = initExplorers(document, node, mml); + this.explorers = explorers; + if (explorers.length <= 1) return; + let lastKeyExplorer = null; + for (let explorer of this.explorers) { + if (!(explorer instanceof ke.AbstractKeyExplorer)) continue; + if (lastKeyExplorer) { + lastKeyExplorer.stoppable = false; + } + lastKeyExplorer = explorer; + } + } -/*==========================================================================*/ + }; -/** - * The objects needed for the explorer - */ -export type ExplorerObjects = { - region?: LiveRegion, - region2?: LiveRegion, - tooltip?: ToolTip, - tooltip2?: ToolTip, - tooltip3?: ToolTip, - magnifier?: HoverRegion } /** @@ -196,7 +180,7 @@ export interface ExplorerMathDocument extends HTMLDOCUMENT { /** * The objects needed for the explorer */ - explorerObjects: ExplorerObjects; + explorerRegions: ExplorerRegions; /** * Add the Explorer to the MathItems in the MathDocument @@ -225,21 +209,33 @@ export function ExplorerMathDocumentMixin visitor.visitTree(node)); this.options.MathItem = ExplorerMathItemMixin(this.options.MathItem, toMathML); - this.explorerObjects = { - region: new LiveRegion(this), - region2: new LiveRegion(this), - tooltip: new ToolTip(this), - tooltip2: new ToolTip(this), - tooltip3: new ToolTip(this), - magnifier: new HoverRegion(this) - }; + this.explorerRegions = initExplorerRegions(this); } /** @@ -315,49 +304,100 @@ export function ExplorerHandler(handler: HANDLER, MmlJax: MATHML = null) { } +/*==========================================================================*/ + /** - * Map for names of menu variables to option variables. - * @type {Map} + * The objects needed for the explorer */ -const menuMap: Map = new Map([ - ['explorer', 'explorer'], - ['highlight', 'highlight'], - ['background', 'backgroundColor'], - ['foreground', 'foregroundColor'], - ['speech', 'speech'], - ['subtitles', 'subtitles'], - ['braille', 'braille'], - ['viewbraille', 'viewbraille'], - ['speechrules', 'speechrules'], - ['autocollapse', 'autocollapse'], - ['collapsible', 'collapsible'], - ['inTabOrder', 'inTabOrder'] -]); - -const optionsMap: Map = new Map( - [...menuMap].map(([x, y]) => [y, x]) as [string, string][] -); +export type ExplorerRegions = { + speechRegion?: LiveRegion, + brailleRegion?: LiveRegion, + magnifier?: HoverRegion, + tooltip1?: ToolTip, + tooltip2?: ToolTip, + tooltip3?: ToolTip +} + + +function initExplorerRegions(document: ExplorerMathDocument) { + return { + speechRegion: new LiveRegion(document), + brailleRegion: new LiveRegion(document), + magnifier: new HoverRegion(document), + tooltip1: new ToolTip(document), + tooltip2: new ToolTip(document), + tooltip3: new ToolTip(document) + }; +} + + +// Each explorer has a name, an option and a region associated. /** - * Copies options from the explorer option names into menu variable names. - * @param {[key: string]: string} src Source structure. - * @param {[key: string]: string} dst Destination structure. + * Generation methods for all MathJax explorers available via option settings. */ -export function optionSettings(src: {[key: string]: string}, dst: {[key: string]: string}) { - copySettings(optionsMap, src, dst); +let allExplorers: {[options: string]: (doc: ExplorerMathDocument, + node: HTMLElement, ...rest: any[]) => Explorer} = { + speech: (doc: ExplorerMathDocument, node: HTMLElement, ...rest: any[]) => { + let explorer = ke.SpeechExplorer.create( + doc, doc.explorerRegions.speechRegion, node, ...rest) as ke.SpeechExplorer; + explorer.speechGenerator.setOptions({locale: 'en', domain: 'mathspeak', + style: 'default', modality: 'speech'}); + explorer.showRegion = 'subtitles'; + return explorer; + }, + braille: (doc: ExplorerMathDocument, node: HTMLElement, ...rest: any[]) => { + let explorer = ke.SpeechExplorer.create( + doc, doc.explorerRegions.brailleRegion, node, ...rest) as ke.SpeechExplorer; + explorer.speechGenerator.setOptions({locale: 'nemeth', domain: 'default', + style: 'default', modality: 'braille'}); + explorer.showRegion = 'viewbraille'; + return explorer; + }, + keymagnifier: (doc: ExplorerMathDocument, node: HTMLElement, ...rest: any[]) => + ke.Magnifier.create(doc, doc.explorerRegions.magnifier, node, ...rest), + mousemagnifier: (doc: ExplorerMathDocument, node: HTMLElement, ...rest: any[]) => + me.ContentHoverer.create(doc, doc.explorerRegions.magnifier, node, + (x: HTMLElement) => x.hasAttribute('data-semantic-type'), + (x: HTMLElement) => x), + // Missing: FlameHighlighter, TreeHighlighter + hover: (doc: ExplorerMathDocument, node: HTMLElement, ...rest: any[]) => + me.FlameHoverer.create(doc, null, node), + typetip: (doc: ExplorerMathDocument, node: HTMLElement, ...rest: any[]) => + me.ValueHoverer.create(doc, doc.explorerRegions.tooltip1, node, + (x: HTMLElement) => x.hasAttribute('data-semantic-type'), + (x: HTMLElement) => x.getAttribute('data-semantic-type')), + roletip: (doc: ExplorerMathDocument, node: HTMLElement, ...rest: any[]) => + me.ValueHoverer.create(doc, doc.explorerRegions.tooltip2, node, + (x: HTMLElement) => x.hasAttribute('data-semantic-role'), + (x: HTMLElement) => x.getAttribute('data-semantic-role')), + prefixtip: (doc: ExplorerMathDocument, node: HTMLElement, ...rest: any[]) => + me.ValueHoverer.create(doc, doc.explorerRegions.tooltip3, node, + (x: HTMLElement) => x.hasAttribute('data-semantic-prefix'), + (x: HTMLElement) => x.getAttribute('data-semantic-prefix')) }; /** - * Copies options from the menu variable names into explorer option names. - * @param {[key: string]: string} src Source structure. - * @param {[key: string]: string} dst Destination structure. + * Initialises explorers for a document. + * @param {ExplorerMathDocument} document The target document. + * @param {HTMLElement} node The node explorers will be attached to. + * @param {string} mml The corresponding Mathml node as a string. + * @return {Explorer[]} A list of initialised explorers. */ -export function menuSettings(src: {[key: string]: string}, dst: {[key: string]: string}) { - copySettings(menuMap, src, dst); -}; +function initExplorers(document: ExplorerMathDocument, node: HTMLElement, mml: string): Explorer[] { + let explorers = []; + for (let key of Object.keys(allExplorers)) { + if (document.options.a11y[key]) { + explorers.push(allExplorers[key](document, node, mml)); + } + } + return explorers; +} + +/* Context Menu Interactions */ /** * Sets a single a11y option for a menu name. @@ -366,27 +406,47 @@ export function menuSettings(src: {[key: string]: string}, dst: {[key: string]: * @param {string|boolean} value The new value. */ export function setA11yOption(document: HTMLDOCUMENT, option: string, value: string|boolean) { - let key = menuMap.get(option); - if (key) { - document.options.a11y[key] = value; - } -} - - -/** - * Copies options from one name set into another. - * @param {Map} map The name map. - * @param {[key: string]: string} src Source structure. - * @param {[key: string]: string} dst Destination structure. - * @private - */ -function copySettings(map: Map, - src: {[key: string]: string}, - dst: {[key: string]: string}) { - for (let key of map.keys()) { - let option = src[key]; - if (src[key] !== undefined) { - dst[map.get(key)] = option; + switch (option) { + case 'magnification': + switch (value) { + case 'None': + document.options.a11y.magnifier = value; + document.options.a11y.keymagnifier = false; + document.options.a11y.mousemagnifier = false; + break; + case 'Keyboard': + document.options.a11y.magnifier = value; + document.options.a11y.keymagnifier = true; + document.options.a11y.mousemagnifier = false; + break; + case 'Mouse': + document.options.a11y.magnifier = value; + document.options.a11y.keymagnifier = false; + document.options.a11y.mousemagnifier = true; + break; + } + break; + case 'highlight': + switch (value) { + case 'None': + document.options.a11y.highlight = value; + document.options.a11y.hover = false; + document.options.a11y.flame = false; + break; + case 'Hover': + document.options.a11y.highlight = value; + document.options.a11y.hover = true; + document.options.a11y.flame = false; + break; + case 'Flame': + document.options.a11y.highlight = value; + document.options.a11y.hover = false; + document.options.a11y.flame = true; + break; + } + break; + // TODO: magnify, similar to zscale. + default: + document.options.a11y[option] = value; } - } -}; +} diff --git a/mathjax3-ts/a11y/explorer/KeyExplorer.ts b/mathjax3-ts/a11y/explorer/KeyExplorer.ts index 3c5dfdaf3..644f5eab0 100644 --- a/mathjax3-ts/a11y/explorer/KeyExplorer.ts +++ b/mathjax3-ts/a11y/explorer/KeyExplorer.ts @@ -131,7 +131,9 @@ export class SpeechExplorer extends AbstractKeyExplorer { * The SRE speech generator associated with the walker. * @type {sre.SpeechGenerator} */ - protected speechGenerator: sre.SpeechGenerator; + public speechGenerator: sre.SpeechGenerator; + + public showRegion: string = 'subtitles'; /** * Flag in case the start method is triggered before the walker is fully @@ -159,12 +161,14 @@ export class SpeechExplorer extends AbstractKeyExplorer { */ public Start() { super.Start(); + let options = this.speechGenerator.getOptions(); this.speechGenerator = new sre.DirectSpeechGenerator(); + this.speechGenerator.setOptions(options); this.walker = sre.WalkerFactory.walker('table', this.node, this.speechGenerator, this.highlighter, this.mml); this.walker.activate(); this.Update(); - if (this.document.options.a11y.subtitles) { + if (this.document.options.a11y[this.showRegion]) { this.region.Show(this.node, this.highlighter); } this.restarted = true; @@ -189,7 +193,7 @@ export class SpeechExplorer extends AbstractKeyExplorer { let speech = walker.speech(); this.node.setAttribute('hasspeech', 'true'); this.Update(); - if (this.restarted && this.document.options.a11y.subtitles) { + if (this.restarted && this.document.options.a11y[this.showRegion]) { this.region.Show(this.node, this.highlighter); } }).catch((error: Error) => console.log(error.message)); diff --git a/mathjax3-ts/a11y/sre_browser.d.ts b/mathjax3-ts/a11y/sre_browser.d.ts index e6c48c4a5..17362572e 100644 --- a/mathjax3-ts/a11y/sre_browser.d.ts +++ b/mathjax3-ts/a11y/sre_browser.d.ts @@ -6,10 +6,14 @@ declare namespace sre { interface SpeechGenerator { speech(): string; + setOptions(options: Object): void; + getOptions(): Object; } class AbstractSpeechGenerator implements SpeechGenerator { speech(): string; + setOptions(options: Object): void; + getOptions(): Object; } class TreeSpeechGenerator extends AbstractSpeechGenerator { } diff --git a/mathjax3-ts/ui/menu/Menu.ts b/mathjax3-ts/ui/menu/Menu.ts index 124f8358b..633d52832 100644 --- a/mathjax3-ts/ui/menu/Menu.ts +++ b/mathjax3-ts/ui/menu/Menu.ts @@ -68,13 +68,16 @@ export interface MenuSettings { scale: string; explorer: boolean; highlight: string; - background: string; - foreground: string; + backgroundColor: string; + foregroundColor: string; speech: boolean; subtitles: boolean; braille: boolean; viewbraille: boolean; speechrules: string; + magnify: string; + magnification: string; + treehighlight: boolean; autocollapse: boolean; collapsible: boolean; inTabOrder: boolean; @@ -110,16 +113,19 @@ export class Menu { ctrl: false, shift: false, scale: 1, - // A11y options + // A11y options explorer: false, highlight: 'None', - background: 'Blue', - foreground: 'Black', + backgroundColor: 'Blue', + foregroundColor: 'Black', speech: true, subtitles: false, braille: true, viewbraille: false, speechrules: 'mathspeak-default', + magnification: 'None', + magnify: false, + treehighlight: false, autocollapse: false, collapsible: false, inTabOrder: true, @@ -366,8 +372,7 @@ export class Menu { this.jax[jax.name] = jax; this.settings.renderer = jax.name; if (window.MathJax._.a11y && window.MathJax._.a11y.explorer) { - window.MathJax._.a11y.explorer_ts.optionSettings( - this.document.options.a11y, this.settings); + Object.assign(this.settings, this.document.options.a11y); } this.settings.scale = jax.options.scale; this.defaultSettings = Object.assign({}, this.settings); @@ -393,10 +398,10 @@ export class Menu { this.variable ('scale', (scale: string) => this.setScale(scale)), this.variable('explorer', (explore: boolean) => this.setExplorer(explore)), this.variable ('highlight'), - this.variable ('background', (background: string) => - this.setA11y('background', background)), - this.variable ('foreground', (foreground: string) => - this.setA11y('foreground', foreground)), + this.variable ('backgroundColor', (background: string) => + this.setA11y('backgroundColor', background)), + this.variable ('foregroundColor', (foreground: string) => + this.setA11y('foregroundColor', foreground)), this.variable('speech', (speech: boolean) => this.setA11y('speech', speech)), this.variable('subtitles', (subtitles: boolean) => @@ -405,8 +410,14 @@ export class Menu { this.setA11y('braille', braille)), this.variable('viewbraille', (viewbraille: boolean) => this.setA11y('viewbraille', viewbraille)), - this.variable ('speechrules', (speechrules: boolean) => + this.variable ('speechrules', (speechrules: string) => this.setA11y('speechrules', speechrules)), + this.variable ('magnification', (magnification: string) => + this.setA11y('magnification', magnification)), + this.variable ('magnify', (magnify: string) => + this.setA11y('magnify', magnify)), + this.variable('treehighlight', (treehighlight: boolean) => + this.setA11y('treehighlight', treehighlight)), this.variable('autocollapse'), this.variable('collapsible', (collapse: boolean) => this.setCollapsible(collapse)), this.variable('inTabOrder', (tab: boolean) => this.setTabOrder(tab)) @@ -454,31 +465,54 @@ export class Menu { this.submenu('Explorer', 'Explorer', [ this.checkbox('Active', 'Active', 'explorer'), this.rule(), - this.submenu('Highlight', 'Highlight', this.radioGroup('highlight', [ - ['None'], ['Hover'], ['Flame'] - ]), true), - this.submenu('Background', 'Background', this.radioGroup('background', [ - ['Blue'], ['Red'], ['Green'], ['Yellow'], ['Cyan'], ['Magenta'], ['White'], ['Black'] - ])), - this.submenu('Foreground', 'Foreground', this.radioGroup('foreground', [ - ['Black'], ['White'], ['Magenta'], ['Cyan'], ['Yellow'], ['Green'], ['Red'], ['Blue'] - ])), - this.rule(), - this.checkbox('Speech', 'Speech Output', 'speech'), - this.checkbox('Subtitles', 'Subtities', 'subtitles'), - this.checkbox('Braille', 'Braille', 'braille'), - this.checkbox('View Braille', 'View Braille', 'viewbraille'), - this.rule(), - this.submenu('Mathspeak', 'Mathspeak Rules', this.radioGroup('speechrules', [ - ['mathspeak-default', 'Verbose'], - ['mathspeak-brief', 'Brief'], - ['mathspeak-sbrief', 'Superbrief'] - ])), - this.submenu('ChromeVox', 'ChromeVox Rules', this.radioGroup('speechrules', [ - ['chromvox-default', 'Verbose'], - ['chromevox-short', 'Short'], - ['chromevox-alternative', 'Alternative'] - ])) + this.submenu('Speech', 'Speech', [ + this.checkbox('Speech', 'Speech Output', 'speech'), + this.checkbox('Subtitles', 'Subtities', 'subtitles'), + this.checkbox('Braille', 'Braille', 'braille'), + this.checkbox('View Braille', 'View Braille', 'viewbraille'), + this.rule(), + this.submenu('Mathspeak', 'Mathspeak Rules', this.radioGroup('speechrules', [ + ['mathspeak-default', 'Verbose'], + ['mathspeak-brief', 'Brief'], + ['mathspeak-sbrief', 'Superbrief'] + ])), + this.submenu('Clearspeak', 'Clearspeak Rules', this.radioGroup('speechrules', [ + ['clearspeak-default', 'Standard'] + ])), + this.submenu('ChromeVox', 'ChromeVox Rules', this.radioGroup('speechrules', [ + ['chromvox-default', 'Verbose'], + ['chromevox-short', 'Short'], + ['chromevox-alternative', 'Alternative'] + ])) + ]), + this.submenu('Highlight', 'Highlight', [ + this.submenu('Background', 'Background', this.radioGroup('backgroundColor', [ + ['Blue'], ['Red'], ['Green'], ['Yellow'], ['Cyan'], ['Magenta'], ['White'], ['Black'] + ])), + this.submenu('Foreground', 'Foreground', this.radioGroup('foregroundColor', [ + ['Black'], ['White'], ['Magenta'], ['Cyan'], ['Yellow'], ['Green'], ['Red'], ['Blue'] + ])), + this.rule(), + this.radioGroup('highlight', [ + ['None'], ['Hover'], ['Flame'] + ]), + this.rule(), + this.checkbox('TreeHihighlighter', 'Tree Highlighting', 'treehighlight') + ]), + this.submenu('Magnification', 'Magnification', [ + this.radioGroup('magnification', [ + ['None'], ['Keyboard'], ['Mouse'] + ]), + this.rule(), + this.radioGroup('magnify', [ + ['200%'], ['300%'], ['400%'], ['500%'] + ]) + ]), + this.submenu('Semantic Info', 'Semantic Info', [ + // this.checkbox('Type', 'Type', 'type'), + // this.checkbox('Role', 'Role', 'role'), + // this.checkbox('Prefix', 'Prefix', 'prefix'), + ], true), ]), this.rule(), this.checkbox('Collapsible', 'Collapsible Math', 'collapsible'), @@ -562,10 +596,7 @@ export class Menu { const settings = localStorage.getItem(Menu.MENU_STORAGE); if (!settings) return; Object.assign(this.settings, JSON.parse(settings)); - if (window.MathJax._.a11y && window.MathJax._.a11y.explorer) { - window.MathJax._.a11y.explorer_ts.menuSettings( - this.settings, this.document.options.a11y); - } + this.mergeA11ySettings(); } catch (err) { console.log('MathJax localStorage error: ' + err.message); } @@ -592,6 +623,29 @@ export class Menu { } } + + /** + * Merge the menu settings into the a11y document options. + */ + protected mergeA11ySettings() { + if (!window.MathJax._.a11y || !window.MathJax._.a11y.explorer) return; + ['explorer', 'highlight', 'backgroundColor', 'foregroundColor', + 'speech', 'subtitles', 'braille', 'viewbraille', 'speechrules', + 'magnification'].forEach(x => this.setA11y(x, this.settings[x])); + } + + + /** + * Sets a single a11y document option. + * @param {string} option The option. + * @param {string|boolean} value Its new value. + */ + protected setA11y(option: string, value: string|boolean) { + if (window.MathJax._.a11y && window.MathJax._.a11y.explorer) { + window.MathJax._.a11y.explorer_ts.setA11yOption(this.document, option, value); + } + } + /*======================================================================*/ /** @@ -781,10 +835,6 @@ export class Menu { }); } - protected setA11y(option: string, value: string|boolean) { - if (window.MathJax._.a11y && window.MathJax._.a11y.explorer) { - window.MathJax._.a11y.explorer_ts.setA11yOption(this.document, option, value); - } /** * @param {MenuMathDocument} document The original document whose list is to be transferred @@ -1001,7 +1051,7 @@ export class Menu { * * @param {string} variable The (pool) variable to attach to each radio button * @param {string[][]} radios An array of [string] or [string, string], giving the id and content - * for each radio button (if only one string is given it is ued for both) + * for each radio button (if only one string is given it is used for both) * @returns {Object[]} An array of JSON objects for radion buttons */ public radioGroup(variable: string, radios: string[][]) { @@ -1044,4 +1094,3 @@ export class Menu { /*======================================================================*/ } - From efc328d1f1daf8d4ad071eec4fc370ebcc65fd5f Mon Sep 17 00:00:00 2001 From: zorkow Date: Wed, 26 Jun 2019 14:53:19 +0100 Subject: [PATCH 03/12] Adds TreeExplorer class. --- mathjax3-ts/a11y/explorer.ts | 24 ++++--- mathjax3-ts/a11y/explorer/TreeExplorer.ts | 78 +++++++++++++++++++++++ mathjax3-ts/a11y/sre_browser.d.ts | 2 + mathjax3-ts/ui/menu/Menu.ts | 13 ++-- 4 files changed, 103 insertions(+), 14 deletions(-) create mode 100644 mathjax3-ts/a11y/explorer/TreeExplorer.ts diff --git a/mathjax3-ts/a11y/explorer.ts b/mathjax3-ts/a11y/explorer.ts index c0615d8fe..0b1fdd480 100644 --- a/mathjax3-ts/a11y/explorer.ts +++ b/mathjax3-ts/a11y/explorer.ts @@ -34,6 +34,7 @@ import {SerializedMmlVisitor} from '../core/MmlTree/SerializedMmlVisitor.js'; import {Explorer} from './explorer/Explorer.js'; import * as ke from './explorer/KeyExplorer.js'; import * as me from './explorer/MouseExplorer.js'; +import {FlameColorer} from './explorer/TreeExplorer.js'; import {LiveRegion, ToolTip, HoverRegion} from './explorer/Region.js'; /** @@ -224,8 +225,9 @@ export function ExplorerMathDocumentMixin Explorer; + /** * Generation methods for all MathJax explorers available via option settings. */ -let allExplorers: {[options: string]: (doc: ExplorerMathDocument, - node: HTMLElement, ...rest: any[]) => Explorer} = { +let allExplorers: {[options: string]: ExplorerInit} = { speech: (doc: ExplorerMathDocument, node: HTMLElement, ...rest: any[]) => { let explorer = ke.SpeechExplorer.create( doc, doc.explorerRegions.speechRegion, node, ...rest) as ke.SpeechExplorer; @@ -361,7 +365,6 @@ let allExplorers: {[options: string]: (doc: ExplorerMathDocument, me.ContentHoverer.create(doc, doc.explorerRegions.magnifier, node, (x: HTMLElement) => x.hasAttribute('data-semantic-type'), (x: HTMLElement) => x), - // Missing: FlameHighlighter, TreeHighlighter hover: (doc: ExplorerMathDocument, node: HTMLElement, ...rest: any[]) => me.FlameHoverer.create(doc, null, node), typetip: (doc: ExplorerMathDocument, node: HTMLElement, ...rest: any[]) => @@ -370,12 +373,17 @@ let allExplorers: {[options: string]: (doc: ExplorerMathDocument, (x: HTMLElement) => x.getAttribute('data-semantic-type')), roletip: (doc: ExplorerMathDocument, node: HTMLElement, ...rest: any[]) => me.ValueHoverer.create(doc, doc.explorerRegions.tooltip2, node, - (x: HTMLElement) => x.hasAttribute('data-semantic-role'), - (x: HTMLElement) => x.getAttribute('data-semantic-role')), + (x: HTMLElement) => x.hasAttribute('data-semantic-role'), + (x: HTMLElement) => x.getAttribute('data-semantic-role')), prefixtip: (doc: ExplorerMathDocument, node: HTMLElement, ...rest: any[]) => me.ValueHoverer.create(doc, doc.explorerRegions.tooltip3, node, - (x: HTMLElement) => x.hasAttribute('data-semantic-prefix'), - (x: HTMLElement) => x.getAttribute('data-semantic-prefix')) + (x: HTMLElement) => x.hasAttribute('data-semantic-prefix'), + (x: HTMLElement) => x.getAttribute('data-semantic-prefix')), + // Missing: FlameHighlighter, TreeHighlighter + flame: (doc: ExplorerMathDocument, node: HTMLElement, ...rest: any[]) => + FlameColorer.create(doc, null, node) + // treecoloring: (doc: ExplorerMathDocument, node: HTMLElement, ...rest: any[]) => + // TreeColorer.create(doc, null, node, ...rest) }; diff --git a/mathjax3-ts/a11y/explorer/TreeExplorer.ts b/mathjax3-ts/a11y/explorer/TreeExplorer.ts new file mode 100644 index 000000000..65990bad2 --- /dev/null +++ b/mathjax3-ts/a11y/explorer/TreeExplorer.ts @@ -0,0 +1,78 @@ +/************************************************************* + * + * Copyright (c) 2009-2019 The MathJax Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +/** + * @fileoverview Tree Explorers allow to switch on effects on the entire + * expression tree. + * + * @author v.sorge@mathjax.org (Volker Sorge) + */ + + +import {A11yDocument, Region} from './Region.js'; +import {Explorer, AbstractExplorer} from './Explorer.js'; +import {sreReady} from '../sre.js'; + + +export interface TreeExplorer extends Explorer { + +} + + +export class AbstractTreeExplorer extends AbstractExplorer { + + /** + * @override + */ + protected constructor(public document: A11yDocument, + protected region: Region, + protected node: HTMLElement, + protected mml: HTMLElement) { + super(document, null, node); + this.Start(); + } + + /** + * @override + */ + readonly stoppable = false; + + /** + * @override + */ + public AddEvents() { } + + /** + * @override + */ + public RemoveEvents() { } + +} + + +export class FlameColorer extends AbstractTreeExplorer { + + public Start() { + this.highlighter.highlightAll(this.node); + } + + public Stop() { + this.highlighter.unhighlightAll(this.node); + } + +} diff --git a/mathjax3-ts/a11y/sre_browser.d.ts b/mathjax3-ts/a11y/sre_browser.d.ts index 17362572e..1dd63a879 100644 --- a/mathjax3-ts/a11y/sre_browser.d.ts +++ b/mathjax3-ts/a11y/sre_browser.d.ts @@ -26,6 +26,8 @@ declare namespace sre { interface Highlighter { highlight(nodes: Node[]): void; unhighlight(): void; + highlightAll(node: Node): void; + unhighlightAll(node: Node): void; colorString(): colorString; isMactionNode(node: Node): boolean; } diff --git a/mathjax3-ts/ui/menu/Menu.ts b/mathjax3-ts/ui/menu/Menu.ts index 633d52832..85341ca67 100644 --- a/mathjax3-ts/ui/menu/Menu.ts +++ b/mathjax3-ts/ui/menu/Menu.ts @@ -77,7 +77,7 @@ export interface MenuSettings { speechrules: string; magnify: string; magnification: string; - treehighlight: boolean; + treecoloring: boolean; autocollapse: boolean; collapsible: boolean; inTabOrder: boolean; @@ -125,7 +125,7 @@ export class Menu { speechrules: 'mathspeak-default', magnification: 'None', magnify: false, - treehighlight: false, + treecoloring: false, autocollapse: false, collapsible: false, inTabOrder: true, @@ -416,8 +416,8 @@ export class Menu { this.setA11y('magnification', magnification)), this.variable ('magnify', (magnify: string) => this.setA11y('magnify', magnify)), - this.variable('treehighlight', (treehighlight: boolean) => - this.setA11y('treehighlight', treehighlight)), + this.variable('treecoloring', (treecoloring: boolean) => + this.setA11y('treecoloring', treecoloring)), this.variable('autocollapse'), this.variable('collapsible', (collapse: boolean) => this.setCollapsible(collapse)), this.variable('inTabOrder', (tab: boolean) => this.setTabOrder(tab)) @@ -497,7 +497,7 @@ export class Menu { ['None'], ['Hover'], ['Flame'] ]), this.rule(), - this.checkbox('TreeHihighlighter', 'Tree Highlighting', 'treehighlight') + this.checkbox('TreeColoring', 'Tree Coloring', 'treecoloring') ]), this.submenu('Magnification', 'Magnification', [ this.radioGroup('magnification', [ @@ -631,7 +631,8 @@ export class Menu { if (!window.MathJax._.a11y || !window.MathJax._.a11y.explorer) return; ['explorer', 'highlight', 'backgroundColor', 'foregroundColor', 'speech', 'subtitles', 'braille', 'viewbraille', 'speechrules', - 'magnification'].forEach(x => this.setA11y(x, this.settings[x])); + 'magnification'].forEach( + x => this.setA11y(x, (this.settings as {[key: string]: any})[x])); } From cd8e88110a9f72fd0da19e0a2200ebb888991b5b Mon Sep 17 00:00:00 2001 From: zorkow Date: Thu, 27 Jun 2019 17:53:56 +0100 Subject: [PATCH 04/12] Implements tree coloring. --- mathjax3-ts/a11y/explorer.ts | 8 ++++---- mathjax3-ts/a11y/explorer/TreeExplorer.ts | 24 +++++++++++++++++++++++ mathjax3-ts/a11y/sre_browser.d.ts | 24 ++++++++--------------- 3 files changed, 36 insertions(+), 20 deletions(-) diff --git a/mathjax3-ts/a11y/explorer.ts b/mathjax3-ts/a11y/explorer.ts index 0b1fdd480..87b3404c6 100644 --- a/mathjax3-ts/a11y/explorer.ts +++ b/mathjax3-ts/a11y/explorer.ts @@ -34,7 +34,7 @@ import {SerializedMmlVisitor} from '../core/MmlTree/SerializedMmlVisitor.js'; import {Explorer} from './explorer/Explorer.js'; import * as ke from './explorer/KeyExplorer.js'; import * as me from './explorer/MouseExplorer.js'; -import {FlameColorer} from './explorer/TreeExplorer.js'; +import {TreeColorer, FlameColorer} from './explorer/TreeExplorer.js'; import {LiveRegion, ToolTip, HoverRegion} from './explorer/Region.js'; /** @@ -381,9 +381,9 @@ let allExplorers: {[options: string]: ExplorerInit} = { (x: HTMLElement) => x.getAttribute('data-semantic-prefix')), // Missing: FlameHighlighter, TreeHighlighter flame: (doc: ExplorerMathDocument, node: HTMLElement, ...rest: any[]) => - FlameColorer.create(doc, null, node) - // treecoloring: (doc: ExplorerMathDocument, node: HTMLElement, ...rest: any[]) => - // TreeColorer.create(doc, null, node, ...rest) + FlameColorer.create(doc, null, node), + treecoloring: (doc: ExplorerMathDocument, node: HTMLElement, ...rest: any[]) => + TreeColorer.create(doc, null, node, ...rest) }; diff --git a/mathjax3-ts/a11y/explorer/TreeExplorer.ts b/mathjax3-ts/a11y/explorer/TreeExplorer.ts index 65990bad2..b8fe2c2f7 100644 --- a/mathjax3-ts/a11y/explorer/TreeExplorer.ts +++ b/mathjax3-ts/a11y/explorer/TreeExplorer.ts @@ -76,3 +76,27 @@ export class FlameColorer extends AbstractTreeExplorer { } } + + +export class TreeColorer extends AbstractTreeExplorer { + + /** + * @override + */ + public Start() { + let generator = sre.SpeechGeneratorFactory.generator('Color'); + if (!this.node.hasAttribute('hasforegroundcolor')) { + generator.generateSpeech(this.node, this.mml); + this.node.setAttribute('hasforegroundcolor', 'true'); + } + this.highlighter.colorizeAll(this.node); + } + + /** + * @override + */ + public Stop() { + this.highlighter.uncolorizeAll(this.node); + } + +} diff --git a/mathjax3-ts/a11y/sre_browser.d.ts b/mathjax3-ts/a11y/sre_browser.d.ts index 1dd63a879..a4ff968f0 100644 --- a/mathjax3-ts/a11y/sre_browser.d.ts +++ b/mathjax3-ts/a11y/sre_browser.d.ts @@ -1,28 +1,15 @@ - declare namespace sre { export type colorType = {color: string, alpha: number}; export type colorString = {foreground: string, background: string}; interface SpeechGenerator { + generateSpeech(node: HTMLElement, xml: HTMLElement): string; speech(): string; setOptions(options: Object): void; getOptions(): Object; } - class AbstractSpeechGenerator implements SpeechGenerator { - speech(): string; - setOptions(options: Object): void; - getOptions(): Object; - } - - class TreeSpeechGenerator extends AbstractSpeechGenerator { } - - class DirectSpeechGenerator extends AbstractSpeechGenerator { } - - class DummySpeechGenerator extends AbstractSpeechGenerator { } - - interface Highlighter { highlight(nodes: Node[]): void; unhighlight(): void; @@ -30,12 +17,14 @@ declare namespace sre { unhighlightAll(node: Node): void; colorString(): colorString; isMactionNode(node: Node): boolean; + colorizeAll(node: Node): void; + uncolorizeAll(node: Node): void; } interface Focus { getNodes(): Node[]; } - + interface Walker { activate(): void; deactivate(): void; @@ -52,7 +41,10 @@ declare namespace sre.WalkerFactory { generator: SpeechGenerator, highlighter: Highlighter, mml: Node): Walker; - +} + +declare namespace sre.SpeechGeneratorFactory { + export function generator(kind: string): sre.SpeechGenerator; } declare namespace sre.Engine { From 1f420bcf18b48f0cdde0cb39ea1b3d4fe7adc910 Mon Sep 17 00:00:00 2001 From: zorkow Date: Thu, 27 Jun 2019 17:54:04 +0100 Subject: [PATCH 05/12] Refactors speech generator generation. --- mathjax3-ts/a11y/explorer/KeyExplorer.ts | 14 ++++++++------ mathjax3-ts/ui/menu/Menu.ts | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/mathjax3-ts/a11y/explorer/KeyExplorer.ts b/mathjax3-ts/a11y/explorer/KeyExplorer.ts index 1d9fad32a..75ad1c17d 100644 --- a/mathjax3-ts/a11y/explorer/KeyExplorer.ts +++ b/mathjax3-ts/a11y/explorer/KeyExplorer.ts @@ -188,7 +188,7 @@ export class SpeechExplorer extends AbstractKeyExplorer { public Start() { super.Start(); let options = this.speechGenerator.getOptions(); - this.speechGenerator = new sre.DirectSpeechGenerator(); + this.speechGenerator = sre.SpeechGeneratorFactory.generator('Direct'); this.speechGenerator.setOptions(options); this.walker = sre.WalkerFactory.walker('table', this.node, this.speechGenerator, this.highlighter, this.mml); @@ -260,9 +260,10 @@ export class SpeechExplorer extends AbstractKeyExplorer { * Initialises the SRE walker. */ private initWalker() { - this.speechGenerator = new sre.TreeSpeechGenerator(); - let dummy = sre.WalkerFactory.walker('dummy', - this.node, this.speechGenerator, this.highlighter, this.mml); + this.speechGenerator = sre.SpeechGeneratorFactory.generator('Tree'); + let dummy = sre.WalkerFactory.walker( + 'dummy', this.node, this.speechGenerator, this.highlighter, this.mml); + this.walker = dummy; this.Speech(dummy); } @@ -285,8 +286,9 @@ export class Magnifier extends AbstractKeyExplorer { protected node: HTMLElement, private mml: HTMLElement) { super(document, region, node); - this.walker = sre.WalkerFactory.walker('table', - this.node, new sre.DummySpeechGenerator(), this.highlighter, this.mml); + this.walker = sre.WalkerFactory.walker( + 'table', this.node, sre.SpeechGeneratorFactory.generator('Dummy'), + this.highlighter, this.mml); } /** diff --git a/mathjax3-ts/ui/menu/Menu.ts b/mathjax3-ts/ui/menu/Menu.ts index 85341ca67..0ab6bdd9a 100644 --- a/mathjax3-ts/ui/menu/Menu.ts +++ b/mathjax3-ts/ui/menu/Menu.ts @@ -643,7 +643,7 @@ export class Menu { */ protected setA11y(option: string, value: string|boolean) { if (window.MathJax._.a11y && window.MathJax._.a11y.explorer) { - window.MathJax._.a11y.explorer_ts.setA11yOption(this.document, option, value); + window.MathJax._.a11y.explorer_ts.setA11yOption(this.document, option, value); } } From 580f3094e18084b0731360f29e64995b8e008956 Mon Sep 17 00:00:00 2001 From: zorkow Date: Fri, 28 Jun 2019 09:14:09 +0100 Subject: [PATCH 06/12] Separates initialisation and attachment of explorers. --- mathjax3-ts/a11y/explorer.ts | 45 +++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/mathjax3-ts/a11y/explorer.ts b/mathjax3-ts/a11y/explorer.ts index 87b3404c6..326b74a9f 100644 --- a/mathjax3-ts/a11y/explorer.ts +++ b/mathjax3-ts/a11y/explorer.ts @@ -88,7 +88,12 @@ export function ExplorerMathItemMixin>( /** * The Explorer objects for this math item */ - protected explorers: Explorer[] = []; + protected explorers: {[key: string]: Explorer} = {}; + + /** + * The currently attached explorers + */ + protected attached: Explorer[] = []; /** * True when a rerendered element should restart the explorer @@ -118,9 +123,11 @@ export function ExplorerMathItemMixin>( this.typesetRoot.setAttribute('sre-explorer-id', this.savedId); this.savedId = null; } - this.addExplorers( - initExplorers(document, node, mml) - ); + // Init explorers: + this.explorers = initExplorers(document, node, mml); + this.attached = attachExplorers(document, this.explorers); + this.addExplorers(this.attached); + // Attach explorers, returns the ones that need to be reactivated. this.state(STATE.EXPLORER); } @@ -131,7 +138,7 @@ export function ExplorerMathItemMixin>( public rerender(document: ExplorerMathDocument, start: number = STATE.RERENDER) { this.savedId = this.typesetRoot.getAttribute('sre-explorer-id'); this.refocus = (window.document.activeElement === this.typesetRoot); - for (let explorer of this.explorers) { + for (let explorer of this.attached) { if (explorer.active) { this.restart = true; explorer.Stop(); @@ -146,7 +153,7 @@ export function ExplorerMathItemMixin>( public updateDocument(document: ExplorerMathDocument) { super.updateDocument(document); this.refocus && this.typesetRoot.focus(); - this.restart && this.explorers.forEach(x => x.Start()); + this.restart && this.attached.forEach(x => x.Start()); this.refocus = this.restart = false; } @@ -156,11 +163,9 @@ export function ExplorerMathItemMixin>( * @param {Explorer[]} explorers The active explorers to be added. */ private addExplorers(explorers: Explorer[]) { - // this.explorers = initExplorers(document, node, mml); - this.explorers = explorers; if (explorers.length <= 1) return; let lastKeyExplorer = null; - for (let explorer of this.explorers) { + for (let explorer of this.attached) { if (!(explorer instanceof ke.AbstractKeyExplorer)) continue; if (lastKeyExplorer) { lastKeyExplorer.stoppable = false; @@ -394,19 +399,33 @@ let allExplorers: {[options: string]: ExplorerInit} = { * @param {string} mml The corresponding Mathml node as a string. * @return {Explorer[]} A list of initialised explorers. */ -function initExplorers(document: ExplorerMathDocument, node: HTMLElement, mml: string): Explorer[] { - let explorers = []; +function initExplorers(document: ExplorerMathDocument, node: HTMLElement, mml: string): {[key: string]: Explorer} { + let explorers: {[key: string]: Explorer} = {}; for (let key of Object.keys(allExplorers)) { + explorers[key] = allExplorers[key](document, node, mml); + } + return explorers; +} + + +function attachExplorers(document: ExplorerMathDocument, explorers: {[key: string]: Explorer}): Explorer[] { + let attached: Explorer[] = []; + for (let key of Object.keys(explorers)) { + let explorer = explorers[key]; if (document.options.a11y[key]) { - explorers.push(allExplorers[key](document, node, mml)); + explorer.Attach(); + attached.push(explorer); + } else { + explorer.Detach(); } } - return explorers; + return attached; } /* Context Menu Interactions */ + /** * Sets a single a11y option for a menu name. * @param {HTMLDOCUMENT} document The current document. From 719ca1eea8876b16fe49e6c6b8cd4ab65befdf32 Mon Sep 17 00:00:00 2001 From: zorkow Date: Mon, 1 Jul 2019 16:00:00 +0100 Subject: [PATCH 07/12] Integrates explorers into menu with correct restart. --- mathjax3-ts/a11y/explorer.ts | 45 ++++++++++++++++-------- mathjax3-ts/a11y/explorer/KeyExplorer.ts | 4 +-- mathjax3-ts/ui/menu/Menu.ts | 44 ++++++++--------------- 3 files changed, 47 insertions(+), 46 deletions(-) diff --git a/mathjax3-ts/a11y/explorer.ts b/mathjax3-ts/a11y/explorer.ts index 326b74a9f..31aea37ac 100644 --- a/mathjax3-ts/a11y/explorer.ts +++ b/mathjax3-ts/a11y/explorer.ts @@ -67,6 +67,7 @@ export interface ExplorerMathItem extends HTMLMATHITEM { */ explorable(document: HTMLDOCUMENT): void; + attachExplorers(document: HTMLDOCUMENT): void; } /** @@ -124,14 +125,29 @@ export function ExplorerMathItemMixin>( this.savedId = null; } // Init explorers: + // Make these part of the explorer. this.explorers = initExplorers(document, node, mml); - this.attached = attachExplorers(document, this.explorers); - this.addExplorers(this.attached); + this.attachExplorers(document); // Attach explorers, returns the ones that need to be reactivated. this.state(STATE.EXPLORER); } + public attachExplorers(document: ExplorerMathDocument) { + this.attached = []; + for (let key of Object.keys(this.explorers)) { + let explorer = this.explorers[key]; + if (document.options.a11y[key]) { + explorer.Attach(); + this.attached.push(explorer); + } else { + explorer.Detach(); + } + } + this.addExplorers(this.attached); + } + + /** * @override */ @@ -171,6 +187,7 @@ export function ExplorerMathItemMixin>( lastKeyExplorer.stoppable = false; } lastKeyExplorer = explorer; + lastKeyExplorer.stoppable = true; } } @@ -408,24 +425,22 @@ function initExplorers(document: ExplorerMathDocument, node: HTMLElement, mml: s } -function attachExplorers(document: ExplorerMathDocument, explorers: {[key: string]: Explorer}): Explorer[] { - let attached: Explorer[] = []; - for (let key of Object.keys(explorers)) { - let explorer = explorers[key]; - if (document.options.a11y[key]) { - explorer.Attach(); - attached.push(explorer); - } else { - explorer.Detach(); +/* Context Menu Interactions */ + + +export function setA11yOptions(document: HTMLDOCUMENT, options: {[key: string]: any}) { + for (let key in options) { + if (document.options.a11y[key] !== undefined) { + setA11yOption(document, key, options[key]); } } - return attached; + // Reinit explorers + for (let item of document.math ) { + (item as ExplorerMathItem).attachExplorers(document as ExplorerMathDocument); + } } -/* Context Menu Interactions */ - - /** * Sets a single a11y option for a menu name. * @param {HTMLDOCUMENT} document The current document. diff --git a/mathjax3-ts/a11y/explorer/KeyExplorer.ts b/mathjax3-ts/a11y/explorer/KeyExplorer.ts index 75ad1c17d..70ceb1936 100644 --- a/mathjax3-ts/a11y/explorer/KeyExplorer.ts +++ b/mathjax3-ts/a11y/explorer/KeyExplorer.ts @@ -241,7 +241,7 @@ export class SpeechExplorer extends AbstractKeyExplorer { this.stopEvent(event); return; } - if (code === 32 && event.shiftKey) { + if (code === 32 && event.shiftKey || code === 13) { this.Start(); this.stopEvent(event); } @@ -346,7 +346,7 @@ export class Magnifier extends AbstractKeyExplorer { this.stopEvent(event); return; } - if (code === 32 && event.shiftKey) { + if (code === 32 && event.shiftKey || code === 13) { this.Start(); this.stopEvent(event); } diff --git a/mathjax3-ts/ui/menu/Menu.ts b/mathjax3-ts/ui/menu/Menu.ts index 0ab6bdd9a..3336b7cbd 100644 --- a/mathjax3-ts/ui/menu/Menu.ts +++ b/mathjax3-ts/ui/menu/Menu.ts @@ -399,25 +399,25 @@ export class Menu { this.variable('explorer', (explore: boolean) => this.setExplorer(explore)), this.variable ('highlight'), this.variable ('backgroundColor', (background: string) => - this.setA11y('backgroundColor', background)), + this.setA11y({'backgroundColor': background})), this.variable ('foregroundColor', (foreground: string) => - this.setA11y('foregroundColor', foreground)), + this.setA11y({'foregroundColor': foreground})), this.variable('speech', (speech: boolean) => - this.setA11y('speech', speech)), + this.setA11y({'speech': speech})), this.variable('subtitles', (subtitles: boolean) => - this.setA11y('subtitles', subtitles)), + this.setA11y({'subtitles': subtitles})), this.variable('braille', (braille: boolean) => - this.setA11y('braille', braille)), + this.setA11y({'braille': braille})), this.variable('viewbraille', (viewbraille: boolean) => - this.setA11y('viewbraille', viewbraille)), + this.setA11y({'viewbraille': viewbraille})), this.variable ('speechrules', (speechrules: string) => - this.setA11y('speechrules', speechrules)), + this.setA11y({'speechrules': speechrules})), this.variable ('magnification', (magnification: string) => - this.setA11y('magnification', magnification)), + this.setA11y({'magnification': magnification})), this.variable ('magnify', (magnify: string) => - this.setA11y('magnify', magnify)), + this.setA11y({'magnify': magnify})), this.variable('treecoloring', (treecoloring: boolean) => - this.setA11y('treecoloring', treecoloring)), + this.setA11y({'treecoloring': treecoloring})), this.variable('autocollapse'), this.variable('collapsible', (collapse: boolean) => this.setCollapsible(collapse)), this.variable('inTabOrder', (tab: boolean) => this.setTabOrder(tab)) @@ -596,7 +596,7 @@ export class Menu { const settings = localStorage.getItem(Menu.MENU_STORAGE); if (!settings) return; Object.assign(this.settings, JSON.parse(settings)); - this.mergeA11ySettings(); + this.setA11y(this.settings); } catch (err) { console.log('MathJax localStorage error: ' + err.message); } @@ -623,27 +623,13 @@ export class Menu { } } - - /** - * Merge the menu settings into the a11y document options. - */ - protected mergeA11ySettings() { - if (!window.MathJax._.a11y || !window.MathJax._.a11y.explorer) return; - ['explorer', 'highlight', 'backgroundColor', 'foregroundColor', - 'speech', 'subtitles', 'braille', 'viewbraille', 'speechrules', - 'magnification'].forEach( - x => this.setA11y(x, (this.settings as {[key: string]: any})[x])); - } - - /** - * Sets a single a11y document option. - * @param {string} option The option. - * @param {string|boolean} value Its new value. + * Merge menu settings into the a11y document options. + * @param {[key: string]: any} options The options. */ - protected setA11y(option: string, value: string|boolean) { + protected setA11y(options: {[key: string]: any}) { if (window.MathJax._.a11y && window.MathJax._.a11y.explorer) { - window.MathJax._.a11y.explorer_ts.setA11yOption(this.document, option, value); + window.MathJax._.a11y.explorer_ts.setA11yOptions(this.document, options); } } From 9b7c004a5232b89706a8bdaafdf2cd1bd6c939aa Mon Sep 17 00:00:00 2001 From: zorkow Date: Mon, 1 Jul 2019 16:11:40 +0100 Subject: [PATCH 08/12] Moves explorer menu into top level accessibility menu. --- mathjax3-ts/ui/menu/Menu.ts | 102 +++++++++++++++++------------------- 1 file changed, 49 insertions(+), 53 deletions(-) diff --git a/mathjax3-ts/ui/menu/Menu.ts b/mathjax3-ts/ui/menu/Menu.ts index 3336b7cbd..2984f6bfd 100644 --- a/mathjax3-ts/ui/menu/Menu.ts +++ b/mathjax3-ts/ui/menu/Menu.ts @@ -462,58 +462,55 @@ export class Menu { this.command('Reset', 'Reset to defaults', () => this.resetDefaults()) ]), this.submenu('Accessibility', 'Accessibility', [ - this.submenu('Explorer', 'Explorer', [ - this.checkbox('Active', 'Active', 'explorer'), + this.checkbox('Activate', 'Activate', 'explorer'), + this.submenu('Speech', 'Speech', [ + this.checkbox('Speech', 'Speech Output', 'speech'), + this.checkbox('Subtitles', 'Subtities', 'subtitles'), + this.checkbox('Braille', 'Braille', 'braille'), + this.checkbox('View Braille', 'View Braille', 'viewbraille'), this.rule(), - this.submenu('Speech', 'Speech', [ - this.checkbox('Speech', 'Speech Output', 'speech'), - this.checkbox('Subtitles', 'Subtities', 'subtitles'), - this.checkbox('Braille', 'Braille', 'braille'), - this.checkbox('View Braille', 'View Braille', 'viewbraille'), - this.rule(), - this.submenu('Mathspeak', 'Mathspeak Rules', this.radioGroup('speechrules', [ - ['mathspeak-default', 'Verbose'], - ['mathspeak-brief', 'Brief'], - ['mathspeak-sbrief', 'Superbrief'] - ])), - this.submenu('Clearspeak', 'Clearspeak Rules', this.radioGroup('speechrules', [ - ['clearspeak-default', 'Standard'] - ])), - this.submenu('ChromeVox', 'ChromeVox Rules', this.radioGroup('speechrules', [ - ['chromvox-default', 'Verbose'], - ['chromevox-short', 'Short'], - ['chromevox-alternative', 'Alternative'] - ])) - ]), - this.submenu('Highlight', 'Highlight', [ - this.submenu('Background', 'Background', this.radioGroup('backgroundColor', [ - ['Blue'], ['Red'], ['Green'], ['Yellow'], ['Cyan'], ['Magenta'], ['White'], ['Black'] - ])), - this.submenu('Foreground', 'Foreground', this.radioGroup('foregroundColor', [ - ['Black'], ['White'], ['Magenta'], ['Cyan'], ['Yellow'], ['Green'], ['Red'], ['Blue'] - ])), - this.rule(), - this.radioGroup('highlight', [ - ['None'], ['Hover'], ['Flame'] - ]), - this.rule(), - this.checkbox('TreeColoring', 'Tree Coloring', 'treecoloring') + this.submenu('Mathspeak', 'Mathspeak Rules', this.radioGroup('speechrules', [ + ['mathspeak-default', 'Verbose'], + ['mathspeak-brief', 'Brief'], + ['mathspeak-sbrief', 'Superbrief'] + ])), + this.submenu('Clearspeak', 'Clearspeak Rules', this.radioGroup('speechrules', [ + ['clearspeak-default', 'Standard'] + ])), + this.submenu('ChromeVox', 'ChromeVox Rules', this.radioGroup('speechrules', [ + ['chromvox-default', 'Verbose'], + ['chromevox-short', 'Short'], + ['chromevox-alternative', 'Alternative'] + ])) + ]), + this.submenu('Highlight', 'Highlight', [ + this.submenu('Background', 'Background', this.radioGroup('backgroundColor', [ + ['Blue'], ['Red'], ['Green'], ['Yellow'], ['Cyan'], ['Magenta'], ['White'], ['Black'] + ])), + this.submenu('Foreground', 'Foreground', this.radioGroup('foregroundColor', [ + ['Black'], ['White'], ['Magenta'], ['Cyan'], ['Yellow'], ['Green'], ['Red'], ['Blue'] + ])), + this.rule(), + this.radioGroup('highlight', [ + ['None'], ['Hover'], ['Flame'] ]), - this.submenu('Magnification', 'Magnification', [ - this.radioGroup('magnification', [ - ['None'], ['Keyboard'], ['Mouse'] - ]), - this.rule(), - this.radioGroup('magnify', [ - ['200%'], ['300%'], ['400%'], ['500%'] - ]) + this.rule(), + this.checkbox('TreeColoring', 'Tree Coloring', 'treecoloring') + ]), + this.submenu('Magnification', 'Magnification', [ + this.radioGroup('magnification', [ + ['None'], ['Keyboard'], ['Mouse'] ]), - this.submenu('Semantic Info', 'Semantic Info', [ - // this.checkbox('Type', 'Type', 'type'), - // this.checkbox('Role', 'Role', 'role'), - // this.checkbox('Prefix', 'Prefix', 'prefix'), - ], true), + this.rule(), + this.radioGroup('magnify', [ + ['200%'], ['300%'], ['400%'], ['500%'] + ]) ]), + this.submenu('Semantic Info', 'Semantic Info', [ + // this.checkbox('Type', 'Type', 'type'), + // this.checkbox('Role', 'Role', 'role'), + // this.checkbox('Prefix', 'Prefix', 'prefix'), + ], true), this.rule(), this.checkbox('Collapsible', 'Collapsible Math', 'collapsible'), this.checkbox('AutoCollapse', 'Auto Collapse', 'autocollapse', {disabled: true}), @@ -577,11 +574,10 @@ export class Menu { * @param {boolean} enable True to enable, false to disable */ protected enableExplorerItems(enable: boolean) { - const menu = (this.menu.findID('Accessibility', 'Explorer') as ContextMenu.Submenu).getSubmenu(); - for (const item of menu.getItems().slice(3)) { - if (!(item instanceof ContextMenu.Rule)) { - enable ? item.enable() : item.disable(); - } + const menu = (this.menu.findID('Accessibility', 'Activate') as ContextMenu.Submenu).getMenu(); + for (const item of menu.getItems().slice(1)) { + if (item instanceof ContextMenu.Rule) break; + enable ? item.enable() : item.disable(); } } From f4a77310b7a54b2bfbc077cef3c76ea8da8ef794 Mon Sep 17 00:00:00 2001 From: zorkow Date: Wed, 3 Jul 2019 11:50:45 +0100 Subject: [PATCH 09/12] Moves A11y options fully to explorer module. --- mathjax3-ts/a11y/explorer.ts | 34 +++++++++++------------ mathjax3-ts/ui/menu/Menu.ts | 54 ++++++++++++++++++------------------ 2 files changed, 44 insertions(+), 44 deletions(-) diff --git a/mathjax3-ts/a11y/explorer.ts b/mathjax3-ts/a11y/explorer.ts index 31aea37ac..75dc43056 100644 --- a/mathjax3-ts/a11y/explorer.ts +++ b/mathjax3-ts/a11y/explorer.ts @@ -233,26 +233,26 @@ export function ExplorerMathDocumentMixin x), hover: (doc: ExplorerMathDocument, node: HTMLElement, ...rest: any[]) => me.FlameHoverer.create(doc, null, node), - typetip: (doc: ExplorerMathDocument, node: HTMLElement, ...rest: any[]) => + infoType: (doc: ExplorerMathDocument, node: HTMLElement, ...rest: any[]) => me.ValueHoverer.create(doc, doc.explorerRegions.tooltip1, node, (x: HTMLElement) => x.hasAttribute('data-semantic-type'), (x: HTMLElement) => x.getAttribute('data-semantic-type')), - roletip: (doc: ExplorerMathDocument, node: HTMLElement, ...rest: any[]) => + infoRole: (doc: ExplorerMathDocument, node: HTMLElement, ...rest: any[]) => me.ValueHoverer.create(doc, doc.explorerRegions.tooltip2, node, (x: HTMLElement) => x.hasAttribute('data-semantic-role'), (x: HTMLElement) => x.getAttribute('data-semantic-role')), - prefixtip: (doc: ExplorerMathDocument, node: HTMLElement, ...rest: any[]) => + infoPrefix: (doc: ExplorerMathDocument, node: HTMLElement, ...rest: any[]) => me.ValueHoverer.create(doc, doc.explorerRegions.tooltip3, node, (x: HTMLElement) => x.hasAttribute('data-semantic-prefix'), (x: HTMLElement) => x.getAttribute('data-semantic-prefix')), diff --git a/mathjax3-ts/ui/menu/Menu.ts b/mathjax3-ts/ui/menu/Menu.ts index 2984f6bfd..a7fb3bab1 100644 --- a/mathjax3-ts/ui/menu/Menu.ts +++ b/mathjax3-ts/ui/menu/Menu.ts @@ -66,21 +66,25 @@ export interface MenuSettings { ctrl: boolean; shift: boolean; scale: string; - explorer: boolean; - highlight: string; + autocollapse: boolean; + collapsible: boolean; + inTabOrder: boolean; + // A11y settings backgroundColor: string; + braille: boolean; + explorer: boolean; foregroundColor: string; + highlight: string; + infoPrefix: boolean; + infoRole: boolean; + infoType: boolean; + magnification: string; + magnify: string; speech: boolean; - subtitles: boolean; - braille: boolean; - viewbraille: boolean; speechrules: string; - magnify: string; - magnification: string; + subtitles: boolean; treecoloring: boolean; - autocollapse: boolean; - collapsible: boolean; - inTabOrder: boolean; + viewbraille: boolean; } export type HTMLMATHITEM = MathItem; @@ -113,22 +117,10 @@ export class Menu { ctrl: false, shift: false, scale: 1, - // A11y options - explorer: false, - highlight: 'None', - backgroundColor: 'Blue', - foregroundColor: 'Black', - speech: true, - subtitles: false, - braille: true, - viewbraille: false, - speechrules: 'mathspeak-default', - magnification: 'None', - magnify: false, - treecoloring: false, autocollapse: false, collapsible: false, - inTabOrder: true, + inTabOrder: true + explorer: false, }, jax: { CHTML: null, @@ -418,6 +410,12 @@ export class Menu { this.setA11y({'magnify': magnify})), this.variable('treecoloring', (treecoloring: boolean) => this.setA11y({'treecoloring': treecoloring})), + this.variable('infoType', (infoType: boolean) => + this.setA11y({'infoType': infoType})), + this.variable('infoRole', (infoRole: boolean) => + this.setA11y({'infoRole': infoRole})), + this.variable('infoPrefix', (infoPrefix: boolean) => + this.setA11y({'infoPrefix': infoPrefix})), this.variable('autocollapse'), this.variable('collapsible', (collapse: boolean) => this.setCollapsible(collapse)), this.variable('inTabOrder', (tab: boolean) => this.setTabOrder(tab)) @@ -507,9 +505,9 @@ export class Menu { ]) ]), this.submenu('Semantic Info', 'Semantic Info', [ - // this.checkbox('Type', 'Type', 'type'), - // this.checkbox('Role', 'Role', 'role'), - // this.checkbox('Prefix', 'Prefix', 'prefix'), + this.checkbox('Type', 'Type', 'infoType'), + this.checkbox('Role', 'Role', 'infoRole'), + this.checkbox('Prefix', 'Prefix', 'infoPrefix') ], true), this.rule(), this.checkbox('Collapsible', 'Collapsible Math', 'collapsible'), @@ -602,7 +600,9 @@ export class Menu { * Save any non-default menu settings in localStorage */ protected saveUserSettings() { + console.log('Saving user settings'); const settings = {} as {[key: string]: any}; + console.log(this.defaultSettings); for (const name of Object.keys(this.settings) as (keyof MenuSettings)[]) { if (this.settings[name] !== this.defaultSettings[name]) { settings[name] = this.settings[name]; From 3abf9ec49283e6ede9b7ed1802e3c2851bff2437 Mon Sep 17 00:00:00 2001 From: zorkow Date: Wed, 3 Jul 2019 12:30:39 +0100 Subject: [PATCH 10/12] Uses activation for tree explorers. --- mathjax3-ts/a11y/explorer/Explorer.ts | 1 - mathjax3-ts/a11y/explorer/TreeExplorer.ts | 26 ++++++++++++++++++----- mathjax3-ts/ui/menu/Menu.ts | 5 ++--- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/mathjax3-ts/a11y/explorer/Explorer.ts b/mathjax3-ts/a11y/explorer/Explorer.ts index fcfa8ffb8..38939b9a7 100644 --- a/mathjax3-ts/a11y/explorer/Explorer.ts +++ b/mathjax3-ts/a11y/explorer/Explorer.ts @@ -155,7 +155,6 @@ export class AbstractExplorer implements Explorer { region: Region, node: HTMLElement, ...rest: any[]): Explorer { let explorer = new this(document, region, node, ...rest); - explorer.Attach(); return explorer; } diff --git a/mathjax3-ts/a11y/explorer/TreeExplorer.ts b/mathjax3-ts/a11y/explorer/TreeExplorer.ts index b8fe2c2f7..284543f02 100644 --- a/mathjax3-ts/a11y/explorer/TreeExplorer.ts +++ b/mathjax3-ts/a11y/explorer/TreeExplorer.ts @@ -44,7 +44,6 @@ export class AbstractTreeExplorer extends AbstractExplorer { protected node: HTMLElement, protected mml: HTMLElement) { super(document, null, node); - this.Start(); } /** @@ -52,15 +51,22 @@ export class AbstractTreeExplorer extends AbstractExplorer { */ readonly stoppable = false; + /** * @override */ - public AddEvents() { } + public Attach() { + super.Attach(); + this.Start(); + } /** * @override */ - public RemoveEvents() { } + public Detach() { + this.Stop(); + super.Detach(); + } } @@ -68,11 +74,16 @@ export class AbstractTreeExplorer extends AbstractExplorer { export class FlameColorer extends AbstractTreeExplorer { public Start() { + if (this.active) return; + this.active = true; this.highlighter.highlightAll(this.node); } public Stop() { - this.highlighter.unhighlightAll(this.node); + if (this.active) { + this.highlighter.unhighlightAll(this.node); + } + this.active = false; } } @@ -84,6 +95,8 @@ export class TreeColorer extends AbstractTreeExplorer { * @override */ public Start() { + if (this.active) return; + this.active = true; let generator = sre.SpeechGeneratorFactory.generator('Color'); if (!this.node.hasAttribute('hasforegroundcolor')) { generator.generateSpeech(this.node, this.mml); @@ -96,7 +109,10 @@ export class TreeColorer extends AbstractTreeExplorer { * @override */ public Stop() { - this.highlighter.uncolorizeAll(this.node); + if (this.active) { + this.highlighter.uncolorizeAll(this.node); + } + this.active = false; } } diff --git a/mathjax3-ts/ui/menu/Menu.ts b/mathjax3-ts/ui/menu/Menu.ts index a7fb3bab1..029583ead 100644 --- a/mathjax3-ts/ui/menu/Menu.ts +++ b/mathjax3-ts/ui/menu/Menu.ts @@ -389,7 +389,8 @@ export class Menu { this.variable('shift'), this.variable ('scale', (scale: string) => this.setScale(scale)), this.variable('explorer', (explore: boolean) => this.setExplorer(explore)), - this.variable ('highlight'), + this.variable ('highlight', (highlight: string) => + this.setA11y({'highlight': highlight})), this.variable ('backgroundColor', (background: string) => this.setA11y({'backgroundColor': background})), this.variable ('foregroundColor', (foreground: string) => @@ -600,9 +601,7 @@ export class Menu { * Save any non-default menu settings in localStorage */ protected saveUserSettings() { - console.log('Saving user settings'); const settings = {} as {[key: string]: any}; - console.log(this.defaultSettings); for (const name of Object.keys(this.settings) as (keyof MenuSettings)[]) { if (this.settings[name] !== this.defaultSettings[name]) { settings[name] = this.settings[name]; From b7c93df7a5493d4c4674ab7fcf5ed168e0edcf8c Mon Sep 17 00:00:00 2001 From: zorkow Date: Wed, 3 Jul 2019 12:49:43 +0100 Subject: [PATCH 11/12] Integrates magnify variable for hover region. --- mathjax3-ts/a11y/explorer.ts | 4 +++- mathjax3-ts/a11y/explorer/Region.ts | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/mathjax3-ts/a11y/explorer.ts b/mathjax3-ts/a11y/explorer.ts index 75dc43056..566673002 100644 --- a/mathjax3-ts/a11y/explorer.ts +++ b/mathjax3-ts/a11y/explorer.ts @@ -487,7 +487,9 @@ export function setA11yOption(document: HTMLDOCUMENT, option: string, value: str break; } break; - // TODO: magnify, similar to zscale. + case 'magnify': + document.options.a11y.magnify = parseFloat(value as string); + break; default: document.options.a11y[option] = value; } diff --git a/mathjax3-ts/a11y/explorer/Region.ts b/mathjax3-ts/a11y/explorer/Region.ts index 12180abfd..6f5f1b5bf 100644 --- a/mathjax3-ts/a11y/explorer/Region.ts +++ b/mathjax3-ts/a11y/explorer/Region.ts @@ -376,7 +376,6 @@ export class HoverRegion extends AbstractRegion { */ constructor(public document: A11yDocument) { super(document); - this.div.style.fontSize = document.options.a11y.magnify + '%'; this.inner.style.lineHeight = '0'; } @@ -430,6 +429,7 @@ export class HoverRegion extends AbstractRegion { * @override */ public Show(node: HTMLElement, highlighter: sre.Highlighter) { + this.div.style.fontSize = this.document.options.a11y.magnify + '%'; this.Update(node); super.Show(node, highlighter); } From e1b8e77b386514120c7b1cb075f7c691016afd8b Mon Sep 17 00:00:00 2001 From: zorkow Date: Wed, 3 Jul 2019 13:31:54 +0100 Subject: [PATCH 12/12] Adds comments and lints. --- mathjax3-ts/a11y/explorer.ts | 29 +++++++++++++++-------- mathjax3-ts/a11y/explorer/TreeExplorer.ts | 14 +++++++---- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/mathjax3-ts/a11y/explorer.ts b/mathjax3-ts/a11y/explorer.ts index 31ca860f5..562837d73 100644 --- a/mathjax3-ts/a11y/explorer.ts +++ b/mathjax3-ts/a11y/explorer.ts @@ -125,14 +125,16 @@ export function ExplorerMathItemMixin>( this.savedId = null; } // Init explorers: - // Make these part of the explorer. this.explorers = initExplorers(document, node, mml); this.attachExplorers(document); - // Attach explorers, returns the ones that need to be reactivated. this.state(STATE.EXPLORER); } - + /** + * Attaches the explorers that are currently meant to be active given + * the document options. Detaches all others. + * @param {ExplorerMathDocument} document The current document. + */ public attachExplorers(document: ExplorerMathDocument) { this.attached = []; for (let key of Object.keys(this.explorers)) { @@ -147,7 +149,6 @@ export function ExplorerMathItemMixin>( this.addExplorers(this.attached); } - /** * @override */ @@ -173,7 +174,6 @@ export function ExplorerMathItemMixin>( this.refocus = this.restart = false; } - /** * Adds a list of explorers and makes sure the right one stops propagating. * @param {Explorer[]} explorers The active explorers to be added. @@ -331,7 +331,7 @@ export function ExplorerHandler(handler: HANDLER, MmlJax: MATHML = null) { /*==========================================================================*/ /** - * The objects needed for the explorer + * The regions objects needed for the explorers. */ export type ExplorerRegions = { speechRegion?: LiveRegion, @@ -343,6 +343,10 @@ export type ExplorerRegions = { } +/** + * Initializes the regions needed for a document. + * @param {ExplorerMathDocument} document The current document. + */ function initExplorerRegions(document: ExplorerMathDocument) { return { speechRegion: new LiveRegion(document), @@ -355,9 +359,11 @@ function initExplorerRegions(document: ExplorerMathDocument) { } -// Each explorer has a name, an option and a region associated. - +/** + * Type of explorer initialization methods. + * @type {(ExplorerMathDocument, HTMLElement, any[]): Explorer} +*/ type ExplorerInit = (doc: ExplorerMathDocument, node: HTMLElement, ...rest: any[]) => Explorer; @@ -401,7 +407,6 @@ let allExplorers: {[options: string]: ExplorerInit} = { me.ValueHoverer.create(doc, doc.explorerRegions.tooltip3, node, (x: HTMLElement) => x.hasAttribute('data-semantic-prefix'), (x: HTMLElement) => x.getAttribute('data-semantic-prefix')), - // Missing: FlameHighlighter, TreeHighlighter flame: (doc: ExplorerMathDocument, node: HTMLElement, ...rest: any[]) => FlameColorer.create(doc, null, node), treecoloring: (doc: ExplorerMathDocument, node: HTMLElement, ...rest: any[]) => @@ -427,7 +432,11 @@ function initExplorers(document: ExplorerMathDocument, node: HTMLElement, mml: s /* Context Menu Interactions */ - +/** + * Sets a list of a11y options for a given document. + * @param {HTMLDOCUMENT} document The current document. + * @param {{[key: string]: any}} options Association list for a11y option value pairs. + */ export function setA11yOptions(document: HTMLDOCUMENT, options: {[key: string]: any}) { for (let key in options) { if (document.options.a11y[key] !== undefined) { diff --git a/mathjax3-ts/a11y/explorer/TreeExplorer.ts b/mathjax3-ts/a11y/explorer/TreeExplorer.ts index 284543f02..cab819a2d 100644 --- a/mathjax3-ts/a11y/explorer/TreeExplorer.ts +++ b/mathjax3-ts/a11y/explorer/TreeExplorer.ts @@ -30,12 +30,12 @@ import {sreReady} from '../sre.js'; export interface TreeExplorer extends Explorer { - + } export class AbstractTreeExplorer extends AbstractExplorer { - + /** * @override */ @@ -67,25 +67,31 @@ export class AbstractTreeExplorer extends AbstractExplorer { this.Stop(); super.Detach(); } - + } export class FlameColorer extends AbstractTreeExplorer { + /** + * @override + */ public Start() { if (this.active) return; this.active = true; this.highlighter.highlightAll(this.node); } + /** + * @override + */ public Stop() { if (this.active) { this.highlighter.unhighlightAll(this.node); } this.active = false; } - + }