| OLD | NEW |
| (Empty) | |
| 1 /** |
| 2 @license |
| 3 Copyright (c) 2017 The Polymer Project Authors. All rights reserved. |
| 4 This code may only be used under the BSD style license found at http://polymer.g
ithub.io/LICENSE.txt |
| 5 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt |
| 6 The complete set of contributors may be found at http://polymer.github.io/CONTRI
BUTORS.txt |
| 7 Code distributed by Google as part of the polymer project is also |
| 8 subject to an additional IP rights grant found at http://polymer.github.io/PATEN
TS.txt |
| 9 */ |
| 10 |
| 11 'use strict'; |
| 12 |
| 13 import {nativeShadow} from './style-settings.js' |
| 14 import StyleTransformer from './style-transformer.js' |
| 15 import {getIsExtends} from './style-util.js' |
| 16 |
| 17 export let flush = function() {}; |
| 18 |
| 19 /** |
| 20 * @param {HTMLElement} element |
| 21 * @return {!Array<string>} |
| 22 */ |
| 23 function getClasses(element) { |
| 24 let classes = []; |
| 25 if (element.classList) { |
| 26 classes = Array.from(element.classList); |
| 27 } else if (element instanceof window['SVGElement'] && element.hasAttribute('cl
ass')) { |
| 28 classes = element.getAttribute('class').split(/\s+/); |
| 29 } |
| 30 return classes; |
| 31 } |
| 32 |
| 33 /** |
| 34 * @param {HTMLElement} element |
| 35 * @return {string} |
| 36 */ |
| 37 function getCurrentScope(element) { |
| 38 let classes = getClasses(element); |
| 39 let idx = classes.indexOf(StyleTransformer.SCOPE_NAME); |
| 40 if (idx > -1) { |
| 41 return classes[idx + 1]; |
| 42 } |
| 43 return ''; |
| 44 } |
| 45 |
| 46 /** |
| 47 * @param {Array<MutationRecord|null>|null} mxns |
| 48 */ |
| 49 function handler(mxns) { |
| 50 for (let x=0; x < mxns.length; x++) { |
| 51 let mxn = mxns[x]; |
| 52 if (mxn.target === document.documentElement || |
| 53 mxn.target === document.head) { |
| 54 continue; |
| 55 } |
| 56 for (let i=0; i < mxn.addedNodes.length; i++) { |
| 57 let n = mxn.addedNodes[i]; |
| 58 if (n.nodeType !== Node.ELEMENT_NODE) { |
| 59 continue; |
| 60 } |
| 61 n = /** @type {HTMLElement} */(n); // eslint-disable-line no-self-assign |
| 62 let root = n.getRootNode(); |
| 63 let currentScope = getCurrentScope(n); |
| 64 // node was scoped, but now is in document |
| 65 if (currentScope && root === n.ownerDocument) { |
| 66 StyleTransformer.dom(n, currentScope, true); |
| 67 } else if (root.nodeType === Node.DOCUMENT_FRAGMENT_NODE) { |
| 68 let newScope; |
| 69 let host = /** @type {ShadowRoot} */(root).host; |
| 70 // element may no longer be in a shadowroot |
| 71 if (!host) { |
| 72 continue; |
| 73 } |
| 74 newScope = getIsExtends(host).is; |
| 75 if (currentScope === newScope) { |
| 76 continue; |
| 77 } |
| 78 if (currentScope) { |
| 79 StyleTransformer.dom(n, currentScope, true); |
| 80 } |
| 81 StyleTransformer.dom(n, newScope); |
| 82 } |
| 83 } |
| 84 } |
| 85 } |
| 86 |
| 87 if (!nativeShadow) { |
| 88 let observer = new MutationObserver(handler); |
| 89 let start = (node) => { |
| 90 observer.observe(node, {childList: true, subtree: true}); |
| 91 } |
| 92 let nativeCustomElements = (window['customElements'] && |
| 93 !window['customElements']['polyfillWrapFlushCallback']); |
| 94 // need to start immediately with native custom elements |
| 95 // TODO(dfreedm): with polyfilled HTMLImports and native custom elements |
| 96 // excessive mutations may be observed; this can be optimized via cooperation |
| 97 // with the HTMLImports polyfill. |
| 98 if (nativeCustomElements) { |
| 99 start(document); |
| 100 } else { |
| 101 let delayedStart = () => { |
| 102 start(document.body); |
| 103 } |
| 104 // use polyfill timing if it's available |
| 105 if (window['HTMLImports']) { |
| 106 window['HTMLImports']['whenReady'](delayedStart); |
| 107 // otherwise push beyond native imports being ready |
| 108 // which requires RAF + readystate interactive. |
| 109 } else { |
| 110 requestAnimationFrame(function() { |
| 111 if (document.readyState === 'loading') { |
| 112 let listener = function() { |
| 113 delayedStart(); |
| 114 document.removeEventListener('readystatechange', listener); |
| 115 } |
| 116 document.addEventListener('readystatechange', listener); |
| 117 } else { |
| 118 delayedStart(); |
| 119 } |
| 120 }); |
| 121 } |
| 122 } |
| 123 |
| 124 flush = function() { |
| 125 handler(observer.takeRecords()); |
| 126 } |
| 127 } |
| OLD | NEW |