diff options
Diffstat (limited to 'examples/view-transitions/src/scripts/spa-navigation.js')
-rw-r--r-- | examples/view-transitions/src/scripts/spa-navigation.js | 470 |
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'); + } + }, + }); } |