aria-api 0.4.7 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/aria.js CHANGED
@@ -19,13 +19,13 @@ module.exports = {
19
19
  };
20
20
 
21
21
  },{"./lib/atree.js":2,"./lib/name.js":5,"./lib/query.js":6}],2:[function(require,module,exports){
22
- var attrs = require('./attrs');
22
+ const attrs = require('./attrs');
23
23
 
24
- var _getOwner = function(node, owners) {
24
+ const _getOwner = function(node, owners) {
25
25
  if (node.nodeType === node.ELEMENT_NODE && node.id) {
26
- var selector = '[aria-owns~="' + CSS.escape(node.id) + '"]';
26
+ const selector = '[aria-owns~="' + CSS.escape(node.id) + '"]';
27
27
  if (owners) {
28
- for (var owner of owners) {
28
+ for (const owner of owners) {
29
29
  if (owner.matches(selector)) {
30
30
  return owner;
31
31
  }
@@ -36,12 +36,12 @@ var _getOwner = function(node, owners) {
36
36
  }
37
37
  };
38
38
 
39
- var _getParentNode = function(node, owners) {
39
+ const _getParentNode = function(node, owners) {
40
40
  return _getOwner(node, owners) || node.parentNode;
41
41
  };
42
42
 
43
- var detectLoop = function(node, owners) {
44
- var seen = [node];
43
+ const detectLoop = function(node, owners) {
44
+ const seen = [node];
45
45
  while ((node = _getParentNode(node, owners))) {
46
46
  if (seen.includes(node)) {
47
47
  return true;
@@ -50,35 +50,35 @@ var detectLoop = function(node, owners) {
50
50
  }
51
51
  };
52
52
 
53
- var getOwner = function(node, owners) {
54
- var owner = _getOwner(node, owners);
53
+ const getOwner = function(node, owners) {
54
+ const owner = _getOwner(node, owners);
55
55
  if (owner && !detectLoop(node, owners)) {
56
56
  return owner;
57
57
  }
58
58
  };
59
59
 
60
- var getParentNode = function(node, owners) {
60
+ const getParentNode = function(node, owners) {
61
61
  return getOwner(node, owners) || node.parentNode;
62
62
  };
63
63
 
64
- var isHidden = function(node) {
64
+ const isHidden = function(node) {
65
65
  return node.nodeType === node.ELEMENT_NODE && attrs.getAttribute(node, 'hidden');
66
66
  };
67
67
 
68
- var getChildNodes = function(node, owners) {
69
- var childNodes = [];
68
+ const getChildNodes = function(node, owners) {
69
+ const childNodes = [];
70
70
 
71
- for (var i = 0; i < node.childNodes.length; i++) {
72
- var child = node.childNodes[i];
71
+ for (let i = 0; i < node.childNodes.length; i++) {
72
+ const child = node.childNodes[i];
73
73
  if (!getOwner(child, owners) && !isHidden(child)) {
74
74
  childNodes.push(child);
75
75
  }
76
76
  }
77
77
 
78
78
  if (node.nodeType === node.ELEMENT_NODE) {
79
- var owns = attrs.getAttribute(node, 'owns') || [];
80
- for (var i = 0; i < owns.length; i++) {
81
- var child = document.getElementById(owns[i]);
79
+ const owns = attrs.getAttribute(node, 'owns') || [];
80
+ for (let i = 0; i < owns.length; i++) {
81
+ const child = document.getElementById(owns[i]);
82
82
  // double check with getOwner for consistency
83
83
  if (child && getOwner(child, owners) === node && !isHidden(child)) {
84
84
  childNodes.push(child);
@@ -89,18 +89,18 @@ var getChildNodes = function(node, owners) {
89
89
  return childNodes;
90
90
  };
91
91
 
92
- var walk = function(root, fn) {
93
- var owners = document.querySelectorAll('[aria-owns]');
94
- var queue = [root];
92
+ const walk = function(root, fn) {
93
+ const owners = document.querySelectorAll('[aria-owns]');
94
+ let queue = [root];
95
95
  while (queue.length) {
96
- var item = queue.shift();
96
+ const item = queue.shift();
97
97
  fn(item);
98
98
  queue = getChildNodes(item, owners).concat(queue);
99
99
  }
100
100
  };
101
101
 
102
- var searchUp = function(node, test) {
103
- var candidate = getParentNode(node);
102
+ const searchUp = function(node, test) {
103
+ const candidate = getParentNode(node);
104
104
  if (candidate) {
105
105
  if (test(candidate)) {
106
106
  return candidate;
@@ -118,40 +118,59 @@ module.exports = {
118
118
  };
119
119
 
120
120
  },{"./attrs":3}],3:[function(require,module,exports){
121
- var constants = require('./constants.js');
121
+ const constants = require('./constants.js');
122
+
123
+ var unique = function(arr) {
124
+ return arr.filter((a, i) => arr.indexOf(a) === i);
125
+ };
126
+
127
+ var flatten = function(arr) {
128
+ return [].concat.apply([], arr);
129
+ };
130
+
131
+ var normalizeRoles = function(roles, includeAbstract) {
132
+ return unique(roles
133
+ .map(r => constants.aliases[r] || r)
134
+ .filter(r => constants.roles[r])
135
+ .filter(r => includeAbstract || !constants.roles[r].abstract)
136
+ );
137
+ };
122
138
 
123
139
  // candidates can be passed for performance optimization
124
- var getRole = function(el, candidates) {
125
- if (el.hasAttribute('role')) {
126
- var role = el.getAttribute('role');
127
- if (!candidates || candidates.includes(role)) {
128
- return role;
129
- } else {
130
- return;
140
+ const getRole = function(el, candidates) {
141
+ // TODO: filter out any invalid roles (e.g. name or context required)
142
+ const roles = normalizeRoles(
143
+ (el.getAttribute('role') || '').toLowerCase().split(/\s+/)
144
+ );
145
+
146
+ if (roles.length > 1 && candidates) {
147
+ return [roles, candidates];
148
+ } else if (roles.length) {
149
+ for (const role of roles) {
150
+ if (!candidates || candidates.includes(role)) {
151
+ return role;
152
+ }
131
153
  }
132
- }
133
- var roles = candidates ? candidates : Object.keys(constants.roles);
134
- for (var role of roles) {
135
- var r = constants.roles[role];
136
- if (r) {
137
- var selector = (r.selectors || []).join(',');
138
- if (selector && el.matches(selector)) {
154
+ } else {
155
+ for (const role of (candidates || Object.keys(constants.roles))) {
156
+ const r = constants.roles[role];
157
+ if (!r.abstract && r.selectors && el.matches(r.selectors.join(','))) {
139
158
  return role;
140
159
  }
141
160
  }
142
161
  }
143
162
  };
144
163
 
145
- var hasRole = function(el, roles) {
146
- var candidates = [].concat.apply([], roles.map(role => {
147
- return (constants.roles[role] || {}).subRoles || [role];
148
- }));
149
- return !!getRole(el, candidates);
164
+ const hasRole = function(el, roles) {
165
+ const subRoles = normalizeRoles(roles, true).map(role => {
166
+ return constants.roles[role].subRoles || [role];
167
+ });
168
+ return !!getRole(el, unique(flatten(subRoles)));
150
169
  };
151
170
 
152
- var getAttribute = function(el, key) {
171
+ const getAttribute = function(el, key) {
153
172
  if (constants.attributeStrongMapping.hasOwnProperty(key)) {
154
- var value = el[constants.attributeStrongMapping[key]];
173
+ const value = el[constants.attributeStrongMapping[key]];
155
174
  if (value) {
156
175
  return value;
157
176
  }
@@ -168,14 +187,14 @@ var getAttribute = function(el, key) {
168
187
  if (el.matches('details:not([open]) > :not(summary)')) {
169
188
  return true;
170
189
  }
171
- var style = window.getComputedStyle(el);
190
+ const style = window.getComputedStyle(el);
172
191
  if (style.display === 'none' || style.visibility === 'hidden') {
173
192
  return true;
174
193
  }
175
194
  }
176
195
 
177
- var type = constants.attributes[key];
178
- var raw = el.getAttribute('aria-' + key);
196
+ const type = constants.attributes[key];
197
+ const raw = el.getAttribute('aria-' + key);
179
198
 
180
199
  if (raw) {
181
200
  if (type === 'bool') {
@@ -204,7 +223,7 @@ var getAttribute = function(el, key) {
204
223
  // list -> aria-controls
205
224
 
206
225
  if (key === 'level') {
207
- for (var i = 1; i <= 6; i++) {
226
+ for (let i = 1; i <= 6; i++) {
208
227
  if (el.tagName.toLowerCase() === 'h' + i) {
209
228
  return i;
210
229
  }
@@ -214,8 +233,8 @@ var getAttribute = function(el, key) {
214
233
  }
215
234
 
216
235
  if (key in constants.attrsWithDefaults) {
217
- var role = getRole(el);
218
- var defaults = (constants.roles[role] || {}).defaults;
236
+ const role = getRole(el);
237
+ const defaults = constants.roles[role].defaults;
219
238
  if (defaults && defaults.hasOwnProperty(key)) {
220
239
  return defaults[key];
221
240
  }
@@ -301,13 +320,8 @@ exports.attributeWeakMapping = {
301
320
  'selected': 'selected',
302
321
  };
303
322
 
304
- var scoped = [
305
- 'main *',
306
- // https://www.w3.org/TR/html/dom.html#sectioning-content-2
307
- 'article *', 'aside *', 'nav *', 'section *',
308
- // https://www.w3.org/TR/html/sections.html#sectioning-roots
309
- 'blockquote *', 'details *', 'dialog *', 'fieldset *', 'figure *', 'td *',
310
- ].join(',');
323
+ // https://www.w3.org/TR/html/dom.html#sectioning-content-2
324
+ const scoped = ['article *', 'aside *', 'nav *', 'section *'].join(',');
311
325
 
312
326
  // https://www.w3.org/TR/html-aam-1.0/#html-element-role-mappings
313
327
  // https://www.w3.org/TR/wai-aria/roles
@@ -319,11 +333,16 @@ exports.roles = {
319
333
  'atomic': true,
320
334
  },
321
335
  },
336
+ alertdialog: {},
337
+ application: {},
322
338
  article: {
323
339
  selectors: ['article'],
324
340
  },
325
341
  banner: {
326
- selectors: ['header:not(' + scoped + ')'],
342
+ selectors: [`header:not(main *, ${scoped})`],
343
+ },
344
+ blockquote: {
345
+ selectors: ['blockquote'],
327
346
  },
328
347
  button: {
329
348
  selectors: [
@@ -336,26 +355,32 @@ exports.roles = {
336
355
  ],
337
356
  nameFromContents: true,
338
357
  },
358
+ caption: {
359
+ selectors: ['caption', 'figcaption'],
360
+ },
339
361
  cell: {
340
- selectors: ['td'],
341
- childRoles: ['gridcell', 'rowheader'],
362
+ selectors: ['td', 'td ~ th:not([scope])'],
363
+ childRoles: ['columnheader', 'gridcell', 'rowheader'],
342
364
  nameFromContents: true,
343
365
  },
344
366
  checkbox: {
345
367
  selectors: ['input[type="checkbox"]'],
346
- childRoles: ['menuitemcheckbox', 'switch'],
368
+ childRoles: ['switch'],
347
369
  nameFromContents: true,
348
370
  defaults: {
349
371
  'checked': 'false',
350
372
  },
351
373
  },
374
+ code: {
375
+ selectors: ['code'],
376
+ },
352
377
  columnheader: {
353
378
  selectors: ['th[scope="col"]'],
354
379
  nameFromContents: true,
355
380
  },
356
381
  combobox: {
357
382
  selectors: [
358
- 'input:not([type])[list]',
383
+ 'input:not([type])[list]',
359
384
  'input[type="email"][list]',
360
385
  'input[type="search"][list]',
361
386
  'input[type="tel"][list]',
@@ -371,46 +396,131 @@ exports.roles = {
371
396
  },
372
397
  },
373
398
  command: {
399
+ abstract: true,
374
400
  childRoles: ['button', 'link', 'menuitem'],
375
401
  },
376
402
  complementary: {
377
- selectors: ['aside'],
403
+ selectors: [
404
+ `aside:not(${scoped})`,
405
+ 'aside[aria-label]',
406
+ 'aside[aria-labelledby]',
407
+ 'aside[title]',
408
+ ],
378
409
  },
379
410
  composite: {
411
+ abstract: true,
380
412
  childRoles: ['grid', 'select', 'spinbutton', 'tablist'],
381
413
  },
382
414
  contentinfo: {
383
- selectors: ['footer:not(' + scoped + ')'],
415
+ selectors: [`footer:not(main *, ${scoped})`],
384
416
  },
385
417
  definition: {
386
418
  selectors: ['dd'],
387
419
  },
420
+ deletion: {
421
+ selectors: ['del', 's'],
422
+ },
388
423
  dialog: {
389
424
  selectors: ['dialog'],
390
425
  childRoles: ['alertdialog'],
391
426
  },
427
+ 'doc-abstract': {},
428
+ 'doc-acknowledgments': {},
429
+ 'doc-afterword': {},
430
+ 'doc-appendix': {},
392
431
  'doc-backlink': {
393
432
  nameFromContents: true,
394
433
  },
434
+ 'doc-biblioentry': {},
435
+ 'doc-bibliography': {},
395
436
  'doc-biblioref': {
396
437
  nameFromContents: true,
397
438
  },
439
+ 'doc-chapter': {},
440
+ 'doc-colophon': {},
441
+ 'doc-conclusion': {},
442
+ 'doc-cover': {},
443
+ 'doc-credit': {},
444
+ 'doc-credits': {},
445
+ 'doc-dedication': {},
446
+ 'doc-endnote': {},
447
+ 'doc-endnotes': {},
448
+ 'doc-epilogue': {},
449
+ 'doc-epigraph': {},
450
+ 'doc-errata': {},
451
+ 'doc-example': {},
452
+ 'doc-footnote': {},
453
+ 'doc-foreword': {},
454
+ 'doc-glossary': {},
398
455
  'doc-glossref': {
399
456
  nameFromContents: true,
400
457
  },
458
+ 'doc-index': {},
459
+ 'doc-introduction': {},
401
460
  'doc-noteref': {
402
461
  nameFromContents: true,
403
462
  },
463
+ 'doc-notice': {},
464
+ 'doc-pagebreak': {
465
+ nameFromContents: true,
466
+ },
467
+ 'doc-pagefooter': {},
468
+ 'doc-pageheader': {},
469
+ 'doc-pagelist': {},
470
+ 'doc-part': {},
471
+ 'doc-preface': {},
472
+ 'doc-prologue': {},
473
+ 'doc-pullquote': {},
474
+ 'doc-qna': {},
475
+ 'doc-subtitle': {
476
+ nameFromContents: true,
477
+ },
478
+ 'doc-tip': {},
479
+ 'doc-toc': {},
404
480
  document: {
405
- selectors: ['body'],
481
+ selectors: ['html'],
406
482
  childRoles: ['article', 'graphics-document'],
407
483
  },
484
+ emphasis: {
485
+ selectors: ['em'],
486
+ },
487
+ feed: {},
408
488
  figure: {
409
489
  selectors: ['figure'],
490
+ childRoles: ['doc-example'],
410
491
  },
411
492
  form: {
412
493
  selectors: ['form[aria-label]', 'form[aria-labelledby]', 'form[title]'],
413
494
  },
495
+ generic: {
496
+ selectors: [
497
+ 'a:not([href])',
498
+ 'area:not([href])',
499
+ `aside:not(${scoped}):not([aria-label]):not([aria-labelledby]):not([title])`,
500
+ 'b',
501
+ 'bdi',
502
+ 'bdo',
503
+ 'body',
504
+ 'data',
505
+ 'div',
506
+ // footer scoped
507
+ // header scoped
508
+ 'i',
509
+ 'li:not(ul > li):not(ol > li)',
510
+ 'pre',
511
+ 'q',
512
+ 'samp',
513
+ 'section:not([aria-label]):not([aria-labelledby]):not([title])',
514
+ 'small',
515
+ 'span',
516
+ 'u',
517
+ ],
518
+ },
519
+ 'graphics-document': {
520
+ selectors: ['svg'],
521
+ },
522
+ 'graphics-object': {},
523
+ 'graphics-symbol': {},
414
524
  grid: {
415
525
  childRoles: ['treegrid'],
416
526
  },
@@ -419,7 +529,14 @@ exports.roles = {
419
529
  nameFromContents: true,
420
530
  },
421
531
  group: {
422
- selectors: ['details', 'optgroup'],
532
+ selectors: [
533
+ 'address',
534
+ 'details',
535
+ 'fieldset',
536
+ 'hgroup',
537
+ 'optgroup',
538
+ 'text',
539
+ ],
423
540
  childRoles: ['row', 'select', 'toolbar', 'graphics-object'],
424
541
  },
425
542
  heading: {
@@ -434,9 +551,22 @@ exports.roles = {
434
551
  childRoles: ['doc-cover'],
435
552
  },
436
553
  input: {
437
- childRoles: ['checkbox', 'option', 'radio', 'slider', 'spinbutton', 'textbox'],
554
+ abstract: true,
555
+ childRoles: [
556
+ 'checkbox',
557
+ 'combobox',
558
+ 'option',
559
+ 'radio',
560
+ 'slider',
561
+ 'spinbutton',
562
+ 'textbox',
563
+ ],
564
+ },
565
+ insertion: {
566
+ selectors: ['ins'],
438
567
  },
439
568
  landmark: {
569
+ abstract: true,
440
570
  childRoles: [
441
571
  'banner',
442
572
  'complementary',
@@ -465,16 +595,17 @@ exports.roles = {
465
595
  ],
466
596
  },
467
597
  link: {
468
- selectors: ['a[href]', 'area[href]', 'link[href]'],
598
+ selectors: ['a[href]', 'area[href]'],
469
599
  childRoles: ['doc-backlink', 'doc-biblioref', 'doc-glossref', 'doc-noteref'],
470
600
  nameFromContents: true,
471
601
  },
472
602
  list: {
473
- selectors: ['dl', 'ol', 'ul'],
474
- childRoles: ['directory', 'feed'],
603
+ selectors: ['dl', 'ol', 'ul', 'menu'],
604
+ childRoles: ['feed'],
475
605
  },
476
606
  listbox: {
477
607
  selectors: [
608
+ 'datalist',
478
609
  'select[multiple]',
479
610
  'select[size]:not([size="0"]):not([size="1"])',
480
611
  ],
@@ -483,7 +614,7 @@ exports.roles = {
483
614
  },
484
615
  },
485
616
  listitem: {
486
- selectors: ['dt', 'ul > li', 'ol > li'],
617
+ selectors: ['ol > li', 'ul > li'],
487
618
  childRoles: ['doc-biblioentry', 'doc-endnote', 'treeitem'],
488
619
  },
489
620
  log: {
@@ -494,11 +625,18 @@ exports.roles = {
494
625
  main: {
495
626
  selectors: ['main'],
496
627
  },
628
+ marquee: {},
497
629
  math: {
498
630
  selectors: ['math'],
499
631
  },
632
+ meter: {
633
+ selectors: ['meter'],
634
+ defaults: {
635
+ 'valuemin': 0,
636
+ 'valuemax': 100,
637
+ },
638
+ },
500
639
  menu: {
501
- selectors: ['menu[type="context"]'],
502
640
  childRoles: ['menubar'],
503
641
  defaults: {
504
642
  'orientation': 'vertical',
@@ -510,12 +648,10 @@ exports.roles = {
510
648
  },
511
649
  },
512
650
  menuitem: {
513
- selectors: ['menuitem[type="command"]'],
514
651
  childRoles: ['menuitemcheckbox'],
515
652
  nameFromContents: true,
516
653
  },
517
654
  menuitemcheckbox: {
518
- selectors: ['menuitem[type="checkbox"]'],
519
655
  childRoles: ['menuitemradio'],
520
656
  nameFromContents: true,
521
657
  defaults: {
@@ -523,7 +659,6 @@ exports.roles = {
523
659
  },
524
660
  },
525
661
  menuitemradio: {
526
- selectors: ['menuitem[type="radio"]'],
527
662
  nameFromContents: true,
528
663
  defaults: {
529
664
  'checked': 'false',
@@ -533,6 +668,9 @@ exports.roles = {
533
668
  selectors: ['nav'],
534
669
  childRoles: ['doc-index', 'doc-pagelist', 'doc-toc'],
535
670
  },
671
+ none: {
672
+ selectors: ['img[alt=""]'],
673
+ },
536
674
  note: {
537
675
  childRoles: ['doc-notice', 'doc-tip'],
538
676
  },
@@ -544,11 +682,15 @@ exports.roles = {
544
682
  'selected': 'false',
545
683
  },
546
684
  },
547
- presentation: {
548
- selectors: ['img[alt=""]'],
685
+ paragraph: {
686
+ selectors: ['p'],
549
687
  },
550
688
  progressbar: {
551
689
  selectors: ['progress'],
690
+ defaults: {
691
+ 'valuemin': 0,
692
+ 'valuemax': 100,
693
+ },
552
694
  },
553
695
  radio: {
554
696
  selectors: ['input[type="radio"]'],
@@ -558,13 +700,16 @@ exports.roles = {
558
700
  'checked': 'false',
559
701
  },
560
702
  },
703
+ radiogroup: {},
561
704
  range: {
562
- childRoles: ['progressbar', 'scrollbar', 'slider', 'spinbutton'],
705
+ abstract: true,
706
+ childRoles: ['meter', 'progressbar', 'scrollbar', 'slider', 'spinbutton'],
563
707
  },
564
708
  region: {
565
709
  selectors: ['section[aria-label]', 'section[aria-labelledby]', 'section[title]'],
566
710
  },
567
711
  roletype: {
712
+ abstract: true,
568
713
  childRoles: ['structure', 'widget', 'window'],
569
714
  },
570
715
  row: {
@@ -573,10 +718,9 @@ exports.roles = {
573
718
  },
574
719
  rowgroup: {
575
720
  selectors: ['tbody', 'thead', 'tfoot'],
576
- nameFromContents: true,
577
721
  },
578
722
  rowheader: {
579
- selectors: ['th[scope="row"]'],
723
+ selectors: ['th[scope="row"]', 'th:not([scope]):not(td ~ th)'],
580
724
  nameFromContents: true,
581
725
  },
582
726
  scrollbar: {
@@ -584,29 +728,39 @@ exports.roles = {
584
728
  'orientation': 'vertical',
585
729
  'valuemin': 0,
586
730
  'valuemax': 100,
587
- // FIXME: halfway between actual valuemin and valuemax
588
- 'valuenow': 50,
589
731
  },
590
732
  },
733
+ search: {
734
+ selectors: ['search'],
735
+ },
591
736
  searchbox: {
592
737
  selectors: ['input[type="search"]:not([list])'],
593
738
  },
594
739
  section: {
740
+ abstract: true,
595
741
  childRoles: [
596
742
  'alert',
743
+ 'blockquote',
744
+ 'caption',
597
745
  'cell',
746
+ 'code',
598
747
  'definition',
748
+ 'deletion',
599
749
  'doc-abstract',
600
750
  'doc-colophon',
601
751
  'doc-credit',
602
752
  'doc-dedication',
603
753
  'doc-epigraph',
604
- 'doc-example',
605
754
  'doc-footnote',
755
+ 'doc-pagefooter',
756
+ 'doc-pageheader',
757
+ 'doc-pullquote',
606
758
  'doc-qna',
759
+ 'emphasis',
607
760
  'figure',
608
761
  'group',
609
762
  'img',
763
+ 'insertion',
610
764
  'landmark',
611
765
  'list',
612
766
  'listitem',
@@ -614,14 +768,20 @@ exports.roles = {
614
768
  'marquee',
615
769
  'math',
616
770
  'note',
771
+ 'paragraph',
617
772
  'status',
773
+ 'strong',
774
+ 'subscript',
775
+ 'superscript',
618
776
  'table',
619
777
  'tabpanel',
620
778
  'term',
779
+ 'time',
621
780
  'tooltip',
622
781
  ],
623
782
  },
624
783
  sectionhead: {
784
+ abstract: true,
625
785
  childRoles: [
626
786
  'columnheader',
627
787
  'doc-subtitle',
@@ -632,7 +792,8 @@ exports.roles = {
632
792
  nameFromContents: true,
633
793
  },
634
794
  select: {
635
- childRoles: ['combobox', 'listbox', 'menu', 'radiogroup', 'tree'],
795
+ abstract: true,
796
+ childRoles: ['listbox', 'menu', 'radiogroup', 'tree'],
636
797
  },
637
798
  separator: {
638
799
  // assume not focussable because <hr> is not
@@ -640,6 +801,8 @@ exports.roles = {
640
801
  childRoles: ['doc-pagebreak'],
641
802
  defaults: {
642
803
  'orientation': 'horizontal',
804
+ 'valuemin': 0,
805
+ 'valuemax': 100,
643
806
  },
644
807
  },
645
808
  slider: {
@@ -655,8 +818,7 @@ exports.roles = {
655
818
  spinbutton: {
656
819
  selectors: ['input[type="number"]'],
657
820
  defaults: {
658
- // FIXME: no valuemin/valuemax
659
- 'valuenow': 0,
821
+ // FIXME: no valuemin/valuemax/valuenow
660
822
  },
661
823
  },
662
824
  status: {
@@ -667,18 +829,30 @@ exports.roles = {
667
829
  'atomic': true,
668
830
  },
669
831
  },
832
+ strong: {
833
+ selectors: ['strong'],
834
+ },
670
835
  structure: {
836
+ abstract: true,
671
837
  childRoles: [
672
838
  'application',
673
839
  'document',
674
840
  'none',
675
- 'presentation',
841
+ 'generic',
842
+ 'range',
676
843
  'rowgroup',
677
844
  'section',
678
845
  'sectionhead',
679
846
  'separator',
680
847
  ],
681
848
  },
849
+ suggestion: {},
850
+ subscript: {
851
+ selectors: ['sub'],
852
+ },
853
+ superscript: {
854
+ selectors: ['sup'],
855
+ },
682
856
  switch: {
683
857
  nameFromContents: true,
684
858
  defaults: {
@@ -700,6 +874,7 @@ exports.roles = {
700
874
  'orientation': 'horizontal',
701
875
  },
702
876
  },
877
+ tabpanel: {},
703
878
  term: {
704
879
  selectors: ['dfn', 'dt'],
705
880
  },
@@ -714,6 +889,14 @@ exports.roles = {
714
889
  ],
715
890
  childRoles: ['searchbox'],
716
891
  },
892
+ time: {
893
+ selectors: ['time'],
894
+ },
895
+ timer: {
896
+ defaults: {
897
+ 'live': 'off',
898
+ },
899
+ },
717
900
  toolbar: {
718
901
  defaults: {
719
902
  'orientation': 'horizontal',
@@ -728,30 +911,35 @@ exports.roles = {
728
911
  'orientation': 'vertical',
729
912
  },
730
913
  },
914
+ treegrid: {},
731
915
  treeitem: {
732
916
  nameFromContents: true,
733
917
  },
734
918
  widget: {
919
+ abstract: true,
735
920
  childRoles: [
736
921
  'command',
737
922
  'composite',
738
923
  'gridcell',
739
924
  'input',
740
- 'range',
925
+ 'progressbar',
741
926
  'row',
927
+ 'scrollbar',
928
+ 'separator',
742
929
  'tab',
743
930
  ],
744
931
  },
745
932
  window: {
933
+ abstract: true,
746
934
  childRoles: ['dialog'],
747
935
  },
748
936
  };
749
937
 
750
- var getSubRoles = function(role) {
751
- var children = (exports.roles[role] || {}).childRoles || [];
752
- var descendents = children.map(getSubRoles);
938
+ const getSubRoles = function(role) {
939
+ const children = (exports.roles[role]).childRoles || [];
940
+ const descendents = children.map(getSubRoles);
753
941
 
754
- var result = [role];
942
+ const result = [role];
755
943
 
756
944
  descendents.forEach(list => {
757
945
  list.forEach(r => {
@@ -766,18 +954,19 @@ var getSubRoles = function(role) {
766
954
 
767
955
  exports.attrsWithDefaults = [];
768
956
 
769
- for (var role in exports.roles) {
957
+ for (const role in exports.roles) {
770
958
  exports.roles[role].subRoles = getSubRoles(role);
771
- for (var key in exports.roles[role].defaults) {
959
+ for (const key in exports.roles[role].defaults) {
772
960
  if (!exports.attrsWithDefaults.includes(key)) {
773
961
  exports.attrsWithDefaults.push(key);
774
962
  }
775
963
  }
776
964
  }
777
- exports.roles['none'] = exports.roles['none'] || {};
778
- exports.roles['none'].subRoles = ['none', 'presentation'];
779
- exports.roles['presentation'] = exports.roles['presentation'] || {};
780
- exports.roles['presentation'].subRoles = ['presentation', 'none'];
965
+
966
+ exports.aliases = {
967
+ 'presentation': 'none',
968
+ 'directory': 'list',
969
+ };
781
970
 
782
971
  exports.nameFromDescendant = {
783
972
  'figure': 'figcaption',
@@ -792,14 +981,14 @@ exports.nameDefaults = {
792
981
  };
793
982
 
794
983
  },{}],5:[function(require,module,exports){
795
- var constants = require('./constants.js');
796
- var atree = require('./atree.js');
797
- var query = require('./query.js');
798
-
799
- var getPseudoContent = function(node, selector) {
800
- var styles = window.getComputedStyle(node, selector);
801
- var ret = styles.getPropertyValue('content');
802
- var inline = styles.display.substr(0, 6) === 'inline';
984
+ const constants = require('./constants.js');
985
+ const atree = require('./atree.js');
986
+ const query = require('./query.js');
987
+
988
+ const getPseudoContent = function(node, selector) {
989
+ const styles = window.getComputedStyle(node, selector);
990
+ const ret = styles.getPropertyValue('content');
991
+ const inline = styles.display.substr(0, 6) === 'inline';
803
992
  if (!ret) {
804
993
  return '';
805
994
  }
@@ -814,12 +1003,12 @@ var getPseudoContent = function(node, selector) {
814
1003
  }
815
1004
  };
816
1005
 
817
- var getContent = function(root, visited) {
818
- var children = atree.getChildNodes(root);
1006
+ const getContent = function(root, visited) {
1007
+ const children = atree.getChildNodes(root);
819
1008
 
820
- var ret = '';
821
- for (var i = 0; i < children.length; i++) {
822
- var node = children[i];
1009
+ let ret = '';
1010
+ for (let i = 0; i < children.length; i++) {
1011
+ const node = children[i];
823
1012
  if (node.nodeType === node.TEXT_NODE) {
824
1013
  ret += node.textContent;
825
1014
  } else if (node.nodeType === node.ELEMENT_NODE) {
@@ -838,18 +1027,15 @@ var getContent = function(root, visited) {
838
1027
  return ret;
839
1028
  };
840
1029
 
841
- var allowNameFromContent = function(el) {
842
- var role = query.getRole(el);
843
- return (constants.roles[role] || {}).nameFromContents;
844
- };
845
-
846
- var isInLabelForOtherWidget = function(el) {
847
- var label = el.parentElement.closest('label');
848
- return label && (!el.labels || !Array.prototype.includes.call(el.labels, label));
1030
+ const allowNameFromContent = function(el) {
1031
+ const role = query.getRole(el);
1032
+ if (role) {
1033
+ return constants.roles[role].nameFromContents;
1034
+ }
849
1035
  };
850
1036
 
851
- var getName = function(el, recursive, visited, directReference) {
852
- var ret = '';
1037
+ const getName = function(el, recursive, visited, directReference) {
1038
+ let ret = '';
853
1039
 
854
1040
  visited = visited || [];
855
1041
  if (visited.includes(el)) {
@@ -865,14 +1051,30 @@ var getName = function(el, recursive, visited, directReference) {
865
1051
 
866
1052
  // B
867
1053
  if (!recursive && el.matches('[aria-labelledby]')) {
868
- var ids = el.getAttribute('aria-labelledby').split(/\s+/);
869
- var strings = ids.map(id => {
870
- var label = document.getElementById(id);
1054
+ const ids = el.getAttribute('aria-labelledby').split(/\s+/);
1055
+ const strings = ids.map(id => {
1056
+ const label = document.getElementById(id);
871
1057
  return label ? getName(label, true, visited, true) : '';
872
1058
  });
873
1059
  ret = strings.join(' ');
874
1060
  }
875
1061
 
1062
+ // E (the current draft has this at this high priority)
1063
+ if (!ret.trim() && recursive) {
1064
+ if (query.matches(el, 'textbox,button')) {
1065
+ ret = el.value || el.textContent;
1066
+ } else if (query.matches(el, 'combobox,listbox')) {
1067
+ const selected = query.querySelector(el, ':selected') || query.querySelector(el, 'option');
1068
+ if (selected) {
1069
+ ret = getName(selected, recursive, visited);
1070
+ } else {
1071
+ ret = el.value || '';
1072
+ }
1073
+ } else if (query.matches(el, 'range')) {
1074
+ ret = '' + (query.getAttribute(el, 'valuetext') || query.getAttribute(el, 'valuenow') || el.value);
1075
+ }
1076
+ }
1077
+
876
1078
  // C
877
1079
  if (!ret.trim() && el.matches('[aria-label]')) {
878
1080
  // FIXME: may skip to 2E
@@ -881,7 +1083,7 @@ var getName = function(el, recursive, visited, directReference) {
881
1083
 
882
1084
  // D
883
1085
  if (!ret.trim() && !recursive && el.labels) {
884
- var strings = Array.prototype.map.call(el.labels, label => {
1086
+ const strings = Array.prototype.map.call(el.labels, label => {
885
1087
  return getName(label, true, visited);
886
1088
  });
887
1089
  ret = strings.join(' ');
@@ -896,31 +1098,19 @@ var getName = function(el, recursive, visited, directReference) {
896
1098
  ret = el.title;
897
1099
  }
898
1100
  if (!ret.trim()) {
899
- for (var selector in constants.nameFromDescendant) {
1101
+ for (const selector in constants.nameFromDescendant) {
900
1102
  if (el.matches(selector)) {
901
- var descendant = el.querySelector(constants.nameFromDescendant[selector]);
1103
+ const descendant = el.querySelector(constants.nameFromDescendant[selector]);
902
1104
  if (descendant) {
903
1105
  ret = getName(descendant, true, visited);
904
1106
  }
905
1107
  }
906
1108
  }
907
1109
  }
908
-
909
- // E
910
- if (!ret.trim() && (recursive || isInLabelForOtherWidget(el) || query.matches(el, 'button'))) {
911
- if (query.matches(el, 'textbox,button,combobox,listbox,range')) {
912
- if (query.matches(el, 'textbox,button')) {
913
- ret = el.value || el.textContent;
914
- } else if (query.matches(el, 'combobox,listbox')) {
915
- var selected = query.querySelector(el, ':selected') || query.querySelector(el, 'option');
916
- if (selected) {
917
- ret = getName(selected, recursive, visited);
918
- } else {
919
- ret = el.value || '';
920
- }
921
- } else if (query.matches(el, 'range')) {
922
- ret = '' + (query.getAttribute(el, 'valuetext') || query.getAttribute(el, 'valuenow') || el.value);
923
- }
1110
+ if (!ret.trim() && el.matches('svg *')) {
1111
+ const svgTitle = el.querySelector('title');
1112
+ if (svgTitle && svgTitle.parentElement === el) {
1113
+ ret = svgTitle.textContent;
924
1114
  }
925
1115
  }
926
1116
 
@@ -930,8 +1120,12 @@ var getName = function(el, recursive, visited, directReference) {
930
1120
  ret = getContent(el, visited);
931
1121
  }
932
1122
 
1123
+ if (!ret.trim() && query.matches(el, 'button')) {
1124
+ ret = el.value || '';
1125
+ }
1126
+
933
1127
  if (!ret.trim()) {
934
- for (var selector in constants.nameDefaults) {
1128
+ for (const selector in constants.nameDefaults) {
935
1129
  if (el.matches(selector)) {
936
1130
  ret = constants.nameDefaults[selector];
937
1131
  }
@@ -953,29 +1147,34 @@ var getName = function(el, recursive, visited, directReference) {
953
1147
  ret = ' ';
954
1148
  }
955
1149
 
956
- var before = getPseudoContent(el, ':before');
957
- var after = getPseudoContent(el, ':after');
1150
+ const before = getPseudoContent(el, ':before');
1151
+ const after = getPseudoContent(el, ':after');
958
1152
  return before + ret + after;
959
1153
  };
960
1154
 
961
- var getNameTrimmed = function(el) {
1155
+ const getNameTrimmed = function(el) {
962
1156
  return getName(el).replace(/\s+/g, ' ').trim();
963
1157
  };
964
1158
 
965
- var getDescription = function(el) {
966
- var ret = '';
1159
+ const getDescription = function(el) {
1160
+ let ret = '';
967
1161
 
968
1162
  if (el.matches('[aria-describedby]')) {
969
- var ids = el.getAttribute('aria-describedby').split(/\s+/);
970
- var strings = ids.map(id => {
971
- var label = document.getElementById(id);
1163
+ const ids = el.getAttribute('aria-describedby').split(/\s+/);
1164
+ const strings = ids.map(id => {
1165
+ const label = document.getElementById(id);
972
1166
  return label ? getName(label, true) : '';
973
1167
  });
974
1168
  ret = strings.join(' ');
1169
+ } else if (el.matches('[aria-description]')) {
1170
+ ret = el.getAttribute('aria-description');
1171
+ } else if (el.matches('svg *')) {
1172
+ const svgDesc = el.querySelector('desc');
1173
+ if (svgDesc && svgDesc.parentElement === el) {
1174
+ ret = svgDesc.textContent;
1175
+ }
975
1176
  } else if (el.title) {
976
1177
  ret = el.title;
977
- } else if (el.placeholder) {
978
- ret = el.placeholder;
979
1178
  }
980
1179
 
981
1180
  ret = (ret || '').trim().replace(/\s+/g, ' ');
@@ -993,34 +1192,32 @@ module.exports = {
993
1192
  };
994
1193
 
995
1194
  },{"./atree.js":2,"./constants.js":4,"./query.js":6}],6:[function(require,module,exports){
996
- var attrs = require('./attrs.js');
997
- var atree = require('./atree.js');
998
-
1195
+ const attrs = require('./attrs.js');
1196
+ const atree = require('./atree.js');
999
1197
 
1000
- var matches = function(el, selector) {
1001
- var actual;
1002
1198
 
1199
+ const matches = function(el, selector) {
1003
1200
  if (selector.substr(0, 1) === ':') {
1004
- var attr = selector.substr(1);
1201
+ const attr = selector.substr(1);
1005
1202
  return attrs.getAttribute(el, attr);
1006
1203
  } else if (selector.substr(0, 1) === '[') {
1007
- var match = /\[([a-z]+)="(.*)"\]/.exec(selector);
1008
- actual = attrs.getAttribute(el, match[1]);
1009
- var rawValue = match[2];
1204
+ const match = /\[([a-z]+)="(.*)"\]/.exec(selector);
1205
+ const actual = attrs.getAttribute(el, match[1]);
1206
+ const rawValue = match[2];
1010
1207
  return actual.toString() === rawValue;
1011
1208
  } else {
1012
1209
  return attrs.hasRole(el, selector.split(','));
1013
1210
  }
1014
1211
  };
1015
1212
 
1016
- var _querySelector = function(all) {
1017
- return function(root, role) {
1018
- var results = [];
1213
+ const _querySelector = function(all) {
1214
+ return function(root, selector) {
1215
+ const results = [];
1019
1216
  try {
1020
1217
  atree.walk(root, node => {
1021
1218
  if (node.nodeType === node.ELEMENT_NODE) {
1022
1219
  // FIXME: skip hidden elements
1023
- if (matches(node, role)) {
1220
+ if (matches(node, selector)) {
1024
1221
  results.push(node);
1025
1222
  if (!all) {
1026
1223
  throw 'StopIteration';
@@ -1037,7 +1234,7 @@ var _querySelector = function(all) {
1037
1234
  };
1038
1235
  };
1039
1236
 
1040
- var closest = function(el, selector) {
1237
+ const closest = function(el, selector) {
1041
1238
  return atree.searchUp(el, candidate => {
1042
1239
  if (candidate.nodeType === candidate.ELEMENT_NODE) {
1043
1240
  return matches(candidate, selector);