/**
* config.js - A modular configuration component for the SL Transport Departures app
* Allows changing settings on the fly, such as orientation (portrait/landscape)
*/
class ConfigManager {
constructor(options = {}) {
// Default options
this.options = {
configButtonId: 'config-button',
configModalId: 'config-modal',
saveToLocalStorage: true,
defaultOrientation: 'normal',
defaultDarkMode: 'auto', // 'auto', 'on', or 'off'
...options
};
// Add updateBackgroundPreview function
this.updateBackgroundPreview = function() {
const preview = document.getElementById('background-preview');
const imageUrl = document.getElementById('background-image-url').value;
if (preview) {
if (imageUrl && imageUrl.trim() !== '') {
preview.innerHTML = `
`;
} else {
preview.innerHTML = '
Instructions: Click on a marker to select a transit stop. Zoom and pan to explore the map.
`;
document.body.appendChild(mapModal);
// Wait for DOM to be ready
await new Promise(resolve => setTimeout(resolve, 100));
// Initialize map centered on Stockholm
const map = L.map('map-container').setView([59.3293, 18.0686], 13);
// Add OpenStreetMap tiles
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors',
maxZoom: 19
}).addTo(map);
// Close handlers
const closeMap = () => {
map.remove();
document.body.removeChild(mapModal);
};
mapModal.querySelector('.map-modal-close').addEventListener('click', closeMap);
mapModal.querySelector('#map-close-button').addEventListener('click', closeMap);
mapModal.addEventListener('click', (e) => {
if (e.target === mapModal) closeMap();
});
// Load nearby transit stops based on map center
const markersLayer = L.layerGroup().addTo(map);
const loadedSiteIds = new Set();
const loadNearbySites = async () => {
const center = map.getCenter();
const zoom = map.getZoom();
// Scale radius based on zoom: wider view = larger radius
const radius = zoom >= 15 ? 500 : zoom >= 13 ? 1500 : zoom >= 11 ? 4000 : 8000;
try {
const response = await fetch(`/api/sites/nearby?lat=${center.lat}&lon=${center.lng}&radius=${radius}`);
const data = await response.json();
if (data.sites) {
data.sites.forEach(site => {
if (loadedSiteIds.has(site.id)) return;
const lat = parseFloat(site.lat);
const lon = parseFloat(site.lon);
if (!lat || !lon || isNaN(lat) || isNaN(lon)) return;
loadedSiteIds.add(site.id);
const customIcon = L.divIcon({
className: 'custom-marker',
html: '