1
1
/* *
2
2
*
3
- * (c) 2009-2020 Øystein Moseng
3
+ * (c) 2009-2021 Øystein Moseng
4
4
*
5
5
* Accessibility component for chart info region and table.
6
6
*
11
11
* */
12
12
import H from '../../Core/Globals.js' ;
13
13
var doc = H . doc ;
14
+ import AST from '../../Core/Renderer/HTML/AST.js' ;
14
15
import U from '../../Core/Utilities.js' ;
15
16
var extend = U . extend , format = U . format , pick = U . pick ;
16
17
import AccessibilityComponent from '../AccessibilityComponent.js' ;
17
18
import Announcer from '../Utils/Announcer.js' ;
18
19
import AnnotationsA11y from './AnnotationsA11y.js' ;
19
20
var getAnnotationsInfoHTML = AnnotationsA11y . getAnnotationsInfoHTML ;
20
21
import ChartUtilities from '../Utils/ChartUtilities.js' ;
21
- var unhideChartElementFromAT = ChartUtilities . unhideChartElementFromAT , getChartTitle = ChartUtilities . getChartTitle , getAxisDescription = ChartUtilities . getAxisDescription ;
22
+ var getAxisDescription = ChartUtilities . getAxisDescription , getAxisRangeDescription = ChartUtilities . getAxisRangeDescription , getChartTitle = ChartUtilities . getChartTitle , unhideChartElementFromAT = ChartUtilities . unhideChartElementFromAT ;
22
23
import HTMLUtilities from '../Utils/HTMLUtilities.js' ;
23
24
var addClass = HTMLUtilities . addClass , setElAttrs = HTMLUtilities . setElAttrs , escapeStringForHTML = HTMLUtilities . escapeStringForHTML , stripHTMLTagsFromString = HTMLUtilities . stripHTMLTagsFromString , getElement = HTMLUtilities . getElement , visuallyHideElement = HTMLUtilities . visuallyHideElement ;
24
25
/* eslint-disable no-invalid-this, valid-jsdoc */
26
+ /**
27
+ * @private
28
+ */
29
+ function stripEmptyHTMLTags ( str ) {
30
+ return str . replace ( / < ( \w + ) [ ^ > ] * ?> \s * < \/ \1> / g, '' ) ;
31
+ }
25
32
/**
26
33
* @private
27
34
*/
@@ -56,27 +63,6 @@ function buildTypeDescriptionFromSeries(chart, types, context) {
56
63
function getTableSummary ( chart ) {
57
64
return chart . langFormat ( 'accessibility.table.tableSummary' , { chart : chart } ) ;
58
65
}
59
- /**
60
- * @private
61
- */
62
- function stripEmptyHTMLTags ( str ) {
63
- return str . replace ( / < ( \w + ) [ ^ > ] * ?> \s * < \/ \1> / g, '' ) ;
64
- }
65
- /**
66
- * @private
67
- */
68
- function enableSimpleHTML ( str ) {
69
- return str
70
- . replace ( / & l t ; ( h [ 1 - 7 ] | p | d i v | u l | o l | l i ) & g t ; / g, '<$1>' )
71
- . replace ( / & l t ; & # x 2 F ; ( h [ 1 - 7 ] | p | d i v | u l | o l | l i | a | b u t t o n ) & g t ; / g, '</$1>' )
72
- . replace ( / & l t ; ( d i v | a | b u t t o n ) i d = & q u o t ; ( [ a - z A - Z \- 0 - 9 # ] * ?) & q u o t ; & g t ; / g, '<$1 id="$2">' ) ;
73
- }
74
- /**
75
- * @private
76
- */
77
- function stringToSimpleHTML ( str ) {
78
- return stripEmptyHTMLTags ( enableSimpleHTML ( escapeStringForHTML ( str ) ) ) ;
79
- }
80
66
/**
81
67
* Return simplified explaination of chart type. Some types will not be familiar
82
68
* to most users, but in those cases we try to add an explaination of the type.
@@ -122,7 +108,7 @@ extend(InfoRegionsComponent.prototype, /** @lends Highcharts.InfoRegionsComponen
122
108
var chart = this . chart ;
123
109
var component = this ;
124
110
this . initRegionsDefinitions ( ) ;
125
- this . addEvent ( chart , 'afterGetTable ' , function ( e ) {
111
+ this . addEvent ( chart , 'aftergetTableAST ' , function ( e ) {
126
112
component . onDataTableCreated ( e ) ;
127
113
} ) ;
128
114
this . addEvent ( chart , 'afterViewData' , function ( tableDiv ) {
@@ -219,7 +205,7 @@ extend(InfoRegionsComponent.prototype, /** @lends Highcharts.InfoRegionsComponen
219
205
updateScreenReaderSection : function ( regionKey ) {
220
206
var chart = this . chart , region = this . screenReaderSections [ regionKey ] , content = region . buildContent ( chart ) , sectionDiv = region . element = ( region . element || this . createElement ( 'div' ) ) , hiddenDiv = ( sectionDiv . firstChild || this . createElement ( 'div' ) ) ;
221
207
this . setScreenReaderSectionAttribs ( sectionDiv , regionKey ) ;
222
- hiddenDiv . innerHTML = content ;
208
+ AST . setElementHTML ( hiddenDiv , content ) ;
223
209
sectionDiv . appendChild ( hiddenDiv ) ;
224
210
region . insertIntoDOM ( sectionDiv , chart ) ;
225
211
visuallyHideElement ( hiddenDiv ) ;
@@ -273,7 +259,7 @@ extend(InfoRegionsComponent.prototype, /** @lends Highcharts.InfoRegionsComponen
273
259
} , formattedString = H . i18nFormat ( format , context , chart ) ;
274
260
this . dataTableButtonId = dataTableButtonId ;
275
261
this . sonifyButtonId = sonifyButtonId ;
276
- return stringToSimpleHTML ( formattedString ) ;
262
+ return stripEmptyHTMLTags ( formattedString ) ;
277
263
} ,
278
264
/**
279
265
* @private
@@ -284,7 +270,7 @@ extend(InfoRegionsComponent.prototype, /** @lends Highcharts.InfoRegionsComponen
284
270
. screenReaderSection . afterChartFormat , context = {
285
271
endOfChartMarker : this . getEndOfChartMarkerText ( )
286
272
} , formattedString = H . i18nFormat ( format , context , chart ) ;
287
- return stringToSimpleHTML ( formattedString ) ;
273
+ return stripEmptyHTMLTags ( formattedString ) ;
288
274
} ,
289
275
/**
290
276
* @private
@@ -364,7 +350,10 @@ extend(InfoRegionsComponent.prototype, /** @lends Highcharts.InfoRegionsComponen
364
350
if ( this . viewDataTableButton ) {
365
351
this . viewDataTableButton . setAttribute ( 'aria-expanded' , 'true' ) ;
366
352
}
367
- e . html = e . html . replace ( '<table ' , '<table tabindex="-1" summary="' + getTableSummary ( chart ) + '"' ) ;
353
+ var attributes = e . tree . attributes || { } ;
354
+ attributes . tabindex = - 1 ;
355
+ attributes . summary = getTableSummary ( chart ) ;
356
+ e . tree . attributes = attributes ;
368
357
}
369
358
} ,
370
359
/**
@@ -455,102 +444,19 @@ extend(InfoRegionsComponent.prototype, /** @lends Highcharts.InfoRegionsComponen
455
444
* @return {string }
456
445
*/
457
446
getAxisDescriptionText : function ( collectionKey ) {
458
- var component = this , chart = this . chart , axes = chart [ collectionKey ] ;
447
+ var chart = this . chart ;
448
+ var axes = chart [ collectionKey ] ;
459
449
return chart . langFormat ( 'accessibility.axis.' + collectionKey + 'Description' + ( axes . length > 1 ? 'Plural' : 'Singular' ) , {
460
450
chart : chart ,
461
451
names : axes . map ( function ( axis ) {
462
452
return getAxisDescription ( axis ) ;
463
453
} ) ,
464
454
ranges : axes . map ( function ( axis ) {
465
- return component . getAxisRangeDescription ( axis ) ;
455
+ return getAxisRangeDescription ( axis ) ;
466
456
} ) ,
467
457
numAxes : axes . length
468
458
} ) ;
469
459
} ,
470
- /**
471
- * Return string with text description of the axis range.
472
- * @private
473
- * @param {Highcharts.Axis } axis The axis to get range desc of.
474
- * @return {string } A string with the range description for the axis.
475
- */
476
- getAxisRangeDescription : function ( axis ) {
477
- var axisOptions = axis . options || { } ;
478
- // Handle overridden range description
479
- if ( axisOptions . accessibility &&
480
- typeof axisOptions . accessibility . rangeDescription !== 'undefined' ) {
481
- return axisOptions . accessibility . rangeDescription ;
482
- }
483
- // Handle category axes
484
- if ( axis . categories ) {
485
- return this . getCategoryAxisRangeDesc ( axis ) ;
486
- }
487
- // Use time range, not from-to?
488
- if ( axis . dateTime && ( axis . min === 0 || axis . dataMin === 0 ) ) {
489
- return this . getAxisTimeLengthDesc ( axis ) ;
490
- }
491
- // Just use from and to.
492
- // We have the range and the unit to use, find the desc format
493
- return this . getAxisFromToDescription ( axis ) ;
494
- } ,
495
- /**
496
- * @private
497
- * @param {Highcharts.Axis } axis
498
- * @return {string }
499
- */
500
- getCategoryAxisRangeDesc : function ( axis ) {
501
- var chart = this . chart ;
502
- if ( axis . dataMax && axis . dataMin ) {
503
- return chart . langFormat ( 'accessibility.axis.rangeCategories' , {
504
- chart : chart ,
505
- axis : axis ,
506
- numCategories : axis . dataMax - axis . dataMin + 1
507
- } ) ;
508
- }
509
- return '' ;
510
- } ,
511
- /**
512
- * @private
513
- * @param {Highcharts.Axis } axis
514
- * @return {string }
515
- */
516
- getAxisTimeLengthDesc : function ( axis ) {
517
- var chart = this . chart , range = { } , rangeUnit = 'Seconds' ;
518
- range . Seconds = ( ( axis . max || 0 ) - ( axis . min || 0 ) ) / 1000 ;
519
- range . Minutes = range . Seconds / 60 ;
520
- range . Hours = range . Minutes / 60 ;
521
- range . Days = range . Hours / 24 ;
522
- [ 'Minutes' , 'Hours' , 'Days' ] . forEach ( function ( unit ) {
523
- if ( range [ unit ] > 2 ) {
524
- rangeUnit = unit ;
525
- }
526
- } ) ;
527
- var rangeValue = range [ rangeUnit ] . toFixed ( rangeUnit !== 'Seconds' &&
528
- rangeUnit !== 'Minutes' ? 1 : 0 // Use decimals for days/hours
529
- ) ;
530
- // We have the range and the unit to use, find the desc format
531
- return chart . langFormat ( 'accessibility.axis.timeRange' + rangeUnit , {
532
- chart : chart ,
533
- axis : axis ,
534
- range : rangeValue . replace ( '.0' , '' )
535
- } ) ;
536
- } ,
537
- /**
538
- * @private
539
- * @param {Highcharts.Axis } axis
540
- * @return {string }
541
- */
542
- getAxisFromToDescription : function ( axis ) {
543
- var chart = this . chart , dateRangeFormat = chart . options . accessibility
544
- . screenReaderSection . axisRangeDateFormat , format = function ( axisKey ) {
545
- return axis . dateTime ? chart . time . dateFormat ( dateRangeFormat , axis [ axisKey ] ) : axis [ axisKey ] ;
546
- } ;
547
- return chart . langFormat ( 'accessibility.axis.rangeFromTo' , {
548
- chart : chart ,
549
- axis : axis ,
550
- rangeFrom : format ( 'min' ) ,
551
- rangeTo : format ( 'max' )
552
- } ) ;
553
- } ,
554
460
/**
555
461
* Remove component traces
556
462
*/
0 commit comments