Anzeige
Smartes Cloud Hosting für anspruchsvolle Projekte.
↬ Loslegen und Spaces testen ↬ Jetzt testen!
Dr. Detlef Groth 28. September 2007

Kalenderdrucken mit JavaScript

Kein Beitragsbild

Die Weihnachtszeit rückt heran und ein selbst gestalteter Kalender wird dankend entgegengenommen. Datums- und Kalenderanzeigen basierend auf JavaScript kursieren in großer Zahl im Internet. Aber eine Kalenderanwendung, mit der man Kalender in Listen- oder Tabellenform ausgeben, Monate und eingebundene Bilder mit der Maus frei auf dem Bildschirm verschieben und erstellte Anordnungen speichern oder wiederherstellen kann, ist nicht darunter. Diesem Mangel wollen wir abhelfen.

Anzeige

Kalenderformen
Je nach Einsatzbereich benötigen wir unterschiedliche Kalender: für den Terminplaner oder das Trainingstagebuch benötigt man einen Kalender in Listenform, für den Bilder-Kalender der Oma einen klassischen Kalender in Tabellenform, eventuell aus Effizienzgründen mit 3 Monaten je Kalenderblatt. Vielleicht möchte man auch die Monate frei auf dem Blatt anordnen oder Bilder einbinden? Wir wollen in diesem Beitrag schrittweise individuelle Kalender realisieren.

Struktur der HTML-Datei
Unsere HTML-Datei besteht aus zwei Bereichen: aus einem Formularbereich, welcher die Auswahl der Art, die Anordnung und die Menge der auszudruckenden Kalender erlaubt. Für das Einbinden von Bildern und eigenen Stylesheets kommt später noch ein Textfenster hinzu. Für diesen Formularbereich wird durch die Stylesheet-Angabe

 @media print { form { display: none ;} } 

verhindert, dass der Formularbereich auf dem Drucker ausgegeben wird. Außerdem enthält unsere HTML-Datei ein leeres Div-Element, welches später den Kalender aufnimmt. Hier der relevante Code aus unserer HTML-Datei:

 <form name="datumwahl"> <select onchange="kalender()" name="monat" size="1"> <option value="0">Januar</option> <option value="1">Februar</option> <option value="2">März</option> <option value="3">April</option> <option value="4">Mai</option> <option value="5">Juni</option> <option value="6">Juli</option> <option value="7">August</option> <option value="8">September</option> <option value="9">Oktober</option> <option value="10">November</option> <option value="11">Dezember</option> </select> <select onchange="kalender()" name="jahr" id="jahr" size="1"> <option value="2006">2006</option> <option value="2007" selected="selected">2007</option> <option value="2008">2008</option> <option value="2009">2009</option> <option value="2010">2010</option> </select> </form> <div id="cal">

 </div>

Monatskalender in Listenform
Als erstes wollen wir einen Kalender in Listenform – zum Beispiel für einen Terminplaner – realisieren. Wir benutzen für unseren Kalender eine Tabelle mit zwei Spalten, eine Spalte für das Datum und eine Spalte für die Notizen zu diesem Tag. Durch die an den Wochentag gekoppelte Vergabe der Klassennamen erreichen wir ein farbliches Einfärben jeder Zeile für die Tage des Wochenendes. Wichtig ist außerdem, dass die Tabelle ein Tbody-Element enthält, ansonsten verweigert der Internet Explorer die Anzeige der dynamisch erzeugten Tabelle.

Ein weiteres Problem stellen die Feiertage dar, jedes Bundesland hat ja hier eigene. Durch das Binden des Click-Ereignisses mit der Maus kann der Anwender „seine“ Feiertage entsprechend einfärben. Für die Wiederherstellung der urspünglichen Färbung extrahieren wir im Falle der Kalenderliste die ersten zwei Buchstaben des Datum-Eintrages. Später, im Falle des Kalenders in Tabellenform, benutzen wir den Index der Tabellenzelle, welche das Click-Ereignis empfängt.

