diff options
author | 2023-07-25 08:35:47 -0400 | |
---|---|---|
committer | 2023-07-25 08:35:47 -0400 | |
commit | 188eeddd47a61e04639670496924c37866180749 (patch) | |
tree | 14c44bb024e71bca1c069ed1c4f0032f9ff7b3db | |
parent | 25e04a2ecbda7952a68220ce6739ae1c75144858 (diff) | |
download | astro-188eeddd47a61e04639670496924c37866180749.tar.gz astro-188eeddd47a61e04639670496924c37866180749.tar.zst astro-188eeddd47a61e04639670496924c37866180749.zip |
Execute scripts on page navigation (view transitions) (#7786)
* Execute scripts on page navigation (view transitions)
* Update .changeset/sharp-seas-smile.md
Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>
---------
Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>
-rw-r--r-- | .changeset/sharp-seas-smile.md | 15 | ||||
-rw-r--r-- | packages/astro/components/ViewTransitions.astro | 21 | ||||
-rw-r--r-- | packages/astro/e2e/fixtures/view-transitions/src/pages/two.astro | 6 | ||||
-rw-r--r-- | packages/astro/e2e/view-transitions.test.js | 23 |
4 files changed, 61 insertions, 4 deletions
diff --git a/.changeset/sharp-seas-smile.md b/.changeset/sharp-seas-smile.md new file mode 100644 index 000000000..1bc478e80 --- /dev/null +++ b/.changeset/sharp-seas-smile.md @@ -0,0 +1,15 @@ +--- +'astro': patch +--- + +Execute scripts when navigating to a new page. + +When navigating to an new page with client-side navigation, scripts are executed (and re-executed) so that any new scripts on the incoming page are run and the DOM can be updated. + +However, `type=module` scripts never re-execute in Astro, and will not do so in client-side routing. To support cases where you want to modify the DOM, a new `astro:load` event listener been added: + +```js +document.addEventListener('astro:load', () => { + updateTheDOMSomehow(); +}); +``` diff --git a/packages/astro/components/ViewTransitions.astro b/packages/astro/components/ViewTransitions.astro index d7703bc82..c2f9a7206 100644 --- a/packages/astro/components/ViewTransitions.astro +++ b/packages/astro/components/ViewTransitions.astro @@ -25,6 +25,7 @@ const { fallback = 'animate' } = Astro.props as Props; const supportsViewTransitions = !!document.startViewTransition; const transitionEnabledOnThisPage = () => !!document.querySelector('[name="astro-view-transitions-enabled"]'); + const onload = () => document.dispatchEvent(new Event('astro:load')); async function getHTML(href: string) { const res = await fetch(href); @@ -40,6 +41,23 @@ const { fallback = 'animate' } = Astro.props as Props; return 'animate'; } + function runScripts() { + let wait = Promise.resolve(); + for(const script of Array.from(document.scripts)) { + const s = document.createElement('script'); + s.innerHTML = script.innerHTML; + for(const attr of script.attributes) { + if(attr.name === 'src') { + const p = new Promise(r => {s.onload = r}); + wait = wait.then(() => p as any); + } + s.setAttribute(attr.name, attr.value); + } + script.replaceWith(s); + } + return wait; + } + const parser = new DOMParser(); async function updateDOM(dir: Direction, html: string, fallback?: Fallback) { @@ -95,6 +113,8 @@ const { fallback = 'animate' } = Astro.props as Props; await finished; } finally { document.documentElement.removeAttribute('data-astro-transition'); + await runScripts(); + onload(); } } @@ -171,5 +191,6 @@ const { fallback = 'animate' } = Astro.props as Props; { passive: true, capture: true } ); }); + addEventListener('load', onload) } </script> diff --git a/packages/astro/e2e/fixtures/view-transitions/src/pages/two.astro b/packages/astro/e2e/fixtures/view-transitions/src/pages/two.astro index ec5b699d8..84b16f259 100644 --- a/packages/astro/e2e/fixtures/view-transitions/src/pages/two.astro +++ b/packages/astro/e2e/fixtures/view-transitions/src/pages/two.astro @@ -3,4 +3,10 @@ import Layout from '../components/Layout.astro'; --- <Layout link="/two.css"> <p id="two">Page 2</p> + <article id="twoarticle"></article> </Layout> +<script> + document.addEventListener('astro:load', () => { + document.getElementById('twoarticle')!.textContent = 'works'; + }, { once: true }); +</script> diff --git a/packages/astro/e2e/view-transitions.test.js b/packages/astro/e2e/view-transitions.test.js index da5252709..d799b5ef3 100644 --- a/packages/astro/e2e/view-transitions.test.js +++ b/packages/astro/e2e/view-transitions.test.js @@ -128,10 +128,6 @@ test.describe('View Transitions', () => { }); test('Stylesheets in the head are waited on', async ({ page, astro }) => { - page.addListener('console', (data) => { - console.log(data); - }); - // Go to page 1 await page.goto(astro.resolveUrl('/one')); let p = page.locator('#one'); @@ -143,4 +139,23 @@ test.describe('View Transitions', () => { await expect(p, 'should have content').toHaveText('Page 2'); await expect(p, 'imported CSS updated').toHaveCSS('font-size', '24px'); }); + + test('astro:load event fires when navigating to new page', async ({ page, astro }) => { + // Go to page 1 + await page.goto(astro.resolveUrl('/one')); + const p = page.locator('#one'); + await expect(p, 'should have content').toHaveText('Page 1'); + + // go to page 2 + await page.click('#click-two'); + const article = page.locator('#twoarticle'); + await expect(article, 'should have script content').toHaveText('works'); + }); + + test('astro:load event fires when navigating directly to a page', async ({ page, astro }) => { + // Go to page 1 + await page.goto(astro.resolveUrl('/two')); + const article = page.locator('#twoarticle'); + await expect(article, 'should have script content').toHaveText('works'); + }); }); |