File size: 7,696 Bytes
4155f6b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import {escape} from './common.js';
import {guides} from './activity-guide-content.js?v=brain-circuit-47';
import {brainConnections,guideSources} from './brain-connections.js?v=brain-circuit-47';

const notes=new Map();
function listSteps(items){return `<ol class="activity-guide-steps">${items.map(([title,text],i)=>`<li><span class="activity-guide-number" aria-hidden="true">${i+1}</span><div><h4>${escape(title)}</h4><p>${escape(text)}</p></div></li>`).join('')}</ol>`}
function references(data,guide){const sources=[...data.sources.map(key=>guideSources[key]),...(guide.primarySources||[])];return `<div class="activity-guide-sources"><h4>Sources and further reading</h4>${sources.map(s=>`<a href="${escape(s.url)}" target="_blank" rel="noreferrer">${escape(s.title)} ↗</a>`).join('')}</div>`}
export function renderActivityGuide(root,id,name,usage){
 const guide=guides[id],brain=brainConnections[id];if(!guide||!brain||!usage)return false;
 const prefix='activity-guide-'+id,isReading=id.startsWith('jewish'),tabNames=['How to use','How it works','Brain connection','Try and check'];
 const quiz=`<section class="activity-guide-check"><span class="activity-guide-label">CHECK YOUR UNDERSTANDING</span><h4>${escape(guide.question)}</h4><div class="activity-guide-answers">${guide.answers.map((a,i)=>`<button class="secondary" data-explain-answer="${i}" aria-pressed="false">${escape(a)}</button>`).join('')}</div><p class="activity-guide-feedback" role="status" hidden></p></section>`;
 root.innerHTML=`<details class="activity-guide" data-guide-for="${id}" open><summary><span class="activity-guide-icon" aria-hidden="true">?</span><span><span class="activity-guide-label">GUIDE · EXPLANATION · BRAIN CONNECTION</span><strong>${escape(name||id)}</strong></span><span class="activity-guide-toggle" aria-hidden="true"></span></summary>
 <div class="activity-guide-body"><p class="activity-guide-idea">${escape(brain.summary)}</p>
 <div class="activity-guide-tabs" role="tablist" aria-label="Guide sections for ${escape(name||id)}">${tabNames.map((label,i)=>`<button id="${prefix}-tab-${i}" role="tab" aria-selected="${i===0}" aria-controls="${prefix}-panel-${i}" tabindex="${i===0?0:-1}" data-explain-tab="${i}">${label}</button>`).join('')}</div>
 <section class="activity-guide-panel" id="${prefix}-panel-0" role="tabpanel" aria-labelledby="${prefix}-tab-0" tabindex="0"><h3>Start here</h3><p>${escape(usage.goal)}</p>${listSteps(usage.steps)}${usage.watch?`<p class="activity-guide-watch"><strong>What to watch:</strong> ${escape(usage.watch)}</p>`:''}${usage.controls?.length?`<details class="activity-guide-controls"><summary>What the controls mean</summary><dl>${usage.controls.map(([term,definition])=>`<div><dt>${escape(term)}</dt><dd>${escape(definition)}</dd></div>`).join('')}</dl></details>`:''}</section>
 <section class="activity-guide-panel" id="${prefix}-panel-1" role="tabpanel" aria-labelledby="${prefix}-tab-1" tabindex="0" hidden><h3>${escape(guide.title)}</h3>${listSteps(guide.steps)}<section class="activity-guide-terms"><h4>Useful words</h4><dl>${brain.terms.map(([term,definition])=>`<div><dt>${escape(term)}</dt><dd>${escape(definition)}</dd></div>`).join('')}</dl></section></section>
 <section class="activity-guide-panel" id="${prefix}-panel-2" role="tabpanel" aria-labelledby="${prefix}-tab-2" tabindex="0" hidden><span class="activity-guide-kind">${escape(brain.kind)}</span><h3>How this connects to the brain</h3><p>${escape(brain.mechanism)}</p><div class="activity-guide-map"><div class="activity-guide-map-head"><span>In this activity</span><span>The connection to the brain or cognition</span></div>${brain.mapping.map(([screen,biology])=>`<div><h4>${escape(screen)}</h4><p>${escape(biology)}</p></div>`).join('')}</div><section class="activity-guide-boundary"><h4>Where the comparison stops</h4><p>${escape(brain.boundary)}</p></section>${references(brain,guide)}</section>
 <section class="activity-guide-panel" id="${prefix}-panel-3" role="tabpanel" aria-labelledby="${prefix}-tab-3" tabindex="0" hidden><h3>Make a prediction, then compare</h3><ol class="activity-guide-experiment">${guide.try.map(t=>`<li>${escape(t)}</li>`).join('')}</ol>${isReading?`<p>Keep your interpretation and reflection in the notes on this source sheet.</p><div class="activity-guide-reading-actions"><button class="secondary" data-explain-notes>Open your source-sheet notes</button><button class="secondary" data-explain-source-check>Open the source question</button></div>`:`<div class="activity-guide-notes"><label>Before trying it: what do you predict?<textarea rows="3" data-explain-note="prediction" aria-label="Your prediction for ${escape(name||id)}" placeholder="I predict… because…"></textarea></label><label>After trying it: what happened?<textarea rows="3" data-explain-note="observation" aria-label="Your observation for ${escape(name||id)}" placeholder="I noticed… A fair comparison would…"></textarea></label></div><p class="activity-guide-note">Guide notes stay while you switch activities. Refreshing the page clears them.</p>${quiz}`}<p class="activity-guide-note">${escape(guide.limits)}</p></section>
 <div class="activity-guide-footer"><span>Change one thing, compare, then explain what happened.</span><button class="primary" data-explain-jump>Go to activity <span aria-hidden="true">↓</span></button></div>
 </div></details>`;
 const box=root.querySelector('.activity-guide'),tabs=[...box.querySelectorAll('[data-explain-tab]')],panels=[...box.querySelectorAll('[role=tabpanel]')];
 function select(index){tabs.forEach((button,i)=>{button.setAttribute('aria-selected',String(i===index));button.tabIndex=i===index?0:-1;panels[i].hidden=i!==index});}
 tabs.forEach((tab,index)=>{tab.onclick=()=>select(index);tab.onkeydown=event=>{let target=index;if(event.key==='ArrowRight')target=(index+1)%tabs.length;else if(event.key==='ArrowLeft')target=(index+tabs.length-1)%tabs.length;else if(event.key==='Home')target=0;else if(event.key==='End')target=tabs.length-1;else return;event.preventDefault();select(target);tabs[target].focus()}});
 box.querySelectorAll('[data-explain-answer]').forEach(button=>button.onclick=()=>{const correct=Number(button.dataset.explainAnswer)===guide.correct;box.querySelectorAll('[data-explain-answer]').forEach(answer=>{answer.classList.remove('activity-guide-correct','activity-guide-revisit');answer.setAttribute('aria-pressed','false')});button.classList.add(correct?'activity-guide-correct':'activity-guide-revisit');button.setAttribute('aria-pressed','true');const feedback=box.querySelector('.activity-guide-feedback');feedback.hidden=false;feedback.textContent=(correct?'Correct. ':'Look again. ')+guide.feedback;});
 const saved=notes.get(id)||{prediction:'',observation:''};box.querySelectorAll('[data-explain-note]').forEach(field=>{field.value=saved[field.dataset.explainNote];field.oninput=()=>{saved[field.dataset.explainNote]=field.value;notes.set(id,saved)}});
 function scrollTo(target){if(!target)return;target.scrollIntoView({behavior:matchMedia('(prefers-reduced-motion: reduce)').matches?'instant':'smooth',block:'start'});target.setAttribute('tabindex','-1');target.focus({preventScroll:true})}
 box.querySelector('[data-explain-jump]').onclick=()=>scrollTo(document.querySelector('#experiment .study-source-list')||document.querySelector('#experiment'));
 box.querySelector('[data-explain-notes]')?.addEventListener('click',()=>scrollTo(document.querySelector('#study-reflection-section')));
 box.querySelector('[data-explain-source-check]')?.addEventListener('click',()=>{const check=document.querySelector('.study-extension');if(check){check.open=true;scrollTo(check)}});
 return true;
}