MathML/Algebra mit MathML und JavaScript
- 15min
- leicht
• MathML
• Einstieg in das DOM
In diesem Tutorial lernen Sie, wie Sie mit MathML Gleichungen auf Webseiten darstellen und mit JavaScript deren DOM verändern.
Inhaltsverzeichnis
Zinseszins
Der Zinseszins sorgt dafür, dass sich gespartes Geld munter vermehrt, aber auch vermeintlich machbare Kreditsummen über die Jahre nicht weniger werden.[1]
<msub>
<mn>K</mn>
<mn>n</mn>
</msub>
<mo>=</mo>
<msub>
<mn>K</mn>
<mn>0</mn>
</msub>
<mo>*</mo>
<msup>
<mrow>
<mo>(</mo>
<mn>1</mn>
<mo>+</mo>
<mfrac>
<mi href="https://de.wikipedia.org/wiki/Zinssatz" title="https://de.wikipedia.org/wiki/Zinssatz">p</mi>
<mn>100</mn>
</mfrac>
<mo>)</mo>
</mrow>
<mi>n</mi>
</msup>
Links in MathML
Ist Ihnen aufgefallen, dass das <mi>-Element ein href-Attribut hat? Es ist angedacht, dies in der künfitgen Spezifikation MathML 4.0 festzulegen, im Firefox und Safari funktioniert es bereits.[2] Der Link erscheint blau - auch ein title-Attribut wird angezeigt.
In Chrome und den anderen Blink-Browsern bleibt das Element funktionslos.
So teuer ist Ihre Immobilie wirklich!
Auch in der Zeit der Niedrigzinsen, die mittlerweile fast schon vorbei scheint, ist es interessant, wie sich eine feste Summe dank Zins und Zinseszins über die Jahre zu einer erklecklichen Gesamtsumme aufbaut.
Gesucht wird die Gesamtsumme Kn - also können wir die obige Formel unverändert verwenden!
Unser Beispiel wird um ein Eingabeformular erweitert, das drei der vier Größen (oder Variablen) abfragt und dann das Ergebnis berechnet:
const
calculator = {},
output = document.querySelector('output');
function empty (node) {
while (node.firstChild) {
node.removeChild(node.firstChild);
}
}
// DOM-Teile merken
['principal', 'rate', 'time', 'total'].forEach(key => {
calculator[key] = {};
// <input>
calculator[key].input = document.querySelector(`[name='${key}']`);
calculator[key].parsedValue = '?';
// Formelteil
calculator[key].mathNode = document.querySelector(`#${key}`);
calculator[key].mathContent = calculator[key].mathNode.firstChild;
// finde DOMElement für Formelteil
calculator[key].mathNode.childNodes.forEach(node => {
if (node.tagName) {
calculator[key].mathContent = node;
}
});
});
Die Verarbeitung der eingegebenen Zahlen erfolgt nun in zwei Schritten:
- Die eingegebenen Werte werden benutzt, um Kn zu ermitteln und auszugeben
- Eingegebene Werte sind immer Strings - sie müssen mit parseFloat erst in (Dezimal)-Zahlen umgewandelt werden.
- Damit gerade hohe Werte wie der Kaufpreis „lesbarer“ werden, werden mit Number.toLocaleString Tausender-Separatoren eingefügt.[3]
- Mithilfe der Math.pow()- Funktion wird nun Kn ermittelt.
- Die MathML-Formel wird nun mit den eingegebenen Werten aktualisiert.
- Es wird mit createElement ein neues Element erzeugt und die mit
event.target.value
ermittelte Eingabe als Textknoten eingefügt. - Kn und Ko bestehen ja aus msub-Elementen. Diese und die mi von
p
undn
werden in je ein mrow mit einer id geschachtelt.
Die id entspricht dem name-Attribut des jeweiligen Eingabefelds.
Sobald eine Eingabe erfolgt, wird das msub-Element gelöscht und ein mn-Element mit dem ermittelten Wert eingefügt.
Dies wird umstandslos mit der neuen replaceChildren-Methode erledigt.
- Es wird mit createElement ein neues Element erzeugt und die mit
Wie lange bis zur ersten Million?
Wenn man Geld und Zinsen einfach auf dem Konto lässt, wäre es interessant zu wissen, wann man (hoffentlich die erste von vielen weiteren) Million(en) erreicht hat.
Gesucht wird nun t
, sodass wir die Gleichung umformen müssen:[4]
<math class="equation" id="schritt1">
<mrow>
<mrow>
<msub>
<mn>K</mn>
<mn>n</mn>
</msub>
</mrow>
...
</mrow>
</math>
<math class="op">
<mrow>
...
</mrow>
</math>
<math class="equation" id="schritt2">
...
</math>
math {
font-size: 2.5em;
display: block;
margin-bottom: 2em;
}
.equation > mrow >mrow:first-of-type {
width: 250px;
display: inline-block;
text-align: right;
background: yellow;
}
@media (min-width: 30em) {
body {
display: grid;
grid-template-columns: 1fr 16em;
max-width: 50em;
}
}
h1, h2, p {
grid-column: 1 / -1;
}
Per CSS werden beide Formelteile in einem Grid angeordnet. Dies funktioniert in allen Browsern problemlos.
Optimalerweise sollten die Terme links des Gleichheitszeichens die gleiche Breite haben:
.equation > mrow >mrow:first-of-type {
width: 250px;
display: inline-block;
text-align: right;
background: yellow;
}
Chrome stellt Terme nicht immer inline dar. Eine Schachtelung mit mrow schafft hier Abhilfe. Das zweite mrow-Element (bzw. das erste Kind des direkt folgenden mrow-Elements) wird nun als inline-block auf eine feste Breite von 250px gebracht.
Die Breitenangabe wird im Firefox 111 ignoriert; im Chrome funktioniert es, allerdings werden die Logarithmen nicht mehr inline dargestellt. Im Live-Beispiel wurden diese deshalb in einem weiteren mrow-Element geschachtelt.
<math class="equation" id="schritt3">
<mrow>
<mrow><!-- per CSS mit 250px Breite -->
<mrow display="inline">
<mo>ln</mo>
<mfrac>
<msub>
<mn>K</mn>
<mn>n</mn>
</msub>
<msub>
<mn>K</mn>
<mn>0</mn>
</msub>
</mfrac>
</mrow>
</mrow>
Was allerdings in beiden Browsern (noch) nicht funktioniert, ist die rechte Ausrichtung am Gleichheitszeichen.[5][6]
Hoffentlich gibt es hier bald Fortschritte in den Browsern!
Als ToDo könnte man die Auflösung der Gleichung automagisch durch JavaScript lösen lassen.[7]
Kapitel 2
ToDo (weitere ToDos)
Dieser Artikel sollte weiter ausgebaut werden.
Bitte schicken Sie Ideen, gute Beispiele und best-practice-Tipps an projekt@selfhtml.org.
Noch besser wäre es, wenn Sie in unserem Wiki mitmachen würden.
--Matthias Scharwies (Diskussion) 23:03, 23. Mär. 2023 (CET)Weblinks
- ↑ Wikipedia: Zinseszins
- ↑ MDN: href in MathML
- ↑ Format a number with comma as a thousands separator in JS (Codingexercises)
- ↑ Laufzeit berechnen (mathebibel.de)
- ↑ SO: All terms left of = should have same length
- ↑ SO: Aligning mathml equations at equal sign
- ↑ Lösen linearer Gleichungssysteme (JavaScript) (Walter Bislin's Blog-De)
- Wiris-Quizz in MathML (datenverdrahten.de)
evtl: