PageSourceSearch

https://sprivod.ru/local/templates/sprivod/js/app.js

js sprivod.ru collected 2026-10-08 07:24:25 UTC 64,449 bytes, 1,666 lines download raw bytes

vendor: 4,209 bytes, lines 1-17
1/*!
2DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
3*/
4"use strict";
5
6function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i.return) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
7function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, _regeneratorDefine2(e, r, n, t); }
8function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
9function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
10var Site = {
11  isMobile: false,
12  Init: function Init() {
13    console.log("jQuery version: " + Helpers.jqVersion());
14    $(window).on("resize", function () {
15      Site.SetIsMobile();
16
17      //if (Site.isMobile) {
18      // Helpers.setCookie('catalog_view_mode', 'tile', 1);
19      //
20      // $('.catalog-section__list').removeClass('catalog-section__list--list');
21      // $('[data-catalog-section-view-tile]').addClass('active');
22      // $('[data-catalog-section-view-list]').removeClass('active');
23      //}
24    });
25  },
26  SetIsMobile: function SetIsMobile() {
27    return Site.isMobile = $(window).innerWidth() < 768;
28  },
29  FixedMenu: function FixedMenu() {
30    var $body = $("body"),
31      $header = $(".header"),
32      $catalogMenu = $(".main-catalog-menu");
33    $(window).scroll(function () {
34      if (!Site.SetIsMobile()) {
35        if ($(this).scrollTop() >= 30) {
36          if (!$body.hasClass("fix-menu")) {
37            $body.addClass("fix-menu");
38          }
39          if (!$header.hasClass("fixed")) {
40            $header.addClass("fixed");
41          }
42          if (!$catalogMenu.hasClass("fixed")) {
43            $catalogMenu.addClass("short");
44          }
45        } else {
46          if ($body.hasClass("fix-menu")) {
47            $body.removeClass("fix-menu");
48          }
49          if ($header.hasClass("fixed")) {
50            $header.removeClass("fixed");
51          }
52          if ($catalogMenu.hasClass("short")) {
53            $catalogMenu.removeClass("short");
54          }
55        }
56      } else {
57        if ($(this).scrollTop() >= 1) {
58          if (!$body.hasClass("fix-menu")) {
59            $body.addClass("fix-menu");
60          }
61          if (!$header.hasClass("fixed")) {
62            $header.addClass("fixed");
63          }
64        } else {
65          if ($body.hasClass("fix-menu")) {
66            $body.removeClass("fix-menu");
67          }
68          if ($header.hasClass("fixed")) {
69            $header.removeClass("fixed");
70          }
71        }
72      }
73    });
74    $(window).scroll();
75  },
76  DetailDatasheet: function DetailDatasheet() {
77    var $tabs = $(".element-detail__tab"),
78      $tabsheet = $(".element-detail__tabsheet");
79    $(document).on("click", ".element-detail__tab", function (e) {
80      var $tab = $(this),
81        index = $tab.data("index"),
82        $sheet = $tabsheet.find("[data-sheet-" + index + "]"),
83        $sheets = $tabsheet.find(".element-detail__sheet");
84      if (Site.SetIsMobile()) {
85        if (!$($sheet).parent().is($tab)) {
86          $($tab).append($($sheet).detach());
87        }
88        if ($($tab).hasClass("expanded")) {
89          $tabs.removeClass("expanded");
90          $sheets.removeClass("active");
91        } else {
92          $tabs.removeClass("expanded");
93          $sheets.removeClass("active");
94          $($tab).addClass("expanded");
95          $($sheet).addClass("active");
96        }
97      } else {
98        $tabs.removeClass("expanded");
99        $sheets.removeClass("active");
100        $tab.addClass("expanded");
101        $sheet.addClass("active");
102      }
103    });
104
105    //костыль на дефолтное открытие 2-го таба
106    var $tab = $('[data-index="2"]'),
107      $sheet = $("[data-sheet-2]");
108    if ($tab.length && $sheet.length) {
109      if (Site.SetIsMobile()) {
110        $tab.append($sheet.detach());
111      }
112      $tab.addClass("expanded");
113      $sheet.addClass("active");
114    }
115    $(window).on("resize", function () {
116      var $activeTab = $(".element-detail__tab.expanded"),
117        $activeSheet = $(".element-detail__sheet.active");
118      if ($activeTab.length && $activeSheet.length) {
119        if (Site.SetIsMobile()) {
120          if (!$($activeSheet).parent().is($($activeTab))) {
121            $($activeTab).append($($activeSheet).detach());
122          }
123        } else {
124          if ($($activeSheet).parent().is($($activeTab))) {
125            $($tabsheet).append($($activeSheet).detach());
126          }
127        }
128      }
129    });
130  },
131  MainCatalogMenu: function MainCatalogMenu() {
132    $(document).on("click", ".header-large__catalog", function (e) {
133      var $burger = $(this).find(".header-large__burger"),
134        $catalogMenu = $(".main-catalog-menu");
135      $catalogMenu.toggleClass("open");
136      $burger.toggleClass("active");
137    });
138    $(document).on("click", function (e) {
139      var $target = $(e.target),
140        $catalogMenu = $(".main-catalog-menu"),
141        $catalogButton = $(".header-large__catalog"),
142        $burgerButton = $(".header-large__burger");
143      var $out = !$target.closest($catalogMenu).length && !$target.closest($catalogButton).length && $catalogMenu.is(":visible");
144      if ($out === true) {
145        $catalogMenu.removeClass("open");
146        $burgerButton.removeClass("active");
147      }
148    });
149  },
150  MobileMenu: function MobileMenu() {
151    $(document).on("click", ".header-mobile__menu", function () {
152      var $menu = $(".mobile-menu"),
153        $initiator = $(this),
154        $burger = $initiator.find(".header-mobile__burger");
155      $menu.toggleClass("open");
156      $burger.toggleClass("active");
157    });
158    $(document).on("click", ".mobile-menu__header", function () {
159      var $item = $(this).parent(),
160        $items = $item.siblings(".mobile-menu__item");
161      if (!$item.hasClass("expanded")) {
162        $items.removeClass("expanded");
163        $item.addClass("expanded");
164      } else {
165        $item.removeClass("expanded");
166      }
167    });
168    $(document).on("click", ".footer-mobile-menu__item", function () {
169      var $item = $(this),
170        $button = $item.data("button"),
171        $items = $(".footer-mobile-menu__item"),
172        $searchWin = $(".footer-mobile-menu__search"),
173        $personalWin = $(".footer-mobile-menu__personal");
174      $items.removeClass("active");
175      $item.addClass("active");
176      if ($button === "search") {
177        $personalWin.hide();
178        if ($searchWin.is(":visible")) {
179          $searchWin.hide();
180        } else {
181          $searchWin.show();
182        }
183      } else if ($button === "personal") {
184        $searchWin.hide();
185        if ($personalWin.is(":visible")) {
186          $personalWin.hide();
187        } else {
188          $personalWin.show();
189        }
190      }
191    });
192  },
193  FooterMenu: function FooterMenu() {
194    $(document).on("click", ".footer-menu__heading", function () {
195      var $item = $(this).parent(),
196        $items = $(".footer-menu");
197      if (Site.SetIsMobile()) {
198        if (!$item.hasClass("expanded")) {
199          $items.removeClass("expanded");
200          $item.addClass("expanded");
201        } else {
202          $item.removeClass("expanded");
203        }
204      }
205    });
206  },
207  SpinBoxField: function SpinBoxField() {
208    $(document).on("click", '[data-spin-box-field]>button[class*="arrow"]', function () {
209      var $spinBox = $(this).parent(),
210        $text = $spinBox.find('input[type="number"]'),
211        value = parseInt($text.val()),
212        min = $spinBox.data("min"),
213        max = $spinBox.data("max");
214      switch ($(this).attr("class")) {
215        case "arrow-up":
216          value < max ? value++ : value;
217          break;
218        case "arrow-down":
219          value > min ? value-- : value;
220          break;
221      }
222      $text.val(value);
223      $text.change();
224    });
225  },
226  PopupForms: function PopupForms() {
227    if (!this.popupInitialized) {
228      this.initPopup();
229      this.popupInitialized = true;
230      setTimeout(function () {
231        if (typeof initPopupLinesBlock === 'function') {
232          initPopupLinesBlock();
233        }
234      }, 200);
235    }
236  },
237  initPopup: function initPopup() {
238    var _this = this;
239    var popupOverlay = document.createElement("div");
240    popupOverlay.className = "popup-overlay";
241    var popupContent = document.createElement("div");
242    popupContent.className = "popup-content";
243    var popupClose = document.createElement("button");
244    popupClose.className = "popup-close";
245    popupClose.innerHTML = "×";
246    popupClose.type = "button";
247    popupContent.appendChild(popupClose);
248    popupOverlay.appendChild(popupContent);
249    document.body.appendChild(popupOverlay);
250    var handleFormSubmit = function handleFormSubmit(form) {
251      var submitBtn = form.querySelector('button[type="submit"]');
252      var formData = new FormData(form);
253      submitBtn.disabled = true;
254      submitBtn.textContent = "Отправка...";
255      fetch("/ajax/form-submit.php", {
256        method: "POST",
257        body: formData,
258        headers: {
259          "X-Requested-With": "XMLHttpRequest"
260        }
261      }).then(function (response) {
262        return response.json();
263      }).then(function (data) {
264        if (data.success) {
265          var successMessage = form.querySelector(".form-message--success");
266          if (successMessage) {
267            successMessage.style.display = "flex";
268            var successChildren = successMessage.querySelectorAll("*");
269            successChildren.forEach(function (child) {
270              child.style.display = "";
271            });
272            form.style.padding = "0";
273            form.style.width = "100%";
274          }
275          var formChildren = form.children;
276          for (var i = 0; i < formChildren.length; i++) {
277            var child = formChildren[i];
278            if (!child.classList.contains("form-message--success")) {
279              child.style.display = "none";
280            }
281          }
282        } else {
283          form.querySelector(".form-message--error").textContent = data.errors.join(", ");
284          form.querySelector(".form-message--error").style.display = "block";
285        }
286      }).catch(function (error) {
287        console.error("Ошибка:", error);
288        form.querySelector(".form-message--error").textContent = "Ошибка сети";
289        form.querySelector(".form-message--error").style.display = "block";
290      }).finally(function () {
291        submitBtn.disabled = false;
292        submitBtn.textContent = "Отправить";
293      });
294    };
295    popupOverlay.addEventListener("click", function (e) {
296      if (e.target === popupOverlay) {
297        _this.closePopup();
298      }
299    });
300    popupContent.addEventListener("click", function (e) {
301      if (e.target.classList.contains("popup-close")) {
302        _this.closePopup();
303      }
304    });
305    document.addEventListener("keydown", function (e) {
306      if (e.key === "Escape" && popupOverlay.style.display === "flex") {
307        _this.closePopup();
308      }
309    });
310    document.addEventListener("submit", function (e) {
311      if (e.target.classList.contains("form__container") && e.target.closest(".popup-content")) {
312        e.preventDefault();
313        handleFormSubmit(e.target);
314      }
315    });
316    this.openPopup = function (formName) {
317      var element = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
318      popupContent.innerHTML = "";
319      popupContent.appendChild(popupClose);
320      var loading = document.createElement("div");
321      loading.className = "popup-loading";
322      loading.textContent = "Загрузка формы...";
323      popupContent.appendChild(loading);
324      popupOverlay.style.display = "flex";
325      var formData = new FormData();
326      formData.append("form_name", formName);
327      formData.append("current_url", window.location.href);
328      if (element) {
329        var attributes = element.dataset;
330        for (var key in attributes) {
331          if (attributes.hasOwnProperty(key)) {
332            var phpKey = key.replace(/([A-Z])/g, '_$1').toLowerCase();
333            formData.append(phpKey, attributes[key]);
334          }
335        }
336      }
337      fetch("/ajax/load-form.php", {
338        method: "POST",
339        body: formData
340      }).then(function (response) {
341        return response.text();
342      }).then(function (html) {
343        popupContent.innerHTML = "";
344        popupContent.appendChild(popupClose);
345        popupContent.insertAdjacentHTML("beforeend", html);
346
347        // --- Определяем название товара ---
348        var productName = null;
349
350        // 1. Если кнопка передана (страница категории) – ищем название в карточке товара
351        if (element) {
352          // Ищем ближайший контейнер карточки (по классу catalog-product__item)
353          var productContainer = element.closest('.catalog-product__item');
354          // Если не нашли, пробуем родительский wrapper (на всякий случай)
355          if (!productContainer) {
356            productContainer = element.closest('.catalog-product__wrapper');
357          }
358          if (productContainer) {
359            var nameSpan = productContainer.querySelector('span[itemprop="name"]');
360            if (nameSpan) {
361              productName = nameSpan.innerText.trim();
362            }
363          }
364        }
365
366        // 2. Если не нашли через кнопку (например, детальная страница) – берём из H1
367        if (!productName) {
368          var h1 = document.querySelector('h1');
369          if (h1) {
370            productName = h1.innerText.trim();
371          }
372        }
373
374        // 3. Заполняем текстовое поле, если название найдено
375        if (productName) {
376          var textarea = document.getElementById('form_MESSAGE');
377          if (textarea) {
378            textarea.value = productName + '\n';  // добавляем перенос строки
379          }
380        }
381        // ---------------------------------
382
383        if (typeof Site.PhoneMask === "function") {
384          Site.PhoneMask();
385        }
386        setTimeout(function () {
387          if (typeof initLinesBlocks === 'function') {
388            initLinesBlocks();
389          }
390        }, 100);
391      }).catch(function (error) {
392        popupContent.innerHTML = "";
393        popupContent.appendChild(popupClose);
394        var errorDiv = document.createElement("div");
395        errorDiv.className = "popup-error";
396        errorDiv.textContent = "Ошибка загрузки формы";
397        popupContent.appendChild(errorDiv);
398        console.error("Popup form error:", error);
399      });
400    };
401    this.closePopup = function () {
402      popupOverlay.style.display = "none";
403      popupContent.innerHTML = "";
404      popupContent.appendChild(popupClose);
405    };
406    var popupButtons = document.querySelectorAll("[data-popup-form]");
407    popupButtons.forEach(function (button) {
408      button.addEventListener("click", function (e) {
409        e.preventDefault();
410        var formName = button.getAttribute("data-popup-form");
411        _this.openPopup(formName, button);
412      });
413    });
414  },
415  PhoneMask: function PhoneMask() {
416    function initPhoneInput(inputElement) {
417      var _inputElement$closest;
418      if (!inputElement) return null;
419      var $input = $(inputElement);
420      var iti = window.intlTelInput(inputElement, {
421        initialCountry: "ru",
422        onlyCountries: ["ru", "am", "az", "by", "kg", "kz", "md", "tj", "tm", "uz"],
423        strictMode: false,
424        separateDialCode: false,
425        autoPlaceholder: "off",
426        countrySearch: false,
427        i18n: window.intlTelInputI18n,
428        customPlaceholder: function customPlaceholder() {
429          return '';
430        }
431      });
432      $.mask.definitions['9'] = false;
433      $.mask.definitions['1'] = "[0-9]";
434      var maskConfigs = {
435        "ru": {
436          mask: "+7 (111) 111-11-11",
437          placeholder: "+7 (912) 345-67-89",
438          dialCode: "7"
439        },
440        "am": {
441          mask: "+374 (111) 111-111",
442          placeholder: "+374 (77) 123-456",
443          dialCode: "374"
444        },
445        "az": {
446          mask: "+994 (111) 111-11-11",
447          placeholder: "+994 (50) 123-45-67",
448          dialCode: "994"
449        },
450        "by": {
451          mask: "+375 (111) 11-111-11",
452          placeholder: "+375 (29) 123-45-67",
453          dialCode: "375"
454        },
455        "kg": {
456          mask: "+996 (111) 111-111",
457          placeholder: "+996 (550) 123-456",
458          dialCode: "996"
459        },
460        "kz": {
461          mask: "+7 (111) 111-11-11",
462          placeholder: "+7 (701) 234-56-78",
463          dialCode: "7"
464        },
465        "md": {
466          mask: "+373 (111) 11-111",
467          placeholder: "+373 (60) 123-456",
468          dialCode: "373"
469        },
470        "tj": {
471          mask: "+992 (111) 11-111-11",
472          placeholder: "+992 (93) 456-78-90",
473          dialCode: "992"
474        },
475        "tm": {
476          mask: "+993 (111) 11-11-11",
477          placeholder: "+993 (61) 234-56-78",
478          dialCode: "993"
479        },
480        "uz": {
481          mask: "+998 (111) 111-11-11",
482          placeholder: "+998 (90) 123-45-67",
483          dialCode: "998"
484        }
485      };
486      function applyMask(countryCode) {
487        var clearValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
488        var config = maskConfigs[countryCode] || maskConfigs.ru;
489        var hadFocus = document.activeElement === inputElement;
490        $input.unmask();
491        $input.mask(config.mask);
492        $input.attr('placeholder', config.placeholder);
493        if (clearValue) {
494          $input.val("");
495        }
496        if (hadFocus) {
497          $input.focus();
498          $input[0].setSelectionRange(0, 0);
499        }
500      }
501      function formatedPhone(value) {
502        if (!value) return '';
503        var digits = value.replace(/\D/g, '');
504        for (var countryCode in maskConfigs) {
505          var dialCode = maskConfigs[countryCode].dialCode;
506          if (digits.startsWith(dialCode)) {
507            return digits.substring(dialCode.length);
508          }
509        }
510        if (digits.startsWith('8')) {
511          return digits.substring(1);
512        }
513        return digits;
514      }
515      inputElement.value = formatedPhone(inputElement.value);
516      applyMask(iti.getSelectedCountryData().iso2);
517      var flagContainer = (_inputElement$closest = inputElement.closest('.iti')) === null || _inputElement$closest === void 0 ? void 0 : _inputElement$closest.querySelector('.iti__flag-container');
518      if (flagContainer) {
519        var dropdownOpening = false;
520        flagContainer.addEventListener('mousedown', function (e) {
521          dropdownOpening = true;
522          setTimeout(function () {
523            return dropdownOpening = false;
524          }, 1000);
525        });
526        flagContainer.addEventListener('click', function (e) {
527          if (dropdownOpening) {
528            var newCountryCode = iti.getSelectedCountryData().iso2;
529            applyMask(newCountryCode);
530          }
531        });
532      }
533      $input.on("countrychange", function () {
534        applyMask(iti.getSelectedCountryData().iso2, true);
535      });
536      return iti;
537    }
538    $(document).ready(function () {
539      $("input[data-phone-mask]").each(function () {
540        initPhoneInput(this);
541      });
542    });
543  },
544  NumberMask: function NumberMask() {
545    function initNumberInput(inputElement) {
546      if (!inputElement) return null;
547      var $input = $(inputElement);
548      var digitsCount = parseInt($input.attr("data-number-mask")) || 0;
549      if (digitsCount > 0) {
550        var maskPattern = "9".repeat(digitsCount);
551        $input.mask(maskPattern);
552      }
553      return $input;
554    }
555    $(document).ready(function () {
556      $("input[data-number-mask]").each(function () {
557        initNumberInput(this);
558      });
559    });
560  },
561  CatalogSection: function CatalogSection() {
562    $(document).on("click", ".catalog-options__sort-box", function () {
563      var $btn = $(this).find("> button"),
564        $list = $(this).find(".catalog-options__sort-list");
565      $btn.toggleClass("open");
566      $list.toggleClass("open");
567    });
568    $(document).on("click", function (e) {
569      var $target = $(e.target),
570        $box = $(".catalog-options__sort-box"),
571        $list = $box.find(".catalog-options__sort-list"),
572        $btn = $box.find("button");
573      var $out = !$target.closest($box).length && !$target.closest($list).length && $list.is(":visible");
574      if ($out === true) {
575        $list.removeClass("open");
576        $btn.removeClass("open");
577      }
578    });
579  },
580  Basket: function Basket() {
581    var btnTemplate = "<button class=\"catalog-product__buy btn btn--cart\" type=\"button\" data-basket-add=\"###\">\n                <u>\u041A\u0443\u043F\u0438\u0442\u044C</u>\n            </button>";
582    var quantityTemplate = "<div class=\"catalog-product__quantity-xs icon-basket-xs\">\n                    <svg><use xlink:href=\"#icon-basket-xs\"></use></svg>\n                </div>\n                <div class=\"catalog-product__quantity\" data-id=\"###\">\n                <div data-spin-box-field data-min=\"1\" data-max=\"999\">\n                    <input type=\"number\" min=\"1\" max=\"999\" value=\"1\" readonly>\n                    <button type=\"button\" class=\"arrow-up\" data-up>+</button>\n                    <button type=\"button\" class=\"arrow-down\" data-down>-</button>\n                </div>\n            </div>";
583    addBasketEvents();
584    function addBasketEvents() {
585      document.querySelectorAll("[data-basket-add]").forEach(function (btn) {
586        if (!btn.initAdd) {
587          btn.addEventListener("click", /*#__PURE__*/function () {
588            var _ref = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(e) {
589              var html;
590              return _regenerator().w(function (_context) {
591                while (1) switch (_context.n) {
592                  case 0:
593                    e.preventDefault();
594                    _context.n = 1;
595                    return Site.basketAction("add", {
596                      id: btn.dataset.basketAdd
597                    });
598                  case 1:
599                    Site.basketUpdateHeader();
600                    Site.basketUpdateMobileFooter();
601                    html = document.createRange().createContextualFragment(quantityTemplate.replace("###", btn.dataset.basketAdd));
602                    btn.replaceWith(html);
603                    addBasketEvents();
604                  case 2:
605                    return _context.a(2);
606                }
607              }, _callee);
608            }));
609            return function (_x) {
610              return _ref.apply(this, arguments);
611            };
612          }());
613        }
614      });
615      document.querySelectorAll(".catalog-product__quantity").forEach(function (block) {
616        if (!block.initQuantity) {
617          var up = block.querySelector(".arrow-up");
618          var down = block.querySelector(".arrow-down");
619          var input = block.querySelector("input");
620          var basketId = block.closest("[data-id]").dataset.id;
621          block.initQuantity = true;
622          up.addEventListener("click", /*#__PURE__*/function () {
623            var _ref2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2(e) {
624              return _regenerator().w(function (_context2) {
625                while (1) switch (_context2.n) {
626                  case 0:
627                    _context2.n = 1;
628                    return Site.basketAction("update", {
629                      id: basketId,
630                      quantity: parseInt(input.value) + 1
631                    });
632                  case 1:
633                    Site.basketUpdateHeader();
634                    Site.basketUpdateMobileFooter();
635                  case 2:
636                    return _context2.a(2);
637                }
638              }, _callee2);
639            }));
640            return function (_x2) {
641              return _ref2.apply(this, arguments);
642            };
643          }());
644          down.addEventListener("click", /*#__PURE__*/function () {
645            var _ref3 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3(e) {
646              var html;
647              return _regenerator().w(function (_context3) {
648                while (1) switch (_context3.n) {
649                  case 0:
650                    if (!(parseInt(input.value) - 1 > 0)) {
651                      _context3.n = 2;
652                      break;
653                    }
654                    _context3.n = 1;
655                    return Site.basketAction("update", {
656                      id: basketId,
657                      quantity: parseInt(input.value) - 1
658                    });
659                  case 1:
660                    _context3.n = 4;
661                    break;
662                  case 2:
663                    _context3.n = 3;
664                    return Site.basketAction("remove", {
665                      id: basketId
666                    });
667                  case 3:
668                    html = document.createRange().createContextualFragment(btnTemplate.replace("###", basketId));
669                    block.replaceWith(html);
670                    addBasketEvents();
671                  case 4:
672                    Site.basketUpdateHeader();
673                    Site.basketUpdateMobileFooter();
674                  case 5:
675                    return _context3.a(2);
676                }
677              }, _callee3);
678            }));
679            return function (_x3) {
680              return _ref3.apply(this, arguments);
681            };
682          }());
683        }
684      });
685    }
686  },
687  Order: function Order() {
688    var elOrderMake = document.querySelector(".cart-page");
689    if (!elOrderMake) return;
690    addBasketEvents();
691    addOrderEvents();
692    summaryScroll();
693    elOrderMake.addEventListener("submit", updateForm.bind(null, "Y"));
694    document.addEventListener("scroll", summaryScroll);
695    function addBasketEvents() {
696      var _elOrderMake$querySel, _elOrderMake$querySel2;
697      elOrderMake.querySelectorAll(".cart-page__cart-item__quantity").forEach(function (quantity) {
698        var up = quantity.querySelector(".arrow-up");
699        var down = quantity.querySelector(".arrow-down");
700        var input = quantity.querySelector("input");
701        var basketId = quantity.closest("[data-id]").dataset.id;
702        up.addEventListener("click", /*#__PURE__*/function () {
703          var _ref4 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4(e) {
704            return _regenerator().w(function (_context4) {
705              while (1) switch (_context4.n) {
706                case 0:
707                  _context4.n = 1;
708                  return Site.orderAction("update", {
709                    id: basketId,
710                    quantity: parseInt(input.value) + 1
711                  });
712                case 1:
713                  Site.basketUpdateHeader();
714                  Site.basketUpdateMobileFooter();
715                  updateForm("N");
716                case 2:
717                  return _context4.a(2);
718              }
719            }, _callee4);
720          }));
721          return function (_x4) {
722            return _ref4.apply(this, arguments);
723          };
724        }());
725        down.addEventListener("click", /*#__PURE__*/function () {
726          var _ref5 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee5(e) {
727            return _regenerator().w(function (_context5) {
728              while (1) switch (_context5.n) {
729                case 0:
730                  if (!(parseInt(input.value) - 1 > 0)) {
731                    _context5.n = 2;
732                    break;
733                  }
734                  _context5.n = 1;
735                  return Site.orderAction("update", {
736                    id: basketId,
737                    quantity: parseInt(input.value) - 1
738                  });
739                case 1:
740                  _context5.n = 3;
741                  break;
742                case 2:
743                  _context5.n = 3;
744                  return Site.orderAction("remove", {
745                    id: [basketId]
746                  });
747                case 3:
748                  Site.basketUpdateHeader();
749                  Site.basketUpdateMobileFooter();
750                  updateForm("N");
751                case 4:
752                  return _context5.a(2);
753              }
754            }, _callee5);
755          }));
756          return function (_x5) {
757            return _ref5.apply(this, arguments);
758          };
759        }());
760      });
761      (_elOrderMake$querySel = elOrderMake.querySelector("[data-select-all]")) === null || _elOrderMake$querySel === void 0 || _elOrderMake$querySel.addEventListener("input", function (e) {
762        elOrderMake.querySelectorAll("[data-select-item]").forEach(function (el) {
763          el.checked = e.target.checked;
764        });
765      });
766      (_elOrderMake$querySel2 = elOrderMake.querySelector("[data-delete-items]")) === null || _elOrderMake$querySel2 === void 0 || _elOrderMake$querySel2.addEventListener("click", /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee6() {
767        var ids;
768        return _regenerator().w(function (_context6) {
769          while (1) switch (_context6.n) {
770            case 0:
771              ids = [];
772              elOrderMake.querySelectorAll("[data-select-item]:checked").forEach(function (input) {
773                ids.push(input.closest("[data-id]").dataset.id);
774              });
775              _context6.n = 1;
776              return Site.orderAction("remove", {
777                id: ids
778              });
779            case 1:
780              updateForm("N");
781            case 2:
782              return _context6.a(2);
783          }
784        }, _callee6);
785      })));
786    }
787    function addOrderEvents() {
788      elOrderMake.querySelectorAll("[name=DELIVERY_ID]").forEach(function (input) {
789        input.addEventListener("input", updateForm.bind(null, "N"));
790      });
791      elOrderMake.querySelectorAll("[name=PAY_SYSTEM_ID]").forEach(function (input) {
792        input.addEventListener("input", updateForm.bind(null, "N"));
793      });
794    }
795    function summaryScroll() {
796      var $scrollBlock = $(".cart-page__summary"),
797        offset = 124;
798      if (!$scrollBlock.hasClass("stick")) {
799        if (!Site.SetIsMobile()) {
800          if ($scrollBlock.length) {
801            if (pageYOffset > offset && !$scrollBlock.hasClass("fixed")) {
802              $scrollBlock.addClass("fixed");
803            } else if (pageYOffset < offset && $scrollBlock.hasClass("fixed")) {
804              $scrollBlock.removeClass("fixed");
805            }
806          }
807        }
808      }
809    }
810    function updateForm() {
811      return _updateForm.apply(this, arguments);
812    }
813    function _updateForm() {
814      _updateForm = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee7() {
815        var confirm,
816          e,
817          fd,
818          html,
819          jsonHtml,
820          _args7 = arguments;
821        return _regenerator().w(function (_context7) {
822          while (1) switch (_context7.n) {
823            case 0:
824              confirm = _args7.length > 0 && _args7[0] !== undefined ? _args7[0] : "N";
825              e = _args7.length > 1 ? _args7[1] : undefined;
826              if (e) e.preventDefault();
827              fd = new FormData(elOrderMake);
828              fd.append("confirmorder", confirm);
829              fd.append("is_ajax_post", "Y");
830              elOrderMake.classList.add("is-loading");
831              _context7.n = 1;
832              return fetch(location, {
833                method: "post",
834                body: fd
835              }).then(function (response) {
836                return response.text();
837              }).then(function (response) {
838                return response;
839              }).catch(function (response) {
840                console.log("error", response);
841                return "";
842              });
843            case 1:
844              html = _context7.v;
845              if (isJson(html)) {
846                jsonHtml = JSON.parse(html);
847                if (jsonHtml && jsonHtml.LINK) {
848                  location.href = jsonHtml.LINK;
849                }
850              } else {
851                elOrderMake.innerHTML = html;
852                addBasketEvents();
853                addOrderEvents();
854                summaryScroll();
855                Site.PhoneMask();
856                elOrderMake.classList.remove("is-loading");
857              }
858            case 2:
859              return _context7.a(2);
860          }
861        }, _callee7);
862      }));
863      return _updateForm.apply(this, arguments);
864    }
865    function isJson(str) {
866      try {
867        JSON.parse(str);
868      } catch (e) {
869        return false;
870      }
871      return true;
872    }
873  },
874  Auth: function Auth() {
875    document.querySelectorAll(".forms form").forEach(function (form) {
876      form.addEventListener("submit", /*#__PURE__*/function () {
877        var _ref7 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee8(e) {
878          var messages, response;
879          return _regenerator().w(function (_context8) {
880            while (1) switch (_context8.n) {
881              case 0:
882                e.preventDefault();
883                messages = form.querySelector(".form-message");
884                messages === null || messages === void 0 || messages.classList.remove("is-show");
885                form.querySelectorAll(".is-error").forEach(function (el) {
886                  el.classList.remove("is-error");
887                });
888                _context8.n = 1;
889                return fetch(form.action, {
890                  method: "post",
891                  body: new FormData(form)
892                }).then(function (response) {
893                  return response.json();
894                }).then(function (response) {
895                  console.log(response);
896                  if (response.result === true && response.action === 'remember') {
897                    var emailVal = document.getElementById('email').value;
898                    localStorage.setItem('tempEmail', emailVal);
899                  }
900                  if (response.result === true && response.action === 'change') {
901                    var newhref = form.querySelector(".forms.change .form-button.btn");
902                    newhref.innerHTML = 'Войти';
903                    newhref.addEventListener('click', function () {
904                      var password = document.getElementById('confirm-password').value;
905                      localStorage.setItem('tempNewPassword', password);
906                      window.location.href = '/profile/';
907                    });
908                  }
909                  return response;
910                }).catch(function (response) {
911                  return {
912                    result: false,
913                    heading: "Ошибка!",
914                    message: response
915                  };
916                });
917              case 1:
918                response = _context8.v;
919                if (response.redirect) {
920                  location.href = response.redirect;
921                }
922                if (response.messages) {
923                  messages.innerHTML = response.messages.join("<br>");
924                  messages.classList.add("is-show");
925                }
926                if (response.errors) {
927                  response.errors.forEach(function (field) {
928                    var _form$querySelector;
929                    if (field === 'Неверное контрольное слово.<br>') {
930                      messages.innerHTML = messages.innerHTML + 'Неверное контрольное слово.<br>';
931                      field = 'CHECKWORD';
932                    }
933                    (_form$querySelector = form.querySelector("[name=".concat(field, "]"))) === null || _form$querySelector === void 0 || _form$querySelector.classList.add("form__input--error");
934                  });
935                }
936              case 2:
937                return _context8.a(2);
938            }
939          }, _callee8);
940        }));
941        return function (_x6) {
942          return _ref7.apply(this, arguments);
943        };
944      }());
945    });
946  },
947  FormRating: function FormRating() {
948    document.addEventListener('click', function (e) {
949      var star = e.target.closest('.form-rating-star');
950      if (star) {
951        var container = star.closest('.form-rating-stars');
952        if (container) {
953          var ratingStars = container.querySelectorAll('.form-rating-star');
954          var ratingInput = document.getElementById('form_rating_value');
955          var selectedRating = parseInt(star.getAttribute('data-rating'));
956          if (ratingInput) {
957            ratingInput.value = selectedRating;
958          }
959          ratingStars.forEach(function (s, index) {
960            var starRating = index + 1;
961            if (starRating <= selectedRating) {
962              s.classList.add('icon-star--active');
963            } else {
964              s.classList.remove('icon-star--active');
965            }
966          });
967        }
968      }
969    });
970  },
971  basketAction: function basketAction(action) {
972    var _arguments = arguments;
973    return _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee9() {
974      var data;
975      return _regenerator().w(function (_context9) {
976        while (1) switch (_context9.n) {
977          case 0:
978            data = _arguments.length > 1 && _arguments[1] !== undefined ? _arguments[1] : [];
979            _context9.n = 1;
980            return fetch("/local/ajax/basket.php", {
981              method: "post",
982              headers: {
983                "Content-Type": "application/json"
984              },
985              body: JSON.stringify({
986                action: action,
987                data: data
988              })
989            }).catch(function (response) {
990              console.log("basketAction", response);
991            });
992          case 1:
993            return _context9.a(2);
994        }
995      }, _callee9);
996    }))();
997  },
998  basketUpdateHeader: function basketUpdateHeader() {
999    return _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee0() {
1000      var html, basket;
1001      return _regenerator().w(function (_context0) {
1002        while (1) switch (_context0.n) {
1003          case 0:
1004            _context0.n = 1;
1005            return fetch("/local/ajax/view/header-basket.php").then(function (response) {
1006              return response.text();
1007            }).then(function (response) {
1008              return response;
1009            }).catch(function (response) {
1010              console.log("basketUpdateHeader", response);
1011            });
1012          case 1:
1013            html = _context0.v;
1014            basket = document.createRange().createContextualFragment(html);
1015            document.querySelectorAll(".header-large__icon--basket").forEach(function (el) {
1016              el.replaceWith(basket.cloneNode(true));
1017            });
1018          case 2:
1019            return _context0.a(2);
1020        }
1021      }, _callee0);
1022    }))();
1023  },
1024  basketUpdateMobileFooter: function basketUpdateMobileFooter() {
1025    return _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee1() {
1026      var html, basket;
1027      return _regenerator().w(function (_context1) {
1028        while (1) switch (_context1.n) {
1029          case 0:
1030            _context1.n = 1;
1031            return fetch("/local/ajax/view/mobile-basket.php").then(function (response) {
1032              return response.text();
1033            }).then(function (response) {
1034              return response;
1035            }).catch(function (response) {
1036              console.log("basketUpdateMobileFooter", response);
1037            });
1038          case 1:
1039            html = _context1.v;
1040            basket = document.createRange().createContextualFragment(html);
1041            document.querySelectorAll(".footer-mobile-menu__item-basket").forEach(function (el) {
1042              el.replaceWith(basket.cloneNode(true));
1043            });
1044          case 2:
1045            return _context1.a(2);
1046        }
1047      }, _callee1);
1048    }))();
1049  },
1050  orderAction: function orderAction(action) {
1051    var _arguments2 = arguments;
1052    return _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee10() {
1053      var data;
1054      return _regenerator().w(function (_context10) {
1055        while (1) switch (_context10.n) {
1056          case 0:
1057            data = _arguments2.length > 1 && _arguments2[1] !== undefined ? _arguments2[1] : [];
1058            _context10.n = 1;
1059            return fetch("/local/ajax/order.php", {
1060              method: "post",
1061              body: JSON.stringify({
1062                action: action,
1063                data: data
1064              })
1065            }).catch(function (response) {
1066              console.log("orderAction", response);
1067            });
1068          case 1:
1069            return _context10.a(2);
1070        }
1071      }, _callee10);
1072    }))();
1073  },
1074  CatalogSwitchView: function CatalogSwitchView() {
1075    $(document).on('click', '[data-catalog-section-view-tile], [data-catalog-section-view-list]', function () {
1076      var btn = $(this),
1077        buttons = $('.catalog-options__view button'),
1078        mode = $(this).data('view'),
1079        view = $('.catalog-section__list');
1080      if (buttons.length) {
1081        buttons.removeClass('active');
1082        btn.addClass('active');
1083      }
1084      if (mode === 'tile') {
1085        view.removeClass('catalog-section__list--list');
1086      } else if (mode === 'list') {
1087        view.addClass('catalog-section__list--list');
1088      }
1089      //Helpers.setCookie('catalog_view_mode', mode, 1);
1090    });
1091  },
1092  AttButton: function AttButton() {
1093    $(document).on("click", ".attention-button", function (e) {
1094      var $buttonPopup = $(this).find(".attention-button-popup");
1095      $buttonPopup.toggleClass("open");
1096    });
1097    $(document).on("click", function (e) {
1098      var $target = $(e.target),
1099        $button = $(".attention-button"),
1100        $buttonPopup = $(".attention-button-popup");
1101      var $out = !$target.closest($button).length && $buttonPopup.is(":visible");
1102      if ($out === true) {
1103        $buttonPopup.removeClass("open");
1104      }
1105    });
1106  },
1107  ShareButton: function ShareButton() {
1108    $(document).on("click", ".share-button", function (e) {
1109      var $buttonPopup = $(this).find(".share-button-popup");
1110      $buttonPopup.toggleClass("open");
1111    });
1112    $(document).on("click", function (e) {
1113      var $target = $(e.target),
1114        $button = $(".share-button"),
1115        $buttonPopup = $(".share-button-popup");
1116      var $out = !$target.closest($button).length && $buttonPopup.is(":visible");
1117      if ($out === true) {
1118        $buttonPopup.removeClass("open");
1119      }
1120    });
1121  }
1122};
1123$(function () {
1124  Site.Init();
1125  Site.FixedMenu();
1126  Site.DetailDatasheet();
1127  Site.MainCatalogMenu();
1128  Site.MobileMenu();
1129  Site.FooterMenu();
1130  Site.SpinBoxField();
1131  Site.PopupForms();
1132  Site.PhoneMask();
1133  Site.CatalogSection();
1134  Site.Basket();
1135  Site.Order();
1136  Site.Auth();
1137  Site.FormRating();
1138  Site.CatalogSwitchView();
1139  Site.AttButton();
1140  Site.ShareButton();
1141});
1142
1143
1144//работаем со звуками - ИСПРАВЛЕННАЯ ВЕРСИЯ
1145$(function () {
1146  const soundSystem = {
1147    enabled: false,
1148    audioPool: [],
1149
1150    createAudio: function() {
1151      const audio = new Audio('/local/sounds/2.mp3');
1152      audio.volume = 0.7;
1153      audio.preload = 'auto';
1154      this.audioPool.push(audio);
1155      return audio;
1156    },
1157
1158    getAudio: function() {
1159      for (let audio of this.audioPool) {
1160        if (audio.paused || audio.ended || audio.currentTime > 0.5) {
1161          audio.currentTime = 0;
1162          return audio;
1163        }
1164      }
1165      return this.createAudio();
1166    },
1167
1168    enable: function() {
1169      if (this.enabled) return;
1170      this.enabled = true;
1171
1172      document.querySelectorAll('.element-detail__consultation, .floating-widget, .header-large__phone')
1173          .forEach(el => {
1174            el.addEventListener('mouseenter', () => this.playHoverSound());
1175          });
1176    },
1177
1178    playHoverSound: function() {
1179      if (!this.enabled) return;
1180      this.getAudio().play().catch(() => {});
1181    },
1182
1183    playClickSound: function() {
1184      this.getAudio().play().catch(() => {});
1185    },
1186
1187    // ОБРАБОТЧИК ТОЛЬКО ДЛЯ WIDGET (с capture)
1188    handleWidgetClick: function(event) {
1189      // Только для widget (чтобы обойти stopPropagation)
1190      let currentElement = event.target;
1191      while (currentElement && currentElement !== document) {
1192        if (currentElement.classList &&
1193            currentElement.classList.contains('floating-widget')) {
1194
1195          this.playClickSound();
1196          if (!this.enabled) this.enable();
1197
1198          // НЕ ПРЕРЫВАЕМ событие!
1199          return;
1200        }
1201        currentElement = currentElement.parentElement;
1202      }
1203    },
1204
1205    // ОБЫЧНЫЙ обработчик для всех остальных кликов
1206    handleGeneralClick: function(event) {
1207      const target = event.target;
1208
1209      // 1. Проверяем другие элементы
1210      if (target.closest('.element-detail__consultation')) {
1211        this.playClickSound();
1212        if (!this.enabled) this.enable();
1213        return;
1214      }
1215
1216      // 2. Проверяем submit кнопку
1217      if (target.tagName === 'BUTTON' &&
1218          target.type === 'submit' &&
1219          target.name === 'web_form_submit' &&
1220          target.classList.contains('form-button')) {
1221
1222        this.playClickSound();
1223        if (!this.enabled) this.enable();
1224        return;
1225      }
1226
1227      // 2. Проверяем submit кнопку
1228      /*if (target.tagName === 'BUTTON' &&
1229          target.classList.contains('contacts-page__commercial-button')) {
1230
1231        this.playClickSound();
1232        if (!this.enabled) this.enable();
1233        return;
1234      }*/
1235      if (
1236          (target.tagName === 'BUTTON' && target.classList.contains('contacts-page__commercial-button')) ||
1237          (target.tagName === 'A' && target.id === 'request_cp')||
1238          (target.tagName === 'A' && target.id === 'request_callback')
1239
1240      ) {
1241        this.playClickSound();
1242        if (!this.enabled) this.enable();
1243        return;
1244      }
1245
1246      // 4. Клик в любом месте
1247      if (!this.enabled) {
1248        this.enable();
1249      }
1250    }
1251  };
1252
1253  // Инициализация
1254  soundSystem.createAudio();
1255  soundSystem.createAudio();
1256  soundSystem.createAudio();
1257
1258  // 1. ОТДЕЛЬНЫЙ обработчик для widget С capture
1259  document.addEventListener('click', (e) => soundSystem.handleWidgetClick(e), true);
1260
1261  // 2. ОБЫЧНЫЙ обработчик для всего остального БЕЗ capture
1262  document.addEventListener('click', (e) => soundSystem.handleGeneralClick(e));
1263
1264  // 3. Делегирование для AJAX кнопок (если всё равно не работает)
1265  $(document).on('click', 'button[type="submit"][name="web_form_submit"]', function(e) {
1266    // Только если еще не обработано в handleGeneralClick
1267    if (!e.soundPlayed) {
1268      soundSystem.playClickSound();
1269      if (!soundSystem.enabled) soundSystem.enabled = true;
1270      e.soundPlayed = true;
1271    }
1272  });
1273
1274});
1275
1276
1277/*-------------------------------------*/
1278// Перехватываем все AJAX отправки форм
1279(function() {
1280  const originalFetch = window.fetch;
1281
1282  window.fetch = function(resource, init) {
1283    // Проверяем, если это отправка нашей формы
1284    if (init && init.body && document.getElementById('form_EMAIL')) {
1285      const emailField = document.getElementById('form_EMAIL');
1286      const email = emailField.value.trim();
1287      const regex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
1288
1289      if (email && !regex.test(email)) {
1290        // Показываем ошибку и блокируем отправку
1291        showError('Введите корректный E-mail');
1292        return Promise.reject(new Error('Invalid email'));
1293      }
1294    }
1295    return originalFetch.apply(this, arguments);
1296  };
1297
1298  function showError(message) {
1299    const emailField = document.getElementById('form_EMAIL');
1300    if (!emailField) return;
1301
1302    // Удаляем старую ошибку если есть
1303    const oldError = emailField.parentNode.querySelector('.email-error-absolute');
1304    if (oldError) oldError.remove();
1305
1306    // Получаем ширину поля email
1307    const rect = emailField.getBoundingClientRect();
1308    const parentRect = emailField.parentNode.getBoundingClientRect();
1309
1310    // ШИРИНА БЛОКА ОШИБКИ = ШИРИНЕ ПОЛЯ EMAIL
1311    const fieldWidth = rect.width;
1312
1313    // Создаем абсолютно позиционированную ошибку НА ВСЮ ШИРИНУ ПОЛЯ
1314    const errorDiv = document.createElement('div');
1315    errorDiv.className = 'email-error-absolute';
1316    errorDiv.style.cssText = `
1317      position: absolute;
1318      left: ${rect.left - parentRect.left}px;
1319      top: ${rect.bottom - parentRect.top + 5}px;
1320      width: ${fieldWidth}px;
1321      color: #ff0000;
1322      font-size: 12px;
1323      padding: 5px 8px;
1324      background: #fff0f0;
1325      border-radius: 3px;
1326      border: 1px solid #ff0000;
1327      z-index: 1000;
1328      box-shadow: 0 2px 5px rgba(0,0,0,0.1);
1329      white-space: normal;
1330      box-sizing: border-box;
1331      word-wrap: break-word;
1332    `;
1333    errorDiv.textContent = message;
1334
1335    // Делаем родителя относительно позиционированным
1336    if (getComputedStyle(emailField.parentNode).position === 'static') {
1337      emailField.parentNode.style.position = 'relative';
1338    }
1339
1340    // Вставляем в родителя поля
1341    emailField.parentNode.appendChild(errorDiv);
1342
1343    // Подсвечиваем поле
1344    emailField.style.borderColor = '#ff0000';
1345    emailField.style.boxShadow = '0 0 0 1px #ff0000';
1346
1347    // Фокус на поле
1348    emailField.focus();
1349
1350    // Убираем ошибку при вводе
1351    const removeError = () => {
1352      if (errorDiv.parentNode) {
1353        errorDiv.parentNode.removeChild(errorDiv);
1354      }
1355      emailField.style.borderColor = '';
1356      emailField.style.boxShadow = '';
1357    };
1358
1359    emailField.addEventListener('input', removeError, { once: true });
1360    emailField.addEventListener('focus', removeError, { once: true });
1361
1362    // Автоудаление через 5 секунд
1363    setTimeout(removeError, 5000);
1364  }
1365})();
1366
1367
1368(function() {
1369  const CONFIG = {
1370    inputSelector: '.header-large__search #title-search-input',
1371    phrases: [
1372      'Преобразователи частоты VEDA',
1373      'Преобразователи частоты SEPDRIVE',
1374      'Высоковольтные преобразователи частоты VEDADRIVE',
1375      'Устройства плавного пуска VEDA MCD',
1376      'Промышленные логические контроллеры'
1377    ],
1378    typingSpeed: 160,       // мс на символ
1379    pauseBetween: 2000,     // пауза после завершения фразы
1380    blinkInterval: 500      // интервал мигания курсора в placeholder
1381  };
1382
1383  function init() {
1384    const input = document.querySelector(CONFIG.inputSelector);
1385    if (!input) return console.error('Поле поиска не найдено');
1386
1387    // Сохраняем оригинальный placeholder (на случай сброса)
1388    const originalPlaceholder = input.placeholder;
1389
1390    let isAnimating = true;
1391    let userInputStarted = false;
1392    let currentPhraseIndex = 0;
1393    let charIndex = 0;
1394    let currentDisplayText = '';      // текст, отображаемый в placeholder (без курсора)
1395    let isCursorVisible = true;
1396
1397    let typingTimeout, blinkTimeout, pauseTimeout;
1398
1399    // Функция обновления placeholder
1400    function updatePlaceholder() {
1401      const cursor = isCursorVisible ? '|' : '';
1402      input.placeholder = currentDisplayText + cursor;
1403    }
1404
1405    // Мигание курсора
1406    function blinkCursor() {
1407      if (!isAnimating || userInputStarted) return;
1408      isCursorVisible = !isCursorVisible;
1409      updatePlaceholder();
1410      blinkTimeout = setTimeout(blinkCursor, CONFIG.blinkInterval);
1411    }
1412
1413    // Печать следующего символа
1414    function typeNextChar() {
1415      if (!isAnimating || userInputStarted) return;
1416      const phrase = CONFIG.phrases[currentPhraseIndex];
1417      if (charIndex < phrase.length) {
1418        charIndex++;
1419        currentDisplayText = phrase.substring(0, charIndex);
1420        isCursorVisible = true; // при печати курсор всегда показываем
1421        updatePlaceholder();
1422        typingTimeout = setTimeout(typeNextChar, CONFIG.typingSpeed);
1423      } else {
1424        // Фраза завершена, ждём паузу
1425        typingTimeout = null;
1426        pauseTimeout = setTimeout(() => {
1427          if (!isAnimating || userInputStarted) return;
1428          // Переход к следующей фразе
1429          currentPhraseIndex = (currentPhraseIndex + 1) % CONFIG.phrases.length;
1430          charIndex = 0;
1431          currentDisplayText = '';
1432          isCursorVisible = true;
1433          updatePlaceholder();
1434          typeNextChar();
1435        }, CONFIG.pauseBetween);
1436      }
1437    }
1438
1439    // Остановка анимации
1440    function stopAnimation(resetPlaceholder = false) {
1441      isAnimating = false;
1442      if (typingTimeout) clearTimeout(typingTimeout);
1443      if (blinkTimeout) clearTimeout(blinkTimeout);
1444      if (pauseTimeout) clearTimeout(pauseTimeout);
1445      typingTimeout = blinkTimeout = pauseTimeout = null;
1446      if (resetPlaceholder) {
1447        input.placeholder = originalPlaceholder;
1448      }
1449    }
1450
1451    // Обработчик ввода пользователем (очистка поля, остановка анимации)
1452    function handleUserInput() {
1453      if (userInputStarted) return;
1454      userInputStarted = true;
1455      stopAnimation(true);
1456      input.value = ''; // на всякий случай очищаем value
1457      // Убираем все обработчики, связанные с анимацией
1458      input.removeEventListener('input', handleUserInput);
1459      input.removeEventListener('focus', handleFocus);
1460      input.removeEventListener('blur', handleBlur);
1461    }
1462
1463    // При фокусе: просто разрешаем ввод (placeholder продолжает обновляться)
1464    function handleFocus() {
1465      if (userInputStarted) return;
1466      // Ничего не делаем, placeholder сам обновляется
1467    }
1468
1469    // При потере фокуса: тоже ничего
1470    function handleBlur() {
1471      // Не требуется
1472    }
1473
1474    // Запуск анимации
1475    function startAnimation() {
1476      isAnimating = true;
1477      userInputStarted = false;
1478      currentPhraseIndex = 0;
1479      charIndex = 0;
1480      currentDisplayText = '';
1481      isCursorVisible = true;
1482      updatePlaceholder();
1483      blinkCursor();
1484      typeNextChar();
1485    }
1486
1487    // Инициализация
1488    function setup() {
1489      // Слушаем только реальный ввод (изменение value)
1490      input.addEventListener('input', handleUserInput);
1491      // На всякий случай добавим фокус/блур, но они не нужны
1492      input.addEventListener('focus', handleFocus);
1493      input.addEventListener('blur', handleBlur);
1494
1495      startAnimation();
1496    }
1497
1498    setup();
1499  }
1500
1501  if (document.readyState === 'loading') {
1502    document.addEventListener('DOMContentLoaded', init);
1503  } else {
1504    init();
1505  }
1506})();
1507
1508
1509  (function() {
1510  // Ждём полной загрузки DOM, даже если скрипт в head
1511  function onReady(fn) {
1512    if (document.readyState !== 'loading') {
1513      fn();
1514    } else {
1515      document.addEventListener('DOMContentLoaded', fn);
1516    }
1517  }
1518
1519  onReady(function() {
1520  var popup = document.getElementById('cookies-agreement');
1521  if (!popup) {
1522  //console.warn('Cookie-согласие: блок #cookies-agreement не найден в DOM');
1523  return;
1524}
1525
1526  var btn = popup.querySelector('.cookies-agreement__button button');
1527  if (!btn) {
1528  //console.warn('Cookie-согласие: кнопка внутри .cookies-agreement__button не найдена. Проверьте разметку.');
1529  return;
1530}
1531
1532  //console.log('Cookie-согласие: кнопка найдена, вешаю обработчик.');
1533
1534  btn.addEventListener('click', function(e) {
1535  e.preventDefault(); // на случай, если кнопка обёрнута в ссылку
1536
1537  // Устанавливаем куку на 365 дней
1538  var d = new Date();
1539  d.setFullYear(d.getFullYear() + 1);
1540  document.cookie = 'cookies_accepted=1; expires=' + d.toUTCString() + '; path=/; SameSite=Lax';
1541
1542  //console.log('Cookie-согласие: кука установлена, скрываю окно.');
1543
1544  // Плавно скрываем
1545  popup.classList.add('hidden');
1546
1547  // Убираем из потока после анимации
1548  popup.addEventListener('transitionend', function handler() {
1549  popup.style.display = 'none';
1550  popup.removeEventListener('transitionend', handler);
1551  //console.log('Cookie-согласие: окно полностью скрыто.');
1552});
1553});
1554});
1555})();
1556
1557if (!window.__agreementHandlerInstalled) {
1558  window.__agreementHandlerInstalled = true;
1559
1560  document.addEventListener('submit', function (e) {
1561    var form = e.target;
1562    if (!form || form.tagName !== 'FORM') return;
1563
1564    var cb = form.querySelector('.form-agreement');
1565    if (!cb) return;
1566
1567    var wrap = cb.closest('.form-links__item') || cb.parentElement;
1568
1569    if (cb.checked) {
1570      // Галочка стоит — снимаем класс ошибки, форма уходит
1571      wrap.classList.remove('form-agreement-error');
1572      return;
1573    }
1574
1575    // Галочка не стоит — блокируем и подсвечиваем
1576    e.preventDefault();
1577    e.stopImmediatePropagation();
1578    e.stopPropagation();
1579
1580    wrap.classList.add('form-agreement-error');
1581    cb.focus();
1582  }, true);
1583
1584  // Снимаем подсветку, как только пользователь поставил галочку
1585  document.addEventListener('change', function (e) {
1586    var cb = e.target.closest && e.target.closest('.form-agreement');
1587    if (!cb) return;
1588    if (cb.checked) {
1589      var wrap = cb.closest('.form-links__item') || cb.parentElement;
1590      if (wrap) wrap.classList.remove('form-agreement-error');
1591    }
1592  }, true);
1593
1594  //console.log('[agreement] installed');
1595}
1596
1597
1598if (!window.__fileFieldsInstalled) {
1599  window.__fileFieldsInstalled = true;
1600
1601  function setupFileFields(form) {
1602  var fileInputs = form.querySelectorAll('input[type="file"]');
1603  if (fileInputs.length < 2) return;
1604
1605  // Собираем строки-обёртки для каждого файлового поля
1606    var rows = [];
1607    fileInputs.forEach(function (input) {
1608      var row = input.closest('.form-container__row.field-group');
1609      if (row) {
1610        row.classList.add('form-file-row');
1611        rows.push(row);
1612      }
1613    });
1614// Первой строке — никаких изменений, остальным — уменьшаем gap формы
1615    rows.forEach(function (row, i) {
1616      if (i > 0) row.classList.add('form-file-row--tight');
1617    });
1618    if (rows.length < 2) return;
1619
1620  // Скрываем все, кроме первой
1621  for (var i = 1; i < rows.length; i++) {
1622  rows[i].style.display = 'none';
1623  }
1624
1625  // Кнопка под первым полем
1626  var btn = document.createElement('button');
1627  btn.type = 'button';
1628  btn.className = 'form-add-file btn';
1629  btn.textContent = 'Добавить вложение';
1630  rows[0].parentNode.insertBefore(btn, rows[0].nextSibling);
1631
1632  var visibleCount = 1;
1633
1634  btn.addEventListener('click', function () {
1635  if (visibleCount >= rows.length) return;
1636  rows[visibleCount].style.display = '';
1637  visibleCount++;
1638
1639  // Переносим кнопку под новое поле
1640  rows[visibleCount - 1].parentNode.insertBefore(btn, rows[visibleCount - 1].nextSibling);
1641
1642  // Если все поля показаны — скрываем кнопку
1643  if (visibleCount >= rows.length) {
1644  btn.style.display = 'none';
1645  }
1646  });
1647  }
1648
1649  // Обрабатываем уже существующие формы
1650  document.querySelectorAll('form').forEach(setupFileFields);
1651
1652  // Следим за новыми формами (попап через ajax)
1653  var mo = new MutationObserver(function (mutations) {
1654  mutations.forEach(function (m) {
1655  m.addedNodes.forEach(function (node) {
1656  if (node.nodeType !== 1) return;
1657  if (node.tagName === 'FORM') setupFileFields(node);
1658  var forms = node.querySelectorAll ? node.querySelectorAll('form') : [];
1659  forms.forEach(setupFileFields);
1660  });
1661  });
1662  });
1663  mo.observe(document.body, { childList: true, subtree: true });
1664
1665  console.log('[file-fields] installed');
1666}

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.