/* widget: interactieve getallenlijn */ function mountNumberline(root, initState){ const S=Object.assign({level:1,yearGroup:null,managedLearningLevel:false,min:0,max:20,step:1,value:0,target:10,score:0,streak:0,solved:false},initState||{}); const rules=mathTaskRules(S.yearGroup,S.level); if(S.managedLearningLevel&&rules){S.min=rules.numberlineMin;S.max=rules.numberlineMax;S.step=rules.numberlineStep;S.value=S.min;S.target=S.min+S.step;} root.innerHTML=`
`; const q=s=>root.querySelector(s), minEl=q('.nlw-min'), maxEl=q('.nlw-max'), stepEl=q('.nlw-step'), line=q('.nlw-line'), valueEl=q('.nlw-value'), task=q('.nlw-task'), feedback=q('.nlw-feedback'),score=q('.nlw-score'); if(![...stepEl.options].some(o=>+o.value===S.step))stepEl.add(new Option(S.step,S.step)); minEl.value=S.min; maxEl.value=S.max; stepEl.value=S.step; [minEl,maxEl,stepEl].forEach(el=>el.disabled=!!S.managedLearningLevel); function normalize(){ let min=Math.max(-1000000,Math.min(999999,+minEl.value||0)); let max=Math.max(-999999,Math.min(1000000,+maxEl.value||20)); if(max<=min) max=min+1; const step=+stepEl.value||1; if((max-min)/step>60) max=min+60*step; S.min=min; S.max=max; S.step=step; if(S.valuemax||(S.value-min)%step!==0) S.value=min; if(S.targetmax||(S.target-min)%step!==0) S.target=min; minEl.value=min; maxEl.value=max; render(); } function render(){ line.innerHTML=""; for(let v=S.min;v<=S.max;v+=S.step){ const b=document.createElement('button'); b.type='button'; b.className='nlw-tick'; b.dataset.v=v; const mark=document.createElement('i'), label=document.createElement('span'); label.textContent=v; b.append(mark,label); b.classList.toggle('selected',v===S.value); b.addEventListener('click',()=>{S.value=v;if(!S.solved)feedback.textContent="";render();}); line.appendChild(b); } valueEl.textContent=S.value; task.textContent=T('numberlineTask').replace('{number}',S.target); score.textContent=T('numberlineScore').replace('{score}',S.score).replace('{streak}',S.streak); } function newTarget(){ const count=Math.floor((S.max-S.min)/S.step);let target=S.target; for(let tries=0;tries<8&&target===S.target;tries++)target=S.min+Math.floor(Math.random()*(count+1))*S.step; S.target=target;S.solved=false; feedback.textContent="";feedback.className='nlw-feedback';render(); } [minEl,maxEl,stepEl].forEach(el=>el.addEventListener('change',normalize)); q('.nlw-minus').addEventListener('click',()=>{S.value=Math.max(S.min,S.value-S.step);render();}); q('.nlw-plus').addEventListener('click',()=>{S.value=Math.min(S.max,S.value+S.step);render();}); q('.nlw-new').addEventListener('click',newTarget); q('.nlw-check').addEventListener('click',()=>{ const ok=S.value===S.target; feedback.textContent=T(ok?'numberlineGood':'numberlineTry'); feedback.className='nlw-feedback '+(ok?'ok':'bad'); if(ok){if(!S.solved){S.score++;S.streak++;S.solved=true;}sndGood();confetti(root);}else{S.streak=0;S.solved=false;sndBad();}render(); }); function labels(){ q('.nlw-settings-label').textContent=T('widgetSettings'); q('.nlw-from-label').textContent=T('numberlineFrom'); q('.nlw-to-label').textContent=T('numberlineTo'); q('.nlw-step-label').textContent=T('numberlineStep'); q('.nlw-new').textContent=T('numberlineNew'); q('.nlw-check').textContent=T('numberlineCheck'); render(); } root.classList.toggle("managed-learning-level",!!S.managedLearningLevel); document.addEventListener('langchange',labels); labels(); normalize(); return {getState:()=>({min:S.min,max:S.max,step:S.step,value:S.value,target:S.target,score:S.score,streak:S.streak,solved:S.solved})}; }