Beispiel:Mathe-Quiz-fertig.html

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche
<!DOCTYPE html>
<html lang="de">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
	<link rel="stylesheet" media="screen" href="./Beispiel:SELFHTML-Beispiel-Grundlayout.css">
    <title>Mathe-Quiz</title>
<style>
.toggle-buttons input[type="radio"] {
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  height: 1px;
  overflow: hidden;
  position: absolute;
  white-space: nowrap;
  width: 1px;
}
.toggle-buttons label {
  display: inline-block;
  border: 1px solid #333;
  border-radius: 0.5em;
  width: 2rem;
  height: 2rem;
  margin: 0.5rem;
  font: 0/0;
  color: transparent;
}

/* Original-SVG-Grafiken in img/mathe-quiz-labels.svg */
.toggle-buttons label[for=add] {
  background-image: url("data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%2024%2024%22%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%3E%0A%20%20%3Cstyle%3E%0A%20%20%20path%20%7B%0A%09%20%20%20stroke%3A%20black%3B%0A%09%20%20%20stroke-width%3A%202.5px%3B%0A%09%20%20%20stroke-linecap%3A%20round%3B%0A%20%20%20%7D%0A%20%20%20%3C/style%3E%0A%20%20%20%3Cpath%20d%3D%22M6%2C12%20h12%20M12%2C6%20v12%22/%3E%0A%3C/svg%3E");
}

.toggle-buttons label[for=subtract] {
  background-image: url("data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%2024%2024%22%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%3E%0A%20%20%3Cstyle%3E%0A%20%20%20path%20%7B%0A%09%20%20%20stroke%3A%20black%3B%0A%09%20%20%20stroke-width%3A%203px%3B%0A%09%20%20%20stroke-linecap%3A%20round%3B%0A%20%20%20%7D%0A%20%20%20%3C/style%3E%0A%20%20%20%3Cpath%20d%3D%22M6%2C12%20h12%22/%3E%0A%3C/svg%3E");
}

.toggle-buttons label[for=divide] {
  background-image: url("data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%2024%2024%22%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%3E%0A%20%20%3Cstyle%3E%0A%20%20%20path%20%7B%0A%09%20%20%20stroke%3A%20black%3B%0A%09%20%20%20stroke-width%3A%203px%3B%0A%09%20%20%20stroke-linecap%3A%20round%3B%0A%20%20%20%7D%0A%20%20%20%3C/style%3E%0A%20%20%20%3Cpath%20d%3D%22M6%2C12%20h12%22/%3E%0A%20%20%20%3Ccircle%20cx%3D%2212%22%20cy%3D%226%22%20r%3D%221.5%22%20/%3E%0A%20%20%20%3Ccircle%20cx%3D%2212%22%20cy%3D%2218%22%20r%3D%221.5%22%20/%3E%20%20%20%0A%3C/svg%3E");
}

.toggle-buttons label[for=multiply] {
  background-image: url("data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%2024%2024%22%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%3E%0A%20%20%3Cstyle%3E%0A%20%20%20path%20%7B%0A%09%20%20%20stroke%3A%20black%3B%0A%09%20%20%20stroke-width%3A%203px%3B%0A%09%20%20%20stroke-linecap%3A%20round%3B%0A%20%20%20%7D%0A%20%20%20%3C/style%3E%0A%20%20%20%3Cpath%20d%3D%22M9%2C9%20l6%2C6%20M15%2C9%20l-6%2C6%22/%3E%0A%3C/svg%3E");
}

.toggle-buttons label[for=any] {
  background-image: url("data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%2048%2048%22%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%3E%0A%20%20%3Cstyle%3E%0A%20%20%20path%20%7B%0A%09%20%20%20stroke%3A%20black%3B%0A%09%20%20%20stroke-width%3A%203px%3B%0A%09%20%20%20stroke-linecap%3A%20round%3B%0A%20%20%20%7D%0A%20%20%20%3C/style%3E%0A%20%20%20%3Cpath%20id%3D%22plus%22%20d%3D%22M6%2C12%20h12%20M12%2C6%20v12%22/%3E%0A%20%20%20%3Cpath%20id%3D%22minus%22%20d%3D%22M30%2C12%20h12%22/%3E%0A%20%20%20%3Cpath%20id%3D%22divide%22%20d%3D%22M6%2C36%20h12%22/%3E%0A%20%20%20%3Ccircle%20cx%3D%2212%22%20cy%3D%2230%22%20r%3D%221.5%22%20/%3E%0A%20%20%20%3Ccircle%20cx%3D%2212%22%20cy%3D%2242%22%20r%3D%221.5%22%20/%3E%20%20%20%0A%20%20%20%3Cpath%20id%3D%22multiply%22%20transform%3D%22translate%2824%2C24%29%22%20d%3D%22M9%2C9%20l6%2C6%20M15%2C9%20l-6%2C6%22/%3E%0A%3C/svg%3E");
}

