Javascript

Mit jQuery schneller zum Ziel

Ein Beispiel wie die freie Javascript-Bibliothek das Codieren vereinfacht

Im alten zerbit.de-Web hatte ich den Zugriff auf ältere Beiträge über die Archiv-Seite zusammengefasst und vereinfacht. Als die Filter- und Sortierungsfunktionen fertig waren, kam ich auf die Idee per Javascript eine Vorschau zu implementieren, die es ermöglicht einen Blick auf den Beitrag zu werfen, ohne die Seite neu laden zu müssen.

Um nun nicht alle Beiträge von vorneherein in unsichtbaren DIV's vorhalten zu müssen, was die Ladezeit der Seite extrem in den Keller gezogen hätte, habe ich die zeitgemäße AJAX-Technik angewandt, soll heißen: der Text eines Beitrags wird auf Anfrage, also auf den Klick eines Benutzers hin, vom Server geladen und angezeigt.

Der dafür notwendige Javascript-Code war nach Fertigstellung fast 90 Zeilen lang! Ein ziemlicher Brocken, nur um den Inhalt einer XML-Datei in ein scrollbares DIV zu laden.

Nun habe ich mich vor Kurzem, im Zuge eines Beitrags über das Anzeigemodul Thickbox, etwas mit der Javascript-Bibliothek jQuery beschäftigt und die Frage war, in wieviel Zeilen man das Problem wohl damit abhandeln kann. Das Ergebnis: 30 Zeilen, inkl. Kommentare und Leerzeilen zwecks Übersichtlichkeit des Codes!

Diese doch erstaunliche Zahl, hat mich dazu bewogen, das Problem und die beiden Lösungsansätze in diesem Artikel einmal näher darzustellen, um einen kleinen Einblick in diese wirklich coole Bibliothek zu vermitteln.

Der HTML-Code

Ausgangspunkt war folgendes, für dieses Beispiel etwas vereinfachtes, HTML-Konstrukt:

<ul>
  <li>

    <div class="item">
      <div id="iteminfo" class="iteminfo">
        <div class="mini">Beitragsdatum</div>
        <div class="title"><a href="#">Beitragstitel</a></div>
        <div class="mini">Schlagworte: ...</div>
      </div>

      <div id="selector" class="selector_plus">
        <a href="javascript: showPreviewSelector();">
          <img id="selimg" src="selector_plus.gif" height="50" width="20">
        </a>
      </div>
    </div>
 
   <div id="preview" class="preview">
      <div id="previewbox">
        <div id="previewtext" class="previewtext">&nbsp;</div>
      </div>
    </div>
 
 </li>
</ul>

Der Aufbau ist recht simpel: innerhalb einer Liste (UL / LI) sind zwei übereinander liegende DIV's definiert (item und preview), wobei das erste durch zwei weitere DIV's unterteilt sind (itemfo und selector). In iteminfo sind die Informationen zum Beitrag untergebracht und in selector ist eine Link-Grafik definiert.

Das DIV preview ist nach dem Laden der Seite durch die CSS-Anweisung display:none zunächst unsichtbar, da die Vorschau ja erst nach Aufforderung, d.h. Klick auf die Link-Grafik geladen werden soll. (Die komplette Beispiel-HTML-Datei inkl. CSS-Anweisungen und Scripte können weiter unten heruntergeladen werden.)

Das Ganze sieht im Browser dann so aus:

Die Daten

Da der Beitragstext nicht in der Seite enthalten ist, muss er irgendwo her kommen. Weil nun das X in AJAX für XML steht, habe ich hierfür auch dieses Format verwendet. Die Struktur der XML-Datei ist denkbar einfach:

<?xml version="1.0" encoding="iso-8859-1"?>
<data>
   <![CDATA[
      ... Beitragstext
   ]]>
</data>

Um das Ganze flexibel zu halten, hatte ich für das Archiv auf zerbit.de natürlich keine starre XML-Datei im Einsatz, sondern etwas ASP-Code, um das XML-Konstrukt dynamisch zu erzeugen. In diesem Beispiel verwende ich jedoch die Datei daten.xml.

Lösung 1 - reines Javascript

Nun zum dynamischen Teil der Seite. Aufgabe ist es, die im HTML-Code bereits definierte Javascript-Funktion showPreviewSelector() mit Leben zu füllen. In Abhängigkeit des aktuellen Status, soll folgendes passieren:

Vorschau wird nicht angezeigt (aufklappen)

  1. Laden des Beitragstextes aus der XML-Datei in das DIV previewtext
  2. Anzeigen des übergeordneten DIV's preview
  3. Ändern der Link-Grafik und des Hintergrundes des DIV's selektor

