DEV Community

Mathieu Préaud
Mathieu Préaud

Posted on

Javascript page transition issue

I'm using Javascript to create some page transition effect to avoid reloading pages while navigating on a website.

The interface of the website is divided in 2 parts. The first part is the menu that is present in all pages of the site. The second part is the main content that refreshs by loading the new content of the page.

The issue is, when I have a link inside the main content main, the link doesn't trigger the page transition. It only works with the links inside the menu.

const main = document.querySelector('.js-content');
const links = [...document.querySelectorAll('a')];

let isAnimating = false;

links.forEach(link => {
    link.addEventListener('click', async e => {
        e.preventDefault();
        if(isAnimating) return
        const url = e.target.href;
        console.log(url)
        startTransition(url);
        const pathname = new URL(url).pathname;
        history.pushState(null, '', pathname);
    })
})

window.addEventListener('popstate', e => {
    const url = window.location.pathname;
    startTransition(url)
})

const startTransition = async (url) => {
    isAnimating = true;
    const html = await fetch(url);
    const htmlString = await html.text();
    const parser = new DOMParser();
    const parsedhtml = parser.parseFromString(htmlString, 'text/html').querySelector('.js-content')

    transitionDiv.classList.add('is-animate-in');
    transitionDiv.addEventListener('transitionend', () => {
        main.innerHTML = parsedhtml.innerHTML;
        transitionDiv.classList.remove('is-animate-in');
        transitionDiv.classList.add('is-animate-out');
        setTimeout(() => {
            transitionDiv.style.transition = '0s';
            transitionDiv.classList.remove('is-animate-out');

            setTimeout(() => {
                transitionDiv.style.transition = '1s';
            }, 100)
            isAnimating = false;
        }, 1000)
    }, {once: true})
}
Enter fullscreen mode Exit fullscreen mode

I read some topics about JS Event Delegation. I tried targeting the node a in the main content, but it doesn't seem to work.

main.addEventListener("click", async (e) =>  {
    if(e.target && e.target.nodeName == "a") {
        e.preventDefault();
        if(isAnimating) return
        const url = e.target.href;
        console.log(url)
        startTransition(url);
        const pathname = new URL(url).pathname;
        history.pushState(null, '', pathname);
    }
});

Enter fullscreen mode Exit fullscreen mode

You can reproduce the issue one this Sandbox.
Thank you.

Top comments (0)