PageSourceSearch

https://www.elle.cz/js/modules/newsletterSignup.js

js elle.cz collected 2026-10-02 07:55:32 UTC 4,003 bytes, 131 lines download raw bytes

1const GENERIC_ERROR_MESSAGE = 'Nastala neznámá chyba. Zkuste to prosím znovu.';
2
3export function initNewsletterSignup(root = document) {
4  const forms = root.querySelectorAll('[data-newsletter-signup-form]:not([data-newsletter-signup-bound])');
5
6  forms.forEach((form) => {
7    const input = form.querySelector('[data-newsletter-signup-input]');
8
9    form.dataset.newsletterSignupBound = 'true';
10
11    if (input instanceof HTMLInputElement) {
12      input.addEventListener('click', () => {
13        toggleDetailsVisibility(form, true);
14      });
15
16      input.addEventListener('focus', () => {
17        toggleDetailsVisibility(form, true);
18      });
19    }
20
21    form.addEventListener('submit', async (event) => {
22      event.preventDefault();
23
24      const submitButton = form.querySelector('.newsletter-signup__submit');
25      const section = form.closest('[data-newsletter-signup-root]');
26
27      if (!(submitButton instanceof HTMLButtonElement) || !(section instanceof HTMLElement)) {
28        return;
29      }
30
31      clearError(section);
32      submitButton.disabled = true;
33
34      try {
35        const response = await fetch(form.action, {
36          method: 'POST',
37          body: new FormData(form),
38          credentials: 'same-origin',
39          headers: {
40            'X-Requested-With': 'XMLHttpRequest',
41            Accept: 'text/html',
42          },
43        });
44
45        if (!response.ok) {
46          throw new Error(`Newsletter signup failed with status ${response.status}.`);
47        }
48
49        const html = await response.text();
50        replaceSection(section, html);
51      } catch (error) {
52        console.error(error);
53        submitButton.disabled = false;
54        showError(section, GENERIC_ERROR_MESSAGE);
55      }
56    });
57  });
58}
59
60function toggleDetailsVisibility(form, isVisible) {
61  if (isVisible) {
62    form.classList.add('newsletter-signup--details-visible');
63    setDetailsState(form, true);
64  }
65}
66
67function replaceSection(currentSection, html) {
68  const template = document.createElement('template');
69  template.innerHTML = html.trim();
70
71  const nextSection = template.content.firstElementChild;
72
73  if (!(nextSection instanceof HTMLElement)) {
74    showError(currentSection, GENERIC_ERROR_MESSAGE);
75    return;
76  }
77
78  currentSection.replaceWith(nextSection);
79  initNewsletterSignup(nextSection);
80}
81
82function clearError(section) {
83  const errorElement = section.querySelector('[data-newsletter-signup-error]');
84  const inputWrap = section.querySelector('.newsletter-signup__input-wrap');
85  const input = section.querySelector('.newsletter-signup__input');
86
87  if (errorElement instanceof HTMLElement) {
88    errorElement.textContent = '';
89    errorElement.classList.remove('newsletter-signup__error--visible');
90  }
91
92  if (inputWrap instanceof HTMLElement) {
93    inputWrap.classList.remove('newsletter-signup__input-wrap--error');
94  }
95
96  if (input instanceof HTMLInputElement) {
97    input.setAttribute('aria-invalid', 'false');
98  }
99}
100
101function showError(section, message) {
102  const form = section.querySelector('[data-newsletter-signup-form]');
103  const errorElement = section.querySelector('[data-newsletter-signup-error]');
104  const inputWrap = section.querySelector('.newsletter-signup__input-wrap');
105  const input = section.querySelector('.newsletter-signup__input');
106
107  if (form instanceof HTMLFormElement) {
108    toggleDetailsVisibility(form, true);
109  }
110
111  if (errorElement instanceof HTMLElement) {
112    errorElement.textContent = message;
113    errorElement.classList.add('newsletter-signup__error--visible');
114  }
115
116  if (inputWrap instanceof HTMLElement) {
117    inputWrap.classList.add('newsletter-signup__input-wrap--error');
118  }
119
120  if (input instanceof HTMLInputElement) {
121    input.setAttribute('aria-invalid', 'true');
122  }
123}
124
125function setDetailsState(form, isExpanded) {
126  const detailsStateInput = form.querySelector('[data-newsletter-signup-details-state]');
127
128  if (detailsStateInput instanceof HTMLInputElement) {
129    detailsStateInput.value = isExpanded ? 'true' : 'false';
130  }
131}

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.