undisclosed
2023-01-31 cc0b201102a902e52407c524ba38611886796d59
commit | author | age
231393 1 /*
U 2     MonatsboxFabrik - a date component for the browser
3     Copyright (c) 2012, 2021  Ulrich Hilger
4
5     This program is free software: you can redistribute it and/or modify
6     it under the terms of the GNU Affero General Public License as published by
7     the Free Software Foundation, either version 3 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU Affero General Public License for more details.
14
15     You should have received a copy of the GNU Affero General Public License
16     along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 /**
20  * Die MonatsboxFabrik liefert mit der Funktion
21  * monatsboxErzeugen eine Monatsbox
22  */
23 function MonatsboxFabrik() {
24   var self = this;
25   this.gewaehlteZelle = null;
26   this.j = -1;
27   this.m = -1;
0dce88 28   this.r = -1; // Ruhetag
231393 29   this.stilName = 'monatsboxRumpf';
0dce88 30   this.alterStilName = 'monatsboxRumpf';
231393 31
U 32   this.kwt = new Array(3, 4, 5, 6, 0, 1, 2);
33   
34 /**
35  * Eine Monatsbox zusammensetzen
36  * 
37  * @param {int} jahr ein beliebiges Jahr
38  * @param {int} monat 0=Januar .. 11=Dezember
39  * @param {int} starttag der Wochentag, mit dem eine Woche startet, 
40  *                  0=Sonntag .. 6=Samstag
41  * @param {int} ruhetag der Wochentag, der als Ruhetag markiert werden soll, 
42  *                  0=Sonntag .. 6=Montag
43  * @param {type} ereignisse eine Map, die fuer jeden Tag mit Ereignissen einen 
44  *                  Klassennamen zurueckgibt
45  * @param {type} lauscher die Funktion, die gerufen wird, wenn ein Tag 
46  *                   geklickt wird
47  * @returns {Element} die Monatsbox
48  */
49   this.monatsboxErzeugen = function(jahr, monat, starttag, ruhetag, ereignisse, lauscher) {
50
51     // Jahr und Monat merken
52     this.j = jahr;
53     this.m = monat;
54
55     // eine Tabelle nimmt die Monatsbox auf
56     var tabelle = document.createElement("table");
57     tabelle.className = "monatsbox";
58     tabelle.setAttribute('jahr', jahr);
59     tabelle.setAttribute('monat', monat);
60
61     // Ruhetagspalte abhaengig vom ersten Tag der Woche bestimmen
62     var ruhetagspalte = self.spalteBestimmen(ruhetag, starttag) + 1;
63     this.r = ruhetagspalte;
64
65     // Ueberschrift bilden
66     tabelle.appendChild(self.monatsboxKopf(starttag, ruhetagspalte));
67
68     // Startdatum setzen
69     var tagesDatum = 1;
70     var datum = new Date();
71     datum.setFullYear(jahr);
72     datum.setDate(tagesDatum);
73     datum.setMonth(this.m);
74
75     // Startspalte abhaengig vom ersten Tag der Woche bestimmen
76     var startspalte = self.spalteBestimmen(datum.getDay(), starttag) + 1;
77
78     // den Rumpf der Monatsbox erzeugen
79     var zeile = 0;
80     var spalte = 0;
81     var w = 0;
82     var tr = document.createElement("tr");
83     var td;
84     var stilName;
85     var letzterTag = self.letzterTagImMonat(jahr, monat);
86     while(tagesDatum <= letzterTag) {
87       stilName = null;
88       td = document.createElement("td");
89       td.onclick = lauscher;
90       if(spalte == ruhetagspalte) {
91         stilName = ereignisse.get(tagesDatum);
92         td.className = "monatsboxRumpfRuhetag";
93       } else if(spalte == 0) {
94         td.className = "monatsboxWoche";
95       } else {
96         stilName = ereignisse.get(tagesDatum);
97         td.className = "monatsboxRumpf";
98       }
99       if(zeile == 0 && spalte < startspalte) {
100         if(spalte == 0) {
101           w = self.kalenderwoche(jahr, monat, tagesDatum, starttag);
102           td.innerHTML = w;
103         }
104       } else if(spalte == 0) {
105         // woche schreiben
106         if(w > 51) {
107           //w = kalenderwoche(jahr, monat, tagesDatum + 1, starttag);
108           w = self.kalenderwoche(jahr, monat, tagesDatum, starttag);
109           td.innerHTML = w;
110         } else {
111           td.innerHTML = ++w;
112         }
113       } else {
114         if(stilName !== null && stilName  !== undefined && stilName.length > 0) {
115           td.className = stilName;
116         }
117         td.innerHTML = String(tagesDatum);
118         datum.setDate(++tagesDatum);
119       }
120       tr.appendChild(td);
121       if(++spalte > 7) {
122         spalte = 0;
123         ++zeile;
124         tabelle.appendChild(tr);
125         tr = document.createElement("tr");
126       } 
127     }
128     if(spalte > 0) {
129       tabelle.appendChild(tr);
130       ++zeile;
131     }
132     if(spalte == 0 && zeile == 5) {
133       self.zeileAnfuegen(tabelle);
134       ++zeile;
135     }
136     while(zeile < 6) {
137       self.zeileAnfuegen(tabelle);
138       zeile++;
139     }
140     return tabelle;
141   };
142
143   this.zeileAnfuegen = function(tabelle) {
144     var tr = document.createElement("tr");
145     var td = document.createElement("td");
146     td.innerHTML = '&nbsp;';
147     tr.appendChild(td);
148     tabelle.appendChild(tr);
149   };
150
151 /**
0dce88 152  * Anhand eines Klick-Ereignisses in die Monatsbox bestimmen, ob ein Tag 
U 153  * angeklickt wurde. Wenn ein Tag angeklickt wurde, diesen farblich 
154  * hervorheben und das Datum des geklickten Tages zurueckgeben. 
155  * Wenn kein Tag angeklickt wurde, null zurueckgeben.
231393 156  */
U 157   this.datum = function(Ereignis) {
cc0b20 158     var ermitteltesDatum = null;
U 159     const td = Ereignis.target;
160     const boxTab = td.parentNode.parentNode;    
161     const meinMonat = Number(boxTab.getAttribute('monat'));
162     const spalte = td.cellIndex;
163     const tagesDatum = Number(td.innerHTML);
231393 164     if(spalte > 0 && tagesDatum !== Number.NaN && tagesDatum > 0) {
U 165       if(this.gewaehlteZelle !== null) {
0dce88 166         this.gewaehlteZelle.className = this.alterStilName;
231393 167       }
U 168       this.gewaehlteZelle = td;
cc0b20 169       ermitteltesDatum = new Date(this.j, meinMonat, tagesDatum);
0dce88 170       this.alterStilName = td.className;
231393 171       td.className = 'monatsboxGewaehlt';
cc0b20 172       //ermitteltesDatum.setFullYear(this.j);
U 173       //ermitteltesDatum.setDate(tagesDatum);
174       //ermitteltesDatum.setMonth(meinMonat);
175       //ermitteltesDatum.setDate(tagesDatum);
176       //ermitteltesDatum.setMonth(meinMonat);
231393 177     }
cc0b20 178     return ermitteltesDatum;
231393 179   };
U 180
181 /**
182  * Die Spalte eines Wochentags abhaengig vom Tag bestimmen, 
183  * mit dem eine Woche startet
184  * 
185  * wochentag: Wochentag, dessenSpalte bestimmt werden soll
186  * starttag: Wochentag, mit dem eine Woche beginnt
187  * 
188  * Jeweils 0=Sonntag .. 6=Samstag
189  */
190   this.spalteBestimmen = function(wochentag, starttag) {
191     var spalte = wochentag - starttag;
192     if(spalte < 0) {
193       spalte = 7 + spalte;
194     }
195     return spalte;
196   };
197
198 /**
199  * Die Ueberschrift einer Monatsbox bestehend aus 
200  * Wochentagsnamen bilden
201  * 
202  * starttag: Wochentag, mit dem eine Woche beginnt
203  * ruhetagspalte: Spalte des Wochentages, der als Ruhetag markiert werden soll
204  * 
205  * Jeweils 0=Sonntag .. 6=Samstag
206  */
207   this.monatsboxKopf = function(starttag, ruhetagspalte) {
208     var tagesnamen = new Array("Sonntag", "Montag", "Dienstag", "Mittwoch", 
209       "Donnerstag", "Freitag", "Samstag");
210     var tr = document.createElement("tr");
211     var td;
212     td = document.createElement("td");
213     td.className = "monatsboxKopfWoche";    
214     td.innerHTML = "Kw";
215     tr.appendChild(td);
216     for(var index = 1; index < 8; index++) {
217       td = document.createElement("td");
218       if(index == ruhetagspalte) {
219         td.className = "monatsboxKopfRuhetag";    
220       } else {
221         td.className = "monatsboxKopf";
222       }
223       //console.log(starttag + ' ' + index);
224       if(Number(starttag) + Number(index) > 7) {
225         td.innerHTML = tagesnamen[Number(starttag) + Number(index) - 8].substring(0, 2); 
226       } else {
227         td.innerHTML = tagesnamen[Number(starttag) + Number(index) - 1].substring(0, 2);
228       }
229       tr.appendChild(td);
230     }
231     return tr;
232   };
233
234 /* ----------------- Datumsberechnungen ---------------------- */
235
236 /**
237  * Bestimmen, ob ein Jahr ein Schaltjahr ist
238  * j: Das Jahr, fuer das bestimmt werden soll,ob es ein Schaltjahr ist
239  * Rueckgabe: true, wenn das Jahr ein Schaltjahr ist, false wenn nicht
240  */
241   this.schaltjahr = function(j) {
242     var istSchalt = false;
243     if(((j % 4 == 0) && (j % 100 != 0)) || (j % 400 == 0)) {
244       istSchalt = true;
245     }
246     return istSchalt;
247   };
248
249 /**
250  * Den letzten Tag eines Monats im Gregorianischen Kalender bestimmen
251  *
252  * @param gJahr  das Jahr des Monats im Gregorianischen Kalender
253  * @param month  der Monat im Gregorianischen Kalender
254  * @return  Nummer des letzten Tages im betreffenden Monat (28, 29, 30 oder 31)
255  */
256   this.letzterTagImMonat = function(gJahr, month) {
257     var letzter = -1;
258     switch (month) {
259       case 3:
260       case 5:
261       case 8:
262       case 10:
263         letzter = 30;
264         break;
265       case 1:
266         if (self.schaltjahr(gJahr)) {
267           letzter = 29;
268         } else {
269           letzter = 28;
270         }
271         break;
272       default:
273         letzter = 31;
274         break;
275     }
276     return letzter;
277   };
278
279 /**
280  * Die Kalenderwoche für ein Datum ermitteln
281  * 
282  * @param {int} jahr
283  * @param {int} monat
284  * @param {int} tag
285  * @param {int} erster  der Wochentag, mit dem eine Woche beginnt (0=Sonntag .. 6=Samstag)
286  * @returns {int} die Nummer der Kalenderwoche
287  */
288   this.kalenderwoche = function(jahr, monat, tag, erster) {
289     var datum = new Date(jahr,monat,tag);
290     var ersterTagDieserẂoche = self.wochenbeginn(datum, erster);
291     var bkw1 = self.beginnKw1(jahr, erster);
292     var kw = Math.floor(1.5 + ( ersterTagDieserẂoche.getTime() - bkw1.getTime() ) / 86400000 / 7);
293     if(kw < 1) {
294       bkw1 = self.beginnKw1(jahr-1, erster);
295       kw = Math.floor(1.5 + ( ersterTagDieserẂoche.getTime() - bkw1.getTime() ) / 86400000 / 7);
296     } else if(kw > 52) {
297       if(ersterTagDieserẂoche.getDate() > 28) {
298         kw = 1;
299       }
300     }
301     return kw;
302   };
303
304 /**
305  * Das Datum des Wochenbeginns fuer die Woche ermitteln, in der 
306  * ein Datum liegt.
307  * 
308  * @param {Date} datum  das Datum, für das der Wochenbeginn gesucht wird
309  * @param {int} erster erster Tag der Woche (0 = Sonntag .. 6 = Samstag)
310  * @returns {Date}  das Datum des ersten Tages der Woche
311  */
312   this.wochenbeginn = function(datum, erster) {
313     var datumTag = datum.getDay();
314     var tagDatum = new Date();
315     tagDatum.setTime(datum.getTime());
316     while(datumTag !== erster) {
317       tagDatum.setTime(tagDatum.getTime() - 86400000);
318       datumTag = tagDatum.getDay();
319     }
320     return tagDatum;
321   };
322
323 /**
324  * Den Wochentag wotag ermitteln, der in der Woche liegt, die mit
325  * dem Datum erster beginnt.
326  * 
327  * Also: Ermittle den Mittwoch der Woche, die mit dem 7.9.2021 beginnt.
328  * 
329  * @param {type} erster Datum des ersten Tages der betreffenden Woche
330  * @param {type} wotag  gesuchter Wochentag (0=Sonntag .. 6=Samstag)
331  * @returns {Date|tagInWo.wtDatum} Datum den gesuchten Wochentags
332  */
333   this.tagInWo = function(erster, wotag) {
334     var wt = erster.getDay();
335     var wtDatum = new Date();
336     wtDatum.setTime(erster.getTime());
337     while(wt !== wotag) {
338       wtDatum.setTime(wtDatum.getTime() + 86400000);
339       wt = wtDatum.getDay();
340     }
341     return wtDatum;
342   };
343
344 /**
345  * Das Datum des ersten Tages der KW 1 eines Jahres 
346  * ermitteln
347  * 
348  * @param {int} jahr  das Jahr, für das der erste Tag der KW 1 ermittelt werden soll
349  * @param {int} erster  der Wochentag, mit dem eine Woche beginnt (0=Sonntag .. 6=Samstag)
350  * @returns {Date} das Datum des ersten Tages der KW 1 von [jahr]
351  */
352   this.beginnKw1 = function(jahr, erster) {
353     var wbJ1 = self.wochenbeginn(new Date(jahr, 0, 1), erster);
354     var ersterWt = self.tagInWo(wbJ1, self.kwt[erster]);
355     if(ersterWt.getFullYear() < jahr) {
356       ersterWt.setTime(ersterWt.getTime() + (7 * 86400000));
357     }
358     return self.wochenbeginn(ersterWt, erster);
359   };  
360   
361   
362 }