aria-api 0.5.0 → 0.7.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 +339 -179
- package/lib/atree.js +24 -24
- package/lib/attrs.js +45 -30
- package/lib/constants.js +155 -26
- package/lib/name.js +103 -85
- 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
|
-
|
|
176
|
-
if (style.display === 'none' || style.visibility === 'hidden') {
|
|
190
|
+
const style = window.getComputedStyle(el);
|
|
191
|
+
if (style.display === 'none' || style.visibility === 'hidden' || style.visibility === 'collapse') {
|
|
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
|
}
|
|
@@ -242,14 +257,18 @@ exports.attributes = {
|
|
|
242
257
|
'activedescendant': 'id',
|
|
243
258
|
'atomic': 'bool',
|
|
244
259
|
'autocomplete': 'token',
|
|
260
|
+
'braillelabel': 'string',
|
|
261
|
+
'brailleroledescription': 'string',
|
|
245
262
|
'busy': 'bool',
|
|
246
263
|
'checked': 'tristate',
|
|
247
264
|
'colcount': 'int',
|
|
248
265
|
'colindex': 'int',
|
|
266
|
+
'colindextext': 'string',
|
|
249
267
|
'colspan': 'int',
|
|
250
268
|
'controls': 'id-list',
|
|
251
269
|
'current': 'token',
|
|
252
270
|
'describedby': 'id-list',
|
|
271
|
+
'description': 'string',
|
|
253
272
|
'details': 'id',
|
|
254
273
|
'disabled': 'bool',
|
|
255
274
|
'dropeffect': 'token-list',
|
|
@@ -279,6 +298,7 @@ exports.attributes = {
|
|
|
279
298
|
'roledescription': 'string',
|
|
280
299
|
'rowcount': 'int',
|
|
281
300
|
'rowindex': 'int',
|
|
301
|
+
'rowindextext': 'string',
|
|
282
302
|
'rowspan': 'int',
|
|
283
303
|
'selected': 'bool-undefined',
|
|
284
304
|
'setsize': 'int',
|
|
@@ -306,7 +326,20 @@ exports.attributeWeakMapping = {
|
|
|
306
326
|
};
|
|
307
327
|
|
|
308
328
|
// https://www.w3.org/TR/html/dom.html#sectioning-content-2
|
|
309
|
-
|
|
329
|
+
const scoped = ['article *', 'aside *', 'nav *', 'section *'].join(',');
|
|
330
|
+
|
|
331
|
+
const svgSelectors = function(selector) {
|
|
332
|
+
return [
|
|
333
|
+
// `${selector}:has(> title:not(:empty))`,
|
|
334
|
+
// `${selector}:has(> desc:not(:empty))`,
|
|
335
|
+
`${selector}[aria-label]`,
|
|
336
|
+
`${selector}[aria-roledescription]`,
|
|
337
|
+
`${selector}[aria-labelledby]`,
|
|
338
|
+
`${selector}[aria-describedby]`,
|
|
339
|
+
`${selector}[tabindex]`,
|
|
340
|
+
`${selector}[role]`,
|
|
341
|
+
];
|
|
342
|
+
};
|
|
310
343
|
|
|
311
344
|
// https://www.w3.org/TR/html-aam-1.0/#html-element-role-mappings
|
|
312
345
|
// https://www.w3.org/TR/wai-aria/roles
|
|
@@ -318,8 +351,11 @@ exports.roles = {
|
|
|
318
351
|
'atomic': true,
|
|
319
352
|
},
|
|
320
353
|
},
|
|
354
|
+
alertdialog: {},
|
|
355
|
+
application: {},
|
|
321
356
|
article: {
|
|
322
357
|
selectors: ['article'],
|
|
358
|
+
childRoles: ['comment'],
|
|
323
359
|
},
|
|
324
360
|
banner: {
|
|
325
361
|
selectors: [`header:not(main *, ${scoped})`],
|
|
@@ -342,7 +378,7 @@ exports.roles = {
|
|
|
342
378
|
selectors: ['caption', 'figcaption'],
|
|
343
379
|
},
|
|
344
380
|
cell: {
|
|
345
|
-
selectors: ['td', 'th:not([scope])'],
|
|
381
|
+
selectors: ['td', 'td ~ th:not([scope])'],
|
|
346
382
|
childRoles: ['columnheader', 'gridcell', 'rowheader'],
|
|
347
383
|
nameFromContents: true,
|
|
348
384
|
},
|
|
@@ -379,8 +415,12 @@ exports.roles = {
|
|
|
379
415
|
},
|
|
380
416
|
},
|
|
381
417
|
command: {
|
|
418
|
+
abstract: true,
|
|
382
419
|
childRoles: ['button', 'link', 'menuitem'],
|
|
383
420
|
},
|
|
421
|
+
comment: {
|
|
422
|
+
nameFromContents: true,
|
|
423
|
+
},
|
|
384
424
|
complementary: {
|
|
385
425
|
selectors: [
|
|
386
426
|
`aside:not(${scoped})`,
|
|
@@ -390,6 +430,7 @@ exports.roles = {
|
|
|
390
430
|
],
|
|
391
431
|
},
|
|
392
432
|
composite: {
|
|
433
|
+
abstract: true,
|
|
393
434
|
childRoles: ['grid', 'select', 'spinbutton', 'tablist'],
|
|
394
435
|
},
|
|
395
436
|
contentinfo: {
|
|
@@ -405,24 +446,59 @@ exports.roles = {
|
|
|
405
446
|
selectors: ['dialog'],
|
|
406
447
|
childRoles: ['alertdialog'],
|
|
407
448
|
},
|
|
449
|
+
'doc-abstract': {},
|
|
450
|
+
'doc-acknowledgments': {},
|
|
451
|
+
'doc-afterword': {},
|
|
452
|
+
'doc-appendix': {},
|
|
408
453
|
'doc-backlink': {
|
|
409
454
|
nameFromContents: true,
|
|
410
455
|
},
|
|
456
|
+
'doc-biblioentry': {},
|
|
457
|
+
'doc-bibliography': {},
|
|
411
458
|
'doc-biblioref': {
|
|
412
459
|
nameFromContents: true,
|
|
413
460
|
},
|
|
461
|
+
'doc-chapter': {},
|
|
462
|
+
'doc-colophon': {},
|
|
463
|
+
'doc-conclusion': {},
|
|
464
|
+
'doc-cover': {},
|
|
465
|
+
'doc-credit': {},
|
|
466
|
+
'doc-credits': {},
|
|
467
|
+
'doc-dedication': {},
|
|
468
|
+
'doc-endnote': {},
|
|
469
|
+
'doc-endnotes': {},
|
|
470
|
+
'doc-epilogue': {},
|
|
471
|
+
'doc-epigraph': {},
|
|
472
|
+
'doc-errata': {},
|
|
473
|
+
'doc-example': {},
|
|
474
|
+
'doc-footnote': {},
|
|
475
|
+
'doc-foreword': {},
|
|
476
|
+
'doc-glossary': {},
|
|
414
477
|
'doc-glossref': {
|
|
415
478
|
nameFromContents: true,
|
|
416
479
|
},
|
|
480
|
+
'doc-index': {},
|
|
481
|
+
'doc-introduction': {},
|
|
417
482
|
'doc-noteref': {
|
|
418
483
|
nameFromContents: true,
|
|
419
484
|
},
|
|
485
|
+
'doc-notice': {},
|
|
420
486
|
'doc-pagebreak': {
|
|
421
487
|
nameFromContents: true,
|
|
422
488
|
},
|
|
489
|
+
'doc-pagefooter': {},
|
|
490
|
+
'doc-pageheader': {},
|
|
491
|
+
'doc-pagelist': {},
|
|
492
|
+
'doc-part': {},
|
|
493
|
+
'doc-preface': {},
|
|
494
|
+
'doc-prologue': {},
|
|
495
|
+
'doc-pullquote': {},
|
|
496
|
+
'doc-qna': {},
|
|
423
497
|
'doc-subtitle': {
|
|
424
498
|
nameFromContents: true,
|
|
425
499
|
},
|
|
500
|
+
'doc-tip': {},
|
|
501
|
+
'doc-toc': {},
|
|
426
502
|
document: {
|
|
427
503
|
selectors: ['html'],
|
|
428
504
|
childRoles: ['article', 'graphics-document'],
|
|
@@ -430,6 +506,7 @@ exports.roles = {
|
|
|
430
506
|
emphasis: {
|
|
431
507
|
selectors: ['em'],
|
|
432
508
|
},
|
|
509
|
+
feed: {},
|
|
433
510
|
figure: {
|
|
434
511
|
selectors: ['figure'],
|
|
435
512
|
childRoles: ['doc-example'],
|
|
@@ -438,11 +515,49 @@ exports.roles = {
|
|
|
438
515
|
selectors: ['form[aria-label]', 'form[aria-labelledby]', 'form[title]'],
|
|
439
516
|
},
|
|
440
517
|
generic: {
|
|
441
|
-
|
|
518
|
+
selectors: [
|
|
519
|
+
'a:not([*|href])',
|
|
520
|
+
'area:not([*|href])',
|
|
521
|
+
`aside:not(${scoped}):not([aria-label]):not([aria-labelledby]):not([title])`,
|
|
522
|
+
'b',
|
|
523
|
+
'bdi',
|
|
524
|
+
'bdo',
|
|
525
|
+
'body',
|
|
526
|
+
'data',
|
|
527
|
+
'div',
|
|
528
|
+
// footer scoped
|
|
529
|
+
// header scoped
|
|
530
|
+
'i',
|
|
531
|
+
'li:not(ul > li):not(ol > li)',
|
|
532
|
+
'pre',
|
|
533
|
+
'q',
|
|
534
|
+
'samp',
|
|
535
|
+
'section:not([aria-label]):not([aria-labelledby]):not([title])',
|
|
536
|
+
'small',
|
|
537
|
+
'span',
|
|
538
|
+
'u',
|
|
539
|
+
],
|
|
442
540
|
},
|
|
443
541
|
'graphics-document': {
|
|
444
542
|
selectors: ['svg'],
|
|
445
543
|
},
|
|
544
|
+
'graphics-object': {
|
|
545
|
+
selectors: [
|
|
546
|
+
...svgSelectors('symbol'),
|
|
547
|
+
...svgSelectors('use'),
|
|
548
|
+
],
|
|
549
|
+
},
|
|
550
|
+
'graphics-symbol': {
|
|
551
|
+
selectors: [
|
|
552
|
+
...svgSelectors('circle'),
|
|
553
|
+
...svgSelectors('ellipse'),
|
|
554
|
+
...svgSelectors('line'),
|
|
555
|
+
...svgSelectors('path'),
|
|
556
|
+
...svgSelectors('polygon'),
|
|
557
|
+
...svgSelectors('polyline'),
|
|
558
|
+
...svgSelectors('rect'),
|
|
559
|
+
],
|
|
560
|
+
},
|
|
446
561
|
grid: {
|
|
447
562
|
childRoles: ['treegrid'],
|
|
448
563
|
},
|
|
@@ -457,7 +572,11 @@ exports.roles = {
|
|
|
457
572
|
'fieldset',
|
|
458
573
|
'hgroup',
|
|
459
574
|
'optgroup',
|
|
575
|
+
...svgSelectors('foreignObject'),
|
|
576
|
+
...svgSelectors('g'),
|
|
460
577
|
'text',
|
|
578
|
+
...svgSelectors('textPath'),
|
|
579
|
+
...svgSelectors('tspan'),
|
|
461
580
|
],
|
|
462
581
|
childRoles: ['row', 'select', 'toolbar', 'graphics-object'],
|
|
463
582
|
},
|
|
@@ -468,11 +587,17 @@ exports.roles = {
|
|
|
468
587
|
'level': 2,
|
|
469
588
|
},
|
|
470
589
|
},
|
|
471
|
-
|
|
472
|
-
selectors: [
|
|
590
|
+
image: {
|
|
591
|
+
selectors: [
|
|
592
|
+
'img:not([alt=""])',
|
|
593
|
+
'graphics-symbol',
|
|
594
|
+
...svgSelectors('image'),
|
|
595
|
+
...svgSelectors('mesh'),
|
|
596
|
+
],
|
|
473
597
|
childRoles: ['doc-cover'],
|
|
474
598
|
},
|
|
475
599
|
input: {
|
|
600
|
+
abstract: true,
|
|
476
601
|
childRoles: [
|
|
477
602
|
'checkbox',
|
|
478
603
|
'combobox',
|
|
@@ -487,6 +612,7 @@ exports.roles = {
|
|
|
487
612
|
selectors: ['ins'],
|
|
488
613
|
},
|
|
489
614
|
landmark: {
|
|
615
|
+
abstract: true,
|
|
490
616
|
childRoles: [
|
|
491
617
|
'banner',
|
|
492
618
|
'complementary',
|
|
@@ -515,13 +641,13 @@ exports.roles = {
|
|
|
515
641
|
],
|
|
516
642
|
},
|
|
517
643
|
link: {
|
|
518
|
-
selectors: ['a[href]', 'area[href]'],
|
|
644
|
+
selectors: ['a[*|href]', 'area[href]'],
|
|
519
645
|
childRoles: ['doc-backlink', 'doc-biblioref', 'doc-glossref', 'doc-noteref'],
|
|
520
646
|
nameFromContents: true,
|
|
521
647
|
},
|
|
522
648
|
list: {
|
|
523
649
|
selectors: ['dl', 'ol', 'ul', 'menu'],
|
|
524
|
-
childRoles: ['
|
|
650
|
+
childRoles: ['feed'],
|
|
525
651
|
},
|
|
526
652
|
listbox: {
|
|
527
653
|
selectors: [
|
|
@@ -534,7 +660,7 @@ exports.roles = {
|
|
|
534
660
|
},
|
|
535
661
|
},
|
|
536
662
|
listitem: {
|
|
537
|
-
selectors: ['li'],
|
|
663
|
+
selectors: ['ol > li', 'ul > li'],
|
|
538
664
|
childRoles: ['doc-biblioentry', 'doc-endnote', 'treeitem'],
|
|
539
665
|
},
|
|
540
666
|
log: {
|
|
@@ -545,6 +671,10 @@ exports.roles = {
|
|
|
545
671
|
main: {
|
|
546
672
|
selectors: ['main'],
|
|
547
673
|
},
|
|
674
|
+
mark: {
|
|
675
|
+
selectors: ['mark'],
|
|
676
|
+
},
|
|
677
|
+
marquee: {},
|
|
548
678
|
math: {
|
|
549
679
|
selectors: ['math'],
|
|
550
680
|
},
|
|
@@ -567,11 +697,10 @@ exports.roles = {
|
|
|
567
697
|
},
|
|
568
698
|
},
|
|
569
699
|
menuitem: {
|
|
570
|
-
childRoles: ['menuitemcheckbox'],
|
|
700
|
+
childRoles: ['menuitemcheckbox', 'menuitemradio'],
|
|
571
701
|
nameFromContents: true,
|
|
572
702
|
},
|
|
573
703
|
menuitemcheckbox: {
|
|
574
|
-
childRoles: ['menuitemradio'],
|
|
575
704
|
nameFromContents: true,
|
|
576
705
|
defaults: {
|
|
577
706
|
'checked': 'false',
|
|
@@ -587,6 +716,9 @@ exports.roles = {
|
|
|
587
716
|
selectors: ['nav'],
|
|
588
717
|
childRoles: ['doc-index', 'doc-pagelist', 'doc-toc'],
|
|
589
718
|
},
|
|
719
|
+
none: {
|
|
720
|
+
selectors: ['img[alt=""]'],
|
|
721
|
+
},
|
|
590
722
|
note: {
|
|
591
723
|
childRoles: ['doc-notice', 'doc-tip'],
|
|
592
724
|
},
|
|
@@ -601,9 +733,6 @@ exports.roles = {
|
|
|
601
733
|
paragraph: {
|
|
602
734
|
selectors: ['p'],
|
|
603
735
|
},
|
|
604
|
-
presentation: {
|
|
605
|
-
selectors: ['img[alt=""]'],
|
|
606
|
-
},
|
|
607
736
|
progressbar: {
|
|
608
737
|
selectors: ['progress'],
|
|
609
738
|
defaults: {
|
|
@@ -619,13 +748,16 @@ exports.roles = {
|
|
|
619
748
|
'checked': 'false',
|
|
620
749
|
},
|
|
621
750
|
},
|
|
751
|
+
radiogroup: {},
|
|
622
752
|
range: {
|
|
753
|
+
abstract: true,
|
|
623
754
|
childRoles: ['meter', 'progressbar', 'scrollbar', 'slider', 'spinbutton'],
|
|
624
755
|
},
|
|
625
756
|
region: {
|
|
626
757
|
selectors: ['section[aria-label]', 'section[aria-labelledby]', 'section[title]'],
|
|
627
758
|
},
|
|
628
759
|
roletype: {
|
|
760
|
+
abstract: true,
|
|
629
761
|
childRoles: ['structure', 'widget', 'window'],
|
|
630
762
|
},
|
|
631
763
|
row: {
|
|
@@ -636,7 +768,7 @@ exports.roles = {
|
|
|
636
768
|
selectors: ['tbody', 'thead', 'tfoot'],
|
|
637
769
|
},
|
|
638
770
|
rowheader: {
|
|
639
|
-
selectors: ['th[scope="row"]'],
|
|
771
|
+
selectors: ['th[scope="row"]', 'th:not([scope]):not(td ~ th)'],
|
|
640
772
|
nameFromContents: true,
|
|
641
773
|
},
|
|
642
774
|
scrollbar: {
|
|
@@ -653,6 +785,7 @@ exports.roles = {
|
|
|
653
785
|
selectors: ['input[type="search"]:not([list])'],
|
|
654
786
|
},
|
|
655
787
|
section: {
|
|
788
|
+
abstract: true,
|
|
656
789
|
childRoles: [
|
|
657
790
|
'alert',
|
|
658
791
|
'blockquote',
|
|
@@ -674,12 +807,13 @@ exports.roles = {
|
|
|
674
807
|
'emphasis',
|
|
675
808
|
'figure',
|
|
676
809
|
'group',
|
|
677
|
-
'
|
|
810
|
+
'image',
|
|
678
811
|
'insertion',
|
|
679
812
|
'landmark',
|
|
680
813
|
'list',
|
|
681
814
|
'listitem',
|
|
682
815
|
'log',
|
|
816
|
+
'mark',
|
|
683
817
|
'marquee',
|
|
684
818
|
'math',
|
|
685
819
|
'note',
|
|
@@ -687,6 +821,7 @@ exports.roles = {
|
|
|
687
821
|
'status',
|
|
688
822
|
'strong',
|
|
689
823
|
'subscript',
|
|
824
|
+
'suggestion',
|
|
690
825
|
'superscript',
|
|
691
826
|
'table',
|
|
692
827
|
'tabpanel',
|
|
@@ -696,6 +831,7 @@ exports.roles = {
|
|
|
696
831
|
],
|
|
697
832
|
},
|
|
698
833
|
sectionhead: {
|
|
834
|
+
abstract: true,
|
|
699
835
|
childRoles: [
|
|
700
836
|
'columnheader',
|
|
701
837
|
'doc-subtitle',
|
|
@@ -706,6 +842,7 @@ exports.roles = {
|
|
|
706
842
|
nameFromContents: true,
|
|
707
843
|
},
|
|
708
844
|
select: {
|
|
845
|
+
abstract: true,
|
|
709
846
|
childRoles: ['listbox', 'menu', 'radiogroup', 'tree'],
|
|
710
847
|
},
|
|
711
848
|
separator: {
|
|
@@ -746,12 +883,12 @@ exports.roles = {
|
|
|
746
883
|
selectors: ['strong'],
|
|
747
884
|
},
|
|
748
885
|
structure: {
|
|
886
|
+
abstract: true,
|
|
749
887
|
childRoles: [
|
|
750
888
|
'application',
|
|
751
889
|
'document',
|
|
752
890
|
'none',
|
|
753
891
|
'generic',
|
|
754
|
-
'presentation',
|
|
755
892
|
'range',
|
|
756
893
|
'rowgroup',
|
|
757
894
|
'section',
|
|
@@ -759,6 +896,7 @@ exports.roles = {
|
|
|
759
896
|
'separator',
|
|
760
897
|
],
|
|
761
898
|
},
|
|
899
|
+
suggestion: {},
|
|
762
900
|
subscript: {
|
|
763
901
|
selectors: ['sub'],
|
|
764
902
|
},
|
|
@@ -786,6 +924,7 @@ exports.roles = {
|
|
|
786
924
|
'orientation': 'horizontal',
|
|
787
925
|
},
|
|
788
926
|
},
|
|
927
|
+
tabpanel: {},
|
|
789
928
|
term: {
|
|
790
929
|
selectors: ['dfn', 'dt'],
|
|
791
930
|
},
|
|
@@ -822,10 +961,12 @@ exports.roles = {
|
|
|
822
961
|
'orientation': 'vertical',
|
|
823
962
|
},
|
|
824
963
|
},
|
|
964
|
+
treegrid: {},
|
|
825
965
|
treeitem: {
|
|
826
966
|
nameFromContents: true,
|
|
827
967
|
},
|
|
828
968
|
widget: {
|
|
969
|
+
abstract: true,
|
|
829
970
|
childRoles: [
|
|
830
971
|
'command',
|
|
831
972
|
'composite',
|
|
@@ -839,15 +980,16 @@ exports.roles = {
|
|
|
839
980
|
],
|
|
840
981
|
},
|
|
841
982
|
window: {
|
|
983
|
+
abstract: true,
|
|
842
984
|
childRoles: ['dialog'],
|
|
843
985
|
},
|
|
844
986
|
};
|
|
845
987
|
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
988
|
+
const getSubRoles = function(role) {
|
|
989
|
+
const children = (exports.roles[role]).childRoles || [];
|
|
990
|
+
const descendents = children.map(getSubRoles);
|
|
849
991
|
|
|
850
|
-
|
|
992
|
+
const result = [role];
|
|
851
993
|
|
|
852
994
|
descendents.forEach(list => {
|
|
853
995
|
list.forEach(r => {
|
|
@@ -862,18 +1004,20 @@ var getSubRoles = function(role) {
|
|
|
862
1004
|
|
|
863
1005
|
exports.attrsWithDefaults = [];
|
|
864
1006
|
|
|
865
|
-
for (
|
|
1007
|
+
for (const role in exports.roles) {
|
|
866
1008
|
exports.roles[role].subRoles = getSubRoles(role);
|
|
867
|
-
for (
|
|
1009
|
+
for (const key in exports.roles[role].defaults) {
|
|
868
1010
|
if (!exports.attrsWithDefaults.includes(key)) {
|
|
869
1011
|
exports.attrsWithDefaults.push(key);
|
|
870
1012
|
}
|
|
871
1013
|
}
|
|
872
1014
|
}
|
|
873
|
-
|
|
874
|
-
exports.
|
|
875
|
-
|
|
876
|
-
|
|
1015
|
+
|
|
1016
|
+
exports.aliases = {
|
|
1017
|
+
'presentation': 'none',
|
|
1018
|
+
'directory': 'list',
|
|
1019
|
+
'img': 'image',
|
|
1020
|
+
};
|
|
877
1021
|
|
|
878
1022
|
exports.nameFromDescendant = {
|
|
879
1023
|
'figure': 'figcaption',
|
|
@@ -888,45 +1032,59 @@ exports.nameDefaults = {
|
|
|
888
1032
|
};
|
|
889
1033
|
|
|
890
1034
|
},{}],5:[function(require,module,exports){
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
1035
|
+
const constants = require('./constants.js');
|
|
1036
|
+
const atree = require('./atree.js');
|
|
1037
|
+
const query = require('./query.js');
|
|
1038
|
+
|
|
1039
|
+
const addSpaces = function(text, el, pseudoSelector) {
|
|
1040
|
+
// https://github.com/w3c/accname/issues/3
|
|
1041
|
+
const styles = window.getComputedStyle(el, pseudoSelector);
|
|
1042
|
+
const inline = styles.display === 'inline';
|
|
1043
|
+
return inline ? text : ` ${text} `;
|
|
1044
|
+
};
|
|
1045
|
+
|
|
1046
|
+
const getPseudoContent = function(el, pseudoSelector) {
|
|
1047
|
+
const styles = window.getComputedStyle(el, pseudoSelector);
|
|
1048
|
+
let tail = styles.getPropertyValue('content').trim();
|
|
1049
|
+
let ret = [];
|
|
1050
|
+
|
|
1051
|
+
let match;
|
|
1052
|
+
while (tail.length) {
|
|
1053
|
+
if (match = tail.match(/^"([^"]*)"/)) {
|
|
1054
|
+
ret.push(match[1]);
|
|
1055
|
+
} else if (match = tail.match(/^([a-z-]+)\(([^)]*)\)/)) {
|
|
1056
|
+
if (match[1] === 'attr') {
|
|
1057
|
+
ret.push(el.getAttribute(match[2]) || '');
|
|
1058
|
+
}
|
|
1059
|
+
} else if (match = tail.match(/^([a-z-]+)/)) {
|
|
1060
|
+
if (match[1] === 'open-quote' || match[1] === 'close-quote') {
|
|
1061
|
+
ret.push('"');
|
|
1062
|
+
}
|
|
1063
|
+
} else if (match = tail.match(/^\//)) {
|
|
1064
|
+
ret = [];
|
|
907
1065
|
} else {
|
|
908
|
-
|
|
1066
|
+
// invalid content, ignore
|
|
1067
|
+
return '';
|
|
909
1068
|
}
|
|
1069
|
+
tail = tail.slice(match[0].length).trim();
|
|
910
1070
|
}
|
|
1071
|
+
|
|
1072
|
+
return addSpaces(ret.join(''), el, pseudoSelector);
|
|
911
1073
|
};
|
|
912
1074
|
|
|
913
|
-
|
|
914
|
-
|
|
1075
|
+
const getContent = function(root, ongoingLabelledBy, visited) {
|
|
1076
|
+
const children = atree.getChildNodes(root);
|
|
915
1077
|
|
|
916
|
-
|
|
917
|
-
for (
|
|
918
|
-
|
|
1078
|
+
let ret = '';
|
|
1079
|
+
for (let i = 0; i < children.length; i++) {
|
|
1080
|
+
const node = children[i];
|
|
919
1081
|
if (node.nodeType === node.TEXT_NODE) {
|
|
920
1082
|
ret += node.textContent;
|
|
921
1083
|
} else if (node.nodeType === node.ELEMENT_NODE) {
|
|
922
1084
|
if (node.tagName.toLowerCase() === 'br') {
|
|
923
1085
|
ret += '\n';
|
|
924
|
-
} else if (window.getComputedStyle(node).display.substr(0, 6) === 'inline' &&
|
|
925
|
-
node.tagName.toLowerCase() !== 'input' &&
|
|
926
|
-
node.tagName.toLowerCase() !== 'img') { // https://github.com/w3c/accname/issues/3
|
|
927
|
-
ret += getName(node, true, visited);
|
|
928
1086
|
} else {
|
|
929
|
-
ret +=
|
|
1087
|
+
ret += getName(node, true, ongoingLabelledBy, visited);
|
|
930
1088
|
}
|
|
931
1089
|
}
|
|
932
1090
|
}
|
|
@@ -934,18 +1092,15 @@ var getContent = function(root, visited) {
|
|
|
934
1092
|
return ret;
|
|
935
1093
|
};
|
|
936
1094
|
|
|
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));
|
|
1095
|
+
const allowNameFromContent = function(el) {
|
|
1096
|
+
const role = query.getRole(el);
|
|
1097
|
+
if (role) {
|
|
1098
|
+
return constants.roles[role].nameFromContents;
|
|
1099
|
+
}
|
|
945
1100
|
};
|
|
946
1101
|
|
|
947
|
-
|
|
948
|
-
|
|
1102
|
+
const getName = function(el, recursive, ongoingLabelledBy, visited, directReference) {
|
|
1103
|
+
let ret = '';
|
|
949
1104
|
|
|
950
1105
|
visited = visited || [];
|
|
951
1106
|
if (visited.includes(el)) {
|
|
@@ -960,15 +1115,31 @@ var getName = function(el, recursive, visited, directReference) {
|
|
|
960
1115
|
// handled in atree
|
|
961
1116
|
|
|
962
1117
|
// B
|
|
963
|
-
if (!
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
return label ? getName(label, true, visited, true) : '';
|
|
1118
|
+
if (!ongoingLabelledBy && el.matches('[aria-labelledby]')) {
|
|
1119
|
+
const ids = el.getAttribute('aria-labelledby').split(/\s+/);
|
|
1120
|
+
const strings = ids.map(id => {
|
|
1121
|
+
const label = document.getElementById(id);
|
|
1122
|
+
return label ? getName(label, true, true, visited, true) : '';
|
|
968
1123
|
});
|
|
969
1124
|
ret = strings.join(' ');
|
|
970
1125
|
}
|
|
971
1126
|
|
|
1127
|
+
// E (the current draft has this at this high priority)
|
|
1128
|
+
if (!ret.trim() && recursive) {
|
|
1129
|
+
if (query.matches(el, 'textbox')) {
|
|
1130
|
+
ret = el.value || el.textContent;
|
|
1131
|
+
} else if (query.matches(el, 'combobox,listbox')) {
|
|
1132
|
+
const selected = query.querySelector(el, ':selected') || query.querySelector(el, 'option');
|
|
1133
|
+
if (selected) {
|
|
1134
|
+
ret = getName(selected, recursive, ongoingLabelledBy, visited);
|
|
1135
|
+
} else {
|
|
1136
|
+
ret = el.value || '';
|
|
1137
|
+
}
|
|
1138
|
+
} else if (query.matches(el, 'range')) {
|
|
1139
|
+
ret = '' + (query.getAttribute(el, 'valuetext') || query.getAttribute(el, 'valuenow') || el.value);
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
|
|
972
1143
|
// C
|
|
973
1144
|
if (!ret.trim() && el.matches('[aria-label]')) {
|
|
974
1145
|
// FIXME: may skip to 2E
|
|
@@ -977,14 +1148,11 @@ var getName = function(el, recursive, visited, directReference) {
|
|
|
977
1148
|
|
|
978
1149
|
// D
|
|
979
1150
|
if (!ret.trim() && !recursive && el.labels) {
|
|
980
|
-
|
|
981
|
-
return getName(label, true, visited);
|
|
1151
|
+
const strings = Array.prototype.map.call(el.labels, label => {
|
|
1152
|
+
return getName(label, true, ongoingLabelledBy, visited);
|
|
982
1153
|
});
|
|
983
1154
|
ret = strings.join(' ');
|
|
984
1155
|
}
|
|
985
|
-
if (!ret.trim()) {
|
|
986
|
-
ret = el.placeholder || '';
|
|
987
|
-
}
|
|
988
1156
|
if (!ret.trim()) {
|
|
989
1157
|
ret = el.alt || '';
|
|
990
1158
|
}
|
|
@@ -992,48 +1160,37 @@ var getName = function(el, recursive, visited, directReference) {
|
|
|
992
1160
|
ret = el.title;
|
|
993
1161
|
}
|
|
994
1162
|
if (!ret.trim()) {
|
|
995
|
-
for (
|
|
1163
|
+
for (const selector in constants.nameFromDescendant) {
|
|
996
1164
|
if (el.matches(selector)) {
|
|
997
|
-
|
|
1165
|
+
const descendant = el.querySelector(constants.nameFromDescendant[selector]);
|
|
998
1166
|
if (descendant) {
|
|
999
|
-
ret = getName(descendant, true, visited);
|
|
1167
|
+
ret = getName(descendant, true, ongoingLabelledBy, visited);
|
|
1000
1168
|
}
|
|
1001
1169
|
}
|
|
1002
1170
|
}
|
|
1003
1171
|
}
|
|
1004
1172
|
if (!ret.trim() && el.matches('svg *')) {
|
|
1005
|
-
|
|
1173
|
+
const svgTitle = el.querySelector('title');
|
|
1006
1174
|
if (svgTitle && svgTitle.parentElement === el) {
|
|
1007
1175
|
ret = svgTitle.textContent;
|
|
1008
1176
|
}
|
|
1009
1177
|
}
|
|
1010
|
-
|
|
1011
|
-
|
|
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
|
-
}
|
|
1178
|
+
if (!ret.trim() && el.matches('a')) {
|
|
1179
|
+
ret = el.getAttribute('xlink:title') || '';
|
|
1027
1180
|
}
|
|
1028
1181
|
|
|
1029
1182
|
// F
|
|
1030
1183
|
// FIXME: menu is not mentioned in the spec
|
|
1031
1184
|
if (!ret.trim() && (recursive || allowNameFromContent(el) || el.closest('label')) && !query.matches(el, 'menu')) {
|
|
1032
|
-
ret = getContent(el, visited);
|
|
1185
|
+
ret = getContent(el, ongoingLabelledBy, visited);
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
if (!ret.trim() && query.matches(el, 'button')) {
|
|
1189
|
+
ret = el.value || '';
|
|
1033
1190
|
}
|
|
1034
1191
|
|
|
1035
1192
|
if (!ret.trim()) {
|
|
1036
|
-
for (
|
|
1193
|
+
for (const selector in constants.nameDefaults) {
|
|
1037
1194
|
if (el.matches(selector)) {
|
|
1038
1195
|
ret = constants.nameDefaults[selector];
|
|
1039
1196
|
}
|
|
@@ -1044,9 +1201,8 @@ var getName = function(el, recursive, visited, directReference) {
|
|
|
1044
1201
|
// handled in getContent
|
|
1045
1202
|
|
|
1046
1203
|
// I
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
ret = el.title || '';
|
|
1204
|
+
if (!ret.trim()) {
|
|
1205
|
+
ret = el.title || el.placeholder || '';
|
|
1050
1206
|
}
|
|
1051
1207
|
|
|
1052
1208
|
// FIXME: not exactly sure about this, but it reduces the number of failing
|
|
@@ -1055,35 +1211,41 @@ var getName = function(el, recursive, visited, directReference) {
|
|
|
1055
1211
|
ret = ' ';
|
|
1056
1212
|
}
|
|
1057
1213
|
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
return before + ret + after;
|
|
1214
|
+
const before = getPseudoContent(el, ':before');
|
|
1215
|
+
const after = getPseudoContent(el, ':after');
|
|
1216
|
+
return addSpaces(before + ret + after, el);
|
|
1061
1217
|
};
|
|
1062
1218
|
|
|
1063
|
-
|
|
1064
|
-
return getName(el)
|
|
1219
|
+
const getNameTrimmed = function(el) {
|
|
1220
|
+
return getName(el)
|
|
1221
|
+
.replace(/[ \n\r\t\f]+/g, ' ')
|
|
1222
|
+
.replace(/^ /, '')
|
|
1223
|
+
.replace(/ $/, '');
|
|
1065
1224
|
};
|
|
1066
1225
|
|
|
1067
|
-
|
|
1068
|
-
|
|
1226
|
+
const getDescription = function(el) {
|
|
1227
|
+
let ret = '';
|
|
1069
1228
|
|
|
1070
1229
|
if (el.matches('[aria-describedby]')) {
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
return label ? getName(label, true) : '';
|
|
1230
|
+
const ids = el.getAttribute('aria-describedby').split(/\s+/);
|
|
1231
|
+
const strings = ids.map(id => {
|
|
1232
|
+
const label = document.getElementById(id);
|
|
1233
|
+
return label ? getName(label, true, true) : '';
|
|
1075
1234
|
});
|
|
1076
1235
|
ret = strings.join(' ');
|
|
1077
1236
|
} else if (el.matches('[aria-description]')) {
|
|
1078
1237
|
ret = el.getAttribute('aria-description');
|
|
1079
1238
|
} else if (el.matches('svg *')) {
|
|
1080
|
-
|
|
1239
|
+
const svgDesc = el.querySelector('desc');
|
|
1081
1240
|
if (svgDesc && svgDesc.parentElement === el) {
|
|
1082
1241
|
ret = svgDesc.textContent;
|
|
1083
1242
|
}
|
|
1084
1243
|
} else if (el.title) {
|
|
1085
1244
|
ret = el.title;
|
|
1086
1245
|
}
|
|
1246
|
+
if (!ret.trim() && el.matches('a')) {
|
|
1247
|
+
ret = el.getAttribute('xlink:title') || '';
|
|
1248
|
+
}
|
|
1087
1249
|
|
|
1088
1250
|
ret = (ret || '').trim().replace(/\s+/g, ' ');
|
|
1089
1251
|
|
|
@@ -1100,34 +1262,32 @@ module.exports = {
|
|
|
1100
1262
|
};
|
|
1101
1263
|
|
|
1102
1264
|
},{"./atree.js":2,"./constants.js":4,"./query.js":6}],6:[function(require,module,exports){
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1265
|
+
const attrs = require('./attrs.js');
|
|
1266
|
+
const atree = require('./atree.js');
|
|
1106
1267
|
|
|
1107
|
-
var matches = function(el, selector) {
|
|
1108
|
-
var actual;
|
|
1109
1268
|
|
|
1269
|
+
const matches = function(el, selector) {
|
|
1110
1270
|
if (selector.substr(0, 1) === ':') {
|
|
1111
|
-
|
|
1271
|
+
const attr = selector.substr(1);
|
|
1112
1272
|
return attrs.getAttribute(el, attr);
|
|
1113
1273
|
} else if (selector.substr(0, 1) === '[') {
|
|
1114
|
-
|
|
1115
|
-
actual = attrs.getAttribute(el, match[1]);
|
|
1116
|
-
|
|
1274
|
+
const match = /\[([a-z]+)="(.*)"\]/.exec(selector);
|
|
1275
|
+
const actual = attrs.getAttribute(el, match[1]);
|
|
1276
|
+
const rawValue = match[2];
|
|
1117
1277
|
return actual.toString() === rawValue;
|
|
1118
1278
|
} else {
|
|
1119
1279
|
return attrs.hasRole(el, selector.split(','));
|
|
1120
1280
|
}
|
|
1121
1281
|
};
|
|
1122
1282
|
|
|
1123
|
-
|
|
1124
|
-
return function(root,
|
|
1125
|
-
|
|
1283
|
+
const _querySelector = function(all) {
|
|
1284
|
+
return function(root, selector) {
|
|
1285
|
+
const results = [];
|
|
1126
1286
|
try {
|
|
1127
1287
|
atree.walk(root, node => {
|
|
1128
1288
|
if (node.nodeType === node.ELEMENT_NODE) {
|
|
1129
1289
|
// FIXME: skip hidden elements
|
|
1130
|
-
if (matches(node,
|
|
1290
|
+
if (matches(node, selector)) {
|
|
1131
1291
|
results.push(node);
|
|
1132
1292
|
if (!all) {
|
|
1133
1293
|
throw 'StopIteration';
|
|
@@ -1144,7 +1304,7 @@ var _querySelector = function(all) {
|
|
|
1144
1304
|
};
|
|
1145
1305
|
};
|
|
1146
1306
|
|
|
1147
|
-
|
|
1307
|
+
const closest = function(el, selector) {
|
|
1148
1308
|
return atree.searchUp(el, candidate => {
|
|
1149
1309
|
if (candidate.nodeType === candidate.ELEMENT_NODE) {
|
|
1150
1310
|
return matches(candidate, selector);
|