summaryrefslogtreecommitdiff
path: root/examples/view-transitions/src/scripts/spa-navigation.js
diff options
context:
space:
mode:
Diffstat (limited to 'examples/view-transitions/src/scripts/spa-navigation.js')
-rw-r--r--examples/view-transitions/src/scripts/spa-navigation.js470
1 files changed, 231 insertions, 239 deletions
diff --git a/examples/view-transitions/src/scripts/spa-navigation.js b/examples/view-transitions/src/scripts/spa-navigation.js
index 39159b5ef..ceaf3a955 100644
--- a/examples/view-transitions/src/scripts/spa-navigation.js
+++ b/examples/view-transitions/src/scripts/spa-navigation.js
@@ -1,262 +1,254 @@
import {
- getNavigationType,
- getPathId,
- isBackNavigation,
- shouldNotIntercept,
- updateTheDOMSomehow,
- useTvFragment,
-} from './utils'
+ getNavigationType,
+ getPathId,
+ isBackNavigation,
+ shouldNotIntercept,
+ updateTheDOMSomehow,
+ useTvFragment,
+} from './utils';
// View Transitions support cross-document navigations.
// Should compare performace.
// https://github.com/WICG/view-transitions/blob/main/explainer.md#cross-document-same-origin-transitions
// https://github.com/WICG/view-transitions/blob/main/explainer.md#script-events
function shouldDisableSpa() {
- return false;
+ return false;
}
navigation.addEventListener('navigate', (navigateEvent) => {
- if (shouldDisableSpa()) return
- if (shouldNotIntercept(navigateEvent)) return
-
- const toUrl = new URL(navigateEvent.destination.url)
- const toPath = toUrl.pathname
- const fromPath = location.pathname
- const navigationType = getNavigationType(fromPath, toPath)
-
- if (location.origin !== toUrl.origin) return
-
- switch (navigationType) {
- case 'home-to-movie':
- case 'tv-to-show':
- handleHomeToMovieTransition(navigateEvent, getPathId(toPath))
- break
- case 'movie-to-home':
- case 'show-to-tv':
- handleMovieToHomeTransition(navigateEvent, getPathId(fromPath))
- break
- case 'movie-to-person':
- handleMovieToPersonTransition(
- navigateEvent,
- getPathId(fromPath),
- getPathId(toPath)
- )
- break
- case 'person-to-movie':
- case 'person-to-show':
- handlePersonToMovieTransition(
- navigateEvent,
- getPathId(fromPath),
- getPathId(toPath)
- )
- break
- default:
- return
- }
-})
+ if (shouldDisableSpa()) return;
+ if (shouldNotIntercept(navigateEvent)) return;
+
+ const toUrl = new URL(navigateEvent.destination.url);
+ const toPath = toUrl.pathname;
+ const fromPath = location.pathname;
+ const navigationType = getNavigationType(fromPath, toPath);
+
+ if (location.origin !== toUrl.origin) return;
+
+ switch (navigationType) {
+ case 'home-to-movie':
+ case 'tv-to-show':
+ handleHomeToMovieTransition(navigateEvent, getPathId(toPath));
+ break;
+ case 'movie-to-home':
+ case 'show-to-tv':
+ handleMovieToHomeTransition(navigateEvent, getPathId(fromPath));
+ break;
+ case 'movie-to-person':
+ handleMovieToPersonTransition(navigateEvent, getPathId(fromPath), getPathId(toPath));
+ break;
+ case 'person-to-movie':
+ case 'person-to-show':
+ handlePersonToMovieTransition(navigateEvent, getPathId(fromPath), getPathId(toPath));
+ break;
+ default:
+ return;
+ }
+});
// TODO: https://developer.chrome.com/docs/web-platform/view-transitions/#transitions-as-an-enhancement
function handleHomeToMovieTransition(navigateEvent, movieId) {
- navigateEvent.intercept({
- async handler() {
- const fragmentUrl = useTvFragment(navigateEvent)
- ? '/fragments/TvDetails'
- : '/fragments/MovieDetails'
- const response = await fetch(`${fragmentUrl}/${movieId}`)
- const data = await response.text()
-
- if (!document.startViewTransition) {
- updateTheDOMSomehow(data);
- return;
- }
-
- const thumbnail = document.getElementById(`movie-poster-${movieId}`)
- if (thumbnail) {
- thumbnail.style.viewTransitionName = 'movie-poster'
- }
-
- const transition = document.startViewTransition(() => {
- if (thumbnail) {
- thumbnail.style.viewTransitionName = ''
- }
- document.getElementById('container').scrollTop = 0
- updateTheDOMSomehow(data)
- })
-
- await transition.finished
- },
- })
+ navigateEvent.intercept({
+ async handler() {
+ const fragmentUrl = useTvFragment(navigateEvent)
+ ? '/fragments/TvDetails'
+ : '/fragments/MovieDetails';
+ const response = await fetch(`${fragmentUrl}/${movieId}`);
+ const data = await response.text();
+
+ if (!document.startViewTransition) {
+ updateTheDOMSomehow(data);
+ return;
+ }
+
+ const thumbnail = document.getElementById(`movie-poster-${movieId}`);
+ if (thumbnail) {
+ thumbnail.style.viewTransitionName = 'movie-poster';
+ }
+
+ const transition = document.startViewTransition(() => {
+ if (thumbnail) {
+ thumbnail.style.viewTransitionName = '';
+ }
+ document.getElementById('container').scrollTop = 0;
+ updateTheDOMSomehow(data);
+ });
+
+ await transition.finished;
+ },
+ });
}
function handleMovieToHomeTransition(navigateEvent, movieId) {
- navigateEvent.intercept({
- scroll: 'manual',
- async handler() {
- const fragmentUrl = useTvFragment(navigateEvent)
- ? '/fragments/TvList'
- : '/fragments/MovieList'
- const response = await fetch(fragmentUrl)
- const data = await response.text()
-
- if (!document.startViewTransition) {
- updateTheDOMSomehow(data)
- return
- }
-
- const tempHomePage = document.createElement('div')
- const moviePoster = document.getElementById(`movie-poster`)
- let thumbnail
-
- // If the movie poster is not in the home page, removes the transition style so that
- // the poster doesn't stay on the page while transitioning
- tempHomePage.innerHTML = data
- if (!tempHomePage.querySelector(`#movie-poster-${movieId}`)) {
- moviePoster?.classList.remove('movie-poster')
- }
-
- const transition = document.startViewTransition(() => {
- updateTheDOMSomehow(data)
-
- thumbnail = document.getElementById(`movie-poster-${movieId}`)
- if (thumbnail) {
- thumbnail.scrollIntoViewIfNeeded()
- thumbnail.style.viewTransitionName = 'movie-poster'
- }
- })
-
- await transition.finished
-
- if (thumbnail) {
- thumbnail.style.viewTransitionName = ''
- }
- },
- })
+ navigateEvent.intercept({
+ scroll: 'manual',
+ async handler() {
+ const fragmentUrl = useTvFragment(navigateEvent)
+ ? '/fragments/TvList'
+ : '/fragments/MovieList';
+ const response = await fetch(fragmentUrl);
+ const data = await response.text();
+
+ if (!document.startViewTransition) {
+ updateTheDOMSomehow(data);
+ return;
+ }
+
+ const tempHomePage = document.createElement('div');
+ const moviePoster = document.getElementById(`movie-poster`);
+ let thumbnail;
+
+ // If the movie poster is not in the home page, removes the transition style so that
+ // the poster doesn't stay on the page while transitioning
+ tempHomePage.innerHTML = data;
+ if (!tempHomePage.querySelector(`#movie-poster-${movieId}`)) {
+ moviePoster?.classList.remove('movie-poster');
+ }
+
+ const transition = document.startViewTransition(() => {
+ updateTheDOMSomehow(data);
+
+ thumbnail = document.getElementById(`movie-poster-${movieId}`);
+ if (thumbnail) {
+ thumbnail.scrollIntoViewIfNeeded();
+ thumbnail.style.viewTransitionName = 'movie-poster';
+ }
+ });
+
+ await transition.finished;
+
+ if (thumbnail) {
+ thumbnail.style.viewTransitionName = '';
+ }
+ },
+ });
}
function handleMovieToPersonTransition(navigateEvent, movieId, personId) {
- // TODO: https://developer.chrome.com/docs/web-platform/view-transitions/#not-a-polyfill
- // ...has example of `back-transition` class applied to document
- const isBack = isBackNavigation(navigateEvent)
-
- navigateEvent.intercept({
- async handler() {
- const response = await fetch('/fragments/PersonDetails/' + personId)
- const data = await response.text()
-
- if (!document.startViewTransition) {
- updateTheDOMSomehow(data)
- return
- }
-
- let personThumbnail
- let moviePoster
- let movieThumbnail
-
- if (!isBack) {
- // We're transitioning the person photo; we need to remove the transition of the poster
- // so that it doesn't stay on the page while transitioning
- moviePoster = document.getElementById(`movie-poster`)
- if (moviePoster) {
- moviePoster.classList.remove('movie-poster')
- }
-
- personThumbnail = document.getElementById(`person-photo-${personId}`)
- if (personThumbnail) {
- personThumbnail.style.viewTransitionName = 'person-photo'
- }
- }
-
- const transition = document.startViewTransition(() => {
- updateTheDOMSomehow(data)
-
- if (personThumbnail) {
- personThumbnail.style.viewTransitionName = ''
- }
-
- if (isBack) {
- // If we're coming back to the person page, we're transitioning
- // into the movie poster thumbnail, so we need to add the tag to it
- movieThumbnail = document.getElementById(`movie-poster-${movieId}`)
- if (movieThumbnail) {
- movieThumbnail.scrollIntoViewIfNeeded()
- movieThumbnail.style.viewTransitionName = 'movie-poster'
- }
- }
-
- document.getElementById('container').scrollTop = 0
- })
-
- await transition.finished
-
- if (movieThumbnail) {
- movieThumbnail.style.viewTransitionName = ''
- }
- },
- })
+ // TODO: https://developer.chrome.com/docs/web-platform/view-transitions/#not-a-polyfill
+ // ...has example of `back-transition` class applied to document
+ const isBack = isBackNavigation(navigateEvent);
+
+ navigateEvent.intercept({
+ async handler() {
+ const response = await fetch('/fragments/PersonDetails/' + personId);
+ const data = await response.text();
+
+ if (!document.startViewTransition) {
+ updateTheDOMSomehow(data);
+ return;
+ }
+
+ let personThumbnail;
+ let moviePoster;
+ let movieThumbnail;
+
+ if (!isBack) {
+ // We're transitioning the person photo; we need to remove the transition of the poster
+ // so that it doesn't stay on the page while transitioning
+ moviePoster = document.getElementById(`movie-poster`);
+ if (moviePoster) {
+ moviePoster.classList.remove('movie-poster');
+ }
+
+ personThumbnail = document.getElementById(`person-photo-${personId}`);
+ if (personThumbnail) {
+ personThumbnail.style.viewTransitionName = 'person-photo';
+ }
+ }
+
+ const transition = document.startViewTransition(() => {
+ updateTheDOMSomehow(data);
+
+ if (personThumbnail) {
+ personThumbnail.style.viewTransitionName = '';
+ }
+
+ if (isBack) {
+ // If we're coming back to the person page, we're transitioning
+ // into the movie poster thumbnail, so we need to add the tag to it
+ movieThumbnail = document.getElementById(`movie-poster-${movieId}`);
+ if (movieThumbnail) {
+ movieThumbnail.scrollIntoViewIfNeeded();
+ movieThumbnail.style.viewTransitionName = 'movie-poster';
+ }
+ }
+
+ document.getElementById('container').scrollTop = 0;
+ });
+
+ await transition.finished;
+
+ if (movieThumbnail) {
+ movieThumbnail.style.viewTransitionName = '';
+ }
+ },
+ });
}
function handlePersonToMovieTransition(navigateEvent, personId, movieId) {
- const isBack = isBackNavigation(navigateEvent)
-
- navigateEvent.intercept({
- scroll: 'manual',
- async handler() {
- const fragmentUrl = useTvFragment(navigateEvent)
- ? '/fragments/TvDetails'
- : '/fragments/MovieDetails'
- const response = await fetch(`${fragmentUrl}/${movieId}`)
- const data = await response.text()
-
- if (!document.startViewTransition) {
- updateTheDOMSomehow(data)
- return
- }
-
- let thumbnail
- let moviePoster
- let movieThumbnail
-
- if (!isBack) {
- movieThumbnail = document.getElementById(`movie-poster-${movieId}`)
- if (movieThumbnail) {
- movieThumbnail.style.viewTransitionName = 'movie-poster'
- }
- }
-
- const transition = document.startViewTransition(() => {
- updateTheDOMSomehow(data)
-
- if (isBack) {
- moviePoster = document.getElementById(`movie-poster`)
- if (moviePoster) {
- moviePoster.classList.remove('movie-poster')
- }
-
- if (personId) {
- thumbnail = document.getElementById(`person-photo-${personId}`)
- if (thumbnail) {
- thumbnail.scrollIntoViewIfNeeded()
- thumbnail.style.viewTransitionName = 'person-photo'
- }
- }
- } else {
- document.getElementById('container').scrollTop = 0
-
- if (movieThumbnail) {
- movieThumbnail.style.viewTransitionName = ''
- }
- }
- })
-
- await transition.finished
-
- if (thumbnail) {
- thumbnail.style.viewTransitionName = ''
- }
-
- if (moviePoster) {
- moviePoster.classList.add('movie-poster')
- }
- },
- })
+ const isBack = isBackNavigation(navigateEvent);
+
+ navigateEvent.intercept({
+ scroll: 'manual',
+ async handler() {
+ const fragmentUrl = useTvFragment(navigateEvent)
+ ? '/fragments/TvDetails'
+ : '/fragments/MovieDetails';
+ const response = await fetch(`${fragmentUrl}/${movieId}`);
+ const data = await response.text();
+
+ if (!document.startViewTransition) {
+ updateTheDOMSomehow(data);
+ return;
+ }
+
+ let thumbnail;
+ let moviePoster;
+ let movieThumbnail;
+
+ if (!isBack) {
+ movieThumbnail = document.getElementById(`movie-poster-${movieId}`);
+ if (movieThumbnail) {
+ movieThumbnail.style.viewTransitionName = 'movie-poster';
+ }
+ }
+
+ const transition = document.startViewTransition(() => {
+ updateTheDOMSomehow(data);
+
+ if (isBack) {
+ moviePoster = document.getElementById(`movie-poster`);
+ if (moviePoster) {
+ moviePoster.classList.remove('movie-poster');
+ }
+
+ if (personId) {
+ thumbnail = document.getElementById(`person-photo-${personId}`);
+ if (thumbnail) {
+ thumbnail.scrollIntoViewIfNeeded();
+ thumbnail.style.viewTransitionName = 'person-photo';
+ }
+ }
+ } else {
+ document.getElementById('container').scrollTop = 0;
+
+ if (movieThumbnail) {
+ movieThumbnail.style.viewTransitionName = '';
+ }
+ }
+ });
+
+ await transition.finished;
+
+ if (thumbnail) {
+ thumbnail.style.viewTransitionName = '';
+ }
+
+ if (moviePoster) {
+ moviePoster.classList.add('movie-poster');
+ }
+ },
+ });
}