|
|
| Zeile 1: |
Zeile 1: |
| | |
| | <!DOCTYPE html> |
| <html lang="de"> | | <html lang="de"> |
| <head> | | <head> |
| <meta charset="UTF-8"> | | <meta charset="UTF-8" /> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | | <meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
| <title>Familienangebote August 2026</title> | | <title>Kalender - August 2026</title> |
| | <style> |
| | *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } |
|
| |
|
| <style>
| | body { |
| body{ | | font-family: 'Segoe UI', system-ui, sans-serif; |
| font-family: Arial, sans-serif;
| | background: #f0f4f8; |
| margin:20px;
| | color: #1a202c; |
| background:#f5f5f5;
| | min-height: 100vh; |
| } | | padding: 1.5rem 1rem 3rem; |
| | } |
|
| |
|
| h1{
| | header { text-align: center; margin-bottom: 1.75rem; } |
| text-align:center;
| |
| } | |
|
| |
|
| .toolbar{
| | header h1 { |
| display:flex;
| | font-size: clamp(1.5rem, 5vw, 2.25rem); |
| gap:10px;
| | font-weight: 700; |
| margin-bottom:20px;
| | letter-spacing: -0.02em; |
| justify-content:center;
| | color: #1a202c; |
| } | | } |
|
| |
|
| button{
| | header p { color: #64748b; font-size: 0.9rem; margin-top: 0.3rem; } |
| cursor:pointer;
| |
| } | |
|
| |
|
| .calendar{ | | .calendar { |
| display:grid;
| | max-width: 900px; |
| grid-template-columns:repeat(7,1fr);
| | margin: 0 auto; |
| gap:10px;
| | background: #fff; |
| }
| | border-radius: 16px; |
| | | overflow: hidden; |
| .weekday{
| | box-shadow: 0 4px 24px rgba(0,0,0,.08); |
| background:#003366;
| | } |
| color:white;
| |
| padding:10px;
| |
| text-align:center;
| |
| font-weight:bold;
| |
| }
| |
| | |
| .day{
| |
| background:white;
| |
| min-height:150px;
| |
| border-radius:8px;
| |
| padding:8px;
| |
| box-shadow:0 2px 5px rgba(0,0,0,.15);
| |
| cursor:pointer;
| |
| }
| |
| | |
| .day-number{
| |
| font-weight:bold;
| |
| margin-bottom:8px;
| |
| }
| |
| | |
| .entry{
| |
| background:#e8f2ff;
| |
| padding:4px;
| |
| margin-bottom:4px;
| |
| border-radius:4px;
| |
| font-size:12px;
| |
| }
| |
| | |
| .modal{
| |
| display:none;
| |
| position:fixed;
| |
| inset:0;
| |
| background:rgba(0,0,0,.5);
| |
| justify-content:center; | |
| align-items:center;
| |
| }
| |
| | |
| .modal-content{
| |
| background:white;
| |
| width:90%;
| |
| max-width:900px;
| |
| max-height:90vh;
| |
| overflow:auto;
| |
| padding:20px;
| |
| border-radius:10px;
| |
| }
| |
| | |
| label{
| |
| display:block;
| |
| margin-top:10px;
| |
| font-weight:bold;
| |
| }
| |
| | |
| input, textarea{
| |
| width:100%;
| |
| padding:8px;
| |
| box-sizing:border-box;
| |
| }
| |
| | |
| .entry-card{
| |
| border:1px solid #ccc;
| |
| padding:10px;
| |
| margin:10px 0;
| |
| border-radius:6px;
| |
| }
| |
| | |
| .actions{
| |
| display:flex;
| |
| gap:10px;
| |
| margin-top:10px;
| |
| } | |
| | |
| .close-btn{
| |
| float:right;
| |
| }
| |
| | |
| .empty{
| |
| background:transparent;
| |
| }
| |
| </style>
| |
| </head>
| |
| <body>
| |
| | |
| <h1>Familienangebote – August 2026</h1>
| |
| | |
| <div class="toolbar">
| |
|
| |
| </div>
| |
| | |
| <div class="calendar" id="calendar"></div>
| |
| | |
| <div class="modal" id="modal">
| |
| <div class="modal-content">
| |
| | |
| <button class="close-btn" onclick="closeModal()">Schließen</button>
| |
| | |
| <h2 id="modalDate"></h2>
| |
| | |
| <button onclick="addEntry()">+ Neuer Eintrag</button>
| |
| | |
| <div id="entriesContainer"></div>
| |
| | |
| </div>
| |
| </div>
| |
| | |
| <script>
| |
|
| |
|
| let data = {
| | .weekdays { |
| "1": [
| | display: grid; |
| { | | grid-template-columns: repeat(7, 1fr); |
| angebot: "Bächlewanderung mit Kind und Kescher", | | background: #1e3a5f; |
| uhrzeit: "10:00 - 13:00", | | color: #fff; |
| ort: "Start und Treffpunkt ist am Parkplatz Bebenhausen.",
| |
| zielgruppe: "Geeignet für Familien mit Kindern ab 5 Jahren",
| |
| anmeldung: "wird benötigt",
| |
| link: "https://www.fbs-tuebingen.de/eltern-und-kinder/kw/bereich/kursdetails/kurs/261-2516B/kursname/Baechlewanderung%20mit%20Kind%20und%20Kescher/kategorie-id/11/", | |
| beschreibung: "Wir wandern am Goldersbach entlang über die Tellerbrücke zur Teufelsbrücke." | |
| } | | } |
| ],
| |
|
| |
|
| "2": [
| | .weekdays span { |
| { | | text-align: center; |
| angebot: "Eiscafé frieDa", | | padding: 0.65rem 0; |
| uhrzeit: "14:00-17:00", | | font-size: 0.75rem; |
| ort: "Café frieDa, Friedrich-Dannenmann-Straße 69, 72070 Tübingen", | | font-weight: 600; |
| zielgruppe: "Familien, Nachbarn, Menschen mit und ohne Behinderung",
| | letter-spacing: 0.06em; |
| anmeldung: "",
| | text-transform: uppercase; |
| link: "https://www.lebenshilfe-tuebingen.de/service/termine/",
| |
| beschreibung: "Das Eiscafé frieDa ist ein Begegnungs-Ort." | |
| },
| |
| {
| |
| angebot: "Geschwisterchen auf dem Weg",
| |
| uhrzeit: "10:00 - 12:00", | |
| ort: "FBS, Raum 003 Villa Metz, Hechingerstraße 13",
| |
| zielgruppe: "Für Kinder ab 4 Jahren mit einem Elternteil", | |
| anmeldung: "wird benötigt",
| |
| link: "https://www.fbs-tuebingen.de/programm/kw/bereich/kursdetails/kurs/261-2509/kursname/Geschwisterchen%20auf%20dem%20Weg/",
| |
| beschreibung: "Vorbereitung auf ein Geschwisterchen."
| |
| } | | } |
| ],
| |
|
| |
|
| "4": [
| | .days { |
| { | | display: grid; |
| angebot: "BabyBrunch", | | grid-template-columns: repeat(7, 1fr); |
| uhrzeit: "09:30-11:30", | | border-left: 1px solid #e2e8f0; |
| ort: "elkiko Familienzentrum", | | border-top: 1px solid #e2e8f0; |
| zielgruppe: "Eltern mit Säuglingen und Kleinkindern", | |
| anmeldung: "babybrunch@elkiko.de",
| |
| link: "https://www.elkiko.de/content2/index.php/de/programm/babybrunch-brunch1plus.html",
| |
| beschreibung: ""
| |
| } | | } |
| ],
| |
|
| |
|
| "5": [
| | .day { |
| { | | min-height: 90px; |
| angebot: "Spielplatztreff", | | padding: 0.45rem; |
| uhrzeit: "14:30-15:30", | | border-right: 1px solid #e2e8f0; |
| ort: "Piratenspielplatz, Anlagenpark", | | border-bottom: 1px solid #e2e8f0; |
| zielgruppe: "Familien mit jüngeren Kindern", | | background: #fff; |
| anmeldung: "-", | | display: flex; |
| link: "", | | flex-direction: column; |
| beschreibung: "Treffpunkt zum Austausch mit der Familienbeauftragten." | | gap: 0.3rem; |
| } | | } |
| ],
| |
|
| |
| "6": [
| |
| {
| |
| angebot: "BabyBrunch",
| |
| uhrzeit: "09:30-11:30",
| |
| ort: "elkiko Familienzentrum",
| |
| zielgruppe: "Eltern mit Säuglingen und Kleinkindern",
| |
| anmeldung: "babybrunch@elkiko.de",
| |
| link: "https://www.elkiko.de/content2/index.php/de/programm/babybrunch-brunch1plus.html",
| |
| beschreibung:
| |
| },
| |
| {
| |
| angebot: "Sommerferien mit dem LESE-HAUS",
| |
| uhrzeit: "11:00"
| |
| ort: Alter Botanischer Garten, Wiese neben dem Kinderspielplatz, bei schlechtem Wetter: Thekla-Waitz-Studio, im EG der Stadtbücherei, Nonnengasse 19, 72070 Tübingen",
| |
| zielgruppe: "Kinder von 4 - 8 Jahre mit Begleitpersonen",
| |
| link: "https://tuebingen.ferienprogramm-online.de/"
| |
| beschreibung: ""Vorlesestunde zum Thema „Unsere Welt ist bunt“ mit allerlei Geschichten, vorgelesen von Lesepatinnen und Lesepaten des LESE-HAUSes sowie Mitarbeitenden der Stadtbücherei.
| |
| Bei schönem Wetter findet die Veranstaltung immer donnerstags im Alten Botanischen Garten an einem schattigen Plätzchen statt. Bei schlechtem Wetter treffen wir uns im Thekla-Waitz-Studio im Erdgeschoss der Stadtbücherei."
| |
|
| |
|
| |
|
| | .day.empty { background: #f8fafc; } |
|
| |
|
| | .day.today .day-number { |
| | background: #1e3a5f; |
| | color: #fff; |
| | border-radius: 50%; |
| | width: 26px; |
| | height: 26px; |
| | display: flex; |
| | align-items: center; |
| | justify-content: center; |
| | } |
|
| |
|
| | .day-number { |
| | font-size: 0.8rem; |
| | font-weight: 600; |
| | color: #475569; |
| | line-height: 1; |
| | margin-bottom: 0.1rem; |
| } | | } |
| ],
| |
|
| |
|
| "9": [
| | .event-chip { |
| { | | background: #dbeafe; |
| angebot: "Eiscafé frieDa",
| | border-left: 3px solid #2563eb; |
| uhrzeit: "14:00-17:00", | | border-radius: 4px; |
| ort: "Café frieDa, Friedrich-Dannenmann-Straße 69, 72070 Tübingen", | | padding: 0.2rem 0.35rem; |
| zielgruppe: "Familien, Nachbarn, Menschen mit und ohne Behinderung", | | font-size: 0.7rem; |
| anmeldung: "", | | line-height: 1.3; |
| link: "https://www.lebenshilfe-tuebingen.de/service/termine/", | | cursor: pointer; |
| beschreibung: "Das Eiscafé frieDa ist ein Begegnungs-Ort." | | transition: background 0.15s, transform 0.1s; |
| | word-break: break-word; |
| } | | } |
| ],
| |
|
| |
|
| "11": [
| | .event-chip:hover { background: #bfdbfe; transform: translateY(-1px); } |
| { | |
| angebot: "BabyBrunch",
| |
| uhrzeit: "09:30-11:30",
| |
| ort: "elkiko Familienzentrum",
| |
| zielgruppe: "Eltern mit Säuglingen und Kleinkindern",
| |
| anmeldung: "babybrunch@elkiko.de",
| |
| link: "https://www.elkiko.de/content2/index.php/de/programm/babybrunch-brunch1plus.html",
| |
| beschreibung: ""
| |
| }
| |
| ],
| |
|
| |
|
| "12": [
| | .event-chip .chip-time { |
| { | | font-weight: 700; |
| angebot: "Spielplatztreff", | | color: #1d4ed8; |
| uhrzeit: "14:30-15:30" | | display: block; |
| } | | } |
| ],
| |
|
| |
|
| "13": [
| | .event-chip .chip-title { |
| { | | color: #1e3a5f; |
| angebot: "BabyBrunch", | | display: block; |
| uhrzeit: "09:30-11:30",
| | white-space: nowrap; |
| ort: "elkiko Familienzentrum",
| | overflow: hidden; |
| zielgruppe: "Eltern mit Säuglingen und Kleinkindern", | | text-overflow: ellipsis; |
| anmeldung: "babybrunch@elkiko.de", | |
| link: "https://www.elkiko.de/content2/index.php/de/programm/babybrunch-brunch1plus.html",
| |
| beschreibung: ""
| |
| },
| |
| {
| |
| angebot: "Sommerferien mit dem LESE-HAUS", | |
| uhrzeit: "11:00" | |
| ort: Alter Botanischer Garten, Wiese neben dem Kinderspielplatz, bei schlechtem Wetter: Thekla-Waitz-Studio, im EG der Stadtbücherei, Nonnengasse 19, 72070 Tübingen",
| |
| zielgruppe: "Kinder von 4 - 8 Jahre mit Begleitpersonen",
| |
| link: "https://tuebingen.ferienprogramm-online.de/"
| |
| beschreibung: ""Vorlesestunde zum Thema „Unsere Welt ist bunt“ mit allerlei Geschichten, vorgelesen von Lesepatinnen und Lesepaten des LESE-HAUSes sowie Mitarbeitenden der Stadtbücherei.
| |
| Bei schönem Wetter findet die Veranstaltung immer donnerstags im Alten Botanischen Garten an einem schattigen Plätzchen statt. Bei schlechtem Wetter treffen wir uns im Thekla-Waitz-Studio im Erdgeschoss der Stadtbücherei."
| |
| } | | } |
| ],
| |
|
| |
|
| "16": [
| | .modal-overlay { |
| { | | display: none; |
| angebot: "Eiscafé frieDa",
| | position: fixed; |
| uhrzeit: "14:00-17:00", | | inset: 0; |
| ort: "Café frieDa, Friedrich-Dannenmann-Straße 69, 72070 Tübingen", | | background: rgba(15, 23, 42, 0.55); |
| zielgruppe: "Familien, Nachbarn, Menschen mit und ohne Behinderung", | | z-index: 100; |
| anmeldung: "", | | align-items: center; |
| link: "https://www.lebenshilfe-tuebingen.de/service/termine/", | | justify-content: center; |
| beschreibung: "Das Eiscafé frieDa ist ein Begegnungs-Ort." | | padding: 1rem; |
| },
| |
| {
| |
| angebot: "Bunt backen mit Kindern: Regenbogen-Muffins & Cake-Pops",
| |
| uhrzeit: "16:00 - 18:30" | |
| } | | } |
| ],
| |
|
| |
|
| "18": [
| | .modal-overlay.open { display: flex; } |
| { | |
| angebot: "BabyBrunch",
| |
| uhrzeit: "09:30-11:30",
| |
| ort: "elkiko Familienzentrum",
| |
| zielgruppe: "Eltern mit Säuglingen und Kleinkindern",
| |
| anmeldung: "babybrunch@elkiko.de",
| |
| link: "https://www.elkiko.de/content2/index.php/de/programm/babybrunch-brunch1plus.html",
| |
| beschreibung: ""
| |
| }
| |
| ],
| |
|
| |
|
| "19": [
| | .modal { |
| {
| | background: #fff; |
| angebot: "Spielplatztreff", | | border-radius: 16px; |
| uhrzeit: "14:30-15:30" | | max-width: 480px; |
| | width: 100%; |
| | padding: 2rem; |
| | position: relative; |
| | box-shadow: 0 20px 60px rgba(0,0,0,.2); |
| | animation: pop .18s ease-out; |
| } | | } |
| ],
| |
|
| |
|
| "20": [
| | @keyframes pop { |
| { | | from { opacity: 0; transform: scale(.94); } |
| angebot: "BabyBrunch",
| | to { opacity: 1; transform: scale(1); } |
| uhrzeit: "09:30-11:30", | |
| ort: "elkiko Familienzentrum",
| |
| zielgruppe: "Eltern mit Säuglingen und Kleinkindern",
| |
| anmeldung: "babybrunch@elkiko.de",
| |
| link: "https://www.elkiko.de/content2/index.php/de/programm/babybrunch-brunch1plus.html", | |
| beschreibung: ""
| |
| },
| |
| {
| |
| angebot: "Sommerferien mit dem LESE-HAUS",
| |
| uhrzeit: "11:00"
| |
| ort: Alter Botanischer Garten, Wiese neben dem Kinderspielplatz, bei schlechtem Wetter: Thekla-Waitz-Studio, im EG der Stadtbücherei, Nonnengasse 19, 72070 Tübingen",
| |
| zielgruppe: "Kinder von 4 - 8 Jahre mit Begleitpersonen",
| |
| link: "https://tuebingen.ferienprogramm-online.de/"
| |
| beschreibung: ""Vorlesestunde zum Thema „Unsere Welt ist bunt“ mit allerlei Geschichten, vorgelesen von Lesepatinnen und Lesepaten des LESE-HAUSes sowie Mitarbeitenden der Stadtbücherei.
| |
| Bei schönem Wetter findet die Veranstaltung immer donnerstags im Alten Botanischen Garten an einem schattigen Plätzchen statt. Bei schlechtem Wetter treffen wir uns im Thekla-Waitz-Studio im Erdgeschoss der Stadtbücherei."
| |
| } | | } |
| ],
| |
|
| |
|
| "23": [
| | .modal-close { |
| {
| | position: absolute; |
| angebot: "Eiscafé frieDa",
| | top: 1rem; |
| uhrzeit: "14:00-17:00", | | right: 1rem; |
| ort: "Café frieDa, Friedrich-Dannenmann-Straße 69, 72070 Tübingen", | | background: #f1f5f9; |
| zielgruppe: "Familien, Nachbarn, Menschen mit und ohne Behinderung", | | border: none; |
| anmeldung: "", | | border-radius: 50%; |
| link: "https://www.lebenshilfe-tuebingen.de/service/termine/", | | width: 32px; |
| beschreibung: "Das Eiscafé frieDa ist ein Begegnungs-Ort." | | height: 32px; |
| | cursor: pointer; |
| | font-size: 1rem; |
| | display: flex; |
| | align-items: center; |
| | justify-content: center; |
| | color: #64748b; |
| | transition: background .15s; |
| } | | } |
| ],
| |
|
| |
|
| "25": [
| | .modal-close:hover { background: #e2e8f0; } |
| { | |
| angebot: "BabyBrunch",
| |
| uhrzeit: "09:30-11:30",
| |
| ort: "elkiko Familienzentrum",
| |
| zielgruppe: "Eltern mit Säuglingen und Kleinkindern",
| |
| anmeldung: "babybrunch@elkiko.de",
| |
| link: "https://www.elkiko.de/content2/index.php/de/programm/babybrunch-brunch1plus.html",
| |
| beschreibung: ""
| |
| }
| |
| ],
| |
|
| |
|
| "26": [
| | .modal-date { |
| {
| | font-size: 0.8rem; |
| angebot: "Spielplatztreff", | | font-weight: 600; |
| uhrzeit: "14:30-15:30" | | letter-spacing: 0.05em; |
| | text-transform: uppercase; |
| | color: #2563eb; |
| | margin-bottom: 0.4rem; |
| } | | } |
| ],
| |
|
| |
|
| "27": [
| | .modal-title { |
| { | | font-size: 1.3rem; |
| angebot: "BabyBrunch", | | font-weight: 700; |
| uhrzeit: "09:30-11:30",
| | color: #1a202c; |
| ort: "elkiko Familienzentrum",
| | margin-bottom: 0.6rem; |
| zielgruppe: "Eltern mit Säuglingen und Kleinkindern",
| | line-height: 1.3; |
| anmeldung: "babybrunch@elkiko.de",
| |
| link: "https://www.elkiko.de/content2/index.php/de/programm/babybrunch-brunch1plus.html", | |
| beschreibung: ""
| |
| },
| |
| {
| |
| angebot: "Sommerferien mit dem LESE-HAUS", | |
| uhrzeit: "11:00" | |
| ort: Alter Botanischer Garten, Wiese neben dem Kinderspielplatz, bei schlechtem Wetter: Thekla-Waitz-Studio, im EG der Stadtbücherei, Nonnengasse 19, 72070 Tübingen",
| |
| zielgruppe: "Kinder von 4 - 8 Jahre mit Begleitpersonen",
| |
| link: "https://tuebingen.ferienprogramm-online.de/"
| |
| beschreibung: ""Vorlesestunde zum Thema „Unsere Welt ist bunt“ mit allerlei Geschichten, vorgelesen von Lesepatinnen und Lesepaten des LESE-HAUSes sowie Mitarbeitenden der Stadtbücherei.
| |
| Bei schönem Wetter findet die Veranstaltung immer donnerstags im Alten Botanischen Garten an einem schattigen Plätzchen statt. Bei schlechtem Wetter treffen wir uns im Thekla-Waitz-Studio im Erdgeschoss der Stadtbücherei."
| |
| } | | } |
| ],
| |
|
| |
|
| "30": [
| | .modal-time { |
| { | | display: inline-flex; |
| angebot: "Eiscafé frieDa",
| | align-items: center; |
| uhrzeit: "14:00-17:00", | | gap: 0.4rem; |
| ort: "Café frieDa, Friedrich-Dannenmann-Straße 69, 72070 Tübingen", | | background: #f0f9ff; |
| zielgruppe: "Familien, Nachbarn, Menschen mit und ohne Behinderung", | | color: #0369a1; |
| anmeldung: "", | | border-radius: 6px; |
| link: "https://www.lebenshilfe-tuebingen.de/service/termine/", | | padding: 0.3rem 0.7rem; |
| beschreibung: "Das Eiscafé frieDa ist ein Begegnungs-Ort." | | font-size: 0.85rem; |
| | font-weight: 600; |
| | margin-bottom: 1rem; |
| } | | } |
| ]
| |
| };
| |
|
| |
|
| |
| let selectedDay = null;
| |
|
| |
| const weekdays = ["Mo","Di","Mi","Do","Fr","Sa","So"];
| |
|
| |
| function saveData(){
| |
| renderCalendar();
| |
| }
| |
|
| |
| function renderCalendar(){
| |
|
| |
| const cal = document.getElementById("calendar");
| |
| cal.innerHTML = "";
| |
|
| |
| weekdays.forEach(day=>{
| |
| const div = document.createElement("div");
| |
| div.className = "weekday";
| |
| div.textContent = day;
| |
| cal.appendChild(div);
| |
| });
| |
|
| |
| const firstDay = new Date(2026,7,1);
| |
|
| |
| let offset = firstDay.getDay();
| |
| offset = offset === 0 ? 6 : offset - 1;
| |
|
| |
|
| for(let i=0;i<offset;i++){ | | .modal-note { |
| const empty = document.createElement("div");
| | font-size: 0.9rem; |
| empty.className = "empty";
| | color: #475569; |
| cal.appendChild(empty);
| | line-height: 1.6; |
| | margin-bottom: 1.2rem; |
| } | | } |
|
| |
|
| for(let day=1; day<=31; day++){ | | .modal-link { |
| | | display: inline-flex; |
| const div = document.createElement("div");
| | align-items: center; |
| div.className = "day";
| | gap: 0.4rem; |
| | | background: #1e3a5f; |
| div.onclick = () => openDay(day);
| | color: #fff; |
| | | text-decoration: none; |
| const dayNumber = document.createElement("div");
| | border-radius: 8px; |
| dayNumber.className = "day-number";
| | padding: 0.55rem 1.1rem; |
| dayNumber.textContent = day;
| | font-size: 0.85rem; |
| | | font-weight: 600; |
| div.appendChild(dayNumber);
| | transition: background .15s; |
| | |
| const entries = data[day] || [];
| |
| | |
| entries.forEach(entry=>{
| |
| const e = document.createElement("div");
| |
| e.className = "entry";
| |
| e.textContent = entry.angebot || "(ohne Titel)";
| |
| div.appendChild(e);
| |
| });
| |
| | |
| cal.appendChild(div);
| |
| } | | } |
| }
| |
|
| |
| function openDay(day){
| |
|
| |
| selectedDay = day;
| |
|
| |
| document.getElementById("modal").style.display="flex";
| |
| document.getElementById("modalDate").textContent =
| |
| `Samstag, ${day}. August 2026`.replace("Samstag", new Date(2026,7,day)
| |
| .toLocaleDateString("de-DE",{weekday:"long"}));
| |
|
| |
| renderEntries();
| |
| }
| |
|
| |
| function closeModal(){
| |
| document.getElementById("modal").style.display="none";
| |
| }
| |
|
| |
| function renderEntries(){
| |
|
| |
|
| const container = document.getElementById("entriesContainer"); | | .modal-link:hover { background: #2563eb; } |
| container.innerHTML = "";
| |
|
| |
|
| if(!data[selectedDay]){ | | @media (max-width: 600px) { |
| data[selectedDay] = [];
| | .weekdays span { font-size: 0.62rem; } |
| | .day { min-height: 60px; padding: 0.3rem; } |
| | .event-chip { font-size: 0.62rem; padding: 0.15rem 0.25rem; } |
| | .event-chip .chip-title { display: none; } |
| } | | } |
| | </style> |
| | </head> |
| | <body> |
|
| |
|
| data[selectedDay].forEach((entry,index)=>{
| | <header> |
| | <h1>August 2026</h1> |
| | <p>Klick auf einen Termin fur mehr Details</p> |
| | </header> |
|
| |
|
| const card = document.createElement("div");
| | <div class="calendar"> |
| card.className = "entry-card";
| | <div class="weekdays"> |
| | | <span>Mo</span><span>Di</span><span>Mi</span><span>Do</span><span>Fr</span><span>Sa</span><span>So</span> |
| card.innerHTML = `
| | </div> |
| <label>Angebot</label>
| | <div class="days" id="calGrid"></div> |
| <input value="${entry.angebot || ''}" onchange="updateField(${index},'angebot',this.value)">
| | </div> |
| | |
| <label>Uhrzeit</label>
| |
| <input value="${entry.uhrzeit || ''}" onchange="updateField(${index},'uhrzeit',this.value)">
| |
|
| |
|
| <label>Treffpunkt/Ort</label>
| | <div class="modal-overlay" id="modalOverlay" role="dialog" aria-modal="true"> |
| <input value="${entry.ort || ''}" onchange="updateField(${index},'ort',this.value)">
| | <div class="modal"> |
| | | <button class="modal-close" id="modalClose" aria-label="Schliessen">✕</button> |
| <label>Zielgruppe</label>
| | <div class="modal-date" id="mDate"></div> |
| <input value="${entry.zielgruppe || ''}" onchange="updateField(${index},'zielgruppe',this.value)">
| | <div class="modal-title" id="mTitle"></div> |
| | | <div class="modal-time">🕐 <span id="mTimeText"></span></div> |
| <label>Anmeldung</label>
| | <div class="modal-note" id="mNote"></div> |
| <input value="${entry.anmeldung || ''}" onchange="updateField(${index},'anmeldung',this.value)">
| | <a class="modal-link" id="mLink" href="#" target="_blank" rel="noopener"> |
| | | 🔗 Mehr Infos |
| <label>Link zum Angebot</label>
| | </a> |
| <input value="${entry.link || ''}" onchange="updateField(${index},'link',this.value)">
| | </div> |
| | |
| <label>Beschreibung</label>
| |
| <textarea rows="4" onchange="updateField(${index},'beschreibung',this.value)">${entry.beschreibung || ''}</textarea>
| |
| | |
| <div class="actions">
| |
| <button onclick="copyEntryToDate(${index})">
| |
| Auf anderes Datum kopieren
| |
| </button> | |
| | |
| <button onclick="deleteEntry(${index})">
| |
| Löschen
| |
| </button>
| |
| </div> | | </div> |
| `;
| |
|
| |
|
| container.appendChild(card);
| | <script> |
| }); | | // ================================================== |
| }
| | // TERMINE - hier pflegen |
| function copyEntryToDate(index){
| | // ================================================== |
| | | var events = [ |
| const targetDay = prompt(
| | { |
| "Auf welchen Tag im August kopieren? (1-31)"
| | datum: "2026-08-05", |
| ); | | titel: "Stadtfest Reutlingen", |
| | | uhrzeit: "14:00", |
| if(!targetDay) return; | | zusatztext: "Das jaehrliche Stadtfest in der Innenstadt mit Live-Musik, Essen und Marktstaenden. Parkplaetze sind begrenzt - Anreise mit OPNV empfohlen.", |
| | | url: "https://www.reutlingen.de" |
| const day = parseInt(targetDay);
| | }, |
| | | { |
| if(day < 1 || day > 31){
| | datum: "2026-08-12", |
| alert("Ungültiger Tag.");
| | titel: "Team-Meeting Q3", |
| return;
| | uhrzeit: "09:30", |
| | zusatztext: "Quartals-Review mit allen Abteilungen. Bitte Berichte bis 08.08. einreichen. Video-Call-Link wird separat verschickt.", |
| | url: "https://meet.example.com/q3-review" |
| | }, |
| | { |
| | datum: "2026-08-22", |
| | titel: "Open-Air Kino", |
| | uhrzeit: "21:00", |
| | zusatztext: "Filmabend im Stadtpark - gezeigt wird Cinema Paradiso (1988). Einlass ab 20:00 Uhr, Decke und Sitzkissen empfohlen. Eintritt frei.", |
| | url: "https://www.openair-kino-beispiel.de" |
| } | | } |
| | ]; |
| | // ================================================== |
|
| |
|
| if(!data[day]){ | | var byDate = {}; |
| data[day] = [];
| | events.forEach(function(e) { |
| } | | if (!byDate[e.datum]) byDate[e.datum] = []; |
| | byDate[e.datum].push(e); |
| | }); |
|
| |
|
| const copy = JSON.parse(
| | var grid = document.getElementById('calGrid'); |
| JSON.stringify(data[selectedDay][index])
| | var year = 2026; |
| );
| | var month = 7; |
| | var firstDay = new Date(year, month, 1).getDay(); |
| | var offset = (firstDay + 6) % 7; |
| | var daysInMonth = new Date(year, month + 1, 0).getDate(); |
| | var today = new Date(); |
|
| |
|
| data[day].push(copy); | | for (var i = 0; i < offset; i++) { |
| | var empty = document.createElement('div'); |
| | empty.className = 'day empty'; |
| | grid.appendChild(empty); |
| | } |
|
| |
|
| saveData(); | | for (var d = 1; d <= daysInMonth; d++) { |
| | var cell = document.createElement('div'); |
| | cell.className = 'day'; |
|
| |
|
| alert( | | var isToday = today.getFullYear() === year |
| "Termin wurde auf den "
| | && today.getMonth() === month |
| + day +
| | && today.getDate() === d; |
| ". August kopiert."
| | if (isToday) cell.classList.add('today'); |
| ); | |
| }
| |
| function addEntry(){
| |
|
| |
|
| data[selectedDay].push({ | | var num = document.createElement('div'); |
| angebot:"",
| | num.className = 'day-number'; |
| uhrzeit:"",
| | num.textContent = d; |
| ort:"",
| | cell.appendChild(num); |
| zielgruppe:"",
| |
| anmeldung:"",
| |
| link:"",
| |
| beschreibung:""
| |
| }); | |
|
| |
|
| saveData(); | | var mm = String(month + 1).padStart(2, '0'); |
| renderEntries(); | | var dd = String(d).padStart(2, '0'); |
| }
| | var dateKey = year + '-' + mm + '-' + dd; |
|
| |
|
| function updateField(index, field, value){ | | if (byDate[dateKey]) { |
| | byDate[dateKey].forEach(function(ev) { |
| | var chip = document.createElement('div'); |
| | chip.className = 'event-chip'; |
|
| |
|
| data[selectedDay][index][field] = value;
| | var timeSpan = document.createElement('span'); |
| | timeSpan.className = 'chip-time'; |
| | timeSpan.textContent = ev.uhrzeit; |
|
| |
|
| saveData();
| | var titleSpan = document.createElement('span'); |
| }
| | titleSpan.className = 'chip-title'; |
| | titleSpan.textContent = ev.titel; |
|
| |
|
| function deleteEntry(index){
| | chip.appendChild(timeSpan); |
| | chip.appendChild(titleSpan); |
|
| |
|
| if(confirm("Eintrag löschen?")){
| | chip.addEventListener('click', (function(evData) { |
| | return function() { openModal(evData); }; |
| | })(ev)); |
|
| |
|
| data[selectedDay].splice(index,1); | | cell.appendChild(chip); |
| | | }); |
| saveData();
| |
| renderEntries();
| |
| } | | } |
| }
| |
|
| |
|
| function copyEntry(index){
| | grid.appendChild(cell); |
| | } |
|
| |
|
| const copy = JSON.parse(
| | var overlay = document.getElementById('modalOverlay'); |
| JSON.stringify(data[selectedDay][index])
| | var btnClose = document.getElementById('modalClose'); |
| );
| |
|
| |
|
| data[selectedDay].push(copy);
| | function openModal(ev) { |
| | | var d = new Date(ev.datum + 'T00:00:00'); |
| saveData(); | | document.getElementById('mDate').textContent = |
| renderEntries(); | | d.toLocaleDateString('de-DE', { weekday: 'long', day: 'numeric', month: 'long', year: 'numeric' }); |
| }
| | document.getElementById('mTitle').textContent = ev.titel; |
| | | document.getElementById('mTimeText').textContent = ev.uhrzeit + ' Uhr'; |
| function exportData(){
| | document.getElementById('mNote').textContent = ev.zusatztext; |
| | | var link = document.getElementById('mLink'); |
| const blob = new Blob(
| | if (ev.url) { |
| [JSON.stringify(data,null,2)],
| | link.href = ev.url; |
| {type:"application/json"}
| | link.style.display = 'inline-flex'; |
| ); | | } else { |
| | | link.style.display = 'none'; |
| const a = document.createElement("a"); | | } |
| a.href = URL.createObjectURL(blob); | | overlay.classList.add('open'); |
| a.download = "familienangebote_august_2026.json"; | | } |
| a.click(); | |
| } | |
| | |
| function importData(event){
| |
|
| |
|
| const file = event.target.files[0];
| | function closeModal() { overlay.classList.remove('open'); } |
| if(!file) return;
| |
| | |
| const reader = new FileReader();
| |
| | |
| reader.onload = e => {
| |
| | |
| data = JSON.parse(e.target.result);
| |
| | |
| saveData();
| |
| | |
| alert("Import erfolgreich.");
| |
| };
| |
| | |
| reader.readAsText(file);
| |
| } | |
| | |
| renderCalendar();
| |
|
| |
|
| | btnClose.addEventListener('click', closeModal); |
| | overlay.addEventListener('click', function(e) { if (e.target === overlay) closeModal(); }); |
| | document.addEventListener('keydown', function(e) { if (e.key === 'Escape') closeModal(); }); |
| </script> | | </script> |
|
| |
| </body> | | </body> |
| </html> | | </html> |