.toggle-buttons label[for=open-dialog] {
  margin: 1em 0 0 0;
}

.toggle-buttons input:checked + label {
  background-color: #ebf5d7;
}

#task {
  font-size: 2em;
  margin: 2em auto;
}

#task span {
  display: inline-block;
  width: 1em;
  text-align: center;
}

/* Scrollleiste von type="number" wird ausgeblendet */
#task input[type="number"]{
  width: 2em;
  -moz-appearance: textfield;
  appearance: textfield;
  margin: 0;
  font-size: 1em;
}

input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button {
      -webkit-appearance: none;
      margin: 0;
}

#task button {
  font-size: 1.33em;
  padding: -0.5em 0 0;
  height: 1em;
  width: 1em;
  line-height: 90%;
  vertical-align: top;
}

output {
  display: block;
  margin: 2em 0;
}

.exact {
	font-weight: bold;
	color: green;
}

output.exact:after {
	content: "✓";
	display: block;
	margin: 0.8em 0 0 1em;
}

.inexact {
	font-weight: bold;
	color: red;
}

output.inexact:after {
	content: "✗";
	display: block;
	margin: 0.8em 0 0 1em;
}
[for=input] {
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    height: 1px;
    overflow: hidden;
    position: absolute;
    white-space: nowrap;
    width: 1px;
}
</style>
<script>
'use strict';
document.addEventListener("DOMContentLoaded", function () {

	let input = document.getElementById('input'),
		output =  document.querySelector('output'),
		randomNumberMax = 10,
		result = 0,
		stat = {
          correct: 0,
          incorrect: 0
		};

	function createGame () {

		document.querySelector('#rechenarten').addEventListener('change', createTask);
		
		// Beim Verlassen der Seite wird vorher die Statistik gespeichert
		window.addEventListener('beforeunload', function(event) {
      		localStorage.setItem('item', JSON.stringify(stat));
		});

		
		// gespeicherte Statistik laden. Wenn keine vorhanden, Info-Template laden
		getStorage();
		
		// Button um Statistiken zurückzusetzen
		document.querySelector('#reset-stat').addEventListener('click', resetStatistics);
       
		// submit-Button einrichten
		document.querySelector('#task').addEventListener('submit', evaluateResponse);

		createTask();
	}

	function createTask () {
		var a,
		b;

		/* In diesem Objekt sind für jeden Operator sowohl die Symbole als auch die Rechenoperation gespeichert. 
		Für den Zufallsoperator werden die Operatoren dann mit der Zufallsfunktion ausgesucht.
		Die Zufallszahlen je nach Operator so ermitteln, dass als Ergebnis nur positive Ganze Zahlen herauskommen.
		*/
		var opMap = {
			"+": function() {
				a = rand( 1, randomNumberMax * 3);
				b = rand( 1, randomNumberMax * 3);
				result = a+b;
				return "+";
			},
			"-": function() {
				// So kann sichergestellt werden, dass das Ergebnis immer positiv ist
				b = rand( 1, randomNumberMax * 3);
				a = rand( b, randomNumberMax * 3);
				result = a-b;
				return "-";
			},
			"×": function() {
				a = rand( 1, randomNumberMax);
				b = rand( 1, randomNumberMax);
				result = a*b;
				return "×";
			},
			"÷": function() {
				// So kann sichergestellt werden, dass das Ergebnis immer eine ganze Zahl ist
				b = rand( 1, randomNumberMax);
				a = b * rand( 0, randomNumberMax);
				result = a/b;
				return "÷";
			},
			"any": function() {
				var p, props = [];

				for (p in opMap) {
					if (p != "any") {
						props.push(p);
					}
				}

				p = rand(0, props.length);

				return opMap[props[p]]();
			}
		};

		// vorherige Eingaben werden entfernt
		output.textContent = 'Bitte gib das Ergebnis ein!';
		output.className = '';
		document.getElementById('input').value = '';

		/* Rechnung durchführen, Zufallszahlen dabei ermitteln und
		Operator-Symbol ins Dokument ausgeben */
		document.querySelector('#operator').textContent = opMap[
			document.querySelector('input[name="op"]:checked').getAttribute(
				"data-operator"
			)
		]();

		// Zufallszahlen in task ausgeben
		document.querySelector('#var1').textContent = a;
		document.querySelector('#var2').textContent = b;
	}

	function evaluateResponse (evt) {
		// Ergebnis mit Eingabe vergleichen
		evt.preventDefault();

		if (result == input.value){
			output.textContent = 'Super!';
			output.className = 'exact';
			stat.correct++;
		} else {
			output.textContent = 'Leider falsch!';
			output.className = 'inexact';
			stat.incorrect++;
		}
		
		setTimeout(createTask, 1000);
	}

	// Statistiken aus LocalStorage holen
    function getStorage () {
	  var eintraegeArray = localStorage.getItem('item');
	  if (eintraegeArray) {
          output.innerText = eintraegeArray;
		  stat = JSON.parse(eintraegeArray);
	  }
	  else {
	    output.textContent = 'Herzlich willkommen in unserem Mathe-Quiz! Gib das Ergebnis der Rechnung ein und drücke die Enter-Taste!';
	  }
	  return stat;
	}
	
	// Statistiken zurücksetzen
    function resetStatistics () {
		stat.correct = 0;
		stat.incorrect = 0;
		getStatistics();
		document.querySelector('#ergebnis').textContent = 'Statisiken wurden zurückgesetzt!';
	}	

	// Statistiken ausgeben
    function getStatistics () {
		document.querySelector('#richtig').textContent =   stat.correct;
		document.querySelector('#falsch').textContent =  stat.incorrect;
		var percentage = stat.correct/( stat.correct+stat.incorrect)*100;
		document.querySelector('#prozent').textContent =  percentage.toFixed(2);
	}	
	

	// erzeugt Zufallszahl
	function rand (min, max) {
		return Math.floor(Math.random() * (max - min + 1)) + min;
	}
	
	//Polyfill für dialog-Element
	document.querySelector('#open-dialog').addEventListener('click', getStatisticsDialog);
	
	function getStatisticsDialog (){
		getStatistics ();
		toggleDialog ();
	}
	
	function toggleDialog (){ 
		var dialog = document.querySelector('dialog'),
	    	closeButton= document.getElementById('close-dialog');
			
		if (!dialog.hasAttribute('open')) {
			// show the dialog 
			dialog.setAttribute('open','open');
			// after displaying the dialog, focus the closeButton inside it
			closeButton.focus();
			closeButton.addEventListener('click', toggleDialog);
			// EventListener für ESC-Taste
			document.addEventListener('keydown', function(event) {
    			if (event.keyCode == 27) {
					toggleDialog();
    			}
			}, true);			
			// only hide the background *after* you've moved focus out of the content that will be "hidden" 
			var div = document.createElement('div');
			div.id = 'backdrop';
		    document.body.appendChild(div); 
		}
		else {		
    		dialog.removeAttribute('open');  
			var div = document.querySelector('#backdrop');
			div.parentNode.removeChild(div);
			lastFocus.focus(); 
 		}
	}
	createGame ();
});
</script>
</head>

