PluginProbe
Extendify / 3.2.1
Extendify v3.2.1
3.2.1 3.2.0 3.1.6 3.1.5 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.6 3.0.5 3.0.4 trunk 0.1.0 0.10.0 0.10.1 0.10.2 0.11.0 0.11.1 0.2.0 0.3.0 0.3.1 0.4.0 0.5.0 0.6.0 All 127 releases
← All changes | src/Toolbar/toolbar.js +52 -29 3.1.33.2.1 View file →
@@ -25,12 +25,22 @@
25 25 const QUICK_EDIT_ON_CLASS = 'extendify-quick-edit-on';
26 26 const AGENT_BTN_HOST_ID = 'wp-admin-bar-extendify-agent-btn';
27 27 const AGENT_SIDEBAR_ID = 'extendify-agent-sidebar';
28 28
29 +function watch(target, options, callback) {
30 + const observer = new MutationObserver(callback);
31 + observer.observe(target, options);
32 + return observer;
33 +}
34 +
29 35 function findExtendifyAgentButton() {
30 36 const host = document.getElementById(AGENT_BTN_HOST_ID);
31 37 if (!host) return null;
32 - return host.querySelector('button') || host;
38 + const mounted = host.querySelector('button:not([disabled])');
39 + if (mounted) return mounted;
40 + // The stand-in never leaves the slot, so a disabled button means not-yet-mounted.
41 + if (host.querySelector('button')) return null;
42 + return host;
33 43 }
34 44
35 45 function clickExtendifyAgent() {
36 46 const btn = findExtendifyAgentButton();
@@ -60,33 +70,45 @@
60 70 * the Zustand store so we don't have to share a chunk with the
61 71 * agent bundle.
62 72 */
63 73 function watchAgentSidebar(toolbar, aiBtn) {
64 - let attached = false;
65 - const observer = new MutationObserver(() => {
66 - const sidebar = document.getElementById(AGENT_SIDEBAR_ID);
67 - if (!sidebar || attached) return;
68 - attached = true;
69 - const update = () => {
70 - const open = !sidebar.hasAttribute('inert');
71 - toolbar.classList.toggle('ext-tb-agent-open', open);
72 - if (!aiBtn) return;
73 - aiBtn.inert = open;
74 - if (open) {
75 - aiBtn.setAttribute('tabindex', '-1');
76 - aiBtn.setAttribute('aria-hidden', 'true');
77 - } else {
78 - aiBtn.removeAttribute('tabindex');
79 - aiBtn.removeAttribute('aria-hidden');
74 + const setOpen = (open) => {
75 + toolbar.classList.toggle('ext-tb-agent-open', open);
76 + if (!aiBtn) return;
77 + aiBtn.inert = open;
78 + if (open) {
79 + aiBtn.setAttribute('tabindex', '-1');
80 + aiBtn.setAttribute('aria-hidden', 'true');
81 + } else {
82 + aiBtn.removeAttribute('tabindex');
83 + aiBtn.removeAttribute('aria-hidden');
84 + }
85 + };
86 + // A resize past the mobile breakpoint replaces this node, so never latch on one.
87 + let watched = null;
88 + let inertObserver = null;
89 + const observer = watch(
90 + document.body,
91 + { childList: true, subtree: true },
92 + () => {
93 + const sidebar = document.getElementById(AGENT_SIDEBAR_ID);
94 + if (sidebar === watched) return;
95 + watched = sidebar;
96 + inertObserver?.disconnect();
97 + inertObserver = null;
98 + if (!sidebar) {
99 + setOpen(false);
100 + return;
80 101 }
81 - };
82 - new MutationObserver(update).observe(sidebar, {
83 - attributes: true,
84 - attributeFilter: ['inert'],
85 - });
86 - update();
87 - });
88 - observer.observe(document.body, { childList: true, subtree: true });
102 + const update = () => setOpen(!sidebar.hasAttribute('inert'));
103 + inertObserver = watch(
104 + sidebar,
105 + { attributes: true, attributeFilter: ['inert'] },
106 + update,
107 + );
108 + update();
109 + },
110 + );
89 111 if (document.getElementById(AGENT_SIDEBAR_ID)) observer.takeRecords();
90 112 }
91 113
92 114 /**
@@ -99,12 +121,13 @@
99 121 const on = document.documentElement.classList.contains(QUICK_EDIT_ON_CLASS);
100 122 btn.setAttribute('aria-checked', on ? 'true' : 'false');
101 123 };
102 124 sync();
103 - new MutationObserver(sync).observe(document.documentElement, {
104 - attributes: true,
105 - attributeFilter: ['class'],
106 - });
125 + watch(
126 + document.documentElement,
127 + { attributes: true, attributeFilter: ['class'] },
128 + sync,
129 + );
107 130 }
108 131
109 132 function init() {
110 133 // Don't wire the toolbar inside another tool's iframe (Customizer preview,