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; |
|
28 |
this.r = -1; |
|
29 |
this.stilName = 'monatsboxRumpf'; |
|
30 |
|
|
31 |
this.kwt = new Array(3, 4, 5, 6, 0, 1, 2); |
|
32 |
|
|
33 |
/** |
|
34 |
* Eine Monatsbox zusammensetzen |
|
35 |
* |
|
36 |
* @param {int} jahr ein beliebiges Jahr |
|
37 |
* @param {int} monat 0=Januar .. 11=Dezember |
|
38 |
* @param {int} starttag der Wochentag, mit dem eine Woche startet, |
|
39 |
* 0=Sonntag .. 6=Samstag |
|
40 |
* @param {int} ruhetag der Wochentag, der als Ruhetag markiert werden soll, |
|
41 |
* 0=Sonntag .. 6=Montag |
|
42 |
* @param {type} ereignisse eine Map, die fuer jeden Tag mit Ereignissen einen |
|
43 |
* Klassennamen zurueckgibt |
|
44 |
* @param {type} lauscher die Funktion, die gerufen wird, wenn ein Tag |
|
45 |
* geklickt wird |
|
46 |
* @returns {Element} die Monatsbox |
|
47 |
*/ |
|
48 |
this.monatsboxErzeugen = function(jahr, monat, starttag, ruhetag, ereignisse, lauscher) { |
|
49 |
|
|
50 |
// Jahr und Monat merken |
|
51 |
this.j = jahr; |
|
52 |
this.m = monat; |
|
53 |
|
|
54 |
// eine Tabelle nimmt die Monatsbox auf |
|
55 |
var tabelle = document.createElement("table"); |
|
56 |
tabelle.className = "monatsbox"; |
|
57 |
tabelle.setAttribute('jahr', jahr); |
|
58 |
tabelle.setAttribute('monat', monat); |
|
59 |
|
|
60 |
// Ruhetagspalte abhaengig vom ersten Tag der Woche bestimmen |
|
61 |
var ruhetagspalte = self.spalteBestimmen(ruhetag, starttag) + 1; |
|
62 |
this.r = ruhetagspalte; |
|
63 |
|
|
64 |
// Ueberschrift bilden |
|
65 |
tabelle.appendChild(self.monatsboxKopf(starttag, ruhetagspalte)); |
|
66 |
|
|
67 |
// Startdatum setzen |
|
68 |
var tagesDatum = 1; |
|
69 |
var datum = new Date(); |
|
70 |
datum.setFullYear(jahr); |
|
71 |
datum.setDate(tagesDatum); |
|
72 |
datum.setMonth(this.m); |
|
73 |
|
|
74 |
// Startspalte abhaengig vom ersten Tag der Woche bestimmen |
|
75 |
var startspalte = self.spalteBestimmen(datum.getDay(), starttag) + 1; |
|
76 |
|
|
77 |
// den Rumpf der Monatsbox erzeugen |
|
78 |
var zeile = 0; |
|
79 |
var spalte = 0; |
|
80 |
var w = 0; |
|
81 |
var tr = document.createElement("tr"); |
|
82 |
var td; |
|
83 |
var stilName; |
|
84 |
var letzterTag = self.letzterTagImMonat(jahr, monat); |
|
85 |
while(tagesDatum <= letzterTag) { |
|
86 |
stilName = null; |
|
87 |
td = document.createElement("td"); |
|
88 |
td.onclick = lauscher; |
|
89 |
if(spalte == ruhetagspalte) { |
|
90 |
stilName = ereignisse.get(tagesDatum); |
|
91 |
td.className = "monatsboxRumpfRuhetag"; |
|
92 |
} else if(spalte == 0) { |
|
93 |
td.className = "monatsboxWoche"; |
|
94 |
} else { |
|
95 |
stilName = ereignisse.get(tagesDatum); |
|
96 |
td.className = "monatsboxRumpf"; |
|
97 |
} |
|
98 |
if(zeile == 0 && spalte < startspalte) { |
|
99 |
if(spalte == 0) { |
|
100 |
w = self.kalenderwoche(jahr, monat, tagesDatum, starttag); |
|
101 |
td.innerHTML = w; |
|
102 |
} |
|
103 |
} else if(spalte == 0) { |
|
104 |
// woche schreiben |
|
105 |
if(w > 51) { |
|
106 |
//w = kalenderwoche(jahr, monat, tagesDatum + 1, starttag); |
|
107 |
w = self.kalenderwoche(jahr, monat, tagesDatum, starttag); |
|
108 |
td.innerHTML = w; |
|
109 |
} else { |
|
110 |
td.innerHTML = ++w; |
|
111 |
} |
|
112 |
} else { |
|
113 |
if(stilName !== null && stilName !== undefined && stilName.length > 0) { |
|
114 |
td.className = stilName; |
|
115 |
} |
|
116 |
td.innerHTML = String(tagesDatum); |
|
117 |
datum.setDate(++tagesDatum); |
|
118 |
} |
|
119 |
tr.appendChild(td); |
|
120 |
if(++spalte > 7) { |
|
121 |
spalte = 0; |
|
122 |
++zeile; |
|
123 |
tabelle.appendChild(tr); |
|
124 |
tr = document.createElement("tr"); |
|
125 |
} |
|
126 |
} |
|
127 |
if(spalte > 0) { |
|
128 |
tabelle.appendChild(tr); |
|
129 |
++zeile; |
|
130 |
} |
|
131 |
if(spalte == 0 && zeile == 5) { |
|
132 |
self.zeileAnfuegen(tabelle); |
|
133 |
++zeile; |
|
134 |
} |
|
135 |
while(zeile < 6) { |
|
136 |
self.zeileAnfuegen(tabelle); |
|
137 |
zeile++; |
|
138 |
} |
|
139 |
return tabelle; |
|
140 |
}; |
|
141 |
|
|
142 |
this.zeileAnfuegen = function(tabelle) { |
|
143 |
var tr = document.createElement("tr"); |
|
144 |
var td = document.createElement("td"); |
|
145 |
td.innerHTML = ' '; |
|
146 |
tr.appendChild(td); |
|
147 |
tabelle.appendChild(tr); |
|
148 |
}; |
|
149 |
|
|
150 |
/** |
|
151 |
* Auf einen Klick in die Tabelle reagieren |
|
152 |
*/ |
|
153 |
this.datum = function(Ereignis) { |
|
154 |
var datum = null; |
|
155 |
var td = Ereignis.target; |
|
156 |
var boxTab = td.parentNode.parentNode; |
|
157 |
var alterStilName = td.className; |
|
158 |
var spalte = td.cellIndex; |
|
159 |
var tagesDatum = Number(td.innerHTML); |
|
160 |
if(spalte > 0 && tagesDatum !== Number.NaN && tagesDatum > 0) { |
|
161 |
if(this.gewaehlteZelle !== null) { |
|
162 |
var gSpalte = this.gewaehlteZelle.cellIndex; |
|
163 |
if(gSpalte === this.r) { |
|
164 |
this.gewaehlteZelle.className = 'monatsboxRumpfRuhetag'; |
|
165 |
} else { |
|
166 |
this.gewaehlteZelle.className = this.stilName; |
|
167 |
} |
|
168 |
} |
|
169 |
this.gewaehlteZelle = td; |
|
170 |
datum = new Date(); |
|
171 |
td.className = 'monatsboxGewaehlt'; |
|
172 |
datum.setFullYear(this.j); |
|
173 |
datum.setDate(tagesDatum); |
|
174 |
datum.setMonth(boxTab.getAttribute('monat')); |
|
175 |
//datum.setMonth(this.m); |
|
176 |
} |
|
177 |
this.stilName = alterStilName; |
|
178 |
return datum; |
|
179 |
}; |
|
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 |
} |