103 lines
4.0 KiB
HTML
103 lines
4.0 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="{{ lang }}">
|
||
<head>
|
||
<meta charset="UTF-8"/>
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||
<title>{% block title %}Skywatcher{% endblock %}</title>
|
||
<link rel="preconnect" href="https://fonts.googleapis.com"/>
|
||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;900&display=swap" rel="stylesheet"/>
|
||
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}?v=4"/>
|
||
{% block head %}{% endblock %}
|
||
</head>
|
||
<body>
|
||
<nav class="nav">
|
||
<a href="/" class="nav-logo">Sky<span>watcher</span></a>
|
||
<form class="nav-search" action="/wetter" method="get" autocomplete="off">
|
||
<div class="nav-search-wrap">
|
||
<svg class="nav-search-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/></svg>
|
||
<input type="hidden" name="lang" value="{{ lang }}">
|
||
<input type="text" name="ort" id="nav-ort" placeholder="{{ T.nav_placeholder }}" value="{{ request.args.get('ort','') }}"/>
|
||
<ul class="ac-list" id="nav-ac"></ul>
|
||
</div>
|
||
</form>
|
||
<span class="nav-clock" id="nav-clock" data-suffix="{{ T.clock_suffix }}"></span>
|
||
<nav class="lang-switch" aria-label="Language">
|
||
<a href="/set-lang?lang=de&next={{ request.full_path }}" class="lang-btn{% if lang == 'de' %} lang-btn--active{% endif %}" hreflang="de">DE</a>
|
||
<a href="/set-lang?lang=en&next={{ request.full_path }}" class="lang-btn{% if lang == 'en' %} lang-btn--active{% endif %}" hreflang="en">EN</a>
|
||
</nav>
|
||
</nav>
|
||
|
||
<main>{% block content %}{% endblock %}</main>
|
||
|
||
<footer class="footer">
|
||
{{ T.data_source }} <a href="https://opendata.dwd.de" target="_blank" rel="noopener noreferrer">Deutscher Wetterdienst – Open Data (MOSMIX)</a>
|
||
</footer>
|
||
|
||
<script>
|
||
function setupAC(input, list) {
|
||
if (!input || !list) return;
|
||
let t;
|
||
input.addEventListener("input", () => {
|
||
clearTimeout(t);
|
||
const q = input.value.trim();
|
||
if (q.length < 2) { list.hidden = true; list.innerHTML = ""; return; }
|
||
t = setTimeout(async () => {
|
||
let data = [];
|
||
try {
|
||
const r = await fetch(`/api/suggest?q=${encodeURIComponent(q)}`);
|
||
if (r.ok) {
|
||
const json = await r.json();
|
||
data = Array.isArray(json) ? json : [];
|
||
}
|
||
} catch (e) {
|
||
data = [];
|
||
}
|
||
list.innerHTML = "";
|
||
if (!data.length) { list.hidden = true; return; }
|
||
data.forEach(item => {
|
||
const li = document.createElement("li");
|
||
li.textContent = item.name;
|
||
li.addEventListener("click", () => {
|
||
input.value = item.name;
|
||
list.hidden = true;
|
||
input.closest("form").submit();
|
||
});
|
||
list.appendChild(li);
|
||
});
|
||
list.hidden = false;
|
||
}, 220);
|
||
});
|
||
document.addEventListener("click", e => { if (!list.contains(e.target) && e.target !== input) list.hidden = true; });
|
||
}
|
||
setupAC(document.getElementById("nav-ort"), document.getElementById("nav-ac"));
|
||
window.setupAC = setupAC;
|
||
|
||
// Live clock — shows location's local time when a timezone meta tag is present
|
||
(function () {
|
||
const tzMeta = document.querySelector('meta[name="location-tz"]');
|
||
const tz = tzMeta ? tzMeta.getAttribute("content") : null;
|
||
const navClock = document.getElementById("nav-clock");
|
||
const heroTime = document.getElementById("hero-time");
|
||
const suffix = navClock ? (navClock.dataset.suffix ? " " + navClock.dataset.suffix : "") : "";
|
||
|
||
function tick() {
|
||
const now = new Date();
|
||
const opts = { hour: "2-digit", minute: "2-digit", hour12: false };
|
||
let timeStr;
|
||
try {
|
||
timeStr = new Intl.DateTimeFormat("de-DE", tz ? { ...opts, timeZone: tz } : opts).format(now);
|
||
} catch (e) {
|
||
timeStr = new Intl.DateTimeFormat("de-DE", opts).format(now);
|
||
}
|
||
if (navClock) navClock.textContent = timeStr + suffix;
|
||
if (heroTime) heroTime.textContent = timeStr + suffix;
|
||
}
|
||
|
||
tick();
|
||
setInterval(tick, 10000);
|
||
})();
|
||
</script>
|
||
{% block scripts %}{% endblock %}
|
||
</body>
|
||
</html>
|