Vorschau wird angezeigt (zuklappen)

  1. Verbergen des DIV's preview
  2. Ändern der Link-Grafik und des Hintergrundes des DIV's selektor in den Originalzustand

Zum Laden von Daten von einem Web-Server per Javascript, wird das XMLHTTP-Objekt verwendet. Um dieses, Browser-unabhängig, korrekt zu initialisieren, verwende ich eine eigenständige Funktion, die das Objekt in einer globalen Variable vorhält:

//globales XMLHTTP-Objekt
var xmlHttp = false;

// --------------------------------------------------------------
function getXMLRequester() {

 var xmlHttp = false;
 
 try {
  // Mozilla und Co.
  if (window.XMLHttpRequest) {
  xmlHttp = new XMLHttpRequest();
  }
  // IE
  else if (window.ActiveXObject) {
   xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
  }
  else {
   // Falls nicht unterstützt
   xmlHttp = false;
  }
 }
 catch( excNotLoadable )
 {      
  xmlHttp = false;
 }
 return xmlHttp;
}

Dieser Requester wird dann in der eigentlichen Funktion showPreviewSelector einmal aufgerufen und man kann über das globale Objekt mit einem Web-Server kommunizieren.

Eine Eigenart des asynchronen Laden von Server-Daten ist, dass man innerhalb des Codes die Rückmeldungen des Servers abwarten muss, bevor man fortfahren kann. Aus diesem Grunde scheint der nachfolgende Code der Funktion etwas zerklüftet:

function showPreviewSelector() {

 //Zugriffsvariablen für die benötigten Seiten-Elemente
 var eSel = document.getElementById("sel");
 var eSelImg = document.getElementById("selimg");
 var ePrv = document.getElementById("prv");
 var ePrvTxt = document.getElementById("prvtxt");
 
 //in Abhängigkeit des aktuellen Status...
 if (eSel.className == 'selector_minus') {
 
  //Vorschau-DIV verbergen und Selektor formatieren
  ePrv.style.display = 'none';
  eSel.className = 'selector_plus';
  eSelImg.src="selector_plus.gif";
  
 } else {

  //event. bereits laufenden XMLHTTP-Request abbrechen
  if( xmlHttp && xmlHttp.readyState ) {
   xmlHttp.abort( );
   xmlHttp = false;
  }
   
  //neue Instanz; Abbruch wenn fehlschlägt
  if( !xmlHttp ) {
   xmlHttp = getXMLRequester( );
   if( !xmlHttp )
    return;
  }

  //Daten-URL festlegen
  var sURL = 'http://localhost/test/art61/data.xml';

  //Daten abholen und verarbeiten...
  xmlHttp.open("GET", sURL, true);
  
  //Verarbeitung, wenn Status OK
  xmlHttp.onreadystatechange = function() {    
   if (xmlHttp.readyState == 4) {
    if (xmlHttp.status == 200) {  
     
     //Text aus XML extrahieren
     var xmlDok = xmlHttp.responseXML;
     var sText = xmlDok.getElementsByTagName("data")[0].firstChild.nodeValue;
     
     //Text in Vorschau-DIV einfügen
     ePrvTxt.innerHTML = sText;
     
     //Vorschau-DIV anzeigen und Selektor formatieren
     ePrv.style.display = 'block';
     eSel.className = 'selector_minus'
     eSelImg.src="selector_minus.gif";
      }
     }
  }
  xmlHttp.send(null); 
 }
}

Die Entscheidung welcher Status gerade anliegt, wird an der anliegenden CSS-Klasse des DIV's selector festgemacht. Es gibt hier nur die beiden "Zustände" selector_plus (Vorsschau ist zu) und selector_minus (Vorschau ist offen).

Wie man sieht, ist der reine Javascript-Code recht umfangreich, was vor allem daran liegt, dass es keine eingebaute Möglichkeit gibt einfacher Daten von einem Web-Server zu laden.

Lösung 2 - jQuery

Sooo... und nun das Ganze noch einmal. Nun aber unter Zuhilfenahme der Javascript-Bibliothek jQuery von John Resig. Sinn dieser Bibliothek ist es, den Web-Entwickler etwas von der Javascript-Komplexität zu entlasten und schneller zu Ergebnissen kommen zu lassen. Um sie zu verwenden, muss man zunächst im HEAD der Seite einen ensprechenden Verweis aufnehmen:

<script type="text/javascript" src="jquery.js"></script>

