(selector, fn, shadowRoot)
| 6 | * Reference: https://javascript.ruanyifeng.com/dom/mutationobserver.html |
| 7 | */ |
| 8 | export function ready(selector, fn, shadowRoot) { |
| 9 | const win = window; |
| 10 | const docRoot = shadowRoot || win.document.documentElement; |
| 11 | if (!docRoot) return false; |
| 12 | const MutationObserver = win.MutationObserver || win.WebKitMutationObserver; |
| 13 | const listeners = docRoot._MutationListeners || []; |
| 14 | |
| 15 | function $ready(selector, fn) { |
| 16 | // Store selectors and callback functions |
| 17 | listeners.push({ |
| 18 | selector: selector, |
| 19 | fn: fn, |
| 20 | }); |
| 21 | |
| 22 | /* Add listening objects */ |
| 23 | if (!docRoot._MutationListeners || !docRoot._MutationObserver) { |
| 24 | docRoot._MutationListeners = listeners; |
| 25 | docRoot._MutationObserver = new MutationObserver(() => { |
| 26 | for (let i = 0; i < docRoot._MutationListeners.length; i++) { |
| 27 | const item = docRoot._MutationListeners[i]; |
| 28 | check(item.selector, item.fn); |
| 29 | } |
| 30 | }); |
| 31 | |
| 32 | docRoot._MutationObserver.observe(docRoot, { |
| 33 | childList: true, |
| 34 | subtree: true, |
| 35 | }); |
| 36 | } |
| 37 | |
| 38 | // Check if the node is already in the DOM |
| 39 | check(selector, fn); |
| 40 | } |
| 41 | |
| 42 | function check(selector, fn) { |
| 43 | const elements = docRoot.querySelectorAll(selector); |
| 44 | for (let i = 0; i < elements.length; i++) { |
| 45 | const element = elements[i]; |
| 46 | element._MutationReadyList_ = element._MutationReadyList_ || []; |
| 47 | if (!element._MutationReadyList_.includes(fn)) { |
| 48 | element._MutationReadyList_.push(fn); |
| 49 | fn.call(element, element); |
| 50 | } |
| 51 | } |
| 52 | } |
| 53 | |
| 54 | const selectorArr = Array.isArray(selector) ? selector : [selector]; |
| 55 | selectorArr.forEach((selector) => $ready(selector, fn)); |
| 56 | } |
no test coverage detected