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