jQuery
Probleme des DOM
DOM-Schnittstelle zum Browser ist schwer zu nutzen
- Zugriff über Tag-Namen oder ID
- Ständiges Suchen im DOM-Baum nach den richtigen Elementen
- Nutzt keinen der Vorteile von JavaScript (funktionale Programmierung)
- Erzeugung von Elementen ist mühselig
- Browser sind häufig inkompatibel (IE6 :-()
DOM-Operationen
- Identifikation: Wie bekomme ich eine Referenz auf den Knoten, der mich interessiert?
- Traversieren: Wie bewege ich mich durch den DOM-Baum?
- Knoten-Manipulation: Wie lese und verändere ich Eigenschaften eines DOM-Knotens?
- Baum-Manipulation: Wie ändere ich die Struktur des DOM-Baumes?
Warum jQuery?
jQuery erleichtert DOM-Programmierung erheblich
- Elemente können per Selektor (ähnlich CSS) gesucht werden
- Funktionale Programmierung (nutzt JavaScript wirklich aus)
- Sehr kompakte Syntax
Historie von jQuery
- entstand 2006 auf einem BarCamp in NewYotk
- Motto: „write less, do more“
- Open-Source
- eine der meistbenutzten JavaScript-Bibliotheken
- mit jQuery-Mobile auch für Smartphones
Was bietet die jQuery-Library?
- Viele Methoden für die Navigation im DOM
- CSS-artige Selektoren, um Elemente auszuwählen (Sizzle-Engine)
- funktionale Programmierung, um auf viele Elemente gleichzeitig zuzugreifen
- method-chaining für einen kompakten Syntax
- Behebt die meisten Browser-Inkompatibilitäten
Initialisierung mit jQuery
- Bevor das DOM aufgebaut ist, kann man keine Änderungen daran vornehmen
- Man kann jQuery eine Initialisierungsfunktion übergeben
- Funktion wird nach Aufbau des DOMs aufgerufen
Beispiel:
$(function() {
// auf dem DOM arbeiten
});
DOM vs. jQuery
jQuery vereinfacht den Zugriff, da nur noch eine Funktion benötigt wird: $
| DOM-Methode | jQuery-Methode |
|---|---|
getElementById("id") | $("#id") |
getElementsByTagName("tag") | $("tag") |
getElementsByName("somename") | $("[name='somename']") |
querySelector("selector") | $("selector") |
querySelectorAll("selector") | $("selector") |
jQuery-Selektoren
Die $-Funktion kann direkt mit CSS-Selektoren umgehen
// id-Selektor
let elem = $("#eineid");
// Gruppen-Selektor
let elems = $("#eineid, p");
// Kontext-Selektor
let elems = $("#eineid < div p");
// Komplexer Selektor
let elems = $("#eineid < h1.special:not(.classy)");
jQuery-Funktion
- die jQuery-Funktion
$()gibt immer ein Array-artiges Objekt zurück, auch bei ID-Selektoren - die DOM-Knoten werden von jQuery gekapselt, der Rückgabewert ist also kein DOM-Knoten
- will man einen DOM-Knoten, kann man ihn jederzeit auslesen
get(index)oder[index]
Beispiel: jQuery-Funktion
// false
document.getElementById("myid") == $("#myid");
document.querySelectorAll("p") == $("p");
// true
document.getElementById("myid") == $("#myid")[0];
document.getElementById("myid") == $("#myid").get(0);
document.querySelectorAll("p")[0] == $("p")[0];
Funktionsweise von jQuery (Getter)
Getter liefern normalerweise das erste Element aus der Liste zurück
<ul>
<li style="font-size: 10px">10px font size</li>
<li style="font-size: 20px">20px font size</li>
<li style="font-size: 30px">30px font size</li>
</ul>
$("li").css("font-size"); // liefert '10px'
Funktionsweise von jQuery (Setter)
Setter arbeiten auf allen Elementen der Liste
<ul>
<li style="font-size: 15px">10px font size</li>
<li style="font-size: 15px">20px font size</li>
<li style="font-size: 15px">30px font size</li>
</ul>
$("li").css("font-size", "15px"); // setzt alle Elemente auf 15px
Überladene Methoden
Viele jQuery-Methoden sind überladen
- Getter:
$("#myid").css(propertyName); - Setter:
$("#myid").css(propertyName, value);
// Multi-Setter
$("#myid").css({
'propertyName1': value1,
'propertyName2': value2,
...
});
// Modifier
$("#myid").css(propertyName, function(idx, oldValue) {
return newValue;
});
Rückgabewerte
Wenn es keinen anderen Rückgabewert gibt, gibt jQuery dasselbe Objekt zurück
| Methode | Rückgabewert |
|---|---|
$("#myId"); | jQuery object |
$("#myId").children(); | jQuery object |
$("#myId").css("margin-left"); | String |
$("#myId").css("margin-left", "10px"); | jQuery object |
$("#myId").addClass("special"); | jQuery object |
Chaining
Statt
$("#myId").css("color", "red");
$("#myId").addClass("special");
$("#myId").attr("src", "foo.png");
Schreibt man
$("#myId")
.css("color", "red")
.addClass("special")
.src = "foo.png";
DOM-Knoten zu jQuery-Objekt
DOM-Knoten in jQuery-Objekt konvertieren
let elem = document.getElementById("myId");
elem = $(elem);
let elems = document.querySelectorAll(".special");
elems = $(elems);
Das DOM traversieren
Mit DOM-Methoden
let elems = document.querySelectorAll("li");
for (let i = 0; i < elems.length; i++) {
let e = elems[i];
// e manipulieren
}
Mit jQuery
$("li").each(function(idx, e) {
// e manipulieren
});
jQuery each()-Loop
$("li").each(function(idx, e) {
// do stuff with e
});
- Mit
return falsekann man die Schleife beenden eist ein normales DOM-Objekt- Will man ein JQuery-Objekt, muss man es erneut wrappen
e = $(e);- anstatt
ekann man auchthisverwenden
Einschränken der gefundenen Knoten
Die gefundenen Knoten können eingeschränkt werden
elment.find(selector)$(selector, element)
CSS-Eigenschaften verändern (DOM)
function highlightField() {
// Text gelb setzen und vergrößern
let elem = document.getElementById("myId");
if (!elem.className) {
elem.className = "highlight";
} else if (elem.className.indexOf("invalid") < 0) {
elem.className += " highlight";
}
}
className ist kein Array, sondern nur ein String. Hierdurch ist das Setzen von Klassen recht mühselig.
CSS-Eigenschaften verändern (jQuery)
Methoden in jQuery
addClass- Klasse hinzufügenremoveClass- Klasse entfernenhasClass- Prüfen, ob Klasse vorhanden isttoggleClass- Klasse „umschalten“
function highlightField() {
// Text gelb setzen und vergrößern
if (!$("#myid").hasClass("invalid")) {
$("#myid").addClass("highlight");
}
}
Guter Stil
Schlecht
$("#main").css("top", parseInt($("#main").css("top")) + 100 + "px");
Funktioniert nicht wenn mehrere Objekte selektiert wurden.
Besser
$("#main").css("top", function(idx, old) {
return parseInt(old) + 100 + "px";
});
jQuery attr()-Funktion
Attribute setzt man mithilfe der attr(name, value)-Funktion
// schlecht
$("img")
.css("color", "red")
.addClass("special")
.src = "foo.png";
// besser
$("img")
.css("color", "red")
.addClass("special")
.attr("src", "foo.png");
So kann man weitere Methodenaufrufe anhängen.
Weitere jQuery-Methoden
Ausgehend von einem jQuery-Objekt
| Methode | Funktion |
|---|---|
.hide() | Schaltet CSS display: none on |
.show() | Schaltet CSS display: none off |
.empty() | Löscht Inhalt (innerHTML = „“) |
.html() | Liest/setzt innerHTML ohne Escaping |
.text() | Liest/setzt innerHTML mit Escaping |
.val() | Liest/setzt Inhalt eines Eingabefeldes input, select, … |
.height() | Liest/setzt die Höhe eines Elements (in Pixel) |
.width() | Liest/setzt die Breite eines Elements (in Pixel) |
DOM innerHTML hacking
Einfaches Beispiel
document.getElementById("myid").innerHTML += "<p>A paragraph!</p>";
Was spricht gegen dieses Vorgehen?
Wird sehr schnell komplex
document.getElementById("myid").innerHTML += "<p style='color: red; " +
"margin-left: 50px;' " +
"onclick='myOnClick();'>" +
"A paragraph!</p>";
Neue Knoten anlegen
document.createElement("tag")- erzeugt einen neuen (leeren) DOM-Knoten vom gegebenen Typdocument.createTextNode("text")- erzeugt einen Textknoten mit dem angegebenen Text als Inhalt
Beispiel: Einen neune H2-Knoten anlegen
let newHeading = document.createElement("h2");
newHeading.innerHTML = "This is a heading";
newHeading.style.color = "green";
Der Knoten muss noch dem DOM-Baum hinzugefügt werden
DOM-Baum verändern (hinzufügen)
Jeder DOM-Knoten hat eine Reihe von Methoden, um den Baum zu verändern
| Methode | Beschreibung |
|---|---|
appendChild(node) | Fügt Konten am Ende der Kinder an |
insertBefore(new, old) | Fügt den Knoten vor dem angegebenen Kindknoten ein |
removeChild(node) | Entfernt das angegebene Kind |
replaceChild(new, old) | Ersetzt das Kind mit einem neuen Knoten |
let p = document.createElement("p");
p.innerHTML = "A paragraph!";
document.getElementById("myid").appendChild(p);
DOM-Baum verändern (löschen)
Ein Knoten von der Seite entfernen
let bullets = document.getElementsByTagName("li");
for (let i = 0; i < bullets.length; i++) {
if (bullets[i].innerHTML.indexOf("child") >= 0) {
bullets[i].parentNode.removeChild(bullets[i]);
}
}
DOM-Manipulation mit jQuery
Einen Knoten anlegen
$("#myid").append($("<div>"));
Einen Knoten löschen
$("li:contains('children')").remove();