diff --git a/docs/assets/js/footer-menu.js b/docs/assets/js/footer-menu.js index dea49e04e9..bec1b8f71e 100644 --- a/docs/assets/js/footer-menu.js +++ b/docs/assets/js/footer-menu.js @@ -391,14 +391,25 @@ const DEFAULT_FOOTER_MENUS = [ } ] +let cachedFooterMenus = null; + async function fetchFooterMenus() { + // If we already have cached data, return it + if (cachedFooterMenus) { + return cachedFooterMenus; + } + try { const response = await fetch('https://www.bnbchain.org/api/v1/landing-menus'); const data = await response.json(); - return data.footerMenus ?? DEFAULT_FOOTER_MENUS; + // Cache the response + cachedFooterMenus = data.footerMenus ?? DEFAULT_FOOTER_MENUS; + return cachedFooterMenus; } catch (error) { console.error('Error fetching footer menus:', error); - return DEFAULT_FOOTER_MENUS; + // Cache the default menus in case of error + cachedFooterMenus = DEFAULT_FOOTER_MENUS; + return cachedFooterMenus; } } @@ -424,21 +435,92 @@ function createMenuHTML(menu) { `; } -async function initializeFooterMenus() { - const footerMenus = await fetchFooterMenus(); +let observer = null; +let isUpdating = false; + +function setupObserver() { + if (observer) { + observer.disconnect(); + } + + const targetNode = document.body; + const config = { childList: true, subtree: true }; + + const callback = (mutationsList, observer) => { + // Prevent recursive calls + if (isUpdating) { + return; + } + + for (const mutation of mutationsList) { + if (mutation.type === 'childList') { + const footerInner = document.querySelector('.doc-footer__inner'); + const copyrightInner = document.querySelector('.doc-copyright__inner'); + + // Only update if footer elements are missing or empty + if ((!footerInner || !footerInner.children.length) || + (!copyrightInner || !copyrightInner.children.length)) { + + // Set flag before updating + isUpdating = true; + + // Use setTimeout to break the synchronous execution chain + setTimeout(() => { + initializeFooterMenus(); + isUpdating = false; + }, 0); + + break; + } + } + } + }; + + observer = new MutationObserver(callback); + observer.observe(targetNode, config); +} + +// Initialize footer content +function initializeFooterMenus() { + // Skip if already has content + const footerInner = document.querySelector('.doc-footer__inner'); + const copyrightElement = document.querySelector('.doc-copyright__inner'); + + if (footerInner?.children.length && copyrightElement?.children.length) { + return; + } + + // If we have cached data, use it immediately + if (cachedFooterMenus) { + updateFooterContent(cachedFooterMenus); + return; + } + + // Only fetch if we don't have cached data + fetchFooterMenus().then(footerMenus => { + updateFooterContent(footerMenus); + }); +} + +// Update footer content without triggering observer +function updateFooterContent(footerMenus) { if (!footerMenus) return; const footerInner = document.querySelector('.doc-footer__inner'); - if (footerInner) { + const copyrightElement = document.querySelector('.doc-copyright__inner'); + + if (footerInner && (!footerInner.children.length)) { footerInner.innerHTML = footerMenus.map(menu => createMenuHTML(menu)).join(''); } - // Update copyright year - const copyrightElement = document.querySelector('.doc-copyright__inner'); - if (copyrightElement) { + if (copyrightElement && (!copyrightElement.children.length)) { const currentYear = new Date().getFullYear(); copyrightElement.innerHTML = `© ${currentYear} Bnbchain.org. All rights reserved.`; } } -document.addEventListener('DOMContentLoaded', initializeFooterMenus); \ No newline at end of file +// Handle initial page load +document.addEventListener('DOMContentLoaded', () => { + initializeFooterMenus(); + setupObserver(); +}); \ No newline at end of file