Automatisch aktualisierte Tabelle


Zu den eher lästigen Arbeiten in Vereinen u. dergl. gehört die ständige Aktualisierung von Veranstaltungsplänen. Wie das Leben so spielt, vergeht die Zeit. Mühsam gemalte Plakate, ellenlange Listen, Finger für Finger getippt, sind urplötzlich überholt. Daran kann auch JavaScript nichts ändern. Aber es kann schon helfen, zu verhindern, daß seitenweise abgelaufene Termine angekündigt werden.

Wunschzettel:
Eine Tabelle soll Veranstaltungstermine auflisten,
abgelaufene sollen automatisch ausgeblendet werden, ohne Lücken zu hinterlassen,
damit der arme Vereinssekretär nicht allzuviel Arbeit hat, sollte die Eingabe der Termine ungeordnet möglich sein.

Pack mer's.


Tabelle schreiben

Zuerst, wie schreibt man eine Tabelle, die von JavaScript aus verändert werden kann?
Man schreibt sie komplett ins Dokument, zunächst mal nur ganz einfach:


<script language="JavaScript">
   document.write("<center><table border='2' width='50%'>");
   document.write("<tr>");
   document.write("<td>" + "Tabelleninhalt" + "</td>");
   document.write("</tr>");
   document.write("</table></center>");
</script>
 

So sieht das dann aus:

Die Sache ist ausbaufähig.

Anmerkung: Was das Tabellendesign angeht, empfiehlt sich CSS, damit der aus Javascript zu schreibende Code nicht unendlich lang und damit fehleranfällig wird. Hier war die Hintergrundfarbe durch CSS festgelegt.

Wenn es nun einige Zellen mehr werden, dann müssen die Zellinhalte in passender Art und Weise im Speicher abgelegt werden. Wir brauchen wohl ein Variablenarray. Machen wir ein Array, aus dem man dann die Tabelle vollschreiben kann. Da dies Array die Daten vom Vereinssekretär aufnehmen soll, wollen wir ihm die Schreibarbeit so weit wie möglich abnehmen, damit ihm mehr Zeit zum Intrigieren bleibt, deshalb dies:


var tabelle=new Array(
// Beginn des jeweils zu aktualisierenden Eintrags
   "datum1/zeit1/veranstaltung1",
   "datum2/zeit2/veranstaltung2"
// Ende des jeweils zu aktualisierenden Eintrags
);
 

Diese Tabelle dürfte in Breite wie Länge gerne größer sein. Die Anführungsstriche, Slashes und Kommas können wir dem Sekretär leider nicht ersparen. Wenn er clever ist, schreibt er sich im Schreibprogramm ein Makro, das ihm aus einer Tabelle diesen Datenstring erstellt.

Anmerkung 1: Bei dieser Art der Dateneingabe sind Kommas innerhalb eines Eintrages, also etwa innerhalb von veranstaltung2 erlaubt. Deshalb zur Trennung die Slashes.

Anmerkung 2: Wenn im Text selber Anführungsstriche enthalten sind, müssen diese mit vorangestelltem Backslash: "\" entschärft werden.

Anmerkung 3: Sollte in der Tabelle später ein Feld leerbleiben, dann fällt nur der Text raus, die Zahl der Slashes muß pro Zeile natürlich immer gleich bleiben.

So, Problem der Speicherung aller Daten ist gelöst. Es geht aber weiter mit den Datumsdaten (schönes Wort, schöne Arbeit!)


Umgang mit Datumsangaben

JavaScript kann mit Daten hervorragend umgehen. Das Problem, man kann nie sicher sein, wie der gerade benutzte Browser ein Datum ausgibt. Da wir hier die Daten von Veranstaltungsterminen mit dem gerade gültigen Rechnerdatum vergleichen müssen, welches in diesem Browser etwa gerade als: ) vorliegt, die Veranstaltungsdaten aber in etwas gebräuchlicherer Form erscheinen sollen, folgt ein Klimmzug.

Wir gehen so vor, daß wir dem Veranstaltungsplan in einer festgelegten Tabellenspalte ein Datum der Form Tag.Monat.Jahr verordnen, wie es ja in unserem Kulturkreis nicht ungewöhnlich ist. Dieses wird in einer speziellen Funktion, die "datum()" heißen wird, ins interne Datumsformat umgewandelt. Das wird sowohl der Sortierung nach dem Datum dienen, als auch der Entscheidung darüber, ob ein Eintrag abgelaufen ist.

Anmerkung: Hier wird vorgesehen, daß dies verordnete Datum auch das angezeigte ist. Sollten diese Angaben aber freier gestaltbar sein, dann könnte man ein eigenes Datumsfeld in der Liste mitführen, ohne es anzuzeigen. Möchte man so etwas wie etwa "Montag, den 30.12.2017" ausgeben, kann man "Montag, den " in einer eigenen Tabellenzelle mitführen und erst bei der Ausgabe mit dem reinen Datumswert zusammensetzen.

