/* MonatsboxFabrik - a date component for the browser Copyright (c) 2012, 2021 Ulrich Hilger This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ /** * Die MonatsboxFabrik liefert mit der Funktion * monatsboxErzeugen eine Monatsbox */ function MonatsboxFabrik() { var self = this; this.gewaehlteZelle = null; this.j = -1; this.m = -1; this.r = -1; // Ruhetag this.stilName = 'monatsboxRumpf'; this.alterStilName = 'monatsboxRumpf'; this.kwt = new Array(3, 4, 5, 6, 0, 1, 2); /** * Eine Monatsbox zusammensetzen * * @param {int} jahr ein beliebiges Jahr * @param {int} monat 0=Januar .. 11=Dezember * @param {int} starttag der Wochentag, mit dem eine Woche startet, * 0=Sonntag .. 6=Samstag * @param {int} ruhetag der Wochentag, der als Ruhetag markiert werden soll, * 0=Sonntag .. 6=Montag * @param {type} ereignisse eine Map, die fuer jeden Tag mit Ereignissen einen * Klassennamen zurueckgibt * @param {type} lauscher die Funktion, die gerufen wird, wenn ein Tag * geklickt wird * @returns {Element} die Monatsbox */ this.monatsboxErzeugen = function(jahr, monat, starttag, ruhetag, ereignisse, lauscher) { // Jahr und Monat merken this.j = jahr; this.m = monat; // eine Tabelle nimmt die Monatsbox auf var tabelle = document.createElement("table"); tabelle.className = "monatsbox"; tabelle.setAttribute('jahr', jahr); tabelle.setAttribute('monat', monat); // Ruhetagspalte abhaengig vom ersten Tag der Woche bestimmen var ruhetagspalte = self.spalteBestimmen(ruhetag, starttag) + 1; this.r = ruhetagspalte; // Ueberschrift bilden tabelle.appendChild(self.monatsboxKopf(starttag, ruhetagspalte)); // Startdatum setzen var tagesDatum = 1; var datum = new Date(); datum.setFullYear(jahr); datum.setDate(tagesDatum); datum.setMonth(this.m); // Startspalte abhaengig vom ersten Tag der Woche bestimmen var startspalte = self.spalteBestimmen(datum.getDay(), starttag) + 1; // den Rumpf der Monatsbox erzeugen var zeile = 0; var spalte = 0; var w = 0; var tr = document.createElement("tr"); var td; var stilName; var letzterTag = self.letzterTagImMonat(jahr, monat); while(tagesDatum <= letzterTag) { stilName = null; td = document.createElement("td"); td.onclick = lauscher; if(spalte == ruhetagspalte) { stilName = ereignisse.get(tagesDatum); td.className = "monatsboxRumpfRuhetag"; } else if(spalte == 0) { td.className = "monatsboxWoche"; } else { stilName = ereignisse.get(tagesDatum); td.className = "monatsboxRumpf"; } if(zeile == 0 && spalte < startspalte) { if(spalte == 0) { w = self.kalenderwoche(jahr, monat, tagesDatum, starttag); td.innerHTML = w; } } else if(spalte == 0) { // woche schreiben if(w > 51) { //w = kalenderwoche(jahr, monat, tagesDatum + 1, starttag); w = self.kalenderwoche(jahr, monat, tagesDatum, starttag); td.innerHTML = w; } else { td.innerHTML = ++w; } } else { if(stilName !== null && stilName !== undefined && stilName.length > 0) { td.className = stilName; } td.innerHTML = String(tagesDatum); datum.setDate(++tagesDatum); } tr.appendChild(td); if(++spalte > 7) { spalte = 0; ++zeile; tabelle.appendChild(tr); tr = document.createElement("tr"); } } if(spalte > 0) { tabelle.appendChild(tr); ++zeile; } if(spalte == 0 && zeile == 5) { self.zeileAnfuegen(tabelle); ++zeile; } while(zeile < 6) { self.zeileAnfuegen(tabelle); zeile++; } return tabelle; }; this.zeileAnfuegen = function(tabelle) { var tr = document.createElement("tr"); var td = document.createElement("td"); td.innerHTML = ' '; tr.appendChild(td); tabelle.appendChild(tr); }; /** * Anhand eines Klick-Ereignisses in die Monatsbox bestimmen, ob ein Tag * angeklickt wurde. Wenn ein Tag angeklickt wurde, diesen farblich * hervorheben und das Datum des geklickten Tages zurueckgeben. * Wenn kein Tag angeklickt wurde, null zurueckgeben. */ this.datum = function(Ereignis) { var ermitteltesDatum = null; const td = Ereignis.target; const boxTab = td.parentNode.parentNode; const meinMonat = Number(boxTab.getAttribute('monat')); const spalte = td.cellIndex; const tagesDatum = Number(td.innerHTML); if(spalte > 0 && tagesDatum !== Number.NaN && tagesDatum > 0) { if(this.gewaehlteZelle !== null) { this.gewaehlteZelle.className = this.alterStilName; } this.gewaehlteZelle = td; ermitteltesDatum = new Date(this.j, meinMonat, tagesDatum); this.alterStilName = td.className; td.className = 'monatsboxGewaehlt'; //ermitteltesDatum.setFullYear(this.j); //ermitteltesDatum.setDate(tagesDatum); //ermitteltesDatum.setMonth(meinMonat); //ermitteltesDatum.setDate(tagesDatum); //ermitteltesDatum.setMonth(meinMonat); } return ermitteltesDatum; }; /** * Die Spalte eines Wochentags abhaengig vom Tag bestimmen, * mit dem eine Woche startet * * wochentag: Wochentag, dessenSpalte bestimmt werden soll * starttag: Wochentag, mit dem eine Woche beginnt * * Jeweils 0=Sonntag .. 6=Samstag */ this.spalteBestimmen = function(wochentag, starttag) { var spalte = wochentag - starttag; if(spalte < 0) { spalte = 7 + spalte; } return spalte; }; /** * Die Ueberschrift einer Monatsbox bestehend aus * Wochentagsnamen bilden * * starttag: Wochentag, mit dem eine Woche beginnt * ruhetagspalte: Spalte des Wochentages, der als Ruhetag markiert werden soll * * Jeweils 0=Sonntag .. 6=Samstag */ this.monatsboxKopf = function(starttag, ruhetagspalte) { var tagesnamen = new Array("Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"); var tr = document.createElement("tr"); var td; td = document.createElement("td"); td.className = "monatsboxKopfWoche"; td.innerHTML = "Kw"; tr.appendChild(td); for(var index = 1; index < 8; index++) { td = document.createElement("td"); if(index == ruhetagspalte) { td.className = "monatsboxKopfRuhetag"; } else { td.className = "monatsboxKopf"; } //console.log(starttag + ' ' + index); if(Number(starttag) + Number(index) > 7) { td.innerHTML = tagesnamen[Number(starttag) + Number(index) - 8].substring(0, 2); } else { td.innerHTML = tagesnamen[Number(starttag) + Number(index) - 1].substring(0, 2); } tr.appendChild(td); } return tr; }; /* ----------------- Datumsberechnungen ---------------------- */ /** * Bestimmen, ob ein Jahr ein Schaltjahr ist * j: Das Jahr, fuer das bestimmt werden soll,ob es ein Schaltjahr ist * Rueckgabe: true, wenn das Jahr ein Schaltjahr ist, false wenn nicht */ this.schaltjahr = function(j) { var istSchalt = false; if(((j % 4 == 0) && (j % 100 != 0)) || (j % 400 == 0)) { istSchalt = true; } return istSchalt; }; /** * Den letzten Tag eines Monats im Gregorianischen Kalender bestimmen * * @param gJahr das Jahr des Monats im Gregorianischen Kalender * @param month der Monat im Gregorianischen Kalender * @return Nummer des letzten Tages im betreffenden Monat (28, 29, 30 oder 31) */ this.letzterTagImMonat = function(gJahr, month) { var letzter = -1; switch (month) { case 3: case 5: case 8: case 10: letzter = 30; break; case 1: if (self.schaltjahr(gJahr)) { letzter = 29; } else { letzter = 28; } break; default: letzter = 31; break; } return letzter; }; /** * Die Kalenderwoche für ein Datum ermitteln * * @param {int} jahr * @param {int} monat * @param {int} tag * @param {int} erster der Wochentag, mit dem eine Woche beginnt (0=Sonntag .. 6=Samstag) * @returns {int} die Nummer der Kalenderwoche */ this.kalenderwoche = function(jahr, monat, tag, erster) { var datum = new Date(jahr,monat,tag); var ersterTagDieserẂoche = self.wochenbeginn(datum, erster); var bkw1 = self.beginnKw1(jahr, erster); var kw = Math.floor(1.5 + ( ersterTagDieserẂoche.getTime() - bkw1.getTime() ) / 86400000 / 7); if(kw < 1) { bkw1 = self.beginnKw1(jahr-1, erster); kw = Math.floor(1.5 + ( ersterTagDieserẂoche.getTime() - bkw1.getTime() ) / 86400000 / 7); } else if(kw > 52) { if(ersterTagDieserẂoche.getDate() > 28) { kw = 1; } } return kw; }; /** * Das Datum des Wochenbeginns fuer die Woche ermitteln, in der * ein Datum liegt. * * @param {Date} datum das Datum, für das der Wochenbeginn gesucht wird * @param {int} erster erster Tag der Woche (0 = Sonntag .. 6 = Samstag) * @returns {Date} das Datum des ersten Tages der Woche */ this.wochenbeginn = function(datum, erster) { var datumTag = datum.getDay(); var tagDatum = new Date(); tagDatum.setTime(datum.getTime()); while(datumTag !== erster) { tagDatum.setTime(tagDatum.getTime() - 86400000); datumTag = tagDatum.getDay(); } return tagDatum; }; /** * Den Wochentag wotag ermitteln, der in der Woche liegt, die mit * dem Datum erster beginnt. * * Also: Ermittle den Mittwoch der Woche, die mit dem 7.9.2021 beginnt. * * @param {type} erster Datum des ersten Tages der betreffenden Woche * @param {type} wotag gesuchter Wochentag (0=Sonntag .. 6=Samstag) * @returns {Date|tagInWo.wtDatum} Datum den gesuchten Wochentags */ this.tagInWo = function(erster, wotag) { var wt = erster.getDay(); var wtDatum = new Date(); wtDatum.setTime(erster.getTime()); while(wt !== wotag) { wtDatum.setTime(wtDatum.getTime() + 86400000); wt = wtDatum.getDay(); } return wtDatum; }; /** * Das Datum des ersten Tages der KW 1 eines Jahres * ermitteln * * @param {int} jahr das Jahr, für das der erste Tag der KW 1 ermittelt werden soll * @param {int} erster der Wochentag, mit dem eine Woche beginnt (0=Sonntag .. 6=Samstag) * @returns {Date} das Datum des ersten Tages der KW 1 von [jahr] */ this.beginnKw1 = function(jahr, erster) { var wbJ1 = self.wochenbeginn(new Date(jahr, 0, 1), erster); var ersterWt = self.tagInWo(wbJ1, self.kwt[erster]); if(ersterWt.getFullYear() < jahr) { ersterWt.setTime(ersterWt.getTime() + (7 * 86400000)); } return self.wochenbeginn(ersterWt, erster); }; }