All checks were successful
dev - build & deploy naar test / build-and-deploy (push) Successful in 1m5s
765 lines
55 KiB
JavaScript
765 lines
55 KiB
JavaScript
/* 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}));
|
||
|
||
/* Gecontroleerde Nederlandse beeldcorrecties. Bestaande handgekozen emoji
|
||
blijven de terugval; deze lijst corrigeert polyseme woorden en geeft veel
|
||
voorkomende concrete woorden een specifieker beeld. */
|
||
const LANGUAGE_PICTURE_EXACT=Object.freeze({
|
||
groentekraam:"🥕🏪",veehouderij:"🐄",wastafel:"🚰",woonkamermeubel:"🛋️",badkamertegel:"🚿",prullenbak:"🗑️",
|
||
tekstproductie:"✍️📄",verdrietverwerking:"😢🧠",bezorgd:"😟",ouderverzorging:"👩❤️",spierkracht:"💪",
|
||
schoolslag:"🏊",wedstrijdreglement:"🏀📋",toneelspeler:"🎭",spellingspatroon:"🔤",meetinstrument:"📐",
|
||
lentebloem:"🌼",zomerdag:"🌞",herfstblad:"🍂",winterjas:"⛄",jaargetijde:"🍁",gitaarspel:"🎸",
|
||
ruimtestation:"🛰️",boekje:"📖",muziek:"🎶",onderzoeksverslag:"🧪📋",grondrecht:"⚖️",
|
||
bol:"🥯",toast:"🍞",korst:"🍞",kruimel:"🍞",karnemelk:"🥛",room:"🥛",boter:"🧈",vla:"🍮",
|
||
brie:"🧀",plak:"🧀",friet:"🍟",puree:"🥔",schil:"🥔",knol:"🥔",prei:"🥬",kool:"🥬",boon:"🫘",erwtje:"🫛",
|
||
koek:"🍪",snoep:"🍬",wafel:"🧇",gebakje:"🧁",slagroom:"🍰",
|
||
stam:"🌳",tak:"🌿",wortel:"🌱",stengel:"🌱",knop:"🌷",boeket:"💐",druppel:"💧",plas:"💦",sloot:"🏞️",beek:"🏞️",
|
||
licht:"☀️",schaduw:"◐",bui:"🌦️",vorst:"🥶",hagel:"🌨️",vlok:"❄️",aarde:"🌍",grond:"🟫",kiem:"🌱",
|
||
bus:"🚌",taxi:"🚕",rit:"🛣️",band:"🛞",step:"🛴",pedaal:"🚲",bel:"🔔",stuur:"🚲",rail:"🛤️",spoor:"🛤️",
|
||
roeispaan:"🚣",vleugel:"✈️",piloot:"🧑✈️",vlucht:"✈️",pad:"🥾",bocht:"↪️",streep:"➖",file:"🚗🚗",route:"🗺️",
|
||
kast:"🗄️",nachtkast:"🗄️",slaapkamer:"🛏️",slaapkamerraam:"🪟",flat:"🏢",hut:"🛖",dak:"🏠",muur:"🧱",deken:"🛏️",kussen:"🛏️",kruk:"🪑",slot:"🔒",sleutel:"🔑",
|
||
pan:"🍳",pot:"🍲",kom:"🥣",lepel:"🥄",bad:"🛁",douche:"🚿",wc:"🚽",kraan:"🚰",zeep:"🧼",
|
||
stof:"🫧",vuil:"🗑️",bezem:"🧹",dweil:"🧽",spons:"🧽",
|
||
duim:"👍",vinger:"☝️",nagel:"💅",pols:"⌚",teen:"🦶",hiel:"🦶",enkel:"🦵",knie:"🦵",
|
||
wang:"🙂",kin:"🙂",nek:"🧣",keel:"🗣️",lip:"👄",kies:"🦷",tong:"👅",speeksel:"💧",gebit:"😁",
|
||
trui:"👕",broek:"👖",rok:"👗",long:"🫁",bloed:"🩸",bot:"🦴",spier:"💪",skelet:"🦴",
|
||
bewegingsapparaat:"🦴",bewegingsrichting:"🧭",lichaamsbeweging:"🤸",bewegingsreeks:"🔄",bewegingsoefening:"🤸",bewegingspatroon:"💃",gaan:"🚶",stap:"👣",staan:"🧍",zitten:"🪑",racen:"🏁",sprinten:"🏃",haasten:"⏩",vluchten:"🏃",
|
||
hupsen:"🐇",bukken:"🙇",rollen:"🤸",draaien:"🔄",blad:"📄",zin:"📝",tekst:"📄",schrift:"📓",
|
||
praten:"🗣️",zeggen:"💬",vragen:"❓",roepen:"📣",fluisteren:"🤫",delen:"🤲",geven:"🎁",halen:"📥",brengen:"📤",
|
||
leuk:"😀",fijn:"😊",glimlach:"🙂",sip:"😔",verdriet:"😢",pijn:"🤕",kwaad:"😠",ruzie:"💢",zorgen:"😟",
|
||
rust:"🧘",kalm:"🙂",stil:"🤫",zacht:"🪶",ademen:"🌬️",dapper:"🦸",durven:"💪",winnen:"🏆",raar:"🤔",wauw:"🤩",
|
||
gezin:"👨👩👧👦",ouders:"👪",mama:"👩",tante:"👩",dochter:"👧",papa:"👨",oom:"👨",zoon:"👦",
|
||
jongen:"👦",meisje:"👧",kleuter:"🧒",puber:"🧑",maat:"🧑🤝🧑",buur:"🏘️",gast:"🧑",juf:"👩🏫",meester:"👨🏫",
|
||
leraar:"🧑🏫",mentor:"🧑🏫",coach:"🧑🏫",team:"👥",klas:"🏫",paar:"👫",kring:"⭕",
|
||
kaart:"🃏",doel:"🥅",trap:"⚽",veld:"🏟️",basket:"🏀",korf:"🧺",worp:"🤾",score:"💯",punt:"🔵",stuk:"🧩",rand:"🧩",
|
||
plaat:"🖼️",beer:"🧸",blok:"🧱",pion:"♟️",plons:"💦",slag:"🏊",prijs:"🏆",beker:"🏆",medaille:"🏅",
|
||
straat:"🛣️",landingsbaan:"🛬",plattegrond:"🗺️",landbouwer:"🧑🌾",plein:"🏘️",les:"📚",gym:"🤸",kassa:"🧾",kar:"🛒",mand:"🧺",klant:"🧑",arts:"🧑⚕️",zaal:"🚪",zorg:"❤️",
|
||
boer:"🧑🌾",stal:"🏚️",schuur:"🏚️",land:"🌾",erf:"🏡",balie:"🛎️",lezer:"📖",buurt:"🏘️",vijver:"🏞️",
|
||
dag:"☀️",uur:"🕐",tijd:"⏰",middag:"🌤️",vroeg:"🌅",wakker:"⏰",ontbijt:"🥣",avond:"🌇",laat:"🌙",
|
||
donker:"🌑",week:"🗓️",maand:"📆",jaar:"🎆",datum:"📅",agenda:"📒",feest:"🥳",kaars:"🕯️",ballon:"🎈",
|
||
lente:"🌼",zomer:"🌞",herfst:"🍂",winter:"⛄",seconde:"⏱️",kwart:"¼",half:"½",duur:"⏳",
|
||
kleur:"🌈",verf:"🎨",kwast:"🖌️",doek:"🖼️",palet:"🎨",tekening:"🖍️",lijn:"➖",vorm:"🔷",vak:"◻️",
|
||
toon:"🎵",lied:"🎶",stem:"🗣️",klank:"🔊",trom:"🥁",fluit:"🪈",snaar:"🎸",toets:"🎹",
|
||
dans:"💃",sprong:"🤸",draai:"🔄",toneel:"🎭",rol:"🎭",pak:"👔",podium:"🎭",foto:"📷",film:"🎬",lens:"📷",
|
||
zoeken:"🔎",vraag:"❓",vondst:"💡",proef:"🧪",test:"✅",buis:"🧪",mengen:"🥣",
|
||
magneet:"🧲",ijzer:"🔩",pool:"🧲",kracht:"💪",wiel:"🛞",as:"⚙️",tand:"🦷",veer:"🪶",hefboom:"⚖️",
|
||
stroom:"⚡",draad:"🧵",stekker:"🔌",digitaal:"💻",internet:"🌐",programmeren:"🧑💻",computer:"💻",muis:"🖱️",scherm:"🖥️",bestand:"📄",ruimte:"🌌",
|
||
planeet:"🪐",raket:"🚀",satelliet:"🛰️",heelal:"🌌",astronaut:"🧑🚀",
|
||
letter:"🔤",woord:"🔠",naam:"🏷️",teken:"✍️",komma:",",titel:"🏷️",prent:"🖼️",taal:"🗣️",
|
||
spraak:"💬",verhaal:"📖",nul:"0️⃣",een:"1️⃣",twee:"2️⃣",drie:"3️⃣",getal:"🔢",cijfer:"🔣",reeks:"🔢",
|
||
som:"➕",plus:"➕",min:"➖",keer:"✖️",hoek:"📐",vlak:"◻️",lengte:"📏",
|
||
samen:"🤝",hulp:"🆘",beurt:"🔄",afspraak:"🤝",regel:"📋",wijk:"🏘️",wereld:"🌍",grens:"🚧",
|
||
noord:"⬆️",zuid:"⬇️",oost:"➡️",west:"⬅️",plek:"📍",richting:"🧭",nieuws:"📰",krant:"🗞️",bericht:"💬",
|
||
radio:"📻",media:"📺",afval:"🗑️",bak:"🗑️",glas:"♻️",papier:"📄",recht:"⚖️",plicht:"📋",keus:"🔀",
|
||
wet:"⚖️",eerlijk:"⚖️",mening:"💭",besluit:"✅"
|
||
});
|
||
/* Betekenisdragende delen voor samenstellingen. Het familiebeeld blijft
|
||
voorop staan; maximaal één tweede symbool verduidelijkt het onderscheid. */
|
||
const LANGUAGE_PICTURE_HINTS=Object.freeze([
|
||
["bescherming","🛡️"],["veiligheid","🛡️"],["verzorging","🧼"],["vaardigheid","🎯"],["onderzoek","🔬"],
|
||
["bereiding","🍳"],["productie","🏭"],["verwerking","🏭"],["organisatie","📋"],["ontwikkeling","📈"],
|
||
["geschiedenis","📜"],["industrie","🏭"],["maatschappij","🌍"],["informatie","ℹ️"],["technologie","💻"],
|
||
["wedstrijd","🏆"],["training","🏋️"],["strategie","♟️"],["berekening","🧮"],["verdeling","📊"],
|
||
["winkel","🏪"],["fabriek","🏭"],["bedrijf","🏭"],["centrum","🏙️"],["gebouw","🏢"],["kamer","🚪"],
|
||
["boek","📕"],["schrift","📓"],["kaart","🗺️"],["verslag","📋"],["bericht","💬"],["programma","💻"],
|
||
["verlichting","💡"],["licht","💡"],["water","💧"],["lucht","🌬️"],["grond","🟫"],["bloem","🌷"],
|
||
["boom","🌳"],["tuin","🌱"],["weide","🌿"],["storm","🌪️"],["regen","🌧️"],["sneeuw","❄️"],
|
||
["bak","📦"],["voer","🍽️"],["hok","🏠"],["stal","🏚️"],["riem","🦮"],["kooi","🪹"],
|
||
["boot","⛵"],["reis","🧳"],["straat","🏘️"],["station","🚉"],["haven","⚓"],
|
||
["deur","🚪"],["raam","🪟"],["kast","🗄️"],["tafel","🪑"],["stoel","🪑"],["bed","🛏️"],
|
||
["zorg","❤️"],["hulp","🤝"],["school","🏫"],["leer","📚"],["taal","🔤"],["reken","🧮"],
|
||
["spel","🎲"],["sport","🏅"],["feest","🥳"],["dag","📅"],["tijd","⏰"],["jaar","🗓️"],
|
||
["kracht","💪"],["energie","⚡"],["stroom","⚡"],["machine","⚙️"],["instrument","🎵"],["muziek","🎶"],
|
||
["groep","👥"],["team","👥"],["familie","👨👩👧"],["ouder","👪"],["kind","🧒"],["mens","🧑"],
|
||
["wereld","🌍"],["milieu","♻️"],["afval","🗑️"],["bestuur","🏛️"]
|
||
]);
|
||
function languageProgressionPicture(word,fallback){
|
||
if(LANGUAGE_PICTURE_EXACT[word])return LANGUAGE_PICTURE_EXACT[word];
|
||
const match=LANGUAGE_PICTURE_HINTS.filter(([part])=>word.includes(part)).sort((a,b)=>b[0].length-a[0].length)
|
||
.find(([,emoji])=>emoji!==fallback);
|
||
return match?fallback+match[1]:fallback
|
||
}
|
||
|
||
/* 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:languageProgressionPicture(word,pic),yearGroup,pictureChecked:true});
|
||
});
|
||
}));
|
||
return out
|
||
})();
|
||
|
||
/* Instapwoorden voor beginnende geletterdheid. In groep 1 zijn woorden alleen
|
||
beeldankers om een letter en beginklank te herkennen; kinderen hoeven deze
|
||
woorden nog niet te lezen. Groep 2 voegt korte, vertrouwde woorden toe voor
|
||
letter-klankkoppeling en het aanvullen van een ontbrekende klank. */
|
||
const LANGUAGE_EARLY_WORDS=Object.freeze({
|
||
1:new Set("aap arm bal bed been boek boom boot bos bus deur ei hand huis jas kaas kat kip koe maan mier mond muis neus oog oor pen peer pet pop rok roos sok tas uil vis voet vuur wiel zon".split(" ")),
|
||
2:new Set("appel beer bij eend geit haas hond kikker paard vos slak spin varken melk taart brood soep rijst mais druif snoep sap koek wortel ster bloem blad wolk regen water steen zand zee gras wind auto fiets trein taxi tram weg zeil step stoel klok bril blok sleutel lamp beker verf schaar school haar hoofd schoen jurk shirt want broek tand lezen eten slapen lopen lachen huilen zingen dansen spelen zitten rennen kijken blij boos bang moe ziek trots rustig baby kind jongen meisje vader moeder zus broer oma opa buur man voetbal puzzel spel knikker winkel boer park klas kok stad dorp dag week jaar feest kaars vlag uur".split(" "))
|
||
});
|
||
const LANGUAGE_LOANWORDS_FROM_YEAR5=new Set("wc ski toast jet rail brie pizza citroen cadeau team club cake score hockey bowlen shirt flat".split(" "));
|
||
|
||
function languageDataComplexity(word){
|
||
const w=String(word||"").toLocaleLowerCase("nl-NL").replace(/[^a-z]/g,"");
|
||
const clusters=(w.match(/[bcdfghjklmnpqrstvwxz]{2,}/g)||[]).reduce((n,x)=>n+x.length-1,0);
|
||
const patterns=(w.match(/aai|ooi|oei|eeuw|ieuw|sch|ng|nk|ch|aa|ee|oo|uu|oe|ie|ei|ij|ou|au|ui|eu/g)||[]).length;
|
||
const syllables=(w.match(/[aeiouy]+/g)||[]).length;
|
||
return w.length+clusters*2+patterns+Math.max(0,syllables-1)*2;
|
||
}
|
||
|
||
/* Een woord stroomt pas in als zowel de geplande woordfamilie, de spelling
|
||
als de inhoud bij het leerjaar passen. Dit voorkomt bijvoorbeeld dat korte
|
||
maar abstracte woorden als 'som', 'wet' en 'team' in de kleuterpool komen. */
|
||
function languageRecommendedYear(item){
|
||
const word=String(item.nl||"").toLocaleLowerCase("nl-NL");
|
||
if(LANGUAGE_EARLY_WORDS[1].has(word))return 1;
|
||
if(LANGUAGE_EARLY_WORDS[2].has(word))return 2;
|
||
const complexity=languageDataComplexity(word);
|
||
const syllables=(word.match(/[aeiouy]+/g)||[]).length;
|
||
const patternYear=/eeuw|ieuw|aai|ooi|oei/.test(word)?5:/sch|ng|nk|ch|oe|ie|ei|ij|ou|au|ui|eu/.test(word)?4:3;
|
||
const loanwordYear=LANGUAGE_LOANWORDS_FROM_YEAR5.has(word)?5:3;
|
||
const spellingYear=Math.max(complexity<=9?3:complexity<=14?4:complexity<=19?5:complexity<=24?6:complexity<=30?7:8,syllables>=3?5:syllables>=2?4:3,patternYear,loanwordYear);
|
||
const themeYear={learning:4,science:4,society:5,arts:3,feelings:3}[item.theme]||3;
|
||
return Math.max(3,Number(item.yearGroup)||3,spellingYear,themeYear);
|
||
}
|
||
const LANGUAGE_NL_BUILTIN_WORDS=LANGUAGE_CONCEPTS.concat(LANGUAGE_NL_PROGRESSION_WORDS)
|
||
.map(item=>Object.assign({},item,{yearGroup:languageRecommendedYear(item)}));
|
||
|
||
/* 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,lang==="nl"?languageRecommendedYear(concept):null];
|
||
})
|
||
]));
|
||
|
||
function languageBuiltinWords(lang=LANG){
|
||
return lang==="nl"?LANGUAGE_NL_BUILTIN_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 fontSize=emoji.length>4?104:emoji.length>2?122:148;
|
||
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="${fontSize}">${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 thema’s",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, yearGroup=null, level=2){
|
||
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 available=yearGroup&&typeof languageWordsForYear==="function"?languageWordsForYear(theme.words,yearGroup,level):theme.words;
|
||
if(!available.length)return;
|
||
const option=document.createElement("option");
|
||
option.value="b:"+theme.id;
|
||
option.textContent=`${theme.icon} ${theme.name} (${available.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("✋👂👃👁️👄🦶😀😢😴🤧👶👦👧👵👴")
|
||
];
|