wicg-inert 3.0.1 → 3.1.1

Sign up to get free protection for your applications and to get access to all the features.
package/dist/inert.js CHANGED
@@ -13,821 +13,828 @@
13
13
  * (http://www.w3.org/Consortium/Legal/2015/copyright-software-and-document).
14
14
  */
15
15
 
16
- // Convenience function for converting NodeLists.
17
- /** @type {typeof Array.prototype.slice} */
18
- var slice = Array.prototype.slice;
19
-
20
- /**
21
- * IE has a non-standard name for "matches".
22
- * @type {typeof Element.prototype.matches}
23
- */
24
- var matches = Element.prototype.matches || Element.prototype.msMatchesSelector;
25
-
26
- /** @type {string} */
27
- var _focusableElementsString = ['a[href]', 'area[href]', 'input:not([disabled])', 'select:not([disabled])', 'textarea:not([disabled])', 'button:not([disabled])', 'details', 'summary', 'iframe', 'object', 'embed', '[contenteditable]'].join(',');
16
+ (function () {
17
+ // Return early if we're not running inside of the browser.
18
+ if (typeof window === 'undefined') {
19
+ return;
20
+ }
28
21
 
29
- /**
30
- * `InertRoot` manages a single inert subtree, i.e. a DOM subtree whose root element has an `inert`
31
- * attribute.
32
- *
33
- * Its main functions are:
34
- *
35
- * - to create and maintain a set of managed `InertNode`s, including when mutations occur in the
36
- * subtree. The `makeSubtreeUnfocusable()` method handles collecting `InertNode`s via registering
37
- * each focusable node in the subtree with the singleton `InertManager` which manages all known
38
- * focusable nodes within inert subtrees. `InertManager` ensures that a single `InertNode`
39
- * instance exists for each focusable node which has at least one inert root as an ancestor.
40
- *
41
- * - to notify all managed `InertNode`s when this subtree stops being inert (i.e. when the `inert`
42
- * attribute is removed from the root node). This is handled in the destructor, which calls the
43
- * `deregister` method on `InertManager` for each managed inert node.
44
- */
22
+ // Convenience function for converting NodeLists.
23
+ /** @type {typeof Array.prototype.slice} */
24
+ var slice = Array.prototype.slice;
45
25
 
46
- var InertRoot = function () {
47
26
  /**
48
- * @param {!Element} rootElement The Element at the root of the inert subtree.
49
- * @param {!InertManager} inertManager The global singleton InertManager object.
27
+ * IE has a non-standard name for "matches".
28
+ * @type {typeof Element.prototype.matches}
50
29
  */
51
- function InertRoot(rootElement, inertManager) {
52
- _classCallCheck(this, InertRoot);
30
+ var matches = Element.prototype.matches || Element.prototype.msMatchesSelector;
53
31
 
54
- /** @type {!InertManager} */
55
- this._inertManager = inertManager;
32
+ /** @type {string} */
33
+ var _focusableElementsString = ['a[href]', 'area[href]', 'input:not([disabled])', 'select:not([disabled])', 'textarea:not([disabled])', 'button:not([disabled])', 'details', 'summary', 'iframe', 'object', 'embed', '[contenteditable]'].join(',');
56
34
 
57
- /** @type {!Element} */
58
- this._rootElement = rootElement;
35
+ /**
36
+ * `InertRoot` manages a single inert subtree, i.e. a DOM subtree whose root element has an `inert`
37
+ * attribute.
38
+ *
39
+ * Its main functions are:
40
+ *
41
+ * - to create and maintain a set of managed `InertNode`s, including when mutations occur in the
42
+ * subtree. The `makeSubtreeUnfocusable()` method handles collecting `InertNode`s via registering
43
+ * each focusable node in the subtree with the singleton `InertManager` which manages all known
44
+ * focusable nodes within inert subtrees. `InertManager` ensures that a single `InertNode`
45
+ * instance exists for each focusable node which has at least one inert root as an ancestor.
46
+ *
47
+ * - to notify all managed `InertNode`s when this subtree stops being inert (i.e. when the `inert`
48
+ * attribute is removed from the root node). This is handled in the destructor, which calls the
49
+ * `deregister` method on `InertManager` for each managed inert node.
50
+ */
59
51
 
52
+ var InertRoot = function () {
60
53
  /**
61
- * @type {!Set<!InertNode>}
62
- * All managed focusable nodes in this InertRoot's subtree.
54
+ * @param {!Element} rootElement The Element at the root of the inert subtree.
55
+ * @param {!InertManager} inertManager The global singleton InertManager object.
63
56
  */
64
- this._managedNodes = new Set();
65
-
66
- // Make the subtree hidden from assistive technology
67
- if (this._rootElement.hasAttribute('aria-hidden')) {
68
- /** @type {?string} */
69
- this._savedAriaHidden = this._rootElement.getAttribute('aria-hidden');
70
- } else {
71
- this._savedAriaHidden = null;
72
- }
73
- this._rootElement.setAttribute('aria-hidden', 'true');
74
-
75
- // Make all focusable elements in the subtree unfocusable and add them to _managedNodes
76
- this._makeSubtreeUnfocusable(this._rootElement);
77
-
78
- // Watch for:
79
- // - any additions in the subtree: make them unfocusable too
80
- // - any removals from the subtree: remove them from this inert root's managed nodes
81
- // - attribute changes: if `tabindex` is added, or removed from an intrinsically focusable
82
- // element, make that node a managed node.
83
- this._observer = new MutationObserver(this._onMutation.bind(this));
84
- this._observer.observe(this._rootElement, { attributes: true, childList: true, subtree: true });
85
- }
57
+ function InertRoot(rootElement, inertManager) {
58
+ _classCallCheck(this, InertRoot);
86
59
 
87
- /**
88
- * Call this whenever this object is about to become obsolete. This unwinds all of the state
89
- * stored in this object and updates the state of all of the managed nodes.
90
- */
60
+ /** @type {!InertManager} */
61
+ this._inertManager = inertManager;
91
62
 
63
+ /** @type {!Element} */
64
+ this._rootElement = rootElement;
92
65
 
93
- _createClass(InertRoot, [{
94
- key: 'destructor',
95
- value: function destructor() {
96
- this._observer.disconnect();
66
+ /**
67
+ * @type {!Set<!InertNode>}
68
+ * All managed focusable nodes in this InertRoot's subtree.
69
+ */
70
+ this._managedNodes = new Set();
97
71
 
98
- if (this._rootElement) {
99
- if (this._savedAriaHidden !== null) {
100
- this._rootElement.setAttribute('aria-hidden', this._savedAriaHidden);
101
- } else {
102
- this._rootElement.removeAttribute('aria-hidden');
103
- }
72
+ // Make the subtree hidden from assistive technology
73
+ if (this._rootElement.hasAttribute('aria-hidden')) {
74
+ /** @type {?string} */
75
+ this._savedAriaHidden = this._rootElement.getAttribute('aria-hidden');
76
+ } else {
77
+ this._savedAriaHidden = null;
104
78
  }
79
+ this._rootElement.setAttribute('aria-hidden', 'true');
80
+
81
+ // Make all focusable elements in the subtree unfocusable and add them to _managedNodes
82
+ this._makeSubtreeUnfocusable(this._rootElement);
105
83
 
106
- this._managedNodes.forEach(function (inertNode) {
107
- this._unmanageNode(inertNode.node);
108
- }, this);
109
-
110
- // Note we cast the nulls to the ANY type here because:
111
- // 1) We want the class properties to be declared as non-null, or else we
112
- // need even more casts throughout this code. All bets are off if an
113
- // instance has been destroyed and a method is called.
114
- // 2) We don't want to cast "this", because we want type-aware optimizations
115
- // to know which properties we're setting.
116
- this._observer = /** @type {?} */null;
117
- this._rootElement = /** @type {?} */null;
118
- this._managedNodes = /** @type {?} */null;
119
- this._inertManager = /** @type {?} */null;
84
+ // Watch for:
85
+ // - any additions in the subtree: make them unfocusable too
86
+ // - any removals from the subtree: remove them from this inert root's managed nodes
87
+ // - attribute changes: if `tabindex` is added, or removed from an intrinsically focusable
88
+ // element, make that node a managed node.
89
+ this._observer = new MutationObserver(this._onMutation.bind(this));
90
+ this._observer.observe(this._rootElement, { attributes: true, childList: true, subtree: true });
120
91
  }
121
92
 
122
93
  /**
123
- * @return {!Set<!InertNode>} A copy of this InertRoot's managed nodes set.
94
+ * Call this whenever this object is about to become obsolete. This unwinds all of the state
95
+ * stored in this object and updates the state of all of the managed nodes.
124
96
  */
125
97
 
126
- }, {
127
- key: '_makeSubtreeUnfocusable',
128
98
 
99
+ _createClass(InertRoot, [{
100
+ key: 'destructor',
101
+ value: function destructor() {
102
+ this._observer.disconnect();
129
103
 
130
- /**
131
- * @param {!Node} startNode
132
- */
133
- value: function _makeSubtreeUnfocusable(startNode) {
134
- var _this2 = this;
135
-
136
- composedTreeWalk(startNode, function (node) {
137
- return _this2._visitNode(node);
138
- });
139
-
140
- var activeElement = document.activeElement;
141
-
142
- if (!document.body.contains(startNode)) {
143
- // startNode may be in shadow DOM, so find its nearest shadowRoot to get the activeElement.
144
- var node = startNode;
145
- /** @type {!ShadowRoot|undefined} */
146
- var root = undefined;
147
- while (node) {
148
- if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
149
- root = /** @type {!ShadowRoot} */node;
150
- break;
104
+ if (this._rootElement) {
105
+ if (this._savedAriaHidden !== null) {
106
+ this._rootElement.setAttribute('aria-hidden', this._savedAriaHidden);
107
+ } else {
108
+ this._rootElement.removeAttribute('aria-hidden');
151
109
  }
152
- node = node.parentNode;
153
- }
154
- if (root) {
155
- activeElement = root.activeElement;
156
110
  }
157
- }
158
- if (startNode.contains(activeElement)) {
159
- activeElement.blur();
160
- // In IE11, if an element is already focused, and then set to tabindex=-1
161
- // calling blur() will not actually move the focus.
162
- // To work around this we call focus() on the body instead.
163
- if (activeElement === document.activeElement) {
164
- document.body.focus();
165
- }
166
- }
167
- }
168
-
169
- /**
170
- * @param {!Node} node
171
- */
172
111
 
173
- }, {
174
- key: '_visitNode',
175
- value: function _visitNode(node) {
176
- if (node.nodeType !== Node.ELEMENT_NODE) {
177
- return;
112
+ this._managedNodes.forEach(function (inertNode) {
113
+ this._unmanageNode(inertNode.node);
114
+ }, this);
115
+
116
+ // Note we cast the nulls to the ANY type here because:
117
+ // 1) We want the class properties to be declared as non-null, or else we
118
+ // need even more casts throughout this code. All bets are off if an
119
+ // instance has been destroyed and a method is called.
120
+ // 2) We don't want to cast "this", because we want type-aware optimizations
121
+ // to know which properties we're setting.
122
+ this._observer = /** @type {?} */null;
123
+ this._rootElement = /** @type {?} */null;
124
+ this._managedNodes = /** @type {?} */null;
125
+ this._inertManager = /** @type {?} */null;
178
126
  }
179
- var element = /** @type {!Element} */node;
180
127
 
181
- // If a descendant inert root becomes un-inert, its descendants will still be inert because of
182
- // this inert root, so all of its managed nodes need to be adopted by this InertRoot.
183
- if (element !== this._rootElement && element.hasAttribute('inert')) {
184
- this._adoptInertRoot(element);
185
- }
128
+ /**
129
+ * @return {!Set<!InertNode>} A copy of this InertRoot's managed nodes set.
130
+ */
186
131
 
187
- if (matches.call(element, _focusableElementsString) || element.hasAttribute('tabindex')) {
188
- this._manageNode(element);
189
- }
190
- }
132
+ }, {
133
+ key: '_makeSubtreeUnfocusable',
191
134
 
192
- /**
193
- * Register the given node with this InertRoot and with InertManager.
194
- * @param {!Node} node
195
- */
196
135
 
197
- }, {
198
- key: '_manageNode',
199
- value: function _manageNode(node) {
200
- var inertNode = this._inertManager.register(node, this);
201
- this._managedNodes.add(inertNode);
202
- }
136
+ /**
137
+ * @param {!Node} startNode
138
+ */
139
+ value: function _makeSubtreeUnfocusable(startNode) {
140
+ var _this2 = this;
203
141
 
204
- /**
205
- * Unregister the given node with this InertRoot and with InertManager.
206
- * @param {!Node} node
207
- */
142
+ composedTreeWalk(startNode, function (node) {
143
+ return _this2._visitNode(node);
144
+ });
208
145
 
209
- }, {
210
- key: '_unmanageNode',
211
- value: function _unmanageNode(node) {
212
- var inertNode = this._inertManager.deregister(node, this);
213
- if (inertNode) {
214
- this._managedNodes['delete'](inertNode);
146
+ var activeElement = document.activeElement;
147
+
148
+ if (!document.body.contains(startNode)) {
149
+ // startNode may be in shadow DOM, so find its nearest shadowRoot to get the activeElement.
150
+ var node = startNode;
151
+ /** @type {!ShadowRoot|undefined} */
152
+ var root = undefined;
153
+ while (node) {
154
+ if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
155
+ root = /** @type {!ShadowRoot} */node;
156
+ break;
157
+ }
158
+ node = node.parentNode;
159
+ }
160
+ if (root) {
161
+ activeElement = root.activeElement;
162
+ }
163
+ }
164
+ if (startNode.contains(activeElement)) {
165
+ activeElement.blur();
166
+ // In IE11, if an element is already focused, and then set to tabindex=-1
167
+ // calling blur() will not actually move the focus.
168
+ // To work around this we call focus() on the body instead.
169
+ if (activeElement === document.activeElement) {
170
+ document.body.focus();
171
+ }
172
+ }
215
173
  }
216
- }
217
174
 
218
- /**
219
- * Unregister the entire subtree starting at `startNode`.
220
- * @param {!Node} startNode
221
- */
175
+ /**
176
+ * @param {!Node} node
177
+ */
222
178
 
223
- }, {
224
- key: '_unmanageSubtree',
225
- value: function _unmanageSubtree(startNode) {
226
- var _this3 = this;
179
+ }, {
180
+ key: '_visitNode',
181
+ value: function _visitNode(node) {
182
+ if (node.nodeType !== Node.ELEMENT_NODE) {
183
+ return;
184
+ }
185
+ var element = /** @type {!Element} */node;
227
186
 
228
- composedTreeWalk(startNode, function (node) {
229
- return _this3._unmanageNode(node);
230
- });
231
- }
187
+ // If a descendant inert root becomes un-inert, its descendants will still be inert because of
188
+ // this inert root, so all of its managed nodes need to be adopted by this InertRoot.
189
+ if (element !== this._rootElement && element.hasAttribute('inert')) {
190
+ this._adoptInertRoot(element);
191
+ }
232
192
 
233
- /**
234
- * If a descendant node is found with an `inert` attribute, adopt its managed nodes.
235
- * @param {!Element} node
236
- */
193
+ if (matches.call(element, _focusableElementsString) || element.hasAttribute('tabindex')) {
194
+ this._manageNode(element);
195
+ }
196
+ }
237
197
 
238
- }, {
239
- key: '_adoptInertRoot',
240
- value: function _adoptInertRoot(node) {
241
- var inertSubroot = this._inertManager.getInertRoot(node);
198
+ /**
199
+ * Register the given node with this InertRoot and with InertManager.
200
+ * @param {!Node} node
201
+ */
242
202
 
243
- // During initialisation this inert root may not have been registered yet,
244
- // so register it now if need be.
245
- if (!inertSubroot) {
246
- this._inertManager.setInert(node, true);
247
- inertSubroot = this._inertManager.getInertRoot(node);
203
+ }, {
204
+ key: '_manageNode',
205
+ value: function _manageNode(node) {
206
+ var inertNode = this._inertManager.register(node, this);
207
+ this._managedNodes.add(inertNode);
248
208
  }
249
209
 
250
- inertSubroot.managedNodes.forEach(function (savedInertNode) {
251
- this._manageNode(savedInertNode.node);
252
- }, this);
253
- }
210
+ /**
211
+ * Unregister the given node with this InertRoot and with InertManager.
212
+ * @param {!Node} node
213
+ */
214
+
215
+ }, {
216
+ key: '_unmanageNode',
217
+ value: function _unmanageNode(node) {
218
+ var inertNode = this._inertManager.deregister(node, this);
219
+ if (inertNode) {
220
+ this._managedNodes['delete'](inertNode);
221
+ }
222
+ }
254
223
 
255
- /**
256
- * Callback used when mutation observer detects subtree additions, removals, or attribute changes.
257
- * @param {!Array<!MutationRecord>} records
258
- * @param {!MutationObserver} self
259
- */
224
+ /**
225
+ * Unregister the entire subtree starting at `startNode`.
226
+ * @param {!Node} startNode
227
+ */
260
228
 
261
- }, {
262
- key: '_onMutation',
263
- value: function _onMutation(records, self) {
264
- records.forEach(function (record) {
265
- var target = /** @type {!Element} */record.target;
266
- if (record.type === 'childList') {
267
- // Manage added nodes
268
- slice.call(record.addedNodes).forEach(function (node) {
269
- this._makeSubtreeUnfocusable(node);
270
- }, this);
271
-
272
- // Un-manage removed nodes
273
- slice.call(record.removedNodes).forEach(function (node) {
274
- this._unmanageSubtree(node);
275
- }, this);
276
- } else if (record.type === 'attributes') {
277
- if (record.attributeName === 'tabindex') {
278
- // Re-initialise inert node if tabindex changes
279
- this._manageNode(target);
280
- } else if (target !== this._rootElement && record.attributeName === 'inert' && target.hasAttribute('inert')) {
281
- // If a new inert root is added, adopt its managed nodes and make sure it knows about the
282
- // already managed nodes from this inert subroot.
283
- this._adoptInertRoot(target);
284
- var inertSubroot = this._inertManager.getInertRoot(target);
285
- this._managedNodes.forEach(function (managedNode) {
286
- if (target.contains(managedNode.node)) {
287
- inertSubroot._manageNode(managedNode.node);
288
- }
289
- });
290
- }
229
+ }, {
230
+ key: '_unmanageSubtree',
231
+ value: function _unmanageSubtree(startNode) {
232
+ var _this3 = this;
233
+
234
+ composedTreeWalk(startNode, function (node) {
235
+ return _this3._unmanageNode(node);
236
+ });
237
+ }
238
+
239
+ /**
240
+ * If a descendant node is found with an `inert` attribute, adopt its managed nodes.
241
+ * @param {!Element} node
242
+ */
243
+
244
+ }, {
245
+ key: '_adoptInertRoot',
246
+ value: function _adoptInertRoot(node) {
247
+ var inertSubroot = this._inertManager.getInertRoot(node);
248
+
249
+ // During initialisation this inert root may not have been registered yet,
250
+ // so register it now if need be.
251
+ if (!inertSubroot) {
252
+ this._inertManager.setInert(node, true);
253
+ inertSubroot = this._inertManager.getInertRoot(node);
291
254
  }
292
- }, this);
293
- }
294
- }, {
295
- key: 'managedNodes',
296
- get: function get() {
297
- return new Set(this._managedNodes);
298
- }
299
255
 
300
- /** @return {boolean} */
256
+ inertSubroot.managedNodes.forEach(function (savedInertNode) {
257
+ this._manageNode(savedInertNode.node);
258
+ }, this);
259
+ }
301
260
 
302
- }, {
303
- key: 'hasSavedAriaHidden',
304
- get: function get() {
305
- return this._savedAriaHidden !== null;
306
- }
261
+ /**
262
+ * Callback used when mutation observer detects subtree additions, removals, or attribute changes.
263
+ * @param {!Array<!MutationRecord>} records
264
+ * @param {!MutationObserver} self
265
+ */
266
+
267
+ }, {
268
+ key: '_onMutation',
269
+ value: function _onMutation(records, self) {
270
+ records.forEach(function (record) {
271
+ var target = /** @type {!Element} */record.target;
272
+ if (record.type === 'childList') {
273
+ // Manage added nodes
274
+ slice.call(record.addedNodes).forEach(function (node) {
275
+ this._makeSubtreeUnfocusable(node);
276
+ }, this);
277
+
278
+ // Un-manage removed nodes
279
+ slice.call(record.removedNodes).forEach(function (node) {
280
+ this._unmanageSubtree(node);
281
+ }, this);
282
+ } else if (record.type === 'attributes') {
283
+ if (record.attributeName === 'tabindex') {
284
+ // Re-initialise inert node if tabindex changes
285
+ this._manageNode(target);
286
+ } else if (target !== this._rootElement && record.attributeName === 'inert' && target.hasAttribute('inert')) {
287
+ // If a new inert root is added, adopt its managed nodes and make sure it knows about the
288
+ // already managed nodes from this inert subroot.
289
+ this._adoptInertRoot(target);
290
+ var inertSubroot = this._inertManager.getInertRoot(target);
291
+ this._managedNodes.forEach(function (managedNode) {
292
+ if (target.contains(managedNode.node)) {
293
+ inertSubroot._manageNode(managedNode.node);
294
+ }
295
+ });
296
+ }
297
+ }
298
+ }, this);
299
+ }
300
+ }, {
301
+ key: 'managedNodes',
302
+ get: function get() {
303
+ return new Set(this._managedNodes);
304
+ }
307
305
 
308
- /** @param {?string} ariaHidden */
306
+ /** @return {boolean} */
309
307
 
310
- }, {
311
- key: 'savedAriaHidden',
312
- set: function set(ariaHidden) {
313
- this._savedAriaHidden = ariaHidden;
314
- }
308
+ }, {
309
+ key: 'hasSavedAriaHidden',
310
+ get: function get() {
311
+ return this._savedAriaHidden !== null;
312
+ }
315
313
 
316
- /** @return {?string} */
317
- ,
318
- get: function get() {
319
- return this._savedAriaHidden;
320
- }
321
- }]);
314
+ /** @param {?string} ariaHidden */
322
315
 
323
- return InertRoot;
324
- }();
316
+ }, {
317
+ key: 'savedAriaHidden',
318
+ set: function set(ariaHidden) {
319
+ this._savedAriaHidden = ariaHidden;
320
+ }
325
321
 
326
- /**
327
- * `InertNode` initialises and manages a single inert node.
328
- * A node is inert if it is a descendant of one or more inert root elements.
329
- *
330
- * On construction, `InertNode` saves the existing `tabindex` value for the node, if any, and
331
- * either removes the `tabindex` attribute or sets it to `-1`, depending on whether the element
332
- * is intrinsically focusable or not.
333
- *
334
- * `InertNode` maintains a set of `InertRoot`s which are descendants of this `InertNode`. When an
335
- * `InertRoot` is destroyed, and calls `InertManager.deregister()`, the `InertManager` notifies the
336
- * `InertNode` via `removeInertRoot()`, which in turn destroys the `InertNode` if no `InertRoot`s
337
- * remain in the set. On destruction, `InertNode` reinstates the stored `tabindex` if one exists,
338
- * or removes the `tabindex` attribute if the element is intrinsically focusable.
339
- */
322
+ /** @return {?string} */
323
+ ,
324
+ get: function get() {
325
+ return this._savedAriaHidden;
326
+ }
327
+ }]);
340
328
 
329
+ return InertRoot;
330
+ }();
341
331
 
342
- var InertNode = function () {
343
332
  /**
344
- * @param {!Node} node A focusable element to be made inert.
345
- * @param {!InertRoot} inertRoot The inert root element associated with this inert node.
333
+ * `InertNode` initialises and manages a single inert node.
334
+ * A node is inert if it is a descendant of one or more inert root elements.
335
+ *
336
+ * On construction, `InertNode` saves the existing `tabindex` value for the node, if any, and
337
+ * either removes the `tabindex` attribute or sets it to `-1`, depending on whether the element
338
+ * is intrinsically focusable or not.
339
+ *
340
+ * `InertNode` maintains a set of `InertRoot`s which are descendants of this `InertNode`. When an
341
+ * `InertRoot` is destroyed, and calls `InertManager.deregister()`, the `InertManager` notifies the
342
+ * `InertNode` via `removeInertRoot()`, which in turn destroys the `InertNode` if no `InertRoot`s
343
+ * remain in the set. On destruction, `InertNode` reinstates the stored `tabindex` if one exists,
344
+ * or removes the `tabindex` attribute if the element is intrinsically focusable.
346
345
  */
347
- function InertNode(node, inertRoot) {
348
- _classCallCheck(this, InertNode);
349
-
350
- /** @type {!Node} */
351
- this._node = node;
352
346
 
353
- /** @type {boolean} */
354
- this._overrodeFocusMethod = false;
355
347
 
348
+ var InertNode = function () {
356
349
  /**
357
- * @type {!Set<!InertRoot>} The set of descendant inert roots.
358
- * If and only if this set becomes empty, this node is no longer inert.
350
+ * @param {!Node} node A focusable element to be made inert.
351
+ * @param {!InertRoot} inertRoot The inert root element associated with this inert node.
359
352
  */
360
- this._inertRoots = new Set([inertRoot]);
361
-
362
- /** @type {?number} */
363
- this._savedTabIndex = null;
364
-
365
- /** @type {boolean} */
366
- this._destroyed = false;
367
-
368
- // Save any prior tabindex info and make this node untabbable
369
- this.ensureUntabbable();
370
- }
353
+ function InertNode(node, inertRoot) {
354
+ _classCallCheck(this, InertNode);
371
355
 
372
- /**
373
- * Call this whenever this object is about to become obsolete.
374
- * This makes the managed node focusable again and deletes all of the previously stored state.
375
- */
356
+ /** @type {!Node} */
357
+ this._node = node;
376
358
 
359
+ /** @type {boolean} */
360
+ this._overrodeFocusMethod = false;
377
361
 
378
- _createClass(InertNode, [{
379
- key: 'destructor',
380
- value: function destructor() {
381
- this._throwIfDestroyed();
362
+ /**
363
+ * @type {!Set<!InertRoot>} The set of descendant inert roots.
364
+ * If and only if this set becomes empty, this node is no longer inert.
365
+ */
366
+ this._inertRoots = new Set([inertRoot]);
382
367
 
383
- if (this._node && this._node.nodeType === Node.ELEMENT_NODE) {
384
- var element = /** @type {!Element} */this._node;
385
- if (this._savedTabIndex !== null) {
386
- element.setAttribute('tabindex', this._savedTabIndex);
387
- } else {
388
- element.removeAttribute('tabindex');
389
- }
368
+ /** @type {?number} */
369
+ this._savedTabIndex = null;
390
370
 
391
- // Use `delete` to restore native focus method.
392
- if (this._overrodeFocusMethod) {
393
- delete element.focus;
394
- }
395
- }
371
+ /** @type {boolean} */
372
+ this._destroyed = false;
396
373
 
397
- // See note in InertRoot.destructor for why we cast these nulls to ANY.
398
- this._node = /** @type {?} */null;
399
- this._inertRoots = /** @type {?} */null;
400
- this._destroyed = true;
374
+ // Save any prior tabindex info and make this node untabbable
375
+ this.ensureUntabbable();
401
376
  }
402
377
 
403
378
  /**
404
- * @type {boolean} Whether this object is obsolete because the managed node is no longer inert.
405
- * If the object has been destroyed, any attempt to access it will cause an exception.
379
+ * Call this whenever this object is about to become obsolete.
380
+ * This makes the managed node focusable again and deletes all of the previously stored state.
406
381
  */
407
382
 
408
- }, {
409
- key: '_throwIfDestroyed',
410
383
 
384
+ _createClass(InertNode, [{
385
+ key: 'destructor',
386
+ value: function destructor() {
387
+ this._throwIfDestroyed();
411
388
 
412
- /**
413
- * Throw if user tries to access destroyed InertNode.
414
- */
415
- value: function _throwIfDestroyed() {
416
- if (this.destroyed) {
417
- throw new Error('Trying to access destroyed InertNode');
389
+ if (this._node && this._node.nodeType === Node.ELEMENT_NODE) {
390
+ var element = /** @type {!Element} */this._node;
391
+ if (this._savedTabIndex !== null) {
392
+ element.setAttribute('tabindex', this._savedTabIndex);
393
+ } else {
394
+ element.removeAttribute('tabindex');
395
+ }
396
+
397
+ // Use `delete` to restore native focus method.
398
+ if (this._overrodeFocusMethod) {
399
+ delete element.focus;
400
+ }
401
+ }
402
+
403
+ // See note in InertRoot.destructor for why we cast these nulls to ANY.
404
+ this._node = /** @type {?} */null;
405
+ this._inertRoots = /** @type {?} */null;
406
+ this._destroyed = true;
418
407
  }
419
- }
420
408
 
421
- /** @return {boolean} */
409
+ /**
410
+ * @type {boolean} Whether this object is obsolete because the managed node is no longer inert.
411
+ * If the object has been destroyed, any attempt to access it will cause an exception.
412
+ */
422
413
 
423
- }, {
424
- key: 'ensureUntabbable',
414
+ }, {
415
+ key: '_throwIfDestroyed',
425
416
 
426
417
 
427
- /** Save the existing tabindex value and make the node untabbable and unfocusable */
428
- value: function ensureUntabbable() {
429
- if (this.node.nodeType !== Node.ELEMENT_NODE) {
430
- return;
418
+ /**
419
+ * Throw if user tries to access destroyed InertNode.
420
+ */
421
+ value: function _throwIfDestroyed() {
422
+ if (this.destroyed) {
423
+ throw new Error('Trying to access destroyed InertNode');
424
+ }
431
425
  }
432
- var element = /** @type {!Element} */this.node;
433
- if (matches.call(element, _focusableElementsString)) {
434
- if ( /** @type {!HTMLElement} */element.tabIndex === -1 && this.hasSavedTabIndex) {
426
+
427
+ /** @return {boolean} */
428
+
429
+ }, {
430
+ key: 'ensureUntabbable',
431
+
432
+
433
+ /** Save the existing tabindex value and make the node untabbable and unfocusable */
434
+ value: function ensureUntabbable() {
435
+ if (this.node.nodeType !== Node.ELEMENT_NODE) {
435
436
  return;
436
437
  }
438
+ var element = /** @type {!Element} */this.node;
439
+ if (matches.call(element, _focusableElementsString)) {
440
+ if ( /** @type {!HTMLElement} */element.tabIndex === -1 && this.hasSavedTabIndex) {
441
+ return;
442
+ }
437
443
 
438
- if (element.hasAttribute('tabindex')) {
444
+ if (element.hasAttribute('tabindex')) {
445
+ this._savedTabIndex = /** @type {!HTMLElement} */element.tabIndex;
446
+ }
447
+ element.setAttribute('tabindex', '-1');
448
+ if (element.nodeType === Node.ELEMENT_NODE) {
449
+ element.focus = function () {};
450
+ this._overrodeFocusMethod = true;
451
+ }
452
+ } else if (element.hasAttribute('tabindex')) {
439
453
  this._savedTabIndex = /** @type {!HTMLElement} */element.tabIndex;
454
+ element.removeAttribute('tabindex');
440
455
  }
441
- element.setAttribute('tabindex', '-1');
442
- if (element.nodeType === Node.ELEMENT_NODE) {
443
- element.focus = function () {};
444
- this._overrodeFocusMethod = true;
445
- }
446
- } else if (element.hasAttribute('tabindex')) {
447
- this._savedTabIndex = /** @type {!HTMLElement} */element.tabIndex;
448
- element.removeAttribute('tabindex');
449
456
  }
450
- }
451
457
 
452
- /**
453
- * Add another inert root to this inert node's set of managing inert roots.
454
- * @param {!InertRoot} inertRoot
455
- */
456
-
457
- }, {
458
- key: 'addInertRoot',
459
- value: function addInertRoot(inertRoot) {
460
- this._throwIfDestroyed();
461
- this._inertRoots.add(inertRoot);
462
- }
463
-
464
- /**
465
- * Remove the given inert root from this inert node's set of managing inert roots.
466
- * If the set of managing inert roots becomes empty, this node is no longer inert,
467
- * so the object should be destroyed.
468
- * @param {!InertRoot} inertRoot
469
- */
458
+ /**
459
+ * Add another inert root to this inert node's set of managing inert roots.
460
+ * @param {!InertRoot} inertRoot
461
+ */
470
462
 
471
- }, {
472
- key: 'removeInertRoot',
473
- value: function removeInertRoot(inertRoot) {
474
- this._throwIfDestroyed();
475
- this._inertRoots['delete'](inertRoot);
476
- if (this._inertRoots.size === 0) {
477
- this.destructor();
463
+ }, {
464
+ key: 'addInertRoot',
465
+ value: function addInertRoot(inertRoot) {
466
+ this._throwIfDestroyed();
467
+ this._inertRoots.add(inertRoot);
478
468
  }
479
- }
480
- }, {
481
- key: 'destroyed',
482
- get: function get() {
483
- return (/** @type {!InertNode} */this._destroyed
484
- );
485
- }
486
- }, {
487
- key: 'hasSavedTabIndex',
488
- get: function get() {
489
- return this._savedTabIndex !== null;
490
- }
491
-
492
- /** @return {!Node} */
493
469
 
494
- }, {
495
- key: 'node',
496
- get: function get() {
497
- this._throwIfDestroyed();
498
- return this._node;
499
- }
470
+ /**
471
+ * Remove the given inert root from this inert node's set of managing inert roots.
472
+ * If the set of managing inert roots becomes empty, this node is no longer inert,
473
+ * so the object should be destroyed.
474
+ * @param {!InertRoot} inertRoot
475
+ */
476
+
477
+ }, {
478
+ key: 'removeInertRoot',
479
+ value: function removeInertRoot(inertRoot) {
480
+ this._throwIfDestroyed();
481
+ this._inertRoots['delete'](inertRoot);
482
+ if (this._inertRoots.size === 0) {
483
+ this.destructor();
484
+ }
485
+ }
486
+ }, {
487
+ key: 'destroyed',
488
+ get: function get() {
489
+ return (/** @type {!InertNode} */this._destroyed
490
+ );
491
+ }
492
+ }, {
493
+ key: 'hasSavedTabIndex',
494
+ get: function get() {
495
+ return this._savedTabIndex !== null;
496
+ }
500
497
 
501
- /** @param {?number} tabIndex */
498
+ /** @return {!Node} */
502
499
 
503
- }, {
504
- key: 'savedTabIndex',
505
- set: function set(tabIndex) {
506
- this._throwIfDestroyed();
507
- this._savedTabIndex = tabIndex;
508
- }
500
+ }, {
501
+ key: 'node',
502
+ get: function get() {
503
+ this._throwIfDestroyed();
504
+ return this._node;
505
+ }
509
506
 
510
- /** @return {?number} */
511
- ,
512
- get: function get() {
513
- this._throwIfDestroyed();
514
- return this._savedTabIndex;
515
- }
516
- }]);
507
+ /** @param {?number} tabIndex */
517
508
 
518
- return InertNode;
519
- }();
509
+ }, {
510
+ key: 'savedTabIndex',
511
+ set: function set(tabIndex) {
512
+ this._throwIfDestroyed();
513
+ this._savedTabIndex = tabIndex;
514
+ }
520
515
 
521
- /**
522
- * InertManager is a per-document singleton object which manages all inert roots and nodes.
523
- *
524
- * When an element becomes an inert root by having an `inert` attribute set and/or its `inert`
525
- * property set to `true`, the `setInert` method creates an `InertRoot` object for the element.
526
- * The `InertRoot` in turn registers itself as managing all of the element's focusable descendant
527
- * nodes via the `register()` method. The `InertManager` ensures that a single `InertNode` instance
528
- * is created for each such node, via the `_managedNodes` map.
529
- */
516
+ /** @return {?number} */
517
+ ,
518
+ get: function get() {
519
+ this._throwIfDestroyed();
520
+ return this._savedTabIndex;
521
+ }
522
+ }]);
530
523
 
524
+ return InertNode;
525
+ }();
531
526
 
532
- var InertManager = function () {
533
527
  /**
534
- * @param {!Document} document
528
+ * InertManager is a per-document singleton object which manages all inert roots and nodes.
529
+ *
530
+ * When an element becomes an inert root by having an `inert` attribute set and/or its `inert`
531
+ * property set to `true`, the `setInert` method creates an `InertRoot` object for the element.
532
+ * The `InertRoot` in turn registers itself as managing all of the element's focusable descendant
533
+ * nodes via the `register()` method. The `InertManager` ensures that a single `InertNode` instance
534
+ * is created for each such node, via the `_managedNodes` map.
535
535
  */
536
- function InertManager(document) {
537
- _classCallCheck(this, InertManager);
538
536
 
539
- if (!document) {
540
- throw new Error('Missing required argument; InertManager needs to wrap a document.');
541
- }
542
-
543
- /** @type {!Document} */
544
- this._document = document;
545
-
546
- /**
547
- * All managed nodes known to this InertManager. In a map to allow looking up by Node.
548
- * @type {!Map<!Node, !InertNode>}
549
- */
550
- this._managedNodes = new Map();
551
-
552
- /**
553
- * All inert roots known to this InertManager. In a map to allow looking up by Node.
554
- * @type {!Map<!Node, !InertRoot>}
555
- */
556
- this._inertRoots = new Map();
557
537
 
538
+ var InertManager = function () {
558
539
  /**
559
- * Observer for mutations on `document.body`.
560
- * @type {!MutationObserver}
540
+ * @param {!Document} document
561
541
  */
562
- this._observer = new MutationObserver(this._watchForInert.bind(this));
563
-
564
- // Add inert style.
565
- addInertStyle(document.head || document.body || document.documentElement);
566
-
567
- // Wait for document to be loaded.
568
- if (document.readyState === 'loading') {
569
- document.addEventListener('DOMContentLoaded', this._onDocumentLoaded.bind(this));
570
- } else {
571
- this._onDocumentLoaded();
572
- }
573
- }
574
-
575
- /**
576
- * Set whether the given element should be an inert root or not.
577
- * @param {!Element} root
578
- * @param {boolean} inert
579
- */
542
+ function InertManager(document) {
543
+ _classCallCheck(this, InertManager);
580
544
 
545
+ if (!document) {
546
+ throw new Error('Missing required argument; InertManager needs to wrap a document.');
547
+ }
581
548
 
582
- _createClass(InertManager, [{
583
- key: 'setInert',
584
- value: function setInert(root, inert) {
585
- if (inert) {
586
- if (this._inertRoots.has(root)) {
587
- // element is already inert
588
- return;
589
- }
590
-
591
- var inertRoot = new InertRoot(root, this);
592
- root.setAttribute('inert', '');
593
- this._inertRoots.set(root, inertRoot);
594
- // If not contained in the document, it must be in a shadowRoot.
595
- // Ensure inert styles are added there.
596
- if (!this._document.body.contains(root)) {
597
- var parent = root.parentNode;
598
- while (parent) {
599
- if (parent.nodeType === 11) {
600
- addInertStyle(parent);
601
- }
602
- parent = parent.parentNode;
603
- }
604
- }
549
+ /** @type {!Document} */
550
+ this._document = document;
551
+
552
+ /**
553
+ * All managed nodes known to this InertManager. In a map to allow looking up by Node.
554
+ * @type {!Map<!Node, !InertNode>}
555
+ */
556
+ this._managedNodes = new Map();
557
+
558
+ /**
559
+ * All inert roots known to this InertManager. In a map to allow looking up by Node.
560
+ * @type {!Map<!Node, !InertRoot>}
561
+ */
562
+ this._inertRoots = new Map();
563
+
564
+ /**
565
+ * Observer for mutations on `document.body`.
566
+ * @type {!MutationObserver}
567
+ */
568
+ this._observer = new MutationObserver(this._watchForInert.bind(this));
569
+
570
+ // Add inert style.
571
+ addInertStyle(document.head || document.body || document.documentElement);
572
+
573
+ // Wait for document to be loaded.
574
+ if (document.readyState === 'loading') {
575
+ document.addEventListener('DOMContentLoaded', this._onDocumentLoaded.bind(this));
605
576
  } else {
606
- if (!this._inertRoots.has(root)) {
607
- // element is already non-inert
608
- return;
609
- }
610
-
611
- var _inertRoot = this._inertRoots.get(root);
612
- _inertRoot.destructor();
613
- this._inertRoots['delete'](root);
614
- root.removeAttribute('inert');
577
+ this._onDocumentLoaded();
615
578
  }
616
579
  }
617
580
 
618
581
  /**
619
- * Get the InertRoot object corresponding to the given inert root element, if any.
620
- * @param {!Node} element
621
- * @return {!InertRoot|undefined}
582
+ * Set whether the given element should be an inert root or not.
583
+ * @param {!Element} root
584
+ * @param {boolean} inert
622
585
  */
623
586
 
624
- }, {
625
- key: 'getInertRoot',
626
- value: function getInertRoot(element) {
627
- return this._inertRoots.get(element);
628
- }
629
587
 
630
- /**
631
- * Register the given InertRoot as managing the given node.
632
- * In the case where the node has a previously existing inert root, this inert root will
633
- * be added to its set of inert roots.
634
- * @param {!Node} node
635
- * @param {!InertRoot} inertRoot
636
- * @return {!InertNode} inertNode
637
- */
588
+ _createClass(InertManager, [{
589
+ key: 'setInert',
590
+ value: function setInert(root, inert) {
591
+ if (inert) {
592
+ if (this._inertRoots.has(root)) {
593
+ // element is already inert
594
+ return;
595
+ }
638
596
 
639
- }, {
640
- key: 'register',
641
- value: function register(node, inertRoot) {
642
- var inertNode = this._managedNodes.get(node);
643
- if (inertNode !== undefined) {
644
- // node was already in an inert subtree
645
- inertNode.addInertRoot(inertRoot);
646
- } else {
647
- inertNode = new InertNode(node, inertRoot);
597
+ var inertRoot = new InertRoot(root, this);
598
+ root.setAttribute('inert', '');
599
+ this._inertRoots.set(root, inertRoot);
600
+ // If not contained in the document, it must be in a shadowRoot.
601
+ // Ensure inert styles are added there.
602
+ if (!this._document.body.contains(root)) {
603
+ var parent = root.parentNode;
604
+ while (parent) {
605
+ if (parent.nodeType === 11) {
606
+ addInertStyle(parent);
607
+ }
608
+ parent = parent.parentNode;
609
+ }
610
+ }
611
+ } else {
612
+ if (!this._inertRoots.has(root)) {
613
+ // element is already non-inert
614
+ return;
615
+ }
616
+
617
+ var _inertRoot = this._inertRoots.get(root);
618
+ _inertRoot.destructor();
619
+ this._inertRoots['delete'](root);
620
+ root.removeAttribute('inert');
621
+ }
648
622
  }
649
623
 
650
- this._managedNodes.set(node, inertNode);
624
+ /**
625
+ * Get the InertRoot object corresponding to the given inert root element, if any.
626
+ * @param {!Node} element
627
+ * @return {!InertRoot|undefined}
628
+ */
651
629
 
652
- return inertNode;
653
- }
630
+ }, {
631
+ key: 'getInertRoot',
632
+ value: function getInertRoot(element) {
633
+ return this._inertRoots.get(element);
634
+ }
654
635
 
655
- /**
656
- * De-register the given InertRoot as managing the given inert node.
657
- * Removes the inert root from the InertNode's set of managing inert roots, and remove the inert
658
- * node from the InertManager's set of managed nodes if it is destroyed.
659
- * If the node is not currently managed, this is essentially a no-op.
660
- * @param {!Node} node
661
- * @param {!InertRoot} inertRoot
662
- * @return {?InertNode} The potentially destroyed InertNode associated with this node, if any.
663
- */
636
+ /**
637
+ * Register the given InertRoot as managing the given node.
638
+ * In the case where the node has a previously existing inert root, this inert root will
639
+ * be added to its set of inert roots.
640
+ * @param {!Node} node
641
+ * @param {!InertRoot} inertRoot
642
+ * @return {!InertNode} inertNode
643
+ */
644
+
645
+ }, {
646
+ key: 'register',
647
+ value: function register(node, inertRoot) {
648
+ var inertNode = this._managedNodes.get(node);
649
+ if (inertNode !== undefined) {
650
+ // node was already in an inert subtree
651
+ inertNode.addInertRoot(inertRoot);
652
+ } else {
653
+ inertNode = new InertNode(node, inertRoot);
654
+ }
664
655
 
665
- }, {
666
- key: 'deregister',
667
- value: function deregister(node, inertRoot) {
668
- var inertNode = this._managedNodes.get(node);
669
- if (!inertNode) {
670
- return null;
671
- }
656
+ this._managedNodes.set(node, inertNode);
672
657
 
673
- inertNode.removeInertRoot(inertRoot);
674
- if (inertNode.destroyed) {
675
- this._managedNodes['delete'](node);
658
+ return inertNode;
676
659
  }
677
660
 
678
- return inertNode;
679
- }
661
+ /**
662
+ * De-register the given InertRoot as managing the given inert node.
663
+ * Removes the inert root from the InertNode's set of managing inert roots, and remove the inert
664
+ * node from the InertManager's set of managed nodes if it is destroyed.
665
+ * If the node is not currently managed, this is essentially a no-op.
666
+ * @param {!Node} node
667
+ * @param {!InertRoot} inertRoot
668
+ * @return {?InertNode} The potentially destroyed InertNode associated with this node, if any.
669
+ */
670
+
671
+ }, {
672
+ key: 'deregister',
673
+ value: function deregister(node, inertRoot) {
674
+ var inertNode = this._managedNodes.get(node);
675
+ if (!inertNode) {
676
+ return null;
677
+ }
680
678
 
681
- /**
682
- * Callback used when document has finished loading.
683
- */
679
+ inertNode.removeInertRoot(inertRoot);
680
+ if (inertNode.destroyed) {
681
+ this._managedNodes['delete'](node);
682
+ }
684
683
 
685
- }, {
686
- key: '_onDocumentLoaded',
687
- value: function _onDocumentLoaded() {
688
- // Find all inert roots in document and make them actually inert.
689
- var inertElements = slice.call(this._document.querySelectorAll('[inert]'));
690
- inertElements.forEach(function (inertElement) {
691
- this.setInert(inertElement, true);
692
- }, this);
693
-
694
- // Comment this out to use programmatic API only.
695
- this._observer.observe(this._document.body, { attributes: true, subtree: true, childList: true });
696
- }
684
+ return inertNode;
685
+ }
697
686
 
698
- /**
699
- * Callback used when mutation observer detects attribute changes.
700
- * @param {!Array<!MutationRecord>} records
701
- * @param {!MutationObserver} self
702
- */
687
+ /**
688
+ * Callback used when document has finished loading.
689
+ */
690
+
691
+ }, {
692
+ key: '_onDocumentLoaded',
693
+ value: function _onDocumentLoaded() {
694
+ // Find all inert roots in document and make them actually inert.
695
+ var inertElements = slice.call(this._document.querySelectorAll('[inert]'));
696
+ inertElements.forEach(function (inertElement) {
697
+ this.setInert(inertElement, true);
698
+ }, this);
699
+
700
+ // Comment this out to use programmatic API only.
701
+ this._observer.observe(this._document.body || this._document.documentElement, { attributes: true, subtree: true, childList: true });
702
+ }
703
703
 
704
- }, {
705
- key: '_watchForInert',
706
- value: function _watchForInert(records, self) {
707
- var _this = this;
708
- records.forEach(function (record) {
709
- switch (record.type) {
710
- case 'childList':
711
- slice.call(record.addedNodes).forEach(function (node) {
712
- if (node.nodeType !== Node.ELEMENT_NODE) {
704
+ /**
705
+ * Callback used when mutation observer detects attribute changes.
706
+ * @param {!Array<!MutationRecord>} records
707
+ * @param {!MutationObserver} self
708
+ */
709
+
710
+ }, {
711
+ key: '_watchForInert',
712
+ value: function _watchForInert(records, self) {
713
+ var _this = this;
714
+ records.forEach(function (record) {
715
+ switch (record.type) {
716
+ case 'childList':
717
+ slice.call(record.addedNodes).forEach(function (node) {
718
+ if (node.nodeType !== Node.ELEMENT_NODE) {
719
+ return;
720
+ }
721
+ var inertElements = slice.call(node.querySelectorAll('[inert]'));
722
+ if (matches.call(node, '[inert]')) {
723
+ inertElements.unshift(node);
724
+ }
725
+ inertElements.forEach(function (inertElement) {
726
+ this.setInert(inertElement, true);
727
+ }, _this);
728
+ }, _this);
729
+ break;
730
+ case 'attributes':
731
+ if (record.attributeName !== 'inert') {
713
732
  return;
714
733
  }
715
- var inertElements = slice.call(node.querySelectorAll('[inert]'));
716
- if (matches.call(node, '[inert]')) {
717
- inertElements.unshift(node);
718
- }
719
- inertElements.forEach(function (inertElement) {
720
- this.setInert(inertElement, true);
721
- }, _this);
722
- }, _this);
723
- break;
724
- case 'attributes':
725
- if (record.attributeName !== 'inert') {
726
- return;
727
- }
728
- var target = /** @type {!Element} */record.target;
729
- var inert = target.hasAttribute('inert');
730
- _this.setInert(target, inert);
731
- break;
732
- }
733
- }, this);
734
- }
735
- }]);
734
+ var target = /** @type {!Element} */record.target;
735
+ var inert = target.hasAttribute('inert');
736
+ _this.setInert(target, inert);
737
+ break;
738
+ }
739
+ }, this);
740
+ }
741
+ }]);
736
742
 
737
- return InertManager;
738
- }();
743
+ return InertManager;
744
+ }();
739
745
 
740
- /**
741
- * Recursively walk the composed tree from |node|.
742
- * @param {!Node} node
743
- * @param {(function (!Element))=} callback Callback to be called for each element traversed,
744
- * before descending into child nodes.
745
- * @param {?ShadowRoot=} shadowRootAncestor The nearest ShadowRoot ancestor, if any.
746
- */
746
+ /**
747
+ * Recursively walk the composed tree from |node|.
748
+ * @param {!Node} node
749
+ * @param {(function (!Element))=} callback Callback to be called for each element traversed,
750
+ * before descending into child nodes.
751
+ * @param {?ShadowRoot=} shadowRootAncestor The nearest ShadowRoot ancestor, if any.
752
+ */
747
753
 
748
754
 
749
- function composedTreeWalk(node, callback, shadowRootAncestor) {
750
- if (node.nodeType == Node.ELEMENT_NODE) {
751
- var element = /** @type {!Element} */node;
752
- if (callback) {
753
- callback(element);
754
- }
755
+ function composedTreeWalk(node, callback, shadowRootAncestor) {
756
+ if (node.nodeType == Node.ELEMENT_NODE) {
757
+ var element = /** @type {!Element} */node;
758
+ if (callback) {
759
+ callback(element);
760
+ }
755
761
 
756
- // Descend into node:
757
- // If it has a ShadowRoot, ignore all child elements - these will be picked
758
- // up by the <content> or <shadow> elements. Descend straight into the
759
- // ShadowRoot.
760
- var shadowRoot = /** @type {!HTMLElement} */element.shadowRoot;
761
- if (shadowRoot) {
762
- composedTreeWalk(shadowRoot, callback, shadowRoot);
763
- return;
764
- }
762
+ // Descend into node:
763
+ // If it has a ShadowRoot, ignore all child elements - these will be picked
764
+ // up by the <content> or <shadow> elements. Descend straight into the
765
+ // ShadowRoot.
766
+ var shadowRoot = /** @type {!HTMLElement} */element.shadowRoot;
767
+ if (shadowRoot) {
768
+ composedTreeWalk(shadowRoot, callback, shadowRoot);
769
+ return;
770
+ }
765
771
 
766
- // If it is a <content> element, descend into distributed elements - these
767
- // are elements from outside the shadow root which are rendered inside the
768
- // shadow DOM.
769
- if (element.localName == 'content') {
770
- var content = /** @type {!HTMLContentElement} */element;
771
- // Verifies if ShadowDom v0 is supported.
772
- var distributedNodes = content.getDistributedNodes ? content.getDistributedNodes() : [];
773
- for (var i = 0; i < distributedNodes.length; i++) {
774
- composedTreeWalk(distributedNodes[i], callback, shadowRootAncestor);
772
+ // If it is a <content> element, descend into distributed elements - these
773
+ // are elements from outside the shadow root which are rendered inside the
774
+ // shadow DOM.
775
+ if (element.localName == 'content') {
776
+ var content = /** @type {!HTMLContentElement} */element;
777
+ // Verifies if ShadowDom v0 is supported.
778
+ var distributedNodes = content.getDistributedNodes ? content.getDistributedNodes() : [];
779
+ for (var i = 0; i < distributedNodes.length; i++) {
780
+ composedTreeWalk(distributedNodes[i], callback, shadowRootAncestor);
781
+ }
782
+ return;
775
783
  }
776
- return;
777
- }
778
784
 
779
- // If it is a <slot> element, descend into assigned nodes - these
780
- // are elements from outside the shadow root which are rendered inside the
781
- // shadow DOM.
782
- if (element.localName == 'slot') {
783
- var slot = /** @type {!HTMLSlotElement} */element;
784
- // Verify if ShadowDom v1 is supported.
785
- var _distributedNodes = slot.assignedNodes ? slot.assignedNodes({ flatten: true }) : [];
786
- for (var _i = 0; _i < _distributedNodes.length; _i++) {
787
- composedTreeWalk(_distributedNodes[_i], callback, shadowRootAncestor);
785
+ // If it is a <slot> element, descend into assigned nodes - these
786
+ // are elements from outside the shadow root which are rendered inside the
787
+ // shadow DOM.
788
+ if (element.localName == 'slot') {
789
+ var slot = /** @type {!HTMLSlotElement} */element;
790
+ // Verify if ShadowDom v1 is supported.
791
+ var _distributedNodes = slot.assignedNodes ? slot.assignedNodes({ flatten: true }) : [];
792
+ for (var _i = 0; _i < _distributedNodes.length; _i++) {
793
+ composedTreeWalk(_distributedNodes[_i], callback, shadowRootAncestor);
794
+ }
795
+ return;
788
796
  }
789
- return;
797
+ }
798
+
799
+ // If it is neither the parent of a ShadowRoot, a <content> element, a <slot>
800
+ // element, nor a <shadow> element recurse normally.
801
+ var child = node.firstChild;
802
+ while (child != null) {
803
+ composedTreeWalk(child, callback, shadowRootAncestor);
804
+ child = child.nextSibling;
790
805
  }
791
806
  }
792
807
 
793
- // If it is neither the parent of a ShadowRoot, a <content> element, a <slot>
794
- // element, nor a <shadow> element recurse normally.
795
- var child = node.firstChild;
796
- while (child != null) {
797
- composedTreeWalk(child, callback, shadowRootAncestor);
798
- child = child.nextSibling;
808
+ /**
809
+ * Adds a style element to the node containing the inert specific styles
810
+ * @param {!Node} node
811
+ */
812
+ function addInertStyle(node) {
813
+ if (node.querySelector('style#inert-style, link#inert-style')) {
814
+ return;
815
+ }
816
+ var style = document.createElement('style');
817
+ style.setAttribute('id', 'inert-style');
818
+ style.textContent = '\n' + '[inert] {\n' + ' pointer-events: none;\n' + ' cursor: default;\n' + '}\n' + '\n' + '[inert], [inert] * {\n' + ' -webkit-user-select: none;\n' + ' -moz-user-select: none;\n' + ' -ms-user-select: none;\n' + ' user-select: none;\n' + '}\n';
819
+ node.appendChild(style);
799
820
  }
800
- }
801
821
 
802
- /**
803
- * Adds a style element to the node containing the inert specific styles
804
- * @param {!Node} node
805
- */
806
- function addInertStyle(node) {
807
- if (node.querySelector('style#inert-style')) {
808
- return;
822
+ if (!Element.prototype.hasOwnProperty('inert')) {
823
+ /** @type {!InertManager} */
824
+ var inertManager = new InertManager(document);
825
+
826
+ Object.defineProperty(Element.prototype, 'inert', {
827
+ enumerable: true,
828
+ /** @this {!Element} */
829
+ get: function get() {
830
+ return this.hasAttribute('inert');
831
+ },
832
+ /** @this {!Element} */
833
+ set: function set(inert) {
834
+ inertManager.setInert(this, inert);
835
+ }
836
+ });
809
837
  }
810
- var style = document.createElement('style');
811
- style.setAttribute('id', 'inert-style');
812
- style.textContent = '\n' + '[inert] {\n' + ' pointer-events: none;\n' + ' cursor: default;\n' + '}\n' + '\n' + '[inert], [inert] * {\n' + ' user-select: none;\n' + ' -webkit-user-select: none;\n' + ' -moz-user-select: none;\n' + ' -ms-user-select: none;\n' + '}\n';
813
- node.appendChild(style);
814
- }
815
-
816
- /** @type {!InertManager} */
817
- var inertManager = new InertManager(document);
818
-
819
- if (!Element.prototype.hasOwnProperty('inert')) {
820
- Object.defineProperty(Element.prototype, 'inert', {
821
- enumerable: true,
822
- /** @this {!Element} */
823
- get: function get() {
824
- return this.hasAttribute('inert');
825
- },
826
- /** @this {!Element} */
827
- set: function set(inert) {
828
- inertManager.setInert(this, inert);
829
- }
830
- });
831
- }
838
+ })();
832
839
 
833
840
  })));