Stand: 17.03.2024
Lernziele
- JavaScript-Code in bestehende Webseiten einbinden
- Gezielt DOM-Elemente als Objekte zugreifen
- DOM-Elemente, insbesondere auch in Listen, manipulieren
- Auf Events reagieren
- Mit JavaScript komplexe Elemente (z.B. Akkordeon) erstellen können
In diesem Kapitel setzen wir JavaScript im Kontext von Webseiten ein. Man nennt das auch Frontend-Programmierung im Gegensatz zur Backend-Programmierung, wo es um die Programmierung eines Servers geht.
Wenn wir uns nochmal vor Augen führen, wie Webseiten mit Hilfe von HTTP abgerufen werden: ein Benutzer (Client) schickt eine Anfrage an einen Server und bekommt ein HTML-Dokument als Antwort. JavaScript ist im HTML-Dokument eingebettet und wird auf der Seite des Clients - genauer gesagt vom Browser - ausgeführt. Deshalb also Frontend-Programmierung, da der Code im Frontend (beim User) ausgeführt wird.
Dies steht im Gegensatz zur Backendprogrammierung (z. B. mit PHP), wo der Code bereits im Server ausgeführt ist. Bei der Backendprogrammierung sieht der User keinen Programmiercode, da dieser bereits vor dem Versenden ausgeführt und in der Regel durch Text/HTML ersetzt wurde.
Wie Sie wissen, kann man sich alle HTML-Elemente als Knoten in einem Baum vorstellen. Man nennt diesen Baum auch Document Object Model oder kurz DOM. Das DOM ist unser wichtigstes Tool, um mit Hilfe von JavaScript Elemente der Webseite zu manipulieren.
Denken Sie auch daran, dass Sie viele der folgenden Beispiele direkt im Browser ausprobieren können, indem Sie die JavaScript-Konsole aktivieren. In Chrome sieht das so aus:
(Löschen Sie die Historie von eventuellen Fehlermeldungen einfach mit CTRL-K).
5.1 JavaScript einbinden
Wie bekommen Sie Ihren Code auf die Webseite? Ähnlich wie bei CSS gibt es verschiedene Möglichkeiten.
5.1.1 JavaScript-Datei verlinken
Wie bei CSS ist es üblich, sämtlichen JavaScript-Code in eine separate Datei zu packen. Dazu legt man in der Regel ein neues Unterverzeichnis js
an und erstellt dort eine Datei z. B. script.js
.
Wenn Sie zwei HTML-Seiten haben, könnte Ihre Verzeichnisstruktur anschließend so aussehen:
css/style.css
js/script.js
index.html
kontakt.html
In der HTML-Datei müssen Sie auf Ihre JavaScript-Datei verweisen, dazu verwenden Sie das Element script
und zwar am Ende des Body, d. h. direkt vor dem schließenden Tag </body>
:
<script src="js/script.js"></script>
Grund ist, dass durch das Laden der JavaScript-Datei nicht das Laden der sichtbaren HTML-Elemente verzögert werden soll.
In der JavaScript-Datei können Sie Funktionen definieren oder auch direkt Befehle aufrufen.
Immediately-invoked Function Expression
Bei komplexerem Code kann es sinnvoll sein, den kompletten JavaScript-Code mit folgedem Ausdruck zu umgeben:
(function() {
// eigener Code...
}());
Es handelt sich hierbei um eine anonyme Funktion, die direkt ausgeführt wird. In der Funktion können Sie ganz normal Code hineindefinieren, auch weitere Funktionsdefinitionen. Die Ummantelung sorgt dafür, dass Ihre Variablen außen nicht sichtbar sind und somit nicht mit anderem JavaScript-Code kollidieren (z. B. externe JavaScript-Libraries, die Sie importieren). Man nennt diese Konstruktion eine Immediately-invoked Function Expression oder kurz IIFE.
5.1.2 JavaScript direkt in HTML einbetten
Sie können sowohl im head
als auch im body
ein oder mehrere Element/e von Typ script
einbauen, wo Sie direkt JavaScript-Code hineinschreiben können. Üblicherweise fügt man dies eher im body
ein und dort am Ende.
Der folgende Code lässt ein Fenster aufgehen, das erst weggeklickt werden muss, bevor es weitergeht:
<script>
alert('hello');
</script>
Hin und wieder sieht man das Attribut type
:
<script type="text/javascript">
alert('hello');
</script>
Dies ist aber spätestens seit HTML 5 nicht mehr zwingend notwendig.
Oft werden in diesem Teil nur Funktionen definiert, die dann jeweils über ein Event (siehe nächsten Abschnitt) aufgerufen werden.
<script>
function foo() {
alert('hello');
}
function bar() {
alert('welt');
}
</script>
5.1.3 Events und Event-Handling
Sie können jedes HTML-Element interaktiv machen, indem Sie auf bestimmte Events reagieren, z. B. auf das Anklicken eines Elements. Prinzipiell funktioniert das so, dass Sie ein Stück JavaScript-Code an das Element binden. Diesen Code nennt man auch Event-Handler oder Event-Listener.
Es gibt zwei Möglichkeiten, diesen Handler an das Element zu binden. Empfohlen ist (häufig) die zweite Option.
In HTML
Sie können den Code direkt im HTML-Element platzieren. Das hat den Nachteil, dass JavaScript und HTML vermischt sind, kann aber dennoch zum Testen sinnvoll sein. Schauen wir uns ein Beispiel an:
<p onclick="console.log('CLICK')">
Klick mich an!
</p>
Es gibt verschiedene Attribute für verschiedene Events. Drei der wichtigsten Events/Attribute sind:
- onclick: Element wird angeklickt
- onmouseover: Maus ist über dem Element
- onmouseout: Maus verlässt Element
Sie schreiben i. d. R. eine eigene JavaScript-Funktion, die Sie z.B. mit onclick aufrufen. Sie können dieser Funktion mit this
das angeklickte Element als Parameter mitgeben. Dazu schreiben Sie
<p onclick="myHandler(this)">
Klick mich an!
</p>
Sie müssen entsprechend eine Funktion haben:
<script>
function myHandler(el) {
alert('You clicked the element ' + el.tagName);
}
</script>
Hier eine komplette Webseite, damit Sie sehen, wo das script
steht und wo das Event ausgelöst wird.
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8"/>
<title>JavaScript: Event</title>
</head>
<body>
<h1>JavaScript: Event</h1>
<button onclick="myHandler(this)">
Klick mich an!
</button>
<script>
function myHandler(el) {
alert('You clicked the element ' + el.tagName);
}
</script>
</body>
</html>
In JavaScript
Im Allgemeinen ist es "sauberer", den Handler nicht direkt in das HTML-Element hineinzuschreiben, sondern in JavaScript das Element (oder die Elemente) herauszusuchen, an die ein Handler gebunden werden soll. Das hat den Vorteil, dass die Definition des Handlers und die Bindung an einem Ort (in JavaScript) sind.
Nehmen wir das Beispiel von oben, wo wir die Bindung in HTML vorgenommen haben:
<p onclick="myHandler(this)">
Klick mich an!
</p>
Wir nehmen hier also den Handler raus:
<p>
Klick mich an!
</p>
Stattdessen erledigen wir das in JavaScript: wir binden mit addEventListener
den Handler (= JavaScript-Code) an das Element:
<script>
document.getElementsByTagName('p')[0].addEventListener('click',
function(event) {
alert('You clicked the element ' + this.tagName);
});
</script>
Sie sehen hier das Schlüsselwort 'click', welches für einen Mausklick steht. Zwei weitere interessante Events sind 'mouseenter' und 'mouseleave'. Das 'on', das Sie bei den Event-Handlern zuvor gesehen haben, fällt hier also weg. Eine ausführliche Liste von Events finden Sie bei w3schools.
Sie definieren den Handler als anonyme Funktion mit einem Parameter. Dieser Parameter bekommt bei jedem Aufruf ein MouseEvent-Objekt, wo z. B. hinterlegt ist, welcher Mausbutton gedrückt wurde oder bei welchen Koordinaten sich der Mauszeiger befand. Weitere Infos finden Sie in der MouseEvent API. Sie sehen hier auch, dass Sie mit this
innerhalb der Funktion auf das HTML-Element zugreifen können, welches das Event ausgelöst hat.
Wenn Sie die Event-Infos nicht benötigen, können Sie den Parameter auch weglassen:
<script>
document.getElementsByTagName('p')[0].addEventListener('click',
function() {
alert('You clicked the element ' + this.tagName);
});
</script>
Im obigen Code haben wir schon vorgegriffen. Dort werden alle p
-Elemente gesammelt, dann das erste genommen und daran die Funktion gehängt.
5.2 JavaScript und DOM
5.2.1 DOM: Document Object Model
Wie anfangs gesagt, ist das Document Object Model unser Werkzeug, um auf die Webseite zuzugreifen. Es handelt sich um eine Baumstruktur von JavaScript-Objekten, die Struktur und Inhalte des HTML-Dokuments wiedergeben.
Dokumentbaum und Knoten
Das eine Objekt, das diese gesamte Struktur enthält, heißt document
. Hier ein Beispiel, wie ein solches Objekt aussehen könnte:
Ein Baum besteht aus Knoten (engl. nodes), die hier als Boxen dargestellt sind.
Es gibt genau einen Wurzelknoten (engl. root). Alle Knoten außer der Wurzel haben genau einen Elternknoten (engl. parent). Jeder Knoten kann einen Kindknoten (engl. child) oder mehrere Kindknoten (engl. children) oder auch keine Kinder haben.
In der Abbildung sehen wir die folgenden Arten von Knoten:
- Dokumentknoten (pink): repräsentiert das gesamte Dokument und stellt viele Hilfsfunktionen bereit
- Elementknoten (blau): entspricht einem HTML-Element
- Textknoten (grün): entspricht dem Text innerhalb eines HTML-Elements
- Attributknoten (grau): entspricht einem Attibut im öffnenden Tag eines HTML-Elements
Es ist wichtig, zwischen Knoten und Elementen zu unterscheiden. Knoten können HTML-Elemente, Text, Attribute oder das ganze Dokument sein. Wir sprechen aber nur von einem Element, wenn es sich um ein HTML-Element handelt.
Das folgende Stück HTML
<p id='foo'>Hallo</p>
resultiert in drei Knoten (HTML-Element, Attribut, Text), aber nur einem Element.
Drei Typen
In JavaScript unterscheidet man drei Typen von Objekten, die durch Vererbung miteinander verwandt sind (obere Typen sind Oberklassen, untere Typen erben Eigenschaften und Methoden).
Sie können die Spezifikation jeweils nachschlagen:
(Referenzseiten von Mozilla.)
Element und HTMLElement
Die Elemente (blau) entsprechen jeweils einem HTMLElement. Sie können über das Objekt document
auf alle im Dokument vorhandenen Elemente zugreifen.
Zu beachten ist, dass document
selbst kein HTML-Element ist. Wenn Sie auf das HTML-Element <html>
zugreifen wollen, nutzen Sie
document.documentElement
Sie haben außerdem Zugriff auf Head und Body mit:
document.body
document.head
Um auf den HTML-Code eines DOM-Elements (inklusive aller enthaltenen Elemente!) als String zuzugreifen, verwendet man innerHTML
:
element.innerHTML
Es ist auch möglich, mit innerText
nur den reinen Text (wie oben, aber ohne HTML-Markup) zu erhalten. Auch hier wird der Text aller enthaltenen Elemente inkludiert:
element.innerText
Weitere nützliche Eigenschaften von Elementen sind:
nodeName
: um welchen HTML-Tag es sich handelt (z. B. "BODY" oder "H1"); wird in Großbuchstaben angegebennodeValue
: gibt den Inhalt des Elements zurück (inkludiert nicht die enthaltenen Elemente, sondern schneidet den Inhalt zu Beginn des ersten Unterelements ab)attributes
: alle Attribute des Elements (wie z. B. auch class)classList
: alle Klassen, denen das Element angehörtid
: die ID, falls vorhanden
Eine Übersicht über diese und weitere Eigenschaften finden Sie bei w3schools.
Jedes Element hat auch Methoden, um innerhalb des Objekts zu suchen, z. B. nach Klassen.
5.2.2 Selektion
Ähnlich wie in CSS möchte man auf bestimmte Elemente der Webseite zugreifen, um auszulesen oder zu ändern. Wir wissen, dass man den Elementtyp, Klassen oder IDs verwenden kann, um auf Elemente zuzugreifen. Darüber hinaus kann man über Beziehungen zwischen Knoten (Eltern-Kind, Geschwister) im Baum "navigieren".
Rückgabe: Element oder HTMLCollection
Die Selektion funktioniert über Methoden, die man auf einem Knoten aufruft. Diese Methoden geben entweder ein einzelnes Element zurück oder eine Liste von Elementen, wir nennen sie HTMLCollection (siehe HTMLCollection bei Mozilla).
Eine HTMLCollection funktioniert ähnlich wie ein Array, ist aber kein echter JavaScript-Array. Der Zugriff auf einzelne Elemente erfolgt zwar auch über eckige Klammern und Index, aber es gibt z. B. die Methode forEach nicht für die HTMLCollection. Stattdessen kann man eine for-of-Schleife verwenden, wie wir gleich noch sehen werden.
Elementselektor
Wenn wir nach einem HTML-Elementtyp suchen wie p
oder h1
oder em
, verwenden wir den Elementselektor.
Mit der Methode getElementsByTagName()
können Sie z. B. alle Elemente vom Typ p
im Dokument auswählen:
document.getElementsByTagName('p')
Wir erhalten eine HTMLCollection. Sie bekommen den ersten Absatz daher mit
document.getElementsByTagName('p')[0]
Da der erste Absatz wieder ein Element ist, können Sie dort wieder nach Elementen suchen:
document.getElementsByTagName('p')[0].getElementsByTagName('strong')
Wollen Sie alle Elemente durchlaufen, verwenden Sie eine for-of-Schleife. Sie können forEach leider nicht nutzen, weil eine HTMLCollection eben kein echter JavaScript-Array ist.
Zum Beispiel wollen wir alle Absätze zählen:
let list = document.getElementsByTagName('p');
let count = 0;
for (el of list)
count++;
}
console.log(count);
Sie können natürlich auch eine traditionelle For-Schleife mit einem Laufparameter i
nehmen.
Klassenselektor
Mit der Methode getElementsByClassName()
können Sie z. B. alle Elemente mit Klasse "foo" auswählen:
document.getElementsByClassName('foo')
Wir erhalten auch hier eine HTMLCollection als Rückgabe.
ID-Selektor
Mit der Methode getElementById()
können Sie z. B. das Element mit ID "textblock" auswählen:
document.getElementById('special')
Hier bekommen wir ein einzelnes Element zurück, falls ein solches existiert. Das heißt, wir können dieses Element direkt manipulieren:
document.getElementById('special').style.backgroundColor = 'yellow';
Wenn ein entsprechendes Element nicht existiert, wird null
zurückgegeben.
Selektion per CSS und NodeList
Die Methode querySelectorAll()
erlaubt Ihnen, CSS-Selektoren zu verwenden, die Sie von den CSS-Regeln her kennen. Zum Beispiel alle Elemente ul
innerhalb von nav
:
document.querySelectorAll('nav ul')
Hier erhalten wir eine NodeList zurück (siehe NodeList bei Mozilla).
Eine NodeList ist etwas anderes als eine HTMLCollection. Auch die NodeList funktioniert ähnlich wie ein Array, aber im Gegensatz zur HTMLCollection gibt es die Methode forEach, das heißt, man kann sich etwas kürzer fassen:
document.querySelectorAll('nav ul').forEach(function(el) {
console.log(el)
});
Oder mit Arrow-Notation:
document.querySelectorAll('nav ul').forEach(el => { console.log(el) });
Beachten Sie, dass Sie hier nicht this
verwenden können.
Mit querySelector()
bekommen wir das erste Element zurück, das "passt":
document.querySelector('a')
Hier können wir also direkt das Element manipulieren, z. B.
document.querySelector('a').style.backgroundColor = 'yellow';
5.2.3 Elementlisten durchlaufen
Wir haben leider die etwas verwirrende Situation, dass es zwei Arten von Elementlisten gibt:
- HTMLCollection: Rückgabe von
getElementsByTagName
odergetElementsByClassName
- NodeList: Rückgabe von
querySelectorAll
Die HTMLCollection muss man mit einer For-Schleife durchlaufen, es gibt keinen forEach-Mechanismus.
let list = document.getElementsByTagName('p');
for (let i = 0; i < list.length; i++) {
console.log(list[i]);
}
Für die NodeList gibt es das forEach
. Zu beachten ist aber, dass innerhalb des forEach
nicht mit this
, sondern über einen Parameter auf das aktuelle Element zugegriffen werden muss.
document.querySelectorAll('p').forEach(function(el) {
console.log(el);
});
Ich persönlich empfehle eher die zweite Methode, da hier das funktionale Programmieren zum Einsatz kommt, was der allgemeinen Philosophie von JavaScript entspricht.
5.2.4 Elemente ändern
Inhalte
Um den Inhalt eines Elements zu ändern, können Sie die Eigenschaft innerText
wie eine Variable benutzen, der Sie einen neuen Inhalt zuweisen:
document.getElementsByTagName('p')[1].innerText = "Doktor Foo was here."
Falls Sie auch HTML einbetten wollen, verwenden Sie innerHTML
:
document.getElementsByTagName('p')[1].innerHTML = "Doktor <strong>foo</strong> was <a href='http://hs-augsburg.de'>here</a>."
ID ändern
Oft möchten Sie ID oder Klasse eines Elements ändern, um ein anderes Stückchen CSS auf das Element anzuwenden. Wir nehmen mal das Element body
als Beispiel:
document.body
IDs funktionieren wie Eigenschaften - Sie können sie einfach setzen. Hier wird die ID des Body-Elements auf "special" gesetzt (egal, ob oder wie die ID vorher gesetzt war):
document.body.id = "special";
Wollen Sie eine ID entfernen, müssen Sie removeAttribute()
anwenden:
document.body.removeAttribute('id');
Klassen ändern
Die Klassen eines Elements können über setAttribute()
gesetzt werden:
element.setAttribute('class', 'foo');
Mehrere Klassen können natürlich mit Leerzeichen angegeben werden:
element.setAttribute('class', 'foo bar doo');
Will man eine neue Klasse zu den bisherigen Klassen hinzufügen, kann man die Liste aller Klassen eines Elements beziehen
element.classList
und dort eine neue Klasse mit add
hinzufügen:
element.classList.add('bar');
Sie entfernen eine Klasse mit remove
:
element.classList.remove('foo');
In den meisten Fällen ist die zweite Variante (über classList
) die bessere Wahl.
Attribute ändern
Sie können mit setAttribute()
beliebige Attribute eines Elements setzen, z. B. einen Handler für das erste p-Element einbauen:
document.getElementsByTagName('p')[1].setAttribute('onclick', 'alert("hello")');
Mit hasAttribute()
können Sie prüfen, ob ein Attribut existiert. Alternativ können Sie getAttribute()
verwenden und prüfen, ob Sie null
zurückbekommen.
Wenn ein Attribut wie href bereits gesetzt ist, können Sie den Attributnamen für den Zugriff benutzen:
document.getElementById('speciallink').href = 'index.html';
Allgemein folgt dies dem Schema
element.attributname
Styling/CSS ändern
Um das Styling (also das CSS) eines Elements zu ändern, verwendet man die Eigenschaft style
.
Allgemein:
element.style.eigenschaft = 'wert';
Ein Beispiel:
document.body.style.backgroundColor = 'yellow';
Dabei ist zu beachten, dass CSS-Eigenschaften mit Bindestrich wie background-color in CamelBack-Schreibweise geändert werden müssen, also im Beispiel: backgroundColor.
Sie können auch in der DOM Style Reference Eigenschaften nachschlagen, wenn Sie unsicher sind, wie sie geschrieben werden.
Außerdem müssen alle nicht-numerischen Werte in Anführungszeichen gesetzt sein:
document.getElementById('foo').style.margin = '20px';
document.getElementById('bar').style.margin = 0;
Zu beachten ist, dass die beschriebene Methode äquivalent dazu ist, das Style-Attribut direkt in einem HTML-Element anzulegen. Die obigen zwei Befehle wirken sich also wie folgt auf die HTML-Elemente aus:
<p id='foo' style='margin:20px'> ... </p>
<p id='bar' style='margin:0'> ... </p>
Wenn Sie das Style-Attribut verwenden, um den aktuellen Style auszulesen, hilft Ihnen das selten weiter.
Styling/CSS auslesen
Um das aktuelle Styling auszulesen, empfiehlt sich die Funktion getComputedStyle
, da Sie mit der obigen Methode nur einen im Element definierten Style zurückbekommen. Die Funktion getComputedStyle
stellt das Objekt window
zur Verfügung (siehe Abschnitt "JavaScript und Browser").
Sie bekommen alle Stilinformationen des Body z. B. mit
getComputedStyle(document.body)
Möchten Sie speziell die Hintergrundfarbe, schreiben Sie
getComputedStyle(document.body).backgroundColor
Es kommt z. B. häufig vor, dass Sie aufgrund der Sichtbarkeit eines Elements Entscheidungen treffen:
if (getComputedStyle(element).display == 'none') { ... }
Löschen
Man kann auch mit der Funktion remove
ein Element löschen:
document.getElementsByTagName('p')[1].remove();
Das Element wird aus dem DOM-Baum entfernt.
5.2.5 Im Baum navigieren
Häufig möchten Sie von einem Element auf das nächste Geschwisterelement oder auf den Elternknoten springen. Dazu gibt es Eigenschaften. Wir müssen hier immer zwischen Elementen (= HTML-Elemente) und Nodes (können auch Text- oder Attributknoten sein) unterscheiden. Das spiegelt sich in den zwei Listentypen HTMLCollection (nur Elemente) und NodeList (Knoten aller Art) wider.
Mit parentNode
oder parentElement
greifen Sie auf den Elternknoten als HTML-Element zu:
element.parentNode
element.parentElement
Mit children
auf alle enthaltenen Kindelemente zu:
element.children
Sie bekommen also eine HTMLCollection. Wenn Sie stattdessen childNodes
verwenden würden, bekämen Sie eine NodeList, die auch alle Text- und Attributknoten enthielte.
Mit nextElementSibling
bekommen Sie das nächstfolgende Geschwisterelement:
element.nextElementSibling
Auch hier ist die Unterscheidung zwischen Element und Knoten wichtig. Mit nextSibling
bekommen Sie evtl. einen Textknoten, mit nextElementSibling
bekommen Sie das nächste HTML-Element (was i. d. R. auch gewünscht ist).
Wenn Sie alle Geschwisterelemente bekommen möchten, können Sie einfach über das Elternelement gehen:
element.parentElement.children
Auch hier haben Sie wieder eine HTMLCollection.
5.3 JavaScript und Browser
Der Browser stellt einige Informationen bereit, die Sie über JavaScript-Objekte beziehen können. Das essentielle Objekt heißt window
(siehe auch Window bei Mozilla).
Sie können Höhe und Breite des Browsers (ohne Scrollbars und Toolbars) bekommen:
window.innerHeight
window.innerWidth
Das Objekt enthält wiederum das Objekt screen
, das die Eigenschaften des Bildschirms (nicht nur des Browserfensters) enthält. Hier einige interessante Eigenschaften:
screen.width
screen.height
screen.availWidth
screen.availHeight
screen.colorDepth
screen.pixelDepth
Das window
-Objekt enthält noch die aktuelle URL in
window.location
Dies Objekt ist eine assoziative Liste, so dass Sie auf einzelne Aspekte so zugreifen können:
window.location.href
window.location.hostname
...
Mit assign()
können Sie den Browser sogar auf eine andere Webseite lenken:
window.location.assign('http://hs-augsburg.de');
In diesem Objekt können Sie auf die Browse-Historie zugreifen:
window.history
Auch hier können Sie den Browser fernsteuern:
history.back()
history.forward()
Methoden
Das window
-Objekt stellt einige interessante Methoden bereits. Eine kennen Sie schon:
window.alert('hallo');
Diese Methode zeigt einen modalen Dialog. Sie können das Objekt auch weglassen:
alert('hallo');
Zwei weitere Methoden sind interessant:
setTimeout()
setInterval()
Beide bekommen eine Funktion und eine Zeitangabe (Dauer in ms). Bei setTimeout
wird die Funktion nach Ablauf der Zeit ausgeführt. Bei setInterval
wird die Funktion immer wieder nach Ablauf dieser Zeit ausgeführt.
Zum Beispiel:
setTimeout(() => { console.log('buh!')}, 2000);
Auch bei diesen Funktionen müssen Sie nicht window
for die Funktion schreiben.
5.4 Praktische Beispiele
5.4.1 Zähler
Ein kleines Beispiel für Interaktivität ist ein Zähler, der bei Knopfdruck hochgezählt wird. Das Ergebnis wird direkt auf der Webseite angezeigt:
Layout
Im HTML-Code erzeugen wir einen Button und ein Feld, in das wir den Zählwert eintragen können. Wir brauchen auch IDs, um die Elemente eindeutig anzusprechen:
<button id="counterbutton">Zähler</button>
<span id="counter">0</span>
Wir schreiben hier erstmal eine 0, aber wir benötigen natürlich eine Variable für diesen Wert.
Programmierung
Den JavaScript-Teil betten wir direkt in die HTML-Datei am Ende des <body>
ein:
<body>
...
<script>
...
</script>
</body>
Im JavaScript-Code führen wir eine globale Variable als Zähler ein:
var ex_counter = 0;
Das Hochzählen ist einfach:
ex_counter++;
Um das Ergebnis in das span
-Element zu schreiben, benutzen wir innerText
:
document.getElementById('counter').innerText = ex_counter;
Jetzt müssen wir diese zwei Codezeilen als Funktion an den Button binden. Den Button bekommen wir so:
document.querySelector('#counterbutton')
Man könnte auch getElementById
benutzen (wie wir es bei dem span
-Element tun). Jetzt hängen wir unseren Code als Handler für Click-Events an den Button:
document.querySelector('#counterbutton').addEventListener('click', function() {
ex_counter++;
document.getElementById('counter').innerText = ex_counter;
});
Beachten Sie, dass der Zähler beim Neuladen der Seite auf 0 gesetzt wird.
5.4.2 Modales Dialogfenster
Ein modales Fenster ist ein Fenster, das den restlichen Inhalt überdeckt und erst weggeklickt werden muss, damit der User weiter mit der Webseite interagieren kann. Das kann man visuell unterstützen, indem man die Seite mit einer halbtransparenten Fläche überlagert:
Layout
Wir platzieren z. B. oberhalb unserer normalen Webseite ein div
, das später die halbtransparente Fläche aufnimmt:
<div id="modal-cover">
...
</div>
Um diese Überdeckung zu erreichen, fixieren wir das div
, drehen den z-index
hoch und stellen mit top
, left
, width
und height
sicher, dass keine Ränder bleiben. Einige der CSS-Befehle, die wir hier verwenden, lernen Sie noch im Kapitel 'Layout mit CSS' kennen.
#modal-cover {
position: fixed;
z-index: 1;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, .3);
...
}
Innerhalb der Fläche definieren wir das modale Fenster und platzieren dort auch das Multiplikationskreuz als Close-Button:
<div id="modal-cover">
<div id="modal-window">
<span id="modal-close">×</span>
Dies ist ein modales Dialogfenster.
</div>
</div>
Den Close-Button positionieren und stylen wir wie folgt:
#modal-close {
position: absolute;
top: 0;
right: 10px;
color: #aaa;
float: right;
font-size: 35px;
font-weight: bold;
cursor: pointer;
}
Jetzt stylen wir noch das eigentliche Fenster. Das position:relative
benötigen wir, damit der Close-Button mit position:absolute
innerhalb des Dialogfensters positioniert wird.
#modal-window {
position: relative;
font-size: 40px;
background-color: white;
border-radius: 8px;
padding: 60px 60px 60px 40px;
}
Damit das Fenster später zentriert erscheint, müssen wir das Styling des umgebenden div
noch ergänzen:
#modal-cover {
...
display: none; /* später auf flex umstellen */
justify-content: center;
align-items: center;
}
Durch die letzten zwei Zeilen erreichen wir das Zentrieren. Zunächst setzen wir das ganze zwar auf display:none
, aber im JavaScript setzen wir die Box auf display:flex
, sobald das Dialogfenster angezeigt werden soll.
Programmierung
Die Programmierung ist sehr simpel. Es geht lediglich darum, das div
mit dem Modalfenster sichtbar zu schalten. Dazu legen wir das div
in einer Variablen ab:
var modal = document.getElementById('modal-cover');
Anschließend definieren wir eine Funktion für das Einschalten. Wir wählen hier display:flex
statt display:block
, weil wir die Flexbox zum Zentrieren des Modalfensters nehmen:
function show_modal() {
modal.style.display = 'flex';
}
Jetzt schreiben wir noch einen Handler für das Schließen und binden ihn an den Close-Button:
document.getElementById('modal-close').addEventListener('click', function() {
modal.style.display = 'none';
});
Das Modalfenster aktivieren wir nach einem Timeout von einer Sekunde:
setTimeout(show_modal, 1000);
Hier zum Anschauen und Runterladen:
5.4.3 Akkordeon
Als "Akkordeon" (engl. accordion) bezeichnet man ein Interface, das von mehreren Textabschnitten nur die Titel anzeigt und die Inhalte erst bei Klick anzeigt. Diese Methode sorgt für Übersichtlichkeit.
Das heißt, bei einem Click auf eine Überschrift wird jeweils der darunter liegende Abschnitt angezeigt. Die anderen Abschnitte werden versteckt.
Wenn Sie z. B. auf Vorlesung 2 klicken, sehen Sie:
Layout
Das Layout in HTML sieht wie folgt aus:
Man umgibt das gesamte Akkordeon mit einem <div>
mit Klasse "accordion". Jeder aufklappbare Abschnitt besteht aus einer Überschrift h2
und einem weiteren <div>
.
<h1>Meine Vorlesungen</h1>
<div class="accordion">
<h2>Vorlesung 1</h2>
<div>
<p>
Lorem ipsum ...
</p>
<p>
Lorem ipsum ...
</p>
</div>
<h2>Vorlesung 2</h2>
<div>
<p>
Lorem ipsum ...
</p>
<p>
Lorem ipsum ...
</p>
</div>
...
</div>
Programmierung
Wir schreiben unseren JavaScript-Code wieder direkt in die HTML-Datei am Ende des <body>
:
<body>
...
<script>
...
</script>
</body>
Als erstes schreiben wir uns eine Funktion, die alle Abschnitte einklappt. Dazu verwenden wir querySelectorAll
, um die Abschnitte einzusammeln. Dank des querySelectorAll
können wir forEach
verwenden, um das Styling aller Abschnitte auf display:none
zu setzen.
function collapseAll() {
document.querySelectorAll('.accordion>div')
.forEach(function(el) {
el.style.display = 'none';
});
}
Als nächstes hängen wir an alle h2
-Elemente einen Handler, der auf einen Klick reagiert.
document.querySelectorAll('.accordion>h2')
.forEach(function(x) {
x.addEventListener('click', function() {
...
});
});
Bei einem Klick sollen
- alle Abschnitte mit unserer Funktion
collapseAll
eingeklappt werden und dann - der Abschnitt, der zur angeklickten Überschrift gehört, aufgeklappt werden.
Wir bekommen den Abschnitt, der zur angeklickten Überschrift gehört, mit nextElementSibling
, da er der nächste Geschwisterknoten hinter der h2
-Überschrift ist.
document.querySelectorAll('.accordion>h2')
.forEach(function(x) {
x.addEventListener('click', function() {
collapseAll();
this.nextElementSibling.style.display = 'block';
});
});
Kompletter Code
Hier nochmal der komplette JavaScript-Code. Er erlaubt zusätzlich das Einklappen aller Abschnitte, wenn man auf die Gesamtüberschrift klickt.
<script>
// Klappt alles ein
function collapseAll() {
document.querySelectorAll('.accordion>div')
.forEach(function(el) {
el.style.display = 'none';
});
}
// Klappt alles ein bei Klick auf Gesamtüberschrift
document.querySelector('h1').addEventListener('click',
function() {
collapseAll();
});
// Klappt angeklickten Abschnitt auf (alles andere zu)
document.querySelectorAll('.accordion>h2')
.forEach(function(x) {
x.addEventListener('click', function() {
collapseAll();
this.nextElementSibling.style.display = 'block';
});
});
</script>
Hier finden Sie das Beispiel in einer HTML-Datei zum Betrachten und Runterladen:
Variante
Ein Akkordeon funktioniert nicht immer gleich. Eine Variante ist zum Beispiel
- Beim Öffnen eines Abschnitts bleiben andere offene Abschnitte offen
- Beim Anklicken eines geöffneten Abschnitts wird dieser geschlossen
Wir benötigen zwei Änderungen. Die erste ist leicht: wir müssen lediglich das collapseAll
entfernen (hier auskommentiert):
document.querySelectorAll('.accordion>h2')
.forEach(function(x) {
x.addEventListener('click', function() {
//collapseAll();
this.nextElementSibling.style.display = 'block';
});
});
Die zweite Änderung ist, dass ein geöffnetes Element geschlossen wird. Dazu müssen wir also wissen, wie die Display-Eigenschaft gesetzt ist ('block' oder 'none'). Dazu verwenden wir getComputedStyle
:
let div = this.nextElementSibling;
getComputedStyle(div).display
Das packen wir in ein If:
let div = this.nextElementSibling;
if (getComputedStyle(div).display == 'none') {
div.style.display = 'block';
} else {
div.style.display = 'none';
}
Insgesamt sieht der Handler so aus:
document.querySelectorAll('.accordion>h2').forEach(function(x) {
x.addEventListener('click', function() {
let div = this.nextElementSibling;
if (getComputedStyle(div).display == 'none') {
div.style.display = 'block';
} else {
div.style.display = 'none';
}
});
});
Auch hier der Code zum Ansehen und Runterladen:
5.4.4 Panel mit Reitern
Eine weitere praktische Anwendung ist eine Anzeige (= Panel), die unterschiedliche Inhalte darstellt, je nachdem, welcher Reiter (auch Tab genannt) angewählt wurde.
Der Startbildschirm könnte so aussehen:
Beim Anklicken des vierten Reiters "Turm", wird der Reiter auf aktiv geschaltet und der Inhalt umgestellt:
Layout
Unser Layout sieht ganz grob so aus: Ein großer div
-Container, der die Reiter als ul
-Liste enthält und im Anschluss alle Inhalte mit jeweils eigenem div
.
Wir fassen das gesamte Element in ein div
mit Klasse "reiter":
<div class="reiter">
...
</div>
Innerhalb dieses Elements haben wir zunächst die Reiter als einfache Liste mit Links. Beachten Sie, dass wir das Link-Attribute href
hier für einen anderen Zweck als üblich verwenden. Dazu später. Außerdem geben wir dem jeweils aktiven Reiter die Klasse "active":
<ul>
<li class="active"><a href="eins">Pusteblume</a></li>
<li><a href="zwei">Hase</a></li>
<li><a href="drei">Dinosaurier</a></li>
<li><a href="vier">Turm</a></li>
</ul>
Die vier Inhalte packen wir jeweils in ein div
, jeweils mit eindeutiger ID. Hier sei nur ein Beispiel gezeigt:
<div id="eins">
<h1>Pusteblume</h1>
<p>
Lorem ipsum ...
</p>
</div>
Sie sehen vielleicht schon, dass die ID mit dem dazugehörigen href
in der Reiterliste übereinstimmt. Wir stellen später über JavaScript die Verbindung her.
Wir gehen hier nicht weiter auf das Styling ein. Schauen Sie sich den Quelltext im Beispiel an, um zu sehen, wie hier gestylt wurde.
Programmierung
Für die Programmierung benötigen wir folgende Schritte:
- An jeden Reiter einen Handler binden
- Im Handler
- den angeklickten Reiter auf aktiv schalten
- den dazugehörigen Content anzeigen (alle anderen verstecken)
- Content vom ersten Reiter anzeigen
Zunächst müssen wir Handler an die Reiter binden. Wir binden die Handler an die li
-Elemente, damit die komplette Box als Link funktioniert. Wenn wir nur das a
ansprechen, gibt es Bereiche innerhalb der Box, die nicht klickbar sind.
document.querySelectorAll('.reiter li').forEach(...);
In dem forEach
wird jedes Listenelement (= Reiter) durchlaufen. Wir hängen an jedes Element einen Click-Handler:
document.querySelectorAll('.reiter li').forEach(el => {
el.addEventListener('click',
event => {
...
});
})
});
Im Handler müssen wir zunächst verhindern, dass eine normale Link-Aktion ausgeführt wird. Das machen wir mit
event.preventDefault();
Anschließend entfernen wir aus allen Reitern die Klasse "active" und fügen Sie nur dem aktuell angeklickten Element hinzu:
for (let ch of el.parentNode.children) {
ch.classList.remove('active');
}
el.classList.add('active');
Zu guter Letzt beziehen wir das Attribut href
aus dem Link (erstes Kind des aktuellen Listenelements).
let ref = el.firstElementChild.getAttribute('href');
Dies ist genau gleich der ID des div
-Elements, das den Inhalt enthält. Also holen wir uns das:
let div = document.getElementById(ref);
Jetzt durchlaufen wir alle div
-Einheiten im Reiter und schalten diese auf unsichtbar, mit Ausnahme des ausgewählten div
, das wir uns ja gemerkt haben:
let inhalte = document.querySelectorAll('.reiter div')
.forEach(function(el) {
if (el !== div) {
el.style.display = 'none';
} else {
el.style.display = 'block';
}
});
Der gesamte Code sieht so aus:
document.querySelectorAll('.reiter li')
.forEach(el => {
el.addEventListener('click', event => {
// verhindern, dass Link verfolgt wird
event.preventDefault();
// Markierung aktiver Reiter
for (let ch of el.parentNode.children) {
ch.classList.remove('active');
}
el.classList.add('active');
// Reiterinhalt zeigen
let ref = el.firstElementChild.getAttribute('href');
let div = document.getElementById(ref);
let inhalte = document.querySelectorAll('.reiter div')
.forEach(function(el) {
if (el !== div) {
el.style.display = 'none';
} else {
el.style.display = 'block';
}
});
})
});
Und hier nochmal zum ausprobieren und anschauen:
5.4.5 Formular validieren
Bei Formularen möchten Sie häufig eine erste Korrektheits-Kontrolle durchführen, noch bevor Sie die Daten zum Server schicken. Zum Beispiel wollen Sie sicherstellen, dass das Namensfeld nicht leer ist oder bei einer e-Mail-Adresse checken, ob die grobe Struktur stimmt.
Layout
Nehmen wir uns ein einfaches Beispielformular:
<form method="get" action="fertig.html">
<label>Name:</label>
<input type="text" name="username"/>
<br/>
<button type="submit" value="Abschicken"/>
</form>
<p id="feedback"></p>
Wir haben hier schon ein Feld für mögliche Rückmeldungen (Feedback) eingerichtet. Das form
-Element kennzeichnet das Formular. Bei dem input
-Element handelt es sich um ein Eingabfeld, label
ist die zugehörige Beschriftung. Mehr Infos zu Formularen bekommen Sie noch in Kapitel 7.
Programmierung
Wir schreiben jetzt eine JavaScript-Funktion, die das Namensfeld prüft. Dazu verwenden wir document.forms
und nehmen dort das erste Element (wir gehen davon aus, dass es das einzige Formular auf der Seite ist). Sie sehen, dass das Formular wiederum als assoziativer Array gespeichert ist und Sie mit "username" auf das Textfeld zugreifen können.
Ist das Namesfeld leer, wird eine Meldung in das bislang leere p
-Element geschrieben und es wird der Wert false
zurückgegeben.
<script type="text/javascript">
function validate() {
let name = document.forms[0]['username'].value;
let feedback = document.getElementById('feedback');
if (name == "") {
feedback.innerText = "Geben Sie bitte Ihren Namen ein.";
return false;
} else {
feedback.innerText = "";
}
}
</script>
Es fehlt noch der Aufruf der Funktion. Diesen positionieren wir in form
im Attribut onsubmit
. Mit dem return
können wir steuern, ob das Formular abgeschickt wird. Hier wird bei der Rückgabe von false
das Abschicken verhindert.
<form method="get" onsubmit="return validate()" action="js_fertig.html">
...
</form>
Alternative
In diesem speziellen Beispiel gibt es auch eine einfachere Lösung: Sie können dem Browser mitteilen, dass das Eingabefeld notwendig ist. Das machen Sie mit dem Attribut required
:
<input type="text" name="username" required/>
Dann können Sie sich den JavaScript-Code sparen. Der Browser verhindert jetzt das Abschicken, wenn das Feld leer bleibt und informiert den User.
5.5 Übungen
5.5.1 Erste Schritte
(E1) JavaScript-Datei einbinden
Schreiben Sie eine HTML-Datei und legen Sie eine JavaScript-Datei an. Verknüpfen Sie die beiden und rufen Sie in der JavaScript-Datei die folgende Zeile auf:
console.log("JavaScript is running...");
Schauen Sie sich diese Datei an, wenn Sie Probleme haben:
Sie können auch diesen Befehl ausprobieren:
alert("Hello, world!");
(E2) Datum anzeigen
Erstellen Sie eine HTML-Datei "heute.html" mit folgendem leeren Element:
<p id="message"></p>
Fügen Sie unterhalb davon (aber innerhalb von body
) ein JavaScript-Element ein:
<script>
let d = new Date();
</script>
Zurzeit wird dort ein neues Objekt angelegt, welches das aktuelle Datum enthält. Sehen Sie sich die Funktionsweise von Date bei JavaScript Date Reference an.
Ergänzen Sie den Code so, dass beim Laden der Seite das aktuelle Datum angezeigt wird:
Probieren Sie auch, die Uhrzeit mit darzustellen:
Beziehen Sie das p
-Element mit document.getElementById()
und befüllen Sie es mit innerText
.
5.5.2 Manipulation des DOM
Laden Sie sich die Datei js_headlines.html herunter. Sie sehen Überschriften und Texte:
Fügen Sie einen JavaScript-Bereich am Ende des <body>
ein und versuchen Sie die folgenden Aufgaben zu lösen.
(M1) Alle Absätze einfärben
Färben Sie alle <p>
-Elemente mit Hilfe einer For-Schleife ein.
Nutzen Sie
document.getElementsByTagName('p')
oder
document.querySelectorAll('p')
um die Elemente einzusammeln.
Anschließend setzen Sie die Eigenschaft style.backgroundColor
auf die gewünschte Farbe.
(M2) Absätze interaktiv einfärben
Färben Sie jetzt nur den Absatz ein, den die Maus berührt (Mouseover-Effekt). Natürlich könnten Sie das auch ganz einfach im CSS mit :hover
erreichen, aber wir wollen es hier mit JavaScript probieren.
Durchlaufen Sie alle p
-Elemente und benutzen Sie addEventListener
, um bei dem Event 'mouseenter' den Hintergrund auf gelb zu setzen.
Außerdem müssen Sie beim Verlassen (Event 'mouseleave') den Hintergrund wieder auf weiß setzen, sonst verbleiben alle berührten Absätze mit gelben Hintergrund.
(M3) Tabelle einfärben
Laden Sie sich die Datei js_table.html herunter. Dort sehen Sie eine Tabelle:
Ihre Aufgabe ist es, jede zweite Zeile mit der Farbe 'cyan' zu unterlegen, um die Tabelle lesbarer zu machen. Auch hier würde man normalerweise CSS verwenden, aber es ist eine gute Übung.
Tipp: Sie können - wie in Java - den Modulo-Operator %
verwenden, um zwischen geraden und ungeraden Zahlen zu unterscheiden.
(M4) Tabelle interaktiv
Nehmen Sie die gleiche Tabelle aus der vorigen Aufgabe und machen Sie die Zeilenmarkierung interaktiv, d. h. dort, wo die Maus ist, soll die komplette Zeile mit 'cyan' hinterlegt werden.
Tipp: Nutzen Sie wieder die Events 'mouseenter' und 'mouseleave'.
(M5) Überschriften nummerieren
Schreiben Sie JavaScript-Code, der alle h2
-Überschriften mit einer Nummerierung versieht:
Schauen Sie, ob Sie mehrere Überschriften-Elemente aufsammeln können. Bei der Beispielseite geht das mit
document.getElementsByTagName('h2')
Alternativ können Sie querySelectorAll
verwenden. Bei letzterer Funktion können Sie forEach
verwenden wie oben beim Akkordeon-Beispiel. Bei getElementsByTagName
müssen Sie eine Schleife bauen.
Außerdem benötigen Sie innerText
, um den Text zu modifizieren, und offensichtlich müssen Sie die Überschriften "zählen".
(M6) Überschriften der nächsten Ebene nummerieren
Anschließend können Sie versuchen, auch die nächste Ebene zu nummerieren:
Hier ist es ratsam, durch die Menge aller H2- und H3-Überschriften zu laufen und dann mit Hilfe der Eigenschaft nodeName
zu schauen, ob man eine H2- oder H3-Überschrift vor sich hat (Vorsicht: Sie müssen bei diesem Text "H2" schreiben, nicht "h2").
5.5.3 Interaktion
(I1) Ask Yoda
Zeigen Sie einen Button, auf dem steht "Ask Yoda". Wenn der User auf den Button drückt, wird eine Weisheit von Yoda angezeigt (googlen Sie nach "yoda quotes", wenn Sie Inspiration brauchen).
Verwenden Sie das HTML-Element button
für den Button. Binden Sie Ihre Funktion am besten mit Hilfe von addEventListener
an das Element. Für das Zitat richten Sie ein leeres p
-Element mit einer ID ein und befüllen Sie es im Event-Handler mit Hilfe von innerText
.
Schön wäre es, wenn Sie ein Array von Zitaten vorhalten und mit Hilfe von Math.random() ein zufälliges Zitat bei jedem Knopfdruck zeigen.
(I2) Passwortabfrage für Dummies
So wie hier dargestellt, sollte man auf keinen Fall Passwörter behandeln. Dies ist rein für Übungszwecke!
Nehmen Sie folgendes Formular und prüfen Sie in JavaScript, ob als Passwort "secret" eingegeben wurde:
<form method="get" onsubmit="return validate()">
<label>Name:</label>
<input type="text" name="username"/><br/>
<label>Passwort:</label>
<input type="password" name="passwort" />
<br/>
<input type="submit" value="Login"/>
</form>
<p id="feedback"></p>
Wenn das Passwort "secret" war, schreiben Sie "Richtig!" in das Feedback-Feld, sonst schreiben Sie "Sorry, das war falsch".
Warum ist diese Abfrage so "dumm"? Ganz klar: jeder kann das Passwort sehen, sobald man den Quellcode der Seite betrachtet.
(I3) Klappbare Seitenleiste
Laden Sie sich das folgende Grid-Seitenlayout herunter:
Fügen Sie JavaScript-Code hinzu, so dass bei Knopfdruck die Seitenleiste verschwindet. Beim nächsten Knopfdruck soll diese wieder erscheinen.
Verändern Sie die Grid-Anordnung und schalten Sie die Seitenleiste (aside) auf display:none
oder display:block
. Um zu unterscheiden, ob Sie die Leiste ein- oder ausblenden müssen, untersuchen Sie genau diese Eigenschaft display
mit einem if
.
(I4) Automatische Einblendung
Kennen Sie auch diese nervigen Erinnerungen, die nach einer Weile irgendwo am Rand erscheinen (oder auch in der Mitte). Sie sollen jetzt eine solche Erinnerung programmieren.
In Ihrem HTML definieren Sie das Fenster zunächst mal:
<div id="window">
Subscribe!
<button type="button" id="closebutton">X</button>
</div>
Das Styling aus dem Screenshot bekommt man mit den folgenden CSS-Regeln. Insbesondere wird das Element zunächst unsichtbar geschaltet mit display:none
:
#window {
display: none;
width: 200px;
height: 80px;
position: fixed;
bottom: 0;
right: 30px;
border-radius: 20px 20px 0 0;
background-color: orange;
color: white;
font-size: 25px;
justify-content: center;
align-items: center;
box-shadow: 4px -6px 30px -10px rgba(0,0,0,0.5)
}
button {
background-color: white;
padding: 5px;
border-style: none;
}
Schreiben Sie JavaScript-Code mit dem (a) das Fenster nach 2 Sekunden erscheint (siehe dazu die Funktion setTimeout
) und (b) der Button das Verschwinden des Fensters verursacht (wieder mit display
).
(I5) Schriftgröße ändern
Erstellen Sie eine HTML-Seite, die ungefähr so aussieht:
Die oberen zwei Elemente sind Buttons, mit denen man die Schriftgröße des Dokuments in 5-Pixel-Schritten verstellen können soll.
Verwenden Sie Elemente vom Typ button
für die Buttons:
<button type="button" id="plus">+</button>
<button type="button" id="minus">-</button>
Wie immer sollten Sie den JavaScript-Code erst im JavaScript-Teil an die Buttons hängen (mit addEventListener
). Noch ein Tipp: wenn Sie die aktuelle Schriftgröße beziehen, hängt da in der Regel ein "px" dran. Arbeiten Sie mit substring
, um das abzuschneiden. Mit parseInt
können Sie einen String in eine Zahl wandeln.
Sie können den folgenden Basiscode verwenden:
(I6) Elemente nach Tags filtern
Es sei eine Webseite mit Boxen gegeben. Diese Boxen haben Schlagworte oder Tags. Sie sollen eine Reihe von Filter-Buttons generieren, so dass auf Knopfdruck nur die Boxen bleiben, die diese Tags aufweisen.
Nach Drücken auf "cat" zeigt sich dieses Bild:
Verwenden Sie den folgenden Basiscode und fügen Sie JavaScript hinzu:
Bei den Boxen sehen Sie folgende Attribute:
<div class="box" data-tags="panda,big">
panda,big
</div>
Die Schreibweise beim Attribut "data-tags" erlaubt ein besonders elegantes Auslesen des Attributs in JavaScript. Wenn die Variable bx
eine solche Box enthält, greifen Sie so auf das Attribut data-tags
zu:
bx.dataset.tags
Siehe auch Using data attributes .
Tipps zum Vorgehen:
- Sammeln Sie alle Tags in einem
Set
- Generieren Sie Buttons für alle Tags (und einen speziellen Button "all")
- Erstellen Sie einen assoziativen Array, in dem für jeden Tag eine Liste der Elemente gespeichert wird, die diesen Tag haben
- Bei Filtern nach einem bestimmten Tag x löschen Sie zunächst alle Elemente (
display:none
) und stellen dann nur solche Elementen mit dem Tag x wieder sichtbar
Styling-Vorschlag für die Buttons oben:
button {
font-family: Helvetica, sans-serif;
font-size: 18px;
margin: 10px;
padding: 4px 10px;
background-color: gray;
color: white;
border-radius: 8px;
border-style: none;
}