teach/public/js/data.js
Ramon ba4483d5d3
All checks were successful
dev - build & deploy naar test / build-and-deploy (push) Successful in 59s
feat: breid taalbibliotheek uit met 1000 woorden (v0.4.43-beta)
2026-07-21 18:50:47 +02:00

647 lines
43 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* teach - woorddata: algemene kaart, thema's, gedeelde woordbronnen */
/* =========================================================
Letter game data
==========================================================*/
const DOTCODE = {
a:[1], b:[1,2], c:[1,4], d:[1,4,5], e:[1,5], f:[1,2,4], g:[1,2,4,5], h:[1,2,5],
i:[2,4], j:[2,4,5], k:[1,3], l:[1,2,3], m:[1,3,4], n:[1,3,4,5], o:[1,3,5],
p:[1,2,3,4], q:[1,2,3,4,5], r:[1,2,3,5], s:[2,3,4], t:[2,3,4,5], u:[1,3,6],
v:[1,2,3,6], w:[2,4,5,6], x:[1,3,4,6], y:[1,3,4,5,6], z:[1,3,5,6]
};
/* cijferblokken gebruikten hiervoor de braille a-j-patronen, maar die
gebruiken nooit posities 3/6 (de onderste rij) - op een kind-oog leken
alle tien blokken daardoor op elkaar. Een eigen codetabel die alle zes
stippen inzet, geeft elk cijfer een echt eigen vorm. */
const DIGIT_DOTCODE = {
"0":[], "1":[2], "2":[2,5], "3":[1,2,3], "4":[1,3,4,6],
"5":[1,2,3,4,5], "6":[1,2,3,4,5,6], "7":[1,2,4,5], "8":[1,2,3,4,6], "9":[1,4,6]
};
/* Klassenmanagement (v0.4.34-beta e.v.): rekenen is het eerste vakgebied waarvan
de leerlijn direct in getalgrenzen te vertalen is (SLO/TULE: groep 3
automatiseert optellen/aftrekken t/m 20, groep 4 t/m 100, groep 5 t/m 1000,
groep 6 t/m 10.000 met de tafels verder uitgebouwd, groep 7-8 bouwen daarop
voort). math.js gebruikt dit als de daadwerkelijke inhoud zodra een leerling
een groep heeft (zie mathRangeFor hieronder) - zonder groep blijft het oude,
vaste 10/20/100-gedrag exact bestaan. */
const SLO_MATH_RANGES = {
1:{addSub:10, timesTable:5},
2:{addSub:10, timesTable:5},
3:{addSub:20, timesTable:5},
4:{addSub:100, timesTable:10},
5:{addSub:1000, timesTable:10},
6:{addSub:10000,timesTable:12},
7:{addSub:10000,timesTable:12},
8:{addSub:10000,timesTable:12},
};
/* niveau (1-3) is de verfijning BINNEN een groep - een breukdeel van de
groep-grens, nooit onder de kleinste bestaande standaardwaarde (10) of
onder tafel 3. Levert bij ontbrekend yearGroup expres geen waarde (math.js
valt dan terug op zijn eigen oude vaste 10/20/100-logica). */
function mathRangeFor(yearGroup, level){
if(yearGroup == null) return null;
const g = SLO_MATH_RANGES[Math.max(1, Math.min(8, +yearGroup || 1))];
if(!g) return null;
const frac = level===1 ? .25 : level===2 ? .6 : 1;
return {
addSub: Math.max(10, Math.round(g.addSub*frac/5)*5),
timesTable: Math.max(3, Math.round(g.timesTable*frac)),
};
}
const VOWELS = "aeiou";
function dotGrid(letter){
const code = (Object.prototype.hasOwnProperty.call(DIGIT_DOTCODE, letter) ? DIGIT_DOTCODE[letter] : DOTCODE[letter]) || [];
const grid = document.createElement("div");
grid.className = "dots";
[1,4,2,5,3,6].forEach(p=>{
const d = document.createElement("i");
d.className = code.includes(p) ? "on" : "off";
grid.appendChild(d);
});
return grid;
}
/* De taalplaatjes hebben één centrale bron. Daardoor gebruiken de spelletjes,
de themakiezer en de afbeeldingenbibliotheek altijd dezelfde woorden en
verdwijnen oude plaatjes niet wanneer de woordenschat wordt uitgebreid. */
const LANGUAGE_THEME_DEFS = [
{id:"animals", icon:"🐾", nl:"Dieren", en:"Animals", colors:["#eaf7df","#cdeeb5"]},
{id:"food", icon:"🍎", nl:"Eten & drinken", en:"Food & drink", colors:["#fff0dc","#ffd9aa"]},
{id:"nature", icon:"🌿", nl:"Natuur & weer", en:"Nature & weather", colors:["#e4f7ee","#bfead4"]},
{id:"travel", icon:"🚲", nl:"Onderweg", en:"Getting around", colors:["#e6f3ff","#beddf8"]},
{id:"home", icon:"🎒", nl:"Thuis & school", en:"Home & school", colors:["#f1ecff","#d9ccff"]},
{id:"body", icon:"👕", nl:"Lichaam & kleding", en:"Body & clothes", colors:["#ffeaf1","#ffcbdc"]},
{id:"actions", icon:"🏃", nl:"Doen", en:"Actions", colors:["#fff8d9","#f6e8a4"]},
{id:"feelings", icon:"🙂", nl:"Gevoelens", en:"Feelings", colors:["#e9f5ff","#c8e4fa"]},
{id:"people", icon:"👨‍👩‍👧", nl:"Mensen & familie", en:"People & family", colors:["#fff0f4","#ffd3df"]},
{id:"play", icon:"🏀", nl:"Spelen & sport", en:"Play & sports", colors:["#fff4dc","#ffdca8"]},
{id:"places", icon:"🏘️", nl:"Plekken & beroepen", en:"Places & jobs", colors:["#e8f3ff","#c9e2fb"]},
{id:"time", icon:"📅", nl:"Tijd & feest", en:"Time & celebrations", colors:["#f2edff","#ddd1ff"]},
{id:"arts", icon:"🎨", nl:"Kunst & muziek", en:"Arts & music", colors:["#fff0fa","#f4ccec"]},
{id:"science", icon:"🔬", nl:"Onderzoeken & techniek", en:"Science & technology", colors:["#e7f7f5","#bfe9e3"]},
{id:"learning", icon:"📚", nl:"Taal & rekenen", en:"Language & maths", colors:["#fff7df","#f3dfa6"]},
{id:"society", icon:"🌍", nl:"Samenleven & wereld", en:"Society & world", colors:["#e8f1ff","#c8daf7"]}
];
const LANGUAGE_CONCEPTS = [
["monkey","animals","aap","monkey","🐵"],
["cat","animals","kat","cat","🐈"],
["dog","animals","hond","dog","🐕"],
["fish","animals","vis","fish","🐟"],
["hen","animals","kip","hen","🐔"],
["mouse","animals","muis","mouse","🐭"],
["bear","animals","beer","bear","🐻"],
["duck","animals","eend","duck","🦆"],
["frog","animals","kikker","frog","🐸"],
["bee","animals","bij","bee","🐝"],
["cow","animals","koe","cow","🐄"],
["pig","animals","varken","pig","🐷"],
["owl","animals","uil","owl","🦉"],
["goat","animals","geit","goat","🐐"],
["hare","animals","haas","hare","🐇"],
["horse","animals","paard","horse","🐴"],
["lion","animals","leeuw","lion","🦁"],
["ant","animals","mier","ant","🐜"],
["egg","food","ei","egg","🥚"],
["apple","food","appel","apple","🍎"],
["pear","food","peer","pear","🍐"],
["cheese","food","kaas","cheese","🧀"],
["milk","food","melk","milk","🥛"],
["cake","food","taart","cake","🎂"],
["bread","food","brood","bread","🍞"],
["soup","food","soep","soup","🥣"],
["rice","food","rijst","rice","🍚"],
["corn","food","mais","corn","🌽"],
["grape","food","druif","grape","🍇"],
["strawberry","food","aardbei","strawberry","🍓"],
["candy","food","snoep","candy","🍬"],
["lemon","food","citroen","lemon","🍋"],
["pizza","food","pizza","pizza","🍕"],
["juice","food","sap","juice","🧃"],
["cookie","food","koek","cookie","🍪"],
["carrot","food","wortel","carrot","🥕"],
["sun","nature","zon","sun","☀️"],
["moon","nature","maan","moon","🌙"],
["star","nature","ster","star","⭐"],
["tree","nature","boom","tree","🌳"],
["rose","nature","roos","rose","🌹"],
["fire","nature","vuur","fire","🔥"],
["flower","nature","bloem","flower","🌷"],
["leaf","nature","blad","leaf","🍃"],
["cloud","nature","wolk","cloud","☁️"],
["rain","nature","regen","rain","🌧️"],
["snow","nature","sneeuw","snow","❄️"],
["water","nature","water","water","💧"],
["stone","nature","steen","stone","🪨"],
["sand","nature","zand","sand","🏖️"],
["sea","nature","zee","sea","🌊"],
["forest","nature","bos","forest","🌲"],
["grass","nature","gras","grass","🌱"],
["wind","nature","wind","wind","💨"],
["rainbow","nature","regenboog","rainbow","🌈"],
["car","travel","auto","car","🚗"],
["bike","travel","fiets","bike","🚲"],
["boat","travel","boot","boat","⛵"],
["train","travel","trein","train","🚂"],
["bus","travel","bus","bus","🚌"],
["taxi","travel","taxi","taxi","🚕"],
["truck","travel","vrachtauto","truck","🚚"],
["jet","travel","vliegtuig","plane","✈️"],
["tram","travel","tram","tram","🚋"],
["ship","travel","schip","ship","🚢"],
["rocket","travel","raket","rocket","🚀"],
["road","travel","weg","road","🛣️"],
["wheel","travel","wiel","wheel","🛞"],
["sail","travel","zeil","sail","⛵"],
["scooter","travel","step","scooter","🛴"],
["tractor","travel","tractor","tractor","🚜"],
["helicopter","travel","helikopter","helicopter","🚁"],
["house","home","huis","house","🏠"],
["book","home","boek","book","📕"],
["pen","home","pen","pen","🖊️"],
["pencil","home","potlood","pencil","✏️"],
["bag","home","tas","bag","🎒"],
["coat","home","jas","coat","🧥"],
["chair","home","stoel","chair","🪑"],
["bed","home","bed","bed","🛏️"],
["door","home","deur","door","🚪"],
["clock","home","klok","clock","⏰"],
["glasses","home","bril","glasses","👓"],
["ball","home","bal","ball","⚽"],
["doll","home","pop","doll","🪆"],
["block","home","blok","block","🧱"],
["key","home","sleutel","key","🔑"],
["lamp","home","lamp","lamp","💡"],
["cup","home","beker","cup","🥤"],
["brush","home","borstel","brush","🪥"],
["drum","home","trommel","drum","🥁"],
["gift","home","cadeau","gift","🎁"],
["paint","home","verf","paint","🎨"],
["scissors","home","schaar","scissors","✂️"],
["desk","home","bureau","desk","🗄️"],
["school","home","school","school","🏫"],
["hand","body","hand","hand","✋"],
["foot","body","voet","foot","🦶"],
["nose","body","neus","nose","👃"],
["eye","body","oog","eye","👁️"],
["ear","body","oor","ear","👂"],
["mouth","body","mond","mouth","👄"],
["hair","body","haar","hair","🧑‍🦱"],
["head","body","hoofd","head","🙂"],
["arm","body","arm","arm","💪"],
["leg","body","been","leg","🦵"],
["cap","body","pet","cap","🧢"],
["sock","body","sok","sock","🧦"],
["shoe","body","schoen","shoe","👟"],
["dress","body","jurk","dress","👗"],
["shirt","body","shirt","shirt","👕"],
["glove","body","want","glove","🧤"],
["pants","body","broek","trousers","👖"],
["skirt","body","rok","skirt","👗"],
["tooth","body","tand","tooth","🦷"],
["read","actions","lezen","read","📖"],
["eat","actions","eten","eat","🍽️"],
["drink","actions","drinken","drink","🥤"],
["sleep","actions","slapen","sleep","😴"],
["walk","actions","lopen","walk","🚶"],
["swim","actions","zwemmen","swim","🏊"],
["jump","actions","springen","jump","🤸"],
["laugh","actions","lachen","laugh","😄"],
["cry","actions","huilen","cry","😢"],
["sing","actions","zingen","sing","🎤"],
["dance","actions","dansen","dance","💃"],
["draw","actions","tekenen","draw","🖍️"],
["write","actions","schrijven","write","✍️"],
["play","actions","spelen","play","🧸"],
["sit","actions","zitten","sit","🧎"],
["run","actions","rennen","run","🏃"],
["climb","actions","klimmen","climb","🧗"],
["wave","actions","zwaaien","wave","👋"],
["look","actions","kijken","look","👀"],
["think","actions","denken","think","🤔"],
["happy","feelings","blij","happy","😀"],
["sad","feelings","verdrietig","sad","😢"],
["angry","feelings","boos","angry","😠"],
["scared","feelings","bang","scared","😨"],
["tired","feelings","moe","tired","🥱"],
["sick","feelings","ziek","sick","🤒"],
["proud","feelings","trots","proud","😌"],
["calm","feelings","rustig","calm","🙂"],
["surprised","feelings","verrast","surprised","😮"],
["excited","feelings","enthousiast","excited","🤩"],
["bird","animals","vogel","bird","🐦"],
["rabbit","animals","konijn","rabbit","🐰"],
["fox","animals","vos","fox","🦊"],
["butterfly","animals","vlinder","butterfly","🦋"],
["snail","animals","slak","snail","🐌"],
["ladybird","animals","lieveheersbeestje","ladybird","🐞"],
["spider","animals","spin","spider","🕷️"],
["turtle","animals","schildpad","turtle","🐢"],
["dolphin","animals","dolfijn","dolphin","🐬"],
["elephant","animals","olifant","elephant","🐘"],
["giraffe","animals","giraf","giraffe","🦒"],
["sheep","animals","schaap","sheep","🐑"],
["banana","food","banaan","banana","🍌"],
["orange","food","sinaasappel","orange","🍊"],
["watermelon","food","watermeloen","watermelon","🍉"],
["cherry","food","kers","cherry","🍒"],
["tomato","food","tomaat","tomato","🍅"],
["potato","food","aardappel","potato","🥔"],
["pancake","food","pannenkoek","pancake","🥞"],
["honey","food","honing","honey","🍯"],
["chocolate","food","chocolade","chocolate","🍫"],
["ice","food","ijs","ice","🍦"],
["sandwich","food","boterham","sandwich","🥪"],
["yoghurt","food","yoghurt","yoghurt","🥣"],
["mountain","nature","berg","mountain","⛰️"],
["island","nature","eiland","island","🏝️"],
["beach","nature","strand","beach","🏖️"],
["river","nature","rivier","river","🏞️"],
["lightning","nature","bliksem","lightning","⚡"],
["fog","nature","mist","fog","🌫️"],
["autumn","nature","herfst","autumn","🍂"],
["spring","nature","lente","spring","🌼"],
["summer","nature","zomer","summer","🌞"],
["winter","nature","winter","winter","⛄"],
["seed","nature","zaad","seed","🌰"],
["motorcycle","travel","motor","motorcycle","🏍️"],
["ambulance","travel","ambulance","ambulance","🚑"],
["firetruck","travel","brandweerauto","firetruck","🚒"],
["policecar","travel","politieauto","policecar","🚓"],
["subway","travel","metro","subway","🚇"],
["canoe","travel","kano","canoe","🛶"],
["bridge","travel","brug","bridge","🌉"],
["tunnel","travel","tunnel","tunnel","🚇"],
["trafficlight","travel","stoplicht","trafficlight","🚦"],
["station","travel","station","station","🚉"],
["airport","travel","vliegveld","airport","🛫"],
["mirror","home","spiegel","mirror","🪞"],
["sofa","home","bank","sofa","🛋️"],
["toilet","home","wc","toilet","🚽"],
["shower","home","douche","shower","🚿"],
["broom","home","bezem","broom","🧹"],
["spoon","home","lepel","spoon","🥄"],
["fork","home","vork","fork","🍴"],
["plate","home","bord","plate","🍽️"],
["computer","home","computer","computer","💻"],
["phone","home","telefoon","phone","📱"],
["window","home","raam","window","🪟"],
["finger","body","vinger","finger","☝️"],
["thumb","body","duim","thumb","👍"],
["knee","body","knie","knee","🦵"],
["heart","body","hart","heart","❤️"],
["brain","body","hersenen","brain","🧠"],
["bone","body","bot","bone","🦴"],
["tongue","body","tong","tongue","👅"],
["blood","body","bloed","blood","🩸"],
["hat","body","hoed","hat","👒"],
["boot","body","laars","boot","🥾"],
["scarf","body","sjaal","scarf","🧣"],
["cook","actions","koken","cook","🧑‍🍳"],
["bake","actions","bakken","bake","🧁"],
["cycle","actions","fietsen","cycle","🚴"],
["drive","actions","rijden","drive","🚙"],
["open","actions","openen","open","📂"],
["close","actions","sluiten","close","📕"],
["wash","actions","wassen","wash","🧼"],
["help","actions","helpen","help","🤝"],
["listen","actions","luisteren","listen","👂"],
["smell","actions","ruiken","smell","👃"],
["shy","feelings","verlegen","shy","😊"],
["curious","feelings","nieuwsgierig","curious","🧐"],
["confused","feelings","verward","confused","😕"],
["lonely","feelings","eenzaam","lonely","😔"],
["friendly","feelings","vriendelijk","friendly","🙂"],
["brave","feelings","dapper","brave","🦸"],
["jealous","feelings","jaloers","jealous","😒"],
["bored","feelings","verveeld","bored","🥱"],
["relieved","feelings","opgelucht","relieved","😌"],
["silly","feelings","grappig","silly","🤪"],
["baby","people","baby","baby","👶"],
["child","people","kind","child","🧒"],
["boy","people","jongen","boy","👦"],
["girl","people","meisje","girl","👧"],
["mother","people","moeder","mother","👩"],
["father","people","vader","father","👨"],
["sister","people","zus","sister","👧"],
["brother","people","broer","brother","👦"],
["grandmother","people","oma","grandmother","👵"],
["grandfather","people","opa","grandfather","👴"],
["family","people","familie","family","👨‍👩‍👧‍👦"],
["friend","people","vriend","friend","🧑‍🤝‍🧑"],
["teacher","people","leerkracht","teacher","🧑‍🏫"],
["pupil","people","leerling","pupil","🧑‍🎓"],
["neighbor","people","buur","neighbor","🏘️"],
["woman","people","vrouw","woman","👩"],
["man","people","man","man","👨"],
["person","people","mens","person","🧑"],
["twins","people","tweeling","twins","👯"],
["group","people","groep","group","👥"],
["football","play","voetbal","football","⚽"],
["basketball","play","basketbal","basketball","🏀"],
["tennis","play","tennis","tennis","🎾"],
["hockey","play","hockey","hockey","🏑"],
["volleyball","play","volleybal","volleyball","🏐"],
["skating","play","schaatsen","skating","⛸️"],
["ski","play","ski","ski","🎿"],
["cycling","play","wielrennen","cycling","🚴"],
["running","play","hardlopen","running","🏃"],
["playground","play","speeltuin","playground","🛝"],
["bowling","play","bowlen","bowling","🎳"],
["slide","play","glijbaan","slide","🛝"],
["kite","play","vlieger","kite","🪁"],
["puzzle","play","puzzel","puzzle","🧩"],
["game","play","spel","game","🎮"],
["dice","play","dobbelsteen","dice","🎲"],
["marble","play","knikker","marble","🔵"],
["teddy","play","knuffel","teddy","🧸"],
["cards","play","kaarten","cards","🃏"],
["chess","play","schaken","chess","♟️"],
["medal","play","medaille","medal","🏅"],
["shop","places","winkel","shop","🏪"],
["bakery","places","bakkerij","bakery","🥐"],
["hospital","places","ziekenhuis","hospital","🏥"],
["doctor","places","dokter","doctor","🧑‍⚕️"],
["police","places","politie","police","👮"],
["firefighter","places","brandweer","firefighter","🧑‍🚒"],
["farm","places","boerderij","farm","🏡"],
["farmer","places","boer","farmer","🧑‍🌾"],
["library","places","bibliotheek","library","📚"],
["librarian","places","bibliothecaris","librarian","📚"],
["park","places","park","park","🏞️"],
["zoo","places","dierentuin","zoo","🦒"],
["museum","places","museum","museum","🏛️"],
["restaurant","places","restaurant","restaurant","🍽️"],
["kitchen","places","keuken","kitchen","🍳"],
["classroom","places","klas","classroom","🏫"],
["office","places","kantoor","office","🏢"],
["garage","places","garage","garage","🚗"],
["postman","places","postbode","postman","📬"],
["nurse","places","verpleegkundige","nurse","🧑‍⚕️"],
["dentist","places","tandarts","dentist","🦷"],
["builder","places","bouwer","builder","👷"],
["chef","places","kok","chef","🧑‍🍳"],
["hairdresser","places","kapper","hairdresser","💇"],
["market","places","markt","market","🛍️"],
["city","places","stad","city","🏙️"],
["village","places","dorp","village","🏘️"],
["church","places","kerk","church","⛪"],
["pool","places","zwembad","pool","🏊"],
["morning","time","ochtend","morning","🌅"],
["afternoon","time","middag","afternoon","🌤️"],
["evening","time","avond","evening","🌇"],
["night","time","nacht","night","🌙"],
["today","time","vandaag","today","📅"],
["tomorrow","time","morgen","tomorrow","➡️"],
["yesterday","time","gisteren","yesterday","⬅️"],
["day","time","dag","day","☀️"],
["week","time","week","week","🗓️"],
["month","time","maand","month","📆"],
["year","time","jaar","year","🎆"],
["birthday","time","verjaardag","birthday","🎂"],
["party","time","feest","party","🥳"],
["candle","time","kaars","candle","🕯️"],
["balloon","time","ballon","balloon","🎈"],
["flag","time","vlag","flag","🚩"],
["crown","time","kroon","crown","👑"],
["christmas","time","kerst","christmas","🎄"],
["easter","time","pasen","easter","🐣"],
["garland","time","slinger","garland","🎊"],
["calendar","time","kalender","calendar","📅"],
["hour","time","uur","hour","🕐"],
["minute","time","minuut","minute","⏱️"],
["season","time","seizoen","season","🍁"]
].map(([id,theme,nl,en,pic])=>({id,theme,nl,en,pic}));
/* Ruim duizend aanvullende Nederlandse woorden, geordend in woordfamilies.
Iedere regel loopt bewust van een kort, concreet basiswoord naar langere
afleidingen, samenstellingen en schooltaal. De positie op de regel bepaalt
het eerste leerjaar waarin het woord wordt aangeboden; hogere leerjaren
behouden de eerder aangeboden woorden. Woorden die al in LANGUAGE_CONCEPTS
staan worden hieronder automatisch overgeslagen. */
const LANGUAGE_NL_PROGRESSION_FAMILIES={
animals:"🐈|kat,poes,kitten,kater,katten,poesje,kattenbak,kattenvoer,huiskat,kattenluik,zwerfkat,kattenkwaad\n🐕|hond,pup,reu,teef,honden,pupje,hondenhok,hondenriem,waakhond,hondensport,geleidehond,hondenbezitter\n🐴|paard,pony,veulen,merrie,hengst,paardenstal,paardrijden,renpaard,paardensprong,paardentrailer,paardenverzorging,paardrijwedstrijd\n🐦|vogel,mus,merel,kraai,duif,nestje,vogelvoer,zangvogel,trekvogel,vogelkooi,vogelkenner,vogelbescherming\n🐟|vis,karper,baars,haai,rog,visje,vijvervis,zeedier,visnet,vissersboot,onderwaterdier,waterdierenverblijf\n🐞|mier,bij,wesp,kever,vlinder,rups,insectenhotel,bijenkorf,sprinkhaan,lieveheersbeestje,insectenkenner,insectenonderzoek\n🐄|koe,kalf,geit,schaap,varken,lammetje,kippenhok,melkkoe,boerderijdier,dierenweide,dierenverzorger,veehouderij",
food:"🍞|brood,bol,toast,korst,kruimel,broodje,volkorenbrood,broodmes,bakkerij,broodbeleg,broodtrommel,broodbereiding\n🍎|fruit,appel,peer,pruim,kers,appeltje,fruitsap,fruitmand,boomgaard,vruchtvlees,fruitsoorten,fruitteeltbedrijf\n🥛|melk,karnemelk,room,boter,vla,melkpak,melkglas,zuivel,melkboer,melkproduct,zuivelfabriek,voedingsmiddel\n🧀|kaas,brie,gaten,plak,korst,kaasje,kaasplank,kaasschaaf,kaaswinkel,smeerkaas,kaasbereiding,zuivelproduct\n🥔|aardappel,friet,puree,schil,knol,pieper,aardappelmes,stamppot,aardappelveld,aardappelplant,aardappelgerecht,aardappelverwerking\n🥕|groente,wortel,prei,kool,boon,erwtje,groentesoep,snijplank,moestuin,groentekraam,groentesoorten,groentegerecht\n🍰|taart,koek,snoep,cake,wafel,gebakje,slagroom,taartpunt,bakvorm,koekjesdeeg,feestmaaltijd,suikergehalte",
nature:"🌳|boom,stam,tak,blad,wortel,boompje,boomschors,boomkroon,loofboom,naaldboom,boomsoorten,bomenonderzoek\n🌷|bloem,roos,tulp,stengel,knop,bloempje,bloempot,bloembol,boeket,zonnebloem,bloemenweide,bloembestuiving\n💧|water,druppel,plas,sloot,beek,waterkant,drinkwater,waterput,grondwater,waterleiding,waterzuivering,waterkringloop\n☀|zon,maan,ster,licht,schaduw,zonnetje,zonlicht,maansikkel,sterrenhemel,zonsopgang,zonnestraling,sterrenstelsel\n🌧|regen,wolk,wind,mist,bui,regendruppel,regenjas,wolkbreuk,weersbericht,regenboog,neerslaggebied,weersverwachting\n❄|sneeuw,ijs,vorst,hagel,vlok,sneeuwpop,ijskoud,sneeuwbal,winterweer,sneeuwstorm,temperatuurdaling,winterlandschap\n🌱|aarde,grond,zaad,kiem,plant,zaadje,potgrond,plantengroei,bodemlaag,bodemvruchtbaarheid,voedingsstoffen,kiemingsproces",
travel:"🚗|auto,bus,taxi,rit,band,autootje,autodeur,autoruit,parkeerplek,autoweg,automobilist,verkeersveiligheid\n🚲|fiets,step,pedaal,bel,stuur,fietsje,fietspad,fietspomp,bakfiets,fietstocht,fietsenmaker,fietsverlichting\n🚂|trein,tram,rail,spoor,rit,treintje,perron,station,spoorlijn,treinreis,treinmachinist,spoorwegovergang\n⛵|boot,schip,kano,zeil,roeispaan,bootje,zeilboot,reddingsboei,haven,scheepsdek,binnenvaartschip,scheepvaartverkeer\n✈|vliegtuig,jet,vleugel,piloot,vlucht,vliegveld,landingsbaan,luchtvaart,vliegreis,verkeerstoren,passagiersvliegtuig,luchtvaartmaatschappij\n🛣|weg,pad,brug,tunnel,bocht,wegdek,kruispunt,rotonde,rijbaan,wegwijzer,infrastructuur,verkeersknooppunt\n🚦|licht,bord,streep,file,route,stoplicht,verkeersbord,zebrapad,voorrang,weggebruiker,verkeersregelaar,verkeerssituatie",
home:"🏠|huis,flat,hut,dak,muur,huisje,voordeur,woonkamer,rijtjeshuis,woonwijk,huizenblok,woninginrichting\n🛏|bed,kast,lamp,deken,kussen,bedje,nachtkast,bedlamp,slaapkamer,dekbedovertrek,slaapvertrek,slaapkamerraam\n🪑|stoel,tafel,bank,kruk,kast,stoeltje,tafelblad,eettafel,boekenkast,stoelzitting,meubelwinkel,woonkamermeubel\n🚪|deur,raam,slot,sleutel,bel,deurtje,deurklink,vensterbank,raamkozijn,voordeurbel,inbraakbeveiliging,toegangssysteem\n🍳|pan,pot,kom,bord,lepel,pannetje,koekenpan,keukenkast,aanrecht,afwasborstel,keukengerei,voedselbereiding\n🚿|bad,douche,wc,kraan,zeep,badje,handdoek,wastafel,badkamer,tandenborstel,waterbesparing,badkamertegel\n🧹|stof,vuil,bezem,dweil,spons,stofdoek,afwasmiddel,prullenbak,schoonmaak,schoonmaker,schoonmaakmiddel,huishoudelijkehulp",
body:"✋|hand,duim,vinger,nagel,pols,handje,vingertop,handpalm,wijsvinger,vingerafdruk,handbeweging,handvaardigheid\n🦶|voet,teen,hiel,enkel,knie,voetje,voetzool,knieschijf,onderbeen,voetstap,lichaamshouding,bewegingsapparaat\n🙂|hoofd,wang,kin,nek,keel,hoofdje,voorhoofd,achterhoofd,gezicht,gezichtsvorm,gelaatsuitdrukking,hoofdbescherming\n👁|oog,oor,neus,mond,lip,oogje,ooglid,neusgat,wenkbrauw,zintuig,gehoororgaan,waarnemingsvermogen\n🦷|tand,kies,tong,speeksel,gebit,tandje,tandvlees,tandenborstel,tandarts,mondzorg,tandheelkunde,gebitsverzorging\n👕|jas,shirt,trui,broek,rok,jasje,regenbroek,winterjas,kledingkast,kledingmaat,kledingstuk,kledingindustrie\n❤|hart,long,bloed,bot,spier,hartslag,bloedvat,longinhoud,skelet,spierkracht,bloedsomloop,ademhalingsstelsel",
actions:"🚶|gaan,lopen,stap,staan,zitten,wandelen,voetstap,doorlopen,oversteken,vooruitgaan,verplaatsing,bewegingsrichting\n🏃|rennen,racen,sprinten,haasten,vluchten,hardlopen,renbaan,wedloop,marathon,snelheidsmeter,hardloopwedstrijd,uithoudingsvermogen\n🤸|springen,hupsen,bukken,rollen,draaien,sprongetje,springtouw,koprol,evenwicht,lichaamsbeweging,bewegingsreeks,bewegingsoefening\n📖|lezen,boek,blad,zin,tekst,leesboek,voorlezen,leesbril,leeshoek,leesstrategie,leesvaardigheid,tekstinterpretatie\n✍|schrijven,pen,schrift,letter,woord,opschrijven,handschrift,schrijfboek,schrijfregel,schrijfopdracht,schrijfvaardigheid,tekstproductie\n🗣|praten,zeggen,vragen,roepen,fluisteren,vertellen,spreekbeurt,gesprek,uitspraak,woordkeuze,taalgebruik,gespreksvaardigheid\n🤝|helpen,delen,geven,halen,brengen,hulpje,samenwerken,meehelpen,ondersteunen,hulpverlening,samenwerkingsvorm,verantwoordelijkheid",
feelings:"😀|blij,leuk,fijn,lachen,vrolijk,glimlach,plezier,opgewekt,tevreden,blijheid,enthousiasme,geluksgevoel\n😢|sip,moe,verdriet,pijn,huilen,traantje,teleurgesteld,verdrietig,somber,eenzaamheid,teleurstelling,verdrietverwerking\n😠|boos,kwaad,ruzie,mopperen,grommen,boosheid,driftig,prikkelbaar,woedend,meningsverschil,frustratie,conflictbeheersing\n😨|bang,eng,schrik,zorgen,trillen,angstig,schrikken,onzeker,bezorgd,angstgevoel,onveiligheid,zelfbescherming\n🙂|rust,kalm,stil,zacht,ademen,rustig,ontspannen,geduldig,vertrouwd,ontspanning,zelfbeheersing,ademhalingsoefening\n😌|trots,dapper,sterk,durven,winnen,trotsheid,moedig,zelfstandig,zelfvertrouwen,doorzetter,doorzettingsvermogen,zelfwaardering\n🤩|nieuw,raar,wauw,vragen,kijken,verrast,benieuwd,nieuwsgierig,verwondering,belangstelling,onderzoekshouding,ontdekkingsvreugde",
people:"👨‍👩‍👧|familie,gezin,kind,baby,ouders,gezinnetje,familielid,stiefouder,grootouder,familieband,gezinssituatie,familiegeschiedenis\n👩|mama,moeder,vrouw,tante,dochter,moedertje,schoonmoeder,moederdag,moederfiguur,moederschap,ouderverzorging,gezinsverantwoordelijkheid\n👨|papa,vader,man,oom,zoon,vadertje,schoonvader,vaderdag,vaderfiguur,vaderschap,oudercontact,opvoedingsverantwoordelijkheid\n🧒|kind,jongen,meisje,kleuter,puber,kindje,schoolkind,leeftijdgenoot,jeugd,ontwikkeling,kinderrechten,identiteitsontwikkeling\n🧑🤝🧑|vriend,maat,buur,gast,club,vriendje,vriendschap,buurkind,kennismaking,groepsgenoot,vertrouwenspersoon,vriendschapsrelatie\n🧑🏫|juf,meester,leraar,mentor,coach,leerkracht,lesgever,schoolteam,begeleider,onderwijsassistent,onderwijsprofessional,leerlingbegeleiding\n👥|groep,team,klas,paar,kring,groepje,klasgenoot,teamlid,samenkomst,groepswerk,groepsvorming,groepsdynamiek",
play:"⚽|bal,doel,trap,team,veld,balletje,voetbal,doelman,wedstrijd,voetballer,voetbaltraining,competitiewedstrijd\n🏀|basket,korf,worp,score,punt,gooien,basketbal,dribbelen,balbezit,teamsport,sportvereniging,wedstrijdreglement\n🧩|puzzel,stuk,vorm,rand,plaat,puzzelstuk,legpuzzel,denkspel,oplossing,puzzelboek,probleemoplossing,denkstrategie\n🧸|pop,beer,blok,trein,auto,popje,knuffel,bouwblok,speelgoed,speelkamer,speelgoedwinkel,fantasiespel\n🎲|spel,beurt,dobbelsteen,kaart,pion,spelletje,spelregel,bordspel,tegenstander,winnaar,spelstrategie,gezelschapsspel\n🏊|zwemmen,duiken,bad,plons,slag,zwemband,zwembad,schoolslag,duikplank,zwemles,zwemvaardigheid,waterveiligheid\n🏅|sport,spel,prijs,beker,medaille,sporter,sportdag,training,kampioen,sportprestatie,sportiviteit,wedstrijdorganisatie",
places:"🏫|school,klas,plein,les,gym,schooltje,schoolbank,schoolplein,schoolgebouw,schooljaar,schoolorganisatie,onderwijsomgeving\n🏪|winkel,kassa,kar,mand,klant,winkeltje,winkelier,winkelstraat,boodschap,winkelcentrum,klantenservice,detailhandel\n🏥|arts,dokter,bed,zaal,zorg,ziekenhuis,verpleegkundige,wachtkamer,behandeling,zorgverlening,gezondheidszorg,ziekenhuisafdeling\n🏡|boer,stal,schuur,land,erf,boerderij,landbouwer,akkerbouw,boerenbedrijf,landbouwgrond,landbouwmachine,voedselproductie\n📚|boek,kast,balie,pas,lezer,bibliotheek,boekenkast,bibliothecaris,uitleentermijn,boekenafdeling,informatiedienst,mediatheekbeheer\n🏙|stad,dorp,straat,plein,buurt,stadje,dorpsplein,woonplaats,stadscentrum,gemeentehuis,stedelijkgebied,bevolkingsdichtheid\n🏞|park,bos,veld,pad,vijver,parkje,speelweide,natuurpark,wandelroute,recreatiegebied,landschapsbeheer,natuurvoorziening",
time:"☀️|dag,uur,tijd,klok,middag,dagje,daglicht,dagdeel,dagritme,tijdstip,dagindeling,tijdswaarneming\n🌅|ochtend,vroeg,wakker,ontbijt,zonsopgang,ochtendlicht,ochtendritueel,schoolochtend,dagbegin,ochtendspits,ochtendprogramma,ochtendactiviteit\n🌇|avond,laat,eten,donker,zonsondergang,avondlicht,avondeten,bedtijd,dagafsluiting,avondprogramma,avondschemering,avondvoorstelling\n🗓|week,maand,jaar,datum,agenda,weekje,weekdag,maandblad,jaartal,kalenderjaar,tijdrekening,kalenderindeling\n🎂|feest,taart,kaars,cadeau,ballon,feestje,verjaardag,feestmuts,feestdag,uitnodiging,feestversiering,verjaardagsviering\n🍂|lente,zomer,herfst,winter,seizoen,lentebloem,zomerdag,herfstblad,winterjas,seizoenswissel,jaargetijde,seizoensverschijnsel\n⏱|minuut,seconde,kwart,half,duur,minuutje,tijdsduur,stopwatch,kwartier,wachttijd,tijdseenheid,tijdsberekening",
arts:"🎨|kleur,verf,kwast,doek,palet,kleurtje,verfpot,schilderen,schilderij,kunstschilder,kleurgebruik,schildertechniek\n🖍|tekening,lijn,vorm,punt,vak,tekenen,kleurplaat,schetsboek,omtrek,tekenmateriaal,beeldverhaal,illustratietechniek\n🎵|toon,lied,stem,klank,maat,liedje,muziek,nootbalk,melodie,muzikant,muziekstuk,muziekuitvoering\n🥁|trom,fluit,snaar,toets,bel,trommel,instrument,gitaarspel,slagwerk,muziekles,muziekinstrument,instrumentenfamilie\n💃|dans,stap,sprong,draai,pas,dansje,dansvloer,dansgroep,choreografie,dansvoorstelling,bewegingspatroon,podiumkunst\n🎭|toneel,rol,pak,tekst,podium,toneelstuk,acteur,optreden,voorstelling,toneelspeler,podiumverlichting,theatervoorstelling\n📷|foto,film,beeld,lens,flits,fotootje,camera,fotoboek,filmopname,fotograaf,beeldbewerking,mediaproductie",
science:"🔍|kijken,zoeken,vraag,vondst,spoor,onderzoek,waarnemen,vergrootglas,ontdekking,onderzoeker,waarneming,onderzoeksresultaat\n🧪|proef,test,buis,stof,mengen,proefje,reactie,meetglas,experiment,laboratorium,proefopstelling,onderzoeksverslag\n🧲|magneet,ijzer,pool,kracht,veld,aantrekken,afstoten,magnetisch,kompasnaald,magneetkracht,magnetisme,natuurverschijnsel\n⚙|wiel,as,tand,veer,hefboom,tandwiel,overbrenging,mechaniek,machine,werktuig,bewegingsenergie,machinewerking\n💡|licht,stroom,draad,lamp,stekker,schakelaar,batterij,stroomkring,elektrisch,elektriciteit,energieverbruik,energievoorziening\n💻|computer,muis,toets,scherm,bestand,computerprogramma,toetsenbord,beeldscherm,digitaal,internet,programmeren,informatietechnologie\n🚀|ruimte,maan,planeet,ster,raket,ruimtevaart,satelliet,heelal,astronaut,zonnestelsel,ruimtestation,ruimteonderzoek",
learning:"🔤|letter,klank,woord,naam,teken,alfabet,lettergreep,klinker,medeklinker,lettervolgorde,klankstructuur,spellingspatroon\n📝|zin,punt,komma,vraag,tekst,zinnetje,hoofdletter,leesteken,zinsdeel,zinsbouw,tekstverband,taalbeschouwing\n📖|boek,blad,kaft,titel,prent,boekje,hoofdstuk,inhoudsopgave,schrijver,boekbespreking,literatuur,leeservaring\n🗣|taal,stem,spraak,gesprek,verhaal,vertellen,luisteraar,spreker,spreekbeurt,gespreksregel,taalgebruik,communicatievaardigheid\n🔢|nul,een,twee,drie,getal,cijfer,reeks,getallenlijn,getalbeeld,plaatswaarde,getalstructuur,getalnotatie\n|som,plus,min,keer,delen,optellen,aftrekken,uitkomst,bewerking,rekenregel,rekenstrategie,bewerkingsvolgorde\n📐|vorm,lijn,hoek,vlak,lengte,driehoek,rechthoek,meetlat,oppervlakte,omtrekberekening,meetinstrument,meetkundigevorm",
society:"🤝|samen,hulp,beurt,afspraak,regel,samenwerken,overleggen,taakverdeling,deelname,samenleving,samenwerkingsverband,maatschappijleer\n🏘|buurt,wijk,dorp,stad,straat,buurthuis,woonwijk,gemeente,provincie,stadsbestuur,gemeenteraad,gebiedsindeling\n🌍|wereld,land,zee,kaart,grens,wereldbol,landkaart,continent,werelddeel,bevolking,wereldbevolking,wereldburgerschap\n🗺|noord,zuid,oost,west,plek,richting,kompas,kaartteken,plattegrond,schaalverdeling,herkenningspunt,kaartvaardigheid\n📰|nieuws,krant,bericht,radio,media,nieuwsblad,journalist,nieuwsbron,actualiteit,nieuwsbericht,betrouwbaarheid,mediageletterdheid\n♻|afval,bak,glas,papier,natuur,recyclen,hergebruik,afvalbak,milieuzorg,afvalscheiding,duurzaamheid,grondstoffengebruik\n⚖|recht,plicht,keus,stem,wet,eerlijk,verkiezing,mening,besluit,democratie,grondrecht,besluitvorming"
};
const LANGUAGE_PROGRESSION_YEARS=[1,2,3,3,4,5,5,6,7,8,7,8];
const LANGUAGE_NL_PROGRESSION_WORDS=(()=>{
const seen=new Set(LANGUAGE_CONCEPTS.map(item=>item.nl)),out=[];
Object.entries(LANGUAGE_NL_PROGRESSION_FAMILIES).forEach(([theme,rows])=>rows.split("\n").forEach(row=>{
const [pic,list]=row.split("|");let familyPosition=0;
list.split(",").forEach(raw=>{
const word=raw.trim();if(!word||seen.has(word))return;seen.add(word);
const slug=word.normalize("NFD").replace(/[\u0300-\u036f]/g,"").replace(/[^a-z]/g,"");
const yearGroup=LANGUAGE_PROGRESSION_YEARS[Math.min(familyPosition++,LANGUAGE_PROGRESSION_YEARS.length-1)];
out.push({id:"nl-"+theme+"-"+slug,theme,nl:word,pic,yearGroup});
});
}));
return out
})();
/* De vertrouwde startkaart blijft exact dezelfde 30 woorden houden. */
const START_WORD_KEYS = {
nl:["monkey","fish","sun","cat","ball","egg","tree","house","moon","boat","hen","mouse","book","star","rose","fire","bike","cake","coat","glasses","clock","pear","cheese","duck","hand","foot","nose","eye","ear","mouth"],
en:["cat","dog","sun","egg","ball","fish","tree","moon","boat","star","book","cake","house","mouse","apple","train","fire","rose","bear","duck","frog","bee","cow","pig","hand","foot","nose","eye","ear","milk"]
};
const WORDS = Object.fromEntries(["nl","en"].map(lang=>[
lang, START_WORD_KEYS[lang].map(id=>{
const concept=LANGUAGE_CONCEPTS.find(item=>item.id===id);
return [concept[lang],concept.pic];
})
]));
function languageBuiltinWords(lang=LANG){
return lang==="nl"?LANGUAGE_CONCEPTS.concat(LANGUAGE_NL_PROGRESSION_WORDS):LANGUAGE_CONCEPTS
}
function languageThemeList(lang=LANG){
return LANGUAGE_THEME_DEFS.map(theme=>({
...theme,
name:theme[lang],
words:languageBuiltinWords(lang).filter(item=>item.theme===theme.id)
.map(item=>[item[lang]||item.nl,item.pic,item.yearGroup||null])
})).filter(theme=>theme.words.length);
}
function languageEmojiDataUrl(emoji,colors=["#f4f8ff","#dce9fa"]){
const svg=`<svg xmlns="http://www.w3.org/2000/svg" width="320" height="320" viewBox="0 0 320 320"><defs><linearGradient id="g" x2="1" y2="1"><stop stop-color="${colors[0]}"/><stop offset="1" stop-color="${colors[1]}"/></linearGradient></defs><rect width="320" height="320" rx="48" fill="url(#g)"/><circle cx="160" cy="160" r="112" fill="#fff" opacity=".92"/><text x="160" y="177" text-anchor="middle" dominant-baseline="middle" font-family="Apple Color Emoji,Segoe UI Emoji,Noto Color Emoji,sans-serif" font-size="148">${emoji}</text></svg>`;
return "data:image/svg+xml;charset=utf-8,"+encodeURIComponent(svg);
}
function languagePictureCatalog(lang=LANG){
const builtinThemes=languageThemeList(lang).map((theme,index)=>({
id:-200-index,nameNl:theme.nl,nameEn:theme.en,scope:"global",filterOnly:true,
languageBuiltin:true,wordPicture:true,icon:theme.icon
}));
const themeIds=new Map(LANGUAGE_THEME_DEFS.map((theme,index)=>[theme.id,-200-index]));
const images=languageBuiltinWords(lang).map((item,index)=>{
const theme=LANGUAGE_THEME_DEFS.find(def=>def.id===item.theme);
const name=item[lang]||item.nl;
return {
id:-1000-index,name,folder:`Taal/Woordenschat/${theme[lang]}`,
scope:"global",themes:[themeIds.get(item.theme)],tags:[item.nl,item.en,theme.nl,theme.en].filter(Boolean),
src:languageEmojiDataUrl(item.pic,theme.colors),value:item.pic,canManage:false,canDelete:false,
wordPicture:true,builtin:true,yearGroup:item.yearGroup||null
};
});
const ownThemes=[];
const customImages=[];
let customId=-5000;
const addOwn=(words,name,folder,themeId)=>{
(words||[]).forEach(([word,pic])=>{
if(!word||!pic)return;
customImages.push({
id:customId--,name:word,folder,scope:"personal",themes:[themeId],tags:[word,name],
src:isImg(pic)?pic:languageEmojiDataUrl(pic),value:pic,canManage:false,canDelete:false,
wordPicture:true,builtin:false
});
});
};
const generalThemeId=-400;
ownThemes.push({id:generalThemeId,nameNl:"Mijn woordkaarten",nameEn:"My word cards",scope:"personal",filterOnly:true,wordPicture:true,icon:"⭐"});
addOwn(GENERAL_EXTRA[lang],lang==="nl"?"Mijn woordkaarten":"My word cards","Taal/Mijn woordkaarten",generalThemeId);
THEMES[lang].forEach((theme,index)=>{
const id=-401-index;
ownThemes.push({id,nameNl:theme.name,nameEn:theme.name,scope:"personal",filterOnly:true,wordPicture:true,icon:"📁"});
addOwn(theme.words,theme.name,["Taal/Mijn themas",theme.folder,theme.name].filter(Boolean).join("/"),id);
});
return {themes:builtinThemes.concat(ownThemes),images:images.concat(customImages)};
}
/* teacher's own additions to the general card (persisted per user) */
let GENERAL_EXTRA = {nl:[], en:[]};
function generalList(){ return WORDS[LANG].concat(GENERAL_EXTRA[LANG]); }
const shuffle = a => { a=a.slice(); for(let i=a.length-1;i>0;i--){const j=Math.floor(Math.random()*(i+1)); [a[i],a[j]]=[a[j],a[i]];} return a; };
/* custom themes: folders of own words.
{nl:[{name:"Herfst", words:[[word,pic],...]}], en:[...]} */
let THEMES = {nl:[], en:[]};
/* ankerbibliotheek: los van borden bewaarde ankerdiagrammen, herbruikbaar op
elk bord. [{id, name, folder?, cells, pics}] - cells/pics in dezelfde vorm
als de widget-staat van anchor.js; folder is een pad ("A/B") zoals bij de
thema's en borden in de mappenverkenner. */
let ANCHOR_LIB = [];
function themesFromData(data){
if(!data) return {nl:[],en:[]};
if(data.themes) return data.themes;
/* migrate old flat word lists into one theme */
const t = {nl:[],en:[]};
if(data.words) ["nl","en"].forEach(l=>{
if(Array.isArray(data.words[l]) && data.words[l].length)
t[l] = [{name: l==="nl" ? "Mijn woorden" : "My words", words: data.words[l]}];
});
return t;
}
const isImg = p => typeof p==="string" && /^(?:data:|https?:|blob:|\/)/.test(p);
function setPic(el, pic){
if(isImg(pic)){ el.innerHTML = ""; const im = document.createElement("img"); im.src = pic; im.alt=""; el.appendChild(im); }
else el.textContent = pic;
}
/* ---- ARASAAC pictogram lookup (shared by the word editor + anchor grid) ---- */
async function arasaacSearch(term, lang){
const resp = await fetch(`https://api.arasaac.org/api/pictograms/${lang}/search/${encodeURIComponent(term)}`);
if(!resp.ok) throw new Error("http "+resp.status);
return resp.json();
}
const arasaacUrl = id => `https://static.arasaac.org/pictograms/${id}/${id}_300.png`;
/* ---- shared word source (general card + themes + anchor grids) ---- */
/* anchor-word widgets register their words here so every language widget
can use them as a theme automatically */
let ANCHORS = []; /* [{el, name, words:[[w,pic],...]}] */
function anchorSources(){
ANCHORS = ANCHORS.filter(a=>a.el && document.contains(a.el));
return ANCHORS.filter(a=>a.words.length);
}
function normWordSource(card){
if(typeof card==="string"){
if(card.startsWith("b:")){
if(languageThemeList().some(theme=>theme.id===card.slice(2))) return card;
}else if(card.startsWith("t")){
const th = THEMES[LANG][+card.slice(1)];
if(th && th.words.length) return card;
}else if(card.startsWith("a")){
if(anchorSources()[+card.slice(1)]) return card;
}
}
return "g";
}
function wordSourceList(card){
card = normWordSource(card);
if(card.startsWith("b:")) return languageThemeList().find(theme=>theme.id===card.slice(2)).words;
if(card.startsWith("t")) return THEMES[LANG][+card.slice(1)].words;
if(card.startsWith("a")) return anchorSources()[+card.slice(1)].words;
return generalList();
}
function fillWordSourceSel(sel, card){
sel.innerHTML = "";
const og = document.createElement("option");
og.value = "g"; og.textContent = "⭐ "+T("cardStart");
sel.appendChild(og);
const builtinGroup = document.createElement("optgroup");
builtinGroup.label = "📚 "+T("wordThemes");
languageThemeList().forEach(theme=>{
const option=document.createElement("option");
option.value="b:"+theme.id;
option.textContent=`${theme.icon} ${theme.name} (${theme.words.length})`;
builtinGroup.appendChild(option);
});
sel.appendChild(builtinGroup);
/* thema's zonder map bovenaan, daarna per map gegroepeerd (optgroup) -
zelfde indeling als de theme-dropdown in de woorden-editor */
const groups = new Map();
THEMES[LANG].forEach((th,i)=>{
if(!th.words.length) return;
const f = th.folder || "";
if(!groups.has(f)) groups.set(f, []);
groups.get(f).push([th, i]);
});
const addOpt = (parent, th, i)=>{
const o = document.createElement("option");
o.value = "t"+i; o.textContent = "★ "+th.name;
parent.appendChild(o);
};
(groups.get("") || []).forEach(([th,i])=>addOpt(sel, th, i));
[...groups.keys()].filter(f=>f).sort().forEach(f=>{
const grp = document.createElement("optgroup");
grp.label = "📁 " + f;
groups.get(f).forEach(([th,i])=>addOpt(grp, th, i));
sel.appendChild(grp);
});
anchorSources().forEach((a,i)=>{
const o = document.createElement("option");
o.value = "a"+i; o.textContent = "⚓ "+a.name;
sel.appendChild(o);
});
sel.value = normWordSource(card);
if(sel.selectedIndex < 0) sel.selectedIndex = 0;
}
/* emoji palette (grouped) */
const splitEmoji = s => {
const out = [];
for(const ch of s){
if(out.length && (ch==="" || ch==="")) out[out.length-1]+=ch;
else if(out.length && out[out.length-1].endsWith("")) out[out.length-1]+=ch;
else out.push(ch);
}
return out;
};
const EMOJI_CATS = [
splitEmoji("🐵🐶🐱🐭🐹🐰🦊🐻🐼🐨🐯🦁🐮🐷🐸🐔🐧🐦🦆🦉🐴🦄🐝🐛🦋🐌🐞🐠🐟🐬🐳🐢🐍🦎🐘🦒"),
splitEmoji("🍎🍐🍊🍋🍌🍉🍇🍓🍒🍑🥝🍅🥕🌽🥔🧀🥚🍞🥐🥞🍕🍟🍦🍪🎂🍫🍬🥛🧃🍯"),
splitEmoji("🌳🌲🌴🌵🌷🌹🌻🌸💐🍄⭐🌙☀️⛅🌈❄️🔥💧🌊🪨"),
splitEmoji("🚗🚕🚌🚑🚒🚜🚲🛴🏍️🚂✈️🚁⛵🚀🛶🚢"),
splitEmoji("⚽🏀🎈🎁🧸📕✏️🖍️✂️🎨🥁🎸👓⌚⏰💡🔑🧤🧢👟👗🧥🛏️🪑🚪🏠"),
splitEmoji("✋👂👃👁️👄🦶😀😢😴🤧👶👦👧👵👴")
];