<body>
<h1>Mathe-Quiz</h1>

<form class="toggle-buttons" id="rechenarten">
   <input type="radio" name="op" data-operator="+" id="add" checked><label for="add">+</label>
   <input type="radio" name="op" data-operator="-" id="subtract"> <label for="subtract">-</label>
   <input type="radio" name="op" data-operator="÷" id="divide"> <label for="divide">/</label>
   <input type="radio" name="op" data-operator="×" id="multiply"> <label for="multiply">x</label>
   <input type="radio" name="op" data-operator="any" id="any"> <label for="any" title="Zufallsauswahl">?</label>
</form>


<form id="task">
	<span id="var1">a</span>
	<span id="operator">+</span>
	<span id="var2">b</span>
	=
	<label for="input">Ergebnis eingeben:</label>
	<input id="input" type="number" step="1" size="3">
	<button type="submit" aria-label="Berechnung starten"></button>
</form>

<p><output>Ergebnisausgabe</output></p>

<button id="open-dialog">Ergebnisse und Statistiken</button>
<dialog role="dialog">
	<button id="close-dialog">X</button>	
	<h2>Ergebnis</h2>
    <p>Richtig: <span class="exact" id="richtig"></span></p>
    <p>Falsch: <span class="inexact" id="falsch"></span></p>
    <p>Prozent: <span id="prozent"></span>%</p>
    
    <button id="reset-stat">Statistiken zurücksetzen</button>
    <p id="ergebnis"></p>
</dialog>

</body>
</html>