/*
|
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 <http://www.gnu.org/licenses/>.
|
*/
|
|
/**
|
* 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;
|
this.stilName = '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);
|
};
|
|
/**
|
* Auf einen Klick in die Tabelle reagieren
|
*/
|
this.datum = function(Ereignis) {
|
var datum = null;
|
var td = Ereignis.target;
|
var boxTab = td.parentNode.parentNode;
|
var alterStilName = td.className;
|
var spalte = td.cellIndex;
|
var tagesDatum = Number(td.innerHTML);
|
if(spalte > 0 && tagesDatum !== Number.NaN && tagesDatum > 0) {
|
if(this.gewaehlteZelle !== null) {
|
var gSpalte = this.gewaehlteZelle.cellIndex;
|
if(gSpalte === this.r) {
|
this.gewaehlteZelle.className = 'monatsboxRumpfRuhetag';
|
} else {
|
this.gewaehlteZelle.className = this.stilName;
|
}
|
}
|
this.gewaehlteZelle = td;
|
datum = new Date();
|
td.className = 'monatsboxGewaehlt';
|
datum.setFullYear(this.j);
|
datum.setDate(tagesDatum);
|
datum.setMonth(boxTab.getAttribute('monat'));
|
//datum.setMonth(this.m);
|
}
|
this.stilName = alterStilName;
|
return datum;
|
};
|
|
/**
|
* 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);
|
};
|
|
|
}
|