diff --git a/index.html b/index.html
index 98e9165..3824541 100644
--- a/index.html
+++ b/index.html
@@ -318,6 +318,35 @@
margin: -4px 0 12px 0;
line-height: 1.4;
}
+
+ .time-24h-block {
+ margin-bottom: 15px;
+ }
+
+ .time-24h-block .time-24h-row {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ flex-wrap: wrap;
+ }
+
+ .time-24h-block input[type="number"] {
+ width: 4.25rem;
+ margin-bottom: 0;
+ text-align: center;
+ }
+
+ .time-24h-sep {
+ font-weight: 600;
+ color: #374151;
+ user-select: none;
+ }
+
+ .time-24h-hint {
+ font-size: 12px;
+ color: #6b7280;
+ margin-top: 4px;
+ }
@@ -355,11 +384,11 @@
-
+
diff --git a/main.js b/main.js
index 912604b..6c93e16 100644
--- a/main.js
+++ b/main.js
@@ -10,9 +10,11 @@ document.addEventListener('DOMContentLoaded', function() {
const wifiPasswordInput = document.getElementById('wifi-password');
const eventTitleInput = document.getElementById('event-title');
const eventStartDateInput = document.getElementById('event-start-date');
- const eventStartTimeInput = document.getElementById('event-start-time');
+ const eventStartHourInput = document.getElementById('event-start-hour');
+ const eventStartMinuteInput = document.getElementById('event-start-minute');
const eventEndDateInput = document.getElementById('event-end-date');
- const eventEndTimeInput = document.getElementById('event-end-time');
+ const eventEndHourInput = document.getElementById('event-end-hour');
+ const eventEndMinuteInput = document.getElementById('event-end-minute');
const eventLocationInput = document.getElementById('event-location');
const eventDescriptionInput = document.getElementById('event-description');
const sizeSelect = document.getElementById('size');
@@ -108,9 +110,11 @@ document.addEventListener('DOMContentLoaded', function() {
const hasWifi = wifiSsidInput.value.trim().length > 0 || wifiPasswordInput.value.trim().length > 0;
const hasEvent = eventTitleInput.value.trim().length > 0 ||
eventStartDateInput.value.length > 0 ||
- eventStartTimeInput.value.length > 0 ||
+ eventStartHourInput.value !== '' ||
+ eventStartMinuteInput.value !== '' ||
eventEndDateInput.value.length > 0 ||
- eventEndTimeInput.value.length > 0 ||
+ eventEndHourInput.value !== '' ||
+ eventEndMinuteInput.value !== '' ||
eventLocationInput.value.trim().length > 0 ||
eventDescriptionInput.value.trim().length > 0;
if (hasText || hasWifi || hasEvent) {
@@ -130,9 +134,11 @@ document.addEventListener('DOMContentLoaded', function() {
wifiPasswordInput.value = '';
eventTitleInput.value = '';
eventStartDateInput.value = '';
- eventStartTimeInput.value = '';
+ eventStartHourInput.value = '';
+ eventStartMinuteInput.value = '';
eventEndDateInput.value = '';
- eventEndTimeInput.value = '';
+ eventEndHourInput.value = '';
+ eventEndMinuteInput.value = '';
eventLocationInput.value = '';
eventDescriptionInput.value = '';
contentModeSelect.value = 'text';
@@ -187,12 +193,35 @@ document.addEventListener('DOMContentLoaded', function() {
}
eventStartDateInput.addEventListener('input', onEventDateTimeInput);
eventStartDateInput.addEventListener('change', onEventDateTimeInput);
- eventStartTimeInput.addEventListener('input', onEventDateTimeInput);
- eventStartTimeInput.addEventListener('change', onEventDateTimeInput);
+ eventStartHourInput.addEventListener('input', onEventDateTimeInput);
+ eventStartHourInput.addEventListener('change', onEventDateTimeInput);
+ eventStartMinuteInput.addEventListener('input', onEventDateTimeInput);
+ eventStartMinuteInput.addEventListener('change', onEventDateTimeInput);
eventEndDateInput.addEventListener('input', onEventDateTimeInput);
eventEndDateInput.addEventListener('change', onEventDateTimeInput);
- eventEndTimeInput.addEventListener('input', onEventDateTimeInput);
- eventEndTimeInput.addEventListener('change', onEventDateTimeInput);
+ eventEndHourInput.addEventListener('input', onEventDateTimeInput);
+ eventEndHourInput.addEventListener('change', onEventDateTimeInput);
+ eventEndMinuteInput.addEventListener('input', onEventDateTimeInput);
+ eventEndMinuteInput.addEventListener('change', onEventDateTimeInput);
+
+ function clampTimeNumberInput(el, max) {
+ if (el.value === '') {
+ return;
+ }
+ var v = parseInt(el.value, 10);
+ if (isNaN(v)) {
+ return;
+ }
+ if (v < 0) {
+ el.value = '0';
+ } else if (v > max) {
+ el.value = String(max);
+ }
+ }
+ eventStartHourInput.addEventListener('blur', function() { clampTimeNumberInput(eventStartHourInput, 23); });
+ eventStartMinuteInput.addEventListener('blur', function() { clampTimeNumberInput(eventStartMinuteInput, 59); });
+ eventEndHourInput.addEventListener('blur', function() { clampTimeNumberInput(eventEndHourInput, 23); });
+ eventEndMinuteInput.addEventListener('blur', function() { clampTimeNumberInput(eventEndMinuteInput, 59); });
eventLocationInput.addEventListener('input', function() {
generateQRCode();
toggleClearButton();
@@ -216,26 +245,39 @@ document.addEventListener('DOMContentLoaded', function() {
return /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}$/.test(s);
}
- function combineDateTime(dateStr, timeStr) {
- if (!dateStr || !timeStr) {
+ function combineDateTimeFromParts(dateStr, hourStr, minuteStr) {
+ if (!dateStr || hourStr === '' || minuteStr === '') {
return '';
}
if (!/^\d{4}-\d{2}-\d{2}$/.test(dateStr)) {
return '';
}
- if (!/^\d{2}:\d{2}$/.test(timeStr)) {
+ var h = parseInt(String(hourStr).trim(), 10);
+ var mi = parseInt(String(minuteStr).trim(), 10);
+ if (isNaN(h) || isNaN(mi)) {
return '';
}
- return dateStr + 'T' + timeStr;
+ if (h < 0 || h > 23 || mi < 0 || mi > 59) {
+ return '';
+ }
+ var pad = function(n) { return String(n).padStart(2, '0'); };
+ return dateStr + 'T' + pad(h) + ':' + pad(mi);
}
- function applyCombinedToDateTimeInputs(combined, dateInput, timeInput) {
+ function applyCombinedToDateTimeInputs(combined, dateInput, hourInput, minuteInput) {
if (!isValidDatetimeLocal(combined)) {
return;
}
- const parts = combined.split('T');
- dateInput.value = parts[0];
- timeInput.value = parts[1];
+ var splitT = combined.split('T');
+ var d = splitT[0];
+ var t = splitT[1];
+ var tm = /^(\d{2}):(\d{2})$/.exec(t);
+ if (!tm) {
+ return;
+ }
+ dateInput.value = d;
+ hourInput.value = String(parseInt(tm[1], 10));
+ minuteInput.value = String(parseInt(tm[2], 10));
}
// Or check for URL parameters if present
@@ -279,13 +321,13 @@ document.addEventListener('DOMContentLoaded', function() {
if (urlParams.has('eventStart')) {
const es = urlParams.get('eventStart');
if (isValidDatetimeLocal(es)) {
- applyCombinedToDateTimeInputs(es, eventStartDateInput, eventStartTimeInput);
+ applyCombinedToDateTimeInputs(es, eventStartDateInput, eventStartHourInput, eventStartMinuteInput);
}
}
if (urlParams.has('eventEnd')) {
const ee = urlParams.get('eventEnd');
if (isValidDatetimeLocal(ee)) {
- applyCombinedToDateTimeInputs(ee, eventEndDateInput, eventEndTimeInput);
+ applyCombinedToDateTimeInputs(ee, eventEndDateInput, eventEndHourInput, eventEndMinuteInput);
}
}
if (urlParams.has('eventLocation')) {
@@ -387,15 +429,26 @@ document.addEventListener('DOMContentLoaded', function() {
eventBerlinPreview.textContent = '';
return;
}
- const startRaw = combineDateTime(eventStartDateInput.value, eventStartTimeInput.value);
+ const startRaw = combineDateTimeFromParts(
+ eventStartDateInput.value,
+ eventStartHourInput.value,
+ eventStartMinuteInput.value
+ );
const endD = eventEndDateInput.value;
- const endT = eventEndTimeInput.value;
+ const endH = eventEndHourInput.value;
+ const endM = eventEndMinuteInput.value;
+ const endTimeComplete = endH !== '' && endM !== '';
+ const endTimeAny = endH !== '' || endM !== '';
let endRaw = '';
- if (endD && endT) {
- endRaw = combineDateTime(endD, endT);
- } else if (endD || endT) {
+ if (endD && endTimeComplete) {
+ endRaw = combineDateTimeFromParts(endD, endH, endM);
+ } else if (endD && !endTimeComplete) {
eventBerlinPreview.textContent =
- 'Bitte geben Sie für das Ende entweder beides (Datum und Uhrzeit, 24h) ein oder lassen Sie beides leer.';
+ 'Bitte geben Sie für das Ende Datum sowie Stunde (0–23) und Minute (0–59) an, oder lassen Sie das Ende vollständig leer.';
+ return;
+ } else if (!endD && endTimeAny) {
+ eventBerlinPreview.textContent =
+ 'Bitte geben Sie für das Ende ein Datum ein, oder entfernen Sie Stunde/Minute.';
return;
}
const sp = parseDatetimeLocalValue(startRaw);
@@ -526,9 +579,16 @@ document.addEventListener('DOMContentLoaded', function() {
if (mode === 'event') {
const title = eventTitleInput.value.trim();
- const startRaw = combineDateTime(eventStartDateInput.value, eventStartTimeInput.value);
+ const startRaw = combineDateTimeFromParts(
+ eventStartDateInput.value,
+ eventStartHourInput.value,
+ eventStartMinuteInput.value
+ );
const endD = eventEndDateInput.value;
- const endT = eventEndTimeInput.value;
+ const endH = eventEndHourInput.value;
+ const endM = eventEndMinuteInput.value;
+ const endTimeComplete = endH !== '' && endM !== '';
+ const endTimeAny = endH !== '' || endM !== '';
const loc = eventLocationInput.value;
const desc = eventDescriptionInput.value;
@@ -539,20 +599,25 @@ document.addEventListener('DOMContentLoaded', function() {
return;
}
if (!startRaw) {
- errorMessage.textContent = 'Bitte geben Sie Datum und Uhrzeit (24h) für den Beginn ein (TT/MM/JJJJ)';
+ errorMessage.textContent =
+ 'Bitte geben Sie Datum sowie Stunde (0–23) und Minute (0–59) für den Beginn ein';
qrcodeCanvas.style.display = 'none';
qrcodeImg.style.display = 'none';
return;
}
- if (endD || endT) {
- if (!endD || !endT) {
- errorMessage.textContent =
- 'Bitte geben Sie für das Ende sowohl Datum (TT/MM/JJJJ) als auch Uhrzeit (24h) an, oder lassen Sie beides leer';
- qrcodeCanvas.style.display = 'none';
- qrcodeImg.style.display = 'none';
- return;
- }
+ if (endD && !endTimeComplete) {
+ errorMessage.textContent =
+ 'Für das Ende: bitte Stunde und Minute ergänzen (0–23 / 0–59) oder Ende leer lassen';
+ qrcodeCanvas.style.display = 'none';
+ qrcodeImg.style.display = 'none';
+ return;
+ }
+ if (!endD && endTimeAny) {
+ errorMessage.textContent = 'Für das Ende bitte zuerst ein Datum wählen oder Zeitfelder leeren';
+ qrcodeCanvas.style.display = 'none';
+ qrcodeImg.style.display = 'none';
+ return;
}
const startParts = parseDatetimeLocalValue(startRaw);
@@ -566,7 +631,7 @@ document.addEventListener('DOMContentLoaded', function() {
const dtStart = wallTimeToICal(startParts);
let endParts;
- const endRaw = endD && endT ? combineDateTime(endD, endT) : '';
+ const endRaw = endD && endTimeComplete ? combineDateTimeFromParts(endD, endH, endM) : '';
if (endRaw) {
endParts = parseDatetimeLocalValue(endRaw);
if (!endParts) {
@@ -740,8 +805,16 @@ document.addEventListener('DOMContentLoaded', function() {
if (eventTitleInput.value.trim()) {
params.set('eventTitle', eventTitleInput.value.trim());
}
- const shareStart = combineDateTime(eventStartDateInput.value, eventStartTimeInput.value);
- const shareEnd = combineDateTime(eventEndDateInput.value, eventEndTimeInput.value);
+ const shareStart = combineDateTimeFromParts(
+ eventStartDateInput.value,
+ eventStartHourInput.value,
+ eventStartMinuteInput.value
+ );
+ const shareEnd = combineDateTimeFromParts(
+ eventEndDateInput.value,
+ eventEndHourInput.value,
+ eventEndMinuteInput.value
+ );
if (shareStart) {
params.set('eventStart', shareStart);
}