├── original.pdf
├── README.md
├── konami.js
├── style.css
├── index.html
└── stuff.js
/original.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kiliankoe/arbeitszeitnachweis/HEAD/original.pdf
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Arbeitszeitnachweis gem. Mindestlohngesetz
2 |
3 | ### Was ist das hier?
4 |
5 | Eine digitale Kopie des Formulars für den Arbeitszeitnachweis nach dem neuem Mindestlohngesetz für SHK Stellen an der TU Dresden, der seit dem 01. Januar 2015 von jedem geringfügig Beschäftigten einmal monatlich bei seinem Arbeitgeber abgegeben werden muss.
6 |
7 | ### Nutzung
8 |
9 | Der Inhalt dieses Repos ist über Github Pages veröffentlicht. Also [hier](http://kiliankoe.github.io/arbeitszeitnachweis/) klicken und Details zur Beschäftigung ausfüllen. Wahlweise auch gerne offline, ist alles nur HTML/CSS/JS, es wird nichts irgendwo gesammelt oder weggeschickt. Man kann die Parameter auch als URL Parameter direkt mit ausfüllen und spart sich noch mehr Arbeit. Einfach den folgenden String kopieren, anpassen und als Bookmark abspeichern.
10 |
11 | ```
12 | http://kiliankoe.github.io/arbeitszeitnachweis/index.html?monat=02&jahr=2015&name=Mustermann,%20Max&personalnummer=00123456&geburtsdatum=01.01.1970&kostenstelle=1111111X&vorgesetzter=Prof.%20Erika%20Mustermann&struktureinheit=Professur%20für%20Formularautomatisierung&laufzeit=01.10.2014-31.03.2015&arbeitszeit=5
13 | ```
14 |
15 | Wird die Wochenarbeitszeit im Formular selbst eingetragen füllt sich das Dokument selbständig mit zufälligen Werten an den Tagen, die links ausgewählt sind (default sind nur Wochentage). Ansonsten kann man natürlich die Arbeitszeiten auch manuell eintragen.
16 |
17 | CMD/CTRL + P und abgeben :)
18 |
--------------------------------------------------------------------------------
/konami.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Konami-JS ~
3 | * :: Now with support for touch events and multiple instances for
4 | * :: those situations that call for multiple easter eggs!
5 | * Code: http://konami-js.googlecode.com/
6 | * Examples: http://www.snaptortoise.com/konami-js
7 | * Copyright (c) 2009 George Mandis (georgemandis.com, snaptortoise.com)
8 | * Version: 1.4.2 (9/2/2013)
9 | * Licensed under the MIT License (http://opensource.org/licenses/MIT)
10 | * Tested in: Safari 4+, Google Chrome 4+, Firefox 3+, IE7+, Mobile Safari 2.2.1 and Dolphin Browser
11 | */
12 |
13 | var Konami = function (callback) {
14 | var konami = {
15 | addEvent: function (obj, type, fn, ref_obj) {
16 | if (obj.addEventListener)
17 | obj.addEventListener(type, fn, false);
18 | else if (obj.attachEvent) {
19 | // IE
20 | obj["e" + type + fn] = fn;
21 | obj[type + fn] = function () {
22 | obj["e" + type + fn](window.event, ref_obj);
23 | }
24 | obj.attachEvent("on" + type, obj[type + fn]);
25 | }
26 | },
27 | input: "",
28 | pattern: "38384040373937396665",
29 | load: function (link) {
30 | this.addEvent(document, "keydown", function (e, ref_obj) {
31 | if (ref_obj) konami = ref_obj; // IE
32 | konami.input += e ? e.keyCode : event.keyCode;
33 | if (konami.input.length > konami.pattern.length)
34 | konami.input = konami.input.substr((konami.input.length - konami.pattern.length));
35 | if (konami.input == konami.pattern) {
36 | konami.code(link);
37 | konami.input = "";
38 | e.preventDefault();
39 | return false;
40 | }
41 | }, this);
42 | this.iphone.load(link);
43 | },
44 | code: function (link) {
45 | window.location = link
46 | },
47 | iphone: {
48 | start_x: 0,
49 | start_y: 0,
50 | stop_x: 0,
51 | stop_y: 0,
52 | tap: false,
53 | capture: false,
54 | orig_keys: "",
55 | keys: ["UP", "UP", "DOWN", "DOWN", "LEFT", "RIGHT", "LEFT", "RIGHT", "TAP", "TAP"],
56 | code: function (link) {
57 | konami.code(link);
58 | },
59 | load: function (link) {
60 | this.orig_keys = this.keys;
61 | konami.addEvent(document, "touchmove", function (e) {
62 | if (e.touches.length == 1 && konami.iphone.capture == true) {
63 | var touch = e.touches[0];
64 | konami.iphone.stop_x = touch.pageX;
65 | konami.iphone.stop_y = touch.pageY;
66 | konami.iphone.tap = false;
67 | konami.iphone.capture = false;
68 | konami.iphone.check_direction();
69 | }
70 | });
71 | konami.addEvent(document, "touchend", function (evt) {
72 | if (konami.iphone.tap == true) konami.iphone.check_direction(link);
73 | }, false);
74 | konami.addEvent(document, "touchstart", function (evt) {
75 | konami.iphone.start_x = evt.changedTouches[0].pageX;
76 | konami.iphone.start_y = evt.changedTouches[0].pageY;
77 | konami.iphone.tap = true;
78 | konami.iphone.capture = true;
79 | });
80 | },
81 | check_direction: function (link) {
82 | x_magnitude = Math.abs(this.start_x - this.stop_x);
83 | y_magnitude = Math.abs(this.start_y - this.stop_y);
84 | x = ((this.start_x - this.stop_x) < 0) ? "RIGHT" : "LEFT";
85 | y = ((this.start_y - this.stop_y) < 0) ? "DOWN" : "UP";
86 | result = (x_magnitude > y_magnitude) ? x : y;
87 | result = (this.tap == true) ? "TAP" : result;
88 |
89 | if (result == this.keys[0]) this.keys = this.keys.slice(1, this.keys.length);
90 | if (this.keys.length == 0) {
91 | this.keys = this.orig_keys;
92 | this.code(link);
93 | }
94 | }
95 | }
96 | }
97 |
98 | typeof callback === "string" && konami.load(callback);
99 | if (typeof callback === "function") {
100 | konami.code = callback;
101 | konami.load();
102 | }
103 |
104 | return konami;
105 | };
106 |
--------------------------------------------------------------------------------
/style.css:
--------------------------------------------------------------------------------
1 | @import url(https://fonts.googleapis.com/css?family=UnifrakturCook:700);
2 |
3 | @page {
4 | size: auto;
5 | margin: 0;
6 | }
7 |
8 | @media print {
9 | ::-webkit-input-placeholder { /* WebKit browsers */
10 | color: transparent;
11 | }
12 | :-moz-placeholder { /* Mozilla Firefox 4 to 18 */
13 | color: transparent;
14 | }
15 | ::-moz-placeholder { /* Mozilla Firefox 19+ */
16 | color: transparent;
17 | }
18 | :-ms-input-placeholder { /* Internet Explorer 10+ */
19 | color: transparent;
20 | }
21 |
22 | /* Fix dark themes in FF */
23 | input[type=text] {
24 | color: black;
25 | background-color: white;
26 | }
27 | }
28 |
29 | body {
30 | font-family: Univers Light, "Univers 45 Light";
31 | width: 21cm;
32 | margin-left: 5cm;
33 | margin-top: 1.5cm;
34 | font-size: 9pt;
35 | }
36 |
37 | body > * {
38 | width: 18cm;
39 | }
40 |
41 | sup {
42 | font-size: 65%;
43 | }
44 |
45 | /* TITLE */
46 |
47 | .title p {
48 | margin: 0;
49 | }
50 |
51 | .title p.left {
52 | font-weight: bold;
53 | float: left;
54 | font-size: 120%;
55 | }
56 |
57 | .title p.right {
58 | color: #FF0000;
59 | float: right;
60 | padding-right: 30px;
61 | font-size: 11pt;
62 | }
63 |
64 | /* SETTINGS */
65 |
66 | #settings {
67 | border: 1px solid #000;
68 | background: #f3f3f3;
69 | position: absolute;
70 | left: 2mm;
71 | top: 2mm;
72 | width: 4cm;
73 | padding: 5px;
74 | }
75 |
76 | #settings h2 {
77 | margin: 0;
78 | }
79 |
80 | #settings input[type=button], #footnotesignlabel {
81 | width:90%;
82 | margin: 0 5%;
83 | border: 1px solid #000;
84 | display: block;
85 | text-align: center;
86 | }
87 |
88 | #settings input[type=button]:hover, #footnotesignlabel:hover {
89 | background: #fff;
90 | }
91 |
92 | #footnotesignlabel {
93 | margin-top: 0.2rem;
94 | }
95 |
96 | #addbookmark {
97 | text-align: center;
98 | margin-top: 10px;
99 | }
100 |
101 | @media print {
102 | #settings {
103 | display: none;
104 | }
105 |
106 | .github-corner {
107 | display: none;
108 | }
109 | }
110 |
111 | /* HEAD */
112 |
113 | input[type=text], input[type=date] {
114 | border: none;
115 | margin-left: 2% !important;
116 | width: 95%;
117 | height: 9pt;
118 | max-width: 95%;
119 | /*
120 | font-family: Comic Sans, Comic Sans MS, cursive;
121 | font-weight: bold;
122 | */
123 | /*-webkit-box-sizing: border-box;
124 | -moz-box-sizing: border-box;
125 | box-sizing: border-box;*/
126 | font-size: 8pt;
127 | }
128 |
129 | input[type=file] {
130 | display: none;
131 | }
132 |
133 | input#struktureinheit, input#laufzeit {
134 | padding-top: 10pt;
135 | }
136 |
137 | #head {
138 | border: 1px solid black;
139 | border-spacing: 0;
140 | clear: both;
141 | /*border-collapse: collapse;*/
142 | width: 18cm;
143 | height: 4.6cm;
144 | }
145 | #fuckinggray {
146 | background-color: #f3f3f3;
147 | height: 6px;
148 | }
149 |
150 | /*#head tr * {
151 | border: 0 !important;
152 | }*/
153 |
154 | #head th {
155 | background: #f3f3f3;
156 | border: none;
157 | font-weight: normal;
158 | text-align: left;
159 | /*
160 | padding: 2px;
161 | padding-top: 4pt;
162 | */
163 | position: relative;
164 | }
165 |
166 | #head td {
167 | padding: 0;
168 | border: .75px solid black;
169 | }
170 |
171 | #head th label {
172 | position: absolute;
173 | bottom: 0;
174 | }
175 |
176 | #head0 {
177 | width: 18%;
178 | }
179 |
180 | #head1 {
181 | width: 30%;
182 | }
183 |
184 | #head2 {
185 | width: 12%;
186 | }
187 |
188 | #head3, #head4 {
189 | width: 17%;
190 | }
191 |
192 | .notop {
193 | border-top: 0 !important;
194 | }
195 |
196 | .nobottom {
197 | border-bottom: 0 !important;
198 | }
199 |
200 | .noright {
201 | border-right: 0 !important;
202 | }
203 |
204 | .extratop {
205 | border-top: .75px solid black !important;
206 | }
207 |
208 | .extrabottom {
209 | border-bottom: .75px solid black !important;
210 | }
211 |
212 | .extraleft {
213 | border-left: .75px solid black !important;
214 | }
215 |
216 | #monatlabel {
217 | padding-left: 55pt;
218 | }
219 |
220 | /* KALENDER */
221 |
222 | #kalender {
223 | border: 2px solid black;
224 | clear: both;
225 | border-collapse: collapse;
226 | width: 18cm;
227 | margin-bottom: 20px;
228 | }
229 |
230 | #kalender td, #kalender th {
231 | border: 1px solid black;
232 | font-weight: normal;
233 | text-align: left;
234 | vertical-align: bottom;
235 | }
236 |
237 | #kalender td {
238 | height: 6mm;
239 | }
240 |
241 | #kalender .kopf td, #kalender .kopf th {
242 | height: 18.2mm;
243 | }
244 |
245 | #kalender tr:first-child th {
246 | vertical-align: middle;
247 | text-align: center;
248 | padding-bottom: 8pt;
249 | }
250 |
251 | #kalender th {
252 | background-color: #f3f3f3;
253 | }
254 |
255 | #kalendertag {
256 | width: 8.5%;
257 | }
258 |
259 | #kommen, #gehen {
260 | width: 10.5%;
261 | }
262 |
263 | #stunden {
264 | width: 21.6%;
265 | }
266 |
267 | #gesamtzahl th {
268 | font-weight: bold;
269 | }
270 |
271 | /* UNTERSCHRIFT */
272 |
273 | #unterschrift {
274 | margin-top: 20pt;
275 | border: 0;
276 | border-collapse: collapse;
277 | }
278 |
279 | #unterschrift td {
280 | width: 51.1%;
281 | height: 14pt;
282 | }
283 |
284 | #unterschrift tr:first-child td {
285 | border-bottom: 1px solid black;
286 | }
287 |
288 | #unterschrift tr:first-child td:first-child {
289 | border-right: 1px solid black;
290 | }
291 |
292 | /* FOOTER */
293 |
294 | .footer {
295 | margin-top: 15px;
296 | background-color: #eee;
297 | font-size: 6pt;
298 | padding-bottom: 3px;
299 | }
300 |
301 | .footer p {
302 | margin: 0;
303 | margin-top: 4pt;
304 | }
305 |
306 | .nosup {
307 | padding-left: 5px;
308 | }
309 |
310 | .hastooltip:hover .tooltip {
311 | display: block;
312 | }
313 |
314 | .tooltip {
315 | display: none;
316 | background: #C8C8C8;
317 | margin-left: 28px;
318 | padding: 10px;
319 | position: absolute;
320 | z-index: 1000;
321 | width:200px;
322 | }
323 |
324 | #unterschriftzelle {
325 | position: relative;
326 | }
327 |
328 | #unterschriftzelle span {
329 | position: absolute;
330 | bottom: 0;
331 | }
332 |
333 | #unterschriftzelle img {
334 | position: absolute;
335 | right: 0.5cm;
336 | bottom: 0;
337 | max-width: 5cm;
338 | max-height: 1cm;
339 | }
340 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Arbeitszeitnachweis gem. Mindestlohngesetz
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
Arbeitszeitnachweis gem. Mindestlohngesetz
14 |
Anlage zum RS D2/1/2015
15 |
16 |
17 |
18 |
19 |
20 |
21 |
Einstellungen
22 |
73 |
76 |
77 |
78 |
116 |
117 |
145 |
146 |
147 |
148 | | | |
149 |
150 |
151 | | Datum, Unterschrift Beschäftigte/r | Datum, Unterschrift Betreuer/in bzw. Vorgesetzte/r |
152 |
153 |
154 |
155 |
164 |
165 |
166 |
--------------------------------------------------------------------------------
/stuff.js:
--------------------------------------------------------------------------------
1 | var kona = new Konami();
2 | kona.code = function() {
3 | document.getElementsByTagName("body")[0].style.fontFamily = "UnifrakturCook";
4 | var inputs = document.getElementsByTagName("input");
5 | for (var i = inputs.length - 1; i >= 0; i--) {
6 | inputs[i].style.fontFamily = "UnifrakturCook";
7 | }
8 | };
9 | kona.load();
10 |
11 | var urlParams;
12 |
13 | window.onload = function () {
14 | var gesamtzahl = document.getElementById("gesamtzahl");
15 | var monat = document.getElementById("monat");
16 | var jahr = document.getElementById("jahr");
17 | var kalender = gesamtzahl.parentNode;
18 |
19 | var datum = new Date();
20 | jahr.value = datum.getFullYear();
21 | monat.value = (datum.getMonth() < 9 ? "0":"") + (datum.getMonth()+1);
22 |
23 | for(var i=1; i<=31; i++) {
24 | var tag = document.createElement("tr");
25 | var th = document.createElement("th");
26 | th.innerHTML = i+".";
27 | tag.appendChild(th);
28 | for(var j=0; j<4; j++) {
29 | var td = document.createElement("td");
30 |
31 | switch (j) {
32 | case 0:
33 | var comeinput = document.createElement("input");
34 | comeinput.id = "kommenzeit"+i;
35 | comeinput.type = "text";
36 | td.appendChild(comeinput);
37 | break;
38 | case 1:
39 | var leaveinput = document.createElement("input");
40 | leaveinput.id = "gehenzeit"+i;
41 | leaveinput.type = "text";
42 | td.appendChild(leaveinput);
43 | break;
44 | case 2:
45 | var stundeninput = document.createElement("input");
46 | stundeninput.id = "tagesstunden";
47 | stundeninput.type = "text";
48 | stundeninput.addEventListener('change', function() {
49 | calculateTotal();
50 | });
51 | td.appendChild(stundeninput);
52 | break;
53 | case 3:
54 | var bemerkung = document.createElement("input");
55 | bemerkung.className = "bemerkung";
56 | bemerkung.id = "bemerkung"+i;
57 | bemerkung.type = "text";
58 | td.appendChild(bemerkung);
59 | break;
60 | default:
61 | break;
62 | }
63 |
64 | tag.appendChild(td);
65 | }
66 |
67 |
68 | kalender.insertBefore(tag, gesamtzahl);
69 | }
70 |
71 | // http://stackoverflow.com/questions/901115/how-can-i-get-query-string-values-in-javascript
72 | var match,
73 | pl = /\+/g, // Regex for replacing addition symbol with a space
74 | search = /([^&=]+)=?([^&]*)/g,
75 | decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); },
76 | query = window.location.search.substring(1);
77 |
78 | urlParams = {};
79 | while (match = search.exec(query))
80 | urlParams[decode(match[1])] = decode(match[2]);
81 |
82 | for (var field in urlParams) {
83 | document.getElementById(field).value = urlParams[field];
84 | document.getElementById(field).checked = true; // needed for the timeoptions
85 | }
86 |
87 | var arbeitszeit = document.getElementById("arbeitszeit").value;
88 | if (arbeitszeit)
89 | generateStuff();
90 | };
91 |
92 | function generateStuff() {
93 | if (numberOfCheckedWeekdays() == 0) {
94 | document.querySelector("fieldset[name='wochentage']").style.color = "red";
95 | return;
96 | } else {
97 | document.querySelector("fieldset[name='wochentage']").style.color = "#000";
98 | }
99 |
100 | var jahr = document.getElementById("jahr").value;
101 | var months = {"01":31, "02":(jahr%400===0||(jahr%4===0&&jahr%100!==0))?29:28, "03":31, "04":30, "05":31, "06":30, "07":31, "08":31, "09":30, "10":31, "11":30, "12":31};
102 |
103 | var gesamtzahl = document.querySelectorAll("#gesamtzahlinput");
104 | var stundenzahl = document.getElementById("arbeitszeit").value;
105 | var monat = document.getElementById("monat").value;
106 |
107 | // don't even try to do stuff when entered month is undefined
108 | // this fucks with getWeeklyDist if not present
109 | if (!(monat in months)) {
110 | return;
111 | }
112 |
113 | var bemerkungsfelder = document.querySelectorAll("input.bemerkungstext");
114 | var cometimesfelder = document.querySelectorAll("input.cometimestext");
115 | var leavetimesfelder = document.querySelectorAll("input.leavetimestext");
116 |
117 | var bemerkungen = [];
118 | var cometimes = [];
119 | var leavetimes = [];
120 |
121 | for (var i = 0; i < bemerkungsfelder.length; ++i) {
122 | if (bemerkungsfelder[i].value)
123 | bemerkungen.push(bemerkungsfelder[i].value);
124 | }
125 | for (i = 0; i < cometimesfelder.length; ++i) {
126 | if (cometimesfelder[i].value)
127 | cometimes.push(cometimesfelder[i].value);
128 | }
129 | for (i = 0; i < leavetimesfelder.length; ++i) {
130 | if (leavetimesfelder[i].value)
131 | leavetimes.push(leavetimesfelder[i].value);
132 | }
133 |
134 | var zellen = document.querySelectorAll("input#tagesstunden");
135 |
136 | var verteilung = getDist(months[monat]);
137 |
138 | for (i = 0; i < zellen.length; i+=1) {
139 | if (stundenzahl !== "" && i < verteilung.length) {
140 | if (verteilung[i] === 0) {
141 | zellen[i].value = "";
142 | document.querySelector("input#bemerkung"+(i+1)).value = "";
143 | document.querySelector("input#kommenzeit"+(i+1)).value = "";
144 | document.querySelector("input#gehenzeit"+(i+1)).value = "";
145 | } else {
146 | zellen[i].value = formatTime(verteilung[i]);
147 | if (bemerkungen.length > 0)
148 | document.querySelector("input#bemerkung"+(i+1)).value = bemerkungen[Math.floor(Math.random()*bemerkungen.length)];
149 | if (cometimes.length > 0){
150 | var clock = cometimes[Math.floor(Math.random()*cometimes.length)];
151 | var h = parseInt(clock.match(/^[\d]+/));
152 | var m = parseInt(clock.match(/[\d]+$/));
153 |
154 | h = (h + Math.floor(m / 60)) % 24
155 | m %= 60
156 |
157 | document.querySelector("input#kommenzeit"+(i+1)).value = h + ":" + (m < 10 ? "0" + m : m);
158 |
159 | var deltaH = Math.floor(verteilung[i])
160 | var deltaM = Math.round((verteilung[i] - deltaH) * 60)
161 | if (14 > h && 11 < h + verteilung[i]){ // lunch time!
162 | var lunchtime = getRandomInt(0, Math.min(3, verteilung[i])) * 30 + m;
163 | deltaM += lunchtime % 60;
164 | deltaH += Math.floor(lunchtime / 60);
165 | }
166 |
167 | var gehenH = h + deltaH
168 | var gehenM = m + deltaM
169 |
170 | gehenH = (gehenH + Math.floor(gehenM / 60)) % 24
171 | gehenM %= 60
172 |
173 | document.querySelector("input#gehenzeit"+(i+1)).value = gehenH + ":" + (gehenM < 10 ? "0" + gehenM : gehenM);
174 | }
175 | }
176 | } else {
177 | zellen[i].value = "";
178 | }
179 | }
180 |
181 | calculateTotal();
182 | generateUnterschrift();
183 | }
184 |
185 | function formatTime(x) {
186 | var formatoption = document.querySelector("input[name='formatoptions']:checked").value;
187 | let hours = Math.floor(x);
188 | let minutes = x - hours;
189 | switch (formatoption) {
190 | case "formatoption1":
191 | return ((minutes > 0.01) ? x.toFixed(2) : hours + "").replace(".",",");
192 | case "formatoption2":
193 | return hours + ":" + (Math.floor(minutes * 60) + "").padStart(2, '0');
194 | default:
195 | console.log("Ya got something freaky going on there with the format options, mate...");
196 | break;
197 | }
198 | }
199 |
200 | function calculateTotal() {
201 | var gesamtzahl = document.querySelectorAll("#gesamtzahlinput");
202 | var zellen = document.querySelectorAll("input#tagesstunden");
203 | var total = 0.0;
204 |
205 | for (var i = 0; i <= zellen.length - 1; i++) {
206 | var hours = zellen[i].value;
207 | hours = parseFloat(hours.replace(',', '.'));
208 | if (isNaN(hours)) {
209 | continue;
210 | }
211 | total += hours;
212 | }
213 | gesamtzahl[0].value = total.toLocaleString("de-DE", {maximumFractionDigits: 2});
214 | }
215 |
216 | function getDist(days) {
217 | var timeoption = document.querySelector("input[name='timeoptions']:checked").value;
218 | switch (timeoption) {
219 | case "timeoption1":
220 | return getRandomDist(days, 4.33);
221 | case "timeoption2":
222 | return getRandomDist(days, 4.0);
223 | case "timeoption3":
224 | return getWeeklyDist(days);
225 | case "timeoption4":
226 | return getEvenDist(days);
227 | default:
228 | console.log("Ya got something freaky going on there with the time options, mate...");
229 | break;
230 | }
231 | }
232 |
233 | function getRandomDist(days, stundenzahl_value) {
234 | var dist = [];
235 | var stundenzahl = document.getElementById("arbeitszeit").value * stundenzahl_value;
236 | var stundenPaket = 1;
237 |
238 | for (var i = days - 1; i >= 0; i--) {
239 | dist[i] = 0;
240 | }
241 | var tage = tagesform.wochentag;
242 | var jahr = document.getElementById("jahr").value;
243 | var monat = document.getElementById("monat").value-1;
244 |
245 | while (stundenzahl > 0) {
246 | //stundenPaket = Math.floor(Math.random() * (stundenzahl+1));
247 |
248 | var tag = Math.floor(Math.random() * days);
249 |
250 | // check if day is valid
251 | // checkboxes for single calendar days, e.g. holidays, could be added
252 | var datum = new Date(jahr, monat, tag+1);
253 | if(tage[datum.getDay()].checked) {
254 | dist[tag] += stundenPaket;
255 | stundenzahl -= stundenPaket;
256 | }
257 | }
258 |
259 | return dist;
260 | }
261 |
262 | function getWeeklyDist(days) {
263 | var dist = [];
264 | for (var i = days - 1; i >= 0; i--) {
265 | dist[i] = 0;
266 | }
267 |
268 | var stundenzahl = document.getElementById("arbeitszeit").value;
269 |
270 | var year = document.getElementById("jahr").value;
271 | var month = document.getElementById("monat").value-1;
272 | var checked_days = [...tagesform.wochentag].map(function(val){ return val.checked });
273 |
274 | var first_checked = Math.min(...checked_days.map(function(val, ind){ return val ? ind : Infinity }));
275 | var last_checked = Math.max(...checked_days.map(function(val, ind){ return val ? ind : -Infinity }));
276 |
277 | var mondays = getMondays(month, year);
278 | if (mondays[0] > 0) // add partial week
279 | mondays.unshift(mondays[0] - 7);
280 |
281 | mondays.forEach(function(monday){
282 | // valid first and last day of week
283 | var first = Math.max(monday + first_checked, 1);
284 | var last = Math.min(monday + last_checked, days);
285 |
286 | // current monday's checked days
287 | var checked_this_week = 0;
288 | for (var i = first; i <= last; i++)
289 | if (checked_days[i - monday])
290 | checked_this_week++;
291 |
292 | // if partial week use relative amount of hours
293 | var remaining_hours = Math.round(stundenzahl * checked_this_week / numberOfCheckedWeekdays());
294 | while (remaining_hours > 0) {
295 | var rand = getRandomInt(first, last);
296 | var validate = new Date(year, month, rand);
297 | if (checked_days[validate.getDay()]) {
298 | var h = getRandomInt(1, remaining_hours); // should result in less distributed results
299 | dist[rand-1] += h;
300 | remaining_hours -= h;
301 | }
302 | }
303 | });
304 |
305 | return dist;
306 | }
307 |
308 | function getEvenDist(days) {
309 | var stundenzahl = document.getElementById("arbeitszeit").value;
310 |
311 | var year = document.getElementById("jahr").value;
312 | var month = document.getElementById("monat").value-1;
313 | var checked_days = [...tagesform.wochentag].map(function(val){ return val.checked });
314 |
315 | var monday = getMondays(month, year)[0] - 1;
316 | while (monday < 0) monday += 7;
317 |
318 | var time_per_day = stundenzahl / checked_days.reduce(function(acc, curr) {
319 | return acc + curr; // Add 1 or 0 to acc
320 | }, 0);
321 |
322 | var dist = [];
323 | for (var i = days - 1; i >= 0; i--) {
324 | dist[i] = 0;
325 |
326 | if (checked_days[(i - monday + 7) % 7]) {
327 | dist[i] = time_per_day;
328 | }
329 | }
330 |
331 | return dist;
332 | }
333 |
334 | // Return zero-indexed dates of mondays in a month, possibly omitting the last one
335 | // if the month ends in the middle of that week.
336 | function getMondays(month, year) {
337 | var date = new Date(year, month, 1);
338 | month = date.getMonth();
339 | var mondays = [];
340 |
341 | // Get the first monday of month
342 | while (date.getDay() !== 1) {
343 | date.setDate(date.getDate() + 1);
344 | }
345 |
346 | // save this and all other mondays
347 | while (date.getMonth() === month) {
348 | mondays.push(date.getDate() - 1); // -1 because final date list is zero-indexed
349 | date.setDate(date.getDate() + 7);
350 | }
351 |
352 | return mondays;
353 | }
354 |
355 | function getRandomInt(min, max) {
356 | min = parseInt(min);
357 | max = parseInt(max);
358 | return Math.floor(Math.random() * (max - min + 1)) + min;
359 | }
360 |
361 | // for debugging only, can be deleted later
362 | function getDayStr(day) {
363 | switch (day) {
364 | case 0: return "sunday";
365 | case 1: return "monday";
366 | case 2: return "tuesday";
367 | case 3: return "wednesday";
368 | case 4: return "thursday";
369 | case 5: return "friday";
370 | case 6: return "saturday";
371 | }
372 | }
373 |
374 | function numberOfCheckedWeekdays() {
375 | var num = 0;
376 | for (var i = 0; i < 7; ++i) {
377 | num += tagesform.wochentag[i].checked;
378 | }
379 | return num;
380 | }
381 |
382 | function addBookmark() {
383 | var urlParams = [
384 | "name",
385 | "geburtsdatum",
386 | "personalnummer",
387 | "vorgesetzter",
388 | "laufzeit",
389 | "kostenstelle",
390 | "struktureinheit",
391 | "arbeitszeit"
392 | ].map(function(param){
393 | return param + "=" + document.getElementById(param).value;
394 | });
395 |
396 | var url = "index.html?"+urlParams.join("&");
397 | if (window.sidebar && window.sidebar.addPanel) {
398 | // Mozilla Firefox Bookmark
399 | window.sidebar.addPanel(document.title, url,'');
400 | } else if(window.external && ('AddFavorite' in window.external)) {
401 | // IE Favorite
402 | window.external.AddFavorite(url ,document.title);
403 | } else if(window.opera && window.print) {
404 | // Opera Hotlist
405 | this.title=document.title;
406 | return true;
407 | } else {
408 | // webkit - safari/chrome
409 | if (window.history)
410 | window.history.pushState({}, document.title, url);
411 | else
412 | window.location.href = url;
413 |
414 | alert('Press ' + (navigator.userAgent.toLowerCase().indexOf('mac') != - 1 ? 'Command/Cmd' : 'CTRL') + ' + D to bookmark this page.');
415 | }
416 | }
417 |
418 | function generateUnterschrift() {
419 | let datestring = document.getElementById("footnotedate").value;
420 | let unterschriftfile = document.getElementById("footnotesign").files[0];
421 |
422 | let unterschriftzelle = document.getElementById("unterschriftzelle");
423 | while (unterschriftzelle.firstElementChild) {
424 | unterschriftzelle.removeChild(unterschriftzelle.firstElementChild)
425 | }
426 |
427 | if (datestring != "") {
428 | var span = document.createElement("span");
429 | span.textContent = new Date(datestring).toLocaleDateString("de");
430 | unterschriftzelle.appendChild(span);
431 | }
432 |
433 | if (unterschriftfile) {
434 | var img = document.createElement("img");
435 | unterschriftzelle.appendChild(img);
436 |
437 | var reader = new FileReader();
438 | reader.onload = function(e) {
439 | img.src = e.target.result;
440 | }
441 | reader.readAsDataURL(unterschriftfile);
442 | }
443 | }
444 |
--------------------------------------------------------------------------------