Spaces. Smartes Cloud Hosting für anspruchsvolle Webprojekte. Loslegen und Spaces testen. Von Mittwald.
Dr. Detlef Groth 28. September 2007

Kalenderdrucken mit JavaScript

Kein Beitragsbild

Die Weihnachtszeit rückt her­an und ein selbst gestal­te­ter Kalender wird dan­kend ent­ge­gen­ge­nom­men. Datums- und Kalenderanzeigen basie­rend auf JavaScript kur­sie­ren in gro­ßer Zahl im Internet. Aber eine Kalenderanwendung, mit der man Kalender in Listen- oder Tabellenform aus­ge­ben, Monate und ein­ge­bun­de­ne Bilder mit der Maus frei auf dem Bildschirm ver­schie­ben und erstell­te Anordnungen spei­chern oder wie­der­her­stel­len kann, ist nicht dar­un­ter. Diesem Mangel wol­len wir abhel­fen.

Kalenderformen
Je nach Einsatzbereich benö­ti­gen wir unter­schied­li­che Kalender: für den Terminplaner oder das Trainingstagebuch benö­tigt man einen Kalender in Listenform, für den Bilder-Kalender der Oma einen klas­si­schen Kalender in Tabellenform, even­tu­ell aus Effizienzgründen mit 3 Monaten je Kalenderblatt. Vielleicht möch­te man auch die Monate frei auf dem Blatt anord­nen oder Bilder ein­bin­den? Wir wol­len in die­sem Beitrag schritt­wei­se indi­vi­du­el­le Kalender rea­li­sie­ren.

Struktur der HTML-Datei
Unsere HTML-Datei besteht aus zwei Bereichen: aus einem Formularbereich, wel­cher die Auswahl der Art, die Anordnung und die Menge der aus­zu­dru­cken­den Kalender erlaubt. Für das Einbinden von Bildern und eige­nen Stylesheets kommt spä­ter noch ein Textfenster hin­zu. Für die­sen Formularbereich wird durch die Stylesheet-Angabe

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

ver­hin­dert, dass der Formularbereich auf dem Drucker aus­ge­ge­ben wird. Außerdem ent­hält unse­re HTML-Datei ein lee­res Div-Element, wel­ches spä­ter den Kalender auf­nimmt. Hier der rele­van­te Code aus unse­rer 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 ers­tes wol­len wir einen Kalender in Listenform – zum Beispiel für einen Terminplaner – rea­li­sie­ren. Wir benut­zen für unse­ren Kalender eine Tabelle mit zwei Spalten, eine Spalte für das Datum und eine Spalte für die Notizen zu die­sem Tag. Durch die an den Wochentag gekop­pel­te Vergabe der Klassennamen errei­chen wir ein farb­li­ches Einfärben jeder Zeile für die Tage des Wochenendes. Wichtig ist außer­dem, dass die Tabelle ein Tbody-Element ent­hält, ansons­ten ver­wei­gert der Internet Explorer die Anzeige der dyna­misch erzeug­ten Tabelle.

Ein wei­te­res Problem stel­len die Feiertage dar, jedes Bundesland hat ja hier eige­ne. Durch das Binden des Click-Ereignisses mit der Maus kann der Anwender “sei­ne” Feiertage ent­spre­chend ein­fär­ben. Für die Wiederherstellung der urspüng­li­chen Färbung extra­hie­ren wir im Falle der Kalenderliste die ers­ten zwei Buchstaben des Datum-Eintrages. Später, im Falle des Kalenders in Tabellenform, benut­zen wir den Index der Tabellenzelle, wel­che das Click-Ereignis emp­fängt.

Hier der JavaScript-Code zum Erstellen des Kalenders in Listenform. Die Funktionen evtGetTarget, evtAdd und addLoadEvent stam­men aus dem jsComponents-Framework, wel­ches im Kopf der Datei ein­ge­bun­den wer­den 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 kor­rek­te Darstellung der lee­ren Zellen unse­rer Tabelle zu erzie­len, machen wir Gebrauch von der Stylesheet-Eigenschaft .lis­te table { empty-cells: show ; } für lee­re Zellen. Außerdem fügen wir eines lee­res Span-Element im JavaScript-Code ein. Die Darstellung unse­rer Tabellenzeilen ist ohne Inhalt. Zum Beispiel: kalender1.html

Monatskalender in Tabellenform
Für den Kalender in Tabellenform benut­zen wir natür­lich eine Tabelle. Es müs­sen zuerst eini­ge lee­re Felder bis zum ers­ten Tag des Monats erzeugt wer­den. Danach wird über die Tage des Monats ite­riert und nach jedem Sonntag wird eine neue Zeile an die Tabelle ange­hängt. Die Tatsache, dass im “java­scrip­ti­schem” die Woche mit dem Sonntag beginnt, kom­pli­ziert den Code ein wenig. Nach dem letz­ten Tag des Monats erfolgt das abschlie­ßen­de Füllen der letz­ten Reihe. Auch hier wird das Click-Ereignis genutzt, um Feiertage fest­zu­le­gen. Mit einem zwei­ten Klick kann ein irr­tüm­lich ange­wähl­ter Feiertag wie­der abge­wählt wer­den. Hier der ent­spre­chen­de JavaScript-Code: kalender2.js

Beispielbild für Kalender in Tabellenform

