From 5b598e77436471cc93a8888c562ded6cd96f2b99 Mon Sep 17 00:00:00 2001
From: weeman <weeman@frankfurt.ccc.de>
Date: Mon, 23 Dec 2024 22:02:50 +0100
Subject: [PATCH] =?UTF-8?q?Setzte=20sticky=20Raumnamen=20f=C3=BCr=20den=20?=
 =?UTF-8?q?Fahrplan.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Leider klappen die aktuellen position: sticky Attribute nicht.
Deswegen jetzt eine Lösung per JavaScript.
Beim Scrollen vom Container wird `top` der Raumnamen
entsprechend der Scroll-Position nachgezogen.
---
 .../plainui/components/calendar.html.j2       | 16 ++++---
 src/plainui/jinja2/plainui/fahrplan.html.j2   |  4 ++
 .../jinja2/plainui/public_fahrplan.html.j2    |  1 +
 src/plainui/static/plainui/js/fahrplan.js     | 47 +++++++++++++++++++
 src/plainui/styles/components/_calendar.scss  |  9 +++-
 src/plainui/styles/components/_fahrplan.scss  |  1 +
 6 files changed, 69 insertions(+), 9 deletions(-)
 create mode 100644 src/plainui/static/plainui/js/fahrplan.js

diff --git a/src/plainui/jinja2/plainui/components/calendar.html.j2 b/src/plainui/jinja2/plainui/components/calendar.html.j2
index 3e52e8350..e09a5a8df 100644
--- a/src/plainui/jinja2/plainui/components/calendar.html.j2
+++ b/src/plainui/jinja2/plainui/components/calendar.html.j2
@@ -7,7 +7,7 @@
   {%- else -%}
     {% set time_steps = events.calendar_time_steps -%}
     {% set step_minutes = events.calendar_step_minutes -%}
-    <div class="hub-fahrplan">
+    <div id="hub-fahrplan-calendar" class="hub-fahrplan">
       {% for step in time_steps %}
         <hr class="hub-calendar__divider"
             style="top: {{ 56 + (loop.index0 * step_minutes * 6) }}px">
@@ -33,12 +33,14 @@
               <div class="hub-calendar__column-title-inner">{{ room.name }}</div>
             </h2>
           {% else %}
-            <a class="text-decoration-none a"
-               href="{{ url('plainui:room', slug=room.slug) }}">
-              <h2 class="hub-calendar__column-title" title="{{ room.name }}">
-                <div class="hub-calendar__column-title-inner">{{ room.name }}</div>
-              </h2>
-            </a>
+            <div class="hub-calendar__column-title">
+              <a class="text-decoration-none a"
+                 href="{{ url('plainui:room', slug=room.slug) }}">
+                <h2 title="{{ room.name }}">
+                  <div class="hub-calendar__column-title-inner">{{ room.name }}</div>
+                </h2>
+              </a>
+            </div>
           {% endif %}
           {% for entry in room_events %}
             {% if entry.type == 'space' %}
diff --git a/src/plainui/jinja2/plainui/fahrplan.html.j2 b/src/plainui/jinja2/plainui/fahrplan.html.j2
index 1e2b05bfc..79f6c5e63 100644
--- a/src/plainui/jinja2/plainui/fahrplan.html.j2
+++ b/src/plainui/jinja2/plainui/fahrplan.html.j2
@@ -4,6 +4,10 @@
 {% import "plainui/components/nav.html.j2" as navMacro with context %}
 {% import "plainui/components/tagbox.html.j2" as tagMacros with context %}
 
+{% block head %}
+  <script src="{{ static('plainui/js/fahrplan.js') }}" /></script>
+{% endblock head %}
+
 {% macro filter_button(value, active, label) -%}
   <button type="submit"
           name="set"