Einer der herausragenden Unterschiede zum puren Javascript ist der fortan wesentlich schnellere Zugriff auf Objekte des HTML-DOM, also der Seitenelemente, wobei man wissen muss, dass man auf alle jQuery-Objekte über die $-Methode zugreift, die die jQuery-Bibliothek repräsentiert. So verkürzt sich z.B. die Javascript-Anweisung

document.getElementById("selector").className == 'selector_minus'

auf

$("#selector").attr("class") == 'selector_minus'

Und dies ist noch eines der längeren und simpleren Beispiele. Wer sich einen Überblick über die jQuery-API und die Syntax verschaffen möchte, dem sei u.a. Visual jQuery empfohlen.

Aber konzentrieren wir uns auf unsere Aufgabe...

Das absolute Killer-Argument für jQuery ist seine AJAX-Funktionalität, d.h. das sog. jQuery AJAX-Plugin, das in der aktuellen Version bereits in der Bibliothek enthalten ist. Mit dieser Schnittstelle kann man kompletten "Overhead" des XMLHTTP-Request getrost zu vergessen. Eine Seite von einem Web-Server zu laden geschieht im einfachsten Fall mit einer Zeile:

$("#test").load("http://localhost/test/test.html");

Mit der Methode $.get und der Angabe einer Callback-Funktion als Parameter, ist es möglich eine XML-Datei zunächst zu laden und dann über eine XPath-Anweisung den Inhalt eines bestimmten XML-Asts auszulesen. Dieses Feature ist prädestiniert für unsere Lösung:

function showPreviewSelectorJ() {

  //abzurufende URL festlegen
  var sURL = 'http://localhost/test/art61/data.xml';

  if ($("#selector").attr("class") == 'selector_minus') {

    //Vorschau-DIV verbergen und Selektor formatieren
    $("#preview").slideUp("normal");
    $("#selector").removeClass().addClass("selector_plus");
    $("#selimg").src("selector_plus.gif");

  } else {

    //Selektor formatieren
    $("#selector").removeClass().addClass("selector_minus");
    $("#selimg").src("selector_minus.gif");

    //über AJAX-Methode Daten holen
    $.get(sURL, function(xml){
        var text = $("data",xml).text();

        //Text in Vorschau-DIV einfügen
        $("#previewtext").html(text);

        //Vorschau-DIV anzeigen
        $("#preview").slideDown("normal");
    });
  }
}

Wie man sieht ist der jQuery-getriebene Javascript-Code wesentlich kürzer und, wie ich finde, auch einfacher zu verstehen, auch wenn man sagen muss, dass die jQuery-Bibliothek bei jedem Aufruf der Seite zusätzlich geladen werden muss. Bei den heutigen Bandbreiten sollte dies aber kein Hinderungsgrund sein.

Im Beispiel verstekt ist noch ein Goodie, dass mit der reinen Javascript-Lösung so nicht realisiert wurde: das DIV preview wird nicht nur einfach angezeigt, sondern es enfaltet sich effektvoll. Zuständig hierfür ist die Zeile $("#preview").slideDown("normal");. Dies ist allerdings nur ein Effekt der Bibliothek. Es gibt zig-verschiedene Arten, um HTML-Elemente "erscheinen" zu lassen.


Das Ergebnis

Der Vollständigkeit halber noch ein Screenshot der ausgeklappten Vorschau...

Downloads

Beispieldateien zu diesem Artikel

Weiterführende Informationen

kick it on dotnet-kicks.de AddThis 0 wikio-Stimme(n) Trackback-Url...

Schlagworte

1 Kommentar bislang...

  • jQuery: für einfacheres JavaScript

    Auch wenn JavaScript mittlerweile für fast jede Webseite eingesetzt wird - nicht zuletzt um dem Web2.0-Hype zu folgen - ist es nicht unbedingt einfach ohne entsprechende Bibliotheken damit zu arbeiten. Dies beginnt schon beim Ansprechen bestimmter Objekt

    http://blog.bauer-online.org/archives/246-jQuery-fuer-einfacheres-JavaScript.html

    1
    TRACKBACK : .: blogging augusto :. : Donnerstag, 16. November 2006 11:19

Dein Kommentar hierzu...


Kommentar-Feed für diesen Beitrag
Gravatare werden unterstützt .:. eMail-Adressen werden nicht veröffentlicht
 

RSS-Feed

Die URL des Standard-Newsfeed von zerbit.de lautet:

http://www.zerbit.de/rssfeed.aspx

Login


 

 

Statistik



kürzlich kommentiert

Artikel 61

  • Datum: 08.10.2006
    Kategorie: Javascript
    Zugriffe: 5.582
    Kommentare: 1
    Trackbacks: 2

Letzte Beiträge

Kategorien

Buttons & More

Blog-Roll

Banner Piraten-Partei