From 22233c5f923822f549214645bac913d28a105ef2 Mon Sep 17 00:00:00 2001 From: Ramon Date: Thu, 16 Jul 2026 09:14:15 +0200 Subject: [PATCH] fix: laat de minutenwijzer de urenwijzer verzetten (v0.3.68-beta) --- VERSION | 2 +- public/js/widgets/learning.js | 6 ++++-- test/widgets.test.js | 11 ++++++++++- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/VERSION b/VERSION index 018a402..42520d0 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.3.67-beta +0.3.68-beta diff --git a/public/js/widgets/learning.js b/public/js/widgets/learning.js index 78c99c0..c87d319 100644 --- a/public/js/widgets/learning.js +++ b/public/js/widgets/learning.js @@ -654,6 +654,8 @@ function mountFractions(root,init){ den.onchange=show.onchange=draw;learningShell(root,[field(T('fractionRows'),den),field(T('fractionLabels'),show)],stage);draw();return{getState:()=>({...S})}; } const clockTurnDelta=(next,previous)=>((next-previous+540)%360)-180; +const clockHourCrossing=(next,previous)=>{const delta=clockTurnDelta(next,previous);return delta>0&&nextprevious?-1:0}; +const clockStepHour=(hour,step,use24)=>use24?(hour+step+24)%24:((hour-1+step+12)%12)+1; const clock24Angle=(angle,delta)=>(angle+delta+720)%720; const clock24Hour=(angle,minute)=>((Math.round((angle-minute/2)/30)%24)+24)%24; function mountClock(root,init){ @@ -677,12 +679,12 @@ function mountClock(root,init){ if(interactive){ const updateAnswer=()=>{face.setAttribute('aria-label',time(S.h,S.m));const answer=stage.querySelector('.clock-live-answer');if(answer){answer.innerHTML='';answer.append(timeBlocks(S.h,S.m))}stage.querySelectorAll('.clock-period .tbtn').forEach(button=>{const active=+button.dataset.period===(S.h>=12?12:0);button.classList.toggle('active',active);button.setAttribute('aria-pressed',String(active))})}; const move=e=>{const r=face.getBoundingClientRect(),dx=e.clientX-r.left-r.width/2,dy=e.clientY-r.top-r.height/2,deg=(Math.atan2(dx,-dy)*180/Math.PI+360)%360; - if(face.dataset.hand==='minute'){const wanted=Math.round(deg/6)%60,allowed=minuteValues(),distance=v=>Math.min(Math.abs(v-wanted),60-Math.abs(v-wanted));S.m=allowed.reduce((best,v)=>distance(v)Math.min(Math.abs(v-wanted),60-Math.abs(v-wanted));S.m=allowed.reduce((best,v)=>distance(v){const angle=hour*30+minute/2,difference=Math.min(Math.abs(angle-face._dragAngle),720-Math.abs(angle-face._dragAngle));if(difference{const angle=(hour%12)*30+minute/2,difference=Math.min(Math.abs(angle-deg),360-Math.abs(angle-deg));if(difference{delete face.dataset.hand;delete face._dragAngle;delete face._lastPointerAngle}; - const start=(e,hand)=>{if(S.solved)return;e.preventDefault();e.stopPropagation();face.dataset.hand=hand;if(hand==='hour'&&uses24()){face._dragAngle=S.h*30+S.m/2;face._lastPointerAngle=null}face.setPointerCapture(e.pointerId);move(e)}; + const start=(e,hand)=>{if(S.solved)return;e.preventDefault();e.stopPropagation();face.dataset.hand=hand;if(hand==='minute')face._lastPointerAngle=null;else if(uses24()){face._dragAngle=S.h*30+S.m/2;face._lastPointerAngle=null}face.setPointerCapture(e.pointerId);move(e)}; hourHand.onpointerdown=e=>start(e,'hour');minuteHand.onpointerdown=e=>start(e,'minute'); face.onpointermove=e=>{if(face.hasPointerCapture(e.pointerId))move(e)}; face.onpointerup=e=>{move(e);face.releasePointerCapture(e.pointerId);clearDrag()}; diff --git a/test/widgets.test.js b/test/widgets.test.js index 8d80de8..2fb4d5a 100644 --- a/test/widgets.test.js +++ b/test/widgets.test.js @@ -102,6 +102,8 @@ test('analoge oefenklok is bedienbaar en houdt opdrachtacties buiten instellinge assert.ok(clockSource.includes('S.h=uses24()?0:12'), 'een 24-uursopdracht begint met een geldige invoerwaarde'); assert.ok(clockSource.includes("hourHand.onpointerdown=e=>start(e,'hour')")); assert.ok(clockSource.includes("minuteHand.onpointerdown=e=>start(e,'minute')")); + assert.ok(clockSource.includes("if(hand==='minute')face._lastPointerAngle=null"), 'de minutenwijzer volgt zijn draairichting over twaalf uur'); + assert.ok(clockSource.includes('if(step)S.h=clockStepHour(S.h,step,uses24())'), 'een volledige minutenomloop verzet de urenwijzer'); assert.ok(!clockSource.includes('face.onpointerdown='), 'de hele klok is geen sleepzone'); assert.doesNotMatch(css,/\.clock-hand::(?:before|after)/, 'geen extra sleepzones rond de wijzers'); for(const key of ['clockMorning','clockAfternoon','clockEvening','clockNight'])assert.equal((core.match(new RegExp(key+':','g'))||[]).length,2,key); @@ -110,9 +112,16 @@ test('analoge oefenklok is bedienbaar en houdt opdrachtacties buiten instellinge assert.match(css,/clock-set-answer\{[^}]*align-items:center[^}]*justify-content:center/); assert.match(css,/clock-period \.tbtn\.active\{[^}]*background:var\(--purple\)/); const context={}; - runInNewContext(source+';globalThis.__clock24={delta:clockTurnDelta,angle:clock24Angle,hour:clock24Hour}',context); + runInNewContext(source+';globalThis.__clock24={delta:clockTurnDelta,crossing:clockHourCrossing,step:clockStepHour,angle:clock24Angle,hour:clock24Hour}',context); assert.equal(context.__clock24.delta(2,358),4,'vooruit over twaalf uur blijft vooruit draaien'); assert.equal(context.__clock24.delta(358,2),-4,'achteruit over twaalf uur blijft achteruit draaien'); + assert.equal(context.__clock24.crossing(2,358),1,'de grote wijzer verhoogt het uur bij een voorwaartse omloop'); + assert.equal(context.__clock24.crossing(358,2),-1,'de grote wijzer verlaagt het uur bij een achterwaartse omloop'); + assert.equal(context.__clock24.crossing(30,20),0,'bewegen binnen hetzelfde uur verzet de kleine wijzer niet'); + assert.deepEqual([ + context.__clock24.step(11,1,false),context.__clock24.step(12,1,false),context.__clock24.step(1,-1,false), + context.__clock24.step(23,1,true),context.__clock24.step(0,-1,true), + ],[12,1,12,0,23]); assert.equal(context.__clock24.angle(719,2),1,'na 23 uur draait de klok door naar 0 uur'); assert.equal(context.__clock24.angle(1,-2),719,'achteruit vanaf 0 uur komt de klok bij 23 uur'); assert.deepEqual([0,11,12,23].map(hour=>context.__clock24.hour(hour*30,0)),[0,11,12,23]);