I want to animate my navbar using JavaScript. I have created separate navbar.html and included it using csi.min.js. When I try to getElementById my navbar, show and hide button. it returns null and when try it on dev console it works.
navbar.html:
<nav>
<div class="site-mobile-menu collapse navbar-collapse show" id="main-navbar">
navbar content
</div>
<nav>
index.html:
<div data-include="/src/navbar.html"></div>
<script src="/src/js/navbar.js"></script>
navbar.js:
window.addEventListener("load", function() {
// debugger;
var mobNav = document.getElementById("main-navbar");
var showNavBtn = document.querySelector("#show-nav");
var hideNavBtn = document.getElementById("hide-nav");
console.log(mobNav + " " + showNavBtn + " " + hideNavBtn);
if (!mobNav == null || !showNavBtn == null || !hideNavBtn == null) {
showNavBtn.onclick = function() {
console.log("clicked");
mobNav.classList.add("nav-shown");
}
} else {
console.log("Error Opening Mobile Navbar");
}
}, false);
When the window load, the elements such as #main-navbar are not in the DOM yet, csi adds them later.
Ideally, csi would give an option to notified when a [data-include] element is loaded but it doesn't. I can suggest 2 ways:
// this is csi re-implementation
function fetchTemplates() {
return Promise.all(
[...document.querySelectorAll('[data-include]')].map(async el => {
const response = await fetch(el.getAttribute('data-include'));
const html = await response.text();
el.outerHTML = html;
}));
}
// now you can call fetchTemplates and wait for it to done
(async () => {
await fetchTemplates()
console.log('templates are loaded. you can now find #main-navbar');
console.log(document.querySelector('#main-navbar'));
})();
https://codesandbox.io/s/zealous-jepsen-12ihl?file=/re-implement-csi.html
MutationObserver to catch when csi replace the element with the fetched content.const div = document.querySelector('[data-include="/src/navbar.html"]');
const observer = new MutationObserver(function (mutationsList, observer) {
const templates = document.querySelectorAll('[data-include]');
if (templates.length === 0) {
console.log('all templates loaded, now you can find #main-navbar');
console.log(document.querySelector('#main-navbar'));
}
// we no longer should observe the div
observer.disconnect();
});
observer.observe(div.parentElement, {
childList: true,
});
https://codesandbox.io/s/zealous-jepsen-12ihl?file=/index.html
Personally I recommend the first option because
XMLHttpRequest).