diff --git a/css.html b/css.html index 288e4d9..86e63f2 100644 --- a/css.html +++ b/css.html @@ -43,9 +43,9 @@
Betrachten wir als Beispiel ein JavaScript, dass die Eingaben eines Formulars überprüft. Beim Absenden des Formulars wird eine Handler-Funktion für das Ereignis submit
aktiv. Diese Funktion soll fehlerhafte Formularfelder rot markieren.
Nehmen wir an, die input
-Eingabefelder sind standardmäßig im Stylesheet so formatiert:
input { - padding: 4px 6px; - border: 1px solid #555; - background-color: #fafafa; + padding: 4px 6px; + border: 1px solid #555; + background-color: #fafafa; }
Im Stylesheet wird nun eine Regel definiert mit den Eigenschaften für fehlerhafte Felder. Wir nutzen dazu einen Selektor mit dem Elementnamen input
kombiniert mit der Klasse fehlerhaft
:
input.fehlerhaft { @@ -58,43 +58,43 @@Stylesheet-Regeln auf ein Element anwenden
element.className = 'klassenname';In der beispielhaften Formularüberprüfung kann das Setzen der Klasse folgendermaßen aussehen: Wir definieren eine Funktion
formularÜberprüfung
, die als Handler für das Ereignissubmit
registriert wird (siehe Ereignisverarbeitung). In dieser Funktion wird das zu überprüfende Formularfeld über das DOM mittelsdocument.getElementById
herausgesucht. Ist der Wert des Feldes leer, wird eine Meldung ausgegeben und das Feld bekommt die Klassefehlerhaft
.function formularÜberprüfung () { - // Spreche das Formularfeld über das DOM an und - // speichere es in eine Variable zwischen: - var element = document.getElementById("kontaktformular-name"); - // Prüfe den Feldwert: - if (element.value == "") { - // Zeige im Fehlerfall ein Hinweisfenster: - window.alert("Bitte geben Sie Ihren Namen an."); - // Weise dem Element die Klasse »fehlerhaft« zu: - element.className = 'fehlerhaft'; - // Setze den Fokus auf das Feld: - element.focus(); - // Verhindere das Absenden des Formulars - // (unterdrücke die Standardaktion des Ereignisses): - return false; - } + // Spreche das Formularfeld über das DOM an und + // speichere es in eine Variable zwischen: + var element = document.getElementById("kontaktformular-name"); + // Prüfe den Feldwert: + if (element.value == "") { + // Zeige im Fehlerfall ein Hinweisfenster: + window.alert("Bitte geben Sie Ihren Namen an."); + // Weise dem Element die Klasse »fehlerhaft« zu: + element.className = 'fehlerhaft'; + // Setze den Fokus auf das Feld: + element.focus(); + // Verhindere das Absenden des Formulars + // (unterdrücke die Standardaktion des Ereignisses): + return false; + } } function init () { - // Starte die Ereignis-Überwachung mittels - // traditionellem Event-Handling - document.getElementById("kontaktformular").onsubmit = formularÜberprüfung; + // Starte die Ereignis-Überwachung mittels + // traditionellem Event-Handling + document.getElementById("kontaktformular").onsubmit = formularÜberprüfung; } window.onload = init;Der zugehörige HTML mit den nötigen IDs könnte so aussehen:
<form action="…" method="post" id="kontaktformular"> - <p><label> - Ihr Name: - <input type="text" name="name" id="kontaktformular-name"> - </label></p> - … weitere Felder … - <p><input type="submit" value="Absenden"></p> + <p><label> + Ihr Name: + <input type="text" name="name" id="kontaktformular-name"> + </label></p> + … weitere Felder … + <p><input type="submit" value="Absenden"></p> </form>Der Clou dieser Vorgehensweise ist, dass Sie mit dem Setzen der Klasse an einem Element nur eine minimale JavaScript-Änderung vornehmen. Diese Änderung führt dazu, dass eine Regel aus dem Stylesheet plötzlich auf bestimmte Elemente greift – der Browser wendet daraufhin automatisch die definierten Formatierungen an.
Über dieses Modell können Sie auch komplexere Aufgabenstellungen lösen, denn Ihnen stehen alle Möglichkeiten von CSS-Selektoren zu Verfügung. Beispielsweise können Sie mittels Nachfahrenselektoren Elemente formatieren, die unterhalb des mit der Klasse markierten Elements liegen. So können Sie durch die Änderung der Klasse gleich mehrere enthaltene, im DOM-Baum unterhalb liegende Elemente formatieren, ohne diese einzeln anzusprechen.
-TODO: Beispiel dazu
+TODO: Beispiel dazu. Mit Nachfahrenselektoren größere Umformatierungen vornehmen, ohne alle Elemente einzeln anzusprechen
@@ -174,7 +174,7 @@Komfortables Hinzufügen, Löschen und Abfragen von Klassen
Die oben vorgestellte Methode zum Setzen der Klasse ist stark vereinfacht und hat verschiedene Nachteile. Ein HTML-Element kann nämlich mehreren Klassen angehören. Die JavaScript-Eigenschaft
@@ -108,37 +108,37 @@className
enthält dann eine Liste von Klassen, die durch Leerzeichen getrennt werden.Komfortables Hinzufügen, Löschen und Abfragen von Klassen
Falls Sie keine Fertigbibliothek nutzen, können Sie diese Helferfunktionen dennoch in ihre Scripte aufnehmen. Eine mögliche Umsetzung als lose globale Funktionen sieht folgendermaßen aus:
function addClass (element, className) { - if (!hasClass(element, className)) { - if (element.className) { - element.className += " " + className; - } else { - element.className = className; - } - } + if (!hasClass(element, className)) { + if (element.className) { + element.className += " " + className; + } else { + element.className = className; + } + } } function removeClass (element, className) { - var regexp = addClass[className]; - if (!regexp) { - regexp = addClass[className] = new RegExp("(^|\\s)" + className + "(\\s|$)"); - } - element.className = element.className.replace(regexp, "$2"); +var regexp = addClass[className]; + if (!regexp) { + regexp = addClass[className] = new RegExp("(^|\\s)" + className + "(\\s|$)"); + } + element.className = element.className.replace(regexp, "$2"); } function hasClass (element, className) { - var regexp = addClass[className]; - if (!regexp) { - regexp = addClass[className] = new RegExp("(^|\\s)" + className + "(\\s|$)"); - } - return regexp.test(element.className); + var regexp = addClass[className]; + if (!regexp) { + regexp = addClass[className] = new RegExp("(^|\\s)" + className + "(\\s|$)"); + } + return regexp.test(element.className); } function toggleClass (element, className) { - if (element.hasClass(className)) { - element.removeClass(className); - } else { - element.addClass(className); - } + if (element.hasClass(className)) { + element.removeClass(className); + } else { + element.addClass(className); + } }Alle Funktionen erwarten jeweils zwei Parameter, nämlich das Elementobjekt und den gewünschten Klassennamen als String. Folgende Beispiele sollen die Anwendung illustrieren:
// Element ansprechen und Elementobjekt in einer Variable zwischenspeichern: @@ -151,9 +151,9 @@Komfortables Hinzufügen, Löschen und Abfragen von Klassen
toggleClass(element, "beispielklasse"); // Vorhandensein einer Klasse prüfen: if (hasClass(element, "beispielklasse")) { - window.alert("Klasse gefunden."); + window.alert("Klasse gefunden."); } else { - window.alert("Klasse nicht gefunden."); + window.alert("Klasse nicht gefunden."); }Mit diesen Funktionen in Ihrem JavaScript-Werkzeugkasten können Sie das Zusammenspiel von JavaScript-Interaktivität und Stylesheet-Formatierungen komfortabel und übersichtlich meistern.
Das
style
-Objekt als Schnittstelle zu Inline-Stylesdocument.getElementById("beispielID").style.backgroundColor = "red";Als Werte müssen Sie stets Strings angeben genau in der Form, wie sie in CSS spezifiziert sind. Das gilt auch für Zahlenwerte, die eine Einheit erfordern:
element.style.marginTop = 15; // Falsch! - element.style.marginTop = "15px"; // Richtig+element.style.marginTop = "15px"; // Richtig
style
ist nicht zum Auslesen der gegenwärtigen Eigenschaftswer
<p id="mit-inline-styles" style="color: red">Element mit Inline-Styles</p>
// Gibt einen leeren String aus: window.alert( - document.getElementById("ohne-inline-styles").style.backgroundColor + document.getElementById("ohne-inline-styles").style.backgroundColor ); // Gibt »red« aus, weil Inline-Style gesetzt wurde: window.alert( - document.getElementById("mit-inline-styles").style.backgroundColor + document.getElementById("mit-inline-styles").style.backgroundColor );
currentStyle
currentStyle
liefert meist ein ähnliches Ergebnis wie das standardisierte getComputedStyle
. In manchen Fällen gibt es jedoch Abweichungen, etwa im obigen Beispiel beim Auslesen des width
-Wertes. Der Internet Explorer gibt auto
zurück, wenn dem Element keine explizite Breite zugewiesen wurde. Für das browserübergreifende Auslesen der Box-Größe eignen sich stattdessen die Eigenschaoffset client
currentStyle
liefert meist ein ähnliches Ergebnis wie das standardisierte getComputedStyle
. In manchen Fällen gibt es jedoch Abweichungen, etwa im obigen Beispiel beim Auslesen des width
-Wertes. Der Internet Explorer gibt auto
zurück, wenn dem Element keine explizite Breite zugewiesen wurde. Für das browserübergreifende Auslesen der Box-Größe eignen sich stattdessen die Eigenschaft offsetWidth/offsetHeight
sowie clientWidth/clientHeight
.
Durch Kombination von getComputedStyle
für standardkonforme Browser und currentStyle
für den Internet Explorer können wir eine lose Helferfunktion schreiben, die uns den aktuellen CSS-Eigenschaftswert liefert. Die Funktion fragt ab, welches Objekt zur Verfügung steht, und bringt den Wert damit in Erfahrung:
function getStyleValue (element, cssProperty) { - var value = ""; - if (window.getComputedStyle) { - value = window.getComputedStyle(element, null)[cssProperty]; - } else if (element.currentStyle) { - value = element.currentStyle[cssProperty]; - } - return value; + var value = ""; + if (window.getComputedStyle) { + value = window.getComputedStyle(element, null)[cssProperty]; + } else if (element.currentStyle) { + value = element.currentStyle[cssProperty]; + } + return value; }
Bei der Anwendung wird der Funktion das Elementobjekt und ein String übergeben, der den Eigenschaftsnamen in der JavaScript-typischen Schreibweise enthält:
var currentFontSize = getStyleValue(document.getElementById("beispielID"), "fontSize"); @@ -247,21 +247,19 @@Browserübergreifendes Auslesen von CSS-Eigenschaften
Über die vorgestellten Techniken ist es nicht browserübergreifend möglich, die aktuelle Höhe und Breite einer Element-Box auszulesen. Stattdessen sollten Sie folgende Eigenschaften der Elementobjekte verwenden. Sie wurden ursprünglich von Microsoft erfunden, erfreuen sich aber breiter Browser-Unterstützung. Im Gegensatz zu getComputedStyle
und currentStyle
geben sie keine String-Werte samt Einheiten zurück, sondern direkt JavaScript-Zahlen (Number-Wert).
Über die vorgestellten Techniken ist es nicht browserübergreifend möglich, die aktuelle Höhe und Breite einer Element-Box in der Einheit Pixel auszulesen. Stattdessen sollten Sie folgende Eigenschaften der Elementobjekte verwenden. Sie wurden ursprünglich von Microsoft erfunden, erfreuen sich aber breiter Browser-Unterstützung. Im Gegensatz zu getComputedStyle
und currentStyle
geben sie keine String-Werte samt Einheiten zurück, sondern direkt JavaScript-Zahlen (Number-Werte) in der Einheit Pixel.
offsetWidth
und offsetHeight
padding
(Innenabstand) und border
(Rahmen) inbegriffen sind, margin
(Außenrahmen) hingegen nicht.padding
) und der Rahmen (border
) inbegriffen sind, der Außenrahmen hingegen (margin
) nicht.clientWidth
und clientHeight
padding
inbegriffen ist, während border
und margin
nicht eingerechnet werden. Ebenso wird eine möglicherweise angezeigte Bildlaufleiste (Scrollbar) nicht einberechnet.clientWidth
und clientHeight
margin
, border
, padding
sowie die Größe der Bildlaufleiste werden nicht einberechnet.padding
inbegriffen ist, während border
und margin
nicht eingerechnet werden. Ebenso wird die Größe einer möglicherweise angezeigte Bildlaufleiste (Scrollbar) nicht einberechnet.scrollWidth
und scrollHeight
In den meisten Fällen werden Sie die äußere Größe eines Elements benötigen, also offsetWidth
und offsetHeight
. Das folgende Beispiel gibt die Größe eines Elements aus:
var element = document.getElementById('beispielID'); window.alert("Breite: " + element.offsetWidth + "\nHöhe: " + element.offsetHeight);-
TODO: Das ist die Theorie, Browser-Unstimmigkeiten sind bei Quirksmode dokumentiert
+Falls sie die innere Größe benötigen, so können Sie zunächst die aktuellen Werte der jeweiligen padding
-Eigenschaften auslesen. Das sind padding-left
und padding-right
für die Breite bzw. padding-top
und padding-bottom
für die Höhe. Diese substrahieren sie von offsetWidth
bzw. offsetHeight
, um die tatsächliche Innengröße zu erhalten.
Hier wird Funktionausdruck notiert und die Funktion in Katze.prototype.miau
gespeichert. Beim Prototypen wird also eine Eigenschaft namens miau
angelegt. Darin steckt nun die neu angelegte Funktion. Wenn wir eine Katze
-Instanz erzeugen, so besitzt sie eine miau
-Methode.
Hier wird ein Funktionausdruck notiert und das Funktionsobjekt in Katze.prototype.miau
gespeichert. Beim Prototypen wird also eine Eigenschaft namens miau
angelegt. Darin steckt nun die neu angelegte Funktion. Wenn wir eine Katze
-Instanz erzeugen, so besitzt sie eine miau
-Methode.
Eine gleichwertige Alternativschreibweise ersetzt das Prototyp-Objekt mit einem eigenen Objekt. Dieses kann z.B. mit einem Object
-Literal notiert werden. Wenn dem Prototypen viele Eigenschaften angehängt werden, ist diese Schreibweise letztlich kürzer, als mehrfach Katze.prototype.eigenschaft = ...
zu schreiben.
-function Katze () {} - -Katze.prototype = { - miau : function () { - alert("Miau!"); - } -}; - -var maunzi = new Katze(); -mauzi.miau(); -- -
Mit dem Object
-Literal wird ein Objekt angelegt, welches eine miau
-Methode besitzt. Durch die Zuweisung an Katze.prototype
wird dieses Objekt wird zum Prototypen für alle Katze
-Instanzen.
Diese Art der Vererbung nennt man Differential Inheritance. Im Gegensatz zur klassenbasierten Vererbung werden beim abgeleiteten Objekt (der Instanz) keine Eigenschaften erzeugt. Die Instanz ist keine Kopie des Prototypen, die Instanz kann sogar leer sein, wie es Katzen-Beispiel der Fall ist. Erst wenn sich die Instanz vom Prototypen unterscheidet, wird bei der Instanz eine Eigenschaft angelegt, die einen anderen Wert als die des Prototypen besitzt. In der Glasplatten-Metapher bedeutet dies: An den Stellen, in denen die Instanz dem Prototyp gleicht, ist die Platte durchsichtig – sie delegiert . Wo sie sich unterscheidet, besitzt sie einen eigenen, andersfarbigen Zettel.
-Nehmen wir an, dass hiesige Katzen meistens von der Rasse »Europäisch Kurzhaar« sind. Anstatt dies jedes Mal beim Erzeugen anzugeben, notieren wir die Eigenschaft im Prototypen:
+Nehmen wir an, dass hiesige Katzen meistens von der Rasse »Europäisch Kurzhaar« sind. Anstatt dies jedes Mal beim Erzeugen anzugeben, legen wir die Eigenschaft beim Prototypen an:
function Katze () {} -Katze.prototype = { - rasse : "Europäisch Kurzhaar" -}; +Katze.prototype.rasse = "Europäisch Kurzhaar"; + var maunzi = new Katze(); alert(maunzi.rasse);@@ -272,6 +254,7 @@
var maunzi = new Katze(); alert(maunzi.rasse); // Derzeit noch »Europäisch Kurzhaar« - vererbt vom Prototypen + maunzi.rasse = "Perser"; alert(maunzi.rasse); // Jetzt »Perser« - eigene Eigenschaft@@ -313,11 +296,9 @@
function Katze () {} -Katze.prototype = { - pfoten : 4, - miau : function () { - alert("Miau!"); - } +Katze.prototype.pfoten = 4; +Katze.prototype.miau = function () { + alert("Miau!"); }; var maunzi = new Katze(); @@ -330,7 +311,7 @@@@ -496,17 +477,17 @@Private Objekte anstatt private Eigenschaften
// Überschreibe Methode des Prototyps: Katze.prototype.miau = function () { - alert("Wau, wau!"); + alert("Wau, wau!"); }; schnucki.miau();
function Konstruktor () {} -Konstruktor.prototype = { - // Öffentliche Eigenschaften - öffentlicheMethode : function () { - alert(this._privateMethode()); - }, - // Pseudo-private Eigenschaften - _privateEigenschaft : 1; - _privateMethode : function () { - this._privateEigenschaft++; - return this._privateEigenschaft; - } + +// Öffentliche Eigenschaften +Konstruktor.prototype.öffentlicheMethode = function () { + alert(this._privateMethode()); +}; + +// Pseudo-private Eigenschaften +Konstruktor.prototype._privateEigenschaft = 1; +Konstruktor.prototype._privateMethode = function () { + this._privateEigenschaft++; + return this._privateEigenschaft; }; var instanz = new Konstruktor(); diff --git a/organisation-ueberblick.html b/organisation-ueberblick.html index ccceb16..13f01d1 100644 --- a/organisation-ueberblick.html +++ b/organisation-ueberblick.html @@ -80,7 +80,7 @@Scripte bei DOM Ready initialisieren
$(document).ready(function () { - // Diese Funktion wird beim DOM ready ausgeführt + // Diese Funktion wird beim DOM ready ausgeführt });@@ -88,7 +88,7 @@Scripte bei DOM Ready initialisieren
$(function () { - // ... + // ... });@@ -110,8 +110,8 @@DOM-Zugriffe über Selektor-Engines
$(document).ready(function () { - // Liefert alle li-Elemente im Element mit der ID produktliste - $('#produktliste li') + // Liefert alle li-Elemente im Element mit der ID produktliste + $('#produktliste li') });@@ -127,9 +127,9 @@Zeitgemäßes Event-Handling
$(document).ready(function () { - $('#produktliste li').click(function (e) { - // ... Verarbeite Ereignis ... - }); + $('#produktliste li').click(function (e) { + // ... Verarbeite Ereignis ... + }); });