programmieren

Terminanzeige in JavaScript

Auf WWW-Seiten kann es des öfteren sehr sinnvoll sein, einen bevorstehenden Termin anzuzeigen. Zu denken wäre hier beispielsweise an Zeitschriften, die über den Erscheinungstermin des nächsten Heftes, bzw. über dessen Redaktionsschluß informieren möchten. Oder an eine WWW-Seite über eine Rockband, auf der immer die Daten des nächsten Konzerts der Band angezeigt werden. Oder das Angebot eines Fußballfans, das den Surfer stets mit dem Spielplan des nächsten Spieltages versorgen soll. So etwas ist natürlich problemlos über eine regelmäßige Pflege der Web-Seiten möglich - indem man die entsprechende Terminangabe immer sofort nach dem gerade verstrichenen Ereignis manuell auf den neuesten Stand bringt. Das Problem dieser Lösung liegt auf der Hand: Man muss die zeitnahe Aktualisierung der Informationen gewährleisten können, was gerade bei schnell wechselnden Terminangaben oftmals nicht möglich ist, da der Durchschnittsbürger ja auch noch andere Dinge zu erledigen hat als die Pflege seiner WWW-Seiten. Ein weiteres Problem liegt darin, dass in der Regel immer eine gewisse Reaktionszeit besteht, d.h. dass zwischen dem Verstreichen des Ereignisses (z.B. dem Ende des Spieltages) und der Aktualisierung des Angebotes eine, wenn auch nur im Stunden- oder gar Minutenbereich liegende, Verzögerung eintritt. Eine alternative Lösung, um diesen Schwierigkeiten aus dem Weg zu gehen, wäre ein gesondertes Programm, dem man von vornherein die Daten einschließlich der jeweiligen Terminangabe vorgibt und das dann, nachdem es die Systemzeit abgefragt hat, aus der jeweils aktuellen Information dynamisch eine entsprechende WWW-Seite generiert. Das erfordert natürlich, dass der verwendete Server solche CGI-Skripten unterstützt, was angesichts der von vielen Systembetreibern gefürchteten Mißbrauchmöglichkeiten von CGI nicht als gemeinhin gegeben vorausgesetzt werden kann. Es bietet sich folglich als goldener Mittelweg der Einsatz einer Programmiersprache auf Client-Seite an - JavaScript. Im folgenden soll anhand eines Primitivbeispiels gezeigt werden, wie man in dieser Sprache einen einfach zu pflegenden Datenbestand zur Terminanzeige realisiert. Dementsprechend ist der Besitz eines JavaScript-fähigen Browsers (wie z.B. "AWeb-II" ab Version 3.2 (bedingt auch 3.1)) Voraussetzung, um die Programmausführung nachvollziehen zu können.

Konzeptionell gestaltet sich die gewünschte Programmfunktion recht simpel. Benötigt wird eine Routine, die im Dokument-Quelltext aufgerufen wird und den aktuellen Termin in den Dokumentinhalt ausgibt. Die Funktion selbst muss den Datensatz in einem Array, Variablen, in denen die Systemzeit gespeichert wird, und eine Schleife, mit der der als nächstes darzustellende Termin festgestellt wird, enhalten. Zu guter letzt muss durch die Funktion natürlich die eigentliche Datenausgabe erfolgen. Im abstrakten Überblick sieht diese Funktion also wie folgt aus:

Definition des Datensatzes
Feststellung der Systemzeit
Bestimmung des aktuellen Datensatzes
Ausgabe des so bestimmten Datensatzes

Um das ganze zu verdeutlichen, soll hier ein (äußerst rudimentärer) Terminplan für Amiga-User erstellt werden. Dabei ist die Fiktivität insbesondere des angegebenen "Gadget"-Redaktionsschlusses und -Erscheinungstermins zu beachten (für die tatsächlichen Werte, die bis dato noch nicht feststehen, sei auf das Editorial dieses "Gadget"s verwiesen). Folgende Termine sollen Bestandteil dieser Datenbank sein:

12.September1998:Computer-Treffen in Barsinghausen
23.September1998:Erscheinungstermin "Amiga Plus" 10/98
03.Oktober1998:Beginn der Infomedia'98 in Antwerpen
13.November1998:Beginn der Computer'98 in Köln
20.November1998:Einsendeschluß "AmigaGadget" #38
23.November1998:Erscheinungstermin "AmigaGadget" #38
24.Dezember1998:Weihnachten

