Skip to content

Commit a2696c2

Browse files
feat(polyfill): add basic aom support
1 parent 8af4402 commit a2696c2

File tree

6 files changed

+88
-2
lines changed

6 files changed

+88
-2
lines changed

Diff for: README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,5 @@ The currently-supported features of `ElementInternals` for form-associated custo
5757

5858
## Current limitations
5959

60-
Right now providing a cross-browser compliant version of `ElementInternals.reportValidity` is not supported. The method essentially behaves as a proxy for `ElementInternals.checkValidity`.
60+
- Right now providing a cross-browser compliant version of `ElementInternals.reportValidity` is not supported. The method essentially behaves as a proxy for `ElementInternals.checkValidity`.
61+
- The polyfill does support the outcomes of the [Accessibility Object Model](https://wicg.github.io/aom/explainer.html#) for applying accessibility rules on the DOM object. However, the spec states that updates using AOM will not be reflected by DOM attributes, but only on the element's accesibility object. However, to emulate this behavior before it is fully supported, it is necessary to use the attributes. If you choose to use this feature, please note that behavior in polyfilled browsers and non-polyfilled browsers will be different; however, the outcome for users will be the same.

Diff for: src/aom.js

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { upgradeMap } from './maps.js';
2+
3+
export const aom = {
4+
ariaAtomic: 'aria-atomic',
5+
ariaAutoComplete: 'aria-autocomplete',
6+
ariaBusy: 'aria-busy',
7+
ariaChecked: 'aria-checked',
8+
ariaColCount: 'aria-colcount',
9+
ariaConIndex: 'aria-colindex',
10+
ariaColSpan: 'aria-colspan',
11+
ariaCurrent: 'aria-current',
12+
ariaDisabled: 'aria-disabled',
13+
ariaExpanded: 'aria-expanded',
14+
ariaHasPopup: 'aria-haspopup',
15+
ariaHidden: 'aria-hidden',
16+
ariaKeyShortcuts: 'aria-keyshortcuts',
17+
ariaLabel: 'aria-label',
18+
ariaLevel: 'aria-level',
19+
ariaLive: 'aria-live',
20+
ariaModal: 'aria-modal',
21+
ariaMultiLine: 'aria-multiline',
22+
ariaMultiSelectable: 'aria-multiselectable',
23+
ariaOrientation: 'aria-orientation',
24+
ariaPlaceholder: 'aria-placeholder',
25+
ariaPosInSet: 'aria-posinset',
26+
ariaPressed: 'aria-pressed',
27+
ariaReadOnly: 'aria-readonly',
28+
ariaRelevant: 'aria-relevant',
29+
ariaRequired: 'aria-required',
30+
ariaRoleDescription: 'aria-roledescription',
31+
ariaRowCount: 'aria-rowcount',
32+
ariaRowIndex: 'aria-rowindex',
33+
ariaRowSpan: 'aria-rowspan',
34+
ariaSelected: 'aria-selected',
35+
ariaSort: 'aria-sort',
36+
ariaValueMax: 'aria-valuemax',
37+
ariaValueMin: 'aria-valuemin',
38+
ariaValueNow: 'aria-valuenow',
39+
ariaValueText: 'aria-valuetext'
40+
};
41+
42+
export const initAom = (ref, internals) => {
43+
for (let key in aom) {
44+
internals[key] = null;
45+
46+
let closureValue = null;
47+
const attributeName = aom[key];
48+
Object.defineProperty(internals, key, {
49+
get() {
50+
return closureValue;
51+
},
52+
set(value) {
53+
closureValue = value;
54+
if (ref.isConnected) {
55+
ref.setAttribute(attributeName, value);
56+
} else {
57+
upgradeMap.set(ref, internals);
58+
}
59+
}
60+
});
61+
}
62+
};

Diff for: src/element-internals.js

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
formElementsMap,
88
refValueMap
99
} from './maps.js';
10+
import { aom, initAom } from './aom.js';
1011
import { getHostRoot, initRef, initLabels, initForm, findParentForm } from './utils.js';
1112
import { ValidityState, reconcileValidty, setValid } from './ValidityState.js';
1213
import { observerCallback, observerConfig } from './mutation-observers.js';
@@ -21,6 +22,7 @@ class ElementInternals {
2122
validityMap.set(this, validity);
2223
internalsMap.set(ref, this);
2324
const { labels, form } = this;
25+
initAom(ref, this);
2426
Object.seal(this);
2527

2628
initRef(ref);

Diff for: src/maps.js

+7
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,10 @@ export const formElementsMap = new WeakMap();
2727
* @type {WeakMap<HTMLElement, any>}
2828
*/
2929
export const refValueMap = new WeakMap();
30+
31+
32+
/**
33+
* Elements that need to be upgraded once added to the DOM
34+
* @type {WeakMap<HTMLElement, ElemntInternals>}
35+
*/
36+
export const upgradeMap = new WeakMap();

Diff for: src/mutation-observers.js

+14-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { internalsMap, shadowHostsMap } from './maps.js';
1+
import { internalsMap, shadowHostsMap, upgradeMap } from './maps.js';
2+
import { aom } from './aom.js';
23
import { initForm } from './utils.js';
34

45
export function observerCallback(mutationList) {
@@ -11,6 +12,18 @@ export function observerCallback(mutationList) {
1112

1213
initForm(node, form, internals);
1314
}
15+
16+
if (upgradeMap.has(node)) {
17+
const internals = upgradeMap.get(node);
18+
const aomKeys = Object.keys(aom);
19+
aomKeys
20+
.filter(key => internals[key] !== null)
21+
.forEach(key => {
22+
console.log({key})
23+
node.setAttribute(aom[key], internals[key]);
24+
});
25+
upgradeMap.delete(node);
26+
}
1427
});
1528

1629
Array.from(removedNodes).forEach(node => {

Diff for: static/scripts/foo-bar.js

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export class FooBar extends HTMLElement {
99
delegatesFocus: true
1010
});
1111
this.internals_ = this.attachInternals();
12+
this.internals_.ariaChecked = true;
1213
this._handleChanges = this._handleChanges.bind(this);
1314
}
1415

0 commit comments

Comments
 (0)