Source code
Revision control
Copy as Markdown
Other Tools
<!DOCTYPE html>
<title>View transitions: cross-document navigation to a prerender with COOP (helper)</title>
<script src="/common/utils.js"></script>
<script src="/speculation-rules/resources/utils.js"></script>
<script src="/speculation-rules/prerender/resources/utils.js"></script>
<style>
@view-transition {
navigation: auto;
}
::view-transition-old(root) {
animation: 300ms ease-out both slide-out;
}
::view-transition-new(root) {
animation: 300ms ease-out both slide-in;
}
@keyframes slide-out {
to { transform: translateX(-100%); }
}
@keyframes slide-in {
from { transform: translateX(100%); }
}
</style>
<script>
const params = new URLSearchParams(location.search);
const uid = params.get('uid');
const mode = params.get('mode');
if (mode === 'runner') {
const ready_channel = new PrerenderChannel('ready-to-activate', uid);
onload = async () => {
const next_url = new URL(`prerender-coop.html?mode=next&uid=${uid}`, window.location).href;
const ready_to_activate = new Promise(resolve => {
ready_channel.addEventListener('message', resolve, {once: true});
});
startPrerendering(next_url);
await ready_to_activate;
window.location.replace(new URL(next_url, window.location));
};
} else if (mode === 'next') {
const ready_channel = new PrerenderChannel('ready-to-activate', uid);
const result_channel = new PrerenderChannel('result', uid);
const was_prerendered = document.prerendering;
let got_pagereveal = false;
let has_view_transition = false;
let transition_error = null;
addEventListener('pagereveal', e => {
got_pagereveal = true;
has_view_transition = !!e.viewTransition;
if (e.viewTransition) {
e.viewTransition.ready.catch(err => {
transition_error = (err && err.message) ? err.message : String(err);
});
}
});
if (document.prerendering) {
document.addEventListener('prerenderingchange', () => {
requestAnimationFrame(() => {
requestAnimationFrame(async () => {
let result = "pass";
if (!got_pagereveal) {
result = "fail: pagereveal did not fire";
} else if (!has_view_transition) {
result = "fail: no viewTransition in pagereveal";
} else if (transition_error) {
result = "fail: transition error: " + transition_error;
}
await result_channel.postMessage(result);
result_channel.close();
window.close();
});
});
});
ready_channel.postMessage('ready');
ready_channel.close();
} else {
addEventListener('pagereveal', e => {
requestAnimationFrame(() => {
requestAnimationFrame(async () => {
let result = "pass";
if (!was_prerendered) {
result = "fail: page was not prerendered";
} else if (!has_view_transition) {
result = "fail: no viewTransition in pagereveal";
} else if (transition_error) {
result = "fail: transition error: " + transition_error;
}
await result_channel.postMessage(result);
result_channel.close();
window.close();
});
});
});
}
}
</script>