Mehrere Monate auf einer Seite dar­stel­len
Um meh­re­re Monate auf einer Seite anzu­zei­gen, erwei­tern wir das Webformular nun um Auswahlmöglichkeiten für die Anzahl der Spalten und Reihen, die aus­ge­ge­ben wer­den sol­len. Damit der Nutzer zwi­schen Tabellen- und Listenform des Kalenders aus­wäh­len kann, wird ein neu­es Auswahlfeld not­wen­dig. Dann erstel­len wir für die aus­ge­wähl­ten Reihen und Spalten einen Kalender in Listen- oder Tabellenformat. Zum funk­tio­nie­ren­den Beispiel: kalender2.html

Anordnen der Kalender mit der Maus
Der Anwender kann die Kalender hier durch Ziehen am Randbereich auch frei mit der Maus anord­nen. Wir fügen zum Anwählen die­ser Funktionalität eine neue Auswahlliste mit den Werten für Drag: kein, zusam­men und ein­zeln. Dabei wird bei zusam­men der Kalender im gan­zen ver­schieb­bar, wäh­rend bei zusam­men jeder Monat sepa­rat ver­scho­ben wer­den kann. Für die Bereitstellung der Drag-Funktionalität benut­zen wir die bereits erwähn­ten jsComponents. Unsere Kalender wer­den nun nicht mehr von den TD-Elementen einer Tabelle auf­ge­nom­men, son­dern von Div-Tags, wel­che abso­lut posi­tio­niert wer­den.

Damit der bestehen­de Code so wenig wie mög­lich ver­än­dert wer­den muss, belas­sen wir die Tabelle, wel­che bis­her die Kalender ent­hält, als Datenspeicher, set­zen aber ihre Style-Eigenschaft dis­play: none;. Die Kalender wer­den aus die­ser Tabelle extra­hiert und in frei posi­tio­nier­ba­re Div-Elemente abge­legt. Um das Maus-Ereignis zum Ziehen des Elementes zu bin­den, initia­li­sie­ren wir die­se Div-Elemente mit JSDragArea(divNode). Die manu­el­le Positionierung der Kalender kann über den Texteingabe-Bereich “Kalender” in einer Textverarbeitung gesi­chert und spä­ter wie­der­her­ge­stellt wer­den. Die Einträge für die ein­zeln posi­tio­nier­ten Kalender in der Textbox sind in fol­gen­dem Format ein­zu­ge­ben:

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

Der Link “Speichern” sichert dabei die mit der Maus vom Anwender erstell­ten Positionen in der Textbox, wäh­rend “Laden” die Positionen in der Textbox auf die Kalender über­trägt.

Bilder ein­bin­den
Was wäre ein Kalender ohne Bilder? Um sol­che ein­zu­bin­den, muss der Anwender nach dem Klicken auf den Bilder-Link im Formular-Bereich in der Textbox die Bild-Daten in fol­gen­der Form ein­ge­ben:

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

Will man die Originalbreite des Bildes ver­wen­den, lässt man die letz­te Spalte, wie bei url3 zu sehen ist, ein­fach frei. Bei den Bildern kön­nen natür­lich auch loka­le Dateien mit­tels des file://-Prefixes genutzt wer­den.

Einige Browser wei­gern sich aller­dings aus Sicherheitsgründen, loka­le Dateien von der Festplatte des Anwenders in Webanwendungen ein­zu­le­sen. So muss zum Anzeigen loka­ler Bilder der aktu­el­le Firefox-Browser erst durch das Bearbeiten der Datei user.js über­re­det wer­den. Diese Datei befin­det sich im Anwenderprofil des Firefox-Browsers. Wie man dies bewerk­stel­ligt zeigt der Eintrag in der Firefox-Wiki. Die ent­spre­chen­de Zeile für die Benutzung des Dr.Web-Kalenders in der Datei user.js lau­tet dann:

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

Für ein kom­for­ta­bles Editieren die­ser Datei kann man auch die Firefox-Extension ChromEditPlus ver­wen­den. Die Browser Opera und der Internet Explorer ken­nen Sicherheits-Einschränkungen zum Anzeigen loka­ler Dateien der­zeit nicht.

Weiterhin ist zu beach­ten, daß man­chem Browser eine URL mit Leerzeichen Probleme berei­tet. Der Anwender kann die Bilder nach dem Einfügen mit der Maus ver­schie­ben und mit­tels des Links “Bildkoordinaten spei­chern” die ver­än­der­ten Positionen zurück an die Textbox schi­cken. Durch das Speichern die­ses Textes in einer nor­ma­len Textverarbeitung, kann die Arbeit an einem Kalender zu einem spä­te­ren Zeitpunkt an glei­cher Stelle fort­ge­setzt wer­den.

Zusammenfassung
Der Vorteil von Online-JavaScript-Anwendungen, wie der hier vor­ge­stell­ten JavaScript-Kalender-Druckerei, liegt auf der Hand: Keine mega­byte-schwe­ren Installationen von Desktop-Software, son­dern ein­fach die URL ansteu­ern, Kalender arran­gie­ren, even­tu­ell Bilder ein­bin­den, aus­dru­cken, fer­tig.

Code-Beispiele: drweb-kalenderdruck.zip. Kommentare und Vorschläge zum Artikel bit­te an den Autor Mail. (tm)

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.