PageSourceSearch

https://hotel-lillevang.dk/assets/js/forms.js?v=7fb012af

js hotel-lillevang.dk collected 2026-10-07 23:02:35 UTC 3,033 bytes, 92 lines download raw bytes

1/**
2 * Formularhåndtering – kontaktformular, selskabsforespørgsel og widget.
3 *
4 * Progressive enhancement: formularerne har rigtige felter med required,
5 * maxlength og korrekte type-attributter, så browseren validerer selv.
6 * Uden JavaScript poster de som almindelig formular; JS giver bare svar
7 * uden at forlade siden.
8 */
9
10const ENDPOINT = '/api/contact';
11
12/** Samler felterne til den besked receptionen modtager. */
13function buildMessage(form) {
14  const fd = new FormData(form);
15  const get = (k) => (fd.get(k) || '').toString().trim();
16
17  const wishes = fd.getAll('wishes').filter(Boolean);
18  const extras = [
19    ['Telefon', get('phone')],
20    ['Firma', get('company')],
21    ['Adresse', [get('address'), get('zip'), get('city')].filter(Boolean).join(', ')],
22    ['Dato', get('date')],
23    ['Antal gæster', get('guests')],
24    ['Ønsker', wishes.join(', ')],
25  ].filter(([, v]) => v);
26
27  const body = get('message');
28  const head = extras.map(([k, v]) => `${k}: ${v}`).join('\n');
29
30  return [head, body].filter(Boolean).join('\n\n');
31}
32
33function wire(form) {
34  const status = form.querySelector('.form__status');
35  const button = form.querySelector('button[type="submit"]');
36  if (!status || !button) return;
37
38  const thanks = status.dataset.thanks || 'Tak for din besked.';
39  const lang = document.documentElement.lang || 'da';
40
41  form.addEventListener('submit', async (e) => {
42    e.preventDefault();
43
44    if (!form.reportValidity()) return;
45
46    const original = button.textContent;
47    button.disabled = true;
48    status.textContent = '';
49    status.removeAttribute('data-state');
50
51    const fd = new FormData(form);
52    const payload = {
53      name: (fd.get('name') || '').toString().trim(),
54      email: (fd.get('email') || '').toString().trim(),
55      message: buildMessage(form),
56      lang,
57      website: (fd.get('website') || '').toString(),
58    };
59
60    try {
61      const res = await fetch(ENDPOINT, {
62        method: 'POST',
63        headers: { 'Content-Type': 'application/json' },
64        body: JSON.stringify(payload),
65      });
66
67      const data = await res.json().catch(() => ({}));
68
69      if (res.ok && data.ok) {
70        form.reset();
71        status.textContent = thanks;
72        status.setAttribute('data-state', 'ok');
73        // Skjul felterne når beskeden er sendt – svaret er det eneste
74        // der er relevant derefter.
75        form.querySelectorAll('fieldset, label, .wishes, .wishes-label, button').forEach((el) => {
76          el.hidden = true;
77        });
78      } else {
79        status.textContent = data.error || 'Beskeden kunne ikke sendes. Prøv igen, eller ring til os.';
80        status.setAttribute('data-state', 'error');
81      }
82    } catch {
83      status.textContent = 'Beskeden kunne ikke sendes. Prøv igen, eller ring til os.';
84      status.setAttribute('data-state', 'error');
85    } finally {
86      button.disabled = false;
87      button.textContent = original;
88    }
89  });
90}
91
92document.querySelectorAll('form#contact-form, form#event-form, form#widget-form').forEach(wire);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.