mirror of
				https://github.com/kevinveenbirkenbach/homepage.veen.world.git
				synced 2025-11-04 09:27:58 +00:00 
			
		
		
		
	Replaced German by English comments
This commit is contained in:
		
							
								
								
									
										12
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								Dockerfile
									
									
									
									
									
								
							@@ -1,18 +1,18 @@
 | 
				
			|||||||
# Basis-Image für Python
 | 
					# Base image for Python
 | 
				
			||||||
FROM python:slim
 | 
					FROM python:slim
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Arbeitsverzeichnis festlegen
 | 
					# Set the working directory
 | 
				
			||||||
WORKDIR /app
 | 
					WORKDIR /app
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Abhängigkeiten kopieren und installieren
 | 
					# Copy and install dependencies
 | 
				
			||||||
COPY app/requirements.txt requirements.txt
 | 
					COPY app/requirements.txt requirements.txt
 | 
				
			||||||
RUN pip install --no-cache-dir -r requirements.txt
 | 
					RUN pip install --no-cache-dir -r requirements.txt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Anwendungscode kopieren
 | 
					# Copy application code
 | 
				
			||||||
COPY app/ .
 | 
					COPY app/ .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Port freigeben
 | 
					# Expose port
 | 
				
			||||||
EXPOSE 5000
 | 
					EXPOSE 5000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Startbefehl
 | 
					# Start command
 | 
				
			||||||
CMD ["python", "app.py"]
 | 
					CMD ["python", "app.py"]
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,7 +15,6 @@ cache_manager.clear_cache()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def load_config(app):
 | 
					def load_config(app):
 | 
				
			||||||
    """Load and resolve the configuration."""
 | 
					    """Load and resolve the configuration."""
 | 
				
			||||||
    # Lade die Konfigurationsdatei
 | 
					 | 
				
			||||||
    with open("config.yaml", "r") as f:
 | 
					    with open("config.yaml", "r") as f:
 | 
				
			||||||
        config = yaml.safe_load(f)
 | 
					        config = yaml.safe_load(f)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -28,7 +27,7 @@ def load_config(app):
 | 
				
			|||||||
app = Flask(__name__)
 | 
					app = Flask(__name__)
 | 
				
			||||||
load_config(app)
 | 
					load_config(app)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Hole die Umgebungsvariable FLASK_ENV oder setze einen Standardwert
 | 
					# Get the environment variable FLASK_ENV or set a default value
 | 
				
			||||||
FLASK_ENV = os.getenv("FLASK_ENV", "production")
 | 
					FLASK_ENV = os.getenv("FLASK_ENV", "production")
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
@app.before_request
 | 
					@app.before_request
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,10 +1,11 @@
 | 
				
			|||||||
/* Den scroll-container so einstellen, dass er nur vertikal scrollt */
 | 
					/* Set the scroll container to only scroll vertically */
 | 
				
			||||||
