Moderne Webseiten beinhalten in der heutigen Zeit einen hohen Anteil clientseitiger Quellcodes in Form von JavaScript. Für diesen Anwender führt dies im Idealfall zu einer verbesserten Benutzbarkeit der Applikation, da diese neben netten UI Effekten nun meist durch Ajax auch weitaus flüssiger bedienbar ist.
Bei vielen Entwicklern solcher dynamischer Webseiten führt der vermehrte JavaScript Anteil allerdings häufig zu Wein- und/oder Schreikrämpfen, denn nur die wenigsten mögen JavaScript wirklich. Die Ursachen für diese Antipathie liegen jedoch selten an JavaScript als Sprache selbst, sondern in den meisten Fällen eher an der unterschiedlichen Implementation des DOMs / BOMs durch die verschiedenen Browserhersteller. Diese Inkonsistenz führt nämlich dazu, dass JavaScript Code, der in einem Browser bzw. einer Version eines Browsers problemlos läuft im nächsten Browser Fehler verursacht und schlichtweg nicht läuft.
Weiter wird häufig bemängelt, das Selektionen fernab von einem einfachen document.getElementById(IdMeinesElements)
relativ kompliziert sind. Als Beispiel wären hier zu nennen: alle Elemente mit einer bestimmten Klasse, ungerade Zeilen einer Tabelle, das aktivierte Element einer RadioButtonGroup usw.
Und nun?
Nun gibt es folgende Strategien mit diesen Problemen umzugehen:
- Man drückt sich immer davor JavaScript zu schreiben und wälzt dies auf einen Kollegen ab
- Man kopiert sich irgendwoher JavaScript Codeschnippsel, die angeben browserunabhängig zu sein und hofft, das dem auch so ist
- Man investiert Unmengen Zeit in die eigene browserübergreifende Implementierung diverser Funktionalitäten
- Man bedient sich eines der am Markt verfügbaren JavaScript Frameworks
Strategie Nr. 1 mag eine Weile ganz gut funktionieren, früher oder später wird aber der Zeitpunkt kommen, an dem man sich nicht mehr drücken kann (ich spreche da aus eigener Erfahrung ;-)).
Strategie Nr. 2 funktioniert immer dann, wenn der Umfang des benötigten JavaScript Codes überschaubar ist. Gemeinsam mit der Applikation wird aber auch irgendwann der zusammenkopierte Code wachsen und die Wartbarkeit entsprechend sinken.
Strategie Nr. 3 ist sicherlich eine prima Idee für alle die außerdem auch ein eigenes Logging Framework, einen eigenen OR Mapper usw implementiert haben, oder kurz gesagt für alle die gerne das Rad neu erfinden ;-)
Gangbar scheint also nur Strategie Nr. 4 zu sein. Schaut man sich nun am Markt um, stößt man unweigerlich auf jQuery. Die freie JavaScript Library adressiert unter anderem genau die zuvor genannten Probleme und hat in letzter Zeit einen wahren Hype verursacht. Dieser Rummel wurde sicherlich auch dadurch verstärkt, dass Microsoft jQuery offiziell supportet, mit Visual Studio ausliefert und die Arbeiten an der hauseigenen JavaScript Bibliothek ASP.NET Ajax Library zugunsten von jQuery eingestellt hat.
Wie legen wir nun aber mit jQuery los? Genau diese Frage möchte ich in diesem und den folgenden Blog Posts beantworten. Da jQuery in einem neuen ASP.NET MVC Projekt automatisch hinzugefügt wird und ASP.NET MVC Entwickler somit sowieso jQuery gewöhnt sind, soll als Beispiel zunächst eine Webforms Anwendung dienen.
Auf die Plätze, fertig, los!
Wenn man jQuery benutzen möchte, besteht der erste Schritt darin, die freie JavaScript Library in seine Seite einzubinden. Dazu lädt man unter http://www.jQuery.com einfach die aktuelle Version der Bibliothek herunter und kopiert diese anschließend zum Beispiel in einen Unterordner Scripts seiner Webanwendung. jQuery ist übrigens in einer für Menschen lesbaren (z. B. jQuery-1.4.2.js) und in einer verkleinerten Version (z, B. jQuery-1.4.2.min.js) verfügbar. In der verkleinerten Version sind unnötige Leerzeichen, Zeilenumbrüche und Kommentare entfernt. Außerdem wurden die Namen der Variablen und nicht öffentlichen Funktionen auf ein oder zwei Buchstaben verkürzt. Sinn dieser Maßnahme ist es die zum Client übertragene Datenmenge zu reduzieren. So ist die verkleinerte Version knappe 100 kb kleiner als die lesbare Variante. Für Produktivszenarien sollte demnach also in jedem Fall die .min Version genutzt werden, wohingegen während der Entwicklungszeit eher die lesbare Variante eingebunden werden sollte. So kann man den Scriptcode im Fall der Fälle nämlich noch debuggen.
So, genug der Vorrede und zurück zur Praxis. Tatsächlich einbinden können wir jQuery nun über folgende Zeile:
<script src="Scripts/jquery-1.4.2.js" type="text/javascript"></script>
Platzieren sollte man diese Zeile übrigens innerhalb des Kopfbereichs der Seite:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script src="Scripts/jquery-1.4.2.js" type="text/javascript"></script>
</head>
Prima, aber was mache ich nun damit?
Gute Frage! Jetzt haben wir jQuery zwar eingebunden, aber wie geht es jetzt weiter. Dazu sollten wir zunächst kurz einen Blick darauf werfen, was wir normalerweise mit JavaScript machen. In den meißten Fällen reduziert sich dies auf:
- Elemente aus dem DOM zu selektieren
- Selektierte Elemente zu manipulieren (ein- / ausblenden, Styledefinitionen zu verändern…)
- Code bei bestimmten Ereignissen ausführen (z. B. click event)
- Neue Elemente dem DOM hinzuzufügen
- Elemente aus dem DOM zu löschen
- AJAX Aufrufe zum Server zu machen und die Antwort zu Verarbeiten
Als kleinen Einstieg picken wir uns exemplarisch die ersten drei Punkte heraus. Wir werden also DOM Elemente selektieren und diese manipulieren. Geschehen wird dies bei dem Klick auf einen Button.
Dazu werden wir eine Meldungszeile, ähnlich wie man sie von Stackoverflow kennt nachbauen.
Der erste Schritt besteht in der Erstellung eines HTML und CSS Grundgerüsts:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>jQuery Demo</title>
<style type="text/css">
body
{
margin: 0px;
}
#message
{
background-color: #FFFF88;
border-bottom: solid 1px #000000;
font-weight: bold;
text-align: center;
padding: 8px;
margin: 0px;
display:none;
font-family: Arial, Verdana, Sans-Serif;
}
#message a
{
float: right;
border: solid 3px black;
font-family: Arial, Verdana, Sans-Serif;
font-weight: bold;
text-decoration: none;
color: Black;
}
</style>
</head>
<body>
<form id="form1" runat="server">
<div id="message"><span>Dummy Nachricht</span><a href="Default.aspx">X</a>
</div>
<div id="content">
<p>
Dies ist eine jQuery Demowebsite</p>
<button id="showMessage">
Klick mich</button>
</div>
</form>
</body>
</html>
Wie man sieht, wird ein DIV Element mit dem Namen message
erstellt, dass als Unterlemente ein SPAN Element und einen Link enthält. Über CSS wird dieses DIV Element noch ein wenig gestyled und initial ausgeblendet. Außerdem ist auf der Seite noch ein Button definiert. Ein Klick auf diesen Button soll der Auslöser sein, um die Meldung anzuzeigen.
Wie aber genau sieht nun der Code aus, um die Nachricht - mit verändertem Text - anzuzeigen?
Mit der Hilfe von jQuery ist dies garnicht so schwer:
$("#showMessage").click(function(evt) {
evt.preventDefault();
$("#message span").text("Du hast den Button geklickt. Klicke nun auf das X, um die Nachricht auszublenden.");
$("#message").fadeIn(2000);
});
Auf den ersten Blick mag der Code etwas verwirrend aussehen. Vor allem durch die vielen $-Zeichen. Daher ein paar erklärende Worte:
In Zeile 1 selektieren wir mit dem Befehl: $("#showMessage")
zunächst das DOM Element mit der ID showMessage, also unseren Button. Das $-Zeichen ist übrigens ein Alias für die jQuery Funktion. Statt $(“message”) hätte ich also auch jQuery("$message") schreiben können. Die Rückgabe des Aufrufs - unabhängig ob via jQuery(…) oder $(…) ist ein Objekt vom Typ jQuery. Dieses Objekt beinhaltet die selektieren DOM Elemente bzw. das selektierte DOM Element sowie einige weitere Funktionen.
In unserem Fall bekommen wir also ein Objekt vom Typ jQuery zurück, dass das DOM Element showMessage
beinhaltet. Für dieses DOM Element wird nun eine anonyme Funktion als Handler für das Ereignis Click registriert.
In Zeile 2 wird mit dem Befehl evt.preventDefault();
nun die Standardaktion die der Browser bei diesem Ereignis, also z. B. das posten des Formulars nach Klick auf den Button, verhindert.
In Zeile 3 werden anschließend alle span Elemente innerhalb des DOM Elements mit der Id message selektiert. In unserem Fall ist dies also genau eins. Für dieses span Element wird mit der Funktion text
jetzt ein neuer Text vergeben. Außerdem wird das Element mit der Id message
in Zeile 4 langsam (über einen Zeitraum von zwei Sekunden) eingeblendet.
Der Quellcode zum Ausblenden der Nachricht sieht ähnlich aus:
$("#message a").click( function(evt) {
evt.preventDefault();
$("#message").fadeOut("slow");
});
In Zeile 1 wird an alle A-Elemente innerhalb des DOM Elements mit der Id message
ein Eventhandler für das Ereignis Click angehangen. Dieser verhindert in Zeile 2 die Standardaktion des Links und blendet in Zeile 3 unsere Nachrichtenzeile wieder aus. Dieses mal wird statt einer Angabe in Millisekunden der String “slow” als Argument übergeben. Dieser ist in den jQuery Quellcodes mit einem Wert von 600 ms hinterlegt.
Perfekt, aber wo schreibe ich den Code nun rein?
So, jetzt wo wir eigentlich den ganzen Quellcode fertig haben stellt sich natürlich die Frage, wie wir ihn in unsere Seite einbinden. Eine naive Implementierung sähe wie folgt aus:
Der Code würde also einfach in ein Scripttag innerhalb des Head Tags kopiert werden. Dies läuft so nicht! Der Grund ist, dass mit diesem Code versucht wird, ein Eventhandler an ein DOM Element zu binden, das es zu diesem Zeitpunkt noch garnicht gibt.
Wie sieht aber die Lösung für das Problem aus?
Alles zu seiner Zeit
Wie wir zuvor gesehen haben, ist unser Code wirkungslos, wenn wir ihn ausführen ehe es ein entsprechendes DOM Element gibt. Daher sollten wir ihn erst auslösen, sobald das DOM vollständig initialisiert ist.
Ein weg dies zu erreichen wäre es, den Code aufzurufen wenn das Ereignis window.onload
eintritt:
window.onload = function() {
$("#showMessage").click(function(evt) {
evt.preventDefault();
// Restlicher Code hier
});
}
Diese Variante würde bereits fehlerfrei funktionieren. Allerdings wird das Ereignis onload erst ausgelöst, wenn das DOM vollständig initialisiert wurde und alle externen Ressourcen, wie zum Beispiel Bilder oder Stylesheets geladen wurden. Dies kann von Fall zu Fall recht lange dauern, so dass der Anwender den Button bereits anklicken könnte, ohne dass unser Script ausgeführt wird. Zum Glück bietet jQuery einen besseren Ansatz, nämlich $(document).ready
. In dieser Variante wird das Ereignis ready ausgelöst, sobald das DOM vollständig initialisiert wurde, aber bevor externe Ressourcen geladen wurden.
Das vollständige Beispiel mit $(document).ready
sieht dann wie folgt aus:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>jQuery Demo</title>
<script src="Scripts/jquery-1.4.1.js" type="text/javascript"></script>
<style type="text/css">
body
{
margin: 0px;
}
#message
{
background-color: #FFFF88;
border-bottom: solid 1px #000000;
font-weight: bold;
text-align: center;
padding: 8px;
margin: 0px;
display:none;
font-family: Arial, Verdana, Sans-Serif;
}
#message a
{
float: right;
border: solid 3px black;
font-family: Arial, Verdana, Sans-Serif;
font-weight: bold;
text-decoration: none;
color: Black;
}
</style>
<script type="text/javascript">
$(document).ready(function() {
$("#showMessage").click(function(evt) {
evt.preventDefault();
$("#message span").text("Du hast den Button geklickt. Klicke nun auf das X, um die Nachricht auszublenden.");
$("#message").fadeIn(2000);
});
$("#message a").click(function(evt) {
evt.preventDefault();
$("#message").fadeOut("slow");
}
}
});
</script>
</head>
<body>
<form id="form1" runat="server">
<div id="message"><span>Dummy Nachricht</span><a href="Default.aspx">X</a>
</div>
<div id="content">
<p>
Dies ist eine jQuery Demowebsite</p>
<button id="showMessage">
Klick mich</button>
</div>
</form>
</body>
</html>
Ausblick und Fazit
Wie dieser Blog Eintrag gezeigt hat, ist jQuery eine recht komfortabel zu bediene JavaScript Library, mit der sich mit wenigen Zeilen Script Code interessante Effekte erzielen lassen. Neben der intuitiven und Browser unabhängigen API besticht die Bibliothek vor allem durch die Fülle an Funktionen und erhältlichen Plug-Ins. Selbstverständlich konnte ich hier nur einen kurzen (ersten) Einblick verschaffen. Da ich das Thema Clientseitige Entwicklung in (ASP.NET) Webanwendungen jedoch für sehr interessant halte, habe ich vor in der nächsten Zeit weitere Einträge zum Thema jQuery mit folgenden Schwerpunkten zu schreiben:
- Nutzen von Content Delivery Networks (CDNs)
- jQuery Selektoren
- Möglichkeiten der DOM Manipulation
- jQuery und Firebug
- jQuery Plugins selber entwickeln
- jQuery UI
- jQuery Utility Funktionen
- jQuery und Ajax für Webforms und ASP.NET MVC
Eventuell werde ich im Anschluss an die Artikel auch kurze Video Tutorials bereitstellen.
Bevor ich allerdings loslege würde mich natürlich interessieren, ob das Thema für euch überhaupt von Interesse ist. Am liebsten in Form eines kurzen Kommentars.
Sollte jemand von euch übrigens das Verlangen haben, das Thema jQuery, oder auch generell ASP.NET mit mir persönlich in lockerer Atmosphäre zu diskutieren: Am 28. Mai werde ich einen Einsteigervortrag zu jQuery auf der dotnet Cologne 2010 halten. Über zahlreiche Besucher des Vortrags und natürlich auch spannende Diskussionen danach würde ich mich sehr freuen.
In den Pausen findet man ihr mich übrigens wahrscheinlich im Ausstellerbereich am Stand der Firma Infragistics. Dort wäre ich dann zusätzlich auch für den ein oder anderen Plausch über die Infragistics NetAdvantage Komponenten zu haben.
Es gibt 5 Kommentare