diff --git a/src/plainui/jinja2/plainui/public_fahrplan.html.j2 b/src/plainui/jinja2/plainui/public_fahrplan.html.j2
index 81e484660..f077861d4 100644
--- a/src/plainui/jinja2/plainui/public_fahrplan.html.j2
+++ b/src/plainui/jinja2/plainui/public_fahrplan.html.j2
@@ -22,6 +22,7 @@
                 document.querySelector('html').classList.add('js');
             });
     </script>
+    <script src="{{ static('plainui/js/fahrplan.js') }}" /></script>
   </head>
   <body class="hub-fahrplan__pub-body eyecandy">
     <div class="hub-bg-L04 hub-fahrplan__pub-content">
diff --git a/src/plainui/static/plainui/js/fahrplan.js b/src/plainui/static/plainui/js/fahrplan.js
new file mode 100644
index 000000000..ad7272a70
--- /dev/null
+++ b/src/plainui/static/plainui/js/fahrplan.js
@@ -0,0 +1,47 @@
+// No ES modules used. Wrap into a closure to avoid collisions.
+(function () {
+  // Wait until document is loaded
+  const docReady = (callback) => {
+    if (document.readyState != "loading") callback();
+    else document.addEventListener("DOMContentLoaded", callback);
+  };
+
+  // Defined in _calendar.scss
+  const scrollOffset = -5;
+
+  /**
+   * Tries to get the Fahrplan Element.
+   * This may be something different depending on whether it shows the public or regular Fahrplan view.
+   */
+  const getFahrplanElement = () => {
+    return document.querySelector(".hub-fahrplan__pub-box") ?? document.getElementById("hub-fahrplan-calendar");
+  };
+
+  docReady(() => {
+    const fahrplanElement = getFahrplanElement();
+
+    if (fahrplanElement === null) {
+      // Nothing to do, if there is no Fahrplan
+      return;
+    }
+
+    const roomNames = document.querySelectorAll(".hub-calendar__column-title");
+
+    /**
+     * When scrolling, keep room names always on top of the columns.
+     *
+     * @param {Event} event
+     */
+    const handleScroll = (event) => {
+      // Keep room names always on top of the columns
+      const scrollPosition = event.target.scrollTop;
+      const roomNameTop = `${scrollPosition + scrollOffset}px`;
+
+      roomNames.forEach((roomName) => {
+        roomName.style.top = roomNameTop;
+      });
+    };
+
+    fahrplanElement.addEventListener("scroll", handleScroll);
+  });
+})();
diff --git a/src/plainui/styles/components/_calendar.scss b/src/plainui/styles/components/_calendar.scss
index fed3ebe66..dd9cfd8cc 100644
--- a/src/plainui/styles/components/_calendar.scss
+++ b/src/plainui/styles/components/_calendar.scss
@@ -1,7 +1,13 @@
 .hub-calendar__column-title {
   height: 72px;
   margin-bottom: 0;
-  padding: map-get($spacers, 1);
+  padding: 0 map-get($spacers, 1) map-get($spacers, 1);
+  position: relative;
+  top: -5px;
+}
+
+.hub-calendar__column-title h2 {
+  font-size: 1.8rem;
 }
 
 .hub-calendar__column-title-inner {
@@ -9,7 +15,6 @@
   -webkit-box-orient: vertical;
   color: $white;
   display: -webkit-box;
-  font: $hub-head-category-font;
   overflow: hidden;
   text-align: center;
   text-overflow: ellipsis;
diff --git a/src/plainui/styles/components/_fahrplan.scss b/src/plainui/styles/components/_fahrplan.scss
index 8e06c1a60..f991cb55c 100644
--- a/src/plainui/styles/components/_fahrplan.scss
+++ b/src/plainui/styles/components/_fahrplan.scss
@@ -123,6 +123,7 @@ $public-fahrplan-body-padding: 0.7rem;
 }
 
 .hub-fahrplan__pub-box {
+  padding-top: 10px;
   max-height: 100%;
   overflow: scroll;
 }
-- 
GitLab