Stand: 24.04.2022
Lernziele
- Eigenen jQuery-Code in bestehende Webseiten einbinden
- Mit jQuery-Code auf Events reagieren und DOM-Elemente verändern
- Mit jQuery komplexe Elemente (z.B. Akkordeon, Reiter-Panel) erstellen können
- Unterschiede zwischen JavaScript und jQuery verstehen
jQuery ist eine kostenlose Javascript-Bibliothek, die den Umgang mit DOM-Elementen erleichtert und zusätzlich viele Effekte anbietet. jQuery nutzt dabei die wohlbekannte CSS-Syntax zur Selektion.
jQuery ist sicher die populärste Bibliothek im WWW für die Frontend-Programmierung, wurde von John Resig entwickelt und 2006 veröffentlicht. jQuery ist nicht verwechseln mit JQuery UI und jQuery Mobile. Letztere sind eigenständige Projekte mit teils ganz anderer Zielsetzung.
Als Literatur empfehlen wir folgendes Buch, das besonders Design-affine Menschen anspricht:
Jon Duckett (2015) JavaScript & jQuery: Interaktive Websites entwickeln, Wiley.
10.1 Grundlegendes
10.1.1 jQuery einbinden
jQuery ist eine JavaScript-Bibliothek. Eine Bibliothek (engl. library) ist eine Datei mit lauter (JavaScript-)Funktionen, die Sie für Ihre Programmierung verwenden können. Das heißt: Sie programmieren in JavaScript und werden dabei durch zusätzliche Funktionalität unterstützt.
Damit Ihr Code funktioniert, muss der Browser die Bibliothek laden. Um dies zu tun, hat man zwei Optionen.
jQuery-Datei selbst bereitstellen
Sie können die Bibliothek als Datei von jquery.com runterladen und anschließen auf Ihre Webseite hochladen. Auf der Webseite können Sie zwischen "compressed" und "uncompressed" unterscheiden. Ersteres bedeutet lediglich, dass alle Leerzeichen und Zeilenumbrüche entfernt sind. Das nennt man auch "minifizieren" und wird mit dem Kürzel "min" angezeigt.
In Ihrer HTML-Datei geben Sie den Ort Ihrer Datei an, zum Beispiel:
<script src="pfad-zu-jquery/jquery-3.2.1.min.js"></script>
Das Einbindung von JavaScript macht man am besten ganz am Ende des body
-Blocks, also direkt vor dem schließenden Tag </body>
.
Externe jQuery-Datei verlinken (CDN)
Alternativ können Sie auf eine Datei verweisen, die bei einem CDN (content delivery network) liegt, z. B. bei Google. Der Vorteil ist, dass die Bibliothek evtl. schon im Cache-Speicher der Browsers liegt, weil andere Webseiten das selbe CDN bemüht haben.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Auch hier gilt: Das Einbindung von JavaScript macht man am besten ganz am Ende des body
-Blocks, also direkt vor dem schließenden Tag </body>
.
Vorsicht: Es gibt eine Variante, die sich "slim" nennt. Diese stellt einige wichtige Effekte nicht zur Verfügung.
jQuery testen
Um herauszufinden, ob jQuery "da" ist, laden Sie die Seite im Browser und öffnen die JavaScript-Konsole. Geben Sie ein:
jQuery
Die Reaktion sollte klar machen, dass es sich um ein Objekt handelt.
Die Versionsnummer bekommen Sie mit
jQuery().jquery
Eigener Code
jQuery-Code wird wie JavaScript-Code eingebunden, denn es ist ja JavaScript.
Also entweder direkt im HTML:
<script>
// Ihr Code
</script>
Oder als Link auf separate Datei z. B. "script.js" im Unterverzeichnis "/js".
<script src="js/script.js"></script>
In beiden Fällen ist es wichtig, dass der eigene Code erst nach der Stelle kommt, wo die Bibliothek eingebunden wird.
Da auch jQuery immer noch JavaScript ist, hat Ihre Datei die Endung .js
.
Basis-Code
Hier ein Beispiel für eine minimale HTML-Datei, die jQuery von Google lädt und dann eine Ausgabe macht:
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<title>JavaScript</title>
</head>
<body>
<p>jQuery running...</p>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
console.log("Hello, jQuery " + jQuery().jquery + "!");
});
</script>
</body>
</html>
Sie sollten auf der Konsole sehen:
Hello, jQuery 3.3.1!
Es wird empfohlen, den jQuery-Code mit diesem Gerüst zu umgeben:
$(document).ready(function(){
...
});
So wird sichergestellt, dass der Code erst ausgeführt wird, wenn die Seite vollständig geladen ist.
10.1.2 jQuery-Befehle
Ein jQuery-Befehl macht in der Regel folgendes:
- ein oder mehrere HTML-Elemente auswählen
- eine Aktion auf diesen Elementen ausführen (z. B. unsichtbar schalten)
Die Basis-Syntax ist:
$(selektor).aktion();
Beispiele sind:
$('p').hide();
$('.test').hide();
Diese Form
$('p').hide();
ist eine Abkürzung für
jQuery('p').hide();
Es wird zu 99% die Form mit dem $ benutzt.
Um sicher zu stellen, dass Ihr Code erst dann ausgeführt wird, wenn die Seite komplett geladen ist, betten Sie den gesamten Code ein in:
$(document).ready(function(){
// jQuery-Code, zum Beispiel:
alert('Hallo');
});
10.2 jQuery und DOM
10.2.1 Selektion und das jQuery-Objekt
Das besondere an jQuery ist, dass Sie mit den Ihnen bekannten CSS-Selektoren arbeiten können. Ergebnisse werden in einem speziellen jQuery-Objekt gespeichert, das so ähnlich wie ein JavaScript-Array funktioniert, aber kein Array ist (es ist auch keine HTMLCollection und auch keine NodeList).
Wie in CSS können Sie Elemente (p, h1, ul, a etc.), Klassen (mit Punkt) und IDs (mit #) auswählen. Als Rückgabe bekommen Sie ein jQuery-Objekt, das alle gefundenen Elemente enthält.
Zum Beispiel alle Absätze im Dokument:
$('p')
Alle Elemente mit Klasse test
:
$('.test')
Alle Absätze innerhalb eines Elements der Klasse test
:
$('.test p')
Das Element mit ID special
:
$('#special')
In jQuery ist es - wie in JavaScript - egal, ob Sie einfache oder doppelte Anführungszeichen verwenden, denn es handelt sich ja immer noch um JavaScript.
Da ein jQuery-Objekt eine Menge von Elementen enthalten kann, kann man einzelne Elemente mit der bekannten Array-Notation beziehen:
$('p')[0]
Sie bekommen hier ein Element-Objekt, wie Sie es auch dem vorigen Kapitel kennen.
10.2.2 Umgang mit dem jQuery-Objekt
(Mehr zum jQuery-Objekt auch in der offiziellen Doku: The jQuery Object)
Das jQuery-Objekt ist zusammen mit speziellen jQuery-Funktionen ein mächtiges Instrument. Auch wenn das jQuery-Objekt mehrere Elemente enthält, kann man mit einer einzigen Funktion alle diese Elemente ansprechen oder anders gesagt: die Funktion wird automatisch auf jedes Element im jQuery-Objekt angewandt.
Wir zeigen das am Beispiel der Funktion hide
(verstecken). Zunächst gibt uns ein Selektor ein jQuery-Objekt zurück, das alle Absätze im Dokument enthält:
$('p')
Wenn wir die jQuery-Aktion hide
anwenden, wird diese Aktion auf jedem Element ausgeführt. Das heißt, Sie müssen weder Schleife noch forEach einsetzen, sondern schreiben einfach:
$('p').hide();
So verstecken Sie mit einer Zeile Code alle Absätze im Dokument. Wichtig ist, dass jQuery-Funktionen wie hide
auch nur auf jQuery-Objekten arbeiten können und nicht auf den regulären Element-Objekten, die wir im letzten Kapitel kennen gelernt haben.
Sie sehen das, wenn Sie auf ein einzelnes Element zugreifen und hide
verwenden wollen.
$('p')[0].hide(); // FEHLER!
Da hier ein Element-Objekt zurückgegeben wird, können Sie keine jQuery-Funktion verwenden, sondern nur die aus dem letzen Kapitel bekannten JavaScript-Mechanismen, z. B.
$('p')[0].style.backgroundColor = 'yellow';
Wenn wir die vielen Funktionen der jQuery-Welt auch bei einzelnen Elementen nutzen möchten, müssen wir eine andere Art des Zugriffs wählen.
Auf Elemente im jQuery-Objekt zugreifen
Die Grundidee ist, dass wir ein Element aus einem jQuery-Objekt herausgreifen und dies wieder als jQuery-Objekt (das nur ein Element enthält) zurückbekommen. Damit das funktioniert, muss man anstatt der Array-Notation die Methode eq()
(für equals) verwenden. Diese gibt das Element zurück, das mit dem Index angegeben ist (startet bei 0). Um den ersten Absatz im Dokument zu verstecken schreiben wir also:
$('p').eq(0).hide();
Zusätzlich gibt es die Methoden first
und last
, die jeweils das erste/letzte Element zurückgeben:
$('p').first().hide();
$('p').last().hide();
Beachten Sie, dass die Rückgaben für die obigen Funktionen auch wieder jQuery-Objekte sind, d. h. auch diese Objekte sind im Grunde Listen, nur eben mit der Länge eins. Es ist in jQuery also irrelevant, ob Sie mit einzelnen Elementen oder einer Liste arbeiten. In der Praxis ist das sehr sinnvoll und spart eine Menge Code.
Alle Elemente durchlaufen
Wenn es eine jQuery-Aktion gibt, die Sie anwenden möchten, müssen Sie gar nicht alle Elemente eines jQuery-Objekts durchlaufen. Gibt es aber keine solche Funktion oder Sie möchten komplexere Handlungen durchführen, brauchen Sie eine Schleife oder einen Mechanismus wie forEach
.
Bei einem jQuery-Objekt funktioniert forEach
aber nicht, da es ja kein JavaScript-Array ist. Stattdessen gibt es eine eigene Methode each
, die ähnlich arbeitet. Wenn man auf jeder Entität einer Liste eine Funktion ausführen möchte, kann man das so schreiben:
$("h1").each(function(){
console.log($(this).text());
});
Das $(this)
verweist dabei auf das aktuell durchlaufene jQuery-Element.
10.2.3 Events und Event-Handling
Events sind Ereignisse, die z. B. vom User ausgelöst werden, z. B.
- click
- dblclick
- mouseenter
- mouseleave
Diese Ereignisse sind gleichzeitig jQuery-Aktionen, mit denen Sie eine eigene Funktion an Elemente binden können. Die Funktion nennt man auch hier Handler.
Hier wird für das Click-Event eine Funktion (= Event-Handler) an alle p
-Elemente gebunden:
$('p').click(function(event){
console.log(event);
});
Ähnlich wie bei JavaScript wird der Handlerfunktion ein Event-Objekt übergeben, das Informationen wie Zeitpunkt des Clicks enthält. Alle Informationen dazu finden Sie in der Event Object API.
$('p').click(function(event){
console.log(event.timeStamp);
});
Die Zeit wird in Millisekunden seit dem 1.1.1970 gemessen.
Wenn Sie diese Infos nicht benötigen, definieren Sie den Handler einfach ohne Parameter:
$('p').click(function(){
// Ihr Code!!
});
Innerhalb Ihres Event-Handlers können Sie mit $(this)
auf das Element zugreifen, das den Event ausgelöst hat:
$('p').click(function(){
$(this).hide();
});
10.2.4 Elemente ändern
Inhalte ändern
Sie können mit jQuery natürlich auch auf Inhalte zugreifen und diese ändern. Im Gegensatz zu DOM-Objekten - wo man mit Eigenschaften arbeitet - funktioniert der Zugriff in jQuery über Getter- und Setter-Methoden.
Den HTML-Text bekommen Sie mit der Getter-Methode html
:
foo = $('p').html();
Zu beachten ist hier, dass nur der HTML-Text des ersten gefundenen Elements zurückgegeben wird. Da jQuery-Objekte immer mehrere Elemente enthalten müssen, müssen Sie bei jeder Funktion wissen, wie damit umgegangen wird. Bei text
wird z. B. der Text aller Elemente zusammenkopiert (s. u.).
Vergleichen wir den Code mit JavaScript:
document.getElementsByTagName('p')[0].innerHTML
Sie ändern HTML-Elemente in jQuery mit der Setter-Methode html
. Auch hier ist Vorsicht angesagt. Beim Setzen von Inhalten werden alle gefundenen Elemente geändert (nicht nur das erste):
$('p').html('I have been <strong>clicked</strong>!');
Möchten Sie nur das erste Element ändern, müssen Sie first
oder eq
einbauen:
$('p').eq(0).html('I have been <strong>clicked</strong>!');
Auch hier der Vergleich zu JavaScript:
document.getElementsByTagName('p')[0].innerHTML =
'I have been <strong>clicked</strong>!'
Sie sehen, dass Getter- und Setter-Methode genau gleich heißen und sich nur darin unterscheiden, dass die Setter-Methode einen Parameter erwartet, nämlich den neuen Wert.
Wollen Sie nur den Text ohne HTML-Markup, schreiben Sie:
foo = $('h1').text();
Wie bereits erwähnt, wird hier der Text aller gefundenen Elemente zusammengeklebt.
Oder Sie setzen Text (von allen gefundenen Elementen):
$('h1').text('I have been clicked!');
Schauen Sie in der jQuery-Doku nach, ob Sie den unterschiedlichen Umgang mit den Elementen herauslesen können: html() | text()
Wenn Sie mit einen Klick auf die Überschrift den Text ändern wollen, schreiben Sie z. B.
$('h1').click(function(){
$(this).html('Das ist <em>schräg</em>!');
});
Nach diesem Befehl reagieren alle h1
-Überschriften auf einen Klick mit der Änderung der Überschrift.
Styling ändern
Das Styling (CSS) ändern Sie mit:
$('h1').css('color', 'red');
Auch das können Sie in einer Interaktion verwenden: Wir möchten, dass der Hintergrund der Überschrift gelb markiert wird, wenn wir mit der Maus in das Element fahren:
$('h1').mouseenter(function(){
$(this).css('background-color', 'yellow');
});
Wenn wir wollen, dass bei Verlassen des Elements der Hintergrund wieder weiß wird, schreiben wir:
$('h1').mouseleave(function(){
$(this).css('background-color', 'white');
});
Klassen ändern
Nehmen wir an, wir haben das folgende CSS vorliegen:
.important {
font-weight: bold;
font-size: 40px;
}
.blue {
color: blue;
}
Sie können eine Klasse hinzufügen mit addClass()
:
$("button").click(function(){
$("h1,h2,p").addClass("blue");
$("div").addClass("important");
});
Sie können eine Klasse entfernen mit removeClass()
:
$("button").click(function(){
$("h1,h2,p").removeClass("blue");
});
Attribute ändern
Klassen sind Attribute, aber es gibt noch weitere Attribute wie "href" oder "src" und natürlich der ID. Sie greifen mit attr
auf ein Attribut zu. Bei mehreren Elementen im jQuery-Objekt wird das erste genommen:
$('a').eq(0).attr('href');
Auch hier haben Sie eine Setter-Variante:
$('a').eq(0).attr('href', 'index.html');
Hier werden alle Elemente verändert.
10.2.5 Verkettung
Die Ausführung einer Funktion gibt wieder das ausgewählte Objekt zurück, so dass Befehle mit Punktnotation verkettet werden können:
$("#p1").css("color","red").slideUp(2000).slideDown(2000);
Dies ist nicht nur möglich, sondern auch gute Praxis!
Ein Vorteil gegenüber der nachfolgenden Lösung ist, dass nur einmal gesucht wird (Selektion), was Rechenzeit spart.
$("#p1").css("color","red");
$("#p1").slideUp(2000);
$("#p1").slideDown(2000);
Abgesehen davon wird der Code durch Verkettung kürzer und - wenn man sich daran gewöhnt hat - auch besser lesbar.
10.2.6 Im Baum navigieren
Wie auch in JavaScript möchten wir im DOM-Baum navigieren. Schauen wir uns nochmal ein Beispiel für einen DOM-Baum an:
Die Wurzel des Dokuments bekommen Sie bei jQuery mit
$(document)
Eltern
Mit parent()
bekommen Sie den einen direkten Elternknoten, den jedes Element hat.
$("span").parent();
Mit parents()
bekommen Sie nicht nur den direkten Elternknoten, sondern auch dessen Elternknoten usw.
Im folgenden Beispiel sehen Sie, dass man in den Klammern auch noch einen Filter angeben kann.
$("span").parents("ul");
Als Anwendungsbeispiel schauen wir uns eine Liste in HTML an:
<ul>
<li>Johnny</li>
<li>Lonny</li>
<li>Donny</li>
</ul>
Vielleicht möchten Sie folgenden Mausover-Effekt erreichen: Wenn der Mauszeiger über ein Item fährt, soll das Item gekennzeichnet werden (z. B. rote Schrift). Gleichzeitig soll aber auch die gesamte Liste markiert werden (z. B. gelber Hintergrund).
Dann schreiben Sie
$('li').mouseenter(function() {
$(this).css('color', 'red');
$(this).parent().css('background-color', 'yellow');
});
Außerdem müssen wir das rückgängig machen, wenn die Maus das Item verlässt:
$('li').mouseleave(function() {
$(this).css('color', 'black');
$(this).parent().css('background-color', 'white');
})
Kinder / Nachfahren
Mit children()
bekommen Sie alle Kindknoten:
$("div").children();
Auch hier können Sie zusätzlich filtern:
$("div").children(".special");
Der Befehl find()
sucht in allen Nachfahren, also allen Kindern und Kindeskindern:
$("div").find("span");
In der Anwendung verwenden Sie diese Methoden, wenn Sie in einem übergeordneten Container ein Event auffangen (z. B. Klick), aber alle enthaltenen Elemente stylen wollen (mit einer nicht-vererbbaren Eigenschaft).
Hier bekommen alle Kindelemente einen Rahmen:
$('div').click(function() {
$(this).children().css('border-style', 'solid');
})
So bekommen alle Kinder und Kindeskinder einen Rahmen:
$('div').click(function() {
$(this).find('*').css('border-style', 'solid');
})
Geschwister
Mit siblings()
bekommen Sie alle Geschwisterknoten. In einer Baumdarstellung wie oben sind das alle benachbarten Knoten mit dem selben Elternknoten.
$("h2").siblings();
Mit next()
bekommen Sie den nächsten (rechten) Geschwisterknoten:
$("h2").next();
Mit nextAll()
bekommen Sie alle Geschwisterknoten, die rechts liegen:
$("h2").nextAll();
Sie können in die Klammer noch einen Filter stecken, um z. B. nur alle Absätze zu bekommen, die unter dem h2
liegen:
$("h2").nextAll("p");
Ähnlich, aber nach links, funktionieren prev()
und prevAll()
.
Nehmen wir an, Sie möchten den Text unter h2
verstecken bzw. zeigen, wenn Sie auf die Überschrift klicken. Dann schreiben Sie:
$('h2').click(function() {
$(this).nextAll('p').toggle();
})
Listen filtern
Viele Selektoren und Funktionen liefern Listen zurück, z. B. parents(), siblings(), nextAll() usw. Es ist möglich, mit filter()
in diesen Listen zu suchen.
$("p").filter(".intro");
Mit not()
können Sie auch die Liste ausdünnen:
$(document).find('*').not('meta');
10.3 Effekte
Neben dem eleganten Ansteuern von DOM-Elementen stellt jQuery auch eine Reihe von wichtigen Effekten bereit, die sehr bequem eingebaut werden können.
10.3.1 Basiseffekte
Hide/Show
Wenn Sie auf Events reagieren reagieren möchten, indem Sie z. B. ein Bildschirmelement aus- oder einschalten, können Sie hide()
und show()
verwenden:
$(this).hide();
$(this).show();
Es gibt auch toggle()
, das ein Element zeigt, wenn es versteckt ist und umgekehrt. Es ist also so eine Art Schalter:
$(this).toggle();
Fade
Mit fadeIn
und fadeOut
können Sie ein Element weich ein- und ausblenden:
fadeIn(speed, callback)
fadeOut(speed, callback)
Die Geschwindigkeit kann optional gesetzt werden (in Millisekunden, also 1000 für eine Sekunde).
Mit "callback" ist eine Funktion gemeint, die Sie übergeben können und die nach Ende des FadeIn ausgeführt wird.
Auch hier haben Sie eine Schalterfunktion:
fadeToggle(speed, callback)
Um zu einer bestimmten Deckkraft (engl. opacity) zu faden, schreibt man:
fadeTo(speed, opacity, callback)
0 ist transparent, 1 ist voll sichtbar.
Slide
Schließlich können Sie ein Element durch "rollen" öffnen oder schließen:
slideDown(speed, callback)
slideUp(speed, callback)
slideToggle(speed, callback)
10.3.2 Animate
Mit animate()
können Sie verschiedene CSS-Eigenschaften (Abstand vom Rand, Höhe, Breite, ...) animieren. Interessant ist insbesondere, dass man mehrere Eigenschaften gleichzeitig animieren kann.
Allgemein sieht das so aus (wobei im Bereich 'css' mehrere Eigenschaften stehen können):
animate({ css }, speed, easing, callback);
Ein Beispiel:
$("button").click(function(){
$("div").animate({marginLeft:'250px'}, 2000, 'swing');
});
Ein paar Dinge muss man beachten:
- die Eigenschaft (wie oben marginLeft) muss in Camelback-Schreibweise geschrieben werden (also nicht margin-left)
- der Wert muss als String geschrieben werden
- die Zeit (speed) wird in Millisekunden angegeben
- das easing bezieht sich auf den Zeitverlauf ('swing' für ease-in/ease-out, 'linear' für linearen Verlauf)
- speed, easing und callback sind optional
- nicht alle CSS-Eigenschaften können animiert werden. Schauen Sie z. B. bei w3schools nach, welche Eigenschaften hier funktionieren
Wie erwähnt können mehrere Eigenschaften gleichzeitig animiert werden:
$("button").click(function(){
$("div").animate({
left:'250px',
opacity:'0.5',
height:'150px',
width:'150px'
});
});
Relative Werte (d. h. relativ zum aktuellen Wert) können Sie mit += und -= angeben:
$("button").click(function(){
$("div").animate({
left:'250px',
height:'+=150px',
width:'+=150px'
});
});
Mehrere Animationen werden hintereinander ausgeführt, wie hier z. B.:
$("button").click(function(){
var div=$("div");
div.animate({height:'300px',opacity:'0.4'},"slow");
div.animate({width:'300px',opacity:'0.8'},"slow");
div.animate({height:'100px',opacity:'0.4'},"slow");
div.animate({width:'100px',opacity:'0.8'},"slow");
});
Man kann auch die Punktnotation ausnutzen:
div.animate({height:'300px',opacity:'0.4'},"slow").animate({width:'300px',opacity:'0.8'},"slow");
Wie oben kann man beliebig viele Animationen aneinander reihen.
10.3.3 Browser-Events und Smooth Scrolling
Neben den bereits erwähnten Events gibt es noch die folgenden Browser-Events:
- resize()
- scroll()
Bei beiden Events kann man einen Handler an das sogenannte window
-Objekt binden.
Das resize
löst den Handler aus, sobald die Fenstergröße vom User verändert wird.
$(window).resize(function() {
console.log('resized...' + $(window).width());
});
Das scroll
löst den Handler aus, sobald der User im Fenster scrollt.
$(window).scroll(function() {
console.log('scrolling');
});
Mit Hilfe dieser Funktionen können Sie z. B. Schaltflächen verändern, wenn das Fenster sich verändert oder der User scrollt.
Smooth Scrolling
Smooth Scrolling bezieht sich auf den Effekt, dass beim Anklicken eines seiteninternen Links nicht hart gesprungen wird, sondern das Fenster zur gewünschten Stelle scrollt.
Für ein weiches Scrolling benötigen wir drei Funktionen
- preventDefault(): verhindert bei einem Click auf einen Link (
a
-Element), dass die Standardaktion (nämlich demhref
auf eine neue Seite folgen) ausgeführt wird. - offset(): gibt die Position des Elements im Gesamtdokument zurück; dies wird anhand von zwei Eigenschaften -
top
undleft
- ausgedrückt - scrollTop(wert): setzt die Scrollposition so, dass der Bereich oberhalb des sichtbaren Bereichs genauso groß ist wie der Wert. Übergibt man also 500 Pixel, so sind genau 500 Pixel oberhalb des sichtbaren Ausschnitts versteckt.
Smooth Scrolling funktioniert prinzipiell so:
- Sie hängen einen Handler an alle seiteninternen Links
- Im Handler:
- Sie unterdrücken mit preventDefault das normale Verhalten des Links
- Mit
this.hash
extrahieren Sie den ID aus dem Link und holen sich das entsprechende Element - Mit
animate
animieren Sie den gesamten Body mit Hilfe vonscrollTop
an die Stelle, wo das anvisierte Element sitzt (dessen Position beziehen Sie mitoffset
)
Schauen Sie zum Beispiel bei w3schools (einfaches Beispiel) oder bei CSS-Tricks (etwas allgemeineres Beispiel) nach, wie man Smooth-Scrolling realisiert.
Update 2020: Mittlerweile ist smooth scrolling trivial geworden. Man kann es einfach in CSS einschalten:
html {
scroll-behavior: smooth;
}
Die obige Übung ist dennoch interessant, um den Event-Mechanismus zu verstehen.
10.4 Praktische Beispiele
10.4.1 Akkordeon
Wir schauen uns jetzt an, wie wir das Akkordeon aus dem letzten Kapitel mit jQuery realisieren:
Layout
In HTML sieht die Struktur wie folgt aus:
<div class="accordion">
<h2>Vorlesung 1</h2>
<div class="section">
<p>
Lorem ipsum ...
</p>
<p>
Lorem ipsum ...
</p>
</div>
<h2>Vorlesung 2</h2>
<div class="section">
<p>
Lorem ipsum ...
</p>
<p>
Lorem ipsum ...
</p>
</div>
...
</div>
Programmierung
Wir wollen auf einen Klick auf eine h2
-Überschrift reagieren, indem wir
- alle Abschnitte zunächst zuklappen und
- den einen Abschnitt hinter dem angeklickten
h2
-Element aufklappen.
In jQuery benötigt man für jeden Schritt eine Zeile Code:
$('.accordion h2').click(function() {
$(this).siblings('div').hide();
$(this).next().show();
});
Im ersten Schritt möchten wir alle Geschwisterknoten vom H2-Element auswählen, aber eben nur die DIV's (und nicht die anderen H2) und diese dann ausschalten mit hide
. In der zweiten Zeile zeigen wir dann das DIV, welches auf das angeklickte H2 folgt.
Hier der Code zum Ausprobieren:
Zum Vergleich den JavaScript-Code. Zum Zuklappen aller Abschnitte hatten wir die Funktion collapseAll
definiert:
document.querySelectorAll('.accordion h2').forEach(function(x) {
x.addEventListener('click', function() {
collapseAll();
this.nextElementSibling.style.display = 'block';
});
});
function collapseAll() {
document.querySelectorAll('.accordion .section').forEach(function(el) {
el.style.display = 'none';
});
}
Sie würden vielleicht zustimmen, dass die jQuery-Variante nicht nur weniger Code erfordert, sondern auch deutlich lesbarer ist.
Toggle-Variante
Eine Variante des Akkordeons lässt die offenen Abschnitte einfach geöffnet, d. h. die erste Zeile fällt weg:
$('.accordion h2').click(function() {
$(this).next().show();
});
Wenn Sie jetzt aber ein zweites Mal auf die Überschrift klicken, soll der Abschnitt wieder verschwinden, beim nächsten Mal wieder auftauchen etc. Dies lässt sich ganz einfach mit der Aktion toggle
ausdrücken:
$('.accordion h2').click(function() {
$(this).next().toggle();
});
Hier nochmal zum Ausprobieren:
Roll-Effekt hinzufügen
Wir möchten jetzt das angeklickte Segment ausrollen mit Hilfe von slideDown
. Wir ändern unseren Code wie folgt.
$('.accordion h2').click(function() {
//$(this).parent().children(".section").css("display", "none");
$(this).next().slideDown();
});
Da das Verschwinden der bislang aufgeklappten Segmente nicht zu unserer Animation passt, haben wir die Zeile auskommentiert. Wir haben noch das Problem, dass bei mehrmaligem Anklicken der Überschrift, das Segment immer neu ausgerollt wird. Wir wollen also vorher testen, ob das Segment nicht schon sichtbar ist. Dazu verwenden wir die Methode css
.
$('.accordion h2').click(function() {
if ($(this).next().eq(0).css('display') == 'none') {
$(this).next().slideDown();
}
});
Wir können jetzt auch sagen: Wenn das Segment aufgerollt ist und ich klicke auf die Überschrift, dann soll das Segment wieder zurollen:
$('.accordion h2').click(function() {
if ($(this).next().eq(0).css('display') == 'none') {
$(this).next().slideDown();
} else {
$(this).next().slideUp();
}
});
Eine letzte Herausforderung ist es, immer nur ein Segment zu zeigen. Dazu müssen wir, bevor wir ein Segment öffnen, alle anderen Segmente schließen. Wir müssen dabei nicht extra checken, ob ein Segment offen ist. Die Methode slideUp
macht einfach nichts, wenn das Segment unsichtbar ist.
$('.accordion h2').click(function() {
// Alle anderen Segmente schließen
$(this).siblings('h2').each(function() {
$(this).next().slideUp();
});
if ($(this).next().eq(0).css('display') == 'none') {
$(this).next().slideDown();
} else {
$(this).next().slideUp();
}
});
Hier finden Sie die Seite mit der Slide-Funktionalität:
10.4.2 Panel mit Reitern
Auch die Reiter-gesteuerte Anzeigen von Inhalten, die wir in JavaScript kennengelernt haben, möchten wir in jQuery umsetzen:
Layout
Das Layout is genauso wie in der JavaScript-Version.
<div class="reiter">
<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>
<div id="eins">
<h1>Pusteblume</h1>
<p>
Lorem ipsum ...
</p>
</div>
...
</div>
Programmierung
Auch hier haben 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 binden wir also die Reiter. Auch hier setzen wir das Standardverhalten von Links mit preventDefault
außer Kraft:
$('.reiter li').click(function(event) {
event.preventDefault();
...
});
Als nächstes setzen wir den angeklickten Reiter auf aktiv:
$('.reiter li').click(function(event) {
event.preventDefault();
$(this).parent().children().removeClass('active');
$(this).addClass('active');
...
});
Jetzt verstecken wir erstmal alle Inhalte und stellen anschließend nur den Content auf sichtbar, der zu dem angeklickten Reiter gehört:
$('.reiter li').click(function(event) {
...
$('.reiter div').hide();
let ref = $(this).find('a').attr('href');
$('#'+ref).show();
});
Zum Schluss schalten wir den Content vom ersten Reiter auf sichtbar. Das soll immer beim Laden der Seite geschehen:
$('.reiter>div').eq(0).show();
Hier nochmal der komplette Code:
$(document).ready(function(){
$('.reiter li').click(function(event) {
event.preventDefault();
$(this).parent().children().removeClass('active');
$(this).addClass('active');
$('.reiter div').hide();
let ref = $(this).find('a').attr('href');
$('#'+ref).show();
});
$('.reiter>div').eq(0).show();
});
Zum Anschauen und Runterladen:
10.5 Vergleich JavaScript und jQuery
Wir sehen uns zentrale Funktionen in JavaScript und jQuery in direkter Gegenüberstellung an.
10.5.1 DOM-Elemente
JS
In JavaScript haben wir mit den folgenden Objekten zu tun:
- HTMLElement (oder nur Element oder Node)
- HTMLCollection
- NodeList
Beispiele:
el = document.getElementById('totop') // HTMLElement
liste = document.getElementsByTagName('h2') // HTMLCollection
nodes = document.querySelectorAll('h2') // NodeList
jQ
In jQuery hat man genau ein Objekt mit einer Liste, die eventuell nur ein Element enthält.
- jQuery-Objekt
Eine Variable, die ein jQuery-Objekt enthält, wird manchmal mit führendem Dollarzeichen geschrieben, um dies zu signalisieren.
Beispiel:
$liste = $('h1') // jQuery-Objekt
10.5.2 Listen durchlaufen
JS
Für eine HTMLCollection muss man eine For-Schleife bemühen:
let list = document.getElementsByTagName('h1');
for (let i = 0; i < list.length; i++) {
console.log(list[i].innerText);
}
For eine NodeList gibt es das forEach:
document.querySelectorAll('h1').forEach(function(el) {
console.log(el.innerText);
});
jQ
For das jQuery-Objekt gibt es das each:
$('h1').each(function(){
console.log($(this).text());
});
10.5.3 Event-Handling
JS
In JavaScript verwenden Sie addEventListener und greifen mit this auf das auslösende Element zu.
document.getElementsById('foo').addEventListener('click',
function(event) {
alert('You clicked: ' + this.innerText);
});
Der Parameter event ist ein Objekt vom Typ MouseEvent.
jQ
In jQuery nutzt man die Funktion click und greift mit $(this) auf das auslösende Element - als jQuery-Objekt - zu:
$('#foo').click(function(event) {
$(this).hide();
});
Der Parameter event ist ein Objekt vom Typ Event Object.
10.5.4 Inhalte und Styling ändern
JS
Zugriff auf den Text eines Elements:
console.log(document.getElementsByTagName('h1')[0].innerText);
Änderung des Textes:
document.getElementsByTagName('h1')[0].innerText = "Foo";
Änderung des Stylings:
document.getElementsByTagName('h1')[0].style.backgroundColor = 'yellow';
Zugriff auf das Styling:
console.log(getComputedStyle(document.getElementsByTagName('h1')[0]).color);
jQ
Zugriff auf den Text eines Elements:
console.log($('h1').eq(0).text());
Änderung des Textes:
$('h1').eq(0).text("Foo");
Änderung des Stylings:
$('h1').eq(0).css('background-color', 'yellow');
Zugriff auf das Styling:
console.log($('h1').eq(0).css('color'));
10.5.5 Zugriff auf Klassen und IDs
JS
Alle Klassen eines Elements beziehen:
console.log(document.getElementsByTagName('div')[0].classList);
Eine Klasse hinzufügen:
document.getElementsByTagName('div')[0].classList.add('foo');
Einen ID setzen:
document.getElementsByTagName('div')[0].id = 'special'
jQ
Alle Klassen eines Elements beziehen:
console.log($('div').eq(0).attr('class'));
Eine Klasse hinzufügen:
$('div').eq(0).addClass('foo');
Einen ID setzen:
$('div').eq(0).attr('id', 'special');
10.6 Übungen
10.6.1 Erste Schritte
(E1) jQuery einbinden
Schreiben Sie eine HTML-Datei, in der Sie einen script
-Teil einbetten (am Ende des Body). Davor binden Sie jQuery ein, entweder eine eigene Datei oder über einen Link auf ein CDN.
Als Code schreiben Sie:
console.log("Hier läuft jQuery-Version " + jQuery().jquery);
Laden Sie die HTML-Datei in einem Browser und schauen Sie sich die Konsole an.
Gewöhnen Sie sich an, Ihren Code mit diesen Zeilen zu umgeben:
$(document).ready(function(){
...
});
So stellen Sie sicher, dass Ihr Code erst ausgeführt wird, wenn die Seite geladen ist.
(E2) Modaldialog in jQuery
Schauen Sie sich das Beispiel "Modales Dialogfenster" im Kapitel 9.4. JavaScript im Web an.
Laden Sie sich den Code runter und ersetzen Sie - wo möglich - die JavaScript-Befehle durch jQuery-Mechanismen:
Tipp: Denken Sie daran, dass eventuell ein #
oder .
beim Selektieren fehlt, wenn Sie auf jQuery umsteigen.
Folgeaufgabe: Wenn wir schon in jQuery sind, können Sie Übergänge hinzufügen. Nutzen Sie z. B. fadeIn
, um die halbtransparente graue Fläche langsam einzublenden.
10.6.2 Manipulation des DOM
Die folgenden Aufgaben beziehen sich auf diesen Basiscode:
Sie sehen Überschriften und Texte:
In der Datei finden Sie bereits eine Verlinkung mit einer jQuery-Bibliothek und einen Code-Bereich (<script>
) für Sie.
(M1) Absätze einfärben
Nehmen Sie den Basiscode:
Implementieren Sie folgenden Mouseover-Effekte.
(a) Zunächst ein leichter Effekt: Wenn Sie mit der Maus einen Absatz berühren, soll dieser mit gelb unterlegt werden.
(b) Erweitern Sie dies, so dass sowohl Absätze als auch alle Überschriften sich so verhalten.
(c) Ein ganz anderer Ansatz: Wenn Sie mit der Maus eine Überschrift berühren, sollen alle darunter liegenden Absätze gelb eingefärbt werden (nur Absätze, keine Überschriften).
(M2) Überschriften nummerieren
Nehmen Sie wieder den Basiscode:
Hier haben wir zwei Teile:
(a) Schreiben Sie jQuery-Code, der alle h2
-Überschriften mit einer Nummerierung versieht:
Sie benötigen die jQuery-Methode text
, um den Text zu modifizieren, und offensichtlich müssen Sie die Überschriften "zählen".
(b) Anschließend versuchen Sie, die nächste Ebene zu nummerieren:
(M3) Automatisches Inhaltsverzeichnis
Nehmen Sie den folgenden Basiscode:
Erstellen Sie automatisch ein Inhaltsverzeichnis (engl. table of contents) in Form einer Liste. Dazu sammeln Sie alle Überschriften vom Typ h2
und h3
ein und erzeugen eine entsprechende Liste. Binden Sie das ganze als nav
-Element in Ihr Dokument ein.
Außerdem sollten Sie seiteninterne Links mit IDs erzeugen. Diese IDs sollte Ihr Code nach einem eigenen System erzeugen.
Ihr Dokument soll bei Erfolg so aussehen:
10.6.3 Interaktion
(I1) 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 jQuery-Code 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:
- Sammeln Sie zunächst alle Tags, die in den Elementen vorkommen in einer geeigneten Datenstruktur auf (jedes Tag darf nur einmal vorkommen)
- Generieren Sie die Buttons (HTML als String) und fügen Sie sie in die Seite ein
- Jetzt hängen Sie an jeden Button einen Listener, der zunächst alle Boxen versteckt und dann nur diejenigen zeigt, die das Tag haben. Auch hier benötigen Sie eine geeignete Datenstruktur, die für jeden Tag alle zugehörigen Boxen speichert.