138 lines
4.4 KiB
JavaScript
138 lines
4.4 KiB
JavaScript
|
|
(function () {
|
|||
|
|
const header = document.querySelector("[data-header]");
|
|||
|
|
const toggle = document.querySelector(".nav-toggle");
|
|||
|
|
if (toggle && header) {
|
|||
|
|
toggle.addEventListener("click", () => {
|
|||
|
|
const open = header.classList.toggle("is-open");
|
|||
|
|
toggle.setAttribute("aria-expanded", open ? "true" : "false");
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const path = location.pathname.replace(/index\.html$/, "");
|
|||
|
|
document.querySelectorAll(".site-nav a[href]").forEach((a) => {
|
|||
|
|
const href = a.getAttribute("href");
|
|||
|
|
if (!href || href === "/") return;
|
|||
|
|
if (path === href || path.startsWith(href)) a.setAttribute("aria-current", "page");
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
const dialog = document.getElementById("product-drawer");
|
|||
|
|
if (dialog) {
|
|||
|
|
document.querySelectorAll("[data-product]").forEach((btn) => {
|
|||
|
|
btn.addEventListener("click", () => {
|
|||
|
|
const d = JSON.parse(btn.getAttribute("data-product"));
|
|||
|
|
dialog.querySelector("[data-d-img]").src = d.image;
|
|||
|
|
dialog.querySelector("[data-d-img]").alt = d.name;
|
|||
|
|
dialog.querySelector("[data-d-name]").textContent = d.name;
|
|||
|
|
dialog.querySelector("[data-d-blurb]").textContent = d.blurb || "";
|
|||
|
|
const link = dialog.querySelector("[data-d-recipe]");
|
|||
|
|
if (d.recipe) {
|
|||
|
|
link.hidden = false;
|
|||
|
|
link.href = "/recepten/" + d.recipe + "/";
|
|||
|
|
} else {
|
|||
|
|
link.hidden = true;
|
|||
|
|
}
|
|||
|
|
dialog.showModal();
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
dialog.querySelector(".drawer-close").addEventListener("click", () => dialog.close());
|
|||
|
|
dialog.addEventListener("click", (e) => {
|
|||
|
|
if (e.target === dialog) dialog.close();
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const form = document.querySelector("[data-mailto]");
|
|||
|
|
if (form) {
|
|||
|
|
form.addEventListener("submit", (e) => {
|
|||
|
|
e.preventDefault();
|
|||
|
|
const fd = new FormData(form);
|
|||
|
|
const subject = encodeURIComponent(fd.get("onderwerp") || "Bericht via cucinafood.nl");
|
|||
|
|
const lines = [];
|
|||
|
|
fd.forEach((v, k) => {
|
|||
|
|
if (k !== "onderwerp") lines.push(k + ": " + v);
|
|||
|
|
});
|
|||
|
|
const body = encodeURIComponent(lines.join("\n"));
|
|||
|
|
location.href = "mailto:info@cucinafood.nl?subject=" + subject + "&body=" + body;
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const root = document.querySelector("[data-finder]");
|
|||
|
|
if (!root) return;
|
|||
|
|
|
|||
|
|
const input = root.querySelector("input[type=search]");
|
|||
|
|
const out = root.querySelector("[data-results]");
|
|||
|
|
const status = root.querySelector("[data-status]");
|
|||
|
|
let stores = [];
|
|||
|
|
|
|||
|
|
const norm = (s) =>
|
|||
|
|
(s || "")
|
|||
|
|
.toLowerCase()
|
|||
|
|
.normalize("NFD")
|
|||
|
|
.replace(/[\u0300-\u036f]/g, "")
|
|||
|
|
.replace(/['’`]/g, "");
|
|||
|
|
|
|||
|
|
function search(q) {
|
|||
|
|
q = norm(q).trim();
|
|||
|
|
if (q.length < 2) return [];
|
|||
|
|
const hits = [];
|
|||
|
|
for (const s of stores) {
|
|||
|
|
const blob = norm([s.city, s.address, s.id, s.label].join(" "));
|
|||
|
|
if (blob.includes(q)) hits.push(s);
|
|||
|
|
if (hits.length >= 40) break;
|
|||
|
|
}
|
|||
|
|
return hits;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function render(hits, q) {
|
|||
|
|
if (q.trim().length < 2) {
|
|||
|
|
status.textContent = "Typ een plaats of postcode. We tonen geen muur van adressen.";
|
|||
|
|
out.innerHTML = "";
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
if (!hits.length) {
|
|||
|
|
status.textContent = "Geen winkels voor “" + q + "”. Probeer een stad, zoals Amsterdam of Gent.";
|
|||
|
|
out.innerHTML = "";
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
status.textContent = hits.length + (hits.length === 40 ? "+" : "") + " winkels bij “" + q + "”";
|
|||
|
|
out.innerHTML = hits
|
|||
|
|
.map((s) => {
|
|||
|
|
const maps = s.maps
|
|||
|
|
? s.maps
|
|||
|
|
: "https://www.google.com/maps/search/?api=1&query=" +
|
|||
|
|
encodeURIComponent(s.address + " " + s.city);
|
|||
|
|
return (
|
|||
|
|
"<li><div><strong>" +
|
|||
|
|
s.city +
|
|||
|
|
"</strong><small>" +
|
|||
|
|
s.address +
|
|||
|
|
"</small></div><a class='btn' href='" +
|
|||
|
|
maps +
|
|||
|
|
"' target='_blank' rel='noopener'>Maps</a></li>"
|
|||
|
|
);
|
|||
|
|
})
|
|||
|
|
.join("");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
fetch("/data/stores.json")
|
|||
|
|
.then((r) => r.json())
|
|||
|
|
.then((data) => {
|
|||
|
|
stores = data;
|
|||
|
|
const start = new URLSearchParams(location.search).get("q") || "";
|
|||
|
|
if (start) input.value = start;
|
|||
|
|
render(search(input.value), input.value);
|
|||
|
|
})
|
|||
|
|
.catch(() => {
|
|||
|
|
status.textContent = "De winkellijst kon niet geladen worden.";
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
let t;
|
|||
|
|
input.addEventListener("input", () => {
|
|||
|
|
clearTimeout(t);
|
|||
|
|
t = setTimeout(() => render(search(input.value), input.value), 80);
|
|||
|
|
});
|
|||
|
|
root.querySelector("form").addEventListener("submit", (e) => {
|
|||
|
|
e.preventDefault();
|
|||
|
|
render(search(input.value), input.value);
|
|||
|
|
});
|
|||
|
|
})();
|