PageSourceSearch

https://www.eta.cz/js/form.js?vjs=1

js eta.cz collected 2026-09-25 02:47:49 UTC 12,956 bytes, 426 lines download raw bytes

1import { delegateEvent } from "./tools.js?vjs=1";
2
3/**
4 * @param {HTMLInputElement} inputElement
5 * @param {HTMLButtonElement} buttonElement
6 */
7function togglePassword(inputElement, buttonElement) {
8  const isPasswordVisible = inputElement.getAttribute("type") === "text";
9
10  if (isPasswordVisible) {
11    inputElement.setAttribute("type", "password");
12    buttonElement.setAttribute("aria-pressed", "false");
13    buttonElement.setAttribute("aria-label", buttonElement.dataset.ariaLabelShow);
14  } else {
15    inputElement.setAttribute("type", "text");
16    buttonElement.setAttribute("aria-pressed", "true");
17    buttonElement.setAttribute("aria-label", buttonElement.dataset.ariaLabelHide);
18  }
19}
20
21/**
22 * @param rootElement HTMLElement
23 * @depricated překlep v názvu třídy .js-toogle-password
24 */
25export function initTooglePassword(rootElement) {
26  rootElement.addEventListener(
27    "click",
28    delegateEvent(".js-toogle-password", (event) => {
29      togglePassword(
30        event.delegateTarget.closest(".form-input").querySelector("input"),
31      );
32    }),
33  );
34}
35
36export function initTogglePassword(rootElement) {
37  // TODO až budou odstraněny všechny elememty s překlepem možno odstranit
38  initTooglePassword(rootElement);
39
40  rootElement.addEventListener(
41      "click",
42      delegateEvent(".js-toggle-password", (event) => {
43        const button = event.delegateTarget;
44        const input = button.closest(".form-input").querySelector("input");
45        togglePassword(input, button);
46      }),
47  );
48}
49
50
51/**
52 * @param rootElement HTMLElement
53 */
54export function initCheckboxToggle(rootElement) {
55  rootElement.querySelectorAll(".js-checkbox-toggle").forEach((element) => {
56    element.addEventListener("change", (event) => {
57      const selector = event.target.dataset.targetSelector;
58      rootElement.querySelector(selector).classList.toggle("is-hidden");
59    });
60  });
61}
62
63/**
64 * @param rootElement HTMLElement
65 */
66export function initCheckboxRequiredToggle(rootElement) {
67  rootElement
68    .querySelectorAll(".js-checkbox-required-toggle")
69    .forEach((element) => {
70      element.addEventListener("change", (event) => {
71        const selector = event.target.dataset.requiredSelector;
72
73        rootElement.querySelectorAll(selector).forEach((targetElement) => {
74          if (event.target.checked) {
75            targetElement.setAttribute("required", "");
76          } else {
77            targetElement.removeAttribute("required");
78          }
79        });
80      });
81    });
82}
83
84/**
85 * @param rootElement HTMLElement
86 */
87export function initRadioRequiredToggle(rootElement) {
88  rootElement
89    .querySelectorAll(".js-radio-required-toggle")
90    .forEach((element) => {
91      element.addEventListener("change", (event) => {
92        const radioElement = event.target;
93        const name = radioElement.getAttribute("name");
94        radioElement
95          .closest("form")
96          .querySelectorAll("input[name=" + name + "]")
97          .forEach((element) => {
98            const selector = element.dataset.requiredSelector;
99            const isCurrent =
100              selector === event.target.dataset.requiredSelector;
101
102            rootElement = document.querySelector("body");
103
104            rootElement.querySelectorAll(selector).forEach((targetElement) => {
105              if (event.target.checked && isCurrent) {
106                targetElement.setAttribute("required", "");
107              } else {
108                targetElement.removeAttribute("required");
109              }
110            });
111          });
112      });
113    });
114}
115
116/**
117 * @param rootElement HTMLElement
118 */
119export function initRadioToggle(rootElement) {
120  rootElement.querySelectorAll(".js-radio-toggle").forEach((element) => {
121    element.addEventListener("change", (event) => {
122      const radioElement = event.target;
123      const name = radioElement.getAttribute("name");
124      radioElement
125        .closest("form")
126        .querySelectorAll("input[name=" + name + "]")
127        .forEach((element) => {
128          const selector = element.dataset.targetSelector;
129
130          rootElement.querySelectorAll(selector).forEach((targetElement) => {
131            targetElement.classList.toggle("is-hidden", !element.checked);
132          });
133        });
134    });
135  });
136}
137
138/**
139 * @param parentElement HTMLElement
140 */
141export function initializeForms(parentElement) {
142  if (parentElement === undefined) {
143    return;
144  }
145
146  initCheckboxToggle(parentElement);
147  initTogglePassword(parentElement);
148  initRadioToggle(parentElement);
149  initCheckboxRequiredToggle(parentElement);
150  initRadioRequiredToggle(parentElement);
151}
152
153export class InputQuantity extends HTMLElement {
154  static formAssociated = true;
155  #internals;
156  #shadowRoot;
157  static observedAttributes = ["value", "min", "max", "step", "name", "label", "data-aria-labelledby-id"];
158
159  constructor() {
160    super();
161    this.#internals = this.attachInternals();
162    this.#shadowRoot = this.attachShadow({
163      mode: "open",
164      delegatesFocus: true,
165    });
166
167    let wrapper = document.createElement("div");
168    wrapper.classList.add("wrapper");
169    const inputId = `quantity_${Math.random().toString(36).substring(2, 9)}`;
170    wrapper.innerHTML = `
171                <button data-action="down" aria-label="Snížit množství">
172                    <svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
173                        <path fill-rule="evenodd" clip-rule="evenodd" d="M6 11.25h12v1.5
173H6v-1.5Z" />
174                    </svg>
175                </button>
176                <input id="${inputId}" type="number" value="1" min="1" step="1" aria-label="množství" />
177                <button data-action="up" aria-label="Zvýšit množství">
178                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" aria-hidden="true">
179                        <path fill-rule="evenodd" clip-rule="evenodd" d="M11.25 12.75V18H12.75V12.75L18 12.75V11.25L12.75 11.25V6H11.25V11.25L6 11.25V12.75L11.25 12.75Z"/>
180                  </svg>
181                </button>
182                <dialog>
183                    <div>Text</div>
184                    <svg xmlns="http://www.w3.org/2000/svg" width="14" height="8" aria-hidden="true">
185                        <path d="M7 8L13.9282 0.5H0.0717969L7 8Z" fill="#4D4D4D"/>
186                    </svg>
187                </dialog>
188            `;
189
190    let style = document.createElement("style");
191    style.innerHTML = `
192                * {
193                box-sizing: border-box;
194                }
195                .wrapper {
196                  display: flex;
197                  justify-content: space-between;
198                  border-radius: 6px;
199                  border: 1px solid var(--color-gray-scale-gray-100);
200                  background: #fff;
201                  height: 46px;
202                  width: 108px;
203                  position: relative;
204                }
205
206                button {
207                  display: flex;
208                  align-items: center;
209                  justify-content: center;
210                  flex-shrink: 0;
211                  padding: 0;
212                  border: 0;
213                  width: 34px;
214                  height: 45px;
215                  background: var(--color-gray-scale-gray-50);
216                  transition: all 300ms;
217                  cursor: pointer;
218                }
219                
220                button svg {
221                  fill: currentColor;
222                  pointer-events: none;
223                }
224
225                button:hover {
226                    background: var(--color-branding-orange);
227                    color: #fff;
228                }
229                
230                @media (max-width: 600px) {
231                  .wrapper {
232                    height: 38px;
233                   }
234                   button {
235                    height: 36px;
236                   }
237                   
238                }
239
240                [data-action="down"] {
241                  border-radius: 5px 0 0 5px;
242                }
243
244                [data-action="up"] {
245                  border-radius: 0 5px 5px 0;
246                }
247
248                input {
249                  width: 38px;
250                  border: none;
251                  appearance: none;
252                  -moz-appearance: textfield;
253                  text-align: center;
254                  outline: none;
255                  padding: 0;
256                }
257
258                input::inner-spin-button {
259                  apperance: none;
260                }
261                input::-webkit-inner-spin-button {
262                  -webkit-appearance: none;
263                }
264                input::-webkit-outer-spin-button {
265                   -webkit-appearance: none;
266                }
267
268                dialog {
269                  min-width: 130px;
270                  margin-bottom: 10px;
271                  color: #fff;
272                  bottom: calc(100% - 4px);
273                  font-size: 12px;
274                  font-weight: 600;
275                  line-height: 129%;
276                  border-radius: 5px;
277                  background: var(--color-gray-scale-gray-700, #4D4D4D);
278                  padding: 8px
279                }
280
281                dialog svg {
282                    position: absolute;
283                    top: 100%;
284                    margin-top: -1px;
285                    left: 46px;
286                }
287                    `;
288
289    this.#shadowRoot.append(wrapper, style);
290
291    let input = this.#shadowRoot.querySelector("input");
292    input.addEventListener("change", () => {
293      this.#internals.setFormValue(input.value);
294      this.setAttribute("value", input.value);
295      this.#validate(input.value);
296
297      this.dispatchEvent(
298        new CustomEvent("change", {
299          bubbles: true,
300          detail: { value: input.value },
301        }),
302      );
303    });
304
305    input.addEventListener("input", () => {
306      if (parseInt(input.value) < parseInt(input.min)) {
307        input.value = input.min;
308      }
309
310      if (parseInt(input.value) > parseInt(input.max)) {
311        input.value = input.max;
312      }
313    });
314
315    this.#shadowRoot.querySelectorAll("button").forEach((button) => {
316      button.addEventListener("click", (event) => {
317        if (event.target.dataset.action === "down") {
318          this.stepDown();
319        } else {
320          this.stepUp();
321        }
322        let input = this.#shadowRoot.querySelector("input");
323        let newValue = input.value;
324        this.setAttribute("value", newValue);
325        this.#validate(newValue);
326
327        this.dispatchEvent(
328          new CustomEvent("change", {
329            bubbles: true,
330            detail: { value: newValue },
331          }),
332        );
333      });
334    });
335  }
336
337  static register() {
338    if (customElements.get("input-quantity") !== undefined) {
339      return;
340    }
341
342    customElements.define("input-quantity", this);
343  }
344
345  #validate(newValue) {
346    let input = this.#shadowRoot.querySelector("input");
347    if (parseInt(newValue) >= parseInt(input.getAttribute("max"))) {
348      this.#showDialog();
349    } else {
350      this.#hideDialog();
351    }
352  }
353
354  formStateRestoreCallback(state, reason) {
355    this.#shadowRoot.querySelector("input").value = state;
356  }
357
358  attributeChangedCallback(name, oldValue, newValue) {
359    let input = this.#shadowRoot.querySelector("input");
360
361    switch (name) {
362      case "value":
363        this.#internals.setFormValue(newValue);
364        input.setAttribute(name, newValue);
365        this.#validate(newValue);
366        break;
367      case "label":
368      case "data-aria-labelledby-id":
369        this.#updateAccessibleName();
370        break;
371      default:
372        input.setAttribute(name, newValue);
373    }
374  }
375
376  #updateAccessibleName() {
377    const input = this.#shadowRoot.querySelector("input");
378    const label = this.getAttribute("label") || "množství";
379    const labelledbyId = this.dataset.ariaLabelledbyId;
380
381    input.setAttribute("aria-label", label);
382
383    if (labelledbyId) {
384      const inputId = input.getAttribute("id");
385      input.setAttribute("aria-labelledby", `${inputId} ${labelledbyId}`);
386    } else {
387      input.removeAttribute("aria-labelledby");
388    }
389  }
390
391  stepDown(n) {
392    this.#shadowRoot.querySelector("input").stepDown(n);
393  }
394
395  stepUp(n) {
396    this.#shadowRoot.querySelector("input").stepUp(n);
397  }
398
399  checkValidity() {
400    this.#shadowRoot.querySelector("input").checkValidity();
401  }
402
403  reportValidity() {
404    this.#shadowRoot.querySelector("input").reportValidity();
405  }
406
407  connectedCallback() {
408    this.#updateAccessibleName();
409  }
410
411  #showDialog() {
412    let maxValue = this.#shadowRoot.querySelector("input").getAttribute("max");
413    let message = this.dataset.message
414      ? this.dataset.message.replace("@pocet", maxValue)
415      : `Maximum je ${maxValue}`;
416
417    let dialog = this.#shadowRoot.querySelector("dialog");
418    dialog.querySelector("div").innerHTML = message;
419    dialog.show();
420    setTimeout(() => this.#hideDialog(), 3000);
421  }
422
423  #hideDialog() {
424    this.#shadowRoot.querySelector("dialog").close();
425  }
426}

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.