oefenhub_docent_module_optellen_en_aftrekken_simpel_v1_23.html
Korte beschrijving
Deze mockup toont de docentweergave van de technische module Optellen & Aftrekken (simpel). In deze view configureert de docent de inhoud van een oefening, zoals de gebruikte bewerkingen, getalbereiken en aanvullende instellingen voor vraaggeneratie.
De pagina maakt onderdeel uit van de flow Nieuwe oefening toevoegen, waarbij na het kiezen van een module de bijbehorende configuratie wordt geladen. De instellingen die hier worden vastgelegd vormen de basis voor de gegenereerde vragen tijdens het oefenen door leerlingen.
Via deze mockup krijg je inzicht in de beschikbare configuratiemogelijkheden en hoe deze doorwerken in de uiteindelijke oefening.
Gerelateerde documentatie
- Bekijk de schermdocumentatie voor meer functionele context.
Bestand
Broncode
/mockups_html/modules/oefenhub_docent_module_optellen_en_aftrekken_simpel_v1_23.html
<!DOCTYPE html>
<html lang="nl">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>OefenHub - Optellen & Aftrekken (simpel)</title>
<style>
:root{
--line:rgba(170,204,238,.62);
--text:#174f9a;
--muted:#55789f;
--accent:#0d5db8;
--accent-2:#2f79db;
--shadow-soft:0 8px 18px rgba(35,100,177,.08);
--warning:#fff0d7;
--warning-text:#8b5a00;
}
*{box-sizing:border-box}
html,body{margin:0;padding:0}
body{
min-height:100vh;
overflow-x:hidden;
font-family:"Segoe UI", Tahoma, sans-serif;
color:var(--text);
background:
radial-gradient(circle at 8% 14%, rgba(255,255,255,.68) 0 12%, transparent 13%),
radial-gradient(circle at 18% 10%, rgba(255,255,255,.45) 0 9%, transparent 10%),
radial-gradient(circle at 86% 17%, rgba(255,255,255,.58) 0 11%, transparent 12%),
linear-gradient(180deg, #7ec2f8 0%, #bfe2fd 15%, #edf7ff 34%, #f7fbff 100%);
}
.wrapModuleModal{width:min(1220px, calc(100% - 30px));margin:0 auto}
.module-config{margin-top:22px;max-width:1220px}
.modal{
background:#f9fbfe;
border:1px solid var(--line);
border-radius:30px;
box-shadow:0 22px 48px rgba(21,58,109,.18);
overflow:hidden;
}
.modal-header{padding:22px 26px 16px}
.modal-sub{margin:8px 0 0;color:var(--muted);font-size:16px;line-height:1.5;max-width:1050px}
.modal-body{padding:22px;max-height:640px;overflow:auto}
.modal-actions{display:flex;justify-content:center;gap:12px;padding-top:8px;flex-wrap:wrap}
.generic-block,.config-section{background:#fff;border:1px solid var(--line);border-radius:24px;padding:18px;margin-bottom:18px}
.section-title{display:flex;align-items:center;justify-content:space-between;gap:20px;margin-bottom:12px}
.section-title h2{margin:0;font-size:22px;color:var(--accent)}
.config-section summary{list-style:none;cursor:pointer;display:flex;align-items:center;justify-content:space-between;gap:18px;font-size:18px;font-weight:900;color:var(--accent)}
.config-section summary::-webkit-details-marker{display:none}
.summary-arrow{font-size:18px;color:#6a8db8;line-height:1;transition:transform .2s ease}
.config-section[open] .summary-arrow{transform:rotate(90deg)}
.config-content{padding-top:16px}
.form-grid{display:grid;grid-template-columns:1.25fr .8fr 1fr;gap:16px;align-items:end}
.field{display:flex;flex-direction:column;gap:7px}
.field label{font-size:14px;font-weight:800;color:#5e7fa8}
input[type="text"],input[type="number"],select{width:100%;height:42px;border-radius:12px;border:1px solid var(--line);background:#f8fbff;padding:0 12px;font-size:14px;color:var(--text)}
.icon-pick{display:flex;gap:10px;flex-wrap:wrap;min-height:46px;align-items:center;background:#f8fbff;border:1px solid var(--line);border-radius:14px;padding:8px 10px}
.icon{width:34px;height:34px;border-radius:12px;border:1px solid var(--line);background:#fff;display:grid;place-items:center;font-size:18px}
.icon.active{background:#edf5ff;border-color:#7fb1ea}
.intro-helper{margin-top:16px;padding-top:14px;border-top:1px solid var(--line)}
.intro-helper-label{font-size:14px;font-weight:800;color:#5e7fa8;margin-bottom:6px}
.intro-helper-text{font-size:14px;color:#6787af;line-height:1.5;margin-bottom:8px}
.intro-helper-formula{font-size:16px;font-weight:900;color:var(--accent);letter-spacing:.02em;text-align:center}
.subcard{border:1px solid var(--line);background:#fbfdff;border-radius:18px;padding:16px}
.subcard h5{margin:0 0 12px;font-size:18px;color:var(--accent)}
.choice-row{display:grid;grid-template-columns:1fr 1fr;gap:18px;margin-bottom:14px}
.choice-row label{display:flex;align-items:center;gap:8px;font-size:14px;color:var(--text);font-weight:800}
.choice-row .right-choice{justify-self:start}
.split-config{display:grid;grid-template-columns:1fr 1px 1fr;gap:18px;align-items:stretch;margin-top:12px;padding:8px 0}
.split-divider{background:linear-gradient(180deg, transparent, #c9d8eb 12%, #c9d8eb 88%, transparent);width:1px}
.stack{display:grid;gap:12px}
.disabled-look{opacity:.45;filter:grayscale(.1)}
.disabled-section{opacity:.58}
.helper{color:#6688b0;font-size:14px;line-height:1.5;margin-top:2px}
.tag-selector{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px}
.number-tag{min-width:40px;height:34px;border-radius:999px;border:1px solid var(--line);display:inline-flex;align-items:center;justify-content:center;padding:0 12px;font-size:14px;font-weight:800;background:#eef4fb;color:var(--accent)}
.number-tag.active{background:#1e5aa8;border-color:#1e5aa8;color:#fff}
.warning{background:var(--warning);color:var(--warning-text);border:1px solid #f2d59c;border-radius:16px;padding:10px 12px;margin-bottom:12px;font-size:14px;line-height:1.45;font-weight:700}
.settings-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px}
.setting-card{border:1px solid var(--line);background:#fbfdff;border-radius:16px;padding:12px 14px}
.setting-card.full{grid-column:1 / -1}
.setting-card h6{margin:0 0 6px;font-size:14px;color:var(--accent);line-height:1.35}
.setting-card p{margin:6px 0 0;font-size:14px;color:#6787af;line-height:1.45}
.radio-row{display:flex;gap:14px;flex-wrap:wrap;min-height:40px;align-items:center;background:#f8fbff;border:1px solid var(--line);border-radius:12px;padding:0 12px}
.radio-row label{display:flex;align-items:center;gap:8px;margin:0;color:var(--text);font-size:14px;font-weight:700}
.range-row{display:flex;align-items:center;gap:12px;margin-top:8px}
.range-row input[type="range"]{flex:1;accent-color:var(--accent-2)}
.range-value{min-width:52px;text-align:right;font-weight:900;color:var(--accent)}
.helper-box{border:1px solid var(--line);background:#fbfdff;border-radius:16px;padding:14px 16px;color:#6787af;font-size:14px;line-height:1.5}
.btn{border:none;border-radius:18px;padding:16px 28px;font-size:18px;font-weight:900;color:#fff;background:linear-gradient(180deg, var(--accent-2), #1e5aa8);cursor:pointer;box-shadow:0 10px 20px rgba(31,90,168,.16)}
.btn.danger{background:linear-gradient(180deg, #f28a8a, #da5656);box-shadow:0 10px 20px rgba(179,72,72,.16)}
@media (max-width:1100px){
.form-grid,.settings-grid,.split-config{grid-template-columns:1fr}
.split-divider{display:none}
}
@media (max-width:700px){
.wrapModuleModal{width:min(100%, calc(100% - 18px))}
.btn{width:100%}
.modal-actions .btn{width:auto;flex:1 1 220px}
}
</style>
</head>
<body>
<div class="wrapModuleModal">
<div class="module-config" id="moduleConfig">
<div class="modal">
<div class="modal-header">
<p class="modal-sub">Gekozen module: <strong>Optellen & Aftrekken (simpel)</strong>. Deze grote modal wordt inhoudelijk volledig vanuit de library opgebouwd. Onderstaande opzet laat zien hoe de configuratie voor deze module eruit kan zien.</p>
</div>
<div class="modal-body">
<div class="generic-block">
<div class="section-title" style="margin-bottom:10px;"><h2 style="font-size:22px;">Algemene oefeninggegevens</h2></div>
<div class="form-grid">
<div class="field">
<label>Geef de naam op voor deze oefening</label>
<input type="text" value="Optellen en aftrekken t/m 20" />
</div>
<div class="field">
<label>Selecteer een icoontje voor deze oefening</label>
<div class="icon-pick">
<div class="icon">➕</div>
<div class="icon active">🧮</div>
<div class="icon">✏️</div>
<div class="icon">🔢</div>
<div class="icon">📘</div>
</div>
</div>
<div class="field">
<label>Wat gaat de oefening inhouden?</label>
<select>
<option>Allebei</option>
<option>Alleen optellen</option>
<option>Alleen aftrekken</option>
</select>
</div>
</div>
<div class="intro-helper">
<div class="intro-helper-label">Getallen posities gedefinieerd</div>
<div class="intro-helper-text">In de instellingen wordt verwezen naar “getal 1” en “getal 2”, hier laten we zien waar welk getal in de som komt te staan.</div>
<div class="intro-helper-formula"><getal 1> + <getal 2> of <getal 1> - <getal 2></div>
</div>
</div>
<details class="config-section" open>
<summary><span>Optellen configureren</span><span class="summary-arrow">›</span></summary>
<div class="config-content">
<div class="subcard">
<h5>Getal 1 configureren</h5>
<div class="choice-row align-right-first">
<label><input type="radio" name="add_num1_mode" checked /> Stel een min/max in</label>
<label class="right-choice"><input type="radio" name="add_num1_mode" /> Exacte getallen gebruiken</label>
</div>
<div class="split-config">
<div class="stack">
<div class="field"><label>Wat is de minimale waarde van het eerste getal?</label><input type="number" value="1" /></div>
<div class="field"><label>Wat is de maximale waarde van het eerste getal?</label><input type="number" value="20" /></div>
</div>
<div class="split-divider"></div>
<div class="disabled-look">
<div class="helper">Selecteer de specifieke getallen die gebruikt mogen worden.</div>
<div class="tag-selector">
<span class="number-tag">1</span><span class="number-tag">2</span><span class="number-tag">3</span><span class="number-tag">4</span><span class="number-tag">5</span>
<span class="number-tag active">6</span><span class="number-tag">7</span><span class="number-tag">8</span><span class="number-tag">9</span><span class="number-tag">10</span>
<span class="number-tag">11</span><span class="number-tag">12</span><span class="number-tag">13</span><span class="number-tag">14</span><span class="number-tag">15</span>
<span class="number-tag">16</span><span class="number-tag">17</span><span class="number-tag">18</span><span class="number-tag">19</span><span class="number-tag">20</span>
</div>
</div>
</div>
</div>
<div class="subcard" style="margin-top:14px;">
<h5>Getal 2 configureren</h5>
<div class="choice-row align-right-first">
<label><input type="radio" name="add_num2_mode" /> Stel een min/max in</label>
<label class="right-choice"><input type="radio" name="add_num2_mode" checked /> Exacte getallen gebruiken</label>
</div>
<div class="split-config">
<div class="stack disabled-look">
<div class="field"><label>Wat is de minimale waarde van het tweede getal?</label><input type="number" value="1" /></div>
<div class="field"><label>Wat is de maximale waarde van het tweede getal?</label><input type="number" value="20" /></div>
</div>
<div class="split-divider"></div>
<div>
<div class="helper">Selecteer de specifieke getallen die gebruikt mogen worden.</div>
<div class="tag-selector">
<span class="number-tag active">1</span><span class="number-tag active">2</span><span class="number-tag">3</span><span class="number-tag active">4</span><span class="number-tag">5</span>
<span class="number-tag active">6</span><span class="number-tag">7</span><span class="number-tag active">8</span><span class="number-tag">9</span><span class="number-tag">10</span>
<span class="number-tag">11</span><span class="number-tag">12</span><span class="number-tag">13</span><span class="number-tag">14</span><span class="number-tag">15</span>
<span class="number-tag">16</span><span class="number-tag">17</span><span class="number-tag">18</span><span class="number-tag">19</span><span class="number-tag">20</span>
</div>
</div>
</div>
</div>
<div class="subcard" style="margin-top:14px;">
<h5>Uitkomst configureren</h5>
<div class="form-grid" style="grid-template-columns:1fr 1fr;">
<div class="field"><label>Wat is de minimale waarde van het antwoord?</label><input type="number" value="2" /></div>
<div class="field"><label>Wat is de maximale waarde van het antwoord?</label><input type="number" value="40" /></div>
</div>
</div>
</div>
</details>
<details class="config-section" open>
<summary><span>Aftrekken configureren</span><span class="summary-arrow">›</span></summary>
<div class="config-content">
<div class="subcard">
<h5>Getal 1 configureren</h5>
<div class="choice-row align-right-first">
<label><input type="radio" name="sub_num1_mode" checked /> Stel een min/max in</label>
<label class="right-choice"><input type="radio" name="sub_num1_mode" /> Exacte getallen gebruiken</label>
</div>
<div class="split-config">
<div class="stack">
<div class="field"><label>Wat is de minimale waarde van het eerste getal?</label><input type="number" value="5" /></div>
<div class="field"><label>Wat is de maximale waarde van het eerste getal?</label><input type="number" value="20" /></div>
</div>
<div class="split-divider"></div>
<div class="disabled-look">
<div class="helper">Selecteer de specifieke getallen die gebruikt mogen worden.</div>
<div class="tag-selector">
<span class="number-tag">1</span><span class="number-tag">2</span><span class="number-tag">3</span><span class="number-tag">4</span><span class="number-tag">5</span>
<span class="number-tag">6</span><span class="number-tag">7</span><span class="number-tag">8</span><span class="number-tag">9</span><span class="number-tag">10</span>
<span class="number-tag">11</span><span class="number-tag">12</span><span class="number-tag">13</span><span class="number-tag">14</span><span class="number-tag">15</span>
<span class="number-tag">16</span><span class="number-tag">17</span><span class="number-tag">18</span><span class="number-tag">19</span><span class="number-tag">20</span>
</div>
</div>
</div>
</div>
<div class="subcard" style="margin-top:14px;">
<h5>Getal 2 configureren</h5>
<div class="choice-row align-right-first">
<label><input type="radio" name="sub_num2_mode" checked /> Stel een min/max in</label>
<label class="right-choice"><input type="radio" name="sub_num2_mode" /> Exacte getallen gebruiken</label>
</div>
<div class="split-config">
<div class="stack">
<div class="field"><label>Wat is de minimale waarde van het tweede getal?</label><input type="number" value="1" /></div>
<div class="field"><label>Wat is de maximale waarde van het tweede getal?</label><input type="number" value="15" /></div>
</div>
<div class="split-divider"></div>
<div class="disabled-look">
<div class="helper">Selecteer de specifieke getallen die gebruikt mogen worden.</div>
<div class="tag-selector">
<span class="number-tag">1</span><span class="number-tag">2</span><span class="number-tag">3</span><span class="number-tag">4</span><span class="number-tag">5</span>
<span class="number-tag">6</span><span class="number-tag">7</span><span class="number-tag">8</span><span class="number-tag">9</span><span class="number-tag">10</span>
<span class="number-tag">11</span><span class="number-tag">12</span><span class="number-tag">13</span><span class="number-tag">14</span><span class="number-tag">15</span>
<span class="number-tag">16</span><span class="number-tag">17</span><span class="number-tag">18</span><span class="number-tag">19</span><span class="number-tag">20</span>
</div>
</div>
</div>
</div>
<div class="subcard" style="margin-top:14px;">
<h5>Uitkomst configureren</h5>
<div class="warning" style="margin-bottom:14px;">Vul als minimale waarde tenminste 0 in zodat je voorkomt dat er een som met negatieve uitkomst gegenereerd wordt.</div>
<div class="form-grid" style="grid-template-columns:1fr 1fr;">
<div class="field"><label>Wat is de minimale waarde van het antwoord?</label><input type="number" value="0" /></div>
<div class="field"><label>Wat is de maximale waarde van het antwoord?</label><input type="number" value="20" /></div>
</div>
</div>
</div>
</details>
<details class="config-section" open>
<summary><span>Optellen en Aftrekken balans configureren</span><span class="summary-arrow">›</span></summary>
<div class="config-content">
<div class="settings-grid disabled-section">
<div class="setting-card">
<h6>Hoeveel procent optel sommen?</h6>
<div class="range-row">
<input id="addBalanceRange" type="range" min="10" max="50" step="5" value="40" />
<div id="addBalanceValue" class="range-value">40%</div>
</div>
</div>
<div class="setting-card">
<h6>Hoeveel procent aftrek sommen?</h6>
<div class="range-row">
<input id="subBalanceRange" type="range" min="10" max="50" step="5" value="40" />
<div id="subBalanceValue" class="range-value">40%</div>
</div>
</div>
<div class="setting-card full">
<div class="helper-box">De percentages worden gebruikt op het moment dat de vragen gegenereert worden om te kijken dat tenminste een bepaalde hoeveel vragen van een bepaald type zijn. Het restant aan vragen zal random opgegevuld worden. Je kunt nooit meer dan 50% van een bepaald type opgeven. Dus als je 50% voor de ene instelt en 10% voor de andere, heb je 40% onvoorspelbare/random opvulling.</div>
</div>
</div>
</div>
</details>
<details class="config-section" open>
<summary><span>Oefening instellingen</span><span class="summary-arrow">›</span></summary>
<div class="config-content">
<div class="settings-grid">
<div class="setting-card">
<h6>Voorkom te veel sommen met “1 + x” of “y + 1”</h6>
<div class="radio-row"><label><input type="radio" name="limit_one_bias" /> Ja</label><label><input type="radio" name="limit_one_bias" checked /> Nee</label></div>
<p>Er is niet te voorspellen wat er “random” gegenereerd wordt. Als je hier voor ja kiest, zijn er maximaal 2 sommen waar of getal 1 of getal 2 een “1” bevat.</p>
</div>
<div class="setting-card">
<h6>Voorkom te veel sommen met hele tientallen</h6>
<div class="radio-row"><label><input type="radio" name="limit_tens_bias" /> Ja</label><label><input type="radio" name="limit_tens_bias" checked /> Nee</label></div>
<p>Er is niet te voorspellen wat er “random” gegenereerd wordt. Als je hier voor ja kiest, zijn er maximaal 4 sommen waar of getal 1 of getal 2 een heel tiental bevat.</p>
</div>
<div class="setting-card">
<h6>De standaard waarde voor het aantal oefeningen</h6>
<input type="number" value="15" />
<p>Als een leerling een oefening wil starten kan het aantal te genereren sommen opgegeven worden. Deze waarde wordt daar gebruikt, maar een leerling kan dit altijd aanpassen.</p>
</div>
<div class="setting-card">
<h6>De minimale waarde voor het aantal oefeningen</h6>
<input type="number" value="10" />
<p>Om te voorkomen dat leerlingen grappig zijn en maar 1 som in een oefening laten genereren, kun je als docent forceren hoeveel het er minimaal moeten zijn.</p>
</div>
<div class="setting-card">
<h6>De maximale waarde voor het aantal oefeningen</h6>
<input type="number" value="40" />
<p>Soms moeten mensen beschermd worden tegen zichzelf, het systeemlimiet is 100.</p>
</div>
<div class="setting-card">
<h6>Is de “Geen idee” knop beschikbaar?</h6>
<div class="radio-row"><label><input type="radio" name="allow_dunno" /> Ja</label><label><input type="radio" name="allow_dunno" checked /> Nee</label></div>
<p>Je geeft hiermee de leerling een knop onder elke vraag om aan te geven dat ze het niet weten. De vraag wordt wel als fout gerekend, maar achteraf in de resultaten is dit wel gemarkeerd om hier naar te kunnen kijken.</p>
</div>
<div class="setting-card full">
<h6>Toon antwoord direct na vraag?</h6>
<div class="radio-row"><label><input type="radio" name="show_answer_after_submit" /> Ja</label><label><input type="radio" name="show_answer_after_submit" checked /> Nee</label></div>
<p>In het geval van nee, ziet een leerling pas aan het einde het resultaat. Als je voor ja kiest wordt na het geven van een antwoord zichtbaar gemaakt of deze goed of fout was, voordat ze verder gaan naar de volgende vraag.</p>
</div>
</div>
</div>
</details>
<div class="modal-actions"><button class="btn danger" id="closeModuleConfigBottom" type="button">Terug naar overzicht</button><button class="btn" type="button">Opslaan en toevoegen</button></div>
</div>
</div>
</div>
</div>
</div>
</section>
</main>
<script>
(function () {
const navItems = document.querySelectorAll('.nav-item[data-menu]');
navItems.forEach(function (item) {
const trigger = item.querySelector('button');
if (!trigger) return;
trigger.addEventListener('click', function (event) {
event.preventDefault();
const isOpen = item.classList.contains('open');
navItems.forEach(function (other) {
other.classList.remove('open');
const btn = other.querySelector('button');
if (btn) btn.setAttribute('aria-expanded', 'false');
});
if (!isOpen) {
item.classList.add('open');
trigger.setAttribute('aria-expanded', 'true');
}
});
});
document.addEventListener('click', function (event) {
navItems.forEach(function (item) {
if (!item.contains(event.target)) {
item.classList.remove('open');
const btn = item.querySelector('button');
if (btn) btn.setAttribute('aria-expanded', 'false');
}
});
});
function bindRange(rangeId, valueId) {
var range = document.getElementById(rangeId);
var value = document.getElementById(valueId);
if (!range || !value) return;
function sync() { value.textContent = range.value + '%'; }
range.addEventListener('input', sync);
sync();
}
bindRange('addBalanceRange', 'addBalanceValue');
bindRange('subBalanceRange', 'subBalanceValue');
var openBtn = document.getElementById('openModuleConfig');
var closeTop = document.getElementById('closeModuleConfigTop');
var closeBottom = document.getElementById('closeModuleConfigBottom');
var config = document.getElementById('moduleConfig');
var selection = document.getElementById('moduleSelection');
function openConfig() {
if (!config) return;
config.hidden = false;
if (selection) selection.hidden = true;
config.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
function closeConfig() {
if (!config) return;
config.hidden = true;
if (selection) selection.hidden = false;
if (selection) selection.scrollIntoView({ behavior: 'smooth', block: 'start' });
else if (openBtn) openBtn.scrollIntoView({ behavior: 'smooth', block: 'center' });
}
if (openBtn) openBtn.addEventListener('click', openConfig);
if (closeTop) closeTop.addEventListener('click', closeConfig);
if (closeBottom) closeBottom.addEventListener('click', closeConfig);
})();
</script>
</body>
</html>