Notenrechner überarbeitet: DOM-Version mit moderner Event-Behandlung und Fehlervalidierung

This commit is contained in:
David Kertzscher 2026-05-06 14:58:05 +00:00
parent f917afd471
commit 8eec0e06d9
3 changed files with 1015 additions and 26 deletions

View file

@ -754,6 +754,473 @@ textarea {
color: #ff1493;
}
/* ===========================
Notenrechner DOM Version Styles
=========================== */
.calculator-tabs {
display: flex;
gap: 0.5rem;
margin: 1.5rem 0;
flex-wrap: wrap;
}
.calculator-tabs .tab-btn {
padding: 0.8rem 1.5rem;
background: rgba(255, 105, 180, 0.1);
border: 2px solid rgba(255, 105, 180, 0.2);
border-radius: 12px;
color: #ff1493;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
font-size: 0.95rem;
}
.calculator-tabs .tab-btn:hover {
background: rgba(255, 105, 180, 0.2);
border-color: #ff1493;
}
.calculator-tabs .tab-btn.active {
background: linear-gradient(135deg, #ff1493 0%, #ff69b4 100%);
color: white;
border-color: #ff1493;
}
.tab-content {
display: none;
animation: slideUp 0.5s ease-out;
}
.tab-content.active {
display: block;
}
.calculator-box {
background: rgba(255, 255, 255, 0.85);
border: 2px solid rgba(255, 105, 180, 0.2);
border-radius: 20px;
padding: 2rem;
box-shadow: 0 8px 32px rgba(255, 20, 147, 0.15);
}
.calculator-box h3 {
color: #ff1493;
margin-bottom: 0.5rem;
}
.calculator-box p {
color: #b8659c;
margin-bottom: 1.5rem;
}
/* Simple Input Group */
.simple-input-group {
display: grid;
grid-template-columns: 1fr 1fr auto;
gap: 1rem;
margin-bottom: 1.5rem;
align-items: end;
}
.input-field {
display: flex;
flex-direction: column;
}
.input-field label {
font-weight: 600;
color: #ff1493;
margin-bottom: 0.5rem;
font-size: 0.95rem;
}
.form-input {
padding: 0.8rem;
border: 2px solid rgba(255, 105, 180, 0.2);
border-radius: 8px;
font-family: inherit;
font-size: 1rem;
color: #6b3a5f;
background: white;
transition: all 0.3s ease;
}
.form-input:focus {
outline: none;
border-color: #ff1493;
box-shadow: 0 0 12px rgba(255, 20, 147, 0.2);
}
.form-input::placeholder {
color: #b8659c;
}
/* Result Box */
.result-box {
background: rgba(255, 192, 203, 0.1);
border: 2px solid rgba(255, 105, 180, 0.2);
border-radius: 12px;
padding: 1.5rem;
margin-top: 1rem;
min-height: 80px;
}
.error-text {
color: #dc143c;
font-weight: 600;
margin: 0;
}
.grade-result-inline {
display: flex;
gap: 2rem;
align-items: center;
justify-content: center;
}
.grade-note,
.grade-note-large {
font-weight: 700;
font-size: 1.5rem;
}
.grade-percent {
font-weight: 600;
font-size: 1.2rem;
color: #b8659c;
background: rgba(255, 192, 203, 0.3);
padding: 0.5rem 1rem;
border-radius: 8px;
}
.grade-result-detailed {
display: flex;
flex-direction: column;
gap: 1rem;
}
.result-header {
display: flex;
justify-content: space-between;
align-items: center;
padding-bottom: 1rem;
border-bottom: 2px solid rgba(255, 105, 180, 0.2);
}
.result-header h4 {
margin: 0;
color: #ff1493;
}
.grade-note-large {
font-size: 2rem;
}
.result-details {
color: #6b3a5f;
}
.result-details p {
margin: 0.3rem 0;
font-size: 0.95rem;
}
/* Progress Bar */
.progress-bar-container {
margin-top: 1.5rem;
}
.progress-bar-background {
width: 100%;
height: 30px;
background: rgba(255, 192, 203, 0.2);
border: 2px solid rgba(255, 105, 180, 0.2);
border-radius: 8px;
overflow: hidden;
margin-bottom: 0.5rem;
}
.progress-bar-fill {
height: 100%;
transition: width 0.5s ease, background-color 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-weight: 600;
font-size: 0.9rem;
}
.progress-text {
text-align: center;
color: #6b3a5f;
font-weight: 600;
font-size: 0.9rem;
margin: 0;
}
/* Grades Container DOM */
.grades-container-dom {
display: flex;
flex-direction: column;
gap: 1rem;
margin-bottom: 1.5rem;
}
.grade-input-group-dom {
animation: slideUp 0.4s ease-out;
}
.grade-input-wrapper-dom {
display: flex;
align-items: center;
gap: 0.8rem;
background: rgba(255, 192, 203, 0.1);
padding: 1rem;
border-radius: 12px;
border: 2px solid rgba(255, 105, 180, 0.15);
transition: all 0.3s ease;
}
.grade-input-wrapper-dom:focus-within {
border-color: rgba(255, 105, 180, 0.4);
background: rgba(255, 192, 203, 0.2);
}
.grade-points-dom,
.grade-max-dom {
flex: 1;
padding: 0.8rem;
border: 1px solid rgba(255, 105, 180, 0.2);
border-radius: 8px;
font-size: 1rem;
font-family: inherit;
color: #6b3a5f;
background: white;
transition: all 0.3s ease;
}
.grade-points-dom:focus,
.grade-max-dom:focus {
outline: none;
border-color: #ff1493;
box-shadow: 0 0 8px rgba(255, 20, 147, 0.2);
}
.grade-points-dom::placeholder,
.grade-max-dom::placeholder {
color: #b8659c;
}
.grade-separator {
font-weight: 600;
color: #ff69b4;
font-size: 1.2rem;
}
.grade-result-dom {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.3rem;
min-width: 80px;
}
.grade-note-dom {
font-weight: 700;
font-size: 1.1rem;
color: #6b3a5f;
}
.grade-percent-dom {
font-weight: 600;
font-size: 0.9rem;
color: #b8659c;
background: rgba(255, 192, 203, 0.3);
padding: 0.3rem 0.6rem;
border-radius: 6px;
}
.grade-remove-btn-dom {
background: none;
border: none;
font-size: 1.3rem;
cursor: pointer;
color: #ff69b4;
padding: 0.5rem;
transition: all 0.3s ease;
border-radius: 50%;
}
.grade-remove-btn-dom:hover {
background: rgba(255, 20, 147, 0.1);
color: #ff1493;
transform: scale(1.2);
}
/* Calculator Buttons */
.calculator-buttons {
display: flex;
flex-direction: column;
gap: 0.8rem;
margin-top: 1.5rem;
}
.btn-add,
.btn-calculate,
.btn-reset {
padding: 1rem 1.5rem;
border: none;
border-radius: 12px;
font-size: 1rem;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
text-transform: uppercase;
letter-spacing: 1px;
}
.btn-add {
background: rgba(255, 105, 180, 0.2);
color: #ff1493;
border: 2px solid rgba(255, 105, 180, 0.3);
}
.btn-add:hover {
background: rgba(255, 105, 180, 0.3);
border-color: #ff1493;
transform: translateY(-2px);
}
.btn-calculate {
background: linear-gradient(135deg, #ff1493 0%, #ff69b4 100%);
color: white;
box-shadow: 0 4px 15px rgba(255, 20, 147, 0.3);
}
.btn-calculate:hover {
transform: translateY(-3px);
box-shadow: 0 6px 20px rgba(255, 20, 147, 0.4);
}
.btn-reset {
background: rgba(200, 100, 150, 0.15);
color: #b8659c;
border: 2px solid rgba(200, 100, 150, 0.3);
}
.btn-reset:hover {
background: rgba(200, 100, 150, 0.25);
border-color: #b8659c;
transform: translateY(-2px);
}
/* Results DOM */
.results-list {
display: flex;
flex-direction: column;
gap: 0.8rem;
}
.results-list h4 {
margin-bottom: 0.5rem;
color: #ff1493;
}
.result-item-dom {
display: flex;
align-items: center;
gap: 1rem;
padding: 1rem;
background: rgba(255, 192, 203, 0.15);
border-radius: 10px;
border-left: 4px solid rgba(255, 105, 180, 0.3);
transition: all 0.3s ease;
animation: slideUp 0.5s ease-out;
}
.result-item-dom:hover {
background: rgba(255, 192, 203, 0.25);
border-left-color: #ff1493;
transform: translateX(5px);
}
.result-number {
font-weight: 700;
color: #ff1493;
min-width: 40px;
}
.result-details {
flex: 1;
color: #6b3a5f;
font-weight: 500;
}
.result-grade-dom {
font-weight: 700;
font-size: 1.1rem;
padding: 0.5rem 1rem;
background: rgba(255, 255, 255, 0.5);
border-radius: 8px;
min-width: 120px;
text-align: center;
}
/* Average Box DOM */
.average-box-dom {
background: linear-gradient(135deg, rgba(255, 192, 203, 0.2) 0%, rgba(255, 160, 180, 0.1) 100%);
border: 2px solid rgba(255, 105, 180, 0.3);
border-radius: 15px;
padding: 1.5rem;
text-align: center;
animation: slideUp 0.6s ease-out;
box-shadow: 0 4px 15px rgba(255, 20, 147, 0.1);
margin-top: 1rem;
}
.average-box-dom h4 {
margin-bottom: 1rem;
color: #ff1493;
}
.average-display-dom {
display: flex;
align-items: center;
justify-content: center;
gap: 1.5rem;
margin: 1rem 0;
}
.average-percent-dom {
font-size: 2.5rem;
font-weight: 800;
color: #ff1493;
background: rgba(255, 192, 203, 0.2);
width: 100px;
height: 100px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
}
.average-note-dom {
font-size: 1.8rem;
font-weight: 700;
}
.average-details-dom {
margin-top: 1rem;
color: #b8659c;
font-weight: 500;
font-size: 0.95rem;
}
/* Grade Scale Table */
.grade-scale-table {
width: 100%;
@ -1578,6 +2045,23 @@ textarea {
width: 100%;
}
.simple-input-group {
grid-template-columns: 1fr;
gap: 0.8rem;
}
.simple-input-group .btn-calculate {
width: 100%;
}
.calculator-tabs {
flex-direction: column;
}
.calculator-tabs .tab-btn {
width: 100%;
}
.stats-grid {
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
gap: 0.8rem;

436
js/notenrechner-dom.js Normal file
View file

@ -0,0 +1,436 @@
/**
* Notenrechner DOM-Version
* Moderne JavaScript DOM-Manipulation mit addEventListener
* David & Karo - EIS Projekt
*/
// Notenmaßstab definieren
const NOTENMASSTAB = {
'sehr gut': { min: 90, max: 100, color: '#ff1493' },
'gut': { min: 75, max: 89, color: '#ff69b4' },
'befriedigend': { min: 60, max: 74, color: '#ffa500' },
'ausreichend': { min: 50, max: 59, color: '#ff8c00' },
'nicht bestanden': { min: 0, max: 49, color: '#dc143c' }
};
/**
* Berechnet die Note basierend auf der Punktzahl
* @param {number} punkte - Erreichte Punktzahl
* @param {number} maxPunkte - Maximale Punktzahl (default: 100)
* @returns {object} - Enthält Note, Prozentage und Details
*/
function berechneNote(punkte, maxPunkte = 100) {
// Eingabe validieren
punkte = parseFloat(punkte);
maxPunkte = parseFloat(maxPunkte);
if (isNaN(punkte) || isNaN(maxPunkte)) {
return {
note: 'Fehler',
prozent: 0,
valid: false,
nachricht: 'Bitte geben Sie Zahlen ein!'
};
}
if (maxPunkte <= 0) {
return {
note: 'Fehler',
prozent: 0,
valid: false,
nachricht: 'Maximale Punktzahl muss größer als 0 sein!'
};
}
if (punkte < 0 || punkte > maxPunkte) {
return {
note: 'Fehler',
prozent: 0,
valid: false,
nachricht: `Punkte müssen zwischen 0 und ${maxPunkte} liegen!`
};
}
// Prozentage berechnen
const prozent = Math.round((punkte / maxPunkte) * 100);
// Note basierend auf Prozentage bestimmen
let note = 'nicht bestanden';
let noteColor = '#dc143c';
for (const [noteText, range] of Object.entries(NOTENMASSTAB)) {
if (prozent >= range.min && prozent <= range.max) {
note = noteText;
noteColor = range.color;
break;
}
}
return {
note: note,
prozent: prozent,
punkte: punkte,
maxPunkte: maxPunkte,
valid: true,
color: noteColor,
nachricht: `${punkte} von ${maxPunkte} Punkten (${prozent}%) = ${note}`
};
}
/**
* Validiert die Eingabe
*/
function validateInput(value, maxValue = 100) {
if (value === '' || value === null) {
return { valid: false, error: 'Bitte geben Sie eine Punktzahl ein!' };
}
const num = parseFloat(value);
if (isNaN(num)) {
return { valid: false, error: 'Bitte geben Sie eine Zahl ein!' };
}
if (num < 0 || num > maxValue) {
return { valid: false, error: `Punktzahl muss zwischen 0 und ${maxValue} liegen!` };
}
return { valid: true };
}
// Warte bis DOM geladen ist
document.addEventListener('DOMContentLoaded', function() {
// Simple Notenrechner
const simplePointsInput = document.getElementById('simple-points');
const simpleMaxInput = document.getElementById('simple-max');
const simpleCalculateBtn = document.getElementById('simple-calculate-btn');
const simpleResult = document.getElementById('simple-result');
const simpleProgressBar = document.getElementById('simple-progress-bar');
// Multiple Notenrechner
const addGradeBtn = document.getElementById('add-grade-btn');
const multipleCalculateBtn = document.getElementById('multiple-calculate-btn');
const multipleResetBtn = document.getElementById('multiple-reset-btn');
const gradesContainer = document.getElementById('grades-container');
const multipleResult = document.getElementById('multiple-result');
const multipleAverage = document.getElementById('multiple-average');
// Simple Grade Calculator Event Listener
if (simpleCalculateBtn && simplePointsInput) {
simpleCalculateBtn.addEventListener('click', function() {
calculateSimpleGrade();
});
// Enter-Taste auch zum Berechnen verwenden
simplePointsInput.addEventListener('keypress', function(event) {
if (event.key === 'Enter') {
calculateSimpleGrade();
}
});
// Live-Berechnung während des Tippens
simplePointsInput.addEventListener('input', function() {
updateSimpleGradeLive();
});
simpleMaxInput.addEventListener('input', function() {
updateSimpleGradeLive();
});
}
// Multiple Grade Calculator Event Listener
if (addGradeBtn) {
addGradeBtn.addEventListener('click', function() {
addGradeInput();
});
}
if (multipleCalculateBtn) {
multipleCalculateBtn.addEventListener('click', function() {
calculateMultipleGrades();
});
}
if (multipleResetBtn) {
multipleResetBtn.addEventListener('click', function() {
resetMultipleCalculator();
});
}
// Initiale Grade hinzufügen
if (gradesContainer) {
addGradeInput();
}
/**
* Berechnet einfache Note und zeigt Ergebnis
*/
function calculateSimpleGrade() {
const points = simplePointsInput.value;
const max = simpleMaxInput.value || 100;
// Validierung
const validation = validateInput(points, max);
if (!validation.valid) {
showSimpleError(validation.error);
return;
}
// Berechnung
const result = berechneNote(parseFloat(points), parseFloat(max));
if (!result.valid) {
showSimpleError(result.nachricht);
return;
}
// Erfolgreiche Anzeige
showSimpleSuccess(result);
}
/**
* Live-Aktualisierung während des Tippens
*/
function updateSimpleGradeLive() {
const points = simplePointsInput.value;
const max = simpleMaxInput.value || 100;
if (points === '') {
simpleResult.innerHTML = '';
simpleProgressBar.style.display = 'none';
return;
}
const validation = validateInput(points, max);
if (!validation.valid) {
simpleResult.innerHTML = `<p class="error-text">⚠️ ${validation.error}</p>`;
simpleProgressBar.style.display = 'none';
return;
}
const result = berechneNote(parseFloat(points), parseFloat(max));
if (result.valid) {
simpleResult.innerHTML = `
<div class="grade-result-inline">
<span class="grade-note" style="color: ${result.color};">${result.note}</span>
<span class="grade-percent">${result.prozent}%</span>
</div>
`;
updateProgressBar(result.prozent, result.color);
}
}
/**
* Fehleranzeige mit rotem Hintergrund
*/
function showSimpleError(errorMessage) {
simplePointsInput.style.borderColor = 'red';
simplePointsInput.style.backgroundColor = 'rgba(220, 20, 60, 0.1)';
simpleResult.innerHTML = `<p class="error-text">❌ ${errorMessage}</p>`;
simpleProgressBar.style.display = 'none';
// Reset nach 2 Sekunden
setTimeout(() => {
simplePointsInput.style.borderColor = '';
simplePointsInput.style.backgroundColor = '';
}, 2000);
}
/**
* Erfolgreiche Anzeige mit Progressbar
*/
function showSimpleSuccess(result) {
simplePointsInput.style.borderColor = 'green';
simplePointsInput.style.backgroundColor = 'rgba(34, 197, 94, 0.1)';
simpleResult.innerHTML = `
<div class="grade-result-detailed">
<div class="result-header">
<h4>📊 Ergebnis:</h4>
<span class="grade-note-large" style="color: ${result.color};">${result.note}</span>
</div>
<div class="result-details">
<p><strong>Punkte:</strong> ${result.punkte} / ${result.maxPunkte}</p>
<p><strong>Prozentage:</strong> ${result.prozent}%</p>
</div>
</div>
`;
updateProgressBar(result.prozent, result.color);
// Reset nach 3 Sekunden
setTimeout(() => {
simplePointsInput.style.borderColor = '';
simplePointsInput.style.backgroundColor = '';
}, 3000);
}
/**
* Aktualisiert die Progressbar
*/
function updateProgressBar(percent, color) {
simpleProgressBar.style.display = 'block';
simpleProgressBar.innerHTML = `
<div class="progress-bar-background">
<div class="progress-bar-fill" style="width: ${percent}%; background-color: ${color};"></div>
</div>
<p class="progress-text">${percent}% Complete</p>
`;
}
/**
* Neue Grade-Input-Zeile hinzufügen (Multiple)
*/
function addGradeInput() {
if (!gradesContainer) return;
const gradeId = Date.now();
const gradeDiv = document.createElement('div');
gradeDiv.className = 'grade-input-group-dom';
gradeDiv.id = `grade-${gradeId}`;
gradeDiv.innerHTML = `
<div class="grade-input-wrapper-dom">
<input
type="number"
class="grade-points-dom"
placeholder="Punkte"
min="0"
step="0.5"
>
<span class="grade-separator">/</span>
<input
type="number"
class="grade-max-dom"
placeholder="Max"
value="100"
min="1"
step="1"
>
<div class="grade-result-dom">
<span class="grade-note-dom">-</span>
<span class="grade-percent-dom">0%</span>
</div>
<button class="grade-remove-btn-dom" type="button"></button>
</div>
`;
gradesContainer.appendChild(gradeDiv);
// Event Listener für neue Eingabe
const pointsInput = gradeDiv.querySelector('.grade-points-dom');
const maxInput = gradeDiv.querySelector('.grade-max-dom');
const removeBtn = gradeDiv.querySelector('.grade-remove-btn-dom');
const noteSpan = gradeDiv.querySelector('.grade-note-dom');
const percentSpan = gradeDiv.querySelector('.grade-percent-dom');
function updateGradeLive() {
const points = parseFloat(pointsInput.value) || 0;
const max = parseFloat(maxInput.value) || 100;
if (max > 0 && points >= 0 && points <= max) {
const result = berechneNote(points, max);
if (result.valid) {
noteSpan.textContent = result.note;
percentSpan.textContent = result.prozent + '%';
noteSpan.style.color = result.color;
}
} else {
noteSpan.textContent = '-';
percentSpan.textContent = '0%';
}
}
pointsInput.addEventListener('input', updateGradeLive);
maxInput.addEventListener('input', updateGradeLive);
removeBtn.addEventListener('click', function() {
gradeDiv.remove();
});
pointsInput.focus();
}
/**
* Berechnet mehrere Noten
*/
function calculateMultipleGrades() {
const gradeInputs = gradesContainer.querySelectorAll('.grade-input-group-dom');
const noten = [];
gradeInputs.forEach(input => {
const points = parseFloat(input.querySelector('.grade-points-dom').value);
const max = parseFloat(input.querySelector('.grade-max-dom').value);
if (!isNaN(points) && !isNaN(max) && max > 0) {
const result = berechneNote(points, max);
if (result.valid) {
noten.push(result);
}
}
});
if (noten.length === 0) {
multipleResult.innerHTML = `<p class="error-text">⚠️ Bitte füllen Sie mindestens eine Note aus!</p>`;
multipleAverage.innerHTML = '';
return;
}
// Einzelnoten anzeigen
let resultHTML = '<div class="results-list"><h4>📊 Ihre Noten:</h4>';
noten.forEach((note, index) => {
resultHTML += `
<div class="result-item-dom">
<span class="result-number">#${index + 1}</span>
<span class="result-details">${note.punkte} / ${note.maxPunkte} (${note.prozent}%)</span>
<span class="result-grade-dom" style="color: ${note.color};">${note.note}</span>
</div>
`;
});
resultHTML += '</div>';
multipleResult.innerHTML = resultHTML;
// Durchschnitt berechnen
if (noten.length > 1) {
const durchschnittProzent = Math.round(
noten.reduce((sum, n) => sum + n.prozent, 0) / noten.length
);
let durchschnittNote = 'nicht bestanden';
let durchschnittColor = '#dc143c';
for (const [noteText, range] of Object.entries(NOTENMASSTAB)) {
if (durchschnittProzent >= range.min && durchschnittProzent <= range.max) {
durchschnittNote = noteText;
durchschnittColor = range.color;
break;
}
}
multipleAverage.innerHTML = `
<div class="average-box-dom">
<h4>📈 Durchschnitt:</h4>
<div class="average-display-dom">
<div class="average-percent-dom">${durchschnittProzent}%</div>
<div class="average-note-dom" style="color: ${durchschnittColor};">${durchschnittNote}</div>
</div>
<p class="average-details-dom">Von ${noten.length} Note(n)</p>
</div>
`;
// Console Ausgabe
console.log(`Durchschnitt: ${durchschnittProzent}% = ${durchschnittNote}`);
} else {
multipleAverage.innerHTML = '';
}
}
/**
* Setzt Multiple Grade Calculator zurück
*/
function resetMultipleCalculator() {
gradesContainer.innerHTML = '';
multipleResult.innerHTML = '';
multipleAverage.innerHTML = '';
addGradeInput();
}
});

View file

@ -46,12 +46,16 @@
<p>Geben Sie Ihre erreichten Punkte und die maximale Punktzahl ein. Der Rechner berechnet automatisch den Prozentsatz.</p>
</div>
<div class="info-card">
<h4>2⃣ Mehrere Noten</h4>
<h4>2⃣ Live-Berechnung</h4>
<p>Das Ergebnis wird direkt auf der Seite angezeigt - ohne Dialoge! Moderne DOM-Manipulation mit JavaScript.</p>
</div>
<div class="info-card">
<h4>3⃣ Mehrere Noten</h4>
<p>Fügen Sie mehrere Noten hinzu, um einen Durchschnitt zu berechnen. Perfekt für Prüfungsvorbereitung!</p>
</div>
<div class="info-card">
<h4>3⃣ Sofort Feedback</h4>
<p>Sehen Sie sofort, welche Note Sie erhalten mit Prozentanzeige und hilfreichen Farben.</p>
<h4>4⃣ Visuelle Rückmeldung</h4>
<p>Farbige Progressbars und Fehlerbehandlung mit rotem Hintergrund beim Input. Sofort Feedback!</p>
</div>
</div>
</section>
@ -97,43 +101,88 @@
</section>
<section class="calculator-section">
<h2>🧮 Interaktiver Notenrechner</h2>
<h2>🧮 Notenrechner DOM-Version</h2>
<div class="calculator-container">
<div class="grades-input-section">
<h3>Gebe deine Noten ein:</h3>
<!-- Tab Navigation -->
<div class="calculator-tabs">
<button class="tab-btn active" onclick="switchNoteTab('simple-tab')">📊 Einfacher Rechner</button>
<button class="tab-btn" onclick="switchNoteTab('multiple-tab')">📈 Multiple Noten</button>
</div>
<!-- Simple Grade Calculator Tab -->
<div id="simple-tab" class="tab-content active">
<div class="calculator-box">
<h3>Einfache Notenberechnung</h3>
<p>Geben Sie eine Punktzahl ein und sehen Sie sofort das Ergebnis auf der Seite!</p>
<div id="grades-container" class="grades-container">
<div class="simple-input-group">
<div class="input-field">
<label for="simple-points">Erreichte Punkte:</label>
<input
type="number"
id="simple-points"
class="form-input"
placeholder="z.B. 85"
min="0"
step="0.5"
>
</div>
<div class="input-field">
<label for="simple-max">Maximale Punktzahl:</label>
<input
type="number"
id="simple-max"
class="form-input"
placeholder="z.B. 100"
value="100"
min="1"
>
</div>
<button id="simple-calculate-btn" class="btn btn-calculate" type="button">
🧮 Berechnen
</button>
</div>
<div id="simple-result" class="result-box"></div>
<div id="simple-progress-bar" class="progress-bar-container"></div>
</div>
</div>
<!-- Multiple Grade Calculator Tab -->
<div id="multiple-tab" class="tab-content">
<div class="calculator-box">
<h3>Mehrere Noten berechnen</h3>
<p>Geben Sie mehrere Noten ein der Durchschnitt wird automatisch berechnet!</p>
<div id="grades-container" class="grades-container-dom">
<!-- Grades werden hier dynamisch eingefügt -->
</div>
<div class="calculator-buttons">
<button id="add-grade-btn" class="btn btn-add"> Weitere Note hinzufügen</button>
<button id="calculate-btn" class="btn btn-calculate">🧮 Berechnen</button>
<button id="reset-btn" class="btn btn-reset">🔄 Zurücksetzen</button>
<button id="add-grade-btn" class="btn btn-add" type="button"> Note hinzufügen</button>
<button id="multiple-calculate-btn" class="btn btn-calculate" type="button">🧮 Berechnen</button>
<button id="multiple-reset-btn" class="btn btn-reset" type="button">🔄 Zurücksetzen</button>
</div>
</div>
<div class="results-section">
<div id="result" class="result-container">
<!-- Ergebnisse werden hier eingefügt -->
</div>
<div id="average-result" class="average-container">
<!-- Durchschnitt wird hier eingefügt -->
</div>
<div id="multiple-result" class="result-box"></div>
<div id="multiple-average" class="average-box"></div>
</div>
</div>
</section>
<section>
<h2>💡 Tipps & Tricks</h2>
<h2>💡 Moderne DOM-Manipulation mit JavaScript</h2>
<div class="tips-box">
<ul>
<li><strong>Live-Anzeige:</strong> Die Note wird automatisch aktualisiert, während du die Punkte eingibst!</li>
<li><strong>Verschiedene Skalen:</strong> Du kannst auch mit anderen Maximalwerten arbeiten (z.B. 50, 80 Punkte)</li>
<li><strong>Durchschnitt:</strong> Wenn du mehrere Noten eingibst, berechnet der Rechner automatisch den Durchschnitt</li>
<li><strong>Mobile-freundlich:</strong> Der Rechner funktioniert auf deinem Handy genauso gut wie am Computer!</li>
<li><strong>Schnell zurücksetzen:</strong> Mit dem "Zurücksetzen"-Button kannst du schnell von vorne anfangen</li>
<li><strong>Keine Dialoge:</strong> Ergebnisse werden direkt auf der Webseite angezeigt ohne prompt() oder alert()!</li>
<li><strong>addEventListener:</strong> Event Handler sind in der JavaScript-Datei (notenrechner-dom.js) registriert, nicht im HTML</li>
<li><strong>DOM-Zugriff:</strong> Das Skript nutzt document.getElementById() und querySelector() um auf HTML-Elemente zuzugreifen</li>
<li><strong>Live-Validierung:</strong> Bei ungültiger Eingabe wird das Input-Feld rot hinterlegt und eine Fehlermeldung angezeigt</li>
<li><strong>Farbige Progressbar:</strong> Ein visueller Balken zeigt den Prozentsatz in der Notenfarbe an</li>
<li><strong>Fehlerbehandlung:</strong> Umfangreiche Validierung der Eingaben mit aussagekräftigen Fehlermeldungen</li>
<li><strong>Template Literals:</strong> JavaScript nutzt moderne Template Literals für die HTML-Ausgabe</li>
</ul>
</div>
</section>
@ -143,7 +192,27 @@
</footer>
</main>
<script src="js/notenrechner.js"></script>
<script src="js/notenrechner-dom.js"></script>
<script src="js/script.js"></script>
<script>
/**
* Tab-Wechsel Funktion für Notenrechner
*/
function switchNoteTab(tabName) {
// Alle Tabs verstecken
document.querySelectorAll('.tab-content').forEach(tab => {
tab.classList.remove('active');
});
// Alle Buttons deaktivieren
document.querySelectorAll('.calculator-tabs .tab-btn').forEach(btn => {
btn.classList.remove('active');
});
// Gewählten Tab anzeigen
document.getElementById(tabName).classList.add('active');
event.target.classList.add('active');
}
</script>
</body>
</html>