import {createStoryPlayer} from './tour-player.mjs'; const dialog=document.querySelector('[data-tour]'); if(dialog) { const $=s=>dialog.querySelector(s),all=s=>Array.from(dialog.querySelectorAll(s)); const strings=Object.fromEntries(all('[data-string]').map(el=>[el.dataset.string,el.textContent])); const recordings=JSON.parse($('#tour-audio-timing').textContent); const scenes=all('[data-scene]'),chapters=all('[data-scene-select]'); const narrator=new Audio(),music=new Audio(dialog.dataset.assets+'music.mp3'); narrator.preload='none';music.preload='none';music.loop=true; const voiceToggle=$('[data-tour-voice]'),musicToggle=$('[data-tour-music]'); let returnFocus=null,currentScene=-1,currentTopic=null,musicRevision=0,frame=0; const track=el=>({id:el.dataset.recording,src:el.dataset.audio||null,pauses:recordings[el.dataset.recording]?.pauses||[]}); const featureTracks=Object.fromEntries(all('template[data-topic-template]').map(el=>[el.dataset.topicTemplate,track(el)])); async function updateMusic(state){ const ticket=++musicRevision; if(dialog.open&&state.started&&musicToggle.checked){ music.volume=Number($('[data-tour-music-volume]').value)/100*(state.running?.38:1); try{await music.play();if(ticket!==musicRevision)return;}catch{if(ticket===musicRevision)musicToggle.checked=false;} }else music.pause(); } function render(state){ if(currentScene!==state.scene){ currentScene=state.scene; scenes.forEach((scene,i)=>scene.hidden=i!==state.scene); chapters.forEach((button,i)=>i===state.scene?button.setAttribute('aria-current','step'):button.removeAttribute('aria-current')); } if(currentTopic!==state.topic){ currentTopic=state.topic;$('[data-tour-feature]').hidden=!state.topic;$('[data-tour-welcome]').hidden=Boolean(state.topic); if(state.topic){const template=$('template[data-topic-template="'+state.topic+'"]');$('[data-tour-feature-content]').replaceChildren(template.content.cloneNode(true));$('.tour-sidebar').scrollTop=0;} } const el=state.topic?$('[data-feature-transcript]'):scenes[state.scene].querySelector('[data-scene-transcript]'); $('[data-tour-caption]').textContent=el?.textContent||''; $('[data-tour-play]').textContent=state.running?strings.pause:state.phase==='complete'?strings.restart:strings.play; $('[data-tour-prev]').disabled=state.scene===0;$('[data-tour-next]').disabled=state.scene===scenes.length-1; for(const button of all('[data-topic]'))button.setAttribute('aria-pressed',String(button.dataset.topic===state.topic)); const labels={ready:'ready',story:'speaking',detail:'speaking',waiting:'waiting',transition:'waiting',paused:'paused',silent:'paused',complete:'end',unavailable:'failed'}; $('[data-tour-status]').textContent=strings[labels[state.phase]]; $('[data-tour-position]').textContent=String(state.scene+1).padStart(2,'0')+' / '+String(scenes.length).padStart(2,'0'); const seek=$('[data-tour-seek]');seek.disabled=state.mode!=='main'||!Number.isFinite(narrator.duration); seek.value=state.mode==='main'&&narrator.duration?narrator.currentTime/narrator.duration*100:0; if(state.running)voiceToggle.checked=true; if(state.phase==='unavailable')voiceToggle.checked=false; updateMusic(state); } const player=createStoryPlayer({audio:narrator,scenes:scenes.map(track),features:featureTracks,onChange:render}); function watchPause(){player.tick();if(dialog.open)frame=requestAnimationFrame(watchPause);} for(const opener of document.querySelectorAll('[data-tour-open]'))opener.addEventListener('click',event=>{event.preventDefault();returnFocus=opener;if(!dialog.open){dialog.showModal();frame=requestAnimationFrame(watchPause);}render(player.snapshot());}); $('[data-tour-start]').addEventListener('click',()=>{voiceToggle.checked=true;player.start(true);}); $('[data-tour-silent]').addEventListener('click',()=>{voiceToggle.checked=false;player.start(false);}); // Hover and keyboard focus only reveal CSS bubbles. They never stop narration. for(const button of all('[data-topic]'))button.addEventListener('click',()=>{player.feature(button.dataset.topic);}); chapters.forEach(button=>button.addEventListener('click',()=>player.select(Number(button.dataset.sceneSelect)))); $('[data-tour-prev]').addEventListener('click',()=>player.select(player.snapshot().scene-1)); $('[data-tour-next]').addEventListener('click',()=>player.select(player.snapshot().scene+1)); $('[data-tour-resume]').addEventListener('click',()=>player.returnToStory()); $('[data-tour-replay]').addEventListener('click',()=>{voiceToggle.checked=true;player.replayFeature();}); $('[data-tour-play]').addEventListener('click',()=>{if(player.snapshot().running)player.pause();else{voiceToggle.checked=true;player.continue();}}); voiceToggle.addEventListener('change',()=>player.setVoice(voiceToggle.checked)); musicToggle.addEventListener('change',()=>updateMusic(player.snapshot())); $('[data-tour-music-volume]').addEventListener('input',()=>updateMusic(player.snapshot())); $('[data-tour-seek]').addEventListener('change',event=>{if(player.snapshot().mode==='main'&&Number.isFinite(narrator.duration))narrator.currentTime=narrator.duration*Number(event.target.value)/100;}); dialog.addEventListener('click',event=>{ const pin=event.target.closest('[data-pin-demo]'),palette=event.target.closest('[data-pin-palette]'),colors=['green','yellow','red','blue']; if(pin){const dot=pin.querySelector('i');dot.dataset.pinColor=event.altKey?colors[(colors.indexOf(dot.dataset.pinColor)+1)%4]:dot.dataset.pinColor==='none'?'green':'none';} if(palette){const dot=$('[data-pin-demo] i');if(dot)dot.dataset.pinColor=palette.dataset.pinPalette;} }); $('[data-tour-film]').addEventListener('click',()=>dialog.close()); dialog.addEventListener('keydown',event=>{ if(event.target.matches('input,textarea,select')||event.altKey||event.ctrlKey||event.metaKey)return; if(event.key==='ArrowRight'){event.preventDefault();player.select(player.snapshot().scene+1);} if(event.key==='ArrowLeft'){event.preventDefault();player.select(player.snapshot().scene-1);} }); dialog.addEventListener('close',()=>{cancelAnimationFrame(frame);player.close();music.pause();music.currentTime=0;voiceToggle.checked=false;returnFocus?.focus();}); document.addEventListener('visibilitychange',()=>{if(document.hidden&&dialog.open){player.pause();music.pause();}}); render(player.snapshot()); }