aria-api 0.5.0 → 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 +235 -145
- package/lib/atree.js +24 -24
- package/lib/attrs.js +44 -29
- package/lib/constants.js +98 -20
- package/lib/name.js +57 -58
- package/lib/query.js +12 -14
- package/package.json +1 -1
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
|
-
|
|
22
|
+
const attrs = require('./attrs');
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
const _getOwner = function(node, owners) {
|
|
25
25
|
if (node.nodeType === node.ELEMENT_NODE && node.id) {
|
|
26
|
-
|
|
26
|
+
const selector = '[aria-owns~="' + CSS.escape(node.id) + '"]';
|
|
27
27
|
if (owners) {
|
|
28
|
-
for (
|
|
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
|
-
|
|
39
|
+
const _getParentNode = function(node, owners) {
|
|
40
40
|
return _getOwner(node, owners) || node.parentNode;
|
|
41
41
|
};
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
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
|
-
|
|
54
|
-
|
|
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
|
-
|
|
60
|
+
const getParentNode = function(node, owners) {
|
|
61
61
|
return getOwner(node, owners) || node.parentNode;
|
|
62
62
|
};
|
|
63
63
|
|
|
64
|
-
|
|
64
|
+
const isHidden = function(node) {
|
|
65
65
|
return node.nodeType === node.ELEMENT_NODE && attrs.getAttribute(node, 'hidden');
|
|
66
66
|
};
|
|
67
67
|
|
|
68
|
-
|
|
69
|
-
|
|
68
|
+
const getChildNodes = function(node, owners) {
|
|
69
|
+
const childNodes = [];
|
|
70
70
|
|
|
71
|
-
for (
|
|
72
|
-
|
|
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
|
-
|
|
80
|
-
for (
|
|
81
|
-
|
|
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
|
-
|
|
93
|
-
|
|
94
|
-
|
|
92
|
+
const walk = function(root, fn) {
|
|
93
|
+
const owners = document.querySelectorAll('[aria-owns]');
|
|
94
|
+
let queue = [root];
|
|
95
95
|
while (queue.length) {
|
|
96
|
-
|
|
96
|
+
const item = queue.shift();
|
|
97
97
|
fn(item);
|
|
98
98
|
queue = getChildNodes(item, owners).concat(queue);
|
|
99
99
|
}
|
|
100
100
|
};
|
|
101
101
|
|
|
102
|
-
|
|
103
|
-
|
|
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,44 +118,59 @@ module.exports = {
|
|
|
118
118
|
};
|
|
119
119
|
|
|
120
120
|
},{"./attrs":3}],3:[function(require,module,exports){
|
|
121
|
-
|
|
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
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
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) {
|
|
131
150
|
if (!candidates || candidates.includes(role)) {
|
|
132
151
|
return role;
|
|
133
152
|
}
|
|
134
153
|
}
|
|
135
154
|
} else {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
var selector = (r.selectors || []).join(',');
|
|
141
|
-
if (selector && el.matches(selector)) {
|
|
142
|
-
return role;
|
|
143
|
-
}
|
|
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(','))) {
|
|
158
|
+
return role;
|
|
144
159
|
}
|
|
145
160
|
}
|
|
146
161
|
}
|
|
147
162
|
};
|
|
148
163
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
return
|
|
152
|
-
})
|
|
153
|
-
return !!getRole(el,
|
|
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)));
|
|
154
169
|
};
|
|
155
170
|
|
|
156
|
-
|
|
171
|
+
const getAttribute = function(el, key) {
|
|
157
172
|
if (constants.attributeStrongMapping.hasOwnProperty(key)) {
|
|
158
|
-
|
|
173
|
+
const value = el[constants.attributeStrongMapping[key]];
|
|
159
174
|
if (value) {
|
|
160
175
|
return value;
|
|
161
176
|
}
|
|
@@ -172,14 +187,14 @@ var getAttribute = function(el, key) {
|
|
|
172
187
|
if (el.matches('details:not([open]) > :not(summary)')) {
|
|
173
188
|
return true;
|
|
174
189
|
}
|
|
175
|
-
|
|
190
|
+
const style = window.getComputedStyle(el);
|
|
176
191
|
if (style.display === 'none' || style.visibility === 'hidden') {
|
|
177
192
|
return true;
|
|
178
193
|
}
|
|
179
194
|
}
|
|
180
195
|
|
|
181
|
-
|
|
182
|
-
|
|
196
|
+
const type = constants.attributes[key];
|
|
197
|
+
const raw = el.getAttribute('aria-' + key);
|
|
183
198
|
|
|
184
199
|
if (raw) {
|
|
185
200
|
if (type === 'bool') {
|
|
@@ -208,7 +223,7 @@ var getAttribute = function(el, key) {
|
|
|
208
223
|
// list -> aria-controls
|
|
209
224
|
|
|
210
225
|
if (key === 'level') {
|
|
211
|
-
for (
|
|
226
|
+
for (let i = 1; i <= 6; i++) {
|
|
212
227
|
if (el.tagName.toLowerCase() === 'h' + i) {
|
|
213
228
|
return i;
|
|
214
229
|
}
|
|
@@ -218,8 +233,8 @@ var getAttribute = function(el, key) {
|
|
|
218
233
|
}
|
|
219
234
|
|
|
220
235
|
if (key in constants.attrsWithDefaults) {
|
|
221
|
-
|
|
222
|
-
|
|
236
|
+
const role = getRole(el);
|
|
237
|
+
const defaults = constants.roles[role].defaults;
|
|
223
238
|
if (defaults && defaults.hasOwnProperty(key)) {
|
|
224
239
|
return defaults[key];
|
|
225
240
|
}
|
|
@@ -306,7 +321,7 @@ exports.attributeWeakMapping = {
|
|
|
306
321
|
};
|
|
307
322
|
|
|
308
323
|
// https://www.w3.org/TR/html/dom.html#sectioning-content-2
|
|
309
|
-
|
|
324
|
+
const scoped = ['article *', 'aside *', 'nav *', 'section *'].join(',');
|
|
310
325
|
|
|
311
326
|
// https://www.w3.org/TR/html-aam-1.0/#html-element-role-mappings
|
|
312
327
|
// https://www.w3.org/TR/wai-aria/roles
|
|
@@ -318,6 +333,8 @@ exports.roles = {
|
|
|
318
333
|
'atomic': true,
|
|
319
334
|
},
|
|
320
335
|
},
|
|
336
|
+
alertdialog: {},
|
|
337
|
+
application: {},
|
|
321
338
|
article: {
|
|
322
339
|
selectors: ['article'],
|
|
323
340
|
},
|
|
@@ -342,7 +359,7 @@ exports.roles = {
|
|
|
342
359
|
selectors: ['caption', 'figcaption'],
|
|
343
360
|
},
|
|
344
361
|
cell: {
|
|
345
|
-
selectors: ['td', 'th:not([scope])'],
|
|
362
|
+
selectors: ['td', 'td ~ th:not([scope])'],
|
|
346
363
|
childRoles: ['columnheader', 'gridcell', 'rowheader'],
|
|
347
364
|
nameFromContents: true,
|
|
348
365
|
},
|
|
@@ -379,6 +396,7 @@ exports.roles = {
|
|
|
379
396
|
},
|
|
380
397
|
},
|
|
381
398
|
command: {
|
|
399
|
+
abstract: true,
|
|
382
400
|
childRoles: ['button', 'link', 'menuitem'],
|
|
383
401
|
},
|
|
384
402
|
complementary: {
|
|
@@ -390,6 +408,7 @@ exports.roles = {
|
|
|
390
408
|
],
|
|
391
409
|
},
|
|
392
410
|
composite: {
|
|
411
|
+
abstract: true,
|
|
393
412
|
childRoles: ['grid', 'select', 'spinbutton', 'tablist'],
|
|
394
413
|
},
|
|
395
414
|
contentinfo: {
|
|
@@ -405,24 +424,59 @@ exports.roles = {
|
|
|
405
424
|
selectors: ['dialog'],
|
|
406
425
|
childRoles: ['alertdialog'],
|
|
407
426
|
},
|
|
427
|
+
'doc-abstract': {},
|
|
428
|
+
'doc-acknowledgments': {},
|
|
429
|
+
'doc-afterword': {},
|
|
430
|
+
'doc-appendix': {},
|
|
408
431
|
'doc-backlink': {
|
|
409
432
|
nameFromContents: true,
|
|
410
433
|
},
|
|
434
|
+
'doc-biblioentry': {},
|
|
435
|
+
'doc-bibliography': {},
|
|
411
436
|
'doc-biblioref': {
|
|
412
437
|
nameFromContents: true,
|
|
413
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': {},
|
|
414
455
|
'doc-glossref': {
|
|
415
456
|
nameFromContents: true,
|
|
416
457
|
},
|
|
458
|
+
'doc-index': {},
|
|
459
|
+
'doc-introduction': {},
|
|
417
460
|
'doc-noteref': {
|
|
418
461
|
nameFromContents: true,
|
|
419
462
|
},
|
|
463
|
+
'doc-notice': {},
|
|
420
464
|
'doc-pagebreak': {
|
|
421
465
|
nameFromContents: true,
|
|
422
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': {},
|
|
423
475
|
'doc-subtitle': {
|
|
424
476
|
nameFromContents: true,
|
|
425
477
|
},
|
|
478
|
+
'doc-tip': {},
|
|
479
|
+
'doc-toc': {},
|
|
426
480
|
document: {
|
|
427
481
|
selectors: ['html'],
|
|
428
482
|
childRoles: ['article', 'graphics-document'],
|
|
@@ -430,6 +484,7 @@ exports.roles = {
|
|
|
430
484
|
emphasis: {
|
|
431
485
|
selectors: ['em'],
|
|
432
486
|
},
|
|
487
|
+
feed: {},
|
|
433
488
|
figure: {
|
|
434
489
|
selectors: ['figure'],
|
|
435
490
|
childRoles: ['doc-example'],
|
|
@@ -438,11 +493,34 @@ exports.roles = {
|
|
|
438
493
|
selectors: ['form[aria-label]', 'form[aria-labelledby]', 'form[title]'],
|
|
439
494
|
},
|
|
440
495
|
generic: {
|
|
441
|
-
|
|
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
|
+
],
|
|
442
518
|
},
|
|
443
519
|
'graphics-document': {
|
|
444
520
|
selectors: ['svg'],
|
|
445
521
|
},
|
|
522
|
+
'graphics-object': {},
|
|
523
|
+
'graphics-symbol': {},
|
|
446
524
|
grid: {
|
|
447
525
|
childRoles: ['treegrid'],
|
|
448
526
|
},
|
|
@@ -473,6 +551,7 @@ exports.roles = {
|
|
|
473
551
|
childRoles: ['doc-cover'],
|
|
474
552
|
},
|
|
475
553
|
input: {
|
|
554
|
+
abstract: true,
|
|
476
555
|
childRoles: [
|
|
477
556
|
'checkbox',
|
|
478
557
|
'combobox',
|
|
@@ -487,6 +566,7 @@ exports.roles = {
|
|
|
487
566
|
selectors: ['ins'],
|
|
488
567
|
},
|
|
489
568
|
landmark: {
|
|
569
|
+
abstract: true,
|
|
490
570
|
childRoles: [
|
|
491
571
|
'banner',
|
|
492
572
|
'complementary',
|
|
@@ -521,7 +601,7 @@ exports.roles = {
|
|
|
521
601
|
},
|
|
522
602
|
list: {
|
|
523
603
|
selectors: ['dl', 'ol', 'ul', 'menu'],
|
|
524
|
-
childRoles: ['
|
|
604
|
+
childRoles: ['feed'],
|
|
525
605
|
},
|
|
526
606
|
listbox: {
|
|
527
607
|
selectors: [
|
|
@@ -534,7 +614,7 @@ exports.roles = {
|
|
|
534
614
|
},
|
|
535
615
|
},
|
|
536
616
|
listitem: {
|
|
537
|
-
selectors: ['li'],
|
|
617
|
+
selectors: ['ol > li', 'ul > li'],
|
|
538
618
|
childRoles: ['doc-biblioentry', 'doc-endnote', 'treeitem'],
|
|
539
619
|
},
|
|
540
620
|
log: {
|
|
@@ -545,6 +625,7 @@ exports.roles = {
|
|
|
545
625
|
main: {
|
|
546
626
|
selectors: ['main'],
|
|
547
627
|
},
|
|
628
|
+
marquee: {},
|
|
548
629
|
math: {
|
|
549
630
|
selectors: ['math'],
|
|
550
631
|
},
|
|
@@ -587,6 +668,9 @@ exports.roles = {
|
|
|
587
668
|
selectors: ['nav'],
|
|
588
669
|
childRoles: ['doc-index', 'doc-pagelist', 'doc-toc'],
|
|
589
670
|
},
|
|
671
|
+
none: {
|
|
672
|
+
selectors: ['img[alt=""]'],
|
|
673
|
+
},
|
|
590
674
|
note: {
|
|
591
675
|
childRoles: ['doc-notice', 'doc-tip'],
|
|
592
676
|
},
|
|
@@ -601,9 +685,6 @@ exports.roles = {
|
|
|
601
685
|
paragraph: {
|
|
602
686
|
selectors: ['p'],
|
|
603
687
|
},
|
|
604
|
-
presentation: {
|
|
605
|
-
selectors: ['img[alt=""]'],
|
|
606
|
-
},
|
|
607
688
|
progressbar: {
|
|
608
689
|
selectors: ['progress'],
|
|
609
690
|
defaults: {
|
|
@@ -619,13 +700,16 @@ exports.roles = {
|
|
|
619
700
|
'checked': 'false',
|
|
620
701
|
},
|
|
621
702
|
},
|
|
703
|
+
radiogroup: {},
|
|
622
704
|
range: {
|
|
705
|
+
abstract: true,
|
|
623
706
|
childRoles: ['meter', 'progressbar', 'scrollbar', 'slider', 'spinbutton'],
|
|
624
707
|
},
|
|
625
708
|
region: {
|
|
626
709
|
selectors: ['section[aria-label]', 'section[aria-labelledby]', 'section[title]'],
|
|
627
710
|
},
|
|
628
711
|
roletype: {
|
|
712
|
+
abstract: true,
|
|
629
713
|
childRoles: ['structure', 'widget', 'window'],
|
|
630
714
|
},
|
|
631
715
|
row: {
|
|
@@ -636,7 +720,7 @@ exports.roles = {
|
|
|
636
720
|
selectors: ['tbody', 'thead', 'tfoot'],
|
|
637
721
|
},
|
|
638
722
|
rowheader: {
|
|
639
|
-
selectors: ['th[scope="row"]'],
|
|
723
|
+
selectors: ['th[scope="row"]', 'th:not([scope]):not(td ~ th)'],
|
|
640
724
|
nameFromContents: true,
|
|
641
725
|
},
|
|
642
726
|
scrollbar: {
|
|
@@ -653,6 +737,7 @@ exports.roles = {
|
|
|
653
737
|
selectors: ['input[type="search"]:not([list])'],
|
|
654
738
|
},
|
|
655
739
|
section: {
|
|
740
|
+
abstract: true,
|
|
656
741
|
childRoles: [
|
|
657
742
|
'alert',
|
|
658
743
|
'blockquote',
|
|
@@ -696,6 +781,7 @@ exports.roles = {
|
|
|
696
781
|
],
|
|
697
782
|
},
|
|
698
783
|
sectionhead: {
|
|
784
|
+
abstract: true,
|
|
699
785
|
childRoles: [
|
|
700
786
|
'columnheader',
|
|
701
787
|
'doc-subtitle',
|
|
@@ -706,6 +792,7 @@ exports.roles = {
|
|
|
706
792
|
nameFromContents: true,
|
|
707
793
|
},
|
|
708
794
|
select: {
|
|
795
|
+
abstract: true,
|
|
709
796
|
childRoles: ['listbox', 'menu', 'radiogroup', 'tree'],
|
|
710
797
|
},
|
|
711
798
|
separator: {
|
|
@@ -746,12 +833,12 @@ exports.roles = {
|
|
|
746
833
|
selectors: ['strong'],
|
|
747
834
|
},
|
|
748
835
|
structure: {
|
|
836
|
+
abstract: true,
|
|
749
837
|
childRoles: [
|
|
750
838
|
'application',
|
|
751
839
|
'document',
|
|
752
840
|
'none',
|
|
753
841
|
'generic',
|
|
754
|
-
'presentation',
|
|
755
842
|
'range',
|
|
756
843
|
'rowgroup',
|
|
757
844
|
'section',
|
|
@@ -759,6 +846,7 @@ exports.roles = {
|
|
|
759
846
|
'separator',
|
|
760
847
|
],
|
|
761
848
|
},
|
|
849
|
+
suggestion: {},
|
|
762
850
|
subscript: {
|
|
763
851
|
selectors: ['sub'],
|
|
764
852
|
},
|
|
@@ -786,6 +874,7 @@ exports.roles = {
|
|
|
786
874
|
'orientation': 'horizontal',
|
|
787
875
|
},
|
|
788
876
|
},
|
|
877
|
+
tabpanel: {},
|
|
789
878
|
term: {
|
|
790
879
|
selectors: ['dfn', 'dt'],
|
|
791
880
|
},
|
|
@@ -822,10 +911,12 @@ exports.roles = {
|
|
|
822
911
|
'orientation': 'vertical',
|
|
823
912
|
},
|
|
824
913
|
},
|
|
914
|
+
treegrid: {},
|
|
825
915
|
treeitem: {
|
|
826
916
|
nameFromContents: true,
|
|
827
917
|
},
|
|
828
918
|
widget: {
|
|
919
|
+
abstract: true,
|
|
829
920
|
childRoles: [
|
|
830
921
|
'command',
|
|
831
922
|
'composite',
|
|
@@ -839,15 +930,16 @@ exports.roles = {
|
|
|
839
930
|
],
|
|
840
931
|
},
|
|
841
932
|
window: {
|
|
933
|
+
abstract: true,
|
|
842
934
|
childRoles: ['dialog'],
|
|
843
935
|
},
|
|
844
936
|
};
|
|
845
937
|
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
938
|
+
const getSubRoles = function(role) {
|
|
939
|
+
const children = (exports.roles[role]).childRoles || [];
|
|
940
|
+
const descendents = children.map(getSubRoles);
|
|
849
941
|
|
|
850
|
-
|
|
942
|
+
const result = [role];
|
|
851
943
|
|
|
852
944
|
descendents.forEach(list => {
|
|
853
945
|
list.forEach(r => {
|
|
@@ -862,18 +954,19 @@ var getSubRoles = function(role) {
|
|
|
862
954
|
|
|
863
955
|
exports.attrsWithDefaults = [];
|
|
864
956
|
|
|
865
|
-
for (
|
|
957
|
+
for (const role in exports.roles) {
|
|
866
958
|
exports.roles[role].subRoles = getSubRoles(role);
|
|
867
|
-
for (
|
|
959
|
+
for (const key in exports.roles[role].defaults) {
|
|
868
960
|
if (!exports.attrsWithDefaults.includes(key)) {
|
|
869
961
|
exports.attrsWithDefaults.push(key);
|
|
870
962
|
}
|
|
871
963
|
}
|
|
872
964
|
}
|
|
873
|
-
|
|
874
|
-
exports.
|
|
875
|
-
|
|
876
|
-
|
|
965
|
+
|
|
966
|
+
exports.aliases = {
|
|
967
|
+
'presentation': 'none',
|
|
968
|
+
'directory': 'list',
|
|
969
|
+
};
|
|
877
970
|
|
|
878
971
|
exports.nameFromDescendant = {
|
|
879
972
|
'figure': 'figcaption',
|
|
@@ -888,14 +981,14 @@ exports.nameDefaults = {
|
|
|
888
981
|
};
|
|
889
982
|
|
|
890
983
|
},{}],5:[function(require,module,exports){
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
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';
|
|
899
992
|
if (!ret) {
|
|
900
993
|
return '';
|
|
901
994
|
}
|
|
@@ -910,12 +1003,12 @@ var getPseudoContent = function(node, selector) {
|
|
|
910
1003
|
}
|
|
911
1004
|
};
|
|
912
1005
|
|
|
913
|
-
|
|
914
|
-
|
|
1006
|
+
const getContent = function(root, visited) {
|
|
1007
|
+
const children = atree.getChildNodes(root);
|
|
915
1008
|
|
|
916
|
-
|
|
917
|
-
for (
|
|
918
|
-
|
|
1009
|
+
let ret = '';
|
|
1010
|
+
for (let i = 0; i < children.length; i++) {
|
|
1011
|
+
const node = children[i];
|
|
919
1012
|
if (node.nodeType === node.TEXT_NODE) {
|
|
920
1013
|
ret += node.textContent;
|
|
921
1014
|
} else if (node.nodeType === node.ELEMENT_NODE) {
|
|
@@ -934,18 +1027,15 @@ var getContent = function(root, visited) {
|
|
|
934
1027
|
return ret;
|
|
935
1028
|
};
|
|
936
1029
|
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
var isInLabelForOtherWidget = function(el) {
|
|
943
|
-
var label = el.parentElement.closest('label');
|
|
944
|
-
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
|
+
}
|
|
945
1035
|
};
|
|
946
1036
|
|
|
947
|
-
|
|
948
|
-
|
|
1037
|
+
const getName = function(el, recursive, visited, directReference) {
|
|
1038
|
+
let ret = '';
|
|
949
1039
|
|
|
950
1040
|
visited = visited || [];
|
|
951
1041
|
if (visited.includes(el)) {
|
|
@@ -961,14 +1051,30 @@ var getName = function(el, recursive, visited, directReference) {
|
|
|
961
1051
|
|
|
962
1052
|
// B
|
|
963
1053
|
if (!recursive && el.matches('[aria-labelledby]')) {
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
1054
|
+
const ids = el.getAttribute('aria-labelledby').split(/\s+/);
|
|
1055
|
+
const strings = ids.map(id => {
|
|
1056
|
+
const label = document.getElementById(id);
|
|
967
1057
|
return label ? getName(label, true, visited, true) : '';
|
|
968
1058
|
});
|
|
969
1059
|
ret = strings.join(' ');
|
|
970
1060
|
}
|
|
971
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
|
+
|
|
972
1078
|
// C
|
|
973
1079
|
if (!ret.trim() && el.matches('[aria-label]')) {
|
|
974
1080
|
// FIXME: may skip to 2E
|
|
@@ -977,7 +1083,7 @@ var getName = function(el, recursive, visited, directReference) {
|
|
|
977
1083
|
|
|
978
1084
|
// D
|
|
979
1085
|
if (!ret.trim() && !recursive && el.labels) {
|
|
980
|
-
|
|
1086
|
+
const strings = Array.prototype.map.call(el.labels, label => {
|
|
981
1087
|
return getName(label, true, visited);
|
|
982
1088
|
});
|
|
983
1089
|
ret = strings.join(' ');
|
|
@@ -992,9 +1098,9 @@ var getName = function(el, recursive, visited, directReference) {
|
|
|
992
1098
|
ret = el.title;
|
|
993
1099
|
}
|
|
994
1100
|
if (!ret.trim()) {
|
|
995
|
-
for (
|
|
1101
|
+
for (const selector in constants.nameFromDescendant) {
|
|
996
1102
|
if (el.matches(selector)) {
|
|
997
|
-
|
|
1103
|
+
const descendant = el.querySelector(constants.nameFromDescendant[selector]);
|
|
998
1104
|
if (descendant) {
|
|
999
1105
|
ret = getName(descendant, true, visited);
|
|
1000
1106
|
}
|
|
@@ -1002,38 +1108,24 @@ var getName = function(el, recursive, visited, directReference) {
|
|
|
1002
1108
|
}
|
|
1003
1109
|
}
|
|
1004
1110
|
if (!ret.trim() && el.matches('svg *')) {
|
|
1005
|
-
|
|
1111
|
+
const svgTitle = el.querySelector('title');
|
|
1006
1112
|
if (svgTitle && svgTitle.parentElement === el) {
|
|
1007
1113
|
ret = svgTitle.textContent;
|
|
1008
1114
|
}
|
|
1009
1115
|
}
|
|
1010
1116
|
|
|
1011
|
-
// E
|
|
1012
|
-
if (!ret.trim() && (recursive || isInLabelForOtherWidget(el) || query.matches(el, 'button'))) {
|
|
1013
|
-
if (query.matches(el, 'textbox,button,combobox,listbox,range')) {
|
|
1014
|
-
if (query.matches(el, 'textbox,button')) {
|
|
1015
|
-
ret = el.value || el.textContent;
|
|
1016
|
-
} else if (query.matches(el, 'combobox,listbox')) {
|
|
1017
|
-
var selected = query.querySelector(el, ':selected') || query.querySelector(el, 'option');
|
|
1018
|
-
if (selected) {
|
|
1019
|
-
ret = getName(selected, recursive, visited);
|
|
1020
|
-
} else {
|
|
1021
|
-
ret = el.value || '';
|
|
1022
|
-
}
|
|
1023
|
-
} else if (query.matches(el, 'range')) {
|
|
1024
|
-
ret = '' + (query.getAttribute(el, 'valuetext') || query.getAttribute(el, 'valuenow') || el.value);
|
|
1025
|
-
}
|
|
1026
|
-
}
|
|
1027
|
-
}
|
|
1028
|
-
|
|
1029
1117
|
// F
|
|
1030
1118
|
// FIXME: menu is not mentioned in the spec
|
|
1031
1119
|
if (!ret.trim() && (recursive || allowNameFromContent(el) || el.closest('label')) && !query.matches(el, 'menu')) {
|
|
1032
1120
|
ret = getContent(el, visited);
|
|
1033
1121
|
}
|
|
1034
1122
|
|
|
1123
|
+
if (!ret.trim() && query.matches(el, 'button')) {
|
|
1124
|
+
ret = el.value || '';
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1035
1127
|
if (!ret.trim()) {
|
|
1036
|
-
for (
|
|
1128
|
+
for (const selector in constants.nameDefaults) {
|
|
1037
1129
|
if (el.matches(selector)) {
|
|
1038
1130
|
ret = constants.nameDefaults[selector];
|
|
1039
1131
|
}
|
|
@@ -1055,29 +1147,29 @@ var getName = function(el, recursive, visited, directReference) {
|
|
|
1055
1147
|
ret = ' ';
|
|
1056
1148
|
}
|
|
1057
1149
|
|
|
1058
|
-
|
|
1059
|
-
|
|
1150
|
+
const before = getPseudoContent(el, ':before');
|
|
1151
|
+
const after = getPseudoContent(el, ':after');
|
|
1060
1152
|
return before + ret + after;
|
|
1061
1153
|
};
|
|
1062
1154
|
|
|
1063
|
-
|
|
1155
|
+
const getNameTrimmed = function(el) {
|
|
1064
1156
|
return getName(el).replace(/\s+/g, ' ').trim();
|
|
1065
1157
|
};
|
|
1066
1158
|
|
|
1067
|
-
|
|
1068
|
-
|
|
1159
|
+
const getDescription = function(el) {
|
|
1160
|
+
let ret = '';
|
|
1069
1161
|
|
|
1070
1162
|
if (el.matches('[aria-describedby]')) {
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1163
|
+
const ids = el.getAttribute('aria-describedby').split(/\s+/);
|
|
1164
|
+
const strings = ids.map(id => {
|
|
1165
|
+
const label = document.getElementById(id);
|
|
1074
1166
|
return label ? getName(label, true) : '';
|
|
1075
1167
|
});
|
|
1076
1168
|
ret = strings.join(' ');
|
|
1077
1169
|
} else if (el.matches('[aria-description]')) {
|
|
1078
1170
|
ret = el.getAttribute('aria-description');
|
|
1079
1171
|
} else if (el.matches('svg *')) {
|
|
1080
|
-
|
|
1172
|
+
const svgDesc = el.querySelector('desc');
|
|
1081
1173
|
if (svgDesc && svgDesc.parentElement === el) {
|
|
1082
1174
|
ret = svgDesc.textContent;
|
|
1083
1175
|
}
|
|
@@ -1100,34 +1192,32 @@ module.exports = {
|
|
|
1100
1192
|
};
|
|
1101
1193
|
|
|
1102
1194
|
},{"./atree.js":2,"./constants.js":4,"./query.js":6}],6:[function(require,module,exports){
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1195
|
+
const attrs = require('./attrs.js');
|
|
1196
|
+
const atree = require('./atree.js');
|
|
1106
1197
|
|
|
1107
|
-
var matches = function(el, selector) {
|
|
1108
|
-
var actual;
|
|
1109
1198
|
|
|
1199
|
+
const matches = function(el, selector) {
|
|
1110
1200
|
if (selector.substr(0, 1) === ':') {
|
|
1111
|
-
|
|
1201
|
+
const attr = selector.substr(1);
|
|
1112
1202
|
return attrs.getAttribute(el, attr);
|
|
1113
1203
|
} else if (selector.substr(0, 1) === '[') {
|
|
1114
|
-
|
|
1115
|
-
actual = attrs.getAttribute(el, match[1]);
|
|
1116
|
-
|
|
1204
|
+
const match = /\[([a-z]+)="(.*)"\]/.exec(selector);
|
|
1205
|
+
const actual = attrs.getAttribute(el, match[1]);
|
|
1206
|
+
const rawValue = match[2];
|
|
1117
1207
|
return actual.toString() === rawValue;
|
|
1118
1208
|
} else {
|
|
1119
1209
|
return attrs.hasRole(el, selector.split(','));
|
|
1120
1210
|
}
|
|
1121
1211
|
};
|
|
1122
1212
|
|
|
1123
|
-
|
|
1124
|
-
return function(root,
|
|
1125
|
-
|
|
1213
|
+
const _querySelector = function(all) {
|
|
1214
|
+
return function(root, selector) {
|
|
1215
|
+
const results = [];
|
|
1126
1216
|
try {
|
|
1127
1217
|
atree.walk(root, node => {
|
|
1128
1218
|
if (node.nodeType === node.ELEMENT_NODE) {
|
|
1129
1219
|
// FIXME: skip hidden elements
|
|
1130
|
-
if (matches(node,
|
|
1220
|
+
if (matches(node, selector)) {
|
|
1131
1221
|
results.push(node);
|
|
1132
1222
|
if (!all) {
|
|
1133
1223
|
throw 'StopIteration';
|
|
@@ -1144,7 +1234,7 @@ var _querySelector = function(all) {
|
|
|
1144
1234
|
};
|
|
1145
1235
|
};
|
|
1146
1236
|
|
|
1147
|
-
|
|
1237
|
+
const closest = function(el, selector) {
|
|
1148
1238
|
return atree.searchUp(el, candidate => {
|
|
1149
1239
|
if (candidate.nodeType === candidate.ELEMENT_NODE) {
|
|
1150
1240
|
return matches(candidate, selector);
|