Dabei ist natürlich auf die HTML-Notation der nicht in den ASCII-Zeichensatz fallenden Sonderzeichen zu achten. Zur Speicherung der Datumsinformationen soll im Beispiel jeweils eine eigene Variable verwendet werden, der Text wird in einer gesonderten vierten Variable gespeichert. Natürlich sind die entsprechenden Arrays vor ihrer Initialisierung zunächst mittels "new Array" zu definieren. Der Datensatz, der den (wie erwähnt an dieser Stelle nur spekulativen) Einsendeschluß für das nächste "Gadget" enthält, sähe nach alldem (die zuvor vorgenommene Array-Definition vorausgesetzt) wie folgt aus:

        termine_text[4]="Einsendeschluß "AmigaGadget" #38";
        termine_zeitjahr[4]=1998;
        termine_zeitmonat[4]=11;
        termine_zeittag[4]=20;
  

Da das Beispiel nicht übermäßig komplex werden soll, ist als weitere Voraussetzung zu beachten, dass die Terminangaben bereits bei der Dateneingabe in aufsteigender Reihenfolge (der erste Eintrag ist der zeitlich früheste, der letzte der späteste) abzulegen sind. Für den späteren Gebrauch in der Praxis kann man sich hier natürlich eine der eigentlichen Terminbestimmung vorgelagerte Sortierroutine schreiben, die zwar einerseits die Skriptabarbeitung bremsen würde, andererseits jedoch die Wartung der Daten erheblich vereinfachen kann, da man mit so einer Sortierroutine neue, eventuell kurzfristig hinzugekommene Einträge einfach am Ende des Datensatz hinzufügen kann und sie nicht erst zwischen zwei bestehende einbauen muss (was u.a. eine Erhöhung der Indexzahlen der nachfolgenden Datensätze erforderlich machen würde).

Als nächstes gilt es nun, die Systemzeit entsprechend der oben vorgenommenen Definition der Datensätze in jeweils einer Variable für die Jahreszahl (yy), den Monat (mm) und den gegenwärtigen Tag (dd) zu speichern. Dabei ist zu beachten, dass bei JavaScript-Datumsangaben die Monate die Werte 0 bis 11 haben und die Jahresanzeige 0 dem Jahr 1900 entspricht:

        var date=new Date();
        var dd=date.getDate();
        var mm=date.getMonth() + 1;
        var yy=date.getYear() + 1900;
  

Die eigentliche Funktion, die Feststellung, welcher Termin der nächste ist, läßt sich jetzt dank der schon bei der Dateneingabe vorgenommenen chronologischen Sortierung relativ einfach in Form einer While-Schleife mit verschachtelten If-Abfragen realisieren. Dazu wird ein Zähler eingerichtet, der von 0 aus solange hochgezählt wird, bis die Zahl der Einträge überstiegen wird. Alternativ muss die While-Schleife aber auch dann abgebrochen werden, wenn der gerade untersuchte Termin vom aktuellen Datum aus in der Zukunft liegt. Um das festzustellen, müssen zunächst die Angaben des aktuellen Datums bezüglich der Jahreszahl, dann des Monats und schlußendlich des Tages miteinander verglichen werden. Wenn der gerade überprüfte Termin nämlich schon von der Jahreszahl aus betrachtet für das gegenwärtige Datum in der Zukunft liegt, erübrigt sich die Prüfung, ob er an einem späteren Tag stattfindet. Ja, sie würde sogar unbrauchbare Ergebnisse liefern - man denke nur daran, dass aktuelles Datum etwa der 31.08.1998, der zu überprüfende Termin jedoch der 01.01.1999 wäre: sowohl Tages- als auch Monatszahl des Termines sind kleiner als die des aktuellen Datums, obwohl der Termin unzweifelhaft ein zukünftiger ist. Auf den nachfolgenden Stufen ist der Vergleichstest nur vorzunehmen, wenn auf den vorherigen Stufen derselbe Wert bei aktuellem Datum und zu testendem Termin festgestellt werden konnte. Andererseits liegt der Termin nämlich bereits in der Vergangenheit und kommt nicht als taugliches Ergebnis in Betracht. Die komplette Schleife sind im Ergebnis wie folgt aus:

       ergebnis=-1;
       zaehler=0;
       while ((zaehler<eintraege) && (ergebnis<0)) {
        if (termine_zeitjahr[zaehler]>yy) {
         ergebnis=zaehler;
        } else {
         if (termine_zeitjahr[zaehler]==yy) {
          if (termine_zeitmonat[zaehler]>mm) {
           ergebnis=zaehler;
          } else {
           if (termine_zeitjahr[zaehler]==yy) {
            if (termine_zeitmonat[zaehler]==mm)) {
             if (termine_zeittag[zaehler]>dd) {
              ergebnis=zaehler;
             }
            }
           }
          }
         }
        }
        zaehler++;
       }
  