.scroll-container {
 | 
					.scroll-container {
 | 
				
			||||||
    overflow-y: auto;
 | 
					    overflow-y: auto;
 | 
				
			||||||
    overflow-x: hidden;
 | 
					    overflow-x: hidden;
 | 
				
			||||||
    /* Native Scrollbar ausblenden */
 | 
					    /* Hide native scrollbar */
 | 
				
			||||||
    scrollbar-width: none; /* Firefox */
 | 
					    scrollbar-width: none; /* Firefox */
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.scroll-container::-webkit-scrollbar {
 | 
					.scroll-container::-webkit-scrollbar {
 | 
				
			||||||
    display: none; /* WebKit */
 | 
					    display: none; /* WebKit */
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -14,13 +15,13 @@
 | 
				
			|||||||
    top: 0;
 | 
					    top: 0;
 | 
				
			||||||
    right: 0;
 | 
					    right: 0;
 | 
				
			||||||
    width: 8px;
 | 
					    width: 8px;
 | 
				
			||||||
    /* height: 100vh;  <-- diese Zeile entfernen oder anpassen */
 | 
					    /* height: 100vh;  <-- remove or adjust this line */
 | 
				
			||||||
    background: transparent;
 | 
					    background: transparent;
 | 
				
			||||||
    transition: opacity 0.3s ease;
 | 
					    transition: opacity 0.3s ease;
 | 
				
			||||||
    opacity: 1;
 | 
					    opacity: 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Der Thumb der Scrollbar */
 | 
					/* The scrollbar thumb */
 | 
				
			||||||
#scroll-thumb {
 | 
					#scroll-thumb {
 | 
				
			||||||
    position: absolute;
 | 
					    position: absolute;
 | 
				
			||||||
    top: 0;
 | 
					    top: 0;
 | 
				
			||||||
@@ -28,4 +29,3 @@
 | 
				
			|||||||
    background-color: rgba(0, 0, 0, 0.2);
 | 
					    background-color: rgba(0, 0, 0, 0.2);
 | 
				
			||||||
    border-radius: 4px;
 | 
					    border-radius: 4px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
  
 | 
					 | 
				
			||||||
@@ -100,11 +100,11 @@ div#navbarNavfooter li.nav-item{
 | 
				
			|||||||
main {
 | 
					main {
 | 
				
			||||||
  position: relative;
 | 
					  position: relative;
 | 
				
			||||||
  box-shadow: 
 | 
					  box-shadow: 
 | 
				
			||||||
    /* Innerer Schatten */
 | 
					    /* Inner shadow */
 | 
				
			||||||
    inset 10px 0 10px -10px rgba(0, 0, 0, 0.3),  /* linker innerer Schatten */
 | 
					    inset 10px 0 10px -10px rgba(0, 0, 0, 0.3),  /* Left inner shadow */
 | 
				
			||||||
    inset -10px 0 10px -10px rgba(0, 0, 0, 0.3), /* rechter innerer Schatten */
 | 
					    inset -10px 0 10px -10px rgba(0, 0, 0, 0.3), /* Right inner shadow */
 | 
				
			||||||
    /* Äußerer Schatten */
 | 
					    /* Outer shadow */
 | 
				
			||||||
    10px 0 10px -10px rgba(0, 0, 0, 0.3),  /* rechter äußerer Schatten */
 | 
					    10px 0 10px -10px rgba(0, 0, 0, 0.3),  /* Right outer shadow */
 | 
				
			||||||
    -10px 0 10px -10px rgba(0, 0, 0, 0.3); /* linker äußerer Schatten */
 | 
					    -10px 0 10px -10px rgba(0, 0, 0, 0.3); /* Left outer shadow */
 | 
				
			||||||
  overflow: visible;
 | 
					  overflow: visible;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,20 +1,20 @@
 | 
				
			|||||||
/* Top-Level Dropdown-Menü */
 | 
					/* Top-level dropdown menu */
 | 
				
			||||||
.nav-item .dropdown-menu {
 | 
					.nav-item .dropdown-menu {
 | 
				
			||||||
    position: absolute; /* Wichtig für Positionierung */
 | 
					    position: absolute; /* Important for positioning */
 | 
				
			||||||
    top: 100%; /* Standardmäßige Öffnung nach unten */
 | 
					    top: 100%; /* Default opening direction: downwards */
 | 
				
			||||||
    left: 0;
 | 
					    left: 0;
 | 
				
			||||||
    z-index: 1050; /* Damit das Menü über anderen Elementen liegt */
 | 
					    z-index: 1050; /* Ensures the menu appears above other elements */
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Submenu-Position */
 | 
					/* Submenu position */
 | 
				
			||||||
.dropdown-submenu > .dropdown-menu {
 | 
					.dropdown-submenu > .dropdown-menu {
 | 
				
			||||||
    position: absolute;
 | 
					    position: absolute;
 | 
				
			||||||
    top: 0;
 | 
					    top: 0;
 | 
				
			||||||
    left: 100%; /* Öffnen nach rechts */
 | 
					    left: 100%; /* Opens to the right */
 | 
				
			||||||
    z-index: 1050;
 | 
					    z-index: 1050;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Sicherstellen, dass der Übergang smooth ist */
 | 
					/* Ensure a smooth transition */
 | 
				
			||||||
.dropdown-menu {
 | 
					.dropdown-menu {
 | 
				
			||||||
    transition: all 0.3s ease-in-out;
 | 
					    transition: all 0.3s ease-in-out;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,25 +15,24 @@ function adjustScrollContainerHeight() {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  // Berechne die verfügbare Höhe für den Scrollbereich
 | 
					  // Calculate the available height for the scroll area
 | 
				
			||||||
  const availableHeight = window.innerHeight - siblingsHeight;
 | 
					  const availableHeight = window.innerHeight - siblingsHeight;
 | 
				
			||||||
  scrollContainer.style.maxHeight = availableHeight + 'px';
 | 
					  scrollContainer.style.maxHeight = availableHeight + 'px';
 | 
				
			||||||
  scrollContainer.style.overflowY = 'auto';
 | 
					  scrollContainer.style.overflowY = 'auto';
 | 
				
			||||||
  scrollContainer.style.overflowX = 'hidden';
 | 
					  scrollContainer.style.overflowX = 'hidden';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Hole die aktuelle Position und Höhe des Scrollbereichs
 | 
					  // Get the current position and height of the scroll container
 | 
				
			||||||
  const scrollContainerRect = scrollContainer.getBoundingClientRect();
 | 
					  const scrollContainerRect = scrollContainer.getBoundingClientRect();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Setze die Position (top) und die Höhe des benutzerdefinierten Scrollbar-Tracks
 | 
					  // Set the position (top) and height of the custom scrollbar track
 | 
				
			||||||
  scrollbarContainer.style.top = scrollContainerRect.top + 'px';
 | 
					  scrollbarContainer.style.top = scrollContainerRect.top + 'px';
 | 
				
			||||||
  scrollbarContainer.style.height = scrollContainerRect.height + 'px';
 | 
					  scrollbarContainer.style.height = scrollContainerRect.height + 'px';
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
window.addEventListener('load', adjustScrollContainerHeight);
 | 
					window.addEventListener('load', adjustScrollContainerHeight);
 | 
				
			||||||
window.addEventListener('resize', adjustScrollContainerHeight);
 | 
					window.addEventListener('resize', adjustScrollContainerHeight);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 2. Aktualisiert den Thumb (Größe und Position) der benutzerdefinierten Scrollbar
 | 
					// 2. Updates the thumb (size and position) of the custom scrollbar
 | 
				
			||||||
function updateCustomScrollbar() {
 | 
					function updateCustomScrollbar() {
 | 
				
			||||||
  const scrollContainer = document.querySelector('.scroll-container');
 | 
					  const scrollContainer = document.querySelector('.scroll-container');
 | 
				
			||||||
  const thumb = document.getElementById('scroll-thumb');
 | 
					  const thumb = document.getElementById('scroll-thumb');
 | 
				
			||||||
@@ -44,22 +43,22 @@ function updateCustomScrollbar() {
 | 
				
			|||||||
  const containerHeight = scrollContainer.clientHeight;
 | 
					  const containerHeight = scrollContainer.clientHeight;
 | 
				
			||||||
  const scrollTop = scrollContainer.scrollTop;
 | 
					  const scrollTop = scrollContainer.scrollTop;
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  // Berechne die Thumb-Höhe (mindestens 20px)
 | 
					  // Calculate the thumb height (minimum 20px)
 | 
				
			||||||
  let thumbHeight = (containerHeight / contentHeight) * containerHeight;
 | 
					  let thumbHeight = (containerHeight / contentHeight) * containerHeight;
 | 
				
			||||||
  thumbHeight = Math.max(thumbHeight, 20);
 | 
					  thumbHeight = Math.max(thumbHeight, 20);
 | 
				
			||||||
  thumb.style.height = thumbHeight + 'px';
 | 
					  thumb.style.height = thumbHeight + 'px';
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  // Berechne die Position des Thumbs
 | 
					  // Calculate the thumb position
 | 
				
			||||||
  const maxScrollTop = contentHeight - containerHeight;
 | 
					  const maxScrollTop = contentHeight - containerHeight;
 | 
				
			||||||
  const maxThumbTop = containerHeight - thumbHeight;
 | 
					  const maxThumbTop = containerHeight - thumbHeight;
 | 
				
			||||||
  const thumbTop = maxScrollTop ? (scrollTop / maxScrollTop) * maxThumbTop : 0;
 | 
					  const thumbTop = maxScrollTop ? (scrollTop / maxScrollTop) * maxThumbTop : 0;
 | 
				
			||||||
  thumb.style.top = thumbTop + 'px';
 | 
					  thumb.style.top = thumbTop + 'px';
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  // Zeige die Scrollbar, falls der Inhalt überläuft, sonst ggf. ausblenden
 | 
					  // Show the scrollbar if content overflows, otherwise hide it
 | 
				
			||||||
  customScrollbar.style.opacity = contentHeight > containerHeight ? '1' : '0';
 | 
					  customScrollbar.style.opacity = contentHeight > containerHeight ? '1' : '0';
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Aktualisiere den Thumb bei Scrollen des Containers
 | 
					// Update the thumb when the container is scrolled
 | 
				
			||||||
const scrollContainer = document.querySelector('.scroll-container');
 | 
					const scrollContainer = document.querySelector('.scroll-container');
 | 
				
			||||||
if (scrollContainer) {
 | 
					if (scrollContainer) {
 | 
				
			||||||
  scrollContainer.addEventListener('scroll', updateCustomScrollbar);
 | 
					  scrollContainer.addEventListener('scroll', updateCustomScrollbar);
 | 
				
			||||||
@@ -67,7 +66,7 @@ if (scrollContainer) {
 | 
				
			|||||||
window.addEventListener('resize', updateCustomScrollbar);
 | 
					window.addEventListener('resize', updateCustomScrollbar);
 | 
				
			||||||
window.addEventListener('load', updateCustomScrollbar);
 | 
					window.addEventListener('load', updateCustomScrollbar);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 3. Interaktivität: Ermögliche Drag & Drop des Scroll-Thumbs
 | 
					// 3. Interactivity: Enable drag & drop for the scroll thumb
 | 
				
			||||||
let isDragging = false;
 | 
					let isDragging = false;
 | 
				
			||||||
let dragStartY = 0;
 | 
					let dragStartY = 0;
 | 
				
			||||||
let scrollStartY = 0;
 | 
					let scrollStartY = 0;
 | 
				
			||||||
@@ -93,11 +92,11 @@ document.addEventListener('mousemove', function(e) {
 | 
				
			|||||||
  const maxThumbTop = containerHeight - thumbHeight;
 | 
					  const maxThumbTop = containerHeight - thumbHeight;
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  const deltaY = e.clientY - dragStartY;
 | 
					  const deltaY = e.clientY - dragStartY;
 | 
				
			||||||
  // Berechne neuen Thumb-Top-Wert
 | 
					  // Calculate the new thumb top position
 | 
				
			||||||
  let newThumbTop = (scrollStartY / maxScrollTop) * maxThumbTop + deltaY;
 | 
					  let newThumbTop = (scrollStartY / maxScrollTop) * maxThumbTop + deltaY;
 | 
				
			||||||
  newThumbTop = Math.max(0, Math.min(newThumbTop, maxThumbTop));
 | 
					  newThumbTop = Math.max(0, Math.min(newThumbTop, maxThumbTop));
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  // Berechne den neuen Scrollwert anhand der Thumb-Position
 | 
					  // Calculate the new scroll position based on the thumb position
 | 
				
			||||||
  const newScrollTop = (newThumbTop / maxThumbTop) * maxScrollTop;
 | 
					  const newScrollTop = (newThumbTop / maxThumbTop) * maxScrollTop;
 | 
				
			||||||
  scrollContainer.scrollTop = newScrollTop;
 | 
					  scrollContainer.scrollTop = newScrollTop;
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,15 +17,15 @@ document.addEventListener('DOMContentLoaded', () => {
 | 
				
			|||||||
        }, 500);
 | 
					        }, 500);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Öffnen beim Hovern
 | 
					      // Open on hover
 | 
				
			||||||
      item.addEventListener('mouseenter', onMouseEnter);
 | 
					      item.addEventListener('mouseenter', onMouseEnter);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Verzögertes Schließen beim Verlassen
 | 
					      // Delayed close on mouse leave
 | 
				
			||||||
      item.addEventListener('mouseleave', onMouseLeave);
 | 
					      item.addEventListener('mouseleave', onMouseLeave);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Öffnen und Position anpassen beim Klicken
 | 
					      // Open and adjust position on click
 | 
				
			||||||
      item.addEventListener('click', (e) => {
 | 
					      item.addEventListener('click', (e) => {
 | 
				
			||||||
        e.stopPropagation(); // Verhindert das Schließen von Menüs bei Klick
 | 
					        e.stopPropagation(); // Prevents menus from closing when clicking inside
 | 
				
			||||||
        if (item.classList.contains('open')) {
 | 
					        if (item.classList.contains('open')) {
 | 
				
			||||||
          closeMenu(item);
 | 
					          closeMenu(item);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
@@ -44,7 +44,7 @@ document.addEventListener('DOMContentLoaded', () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  addAllMenuEventListeners();
 | 
					  addAllMenuEventListeners();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Globale Klick-Listener, um Menüs zu schließen, wenn außerhalb geklickt wird
 | 
					  // Global click listener to close menus when clicking outside
 | 
				
			||||||
  document.addEventListener('click', () => {
 | 
					  document.addEventListener('click', () => {
 | 
				
			||||||
    [...menuItems, ...subMenuItems].forEach(item => closeMenu(item));
 | 
					    [...menuItems, ...subMenuItems].forEach(item => closeMenu(item));
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
@@ -71,7 +71,7 @@ document.addEventListener('DOMContentLoaded', () => {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  function isSmallScreen() {
 | 
					  function isSmallScreen() {
 | 
				
			||||||
  return window.innerWidth < 992; // Bootstrap-Breakpoint für 'lg'
 | 
					    return window.innerWidth < 992; // Bootstrap breakpoint for 'lg'
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
  function adjustMenuPosition(submenu, parent, isTopLevel) {
 | 
					  function adjustMenuPosition(submenu, parent, isTopLevel) {
 | 
				
			||||||
@@ -89,12 +89,12 @@ function adjustMenuPosition(submenu, parent, isTopLevel) {
 | 
				
			|||||||
    submenu.style.right = '';
 | 
					    submenu.style.right = '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (isTopLevel) {
 | 
					    if (isTopLevel) {
 | 
				
			||||||
      if (isSmallScreen && spaceBelow < spaceAbove) {
 | 
					      if (isSmallScreen() && spaceBelow < spaceAbove) {
 | 
				
			||||||
        // Für kleine Bildschirme: Menü direkt über dem Eltern-Element öffnen
 | 
					        // For small screens: Open menu directly above the parent element
 | 
				
			||||||
        submenu.style.top = 'auto';
 | 
					        submenu.style.top = 'auto';
 | 
				
			||||||
        submenu.style.bottom = `${parentRect.height}px`; // Direkt über dem Eltern-Element
 | 
					        submenu.style.bottom = `${parentRect.height}px`; // Directly above the parent element
 | 
				
			||||||
      } 
 | 
					      } 
 | 
				
			||||||
        // Top-Level-Menü
 | 
					      // Top-level menu
 | 
				
			||||||
      else if (spaceBelow < spaceAbove) {
 | 
					      else if (spaceBelow < spaceAbove) {
 | 
				
			||||||
        submenu.style.bottom = `${window.innerHeight - parentRect.bottom - parentRect.height}px`;
 | 
					        submenu.style.bottom = `${window.innerHeight - parentRect.bottom - parentRect.height}px`;
 | 
				
			||||||
        submenu.style.top = 'auto';
 | 
					        submenu.style.top = 'auto';
 | 
				
			||||||
@@ -103,18 +103,18 @@ function adjustMenuPosition(submenu, parent, isTopLevel) {
 | 
				
			|||||||
        submenu.style.bottom = 'auto';
 | 
					        submenu.style.bottom = 'auto';
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        // Submenü
 | 
					      // Submenu
 | 
				
			||||||
      const prefersRight = spaceRight >= spaceLeft;
 | 
					      const prefersRight = spaceRight >= spaceLeft;
 | 
				
			||||||
      submenu.style.left = prefersRight ? '100%' : 'auto';
 | 
					      submenu.style.left = prefersRight ? '100%' : 'auto';
 | 
				
			||||||
      submenu.style.right = prefersRight ? 'auto' : '100%';
 | 
					      submenu.style.right = prefersRight ? 'auto' : '100%';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Nach oben öffnen, wenn unten kein Platz ist
 | 
					      // Open upwards if there's no space below
 | 
				
			||||||
      if (spaceBelow < spaceAbove) {
 | 
					      if (spaceBelow < spaceAbove) {
 | 
				
			||||||
        submenu.style.bottom = `0`;
 | 
					        submenu.style.bottom = `0`;
 | 
				
			||||||
        submenu.style.top = `auto`;
 | 
					        submenu.style.top = `auto`;
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        submenu.style.top = `0`;
 | 
					        submenu.style.top = `0`;
 | 
				
			||||||
            submenu.style.bottom = '${parentRect.height}px';
 | 
					        submenu.style.bottom = `${parentRect.height}px`;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
// Initialisiert alle Tooltips auf der Seite
 | 
					// Initializes all tooltips on the page
 | 
				
			||||||
document.addEventListener('DOMContentLoaded', function () {
 | 
					document.addEventListener('DOMContentLoaded', function () {
 | 
				
			||||||
    var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
 | 
					    var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
 | 
				
			||||||
    tooltipTriggerList.forEach(function (tooltipTriggerEl) {
 | 
					    tooltipTriggerList.forEach(function (tooltipTriggerEl) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,7 +29,6 @@
 | 
				
			|||||||
            {% include "moduls/navigation.html.j2"%}
 | 
					            {% include "moduls/navigation.html.j2"%}
 | 
				
			||||||
            <main id="main">
 | 
					            <main id="main">
 | 
				
			||||||
            <div class="scroll-container">
 | 
					            <div class="scroll-container">
 | 
				
			||||||
                <!-- Hier kommt dein Hauptinhalt -->
 | 
					 | 
				
			||||||
                {% block content %}{% endblock %}
 | 
					                {% block content %}{% endblock %}
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
            </main>
 | 
					            </main>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,7 +13,7 @@ def compute_card_classes(cards):
 | 
				
			|||||||
    elif num_cards % 2 == 0:
 | 
					    elif num_cards % 2 == 0:
 | 
				
			||||||
        lg_classes = ["col-lg-6"] * num_cards
 | 
					        lg_classes = ["col-lg-6"] * num_cards
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        # Für komplexe Fälle (z. B. 5, 7, 11) – Stelle sicher, dass mindestens 3 pro Zeile erscheinen
 | 
					        # For complex cases (e.g., 5, 7, 11) – Ensure at least 3 per row
 | 
				
			||||||
        for i in range(num_cards):
 | 
					        for i in range(num_cards):
 | 
				
			||||||
            if num_cards % 4 == 3:
 | 
					            if num_cards % 4 == 3:
 | 
				
			||||||
                if i < 3:
 | 
					                if i < 3:
 | 
				
			||||||
@@ -32,7 +32,7 @@ def compute_card_classes(cards):
 | 
				
			|||||||
                    lg_classes.append("col-lg-6")
 | 
					                    lg_classes.append("col-lg-6")
 | 
				
			||||||
                else:
 | 
					                else:
 | 
				
			||||||
                    lg_classes.append("col-lg-4")
 | 
					                    lg_classes.append("col-lg-4")
 | 
				
			||||||
    # md-Klassen: Wenn die Anzahl der Karten gerade ist oder wenn nicht die letzte Karte, ansonsten "col-md-12"
 | 
					    # md classes: If the number of cards is even or if not the last card, otherwise "col-md-12"
 | 
				
			||||||
    md_classes = []
 | 
					    md_classes = []
 | 
				
			||||||
    for i in range(num_cards):
 | 
					    for i in range(num_cards):
 | 
				
			||||||
        if num_cards % 2 == 0 or i < num_cards - 1:
 | 
					        if num_cards % 2 == 0 or i < num_cards - 1:
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user