PageSourceSearch

https://www.bro-coli.com/assets/contact-form.js

js bro-coli.com collected 2026-10-06 19:23:50 UTC 4,272 bytes, 115 lines download raw bytes

1/*
2 * Kontaktní formulář – odeslání na nový backend /api/contact.
3 * Nahrazuje původní Contact Form 7 JS (které posílalo na WordPress REST API).
4 * Zachovává vzhled a stavové třídy CF7, aby formulář vypadal a choval se 1:1.
5 */
6(function () {
7  'use strict';
8
9  var ENDPOINT = '/api/contact';
10  var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
11
12  function ready(fn) {
13    if (document.readyState !== 'loading') fn();
14    else document.addEventListener('DOMContentLoaded', fn);
15  }
16
17  function clearTips(form) {
18    form.querySelectorAll('.wpcf7-not-valid-tip').forEach(function (t) { t.remove(); });
19    form.querySelectorAll('.wpcf7-not-valid').forEach(function (el) {
20      el.classList.remove('wpcf7-not-valid');
21      el.setAttribute('aria-invalid', 'false');
22    });
23  }
24
25  function showTip(input, msg) {
26    if (!input) return;
27    input.classList.add('wpcf7-not-valid');
28    input.setAttribute('aria-invalid', 'true');
29    var tip = document.createElement('span');
30    tip.className = 'wpcf7-not-valid-tip';
31    tip.setAttribute('aria-hidden', 'true');
32    tip.textContent = msg;
33    (input.closest('.wpcf7-form-control-wrap') || input.parentNode).appendChild(tip);
34  }
35
36  function setStatus(form, state, message) {
37    // state: 'sent' | 'invalid' | 'failed' | 'submitting' | ''
38    form.classList.remove('sent', 'invalid', 'failed', 'submitting', 'init');
39    if (state) form.classList.add(state);
40    var out = form.querySelector('.wpcf7-response-output');
41    if (out) {
42      out.textContent = message || '';
43      out.setAttribute('aria-hidden', message ? 'false' : 'true');
44      out.style.display = message ? 'block' : '';
45    }
46  }
47
48  function clientValidate(form) {
49    clearTips(form);
50    var ok = true;
51    var name = form.querySelector('[name="your-name"]');
52    var email = form.querySelector('[name="your-email"]');
53    var message = form.querySelector('[name="message"]');
54    var consent = form.querySelector('[name="consent-1"]');
55
56    if (name && !name.value.trim()) { showTip(name, 'Please fill out this field.'); ok = false; }
57    if (email && !email.value.trim()) { showTip(email, 'Please fill out this field.'); ok = false; }
58    else if (email && !EMAIL_RE.test(email.value.trim())) { showTip(email, 'The e-mail address is invalid.'); ok = false; }
59    if (message && !message.value.trim()) {
60      showTip(message, 'Please fill out this field.'); ok = false;
61    }
62    if (consent && consent.type === 'checkbox' && !consent.checked) {
63      showTip(consent, 'You must accept the terms.'); ok = false;
64    }
65    return ok;
66  }
67
68  function handle(form) {
69    form.setAttribute('novalidate', 'novalidate');
70    form.addEventListener('submit', function (e) {
71      e.preventDefault();
72      e.stopPropagation();
73
74      if (!clientValidate(form)) {
75        setStatus(form, 'invalid', 'One or more fields have an error. Please check and try again.');
76        return;
77      }
78
79      var submitBtn = form.querySelector('[type="submit"]');
80      if (submitBtn) submitBtn.disabled = true;
81      setStatus(form, 'submitting', 'Sending…');
82
83      fetch(ENDPOINT, {
84        method: 'POST',
85        headers: { Accept: 'application/json' },
86        body: new FormData(form),
87      })
88        .then(function (res) { return res.json().then(function (d) { return { res: res, data: d }; }); })
89        .then(function (r) {
90          if (r.res.ok && r.data.ok) {
91            setStatus(form, 'sent', r.data.message || 'Thank you for your message!');
92            form.reset();
93          } else {
94            if (r.data && r.data.errors) {
95              Object.keys(r.data.errors).forEach(function (field) {
96                showTip(form.querySelector('[name="' + field + '"]'), r.data.errors[field]);
97              });
98            }
99            setStatus(form, r.res.status === 422 ? 'invalid' : 'failed',
100              (r.data && r.data.message) || 'Something went wrong. Please try again.');
101          }
102        })
103        .catch(function () {
104          setStatus(form, 'failed', 'Network error. Please try again later.');
105        })
106        .finally(function () {
107          if (submitBtn) submitBtn.disabled = false;
108        });
109    });
110  }
111
112  ready(function () {
113    document.querySelectorAll('form.wpcf7-form').forEach(handle);
114  });
115})();

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.