Hier der JavaScript-Code zum Erstellen des Kalenders in Listenform. Die Funktionen evtGetTarget, evtAdd und addLoadEvent stammen aus dem jsComponents-Framework, welches im Kopf der Datei eingebunden werden muss.

 var Monat = new Array( "Januar", "Februar", "März",  "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"); var Wochentag = new Array("So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"); function toggleBackground(e) { // Feiertage per click einfaerben var td = evtGetTarget(e); var tr = td.parentNode ; if (tr.className != "So") { tr.className = "So" ; } else { tr.className = tr.firstChild.innerHTML.substr(0,2) ; } } function kalender () { // Hauptfunktion var div = document.getElementById("cal"); // alte Einträge entfernen var child = div.firstChild ; while (child) { div.removeChild(child); child = div.firstChild; } // Formwerte extrahieren var year = document.forms[0].jahr.value ; var month = document.forms[0].monat.value ; div.className = "liste"; // Datum initialisieren var datum = new Date(); datum.setDate(1); datum.setMonth(month); datum.setYear(year); appendCalList(div,datum); } function appendCalList(node,datum) { // Kalender in Listenform erstellen var h2 = document.createElement("h2"); var month = datum.getMonth(); h2.appendChild(document.createTextNode(Monat[month]+ " "+datum.getFullYear())); var table = document.createElement("table"); // Tbody notwendig fuer IE var tbody = document.createElement("tbody"); var lastMonth = month; for (var i = 1 ; i < 32; i++) { datum.setDate(i); if (lastMonth != datum.getMonth()) { break ; } var tr = document.createElement("tr"); var tiw = datum.getDay(); tr.className = Wochentag[tiw]; // Ereignis binden evtAdd aus jsComponents evtAdd(tr,"click",toggleBackground); var td1 = document.createElement("td"); var d = datum.getDate(); if (d < 10) { d = "0"+d; } var monidx = datum.getMonth() var mon = Monat[monidx].substr(0,3); var text = ""+Wochentag[tiw] + " " + d + " " + mon; td1.appendChild(document.createTextNode(text)); var td2 = document.createElement("td"); td2.appendChild(document.createElement("span")); td2.className = "entry" ; tr.appendChild(td1); tr.appendChild(td2); tbody.appendChild(tr); } node.appendChild(h2); table.appendChild(tbody); node.appendChild(table); } // Besseres window.onload aus jsCompontents-Framework addLoadEvent(kalender);

Um eine korrekte Darstellung der leeren Zellen unserer Tabelle zu erzielen, machen wir Gebrauch von der Stylesheet-Eigenschaft .liste table { empty-cells: show ; } für leere Zellen. Außerdem fügen wir eines leeres Span-Element im JavaScript-Code ein. Die Darstellung unserer Tabellenzeilen ist ohne Inhalt. Zum Beispiel: kalender1.html

Monatskalender in Tabellenform
Für den Kalender in Tabellenform benutzen wir natürlich eine Tabelle. Es müssen zuerst einige leere Felder bis zum ersten Tag des Monats erzeugt werden. Danach wird über die Tage des Monats iteriert und nach jedem Sonntag wird eine neue Zeile an die Tabelle angehängt. Die Tatsache, dass im „javascriptischem“ die Woche mit dem Sonntag beginnt, kompliziert den Code ein wenig. Nach dem letzten Tag des Monats erfolgt das abschließende Füllen der letzten Reihe. Auch hier wird das Click-Ereignis genutzt, um Feiertage festzulegen. Mit einem zweiten Klick kann ein irrtümlich angewählter Feiertag wieder abgewählt werden. Hier der entsprechende JavaScript-Code: kalender2.js

Beispielbild für Kalender in Tabellenform

Mehrere Monate auf einer Seite darstellen
Um mehrere Monate auf einer Seite anzuzeigen, erweitern wir das Webformular nun um Auswahlmöglichkeiten für die Anzahl der Spalten und Reihen, die ausgegeben werden sollen. Damit der Nutzer zwischen Tabellen- und Listenform des Kalenders auswählen kann, wird ein neues Auswahlfeld notwendig. Dann erstellen wir für die ausgewählten Reihen und Spalten einen Kalender in Listen- oder Tabellenformat. Zum funktionierenden Beispiel: kalender2.html

Anordnen der Kalender mit der Maus
Der Anwender kann die Kalender hier durch Ziehen am Randbereich auch frei mit der Maus anordnen. Wir fügen zum Anwählen dieser Funktionalität eine neue Auswahlliste mit den Werten für Drag: kein, zusammen und einzeln. Dabei wird bei zusammen der Kalender im ganzen verschiebbar, während bei zusammen jeder Monat separat verschoben werden kann. Für die Bereitstellung der Drag-Funktionalität benutzen wir die bereits erwähnten jsComponents. Unsere Kalender werden nun nicht mehr von den TD-Elementen einer Tabelle aufgenommen, sondern von Div-Tags, welche absolut positioniert werden.

Damit der bestehende Code so wenig wie möglich verändert werden muss, belassen wir die Tabelle, welche bisher die Kalender enthält, als Datenspeicher, setzen aber ihre Style-Eigenschaft display: none;. Die Kalender werden aus dieser Tabelle extrahiert und in frei positionierbare Div-Elemente abgelegt. Um das Maus-Ereignis zum Ziehen des Elementes zu binden, initialisieren wir diese Div-Elemente mit JSDragArea(divNode). Die manuelle Positionierung der Kalender kann über den Texteingabe-Bereich „Kalender“ in einer Textverarbeitung gesichert und später wiederhergestellt werden. Die Einträge für die einzeln positionierten Kalender in der Textbox sind in folgendem Format einzugeben:

 top,left|| top,left|| top,left|| ...

Der Link „Speichern“ sichert dabei die mit der Maus vom Anwender erstellten Positionen in der Textbox, während „Laden“ die Positionen in der Textbox auf die Kalender überträgt.

Bilder einbinden
Was wäre ein Kalender ohne Bilder? Um solche einzubinden, muss der Anwender nach dem Klicken auf den Bilder-Link im Formular-Bereich in der Textbox die Bild-Daten in folgender Form eingeben:

 url1,top,left,width||  url2,top,left,width|| url3,top,left,||

Will man die Originalbreite des Bildes verwenden, lässt man die letzte Spalte, wie bei url3 zu sehen ist, einfach frei. Bei den Bildern können natürlich auch lokale Dateien mittels des file://-Prefixes genutzt werden.

Einige Browser weigern sich allerdings aus Sicherheitsgründen, lokale Dateien von der Festplatte des Anwenders in Webanwendungen einzulesen. So muss zum Anzeigen lokaler Bilder der aktuelle Firefox-Browser erst durch das Bearbeiten der Datei user.js überredet werden. Diese Datei befindet sich im Anwenderprofil des Firefox-Browsers. Wie man dies bewerkstelligt zeigt der Eintrag in der Firefox-Wiki. Die entsprechende Zeile für die Benutzung des Dr.Web-Kalenders in der Datei user.js lautet dann:

 user_pref("capability.policy.localfilelinks.sites","http://www.drweb.de/");

Für ein komfortables Editieren dieser Datei kann man auch die Firefox-Extension ChromEditPlus verwenden. Die Browser Opera und der Internet Explorer kennen Sicherheits-Einschränkungen zum Anzeigen lokaler Dateien derzeit nicht.

Weiterhin ist zu beachten, daß manchem Browser eine URL mit Leerzeichen Probleme bereitet. Der Anwender kann die Bilder nach dem Einfügen mit der Maus verschieben und mittels des Links „Bildkoordinaten speichern“ die veränderten Positionen zurück an die Textbox schicken. Durch das Speichern dieses Textes in einer normalen Textverarbeitung, kann die Arbeit an einem Kalender zu einem späteren Zeitpunkt an gleicher Stelle fortgesetzt werden.

Zusammenfassung
Der Vorteil von Online-JavaScript-Anwendungen, wie der hier vorgestellten JavaScript-Kalender-Druckerei, liegt auf der Hand: Keine megabyte-schweren Installationen von Desktop-Software, sondern einfach die URL ansteuern, Kalender arrangieren, eventuell Bilder einbinden, ausdrucken, fertig.

Code-Beispiele: drweb-kalenderdruck.zip. Kommentare und Vorschläge zum Artikel bitte an den Autor Mail. ™

Erstveröffentlichung 28.09.2007

Dr. Detlef Groth

Dr. Detlef Groth, von Beruf Biochemiker und IT-Konsultant, arbeitet als Bioinformatiker und Autor in Potsdam und Umgebung.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.