fix: libelle en dierenvormen herstellen, instellingen omdraaien (v0.4.81-beta)
All checks were successful
dev - build & deploy naar test / build-and-deploy (push) Successful in 35s
All checks were successful
dev - build & deploy naar test / build-and-deploy (push) Successful in 35s
- Libelle in de vijverplaat kreeg weer vier symmetrische vleugels - Zeepaardje in het koraalrif herbouwd van een onherkenbare buis naar een duidelijk zeepaardje, verplaatst zodat het niet meer over de clownvis valt - Nieuwe coloringLegPath()-vorm: giraffe en zebra hebben nu getapte, licht geknikte poten in plaats van rechte kokerpoten - Instellingenindeling omgedraaid: de kleurplaat (thema/plaat) is weer direct zichtbaar, kleurhulp/reset gaan achter het tandwiel - Letterblokken en rekenwidgets: niveauknoppen naar het tandwiel, het woord/thema blijft direct zichtbaar - Klok, geldrekenen, plaatswaardetabel, boom&blad/vogels/planten en topografie: spel/activiteit (en bij geld/plaatswaarde het bijpassende veld) staan weer in de vaste bovenbalk, niveau staat achter het tandwiel - Plaatswaardetabel toont nu ook in verkennen-stand een vaste bovenbalk (spel, getal, dobbelsteen) in plaats van alleen in bouwen-stand - Bugfix onderweg: niveauwissel in verkennen-stand van de plaatswaardetabel sprong per ongeluk naar bouwen-stand - nu blijft de stand behouden Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011YErxhic5w9K57zmt8Q1uS
This commit is contained in:
parent
d8610b010d
commit
84fd02d135
12 changed files with 161 additions and 113 deletions
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
||||||
0.4.80-beta
|
0.4.81-beta
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,11 @@
|
||||||
bestand zet nooit een `fill` op een kleurvak - dat zou van de vulling van de
|
bestand zet nooit een `fill` op een kleurvak - dat zou van de vulling van de
|
||||||
verfemmer winnen en de verf onzichtbaar maken. */
|
verfemmer winnen en de verf onzichtbaar maken. */
|
||||||
.coloring-app{--coloring-ink:#1c293d;--coloring-detail:#2d3e56;height:100%;min-height:0;display:flex;flex-direction:column;background:linear-gradient(180deg,color-mix(in srgb,var(--orange) 4%,var(--surface)),var(--surface));color:var(--ink)}
|
.coloring-app{--coloring-ink:#1c293d;--coloring-detail:#2d3e56;height:100%;min-height:0;display:flex;flex-direction:column;background:linear-gradient(180deg,color-mix(in srgb,var(--orange) 4%,var(--surface)),var(--surface));color:var(--ink)}
|
||||||
/* de veelgebruikte rij (kwast/emmer/gum, kleur, dikte) blijft altijd
|
/* de kleurplaat zelf moet snel te kiezen zijn: thema en plaat blijven dus
|
||||||
zichtbaar; thema, plaat, kleurhulp en reset - die je zelden aanpast -
|
altijd zichtbaar, samen met kwast/emmer/gum. Kleurhulp en reset - die je
|
||||||
zitten achter het ⚙-tandwiel (.edu-settings, zie teach.css) zodat ze niet
|
zelden aanpast - zitten achter het ⚙-tandwiel (.edu-settings, zie
|
||||||
permanent ruimte innemen naast wat je continu gebruikt */
|
teach.css) zodat ze niet permanent ruimte innemen. */
|
||||||
.coloring-tools{display:flex;align-items:center;gap:7px;flex-wrap:wrap;padding:9px 11px;border-bottom:1px solid color-mix(in srgb,var(--line) 72%,var(--orange));background:color-mix(in srgb,var(--surface) 96%,var(--orange))}
|
.coloring-tools,.coloring-choices{display:flex;align-items:center;gap:7px;flex-wrap:wrap;padding:9px 11px;border-bottom:1px solid color-mix(in srgb,var(--line) 72%,var(--orange));background:color-mix(in srgb,var(--surface) 96%,var(--orange))}
|
||||||
.coloring-choices{gap:8px}
|
|
||||||
.coloring-choices label{display:grid;grid-template-columns:auto minmax(120px,1fr);align-items:center;gap:6px;color:var(--muted);font-size:11px;font-weight:850}
|
.coloring-choices label{display:grid;grid-template-columns:auto minmax(120px,1fr);align-items:center;gap:6px;color:var(--muted);font-size:11px;font-weight:850}
|
||||||
.coloring-choices select{height:36px;max-width:230px;border:1px solid color-mix(in srgb,var(--line) 72%,var(--orange));border-radius:11px;padding:0 30px 0 10px;background:var(--surface);color:var(--ink);box-shadow:0 2px 8px rgba(30,50,90,.07);font:inherit;font-weight:750}
|
.coloring-choices select{height:36px;max-width:230px;border:1px solid color-mix(in srgb,var(--line) 72%,var(--orange));border-radius:11px;padding:0 30px 0 10px;background:var(--surface);color:var(--ink);box-shadow:0 2px 8px rgba(30,50,90,.07);font:inherit;font-weight:750}
|
||||||
.coloring-fit{padding:6px 10px;border:1px solid color-mix(in srgb,var(--line) 75%,var(--orange));border-radius:999px;background:color-mix(in srgb,var(--surface) 92%,var(--orange));color:var(--muted);box-shadow:0 2px 8px rgba(30,50,90,.06);font-size:11px;font-weight:800;white-space:nowrap}
|
.coloring-fit{padding:6px 10px;border:1px solid color-mix(in srgb,var(--line) 75%,var(--orange));border-radius:999px;background:color-mix(in srgb,var(--surface) 92%,var(--orange));color:var(--muted);box-shadow:0 2px 8px rgba(30,50,90,.06);font-size:11px;font-weight:800;white-space:nowrap}
|
||||||
|
|
@ -28,9 +27,9 @@
|
||||||
.coloring-size.on{outline:2px solid var(--orange);outline-offset:-2px}
|
.coloring-size.on{outline:2px solid var(--orange);outline-offset:-2px}
|
||||||
.coloring-custom{display:flex;align-items:center;gap:5px;color:var(--muted);font-size:10px;font-weight:800}
|
.coloring-custom{display:flex;align-items:center;gap:5px;color:var(--muted);font-size:10px;font-weight:800}
|
||||||
.coloring-custom input{width:36px;height:36px;padding:3px;border:1px solid var(--line);border-radius:10px;background:var(--surface);box-shadow:0 2px 7px rgba(30,50,90,.08);cursor:pointer}
|
.coloring-custom input{width:36px;height:36px;padding:3px;border:1px solid var(--line);border-radius:10px;background:var(--surface);box-shadow:0 2px 7px rgba(30,50,90,.08);cursor:pointer}
|
||||||
.coloring-choices .coloring-guide-btn{background:color-mix(in srgb,var(--teal) 14%,var(--surface));box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--teal) 20%,transparent)}
|
.coloring-guide-btn{width:36px;height:36px;border:0;border-radius:10px;font-size:18px;cursor:pointer;background:color-mix(in srgb,var(--teal) 14%,var(--surface));box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--teal) 20%,transparent)}
|
||||||
.coloring-choices .coloring-guide-btn.on{outline:2px solid var(--teal);outline-offset:-2px}
|
.coloring-guide-btn.on{outline:2px solid var(--teal);outline-offset:-2px}
|
||||||
.coloring-choices .coloring-reset{background:var(--red-soft);color:var(--red);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--red) 18%,transparent)}
|
.coloring-reset{width:36px;height:36px;border:0;border-radius:10px;font-size:18px;cursor:pointer;background:var(--red-soft);color:var(--red);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--red) 18%,transparent)}
|
||||||
.coloring-tools .coloring-done{width:auto;min-width:112px;margin-left:auto;padding:0 14px;color:#fff;box-shadow:0 4px 10px color-mix(in srgb,var(--orange) 24%,transparent);font-size:13px}
|
.coloring-tools .coloring-done{width:auto;min-width:112px;margin-left:auto;padding:0 14px;color:#fff;box-shadow:0 4px 10px color-mix(in srgb,var(--orange) 24%,transparent);font-size:13px}
|
||||||
.coloring-stage{flex:1;min-height:0;overflow:auto;display:grid;place-items:center;padding:18px;background:radial-gradient(circle at 12% 18%,color-mix(in srgb,var(--orange) 13%,transparent),transparent 31%),radial-gradient(circle at 88% 82%,color-mix(in srgb,var(--purple) 10%,transparent),transparent 34%),linear-gradient(145deg,var(--surface-2),color-mix(in srgb,var(--purple) 5%,var(--surface)))}
|
.coloring-stage{flex:1;min-height:0;overflow:auto;display:grid;place-items:center;padding:18px;background:radial-gradient(circle at 12% 18%,color-mix(in srgb,var(--orange) 13%,transparent),transparent 31%),radial-gradient(circle at 88% 82%,color-mix(in srgb,var(--purple) 10%,transparent),transparent 34%),linear-gradient(145deg,var(--surface-2),color-mix(in srgb,var(--purple) 5%,var(--surface)))}
|
||||||
/* het papier vangt alle aanwijzing op; binnen de SVG wordt meetkundig
|
/* het papier vangt alle aanwijzing op; binnen de SVG wordt meetkundig
|
||||||
|
|
@ -65,11 +64,11 @@
|
||||||
widget-venster (dat kan smal staan op een brede monitor), niet op de
|
widget-venster (dat kan smal staan op een brede monitor), niet op de
|
||||||
breedte van de hele browser - zie .widget-body{container-name:widget} */
|
breedte van de hele browser - zie .widget-body{container-name:widget} */
|
||||||
@container widget (max-width:620px){
|
@container widget (max-width:620px){
|
||||||
.coloring-tools{padding:6px;gap:4px}
|
.coloring-tools,.coloring-choices{padding:6px;gap:4px}
|
||||||
.coloring-choices label{grid-template-columns:1fr;gap:2px;flex:1;min-width:125px}
|
.coloring-choices label{grid-template-columns:1fr;gap:2px;flex:1;min-width:125px}
|
||||||
.coloring-choices select{width:100%;max-width:none;height:32px}
|
.coloring-choices select{width:100%;max-width:none;height:32px}
|
||||||
.coloring-fit{width:100%;text-align:center}
|
.coloring-fit{width:100%;text-align:center}
|
||||||
.coloring-tools button{width:32px;height:32px;font-size:16px}
|
.coloring-tools button,.coloring-guide-btn,.coloring-reset{width:32px;height:32px;font-size:16px}
|
||||||
.coloring-tool-buttons button{min-width:36px;width:36px;padding:0}.coloring-tool-label{display:none}
|
.coloring-tool-buttons button{min-width:36px;width:36px;padding:0}.coloring-tool-label{display:none}
|
||||||
.coloring-color i{width:18px;height:18px}
|
.coloring-color i{width:18px;height:18px}
|
||||||
.coloring-custom span{display:none}.coloring-custom input{width:32px;height:32px}
|
.coloring-custom span{display:none}.coloring-custom input{width:32px;height:32px}
|
||||||
|
|
@ -78,5 +77,5 @@
|
||||||
.coloring-paper{min-width:360px;border-radius:10px}
|
.coloring-paper{min-width:360px;border-radius:10px}
|
||||||
.coloring-hint{font-size:10px}
|
.coloring-hint{font-size:10px}
|
||||||
}
|
}
|
||||||
@media(pointer:coarse){.coloring-tools button,.coloring-custom input{min-width:40px;min-height:40px}.coloring-choices select{min-height:40px}}
|
@media(pointer:coarse){.coloring-tools button,.coloring-custom input,.coloring-guide-btn,.coloring-reset{min-width:40px;min-height:40px}.coloring-choices select{min-height:40px}}
|
||||||
@media(prefers-reduced-motion:reduce){.coloring-app *{scroll-behavior:auto!important;transition:none!important}}
|
@media(prefers-reduced-motion:reduce){.coloring-app *{scroll-behavior:auto!important;transition:none!important}}
|
||||||
|
|
|
||||||
|
|
@ -1559,6 +1559,10 @@ body.tb-left #rolePreviewBanner,body.tb-right #rolePreviewBanner{top:8px}
|
||||||
.managed-learning-level .clock-level-control,
|
.managed-learning-level .clock-level-control,
|
||||||
.managed-learning-level .place-level-control,
|
.managed-learning-level .place-level-control,
|
||||||
.managed-learning-level .money-level-control{display:none;}
|
.managed-learning-level .money-level-control{display:none;}
|
||||||
|
/* niveau kan ook als tandwielveld staan (gearField/field rond .lg-levels) -
|
||||||
|
dan moet het hele label (incl. "Niveau"-tekst) verdwijnen, niet alleen de
|
||||||
|
knoppenrij erin, anders blijft er een lege regel in het tandwielpaneel over */
|
||||||
|
.managed-learning-level .edu-controls label:has(.lg-levels){display:none;}
|
||||||
.board-learning-level{display:grid;grid-template-columns:auto auto minmax(130px,1fr);align-items:end;gap:8px;padding:8px 10px;border-bottom:1px solid var(--line);background:color-mix(in srgb,var(--accent) 7%,var(--surface));font-size:11px}
|
.board-learning-level{display:grid;grid-template-columns:auto auto minmax(130px,1fr);align-items:end;gap:8px;padding:8px 10px;border-bottom:1px solid var(--line);background:color-mix(in srgb,var(--accent) 7%,var(--surface));font-size:11px}
|
||||||
.board-learning-level label{display:grid;gap:3px;color:var(--muted);font-weight:800}
|
.board-learning-level label{display:grid;gap:3px;color:var(--muted);font-weight:800}
|
||||||
.board-learning-select{min-width:104px;border:1px solid var(--line);border-radius:8px;padding:6px 8px;background:var(--surface);color:var(--ink);font:inherit;font-weight:750}
|
.board-learning-select{min-width:104px;border:1px solid var(--line);border-radius:8px;padding:6px 8px;background:var(--surface);color:var(--ink);font:inherit;font-weight:750}
|
||||||
|
|
@ -1994,6 +1998,10 @@ body.dark .bd-stage{background:radial-gradient(circle at 50% 20%,var(--surface-2
|
||||||
.topo-province.inactive{opacity:.32}.topo-region[role=button],.topo-river[role=button],.world-continent[role=button]{cursor:pointer}.topo-region.picked .topo-province{fill:var(--red)!important}.topo-region.target .topo-province{fill:var(--green)!important}.topo-region:hover .topo-province,.topo-region:focus .topo-province{filter:brightness(.88) saturate(1.12)}.topo-region:focus-visible .topo-province{stroke:var(--navy);stroke-width:8}.topo-region-label{font-size:20px}
|
.topo-province.inactive{opacity:.32}.topo-region[role=button],.topo-river[role=button],.world-continent[role=button]{cursor:pointer}.topo-region.picked .topo-province{fill:var(--red)!important}.topo-region.target .topo-province{fill:var(--green)!important}.topo-region:hover .topo-province,.topo-region:focus .topo-province{filter:brightness(.88) saturate(1.12)}.topo-region:focus-visible .topo-province{stroke:var(--navy);stroke-width:8}.topo-region-label{font-size:20px}
|
||||||
.topo-river.inactive{opacity:.22}.topo-river-hit,.topo-river-line{fill:none;stroke-linecap:round;stroke-linejoin:round}.topo-river-hit{stroke:transparent;stroke-width:38;pointer-events:stroke}.topo-river-line{stroke:var(--river-color);stroke-width:10;pointer-events:none;transition:stroke .15s,stroke-width .15s}.topo-river:hover .topo-river-line,.topo-river:focus .topo-river-line{stroke-width:15}.topo-river:focus-visible .topo-river-line{stroke:var(--navy);stroke-width:18}.topo-river.picked .topo-river-line{stroke:var(--red)}.topo-river.target .topo-river-line{stroke:var(--green);stroke-width:16}.topo-river-label{fill:#18324e;paint-order:stroke;stroke:#fff;stroke-width:5px;stroke-linejoin:round;font-size:20px;font-style:italic;font-weight:950;text-anchor:middle;pointer-events:none}
|
.topo-river.inactive{opacity:.22}.topo-river-hit,.topo-river-line{fill:none;stroke-linecap:round;stroke-linejoin:round}.topo-river-hit{stroke:transparent;stroke-width:38;pointer-events:stroke}.topo-river-line{stroke:var(--river-color);stroke-width:10;pointer-events:none;transition:stroke .15s,stroke-width .15s}.topo-river:hover .topo-river-line,.topo-river:focus .topo-river-line{stroke-width:15}.topo-river:focus-visible .topo-river-line{stroke:var(--navy);stroke-width:18}.topo-river.picked .topo-river-line{stroke:var(--red)}.topo-river.target .topo-river-line{stroke:var(--green);stroke-width:16}.topo-river-label{fill:#18324e;paint-order:stroke;stroke:#fff;stroke-width:5px;stroke-linejoin:round;font-size:20px;font-style:italic;font-weight:950;text-anchor:middle;pointer-events:none}
|
||||||
.world-map-wrap{padding:12px}.world-map{width:100%;max-width:680px;max-height:none}.world-continent{stroke:#fff;stroke-width:1.4;stroke-linejoin:round;vector-effect:non-scaling-stroke;transition:filter .15s,opacity .15s,fill .15s}.world-continent.inactive{opacity:.28}.world-continent:hover,.world-continent:focus{filter:brightness(.88) saturate(1.12);outline:none}.world-continent:focus-visible{stroke:var(--navy);stroke-width:4}.world-continent.picked{fill:var(--red)!important}.world-continent.target{fill:var(--green)!important}.world-continent-label{fill:#18324e;paint-order:stroke;stroke:#fff;stroke-width:3px;stroke-linejoin:round;font-size:14px;font-weight:950;text-anchor:middle;pointer-events:none}
|
.world-map-wrap{padding:12px}.world-map{width:100%;max-width:680px;max-height:none}.world-continent{stroke:#fff;stroke-width:1.4;stroke-linejoin:round;vector-effect:non-scaling-stroke;transition:filter .15s,opacity .15s,fill .15s}.world-continent.inactive{opacity:.28}.world-continent:hover,.world-continent:focus{filter:brightness(.88) saturate(1.12);outline:none}.world-continent:focus-visible{stroke:var(--navy);stroke-width:4}.world-continent.picked{fill:var(--red)!important}.world-continent.target{fill:var(--green)!important}.world-continent-label{fill:#18324e;paint-order:stroke;stroke:#fff;stroke-width:3px;stroke-linejoin:round;font-size:14px;font-weight:950;text-anchor:middle;pointer-events:none}
|
||||||
|
/* een veelgebruikte keuze (spel/activiteit) die in de vaste bovenbalk van
|
||||||
|
klok/geld/plaatswaarde/wereld staat i.p.v. achter het tandwiel */
|
||||||
|
.top-field{display:flex;flex-direction:column;gap:2px;font-size:11px;font-weight:800;color:var(--muted)}
|
||||||
|
.top-field select{height:36px;border:1px solid var(--line);border-radius:9px;padding:0 8px;background:var(--surface);color:var(--ink);font:inherit;font-weight:750}
|
||||||
.topo-world-legend{width:100%;display:flex;flex-wrap:wrap;justify-content:center;gap:6px}.topo-world-legend span{display:flex;align-items:center;gap:5px;padding:5px 8px;border:1px solid color-mix(in srgb,var(--line) 75%,transparent);border-radius:999px;background:var(--surface);color:var(--ink);font-size:11px;font-weight:850}.topo-world-legend i{width:10px;height:10px;flex:none;border:1px solid rgba(24,50,78,.18);border-radius:50%}
|
.topo-world-legend{width:100%;display:flex;flex-wrap:wrap;justify-content:center;gap:6px}.topo-world-legend span{display:flex;align-items:center;gap:5px;padding:5px 8px;border:1px solid color-mix(in srgb,var(--line) 75%,transparent);border-radius:999px;background:var(--surface);color:var(--ink);font-size:11px;font-weight:850}.topo-world-legend i{width:10px;height:10px;flex:none;border:1px solid rgba(24,50,78,.18);border-radius:50%}
|
||||||
body.dark .world-fact{background:#1d3b2a;color:#a9e5b7}body.dark .world-fact .world-identity em{color:#a9e5b7}body.dark .topo-map-wrap{background:linear-gradient(155deg,#193446,#122c3e)}body.dark .topo-water{fill:#173145}body.dark .topo-label,body.dark .topo-city-label,body.dark .topo-river-label,body.dark .world-continent-label{fill:#f7fbff;stroke:#18324e}body.dark .topo-source{color:#a9cadb}
|
body.dark .world-fact{background:#1d3b2a;color:#a9e5b7}body.dark .world-fact .world-identity em{color:#a9e5b7}body.dark .topo-map-wrap{background:linear-gradient(155deg,#193446,#122c3e)}body.dark .topo-water{fill:#173145}body.dark .topo-label,body.dark .topo-city-label,body.dark .topo-river-label,body.dark .world-continent-label{fill:#f7fbff;stroke:#18324e}body.dark .topo-source{color:#a9cadb}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
/* version — shown until /api/version resolves (or if the fetch fails, e.g. offline).
|
/* version — shown until /api/version resolves (or if the fetch fails, e.g. offline).
|
||||||
Kept in sync by hand with the VERSION file at the repo root on every release. */
|
Kept in sync by hand with the VERSION file at the repo root on every release. */
|
||||||
const VERSION = "0.4.80-beta";
|
const VERSION = "0.4.81-beta";
|
||||||
/* Safari en oudere mobiele browsers behandelen 100vh/100% soms als de hoogte
|
/* Safari en oudere mobiele browsers behandelen 100vh/100% soms als de hoogte
|
||||||
achter hun adres- en navigatiebalk. visualViewport geeft de werkelijk
|
achter hun adres- en navigatiebalk. visualViewport geeft de werkelijk
|
||||||
zichtbare hoogte; de CSS gebruikt deze pixelwaarde als betrouwbare bron en
|
zichtbare hoogte; de CSS gebruikt deze pixelwaarde als betrouwbare bron en
|
||||||
|
|
@ -201,7 +201,7 @@ const I18N = {
|
||||||
avatarAcc_backpack:"Rugtas", avatarAcc_satchel:"Schoudertas", avatarAcc_wings:"Vleugels", avatarAcc_star:"Gouden ster", avatarAcc_medal:"Medaille",
|
avatarAcc_backpack:"Rugtas", avatarAcc_satchel:"Schoudertas", avatarAcc_wings:"Vleugels", avatarAcc_star:"Gouden ster", avatarAcc_medal:"Medaille",
|
||||||
avatarSave:"Opslaan", avatarSaved:"Personage opgeslagen ✓",
|
avatarSave:"Opslaan", avatarSaved:"Personage opgeslagen ✓",
|
||||||
clock24Hour:"24-uursklok",
|
clock24Hour:"24-uursklok",
|
||||||
widgetSettings:"Instellingen", clockWelcome:"Oefenen met de klok", clockWelcomeHint:"Kies bovenaan niveau 1, 2 of 3. Kies bij Instellingen hoe de opdracht wordt getoond en start daarna.", clockSetTitle:"Zet de wijzers op de goede tijd", clockReadTitle:"Bekijk de opdracht en maak de tijd", clockChooseTitle:"Kies het juiste tijdblok", clockYourTask:"Jouw opdracht", clockLinkHands:"Grote wijzer draait mee", clockTypeHint:"Voer de tijd in als UU:MM.", clockLevel1Hint:"Niveau 1: hele en halve uren", clockLevel2Hint:"Niveau 2: stappen van vijf minuten", clockLevel3Hint:"Niveau 3: alle minuten, met optioneel 24 uur en dagdelen", clockBuildHint:"Sleep vier cijfers naar de vakken en maak UU:MM.", clockDigitGhost:"?", clockDigit:"Cijfer {digit}", clockIncomplete:"Maak eerst de volledige tijd af.", clockCorrect:"Goed gedaan! Kies de volgende opdracht. 🌟", clockTryAgain:"Bijna! Probeer het nog een keer.", clockStartTask:"Start opdracht", clockNextTask:"Volgende opdracht", clockLevel:"Niveau", clockLevelHour:"Hele uren", clockLevelQuarter:"Kwartieren", clockLevelFive:"Vijf minuten", clockLevelMinute:"Iedere minuut", clockLearningStyle:"Opdracht tonen", clockStyleAnalogue:"Analoge klok", clockStyleDigital:"Grote digitale tijd", clockStyleWords:"In woorden", clockStyleBoth:"Klok, cijfers en woorden", clockDragHint:"Sleep de wijzers om de tijd te veranderen.", clockGame:"Spel", clockGameSet:"Klok zetten", clockGameRead:"Tijd aflezen", clockGameChoose:"Kies de tijd", clockStart:"Kies ‘Nieuwe opdracht’ om te beginnen", clockRead:"Welke tijd zie je? Stel je antwoord hieronder in.", clockChoose:"Welke digitale tijd hoort bij deze klok?", clockTry:"Nog niet. Het goede antwoord is {time}.", clockScore:"Score: {score} · reeks: {streak}", clockWordsHour:"{hour} uur", clockWordsQuarterPast:"kwart over {hour}", clockWordsHalf:"half {hour}", clockWordsQuarterTo:"kwart voor {hour}", clockWordsPast:"{minutes} over {hour}", clockWordsTo:"{minutes} voor {hour}", clockMorning:"in de ochtend", clockAfternoon:"in de middag", clockEvening:"in de avond", clockNight:"in de nacht", fractionRows:"Rijen", fractionLabels:"Breuken tonen", fractionHint:"Tik in een rij tot waar je de breuk wilt kleuren.", fractionSelected:"Gekozen breuk: {fraction}", fractionClear:"Leegmaken", clockTask:"Oefenopdracht", clockSet:"Zet de klok op {time}", clockHour:"Uur", clockMinute:"Minuten", placeNumber:"Getal", placeGame:"Spel", placeGameExplore:"Verkennen", placeGameBuild:"Bouwen", placeLevel:"Niveau", placeLevel1Hint:"Niveau 1: getallen tot 100 (T en E)", placeLevel2Hint:"Niveau 2: getallen tot 1000 (H, T en E)", placeLevel3Hint:"Niveau 3: getallen tot 1.000.000 (HD, TD, D, H, T en E)", placeBuildTitle:"Bouw het getal", placeYourTask:"Jouw opdracht", placeBuildHint:"Sleep de cijfers naar de vakken en bouw het getal.", placeDigitGhost:"?", placeIncomplete:"Maak eerst het hele getal af.", placeCorrect:"Goed gedaan! Kies de volgende opdracht. 🌟", placeTryAgain:"Bijna! Probeer het nog een keer.", placeNextTask:"Volgende opdracht", placeScore:"Score: {score} · reeks: {streak}", moneyMake:"Maak € {amount}", wordtypeSentence:"Zin", wordtypeHint:"Tik: blauw zelfstandig naamwoord · groen werkwoord · geel bijvoeglijk naamwoord", scheduleActivity:"activiteit…", scheduleEmpty:"Voeg de eerste activiteit toe.", scheduleCount:"{count} momenten op de planning", pollReset:"Opnieuw", pollQuestion:"Vraag", pollOptions:"Antwoorden (één per regel)", pollTotal:"{count} stemmen", moodTotal:"{count} kinderen hebben gekozen", moodVote:"Kies {face}", galleryFavorites:"Favorieten", galleryFavorite:"Favoriet maken", galleryEmpty:"Geen widgets gevonden.", gallerySearch:"Zoek widgets…", templateMath:"Rekenles", templateLanguage:"Taalles", templateDay:"Dagstart", exportBoard:"Exporteren", importBoard:"Importeren", importError:"Dit is geen geldig Teach-bordbestand.", widgetDuplicate:"Dupliceren", widgetLock:"Vastzetten", widgetUnlock:"Losmaken", widgetPreview:"Voorbeeld zonder bediening", undo:"Ongedaan maken", redo:"Opnieuw",
|
widgetSettings:"Instellingen", levelWidget:"Niveau", clockWelcome:"Oefenen met de klok", clockWelcomeHint:"Kies bovenaan niveau 1, 2 of 3. Kies bij Instellingen hoe de opdracht wordt getoond en start daarna.", clockSetTitle:"Zet de wijzers op de goede tijd", clockReadTitle:"Bekijk de opdracht en maak de tijd", clockChooseTitle:"Kies het juiste tijdblok", clockYourTask:"Jouw opdracht", clockLinkHands:"Grote wijzer draait mee", clockTypeHint:"Voer de tijd in als UU:MM.", clockLevel1Hint:"Niveau 1: hele en halve uren", clockLevel2Hint:"Niveau 2: stappen van vijf minuten", clockLevel3Hint:"Niveau 3: alle minuten, met optioneel 24 uur en dagdelen", clockBuildHint:"Sleep vier cijfers naar de vakken en maak UU:MM.", clockDigitGhost:"?", clockDigit:"Cijfer {digit}", clockIncomplete:"Maak eerst de volledige tijd af.", clockCorrect:"Goed gedaan! Kies de volgende opdracht. 🌟", clockTryAgain:"Bijna! Probeer het nog een keer.", clockStartTask:"Start opdracht", clockNextTask:"Volgende opdracht", clockLevel:"Niveau", clockLevelHour:"Hele uren", clockLevelQuarter:"Kwartieren", clockLevelFive:"Vijf minuten", clockLevelMinute:"Iedere minuut", clockLearningStyle:"Opdracht tonen", clockStyleAnalogue:"Analoge klok", clockStyleDigital:"Grote digitale tijd", clockStyleWords:"In woorden", clockStyleBoth:"Klok, cijfers en woorden", clockDragHint:"Sleep de wijzers om de tijd te veranderen.", clockGame:"Spel", clockGameSet:"Klok zetten", clockGameRead:"Tijd aflezen", clockGameChoose:"Kies de tijd", clockStart:"Kies ‘Nieuwe opdracht’ om te beginnen", clockRead:"Welke tijd zie je? Stel je antwoord hieronder in.", clockChoose:"Welke digitale tijd hoort bij deze klok?", clockTry:"Nog niet. Het goede antwoord is {time}.", clockScore:"Score: {score} · reeks: {streak}", clockWordsHour:"{hour} uur", clockWordsQuarterPast:"kwart over {hour}", clockWordsHalf:"half {hour}", clockWordsQuarterTo:"kwart voor {hour}", clockWordsPast:"{minutes} over {hour}", clockWordsTo:"{minutes} voor {hour}", clockMorning:"in de ochtend", clockAfternoon:"in de middag", clockEvening:"in de avond", clockNight:"in de nacht", fractionRows:"Rijen", fractionLabels:"Breuken tonen", fractionHint:"Tik in een rij tot waar je de breuk wilt kleuren.", fractionSelected:"Gekozen breuk: {fraction}", fractionClear:"Leegmaken", clockTask:"Oefenopdracht", clockSet:"Zet de klok op {time}", clockHour:"Uur", clockMinute:"Minuten", placeNumber:"Getal", placeGame:"Spel", placeGameExplore:"Verkennen", placeGameBuild:"Bouwen", placeLevel:"Niveau", placeLevel1Hint:"Niveau 1: getallen tot 100 (T en E)", placeLevel2Hint:"Niveau 2: getallen tot 1000 (H, T en E)", placeLevel3Hint:"Niveau 3: getallen tot 1.000.000 (HD, TD, D, H, T en E)", placeBuildTitle:"Bouw het getal", placeYourTask:"Jouw opdracht", placeBuildHint:"Sleep de cijfers naar de vakken en bouw het getal.", placeDigitGhost:"?", placeIncomplete:"Maak eerst het hele getal af.", placeCorrect:"Goed gedaan! Kies de volgende opdracht. 🌟", placeTryAgain:"Bijna! Probeer het nog een keer.", placeNextTask:"Volgende opdracht", placeScore:"Score: {score} · reeks: {streak}", moneyMake:"Maak € {amount}", wordtypeSentence:"Zin", wordtypeHint:"Tik: blauw zelfstandig naamwoord · groen werkwoord · geel bijvoeglijk naamwoord", scheduleActivity:"activiteit…", scheduleEmpty:"Voeg de eerste activiteit toe.", scheduleCount:"{count} momenten op de planning", pollReset:"Opnieuw", pollQuestion:"Vraag", pollOptions:"Antwoorden (één per regel)", pollTotal:"{count} stemmen", moodTotal:"{count} kinderen hebben gekozen", moodVote:"Kies {face}", galleryFavorites:"Favorieten", galleryFavorite:"Favoriet maken", galleryEmpty:"Geen widgets gevonden.", gallerySearch:"Zoek widgets…", templateMath:"Rekenles", templateLanguage:"Taalles", templateDay:"Dagstart", exportBoard:"Exporteren", importBoard:"Importeren", importError:"Dit is geen geldig Teach-bordbestand.", widgetDuplicate:"Dupliceren", widgetLock:"Vastzetten", widgetUnlock:"Losmaken", widgetPreview:"Voorbeeld zonder bediening", undo:"Ongedaan maken", redo:"Opnieuw",
|
||||||
wg_sentence:"Zinsbouwer", wg_sentence_d:"Bouw zinnen met kleurgecodeerde zinsdelen en voeg eigen woorden toe.",
|
wg_sentence:"Zinsbouwer", wg_sentence_d:"Bouw zinnen met kleurgecodeerde zinsdelen en voeg eigen woorden toe.",
|
||||||
sentence_who:"Wie?", sentence_does:"Doet wat?", sentence_what:"Wat of waar?", sentenceHint:"Kies woorden om een zin te maken…",
|
sentence_who:"Wie?", sentence_does:"Doet wat?", sentence_what:"Wat of waar?", sentenceHint:"Kies woorden om een zin te maken…",
|
||||||
sentenceAdd:"eigen woord of zinsdeel…", sentenceClear:"Wissen", sentenceSpeak:"🔊 Lees voor", sentenceRemove:"Verwijder woord", sentenceSurprise:"✨ Verrassingszin",
|
sentenceAdd:"eigen woord of zinsdeel…", sentenceClear:"Wissen", sentenceSpeak:"🔊 Lees voor", sentenceRemove:"Verwijder woord", sentenceSurprise:"✨ Verrassingszin",
|
||||||
|
|
@ -634,7 +634,7 @@ const I18N = {
|
||||||
avatarAcc_backpack:"Backpack", avatarAcc_satchel:"Satchel", avatarAcc_wings:"Wings", avatarAcc_star:"Golden star", avatarAcc_medal:"Medal",
|
avatarAcc_backpack:"Backpack", avatarAcc_satchel:"Satchel", avatarAcc_wings:"Wings", avatarAcc_star:"Golden star", avatarAcc_medal:"Medal",
|
||||||
avatarSave:"Save", avatarSaved:"Character saved ✓",
|
avatarSave:"Save", avatarSaved:"Character saved ✓",
|
||||||
clock24Hour:"24-hour clock",
|
clock24Hour:"24-hour clock",
|
||||||
widgetSettings:"Settings", clockWelcome:"Practise telling time", clockWelcomeHint:"Choose level 1, 2 or 3 at the top. In Settings, choose how the task is shown, then start.", clockSetTitle:"Move the hands to the correct time", clockReadTitle:"View the task and make the time", clockChooseTitle:"Choose the correct time block", clockYourTask:"Your task", clockLinkHands:"Move the minute hand along", clockTypeHint:"Enter the time as HH:MM.", clockLevel1Hint:"Level 1: whole and half hours", clockLevel2Hint:"Level 2: five-minute steps", clockLevel3Hint:"Level 3: every minute, with optional 24-hour time and day parts", clockBuildHint:"Drag four digits into the slots to make HH:MM.", clockDigitGhost:"?", clockDigit:"Digit {digit}", clockIncomplete:"Complete the full time first.", clockCorrect:"Well done! Choose the next task. 🌟", clockTryAgain:"Almost! Try again.", clockStartTask:"Start task", clockNextTask:"Next task", clockLevel:"Level", clockLevelHour:"Whole hours", clockLevelQuarter:"Quarter hours", clockLevelFive:"Five minutes", clockLevelMinute:"Every minute", clockLearningStyle:"Show task as", clockStyleAnalogue:"Analogue clock", clockStyleDigital:"Large digital time", clockStyleWords:"In words", clockStyleBoth:"Clock, digits and words", clockDragHint:"Drag the hands to change the time.", clockGame:"Game", clockGameSet:"Set the clock", clockGameRead:"Read the time", clockGameChoose:"Choose the time", clockStart:"Choose ‘New task’ to begin", clockRead:"What time is it? Set your answer below.", clockChoose:"Which digital time matches this clock?", clockTry:"Not yet. The correct answer is {time}.", clockScore:"Score: {score} · streak: {streak}", clockWordsHour:"{hour} o'clock", clockWordsQuarterPast:"quarter past {hour}", clockWordsHalf:"half past {hour}", clockWordsQuarterTo:"quarter to {hour}", clockWordsPast:"{minutes} past {hour}", clockWordsTo:"{minutes} to {hour}", clockMorning:"in the morning", clockAfternoon:"in the afternoon", clockEvening:"in the evening", clockNight:"at night", fractionRows:"Rows", fractionLabels:"Show fractions", fractionHint:"Tap a row up to the part you want to colour.", fractionSelected:"Selected fraction: {fraction}", fractionClear:"Clear", clockTask:"Practice task", clockSet:"Set the clock to {time}", clockHour:"Hour", clockMinute:"Minutes", placeNumber:"Number", placeGame:"Game", placeGameExplore:"Explore", placeGameBuild:"Build", placeLevel:"Level", placeLevel1Hint:"Level 1: numbers up to 100 (T and E)", placeLevel2Hint:"Level 2: numbers up to 1000 (H, T and E)", placeLevel3Hint:"Level 3: numbers up to 1,000,000 (HD, TD, D, H, T and E)", placeBuildTitle:"Build the number", placeYourTask:"Your task", placeBuildHint:"Drag the digits into the slots to build the number.", placeDigitGhost:"?", placeIncomplete:"Complete the whole number first.", placeCorrect:"Well done! Choose the next task. 🌟", placeTryAgain:"Almost! Try again.", placeNextTask:"Next task", placeScore:"Score: {score} · streak: {streak}", moneyMake:"Make € {amount}", wordtypeSentence:"Sentence", wordtypeHint:"Tap: blue noun · green verb · yellow adjective", scheduleActivity:"activity…", scheduleEmpty:"Add the first activity.", scheduleCount:"{count} moments in the schedule", pollReset:"Reset", pollQuestion:"Question", pollOptions:"Answers (one per line)", pollTotal:"{count} votes", moodTotal:"{count} children have chosen", moodVote:"Choose {face}", galleryFavorites:"Favourites", galleryFavorite:"Add favourite", galleryEmpty:"No widgets found.", gallerySearch:"Search widgets…", templateMath:"Maths lesson", templateLanguage:"Language lesson", templateDay:"Day start", exportBoard:"Export", importBoard:"Import", importError:"This is not a valid Teach board file.", widgetDuplicate:"Duplicate", widgetLock:"Lock", widgetUnlock:"Unlock", widgetPreview:"Preview without controls", undo:"Undo", redo:"Redo",
|
widgetSettings:"Settings", levelWidget:"Level", clockWelcome:"Practise telling time", clockWelcomeHint:"Choose level 1, 2 or 3 at the top. In Settings, choose how the task is shown, then start.", clockSetTitle:"Move the hands to the correct time", clockReadTitle:"View the task and make the time", clockChooseTitle:"Choose the correct time block", clockYourTask:"Your task", clockLinkHands:"Move the minute hand along", clockTypeHint:"Enter the time as HH:MM.", clockLevel1Hint:"Level 1: whole and half hours", clockLevel2Hint:"Level 2: five-minute steps", clockLevel3Hint:"Level 3: every minute, with optional 24-hour time and day parts", clockBuildHint:"Drag four digits into the slots to make HH:MM.", clockDigitGhost:"?", clockDigit:"Digit {digit}", clockIncomplete:"Complete the full time first.", clockCorrect:"Well done! Choose the next task. 🌟", clockTryAgain:"Almost! Try again.", clockStartTask:"Start task", clockNextTask:"Next task", clockLevel:"Level", clockLevelHour:"Whole hours", clockLevelQuarter:"Quarter hours", clockLevelFive:"Five minutes", clockLevelMinute:"Every minute", clockLearningStyle:"Show task as", clockStyleAnalogue:"Analogue clock", clockStyleDigital:"Large digital time", clockStyleWords:"In words", clockStyleBoth:"Clock, digits and words", clockDragHint:"Drag the hands to change the time.", clockGame:"Game", clockGameSet:"Set the clock", clockGameRead:"Read the time", clockGameChoose:"Choose the time", clockStart:"Choose ‘New task’ to begin", clockRead:"What time is it? Set your answer below.", clockChoose:"Which digital time matches this clock?", clockTry:"Not yet. The correct answer is {time}.", clockScore:"Score: {score} · streak: {streak}", clockWordsHour:"{hour} o'clock", clockWordsQuarterPast:"quarter past {hour}", clockWordsHalf:"half past {hour}", clockWordsQuarterTo:"quarter to {hour}", clockWordsPast:"{minutes} past {hour}", clockWordsTo:"{minutes} to {hour}", clockMorning:"in the morning", clockAfternoon:"in the afternoon", clockEvening:"in the evening", clockNight:"at night", fractionRows:"Rows", fractionLabels:"Show fractions", fractionHint:"Tap a row up to the part you want to colour.", fractionSelected:"Selected fraction: {fraction}", fractionClear:"Clear", clockTask:"Practice task", clockSet:"Set the clock to {time}", clockHour:"Hour", clockMinute:"Minutes", placeNumber:"Number", placeGame:"Game", placeGameExplore:"Explore", placeGameBuild:"Build", placeLevel:"Level", placeLevel1Hint:"Level 1: numbers up to 100 (T and E)", placeLevel2Hint:"Level 2: numbers up to 1000 (H, T and E)", placeLevel3Hint:"Level 3: numbers up to 1,000,000 (HD, TD, D, H, T and E)", placeBuildTitle:"Build the number", placeYourTask:"Your task", placeBuildHint:"Drag the digits into the slots to build the number.", placeDigitGhost:"?", placeIncomplete:"Complete the whole number first.", placeCorrect:"Well done! Choose the next task. 🌟", placeTryAgain:"Almost! Try again.", placeNextTask:"Next task", placeScore:"Score: {score} · streak: {streak}", moneyMake:"Make € {amount}", wordtypeSentence:"Sentence", wordtypeHint:"Tap: blue noun · green verb · yellow adjective", scheduleActivity:"activity…", scheduleEmpty:"Add the first activity.", scheduleCount:"{count} moments in the schedule", pollReset:"Reset", pollQuestion:"Question", pollOptions:"Answers (one per line)", pollTotal:"{count} votes", moodTotal:"{count} children have chosen", moodVote:"Choose {face}", galleryFavorites:"Favourites", galleryFavorite:"Add favourite", galleryEmpty:"No widgets found.", gallerySearch:"Search widgets…", templateMath:"Maths lesson", templateLanguage:"Language lesson", templateDay:"Day start", exportBoard:"Export", importBoard:"Import", importError:"This is not a valid Teach board file.", widgetDuplicate:"Duplicate", widgetLock:"Lock", widgetUnlock:"Unlock", widgetPreview:"Preview without controls", undo:"Undo", redo:"Redo",
|
||||||
wg_sentence:"Sentence builder", wg_sentence_d:"Build sentences with colour-coded parts and add your own words.",
|
wg_sentence:"Sentence builder", wg_sentence_d:"Build sentences with colour-coded parts and add your own words.",
|
||||||
sentence_who:"Who?", sentence_does:"Does what?", sentence_what:"What or where?", sentenceHint:"Choose words to build a sentence…",
|
sentence_who:"Who?", sentence_does:"Does what?", sentence_what:"What or where?", sentenceHint:"Choose words to build a sentence…",
|
||||||
sentenceAdd:"your own word or phrase…", sentenceClear:"Clear", sentenceSpeak:"🔊 Read aloud", sentenceRemove:"Remove word", sentenceSurprise:"✨ Surprise sentence",
|
sentenceAdd:"your own word or phrase…", sentenceClear:"Clear", sentenceSpeak:"🔊 Read aloud", sentenceRemove:"Remove word", sentenceSurprise:"✨ Surprise sentence",
|
||||||
|
|
|
||||||
|
|
@ -238,14 +238,18 @@ function plateEcosystem(){
|
||||||
coloringFlat("frog-belly","M 266 496 C 282 526 302 540 334 542 C 366 540 388 526 402 496 C 400 532 372 548 334 548 C 296 548 268 532 266 496 Z","#f7c948"),2)+
|
coloringFlat("frog-belly","M 266 496 C 282 526 302 540 334 542 C 366 540 388 526 402 496 C 400 532 372 548 334 548 C 296 548 268 532 266 496 Z","#f7c948"),2)+
|
||||||
coloringLine("M 306 448 C 320 458 348 458 362 448",2)+
|
coloringLine("M 306 448 C 320 458 348 458 362 448",2)+
|
||||||
coloringLine("M 274 480 C 296 490 372 490 394 480 M 260 524 C 284 536 384 536 408 524",3))+
|
coloringLine("M 274 480 C 296 490 372 490 394 480 M 260 524 C 284 536 384 536 408 524",3))+
|
||||||
|
/* vier vleugels symmetrisch aan weerszijden van het lijf in plaats van
|
||||||
|
twee dunne slierten aan één kant - dat las niet als vleugels */
|
||||||
coloringGroup("dragonfly",
|
coloringGroup("dragonfly",
|
||||||
coloringFlat("dragonfly-wing-upper","M 596 236 C 636 214 690 212 720 226 C 690 250 638 256 600 248 Z","#2fb7a8")+
|
coloringFlat("dragonfly-wing-front-right",coloringPetalPath(600,250,-15,95,26),"#2fb7a8")+
|
||||||
coloringFlat("dragonfly-wing-lower","M 596 252 C 636 268 686 276 714 290 C 682 302 632 292 598 268 Z","#2fb7a8")+
|
coloringFlat("dragonfly-wing-back-right",coloringPetalPath(600,250,25,85,24),"#2fb7a8")+
|
||||||
coloringContour("dragonfly-body","M 566 232 C 578 226 592 226 600 234 C 602 262 598 296 588 322 C 578 300 570 266 566 232 Z","#7557c8")+
|
coloringFlat("dragonfly-wing-front-left",coloringPetalPath(600,250,195,95,26),"#2fb7a8")+
|
||||||
coloringCircle("dragonfly-head",582,220,20,"#7557c8","coloring-contour")+
|
coloringFlat("dragonfly-wing-back-left",coloringPetalPath(600,250,155,85,24),"#2fb7a8")+
|
||||||
|
coloringContour("dragonfly-body","M 588 232 C 588 224 596 220 600 220 C 604 220 612 224 612 232 C 616 260 614 300 606 336 C 604 342 596 342 594 336 C 586 300 584 260 588 232 Z","#7557c8")+
|
||||||
|
coloringCircle("dragonfly-head",600,200,19,"#7557c8","coloring-contour")+
|
||||||
coloringGroup("dragonfly-detail",
|
coloringGroup("dragonfly-detail",
|
||||||
coloringDot(574,214,5)+coloringDot(590,214,5)+
|
coloringDot(592,196,5)+coloringDot(608,196,5)+
|
||||||
coloringLine("M 572 254 L 596 254 M 574 274 L 594 274 M 578 294 L 592 294",2)))+
|
coloringLine("M 590 250 L 610 250 M 592 275 L 608 275 M 594 300 L 606 300",2)))+
|
||||||
coloringGroup("front-reeds",
|
coloringGroup("front-reeds",
|
||||||
coloringLine("M 160 590 C 168 556 172 534 170 512 M 190 594 C 200 562 204 542 204 520 M 640 588 C 648 556 652 534 650 514",2),2)
|
coloringLine("M 160 590 C 168 556 172 534 170 512 M 190 594 C 200 562 204 542 204 520 M 640 588 C 648 556 652 534 650 514",2),2)
|
||||||
);
|
);
|
||||||
|
|
@ -272,15 +276,16 @@ function plateSavanna(){
|
||||||
coloringLine("M 166 232 C 162 288 164 344 172 392 M 186 232 C 182 288 186 344 194 392",2))+
|
coloringLine("M 166 232 C 162 288 164 344 172 392 M 186 232 C 182 288 186 344 194 392",2))+
|
||||||
coloringLine("M 80 206 C 120 202 240 202 280 206 M 100 154 C 130 148 200 148 240 154",3))+
|
coloringLine("M 80 206 C 120 202 240 202 280 206 M 100 154 C 130 148 200 148 240 154",3))+
|
||||||
coloringGroup("giraffe",
|
coloringGroup("giraffe",
|
||||||
/* vier poten met een knik en een hoef; de nek loopt breed uit in de
|
/* getapte poten met een lichte knik ipv rechte kokers, en een hoef
|
||||||
|
die uit de poot zelf voortkomt; de nek loopt breed uit in de
|
||||||
schouder in plaats van als losse balk op het lichaam te staan */
|
schouder in plaats van als losse balk op het lichaam te staan */
|
||||||
coloringFlat("giraffe-hind-leg-far","M 648 462 L 678 462 L 674 516 L 686 566 L 658 570 L 646 516 Z","#f7c948")+
|
coloringFlat("giraffe-hind-leg-far",coloringLegPath(663,462,566,30,15,26,5),"#f7c948")+
|
||||||
coloringFlat("giraffe-fore-leg-far","M 540 458 L 568 458 L 568 514 L 576 566 L 548 570 L 540 514 Z","#f7c948")+
|
coloringFlat("giraffe-fore-leg-far",coloringLegPath(554,458,566,28,14,24,-4),"#f7c948")+
|
||||||
coloringFlat("giraffe-tail","M 686 424 C 706 442 718 466 720 492 C 706 488 692 472 682 450 Z","#f7c948")+
|
coloringFlat("giraffe-tail","M 686 424 C 706 442 718 466 720 492 C 706 488 692 472 682 450 Z","#f7c948")+
|
||||||
coloringContour("giraffe-body","M 502 448 C 500 402 540 378 596 378 C 654 378 692 402 694 448 C 696 486 652 502 594 502 C 536 502 504 486 502 448 Z","#f7c948")+
|
coloringContour("giraffe-body","M 502 448 C 500 402 540 378 596 378 C 654 378 692 402 694 448 C 696 486 652 502 594 502 C 536 502 504 486 502 448 Z","#f7c948")+
|
||||||
coloringContour("giraffe-neck","M 496 424 C 480 356 474 280 480 200 L 530 192 C 532 272 542 352 558 416 C 538 432 512 434 496 424 Z","#f7c948")+
|
coloringContour("giraffe-neck","M 496 424 C 480 356 474 280 480 200 L 530 192 C 532 272 542 352 558 416 C 538 432 512 434 496 424 Z","#f7c948")+
|
||||||
coloringFlat("giraffe-hind-leg-near","M 612 468 L 646 468 L 642 522 L 654 576 L 620 580 L 608 522 Z","#f7c948")+
|
coloringFlat("giraffe-hind-leg-near",coloringLegPath(629,468,578,32,16,28,7),"#f7c948")+
|
||||||
coloringFlat("giraffe-fore-leg-near","M 506 464 L 540 464 L 538 520 L 546 576 L 512 580 L 504 520 Z","#f7c948")+
|
coloringFlat("giraffe-fore-leg-near",coloringLegPath(523,464,578,32,15,28,-6),"#f7c948")+
|
||||||
coloringContour("giraffe-head","M 476 204 C 460 176 474 146 504 140 C 536 134 560 154 562 182 C 546 206 506 216 476 204 Z","#f7c948")+
|
coloringContour("giraffe-head","M 476 204 C 460 176 474 146 504 140 C 536 134 560 154 562 182 C 546 206 506 216 476 204 Z","#f7c948")+
|
||||||
coloringFlat("giraffe-muzzle","M 478 174 C 452 166 432 176 426 194 C 442 210 466 214 486 206 Z","#f2b38f")+
|
coloringFlat("giraffe-muzzle","M 478 174 C 452 166 432 176 426 194 C 442 210 466 214 486 206 Z","#f2b38f")+
|
||||||
coloringGroup("giraffe-detail",
|
coloringGroup("giraffe-detail",
|
||||||
|
|
@ -305,13 +310,13 @@ function plateSavanna(){
|
||||||
coloringLine("M 434 190 C 438 200 446 206 456 208 M 682 450 C 692 462 700 476 704 490",2)+
|
coloringLine("M 434 190 C 438 200 446 206 456 208 M 682 450 C 692 462 700 476 704 490",2)+
|
||||||
coloringLine("M 512 444 C 548 458 630 462 684 452 M 494 256 C 510 262 526 270 536 276 M 548 520 C 560 526 574 526 584 522",3))+
|
coloringLine("M 512 444 C 548 458 630 462 684 452 M 494 256 C 510 262 526 270 536 276 M 548 520 C 560 526 574 526 584 522",3))+
|
||||||
coloringGroup("zebra",
|
coloringGroup("zebra",
|
||||||
coloringFlat("zebra-hind-leg-far","M 352 458 L 380 458 L 376 508 L 386 556 L 360 560 L 350 508 Z","#ffffff")+
|
coloringFlat("zebra-hind-leg-far",coloringLegPath(366,458,560,28,14,24,5),"#ffffff")+
|
||||||
coloringFlat("zebra-fore-leg-far","M 254 456 L 280 456 L 280 506 L 286 556 L 260 560 L 254 506 Z","#ffffff")+
|
coloringFlat("zebra-fore-leg-far",coloringLegPath(267,456,560,26,13,22,-4),"#ffffff")+
|
||||||
coloringFlat("zebra-tail","M 384 428 C 404 442 416 462 420 486 C 406 482 392 468 382 448 Z","#ffffff")+
|
coloringFlat("zebra-tail","M 384 428 C 404 442 416 462 420 486 C 406 482 392 468 382 448 Z","#ffffff")+
|
||||||
coloringContour("zebra-body","M 222 446 C 220 404 258 380 306 380 C 356 380 392 404 394 446 C 396 480 356 496 306 496 C 254 496 224 480 222 446 Z","#ffffff")+
|
coloringContour("zebra-body","M 222 446 C 220 404 258 380 306 380 C 356 380 392 404 394 446 C 396 480 356 496 306 496 C 254 496 224 480 222 446 Z","#ffffff")+
|
||||||
coloringContour("zebra-neck","M 222 428 C 212 388 202 352 196 322 L 248 306 C 260 348 272 388 284 424 C 264 442 240 444 222 428 Z","#ffffff")+
|
coloringContour("zebra-neck","M 222 428 C 212 388 202 352 196 322 L 248 306 C 260 348 272 388 284 424 C 264 442 240 444 222 428 Z","#ffffff")+
|
||||||
coloringFlat("zebra-hind-leg-near","M 322 464 L 352 464 L 348 514 L 358 566 L 328 570 L 318 514 Z","#ffffff")+
|
coloringFlat("zebra-hind-leg-near",coloringLegPath(337,464,570,30,15,26,6),"#ffffff")+
|
||||||
coloringFlat("zebra-fore-leg-near","M 224 462 L 254 462 L 252 512 L 258 566 L 228 570 L 222 512 Z","#ffffff")+
|
coloringFlat("zebra-fore-leg-near",coloringLegPath(239,462,570,30,14,26,-5),"#ffffff")+
|
||||||
coloringContour("zebra-head","M 186 324 C 168 298 182 268 210 262 C 240 256 264 276 266 304 C 248 326 214 336 186 324 Z","#ffffff")+
|
coloringContour("zebra-head","M 186 324 C 168 298 182 268 210 262 C 240 256 264 276 266 304 C 248 326 214 336 186 324 Z","#ffffff")+
|
||||||
coloringFlat("zebra-muzzle","M 188 292 C 164 284 144 294 138 312 C 154 328 176 332 196 324 Z","#26344a")+
|
coloringFlat("zebra-muzzle","M 188 292 C 164 284 144 294 138 312 C 154 328 176 332 196 324 Z","#26344a")+
|
||||||
coloringGroup("zebra-stripes",
|
coloringGroup("zebra-stripes",
|
||||||
|
|
|
||||||
|
|
@ -190,18 +190,19 @@ function plateReef(){
|
||||||
coloringDot(498,278,6),2)+
|
coloringDot(498,278,6),2)+
|
||||||
coloringLine("M 520 250 C 532 270 536 288 536 298 C 536 310 532 328 520 346",2)+
|
coloringLine("M 520 250 C 532 270 536 288 536 298 C 536 310 532 328 520 346",2)+
|
||||||
coloringLine("M 318 292 C 336 284 352 280 368 278 M 318 308 C 336 314 352 318 368 320",3))+
|
coloringLine("M 318 292 C 336 284 352 280 368 278 M 318 308 C 336 314 352 318 368 320",3))+
|
||||||
|
/* paardenkop met snuit, een gewelfde rug en een duidelijk gekrulde staart
|
||||||
|
- los van elkaar getekend zodat elk onderdeel scherp herkenbaar blijft,
|
||||||
|
in plaats van één doorlopend buis-silhouet dat als worm of blob las */
|
||||||
coloringGroup("seahorse",
|
coloringGroup("seahorse",
|
||||||
coloringFlat("seahorse-fin","M 646 264 C 668 256 688 262 696 278 C 680 292 656 292 642 282 Z","#f7c948")+
|
coloringContour("seahorse-head","M 731 190 C 731 168 715 152 693 152 C 673 152 659 166 657 186 C 637 182 619 190 613 206 C 627 220 649 222 665 214 C 671 226 683 234 697 234 C 717 234 733 218 733 198 C 733 195 732 192 731 190 Z","#f7c948")+
|
||||||
/* stevige romp met een aparte gekrulde staart: het smalle buisje dat er
|
coloringContour("seahorse-body","M 681 232 C 665 255 660 285 670 312 L 690 322 C 700 292 713 262 717 234 C 707 226 691 226 681 232 Z","#f7c948")+
|
||||||
eerst stond las als een worm */
|
coloringContour("seahorse-tail","M 670 312 L 690 322 C 701 348 695 376 671 388 C 647 400 621 388 615 364 C 611 348 621 332 637 328 C 645 326 653 328 657 334 L 670 312 Z","#f7c948")+
|
||||||
coloringContour("seahorse-body","M 586 208 C 626 202 654 228 654 268 C 654 302 638 330 620 352 L 580 336 C 598 310 614 286 614 262 C 614 238 602 226 582 228 Z","#f7c948")+
|
coloringFlat("seahorse-fin",coloringPetalPath(713,244,-40,42,17),"#2fb7a8")+
|
||||||
coloringContour("seahorse-tail","M 580 336 L 620 352 C 608 376 612 396 630 402 C 648 408 662 396 664 380 C 674 410 646 434 618 424 C 586 412 572 374 580 336 Z","#f7c948")+
|
|
||||||
coloringFlat("seahorse-snout","M 574 202 C 548 194 528 202 522 218 C 536 234 560 240 582 232 Z","#f7c948")+
|
|
||||||
coloringGroup("seahorse-detail",
|
coloringGroup("seahorse-detail",
|
||||||
coloringFlat("seahorse-crown","M 600 208 C 596 182 606 162 624 154 C 628 178 620 198 610 212 Z","#f28c3c")+
|
coloringFlat("seahorse-crown","M 695 154 C 691 136 697 122 709 116 C 715 132 711 148 701 158 Z","#f28c3c")+
|
||||||
coloringCircle("seahorse-eye",594,224,11,"#ffffff")+
|
coloringCircle("seahorse-eye",705,180,11,"#ffffff")+
|
||||||
coloringDot(594,224,5)+
|
coloringDot(705,180,5)+
|
||||||
coloringLine("M 606 254 C 620 258 632 256 642 250 M 600 288 C 614 292 626 290 636 284 M 588 320 C 600 326 612 326 620 322 M 596 372 C 608 378 620 378 628 374",2)))+
|
coloringLine("M 689 244 C 697 248 707 246 715 240 M 677 274 C 685 278 695 276 703 270 M 637 362 C 643 368 653 370 661 366",2)))+
|
||||||
coloringGroup("starfish",
|
coloringGroup("starfish",
|
||||||
coloringFlat("starfish",coloringStarPath(456,528,50),"#e0554d")+
|
coloringFlat("starfish",coloringStarPath(456,528,50),"#e0554d")+
|
||||||
coloringGroup("starfish-detail",
|
coloringGroup("starfish-detail",
|
||||||
|
|
|
||||||
|
|
@ -100,6 +100,19 @@ function coloringPetalPath(cx,cy,angle,len,wide){
|
||||||
return `M ${n(cx)} ${n(cy)} C ${n(cx+nx+ux*len*.28)} ${n(cy+ny+uy*len*.28)} ${n(tipX+nx*.52)} ${n(tipY+ny*.52)} ${n(tipX)} ${n(tipY)}`+
|
return `M ${n(cx)} ${n(cy)} C ${n(cx+nx+ux*len*.28)} ${n(cy+ny+uy*len*.28)} ${n(tipX+nx*.52)} ${n(tipY+ny*.52)} ${n(tipX)} ${n(tipY)}`+
|
||||||
` C ${n(tipX-nx*.52)} ${n(tipY-ny*.52)} ${n(cx-nx+ux*len*.28)} ${n(cy-ny+uy*len*.28)} ${n(cx)} ${n(cy)} Z`;
|
` C ${n(tipX-nx*.52)} ${n(tipY-ny*.52)} ${n(cx-nx+ux*len*.28)} ${n(cy-ny+uy*len*.28)} ${n(cx)} ${n(cy)} Z`;
|
||||||
}
|
}
|
||||||
|
/* Getapt dierenbeen: schouderbreedte boven, smal bij de enkel, breder bij de
|
||||||
|
hoef, met een lichte knik zodat het geen rechte kokerpoot wordt. */
|
||||||
|
function coloringLegPath(cx,topY,hoofY,topW,kneeW,hoofW,bend=0){
|
||||||
|
const n=coloringRound,kneeY=topY+(hoofY-topY)*.58;
|
||||||
|
const l1=cx-topW/2,l2=cx-kneeW/2+bend,l3=cx-hoofW/2+bend;
|
||||||
|
const r1=cx+topW/2,r2=cx+kneeW/2+bend,r3=cx+hoofW/2+bend;
|
||||||
|
const midTop=topY+(kneeY-topY)*.5,midHoof=kneeY+(hoofY-kneeY)*.5;
|
||||||
|
return `M ${n(l1)} ${n(topY)} C ${n(l1)} ${n(midTop)} ${n(l2)} ${n(kneeY-(kneeY-topY)*.3)} ${n(l2)} ${n(kneeY)}`+
|
||||||
|
` C ${n(l2)} ${n(midHoof)} ${n(l3)} ${n(hoofY-(hoofY-kneeY)*.3)} ${n(l3)} ${n(hoofY)}`+
|
||||||
|
` L ${n(r3)} ${n(hoofY)}`+
|
||||||
|
` C ${n(r3)} ${n(hoofY-(hoofY-kneeY)*.3)} ${n(r2)} ${n(midHoof)} ${n(r2)} ${n(kneeY)}`+
|
||||||
|
` C ${n(r2)} ${n(kneeY-(kneeY-topY)*.3)} ${n(r1)} ${n(midTop)} ${n(r1)} ${n(topY)} Z`;
|
||||||
|
}
|
||||||
function coloringScene(id,content){
|
function coloringScene(id,content){
|
||||||
return `<svg class="coloring-sheet" data-scene="${id}" viewBox="0 0 800 600" preserveAspectRatio="xMidYMid meet" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false">
|
return `<svg class="coloring-sheet" data-scene="${id}" viewBox="0 0 800 600" preserveAspectRatio="xMidYMid meet" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false">
|
||||||
<defs class="coloring-clips"></defs>
|
<defs class="coloring-clips"></defs>
|
||||||
|
|
@ -198,11 +211,13 @@ function mountColoring(root,initState,opts={}){
|
||||||
<div class="coloring-sizes"></div>
|
<div class="coloring-sizes"></div>
|
||||||
<button class="coloring-done tbtn" type="button"></button>
|
<button class="coloring-done tbtn" type="button"></button>
|
||||||
</div>
|
</div>
|
||||||
<details class="edu-settings widget-gear"><summary>⚙ <span class="coloring-settings-label"></span></summary>
|
<div class="coloring-choices">
|
||||||
<div class="coloring-choices edu-controls">
|
|
||||||
<label><span class="coloring-theme-label"></span><select class="coloring-theme"></select></label>
|
<label><span class="coloring-theme-label"></span><select class="coloring-theme"></select></label>
|
||||||
<label><span class="coloring-page-label"></span><select class="coloring-page"></select></label>
|
<label><span class="coloring-page-label"></span><select class="coloring-page"></select></label>
|
||||||
<span class="coloring-fit"></span>
|
<span class="coloring-fit"></span>
|
||||||
|
</div>
|
||||||
|
<details class="edu-settings widget-gear"><summary>⚙ <span class="coloring-settings-label"></span></summary>
|
||||||
|
<div class="edu-controls">
|
||||||
<button class="coloring-guide-btn" type="button">🎯</button>
|
<button class="coloring-guide-btn" type="button">🎯</button>
|
||||||
<button class="coloring-reset" type="button">↺</button>
|
<button class="coloring-reset" type="button">↺</button>
|
||||||
</div></details>
|
</div></details>
|
||||||
|
|
|
||||||
|
|
@ -669,6 +669,13 @@ function mountClock(root,init){
|
||||||
if(typeof S.level==='string')S.level={hour:1,quarter:2,five:2,minute:3}[S.level]||1;S.level=Math.max(1,Math.min(3,+S.level||1));const assignedRules=mathTaskRules(S.yearGroup,S.level);if(S.managedLearningLevel&&assignedRules)S.level=assignedRules.clockLevel;S.amode=S.amode==='type'?'type':'blocks';S.input=String(S.input||'').replace(/\D/g,'').slice(0,4);
|
if(typeof S.level==='string')S.level={hour:1,quarter:2,five:2,minute:3}[S.level]||1;S.level=Math.max(1,Math.min(3,+S.level||1));const assignedRules=mathTaskRules(S.yearGroup,S.level);if(S.managedLearningLevel&&assignedRules)S.level=assignedRules.clockLevel;S.amode=S.amode==='type'?'type':'blocks';S.input=String(S.input||'').replace(/\D/g,'').slice(0,4);
|
||||||
const style=document.createElement('select'),game=document.createElement('select'),linkHands=document.createElement('input'),use24=document.createElement('input'),stage=document.createElement('div'),add=(el,items)=>items.forEach(([value,key])=>el.add(new Option(T(key),value)));
|
const style=document.createElement('select'),game=document.createElement('select'),linkHands=document.createElement('input'),use24=document.createElement('input'),stage=document.createElement('div'),add=(el,items)=>items.forEach(([value,key])=>el.add(new Option(T(key),value)));
|
||||||
add(style,[['analogue','clockStyleAnalogue'],['digital','clockStyleDigital'],['words','clockStyleWords'],['both','clockStyleBoth']]);add(game,[['set','clockGameSet'],['read','clockGameRead'],['choose','clockGameChoose']]);style.value=S.style;game.value=S.game;linkHands.type='checkbox';linkHands.checked=S.linkHands;linkHands.onchange=()=>{S.linkHands=linkHands.checked};use24.type='checkbox';use24.checked=S.use24;use24.onchange=()=>{S.use24=use24.checked;newTask()};const linkSetting=field(T('clockLinkHands'),linkHands),hour24Setting=field(T('clock24Hour'),use24),syncSettings=()=>{linkSetting.hidden=game.value!=='set';hour24Setting.hidden=S.level!==3};
|
add(style,[['analogue','clockStyleAnalogue'],['digital','clockStyleDigital'],['words','clockStyleWords'],['both','clockStyleBoth']]);add(game,[['set','clockGameSet'],['read','clockGameRead'],['choose','clockGameChoose']]);style.value=S.style;game.value=S.game;linkHands.type='checkbox';linkHands.checked=S.linkHands;linkHands.onchange=()=>{S.linkHands=linkHands.checked};use24.type='checkbox';use24.checked=S.use24;use24.onchange=()=>{S.use24=use24.checked;newTask()};const linkSetting=field(T('clockLinkHands'),linkHands),hour24Setting=field(T('clock24Hour'),use24),syncSettings=()=>{linkSetting.hidden=game.value!=='set';hour24Setting.hidden=S.level!==3};
|
||||||
|
/* het spel (zetten/aflezen/kiezen) verandert per opgave en hoort dus in de
|
||||||
|
vaste bovenbalk; het niveau staat meestal vast (en is bij beheerd niveau
|
||||||
|
zelfs uitgeschakeld) en gaat daarom net als de weergavestijl achter het
|
||||||
|
tandwiel */
|
||||||
|
const gameField=field(T('clockGame'),game);gameField.classList.add('top-field');
|
||||||
|
const levels=document.createElement('div');levels.className='lg-levels clock-levels';
|
||||||
|
const levelButtons=[1,2,3].map(value=>{const button=document.createElement('button');button.type='button';button.textContent=T('lvl'+value);button.title=T('clockLevel'+value+'Hint');button.onclick=()=>chooseLevel(value);levels.append(button);return button});
|
||||||
const minuteValues=()=>assignedRules?.clockMinutes||(S.level===1?[0,30]:S.level===2?Array.from({length:12},(_,i)=>i*5):Array.from({length:60},(_,i)=>i)),time=(hour,minute)=>`${hour}:${String(minute).padStart(2,'0')}`;
|
const minuteValues=()=>assignedRules?.clockMinutes||(S.level===1?[0,30]:S.level===2?Array.from({length:12},(_,i)=>i*5):Array.from({length:60},(_,i)=>i)),time=(hour,minute)=>`${hour}:${String(minute).padStart(2,'0')}`;
|
||||||
const uses24=()=>S.level===3&&S.use24;
|
const uses24=()=>S.level===3&&S.use24;
|
||||||
const daypartKey=hour=>hour<6?'clockNight':hour<12?'clockMorning':hour<18?'clockAfternoon':'clockEvening',clockHour=hour=>hour%12||12;
|
const daypartKey=hour=>hour<6?'clockNight':hour<12?'clockMorning':hour<18?'clockAfternoon':'clockEvening',clockHour=hour=>hour%12||12;
|
||||||
|
|
@ -711,12 +718,12 @@ function mountClock(root,init){
|
||||||
const typeAnswer=()=>{const wrap=document.createElement('div');wrap.className='clock-type-answer';const hint=document.createElement('p');hint.textContent=T('clockTypeHint');const display=document.createElement('output');display.className='clock-type-display';const shown=(S.input+'____').slice(0,4);display.textContent=shown.slice(0,2)+':'+shown.slice(2);const pad=document.createElement('div');pad.className='clock-keypad';['7','8','9','⌫','4','5','6','0','1','2','3','✓'].forEach(key=>{const button=btn(key,()=>{if(S.solved)return;if(key==='⌫')S.input=S.input.slice(0,-1);else if(key==='✓'){check();return}else if(S.input.length<4)S.input+=key;S.feedback='';draw()});if(key==='✓')button.classList.add('ok');pad.append(button)});wrap.append(hint,display,pad);return wrap};
|
const typeAnswer=()=>{const wrap=document.createElement('div');wrap.className='clock-type-answer';const hint=document.createElement('p');hint.textContent=T('clockTypeHint');const display=document.createElement('output');display.className='clock-type-display';const shown=(S.input+'____').slice(0,4);display.textContent=shown.slice(0,2)+':'+shown.slice(2);const pad=document.createElement('div');pad.className='clock-keypad';['7','8','9','⌫','4','5','6','0','1','2','3','✓'].forEach(key=>{const button=btn(key,()=>{if(S.solved)return;if(key==='⌫')S.input=S.input.slice(0,-1);else if(key==='✓'){check();return}else if(S.input.length<4)S.input+=key;S.feedback='';draw()});if(key==='✓')button.classList.add('ok');pad.append(button)});wrap.append(hint,display,pad);return wrap};
|
||||||
const newTask=()=>{const target=randomTime();S.targetH=target.h;S.targetM=target.m;S.h=uses24()?0:12;S.m=0;S.task=true;S.solved=false;S.feedback='';S.input='';S.choices=[];S.answerDigits=[null,null,null,null];if(S.game==='choose'){S.choices=[target];while(S.choices.length<3){const option=randomTime();if(!S.choices.some(x=>x.h===option.h&&x.m===option.m))S.choices.push(option)}S.choices.sort(()=>Math.random()-.5)}draw()};
|
const newTask=()=>{const target=randomTime();S.targetH=target.h;S.targetM=target.m;S.h=uses24()?0:12;S.m=0;S.task=true;S.solved=false;S.feedback='';S.input='';S.choices=[];S.answerDigits=[null,null,null,null];if(S.game==='choose'){S.choices=[target];while(S.choices.length<3){const option=randomTime();if(!S.choices.some(x=>x.h===option.h&&x.m===option.m))S.choices.push(option)}S.choices.sort(()=>Math.random()-.5)}draw()};
|
||||||
const chooseLevel=value=>{S.level=value;S.score=0;S.streak=0;syncSettings();newTask()},toggleMode=()=>{S.amode=S.amode==='blocks'?'type':'blocks';S.feedback='';S.input='';S.answerDigits=[null,null,null,null];draw()};
|
const chooseLevel=value=>{S.level=value;S.score=0;S.streak=0;syncSettings();newTask()},toggleMode=()=>{S.amode=S.amode==='blocks'?'type':'blocks';S.feedback='';S.input='';S.answerDigits=[null,null,null,null];draw()};
|
||||||
const draw=()=>{S.style=style.value;S.game=game.value;stage.className='clock-app';stage.innerHTML='';const top=document.createElement('div');top.className='clock-top';const levelControl=document.createElement('div');levelControl.className='clock-level-control';const label=document.createElement('span');label.textContent=T('clockLevel');const levels=document.createElement('div');levels.className='lg-levels clock-levels';[1,2,3].forEach(value=>{const button=document.createElement('button');button.type='button';button.textContent=T('lvl'+value);button.title=T('clockLevel'+value+'Hint');button.classList.toggle('active',S.level===value);button.onclick=()=>chooseLevel(value);levels.append(button)});levelControl.append(label,levels);top.append(levelControl);if(S.game!=='set'){const mode=btn(S.amode==='blocks'?'🧱':'⌨️',toggleMode);mode.classList.add('clock-mode');mode.title=T('amode');top.append(mode)}const score=document.createElement('span');score.className='clock-score';score.textContent=T('clockScore').replace('{score}',S.score).replace('{streak}',S.streak);top.append(score);stage.append(top);const card=document.createElement('section');card.className='clock-task-card';const title=document.createElement('h3');title.textContent=S.game==='set'?T('clockSetTitle'):S.game==='read'?T('clockReadTitle'):T('clockChooseTitle');card.append(title);
|
const draw=()=>{S.style=style.value;S.game=game.value;stage.className='clock-app';stage.innerHTML='';const top=document.createElement('div');top.className='clock-top';levelButtons.forEach((button,index)=>button.classList.toggle('active',S.level===index+1));top.append(gameField);if(S.game!=='set'){const mode=btn(S.amode==='blocks'?'🧱':'⌨️',toggleMode);mode.classList.add('clock-mode');mode.title=T('amode');top.append(mode)}const score=document.createElement('span');score.className='clock-score';score.textContent=T('clockScore').replace('{score}',S.score).replace('{streak}',S.streak);top.append(score);stage.append(top);const card=document.createElement('section');card.className='clock-task-card';const title=document.createElement('h3');title.textContent=S.game==='set'?T('clockSetTitle'):S.game==='read'?T('clockReadTitle'):T('clockChooseTitle');card.append(title);
|
||||||
if(S.task&&S.game==='set'){const prompt=document.createElement('div');prompt.className='clock-target';const label=document.createElement('span');label.textContent=T('clockYourTask');prompt.append(label,assignment(S.targetH,S.targetM,true));card.append(prompt);const work=document.createElement('div');work.className='clock-work';const answer=document.createElement('div');answer.className='clock-set-answer';if(uses24())answer.append(periodControl());const live=document.createElement('div');live.className='clock-live-answer';live.append(timeBlocks(S.h,S.m));answer.append(live);work.append(makeClock(S.h,S.m,true),answer);card.append(work);}
|
if(S.task&&S.game==='set'){const prompt=document.createElement('div');prompt.className='clock-target';const label=document.createElement('span');label.textContent=T('clockYourTask');prompt.append(label,assignment(S.targetH,S.targetM,true));card.append(prompt);const work=document.createElement('div');work.className='clock-work';const answer=document.createElement('div');answer.className='clock-set-answer';if(uses24())answer.append(periodControl());const live=document.createElement('div');live.className='clock-live-answer';live.append(timeBlocks(S.h,S.m));answer.append(live);work.append(makeClock(S.h,S.m,true),answer);card.append(work);}
|
||||||
if(S.task&&S.game==='read'){const layout=document.createElement('div');layout.className='clock-read-layout';layout.append(assignment(S.targetH,S.targetM),S.amode==='blocks'?blockAnswer():typeAnswer());card.append(layout)}
|
if(S.task&&S.game==='read'){const layout=document.createElement('div');layout.className='clock-read-layout';layout.append(assignment(S.targetH,S.targetM),S.amode==='blocks'?blockAnswer():typeAnswer());card.append(layout)}
|
||||||
if(S.task&&S.game==='choose'){card.append(assignment(S.targetH,S.targetM));if(!S.solved){const choices=document.createElement('div');choices.className='clock-choices '+(S.amode==='blocks'?'wood':'plain');const asWords=['digital','both'].includes(S.style);S.choices.forEach(option=>{const choose=()=>setFeedback(option.h===S.targetH&&option.m===S.targetM);if(asWords){const button=btn(words(option.h,option.m),choose);button.classList.add('clock-word-choice');choices.append(button)}else if(S.amode==='blocks')choices.append(timeBlocks(option.h,option.m,choose));else{const button=btn(time(option.h,option.m),choose);button.classList.add('clock-digital-choice');choices.append(button)}});card.append(choices)}}
|
if(S.task&&S.game==='choose'){card.append(assignment(S.targetH,S.targetM));if(!S.solved){const choices=document.createElement('div');choices.className='clock-choices '+(S.amode==='blocks'?'wood':'plain');const asWords=['digital','both'].includes(S.style);S.choices.forEach(option=>{const choose=()=>setFeedback(option.h===S.targetH&&option.m===S.targetM);if(asWords){const button=btn(words(option.h,option.m),choose);button.classList.add('clock-word-choice');choices.append(button)}else if(S.amode==='blocks')choices.append(timeBlocks(option.h,option.m,choose));else{const button=btn(time(option.h,option.m),choose);button.classList.add('clock-digital-choice');choices.append(button)}});card.append(choices)}}
|
||||||
const feedback=document.createElement('p');feedback.className='clock-feedback '+(S.feedback==='good'?'ok':S.feedback?'bad':'');feedback.setAttribute('role','status');if(S.feedback)feedback.textContent=T(S.feedback==='good'?'clockCorrect':S.feedback==='incomplete'?'clockIncomplete':'clockTryAgain');if(S.feedback==='good'&¤tUser&¤tUser.avatar){const cheer=renderAvatarFace(currentUser.avatar,'md');cheer.classList.add('av-cheer');feedback.append(cheer)}card.append(feedback);const actions=document.createElement('div');actions.className='clock-actions';if(S.task&&S.game!=='choose'&&!S.solved&&!(S.game==='read'&&S.amode==='type'))actions.append(btn(T('numberlineCheck'),check,''));actions.append(btn(T('clockNextTask'),newTask,'ghost'));card.append(actions);if(S.task&&S.game==='set'){const hint=document.createElement('small');hint.className='clock-drag-hint';hint.textContent=T('clockDragHint');card.append(hint)}stage.append(card)};
|
const feedback=document.createElement('p');feedback.className='clock-feedback '+(S.feedback==='good'?'ok':S.feedback?'bad':'');feedback.setAttribute('role','status');if(S.feedback)feedback.textContent=T(S.feedback==='good'?'clockCorrect':S.feedback==='incomplete'?'clockIncomplete':'clockTryAgain');if(S.feedback==='good'&¤tUser&¤tUser.avatar){const cheer=renderAvatarFace(currentUser.avatar,'md');cheer.classList.add('av-cheer');feedback.append(cheer)}card.append(feedback);const actions=document.createElement('div');actions.className='clock-actions';if(S.task&&S.game!=='choose'&&!S.solved&&!(S.game==='read'&&S.amode==='type'))actions.append(btn(T('numberlineCheck'),check,''));actions.append(btn(T('clockNextTask'),newTask,'ghost'));card.append(actions);if(S.task&&S.game==='set'){const hint=document.createElement('small');hint.className='clock-drag-hint';hint.textContent=T('clockDragHint');card.append(hint)}stage.append(card)};
|
||||||
style.onchange=draw;game.onchange=()=>{syncSettings();newTask()};learningShell(root,[field(T('clockLearningStyle'),style),field(T('clockGame'),game),linkSetting,hour24Setting],stage);root.classList.toggle('managed-learning-level',!!S.managedLearningLevel);syncSettings();newTask();return{getState:()=>persistedLearningState(S,{choices:S.choices.map(x=>({...x})),answerDigits:[...S.answerDigits]})};
|
style.onchange=draw;game.onchange=()=>{syncSettings();newTask()};learningShell(root,[field(T('clockLevel'),levels),field(T('clockLearningStyle'),style),linkSetting,hour24Setting],stage);root.classList.toggle('managed-learning-level',!!S.managedLearningLevel);syncSettings();newTask();return{getState:()=>persistedLearningState(S,{choices:S.choices.map(x=>({...x})),answerDigits:[...S.answerDigits]})};
|
||||||
}
|
}
|
||||||
const PLACE_COLUMNS=['HD','TD','D','H','T','E'];
|
const PLACE_COLUMNS=['HD','TD','D','H','T','E'];
|
||||||
const placeLevelDigits=level=>level===1?2:level===2?3:6;
|
const placeLevelDigits=level=>level===1?2:level===2?3:6;
|
||||||
|
|
@ -725,17 +732,22 @@ function mountPlacevalue(root,init){
|
||||||
S.level=Math.max(1,Math.min(3,+S.level||1));const assignedRules=mathTaskRules(S.yearGroup,S.level);if(S.managedLearningLevel&&assignedRules)S.level=assignedRules.placeLevel;S.game=S.game==='build'?'build':'explore';if(!Array.isArray(S.answerDigits))S.answerDigits=null;
|
S.level=Math.max(1,Math.min(3,+S.level||1));const assignedRules=mathTaskRules(S.yearGroup,S.level);if(S.managedLearningLevel&&assignedRules)S.level=assignedRules.placeLevel;S.game=S.game==='build'?'build':'explore';if(!Array.isArray(S.answerDigits))S.answerDigits=null;
|
||||||
const input=num(S.number,0,999999),game=document.createElement('select'),stage=document.createElement('div');
|
const input=num(S.number,0,999999),game=document.createElement('select'),stage=document.createElement('div');
|
||||||
game.add(new Option(T('placeGameExplore'),'explore'));game.add(new Option(T('placeGameBuild'),'build'));game.value=S.game;
|
game.add(new Option(T('placeGameExplore'),'explore'));game.add(new Option(T('placeGameBuild'),'build'));game.value=S.game;
|
||||||
|
/* spel en getal kies je elke keer opnieuw, dus die staan in de vaste
|
||||||
|
bovenbalk; niveau staat meestal vast (en is bij beheerd niveau
|
||||||
|
uitgeschakeld) en gaat achter het tandwiel */
|
||||||
const gameSetting=field(T('placeGame'),game),numberSetting=field(T('placeNumber'),input),diceBtn=btn('🎲',()=>{input.value=Math.floor(Math.random()*999999);drawExplore()});
|
const gameSetting=field(T('placeGame'),game),numberSetting=field(T('placeNumber'),input),diceBtn=btn('🎲',()=>{input.value=Math.floor(Math.random()*999999);drawExplore()});
|
||||||
const syncSettings=()=>{numberSetting.hidden=S.game!=='explore';diceBtn.hidden=S.game!=='explore'};
|
gameSetting.classList.add('top-field');numberSetting.classList.add('top-field');
|
||||||
|
const levels=document.createElement('div');levels.className='lg-levels place-levels';
|
||||||
|
const levelButtons=[1,2,3].map(value=>{const button=document.createElement('button');button.type='button';button.textContent=T('lvl'+value);button.title=T('placeLevel'+value+'Hint');button.onclick=()=>chooseLevel(value);levels.append(button);return button});
|
||||||
const activeCols=()=>PLACE_COLUMNS.slice(6-placeLevelDigits(S.level));
|
const activeCols=()=>PLACE_COLUMNS.slice(6-placeLevelDigits(S.level));
|
||||||
const maxForLevel=()=>Math.pow(10,placeLevelDigits(S.level))-1;
|
const maxForLevel=()=>Math.pow(10,placeLevelDigits(S.level))-1;
|
||||||
const woodDigit=value=>{const block=document.createElement('span');block.className='blok sm place-digit-block';const label=document.createElement('span');label.className='bl';label.textContent=String(value);const dots=dotGrid(Number(value));dots.classList.add('blok-dots');block.append(label,dots);return block};
|
const woodDigit=value=>{const block=document.createElement('span');block.className='blok sm place-digit-block';const label=document.createElement('span');label.className='bl';label.textContent=String(value);const dots=dotGrid(Number(value));dots.classList.add('blok-dots');block.append(label,dots);return block};
|
||||||
const drawExplore=()=>{S.number=Math.max(0,Math.min(999999,+input.value||0));const digits=String(S.number).padStart(6,'0').split('');stage.className='place-grid';stage.innerHTML='';PLACE_COLUMNS.forEach((x,i)=>{const d=document.createElement('div');const b=document.createElement('b');b.textContent=x;const o=document.createElement('output');o.textContent=digits[i];d.append(b,o);stage.append(d)})};
|
const drawExplore=()=>{S.number=Math.max(0,Math.min(999999,+input.value||0));const digits=String(S.number).padStart(6,'0').split('');stage.className='place-app';stage.innerHTML='';levelButtons.forEach((button,index)=>button.classList.toggle('active',S.level===index+1));const top=document.createElement('div');top.className='place-top';top.append(gameSetting,numberSetting,diceBtn);stage.append(top);const grid=document.createElement('div');grid.className='place-grid';PLACE_COLUMNS.forEach((x,i)=>{const d=document.createElement('div');const b=document.createElement('b');b.textContent=x;const o=document.createElement('output');o.textContent=digits[i];d.append(b,o);grid.append(d)});stage.append(grid)};
|
||||||
const setFeedback=ok=>{if(S.solved)return;if(ok){S.solved=true;S.score++;S.streak++;S.feedback='good';sndGood()}else{S.streak=0;S.feedback='bad';sndBad()}drawBuild()};
|
const setFeedback=ok=>{if(S.solved)return;if(ok){S.solved=true;S.score++;S.streak++;S.feedback='good';sndGood()}else{S.streak=0;S.feedback='bad';sndBad()}drawBuild()};
|
||||||
const check=()=>{if(S.answerDigits.some(d=>d===null)){S.feedback='incomplete';sndBad();drawBuild();return}setFeedback(Number(S.answerDigits.join(''))===S.target)};
|
const check=()=>{if(S.answerDigits.some(d=>d===null)){S.feedback='incomplete';sndBad();drawBuild();return}setFeedback(Number(S.answerDigits.join(''))===S.target)};
|
||||||
const needsNewTask=()=>S.target===null||!Array.isArray(S.answerDigits)||S.answerDigits.length!==activeCols().length;
|
const needsNewTask=()=>S.target===null||!Array.isArray(S.answerDigits)||S.answerDigits.length!==activeCols().length;
|
||||||
const newTask=()=>{S.target=Math.floor(Math.random()*(maxForLevel()+1));S.answerDigits=activeCols().map(()=>null);S.solved=false;S.feedback='';drawBuild()};
|
const newTask=()=>{S.target=Math.floor(Math.random()*(maxForLevel()+1));S.answerDigits=activeCols().map(()=>null);S.solved=false;S.feedback='';drawBuild()};
|
||||||
const chooseLevel=value=>{S.level=value;S.score=0;S.streak=0;newTask()};
|
const chooseLevel=value=>{S.level=value;S.score=0;S.streak=0;if(S.game==='build')newTask();else drawExplore()};
|
||||||
const buildAnswer=()=>{
|
const buildAnswer=()=>{
|
||||||
const answer=document.createElement('div');answer.className='place-block-answer';const instruction=document.createElement('p');instruction.textContent=T('placeBuildHint');
|
const answer=document.createElement('div');answer.className='place-block-answer';const instruction=document.createElement('p');instruction.textContent=T('placeBuildHint');
|
||||||
const slots=document.createElement('div');slots.className='place-answer-slots';const cols=activeCols();
|
const slots=document.createElement('div');slots.className='place-answer-slots';const cols=activeCols();
|
||||||
|
|
@ -755,10 +767,8 @@ function mountPlacevalue(root,init){
|
||||||
};
|
};
|
||||||
const drawBuild=()=>{
|
const drawBuild=()=>{
|
||||||
stage.className='place-app';stage.innerHTML='';const top=document.createElement('div');top.className='place-top';
|
stage.className='place-app';stage.innerHTML='';const top=document.createElement('div');top.className='place-top';
|
||||||
const levelControl=document.createElement('div');levelControl.className='place-level-control';const label=document.createElement('span');label.textContent=T('placeLevel');
|
levelButtons.forEach((button,index)=>button.classList.toggle('active',S.level===index+1));
|
||||||
const levels=document.createElement('div');levels.className='lg-levels place-levels';
|
top.append(gameSetting);
|
||||||
[1,2,3].forEach(value=>{const button=document.createElement('button');button.type='button';button.textContent=T('lvl'+value);button.title=T('placeLevel'+value+'Hint');button.classList.toggle('active',S.level===value);button.onclick=()=>chooseLevel(value);levels.append(button)});
|
|
||||||
levelControl.append(label,levels);top.append(levelControl);
|
|
||||||
const score=document.createElement('span');score.className='place-score';score.textContent=T('placeScore').replace('{score}',S.score).replace('{streak}',S.streak);top.append(score);stage.append(top);
|
const score=document.createElement('span');score.className='place-score';score.textContent=T('placeScore').replace('{score}',S.score).replace('{streak}',S.streak);top.append(score);stage.append(top);
|
||||||
const card=document.createElement('section');card.className='place-task-card';const title=document.createElement('h3');title.textContent=T('placeBuildTitle');card.append(title);
|
const card=document.createElement('section');card.className='place-task-card';const title=document.createElement('h3');title.textContent=T('placeBuildTitle');card.append(title);
|
||||||
const target=document.createElement('div');target.className='place-target';const targetLabel=document.createElement('span');targetLabel.textContent=T('placeYourTask');
|
const target=document.createElement('div');target.className='place-target';const targetLabel=document.createElement('span');targetLabel.textContent=T('placeYourTask');
|
||||||
|
|
@ -767,8 +777,8 @@ function mountPlacevalue(root,init){
|
||||||
if(S.feedback)feedback.textContent=T(S.feedback==='good'?'placeCorrect':S.feedback==='incomplete'?'placeIncomplete':'placeTryAgain');if(S.feedback==='good'&¤tUser&¤tUser.avatar){const cheer=renderAvatarFace(currentUser.avatar,'md');cheer.classList.add('av-cheer');feedback.append(cheer)}card.append(feedback);
|
if(S.feedback)feedback.textContent=T(S.feedback==='good'?'placeCorrect':S.feedback==='incomplete'?'placeIncomplete':'placeTryAgain');if(S.feedback==='good'&¤tUser&¤tUser.avatar){const cheer=renderAvatarFace(currentUser.avatar,'md');cheer.classList.add('av-cheer');feedback.append(cheer)}card.append(feedback);
|
||||||
const actions=document.createElement('div');actions.className='place-actions';if(!S.solved)actions.append(btn(T('numberlineCheck'),check,''));actions.append(btn(T('placeNextTask'),newTask,'ghost'));card.append(actions);stage.append(card);
|
const actions=document.createElement('div');actions.className='place-actions';if(!S.solved)actions.append(btn(T('numberlineCheck'),check,''));actions.append(btn(T('placeNextTask'),newTask,'ghost'));card.append(actions);stage.append(card);
|
||||||
};
|
};
|
||||||
input.oninput=drawExplore;game.onchange=()=>{S.game=game.value;syncSettings();if(S.game!=='build')drawExplore();else if(needsNewTask())newTask();else drawBuild()};
|
input.oninput=drawExplore;game.onchange=()=>{S.game=game.value;if(S.game!=='build')drawExplore();else if(needsNewTask())newTask();else drawBuild()};
|
||||||
learningShell(root,[gameSetting,numberSetting,diceBtn],stage);root.classList.toggle('managed-learning-level',!!S.managedLearningLevel);syncSettings();
|
learningShell(root,[field(T('placeLevel'),levels)],stage);root.classList.toggle('managed-learning-level',!!S.managedLearningLevel);
|
||||||
if(S.game!=='build')drawExplore();else if(needsNewTask())newTask();else drawBuild();
|
if(S.game!=='build')drawExplore();else if(needsNewTask())newTask();else drawBuild();
|
||||||
return{getState:()=>persistedLearningState(S,{answerDigits:S.answerDigits?[...S.answerDigits]:null})};
|
return{getState:()=>persistedLearningState(S,{answerDigits:S.answerDigits?[...S.answerDigits]:null})};
|
||||||
}
|
}
|
||||||
|
|
@ -778,7 +788,13 @@ function mountMoney(root,init){
|
||||||
S.level=Math.max(1,Math.min(3,+S.level||1));const assignedRules=mathTaskRules(S.yearGroup,S.level);if(S.managedLearningLevel&&assignedRules)S.level=assignedRules.moneyLevel;S.style=['amount','words','both'].includes(S.style)?S.style:'both';S.game=['make','count','change'].includes(S.game)?S.game:'make';S.category=['all','food','school','play'].includes(S.category)?S.category:'all';S.amode=S.amode==='type'?'type':'blocks';S.selected=Array.isArray(S.selected)?S.selected.map(Number).filter(Number.isFinite):[];S.given=Array.isArray(S.given)?S.given.map(Number).filter(Number.isFinite):[];
|
S.level=Math.max(1,Math.min(3,+S.level||1));const assignedRules=mathTaskRules(S.yearGroup,S.level);if(S.managedLearningLevel&&assignedRules)S.level=assignedRules.moneyLevel;S.style=['amount','words','both'].includes(S.style)?S.style:'both';S.game=['make','count','change'].includes(S.game)?S.game:'make';S.category=['all','food','school','play'].includes(S.category)?S.category:'all';S.amode=S.amode==='type'?'type':'blocks';S.selected=Array.isArray(S.selected)?S.selected.map(Number).filter(Number.isFinite):[];S.given=Array.isArray(S.given)?S.given.map(Number).filter(Number.isFinite):[];
|
||||||
const style=document.createElement('select'),game=document.createElement('select'),category=document.createElement('select'),stage=document.createElement('div'),add=(el,items)=>items.forEach(([value,key])=>el.add(new Option(T(key),value)));
|
const style=document.createElement('select'),game=document.createElement('select'),category=document.createElement('select'),stage=document.createElement('div'),add=(el,items)=>items.forEach(([value,key])=>el.add(new Option(T(key),value)));
|
||||||
add(style,[['amount','moneyStyleAmount'],['words','moneyStyleWords'],['both','moneyStyleBoth']]);add(game,[['make','moneyGameMake'],['count','moneyGameCount'],['change','moneyGameChange']]);add(category,[['all','moneyCategoryAll'],['food','moneyCategoryFood'],['school','moneyCategorySchool'],['play','moneyCategoryPlay']]);style.value=S.style;game.value=S.game;category.value=S.category;
|
add(style,[['amount','moneyStyleAmount'],['words','moneyStyleWords'],['both','moneyStyleBoth']]);add(game,[['make','moneyGameMake'],['count','moneyGameCount'],['change','moneyGameChange']]);add(category,[['all','moneyCategoryAll'],['food','moneyCategoryFood'],['school','moneyCategorySchool'],['play','moneyCategoryPlay']]);style.value=S.style;game.value=S.game;category.value=S.category;
|
||||||
const styleSetting=field(T('moneyLearningStyle'),style),gameSetting=field(T('moneyGame'),game),categorySetting=field(T('moneyCategory'),category),syncSettings=()=>{styleSetting.hidden=S.game==='count';categorySetting.hidden=S.game!=='change'};
|
const styleSetting=field(T('moneyLearningStyle'),style),gameSetting=field(T('moneyGame'),game),categorySetting=field(T('moneyCategory'),category),syncSettings=()=>{styleSetting.hidden=S.game==='count'};
|
||||||
|
/* spel (en bij het wisselgeld-spel: categorie) kies je elke keer opnieuw en
|
||||||
|
staat dus in de vaste bovenbalk; niveau staat meestal vast (en is bij
|
||||||
|
beheerd niveau uitgeschakeld) en gaat achter het tandwiel */
|
||||||
|
gameSetting.classList.add('top-field');categorySetting.classList.add('top-field');
|
||||||
|
const levels=document.createElement('div');levels.className='lg-levels money-levels';
|
||||||
|
const levelButtons=[1,2,3].map(value=>{const button=document.createElement('button');button.type='button';button.textContent=T('lvl'+value);button.title=T('moneyLevel'+value+'Hint');button.onclick=()=>chooseLevel(value);levels.append(button);return button});
|
||||||
const format=cents=>{const value=(Math.max(0,cents)/100).toFixed(2);return '€ '+(LANG==='nl'?value.replace('.',','):value)};
|
const format=cents=>{const value=(Math.max(0,cents)/100).toFixed(2);return '€ '+(LANG==='nl'?value.replace('.',','):value)};
|
||||||
const nlSmall=['nul','een','twee','drie','vier','vijf','zes','zeven','acht','negen','tien','elf','twaalf','dertien','veertien','vijftien','zestien','zeventien','achttien','negentien'],nlTens=['','','twintig','dertig','veertig','vijftig','zestig','zeventig','tachtig','negentig'];
|
const nlSmall=['nul','een','twee','drie','vier','vijf','zes','zeven','acht','negen','tien','elf','twaalf','dertien','veertien','vijftien','zestien','zeventien','achttien','negentien'],nlTens=['','','twintig','dertig','veertig','vijftig','zestig','zeventig','tachtig','negentig'];
|
||||||
const enSmall=['zero','one','two','three','four','five','six','seven','eight','nine','ten','eleven','twelve','thirteen','fourteen','fifteen','sixteen','seventeen','eighteen','nineteen'],enTens=['','','twenty','thirty','forty','fifty','sixty','seventy','eighty','ninety'];
|
const enSmall=['zero','one','two','three','four','five','six','seven','eight','nine','ten','eleven','twelve','thirteen','fourteen','fifteen','sixteen','seventeen','eighteen','nineteen'],enTens=['','','twenty','thirty','forty','fifty','sixty','seventy','eighty','ninety'];
|
||||||
|
|
@ -809,13 +825,13 @@ function mountMoney(root,init){
|
||||||
const resetAnswer=()=>{S.selected=[];S.input='';S.answerDigits=emptyDigits();S.feedback='';S.solved=false;draw()};
|
const resetAnswer=()=>{S.selected=[];S.input='';S.answerDigits=emptyDigits();S.feedback='';S.solved=false;draw()};
|
||||||
const newTask=()=>{const task=createMoneyTask(S.level,S.game,S.category,S.targetCents,S.productId);S.targetCents=task.targetCents;S.paidCents=task.paidCents;S.productId=task.productId;S.selected=[];S.given=breakdown(task.targetCents);S.input='';S.answerDigits=emptyDigits();S.solved=false;S.feedback='';draw()};
|
const newTask=()=>{const task=createMoneyTask(S.level,S.game,S.category,S.targetCents,S.productId);S.targetCents=task.targetCents;S.paidCents=task.paidCents;S.productId=task.productId;S.selected=[];S.given=breakdown(task.targetCents);S.input='';S.answerDigits=emptyDigits();S.solved=false;S.feedback='';draw()};
|
||||||
const chooseLevel=value=>{S.level=value;S.score=0;S.streak=0;newTask()},toggleMode=()=>{S.amode=S.amode==='blocks'?'type':'blocks';S.input='';S.answerDigits=emptyDigits();S.feedback='';draw()};
|
const chooseLevel=value=>{S.level=value;S.score=0;S.streak=0;newTask()},toggleMode=()=>{S.amode=S.amode==='blocks'?'type':'blocks';S.input='';S.answerDigits=emptyDigits();S.feedback='';draw()};
|
||||||
const draw=()=>{S.style=style.value;S.game=game.value;stage.className='money-app';stage.innerHTML='';const top=document.createElement('div');top.className='money-top';const levelControl=document.createElement('div');levelControl.className='money-level-control';const levelLabel=document.createElement('span');levelLabel.textContent=T('moneyLevel');const levels=document.createElement('div');levels.className='lg-levels money-levels';[1,2,3].forEach(value=>{const button=document.createElement('button');button.type='button';button.textContent=T('lvl'+value);button.title=T('moneyLevel'+value+'Hint');button.classList.toggle('active',S.level===value);button.onclick=()=>chooseLevel(value);levels.append(button)});levelControl.append(levelLabel,levels);top.append(levelControl);if(S.game!=='make'){const mode=btn(S.amode==='blocks'?'🧱':'⌨️',toggleMode);mode.classList.add('money-mode');mode.title=T('amode');top.append(mode)}const score=document.createElement('span');score.className='money-score';score.textContent=T('moneyScore').replace('{score}',S.score).replace('{streak}',S.streak);top.append(score);stage.append(top);
|
const draw=()=>{S.style=style.value;S.game=game.value;stage.className='money-app';stage.innerHTML='';const top=document.createElement('div');top.className='money-top';levelButtons.forEach((button,index)=>button.classList.toggle('active',S.level===index+1));top.append(gameSetting);if(S.game==='change')top.append(categorySetting);if(S.game!=='make'){const mode=btn(S.amode==='blocks'?'🧱':'⌨️',toggleMode);mode.classList.add('money-mode');mode.title=T('amode');top.append(mode)}const score=document.createElement('span');score.className='money-score';score.textContent=T('moneyScore').replace('{score}',S.score).replace('{streak}',S.streak);top.append(score);stage.append(top);
|
||||||
const card=document.createElement('section');card.className='money-task-card';const title=document.createElement('h3'),levelHint=document.createElement('p');title.textContent=T(S.game==='make'?'moneyMakeTitle':S.game==='count'?'moneyCountTitle':'moneyChangeTitle');levelHint.className='money-level-hint';levelHint.textContent=T('moneyLevel'+S.level+'Hint');card.append(title,levelHint);
|
const card=document.createElement('section');card.className='money-task-card';const title=document.createElement('h3'),levelHint=document.createElement('p');title.textContent=T(S.game==='make'?'moneyMakeTitle':S.game==='count'?'moneyCountTitle':'moneyChangeTitle');levelHint.className='money-level-hint';levelHint.textContent=T('moneyLevel'+S.level+'Hint');card.append(title,levelHint);
|
||||||
if(S.game==='make'){const target=document.createElement('div');target.className='money-target';const label=document.createElement('span');label.textContent=T('moneyYourTask');target.append(label,amountDisplay(S.targetCents,true));card.append(target);const wallet=document.createElement('div');wallet.className='money-wallet';const walletHead=document.createElement('div');const walletLabel=document.createElement('b');walletLabel.textContent=T('moneyWallet');const total=document.createElement('output');total.textContent=format(S.selected.reduce((sum,item)=>sum+item,0));walletHead.append(walletLabel,total);wallet.append(walletHead);if(S.selected.length)wallet.append(pile(S.selected,true,wallet));else{const hint=document.createElement('p');hint.textContent=T('moneyWalletHint');wallet.append(hint)}card.append(wallet,moneyTray(wallet))}
|
if(S.game==='make'){const target=document.createElement('div');target.className='money-target';const label=document.createElement('span');label.textContent=T('moneyYourTask');target.append(label,amountDisplay(S.targetCents,true));card.append(target);const wallet=document.createElement('div');wallet.className='money-wallet';const walletHead=document.createElement('div');const walletLabel=document.createElement('b');walletLabel.textContent=T('moneyWallet');const total=document.createElement('output');total.textContent=format(S.selected.reduce((sum,item)=>sum+item,0));walletHead.append(walletLabel,total);wallet.append(walletHead);if(S.selected.length)wallet.append(pile(S.selected,true,wallet));else{const hint=document.createElement('p');hint.textContent=T('moneyWalletHint');wallet.append(hint)}card.append(wallet,moneyTray(wallet))}
|
||||||
if(S.game==='count'){const target=document.createElement('div');target.className='money-count-task';target.append(pile(S.given));card.append(target,S.amode==='blocks'?digitAnswer():typeAnswer())}
|
if(S.game==='count'){const target=document.createElement('div');target.className='money-count-task';target.append(pile(S.given));card.append(target,S.amode==='blocks'?digitAnswer():typeAnswer())}
|
||||||
if(S.game==='change'){const item=currentProduct(),shop=document.createElement('div');shop.className='money-shop-task';const product=document.createElement('div');product.className='money-product';const emoji=document.createElement('span'),productName=document.createElement('strong');emoji.className='money-product-icon';emoji.textContent=item.icon;productName.className='money-product-name';productName.textContent=LANG==='nl'?item.nl:item.en;const priceLabel=document.createElement('b');priceLabel.textContent=T('moneyPrice');product.append(emoji,productName,priceLabel,amountDisplay(S.targetCents,true));const paid=document.createElement('div');paid.className='money-paid';const paidLabel=document.createElement('b');paidLabel.textContent=T('moneyPaid');const paidAmount=document.createElement('output');paidAmount.textContent=format(S.paidCents);paid.append(paidLabel,paidAmount,pile([S.paidCents]));shop.append(product,paid);card.append(shop,S.amode==='blocks'?digitAnswer():typeAnswer())}
|
if(S.game==='change'){const item=currentProduct(),shop=document.createElement('div');shop.className='money-shop-task';const product=document.createElement('div');product.className='money-product';const emoji=document.createElement('span'),productName=document.createElement('strong');emoji.className='money-product-icon';emoji.textContent=item.icon;productName.className='money-product-name';productName.textContent=LANG==='nl'?item.nl:item.en;const priceLabel=document.createElement('b');priceLabel.textContent=T('moneyPrice');product.append(emoji,productName,priceLabel,amountDisplay(S.targetCents,true));const paid=document.createElement('div');paid.className='money-paid';const paidLabel=document.createElement('b');paidLabel.textContent=T('moneyPaid');const paidAmount=document.createElement('output');paidAmount.textContent=format(S.paidCents);paid.append(paidLabel,paidAmount,pile([S.paidCents]));shop.append(product,paid);card.append(shop,S.amode==='blocks'?digitAnswer():typeAnswer())}
|
||||||
const feedback=document.createElement('p');feedback.className='money-feedback '+(S.feedback==='good'?'ok':S.feedback?'bad':'');feedback.setAttribute('role','status');feedback.textContent=S.feedback?feedbackText():'';if(S.feedback==='good'&¤tUser&¤tUser.avatar){const cheer=renderAvatarFace(currentUser.avatar,'md');cheer.classList.add('av-cheer');feedback.append(cheer)}card.append(feedback);const actions=document.createElement('div');actions.className='money-actions';if(!S.solved)actions.append(btn(T('numberlineCheck'),check,''));if(!S.solved)actions.append(btn(T('moneyClear'),resetAnswer,'ghost'));actions.append(btn(T('moneyNextTask'),newTask,'ghost'));card.append(actions);stage.append(card)};
|
const feedback=document.createElement('p');feedback.className='money-feedback '+(S.feedback==='good'?'ok':S.feedback?'bad':'');feedback.setAttribute('role','status');feedback.textContent=S.feedback?feedbackText():'';if(S.feedback==='good'&¤tUser&¤tUser.avatar){const cheer=renderAvatarFace(currentUser.avatar,'md');cheer.classList.add('av-cheer');feedback.append(cheer)}card.append(feedback);const actions=document.createElement('div');actions.className='money-actions';if(!S.solved)actions.append(btn(T('numberlineCheck'),check,''));if(!S.solved)actions.append(btn(T('moneyClear'),resetAnswer,'ghost'));actions.append(btn(T('moneyNextTask'),newTask,'ghost'));card.append(actions);stage.append(card)};
|
||||||
style.onchange=draw;game.onchange=()=>{S.game=game.value;syncSettings();newTask()};category.onchange=()=>{S.category=category.value;newTask()};learningShell(root,[styleSetting,gameSetting,categorySetting],stage);root.classList.toggle('managed-learning-level',!!S.managedLearningLevel);syncSettings();newTask();return{getState:()=>persistedLearningState(S,{selected:[...S.selected],given:[...S.given],answerDigits:[...S.answerDigits]})};
|
style.onchange=draw;game.onchange=()=>{S.game=game.value;syncSettings();newTask()};category.onchange=()=>{S.category=category.value;newTask()};learningShell(root,[field(T('moneyLevel'),levels),styleSetting],stage);root.classList.toggle('managed-learning-level',!!S.managedLearningLevel);syncSettings();newTask();return{getState:()=>persistedLearningState(S,{selected:[...S.selected],given:[...S.given],answerDigits:[...S.answerDigits]})};
|
||||||
}
|
}
|
||||||
|
|
||||||
function mountWordtypes(root,init){
|
function mountWordtypes(root,init){
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,6 @@ function mountLetterGame(root, initState, opts){
|
||||||
root.innerHTML = `
|
root.innerHTML = `
|
||||||
<div class="lg">
|
<div class="lg">
|
||||||
<div class="lg-top">
|
<div class="lg-top">
|
||||||
<div class="lg-levels">
|
|
||||||
<button data-l="1"></button><button data-l="2"></button><button data-l="3"></button>
|
|
||||||
</div>
|
|
||||||
<div class="lg-cards"></div>
|
<div class="lg-cards"></div>
|
||||||
<div class="lg-progress"><span class="lg-count"></span><span class="lg-stars"></span></div>
|
<div class="lg-progress"><span class="lg-count"></span><span class="lg-stars"></span></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -86,14 +83,17 @@ function mountLetterGame(root, initState, opts){
|
||||||
instrEl = el(".lg-instr"), nextBtn = el(".lg-next"), doneEl = el(".lg-done"),
|
instrEl = el(".lg-instr"), nextBtn = el(".lg-next"), doneEl = el(".lg-done"),
|
||||||
countEl = el(".lg-count"), starsEl = el(".lg-stars"), cardsEl = el(".lg-cards");
|
countEl = el(".lg-count"), starsEl = el(".lg-stars"), cardsEl = el(".lg-cards");
|
||||||
|
|
||||||
/* zeldzaam gebruikte besturing (geluid, invoerwijze, aantal kaarten) achter
|
/* de kaartjes (het woord/thema) moeten snel te kiezen zijn - dat verandert
|
||||||
een tandwiel: die concurreerden eerder met de niveauknoppen om ruimte in
|
per opdracht. Niveau staat meestal vast (en is bij beheerd niveau zelfs
|
||||||
één brede rij, terwijl ze maar zelden worden aangepast */
|
uitgeschakeld), dus dat gaat samen met geluid/invoerwijze/aantal achter
|
||||||
|
het tandwiel in plaats van in de brede rij te concurreren om ruimte. */
|
||||||
|
const levels=document.createElement("div");levels.className="lg-levels";
|
||||||
|
levels.innerHTML=`<button data-l="1"></button><button data-l="2"></button><button data-l="3"></button>`;
|
||||||
const numSel=document.createElement("select");numSel.className="lg-num";
|
const numSel=document.createElement("select");numSel.className="lg-num";
|
||||||
const sndBtn=document.createElement("button");sndBtn.type="button";sndBtn.className="lg-snd";
|
const sndBtn=document.createElement("button");sndBtn.type="button";sndBtn.className="lg-snd";
|
||||||
const modeBtn=document.createElement("button");modeBtn.type="button";modeBtn.className="lg-mode";
|
const modeBtn=document.createElement("button");modeBtn.type="button";modeBtn.className="lg-mode";
|
||||||
el(".lg-top").insertAdjacentElement("beforebegin",widgetGear([
|
el(".lg-top").insertAdjacentElement("beforebegin",widgetGear([
|
||||||
gearField(T("sndWidget"),sndBtn),gearField(T("amode"),modeBtn),gearField(T("numWords"),numSel)
|
gearField(T("levelWidget"),levels),gearField(T("sndWidget"),sndBtn),gearField(T("amode"),modeBtn),gearField(T("numWords"),numSel)
|
||||||
]));
|
]));
|
||||||
/* card buttons (built dynamically: N cards + star + edit) */
|
/* card buttons (built dynamically: N cards + star + edit) */
|
||||||
function buildNumSel(){
|
function buildNumSel(){
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,6 @@ function mountMath(root, initState, mode, opts){
|
||||||
root.innerHTML = `
|
root.innerHTML = `
|
||||||
<div class="mt blocks">
|
<div class="mt blocks">
|
||||||
<div class="mt-top">
|
<div class="mt-top">
|
||||||
<div class="lg-levels">
|
|
||||||
<button data-l="1"></button><button data-l="2"></button><button data-l="3"></button>
|
|
||||||
</div>
|
|
||||||
<div class="mt-score"></div>
|
<div class="mt-score"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-card">
|
<div class="mt-card">
|
||||||
|
|
@ -54,9 +51,16 @@ function mountMath(root, initState, mode, opts){
|
||||||
fbEl.appendChild(cheer);
|
fbEl.appendChild(cheer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* niveau staat meestal vast (en is bij beheerd niveau uitgeschakeld), dus
|
||||||
|
dat gaat net als geluid/invoerwijze achter het tandwiel in plaats van
|
||||||
|
permanent ruimte te vragen naast de opgave zelf */
|
||||||
|
const levels=document.createElement("div");levels.className="lg-levels";
|
||||||
|
levels.innerHTML=`<button data-l="1"></button><button data-l="2"></button><button data-l="3"></button>`;
|
||||||
const sndBtn=document.createElement("button");sndBtn.type="button";sndBtn.className="lg-snd";
|
const sndBtn=document.createElement("button");sndBtn.type="button";sndBtn.className="lg-snd";
|
||||||
const modeBtn=document.createElement("button");modeBtn.type="button";modeBtn.className="lg-mode";
|
const modeBtn=document.createElement("button");modeBtn.type="button";modeBtn.className="lg-mode";
|
||||||
el(".mt-top").insertAdjacentElement("beforebegin",widgetGear([gearField(T("sndWidget"),sndBtn),gearField(T("amode"),modeBtn)]));
|
el(".mt-top").insertAdjacentElement("beforebegin",widgetGear([
|
||||||
|
gearField(T("levelWidget"),levels),gearField(T("sndWidget"),sndBtn),gearField(T("amode"),modeBtn)
|
||||||
|
]));
|
||||||
const mtEl = el(".mt"), qEl = el(".mt-q"), aEl = el(".mt-a"), fbEl = el(".mt-fb"),
|
const mtEl = el(".mt"), qEl = el(".mt-q"), aEl = el(".mt-a"), fbEl = el(".mt-fb"),
|
||||||
scoreEl = el(".mt-score"), doneEl = el(".mt-done"),
|
scoreEl = el(".mt-score"), doneEl = el(".mt-done"),
|
||||||
padEl = el(".mt-pad"), slotsEl = el(".mt-slots"), trayEl = el(".mt-tray");
|
padEl = el(".mt-pad"), slotsEl = el(".mt-slots"), trayEl = el(".mt-tray");
|
||||||
|
|
|
||||||
|
|
@ -521,8 +521,24 @@ function mountWorldQuiz(root,init,config){
|
||||||
const activity=worldSelect(S.activity,[["learn","worldLearn"],["quiz","worldQuiz"],["flash","worldFlash"],["spell","worldSpell"]]);
|
const activity=worldSelect(S.activity,[["learn","worldLearn"],["quiz","worldQuiz"],["flash","worldFlash"],["spell","worldSpell"]]);
|
||||||
const exercise=worldSelect(S.exercise,exerciseOptions);
|
const exercise=worldSelect(S.exercise,exerciseOptions);
|
||||||
const stage=document.createElement("div");
|
const stage=document.createElement("div");
|
||||||
|
/* activiteit en oefening kies je elke keer opnieuw, dus die staan in de
|
||||||
|
vaste bovenbalk; niveau staat meestal vast en gaat achter het tandwiel */
|
||||||
|
const activitySetting=field(T("worldActivity"),activity);
|
||||||
const exerciseSetting=field(T("worldExercise"),exercise);
|
const exerciseSetting=field(T("worldExercise"),exercise);
|
||||||
const settings=[field(T("worldActivity"),activity),exerciseSetting];
|
activitySetting.classList.add("top-field");
|
||||||
|
exerciseSetting.classList.add("top-field");
|
||||||
|
const levels=document.createElement("div");
|
||||||
|
levels.className="lg-levels world-levels";
|
||||||
|
const levelButtons=[1,2,3].map(value=>{
|
||||||
|
const button=document.createElement("button");
|
||||||
|
button.type="button";
|
||||||
|
button.textContent=T("lvl"+value);
|
||||||
|
button.title=T("worldLevel"+value+"Hint");
|
||||||
|
button.onclick=()=>chooseLevel(value);
|
||||||
|
levels.append(button);
|
||||||
|
return button;
|
||||||
|
});
|
||||||
|
const settings=[field(T("worldLevel"),levels)];
|
||||||
let view,viewSetting;
|
let view,viewSetting;
|
||||||
if(config.type==="trees"){
|
if(config.type==="trees"){
|
||||||
view=worldSelect(S.view,[["tree","worldTreeWhole"],["leaf","worldTreeLeaf"],["mixed","worldTreeMixed"]]);
|
view=worldSelect(S.view,[["tree","worldTreeWhole"],["leaf","worldTreeLeaf"],["mixed","worldTreeMixed"]]);
|
||||||
|
|
@ -587,29 +603,14 @@ function mountWorldQuiz(root,init,config){
|
||||||
S.activity=activity.value;
|
S.activity=activity.value;
|
||||||
S.exercise=exercise.value;
|
S.exercise=exercise.value;
|
||||||
if(view)S.view=view.value;
|
if(view)S.view=view.value;
|
||||||
exerciseSetting.hidden=S.activity!=="quiz";
|
|
||||||
if(viewSetting)viewSetting.hidden=S.activity==="quiz"&&!["recognize","photo"].includes(S.exercise);
|
if(viewSetting)viewSetting.hidden=S.activity==="quiz"&&!["recognize","photo"].includes(S.exercise);
|
||||||
stage.className="world-app";
|
stage.className="world-app";
|
||||||
stage.innerHTML="";
|
stage.innerHTML="";
|
||||||
const top=document.createElement("div");
|
const top=document.createElement("div");
|
||||||
top.className="world-top";
|
top.className="world-top";
|
||||||
const levelControl=document.createElement("div");
|
levelButtons.forEach((button,index)=>button.classList.toggle("active",S.level===index+1));
|
||||||
levelControl.className="world-level-control";
|
top.append(activitySetting);
|
||||||
const levelLabel=document.createElement("span");
|
if(S.activity==="quiz")top.append(exerciseSetting);
|
||||||
levelLabel.textContent=T("worldLevel");
|
|
||||||
const levels=document.createElement("div");
|
|
||||||
levels.className="lg-levels world-levels";
|
|
||||||
[1,2,3].forEach(value=>{
|
|
||||||
const button=document.createElement("button");
|
|
||||||
button.type="button";
|
|
||||||
button.textContent=T("lvl"+value);
|
|
||||||
button.title=T("worldLevel"+value+"Hint");
|
|
||||||
button.classList.toggle("active",S.level===value);
|
|
||||||
button.onclick=()=>chooseLevel(value);
|
|
||||||
levels.append(button);
|
|
||||||
});
|
|
||||||
levelControl.append(levelLabel,levels);
|
|
||||||
top.append(levelControl);
|
|
||||||
const title=document.createElement("strong");
|
const title=document.createElement("strong");
|
||||||
title.textContent=T("wg_"+config.type);
|
title.textContent=T("wg_"+config.type);
|
||||||
const score=document.createElement("span");
|
const score=document.createElement("span");
|
||||||
|
|
@ -950,6 +951,24 @@ function mountTopography(root,init){
|
||||||
const activity=worldSelect(S.activity,[["learn","worldLearn"],["quiz","worldQuiz"],["flash","worldFlash"],["spell","worldSpell"]]);
|
const activity=worldSelect(S.activity,[["learn","worldLearn"],["quiz","worldQuiz"],["flash","worldFlash"],["spell","worldSpell"]]);
|
||||||
const mode=worldSelect(S.mode,modeOptions);
|
const mode=worldSelect(S.mode,modeOptions);
|
||||||
const stage=document.createElement("div");
|
const stage=document.createElement("div");
|
||||||
|
/* activiteit en werkgebied kies je elke keer opnieuw, dus die staan in de
|
||||||
|
vaste bovenbalk; niveau staat meestal vast en gaat achter het tandwiel */
|
||||||
|
const activitySetting=field(T("worldActivity"),activity);
|
||||||
|
const modeSetting=field(T("topoMode"),mode);
|
||||||
|
activitySetting.classList.add("top-field");
|
||||||
|
modeSetting.classList.add("top-field");
|
||||||
|
const levels=document.createElement("div");
|
||||||
|
levels.className="lg-levels world-levels";
|
||||||
|
const levelButtons=[1,2,3].map(value=>{
|
||||||
|
const button=document.createElement("button");
|
||||||
|
button.type="button";
|
||||||
|
button.textContent=T("lvl"+value);
|
||||||
|
button.title=T("worldLevel"+value+"Hint");
|
||||||
|
button.onclick=()=>chooseLevel(value);
|
||||||
|
levels.append(button);
|
||||||
|
return button;
|
||||||
|
});
|
||||||
|
const levelField=field(T("worldLevel"),levels);
|
||||||
const pool=()=>{
|
const pool=()=>{
|
||||||
const items=S.mode==="provinces"?NL_PROVINCES
|
const items=S.mode==="provinces"?NL_PROVINCES
|
||||||
:S.mode==="capitals"?NL_CITIES.filter(item=>item.capital)
|
:S.mode==="capitals"?NL_CITIES.filter(item=>item.capital)
|
||||||
|
|
@ -992,25 +1011,9 @@ function mountTopography(root,init){
|
||||||
stage.innerHTML="";
|
stage.innerHTML="";
|
||||||
const top=document.createElement("div");
|
const top=document.createElement("div");
|
||||||
top.className="world-top";
|
top.className="world-top";
|
||||||
if(S.mode!=="regions"){
|
levelField.hidden=S.mode==="regions";
|
||||||
const levelControl=document.createElement("div");
|
levelButtons.forEach((button,index)=>button.classList.toggle("active",S.level===index+1));
|
||||||
levelControl.className="world-level-control";
|
top.append(activitySetting,modeSetting);
|
||||||
const levelLabel=document.createElement("span");
|
|
||||||
levelLabel.textContent=T("worldLevel");
|
|
||||||
const levels=document.createElement("div");
|
|
||||||
levels.className="lg-levels world-levels";
|
|
||||||
[1,2,3].forEach(value=>{
|
|
||||||
const button=document.createElement("button");
|
|
||||||
button.type="button";
|
|
||||||
button.textContent=T("lvl"+value);
|
|
||||||
button.title=T("worldLevel"+value+"Hint");
|
|
||||||
button.classList.toggle("active",S.level===value);
|
|
||||||
button.onclick=()=>chooseLevel(value);
|
|
||||||
levels.append(button);
|
|
||||||
});
|
|
||||||
levelControl.append(levelLabel,levels);
|
|
||||||
top.append(levelControl);
|
|
||||||
}
|
|
||||||
const title=document.createElement("strong");
|
const title=document.createElement("strong");
|
||||||
title.textContent=T("wg_topography");
|
title.textContent=T("wg_topography");
|
||||||
const score=document.createElement("span");
|
const score=document.createElement("span");
|
||||||
|
|
@ -1085,10 +1088,7 @@ function mountTopography(root,init){
|
||||||
const isTaskActivity=()=>["quiz","flash","spell"].includes(S.activity);
|
const isTaskActivity=()=>["quiz","flash","spell"].includes(S.activity);
|
||||||
activity.onchange=()=>{S.activity=activity.value;if(isTaskActivity())newTask();else draw()};
|
activity.onchange=()=>{S.activity=activity.value;if(isTaskActivity())newTask();else draw()};
|
||||||
mode.onchange=()=>{S.mode=mode.value;if(isTaskActivity())newTask();else draw()};
|
mode.onchange=()=>{S.mode=mode.value;if(isTaskActivity())newTask();else draw()};
|
||||||
learningShell(root,[
|
learningShell(root,[levelField],stage);
|
||||||
field(T("worldActivity"),activity),
|
|
||||||
field(T("topoMode"),mode),
|
|
||||||
],stage);
|
|
||||||
if(isTaskActivity())newTask();else draw();
|
if(isTaskActivity())newTask();else draw();
|
||||||
return{getState:()=>({...S})};
|
return{getState:()=>({...S})};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -164,7 +164,7 @@ test('analoge oefenklok is bedienbaar en houdt opdrachtacties buiten instellinge
|
||||||
const [source,css,core]=await Promise.all([readFile('public/js/widgets/learning.js','utf8'),readFile('public/css/teach.css','utf8'),readFile('public/js/core.js','utf8')]);
|
const [source,css,core]=await Promise.all([readFile('public/js/widgets/learning.js','utf8'),readFile('public/css/teach.css','utf8'),readFile('public/js/core.js','utf8')]);
|
||||||
for(const feature of ['onpointerdown','onpointermove','setPointerCapture','releasePointerCapture','getBoundingClientRect','clock-time-blocks','dotGrid'])assert.ok(source.includes(feature),feature);
|
for(const feature of ['onpointerdown','onpointermove','setPointerCapture','releasePointerCapture','getBoundingClientRect','clock-time-blocks','dotGrid'])assert.ok(source.includes(feature),feature);
|
||||||
assert.match(css,/clock\.interactive[^}]*touch-action:none/);
|
assert.match(css,/clock\.interactive[^}]*touch-action:none/);
|
||||||
assert.match(source,/learningShell\(root,\[field\(T\('clockLearningStyle'\),style\),field\(T\('clockGame'\),game\),linkSetting,hour24Setting\],stage\)/);
|
assert.match(source,/learningShell\(root,\[field\(T\('clockLevel'\),levels\),field\(T\('clockLearningStyle'\),style\),linkSetting,hour24Setting\],stage\)/);
|
||||||
const clockSource=source.slice(source.indexOf('function mountClock'),source.indexOf('function mountPlacevalue'));
|
const clockSource=source.slice(source.indexOf('function mountClock'),source.indexOf('function mountPlacevalue'));
|
||||||
assert.doesNotMatch(clockSource,/learningShell\(root,\[[^\]]*(?:numberlineCheck|numberlineNew|clockHour|clockMinute)/);
|
assert.doesNotMatch(clockSource,/learningShell\(root,\[[^\]]*(?:numberlineCheck|numberlineNew|clockHour|clockMinute)/);
|
||||||
for(const feature of ['answerDigits','clock-answer-slots','clock-block-tray','dragClone','droptarget',"'0123456789'.split('')",'clock-keypad',"S.amode==='blocks'?'🧱':'⌨️'"])assert.ok(clockSource.includes(feature),feature);
|
for(const feature of ['answerDigits','clock-answer-slots','clock-block-tray','dragClone','droptarget',"'0123456789'.split('')",'clock-keypad',"S.amode==='blocks'?'🧱':'⌨️'"])assert.ok(clockSource.includes(feature),feature);
|
||||||
|
|
@ -227,11 +227,11 @@ test('geldrekenen biedt drie niveaus, leerwijzen, spellen en directe bediening',
|
||||||
assert.ok(moneySource.includes("denominations=()=>levelRule().denominations"));
|
assert.ok(moneySource.includes("denominations=()=>levelRule().denominations"));
|
||||||
assert.ok(moneySource.includes("S.game==='change'"));
|
assert.ok(moneySource.includes("S.game==='change'"));
|
||||||
for(const feature of ['money-wallet','money-cash-tray','money-answer-slots','money-digit-tray','money-keypad','dragClone','droptarget','getBoundingClientRect','amountWords','money-piece-image','money-product-icon','money-product-name','money-level-hint'])assert.ok(moneySource.includes(feature),feature);
|
for(const feature of ['money-wallet','money-cash-tray','money-answer-slots','money-digit-tray','money-keypad','dragClone','droptarget','getBoundingClientRect','amountWords','money-piece-image','money-product-icon','money-product-name','money-level-hint'])assert.ok(moneySource.includes(feature),feature);
|
||||||
assert.ok(moneySource.includes("learningShell(root,[styleSetting,gameSetting,categorySetting],stage)"),'alleen voorkeuren staan onder instellingen');
|
assert.ok(moneySource.includes("learningShell(root,[field(T('moneyLevel'),levels),styleSetting],stage)"),'spel en categorie kies je elke keer opnieuw en staan dus zichtbaar; niveau staat achter instellingen');
|
||||||
assert.ok(moneySource.includes("style.onchange=draw"));
|
assert.ok(moneySource.includes("style.onchange=draw"));
|
||||||
assert.ok(moneySource.includes("game.onchange=()=>{S.game=game.value;syncSettings();newTask()}"));
|
assert.ok(moneySource.includes("game.onchange=()=>{S.game=game.value;syncSettings();newTask()}"));
|
||||||
assert.ok(moneySource.includes("category.onchange=()=>{S.category=category.value;newTask()}"));
|
assert.ok(moneySource.includes("category.onchange=()=>{S.category=category.value;newTask()}"));
|
||||||
assert.ok(moneySource.includes("categorySetting.hidden=S.game!=='change'"));
|
assert.ok(moneySource.includes("if(S.game==='change')top.append(categorySetting)"));
|
||||||
assert.doesNotMatch(moneySource,/learningShell\(root,\[[^\]]*(?:numberlineCheck|numberlineNew|moneyClear|moneyNextTask)/);
|
assert.doesNotMatch(moneySource,/learningShell\(root,\[[^\]]*(?:numberlineCheck|numberlineNew|moneyClear|moneyNextTask)/);
|
||||||
for(const key of ['moneyLearningStyle','moneyStyleAmount','moneyStyleWords','moneyStyleBoth','moneyGame','moneyGameMake','moneyGameCount','moneyGameChange','moneyLevel','moneyLevel1Hint','moneyLevel2Hint','moneyLevel3Hint','moneyScore','moneyMakeTitle','moneyCountTitle','moneyChangeTitle','moneyWallet','moneyTray','moneyBuildHint','moneyTypeHint','moneyCorrect','moneyNextTask','moneyRemove','moneyCategory','moneyCategoryAll','moneyCategoryFood','moneyCategorySchool','moneyCategoryPlay'])assert.equal((core.match(new RegExp(key+':','g'))||[]).length,2,key);
|
for(const key of ['moneyLearningStyle','moneyStyleAmount','moneyStyleWords','moneyStyleBoth','moneyGame','moneyGameMake','moneyGameCount','moneyGameChange','moneyLevel','moneyLevel1Hint','moneyLevel2Hint','moneyLevel3Hint','moneyScore','moneyMakeTitle','moneyCountTitle','moneyChangeTitle','moneyWallet','moneyTray','moneyBuildHint','moneyTypeHint','moneyCorrect','moneyNextTask','moneyRemove','moneyCategory','moneyCategoryAll','moneyCategoryFood','moneyCategorySchool','moneyCategoryPlay'])assert.equal((core.match(new RegExp(key+':','g'))||[]).length,2,key);
|
||||||
assert.match(css,/money-app\{[^}]*align-self:flex-start[^}]*justify-content:flex-start/);
|
assert.match(css,/money-app\{[^}]*align-self:flex-start[^}]*justify-content:flex-start/);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue