/* widget: Flitswoorden */ /* ========================================================= Flash words widget ==========================================================*/ function mountFlits(root, initState){ const S = { card:0, dur:2, idx:0, order:[], score:0, tries:0 }; if(initState){ S.card = initState.card ?? 0; S.dur = initState.dur || 2; S.score=+initState.score||0; S.tries=+initState.tries||0; } let flashTimer = null, assessed=false; root.innerHTML = `

• • •
`; const el = s => root.querySelector(s); const srcSel = el(".fl-src"), durSel = el(".fl-dur"), wordEl = el(".fl-word"), picEl = el(".fl-pic"), cntEl = el(".fl-cnt"), reflect=el(".fl-reflect"); function list(){ S.card = normWordSource(S.card); return wordSourceList(S.card); } function buildSrc(){ fillWordSourceSel(srcSel, S.card); durSel.innerHTML = ""; [0.5,1,2,3,5].forEach(d=>{ const o = document.createElement("option"); o.value = d; o.textContent = d+" "+T("flSec"); durSel.appendChild(o); }); durSel.value = S.dur; } function newRound(){ S.order = shuffle(list().map((_,i)=>i)); S.idx = 0; } function cur(){ return list()[S.order[S.idx]]; } function score(){ cntEl.textContent = `${T("word")} ${S.idx+1}/${S.order.length} · ${T("flScore").replace("{score}",S.score)}`; } function hide(ask=false){ wordEl.textContent = "• • •"; wordEl.classList.add("dim"); picEl.textContent = ""; reflect.hidden=!ask||assessed; } function flash(){ clearTimeout(flashTimer); assessed=false; wordEl.textContent = cur()[0]; wordEl.classList.remove("dim"); picEl.textContent = ""; reflect.hidden=true; score(); flashTimer = setTimeout(()=>hide(true), S.dur*1000); } function show(){ clearTimeout(flashTimer); wordEl.textContent = cur()[0]; wordEl.classList.remove("dim"); setPic(picEl, cur()[1]); reflect.hidden=assessed; } function assess(ok){ if(assessed)return;assessed=true; S.tries++; if(ok){S.score++;sndGood();confetti(el('.mt-card'));}else sndBad(); score(); reflect.hidden=true; } el(".fl-flash").addEventListener("click", flash); el(".fl-show").addEventListener("click", show); el(".fl-got").addEventListener("click",()=>assess(true)); el(".fl-again").addEventListener("click",()=>assess(false)); el(".fl-next").addEventListener("click", ()=>{ S.idx++; if(S.idx >= S.order.length) newRound(); flash(); }); srcSel.addEventListener("change", ()=>{ S.card = srcSel.value; newRound(); hide(); cntEl.textContent = ""; }); durSel.addEventListener("change", ()=>{ S.dur = +durSel.value; }); function labels(){ el(".fl-flash").textContent = T("flFlash"); el(".fl-show").textContent = T("flShow"); el(".fl-next").textContent = T("flNext"); el(".fl-mission").textContent=T("flMission"); el(".fl-question").textContent=T("flQuestion"); el(".fl-got").textContent=T("flGotIt"); el(".fl-again").textContent=T("flAgain"); buildSrc(); if(S.order.length)score(); } document.addEventListener("langchange", ()=>{ S.card=0; labels(); newRound(); hide(); }); document.addEventListener("wordschange", ()=>{ buildSrc(); newRound(); hide(); }); labels(); newRound(); return { getState: ()=>({card:S.card, dur:S.dur, score:S.score, tries:S.tries}) }; }