das Zunächst die im head unterzubringende Funktion.


function datum(x)
   {
   var t=new Date();
   var felder=new Array();
   var datteil=new Array(2);
   felder=x.split("/");
   datteil=felder[0].split(".");
   t.setDate(datteil[0]);
   t.setMonth(datteil[1]-1);
   t.setYear(datteil[2]);
   return t;
   }
 

Was genau tut sie?
Die übergebene Variable x enthält eine ganze Tabellenzeile. Wir nehmen hier mal an, daß die Datumsangabe sich in der jeweils ersten Zelle der Tabellenzeile befindet. Diese muß man aber erst aus der Zeile extrahieren, welche ja mehrere durch Slash getrennte Bereiche enthält. Das erledigt die split("/")-Funktion, die die Einzeleinträge, jeweils von Slash bis Slash in das Array felder packt. Dort liegt dann das Datum in felder[0]. (Oder, wenn es etwa stattdessen in der nten Spalte der ursprünglichen Tabelle liegt, in felder[n-1]).
split(".") zerlegt anschließend die dort enthaltene Datumsangabe und speichert die drei Bestandteile im Array datteil. Dann erfolgt der Aufbau einer Datumsvariablen t, die am Ende zurückgemeldet wird.
Tolle Funktion. Sie erlaubt es später, als Kriterium für das Anzeigen einer Zeile eine Abfrage dieser Art zu machen:


var heute=new Date();
if(datum(tabelle[i])>=heute)....
 

Eine weitere wichtige Anwendung betrifft die Sortierung. Die sehr schöne Funktion sort() läßt sich mühelos auf das Tabellenarray anwenden. Wenn man ihr im Argument nichts weiter sagt, sortiert sie nach Ascii-Wert des jeweils ersten Zeichens jeder Zeile. Um nach den altdeutschen Datumsangaben sortieren zu können, muß im Argument eine Funktion aufgerufen werden, die jeweils zwei der zu sortierenden Datumseinträge miteinander vergleicht. Das geht aber natürlich nur mit "offiziellen" Datumsvariablen. Nach dieser lichtvollen Erklärung ist der folgende Code ja wohl klar:


function zeitlich(x,y)
   {
   return datum(x)-datum(y);
   }
...
tabelle.sort(zeitlich);
 

Oder etwa nicht? Frage bitte niemand, warum etwa die schöne Funktion "zeitlich" hier ohne Argument aufgerufen wird. Ich weiß es nicht. Aber, es klappt.


Es wird ernst

Nix ist klar, das Schreiben der Tabelleninhalte setzt voraus, daß die Zeilen zuvor zerlegt werden. Das geht aber, wie oben bei der datum()-Funktion mit split("/"). Geschrieben wird bedingt, also nur, was an Terminen noch aktuell ist.
Es folgt sogleich der ultimative Test, dem die weiteren Einzelheiten zu entnehmen sind. Ich gebe hier 11 Termine vor. Zunächst folgt der Code im Head-Bereich. Zu diesem gehören die schon gezeigten Funktionen. Aber auch das Tabellenarray, das vom Sekretär alle paar Monate die neuen, demnächst wieder erledigt sein werdenden Termine erhalten muß.


var heute=new Date();
var tabelle=new Array(
"12.03.2001/Werkessen/Küche/16.30 Uhr",
"5.03.2001/Kinogang/Bergweg 5/22 Uhr",
...
"2.12.2001/Konzert/Haupthalle/17 Uhr");
tabelle.sort(zeitlich);
 

Am Ort der gewünschten Tabelle folgt der Code etwa wie hier:


<script>
var tab=new Array();
document.write("<table cellspacing='2' cellpadding='5' border='2' width='100%'>");
for(i=0;i<tabelle.length;i++)
   {
   if(datum(tabelle[i])>=heute)
      {
      tab=tabelle[i].split("/");
      document.write("<tr>");
      document.write("<td>" + tab[0] + "</td>");
      document.write("<td>" + tab[1] + "</td>");
      document.write("<td>" + tab[2] + "</td>");
      document.write("<td>" + tab[3] + "</td>");
      document.write("</tr>");
      }
   }
document.write("</table>");
</script>
 

Da ist sie nun:

Diese schöne (?) Tabelle zeigt keine überholten Termine an und alle schön sortiert. Schön, nicht?

Anmerkung: Da hier sowieso nach dem Datum des Eintrags gefragt wird, bietet es sich an, etwa für den gerade HEUTIGEN Termin eine spezielle Hervorhebung vorzusehen, die auch an anderem Ort, etwa am Seitenbeginn stehen könnte.