Nach ihrer Abarbeitung befindet sich in der ergebnis-Variable entweder der Ausgangswert -1 (dann liegen alle gespeicherten Termine in der Vergangenheit) oder der Indexwert des Termines, an dem die Prüfung "stoppte", der also der unmittelbar bevorstehende ist. Dessen Daten müssen nun einfach nur noch mit Hilfe der document.write-Klasse ausgegeben werden. Die komplette Funktion sieht, in eine Beispiels-HTML-Datei eingebunden, mithin so aus:

  <!doctype HTML public "-//W3O//DTD W3 HTML 3.2//EN">
  <html>
   <head>
    <script language="JavaScript">
     <!--
      function getactual() {

       eintraege=7;
       var termine_text=new Array(eintraege);
       var termine_zeitjahr=new Array(eintraege);
       var termine_zeitmonat=new Array(eintraege);
       var termine_zeittag=new Array(eintraege);

       termine_text[0]="Computer-Treffen in Barsinghausen";
       termine_zeitjahr[0]=1998;
       termine_zeitmonat[0]=9;
       termine_zeittag[0]=12;
       termine_text[1]="Erscheinungstermin &quot;Amiga Plus&quot; 10/98";
       termine_zeitjahr[1]=1998;
       termine_zeitmonat[1]=9;
       termine_zeittag[1]=23;
       termine_text[2]="Beginn der Infomedia'98 in Antwerpen";
       termine_zeitjahr[2]=1998;
       termine_zeitmonat[2]10;
       termine_zeittag[2]=3;
       termine_text[3]="Beginn der Computer'98 in K&ouml;ln";
       termine_zeitjahr[3]=1998;
       termine_zeitmonat[3]=11;
       termine_zeittag[3]=13;
       termine_text[4]="Einsendeschlu&szlig; &quot;AmigaGadget&quot; &#35;38";
       termine_zeitjahr[4]=1998;
       termine_zeitmonat[4]=11;
       termine_zeittag[4]=20;
       termine_text[5]="Erscheinungstermin &quot;AmigaGadget&quot; &#35;38";
       termine_zeitjahr[5]=1998;
       termine_zeitmonat[5]=11;
       termine_zeittag[5]=23;
       termine_text[6]="Weihnachten";
       termine_zeitjahr[6]=1998;
       termine_zeitmonat[6]=12;
       termine_zeittag[6]=24;

       var date=new Date();
       var dd=date.getDate();
       var mm=date.getMonth() + 1;
       var yy=date.getYear() + 1900;

       ergebnis=-1;
       zaehler=0;
       while ((zaehler<eintraege) && (ergebnis<0)) {
        if (termine_zeitjahr[zaehler]>yy) {
         ergebnis=zaehler;
        } else {
         if (termine_zeitjahr[zaehler]==yy) {
          if (termine_zeitmonat[zaehler]>mm) {
           ergebnis=zaehler;
          } else {
           if (termine_zeitjahr[zaehler]==yy) {
            if (termine_zeitmonat[zaehler]==mm) {
             if (termine_zeittag[zaehler]>dd) {
              ergebnis=zaehler;
             }
            }
           }
          }
         }
        }
        zaehler++;
       }
       if (ergebnis>=0) {
        document.write ("<strong>N&auml;chster Amiga-Termin:</strong> ");
        document.write (termine_text[ergebnis]+" am ");
        document.write (termine_zeittag[ergebnis]+".");
        document.write (termine_zeitmonat[ergebnis]+".");
        document.write (termine_zeitjahr[ergebnis]);
       } else {
        document.write ("<strong>Keine weiteren Amiga-Termine ");
        document.write ("gespeichert.</strong>");
       }
       document.write ("<br>");
      }
     //-->
    </script>
  

</head> <body> <h2 align=center> Mein privater Terminkalender </h2> <script language="JavaScript"> <!-- getactual(); //--> </script> Ab zum <a href="http://www.amigagadget.de/">AmigaGadget</a>. </body> </html>

Das alles kann natürlich noch erheblich optimiert und erweitert werden. Ein Anwendungsbeispiel dieser Grundfunktion findet sich im übrigen unter der URL http://www.jura.uni-marburg.de/sonstiges/info/klausurenkurs.html. Als Verbesserung wäre u.a. die Speicherung sämtlicher Datumsinformationen in einer einzigen Variable denkbar, als Erweiterung die Berücksichtigung von Stunden-Angaben oder die Ausgabe der bis zum nächsten Termin noch abzuwartenden Zeitspanne. Hier sind der Phantasie, wie so oft beim Programmieren, kaum Grenzen gesetzt.

(c) 1998 by Andreas Neumann

Zurück