All checks were successful
dev - build & deploy naar test / build-and-deploy (push) Successful in 41s
74 lines
3.1 KiB
JavaScript
74 lines
3.1 KiB
JavaScript
/* widget: Namenkiezer */
|
|
/* =========================================================
|
|
Name picker widget
|
|
==========================================================*/
|
|
function mountNames(root, initState){
|
|
let used = new Set(initState?.used||[]), spinning = false;
|
|
root.innerHTML = `
|
|
<div class="np">
|
|
<div class="np-result">🎯</div>
|
|
<div class="np-progress" aria-live="polite"></div>
|
|
<textarea class="np-list" spellcheck="false"></textarea>
|
|
<div class="np-row">
|
|
<button class="tbtn np-pick"></button>
|
|
<button class="tbtn ghost np-reset"></button>
|
|
<label><input type="checkbox" class="np-nr"><span class="np-nrl"></span></label>
|
|
</div>
|
|
</div>`;
|
|
const ta = root.querySelector(".np-list"),
|
|
result = root.querySelector(".np-result"),
|
|
pickBtn = root.querySelector(".np-pick"),
|
|
nr = root.querySelector(".np-nr");
|
|
if(initState){
|
|
ta.value = initState.names || "";
|
|
nr.checked = !!initState.nr;
|
|
}
|
|
ta.addEventListener("input", ()=>{used.clear();updateProgress();});
|
|
ta.addEventListener("keydown", e=>e.stopPropagation());
|
|
function names(){ return ta.value.split("\n").map(s=>s.trim()).filter(Boolean); }
|
|
function updateProgress(){const all=names();used=new Set([...used].filter(name=>all.includes(name)));root.querySelector('.np-progress').textContent=T('namesProgress').replace('{used}',used.size).replace('{total}',all.length)}
|
|
pickBtn.addEventListener("click", ()=>{
|
|
if(spinning) return;
|
|
const all = names();
|
|
if(!all.length){ ta.focus(); return; }
|
|
let pool = nr.checked ? all.filter(n=>!used.has(n)) : all;
|
|
if(!pool.length){
|
|
result.textContent = T("namesDone");
|
|
updateProgress();
|
|
return;
|
|
}
|
|
spinning = true;
|
|
result.classList.remove("winner");
|
|
result.classList.add("spin");
|
|
const FUN = ["🌟","🎉","🦄","🚀","🐸","🎈","🍀","⚡"];
|
|
let n = 0;
|
|
const iv = setInterval(()=>{
|
|
result.textContent = all[Math.floor(Math.random()*all.length)];
|
|
tone(400+Math.random()*300, 0.03, 0, "square", 0.04);
|
|
if(++n >= 16){
|
|
clearInterval(iv);
|
|
const winner = pool[Math.floor(Math.random()*pool.length)];
|
|
const em = FUN[Math.floor(Math.random()*8)];
|
|
result.textContent = `${em} ${winner} ${em}`;
|
|
result.classList.remove("spin");
|
|
result.classList.add("winner");
|
|
confetti(result.parentElement);
|
|
if(nr.checked) used.add(winner);
|
|
updateProgress();
|
|
sndWin();
|
|
spinning = false;
|
|
}
|
|
}, 80);
|
|
});
|
|
root.querySelector('.np-reset').addEventListener('click',()=>{used.clear();result.textContent='🎯';result.classList.remove('winner','spin');updateProgress()});
|
|
function labels(){
|
|
ta.placeholder = T("namesPh");
|
|
pickBtn.textContent = T("namesPick");
|
|
root.querySelector('.np-reset').textContent=T('namesReset');
|
|
root.querySelector(".np-nrl").textContent = T("namesNoRep");
|
|
updateProgress();
|
|
}
|
|
document.addEventListener("langchange", labels);
|
|
labels();
|
|
return { getState: ()=>({names:ta.value, nr:nr.checked, used:[...used]}) };
|
|
}
|