PageSourceSearch

https://axiomacapital.ru/assets/js/form.js

js axiomacapital.ru collected 2026-10-07 17:53:44 UTC 8,408 bytes, 230 lines download raw bytes

1// Глобальные переменные для функций
2var showModal;
3var hideModal;
4
5document.addEventListener("DOMContentLoaded", function () {
6  // ===== 1) Получение CSRF-токена
7  function getCsrfToken(callback) {
8    fetch("/assets/php/csrf_token.php", {
9      method: "GET",
10      headers: { "X-Requested-With": "XMLHttpRequest" },
11      credentials: "same-origin"
12    })
13      .then((res) => {
14        if (!res.ok) throw new Error("Ошибка при получении CSRF токена");
15        return res.text();
16      })
17      .then((token) => callback(token))
18      .catch((err) => {
19        console.error("Ошибка CSRF:", err);
20      });
21  }
22
23  // ===== 2) Модальное окно для результата
24  const modal = document.getElementById("modal");
25  const modalMessage = document.getElementById("modal-message");
26  const modalIcon = document.getElementById("modal-icon");
27  const modalClose = modal ? modal.querySelector(".modal__close") : null;
28
29  // Определяем глобальную функцию hideModal
30  hideModal = function () {
31    const modalElement = document.getElementById("modal");
32    if (!modalElement) return;
33    modalElement.style.display = "none";
34    modalElement.setAttribute("aria-hidden", "true");
35  };
36
37  // Определяем глобальную функцию showModal
38  showModal = function (message, isSuccess = true) {
39    const modalElement = document.getElementById("modal");
40    const modalMessageElement = document.getElementById("modal-message");
41    const modalIconElement = document.getElementById("modal-icon");
42
43    if (!modalElement || !modalMessageElement) {
44      console.error("Модальное окно не найдено на странице!");
45      return;
46    }
47
48    modalMessageElement.textContent = message;
49
50    if (modalIconElement) {
51      const iconUrl = isSuccess
52        ? "/assets/img/icons/success-icon.svg"
53        : "/assets/img/icons/error-icon.svg";
54
55      modalIconElement.src = iconUrl;
56      modalIconElement.style.display = "block";
57      modalIconElement.alt = isSuccess ? "Успех" : "Ошибка";
58    }
59
60    modalElement.style.display = "flex";
61    modalElement.setAttribute("aria-hidden", "false");
62
63    if (isSuccess) {
64      setTimeout(hideModal, 5000);
65    }
66  };
67
68  if (modalClose) {
69    modalClose.addEventListener("click", hideModal);
70  }
71
72  window.addEventListener("click", (e) => {
73    if (modal && e.target === modal) {
74      hideModal();
75    }
76  });
77
78  // Close on Escape key
79  document.addEventListener("keydown", (e) => {
80    if (e.key === "Escape" && modal && modal.style.display === "flex") {
81      hideModal();
82    }
83  });
84
85  // ===== 3) Функция для отправки формы AJAX'ом
86  function handleFormSubmit(form, csrfToken) {
87    form.addEventListener("submit", (event) => {
88      event.preventDefault();
89
90      // Disable submit button to prevent multiple submissions
91      const submitButton = form.querySelector('button[type="submit"]');
92      let originalText = "";
93      if (submitButton) {
94        submitButton.disabled = true;
95        originalText = submitButton.innerHTML;
96        submitButton.innerHTML = "<span>Отправка...</span>";
97      }
98
99      const formData = new FormData(form);
100
101      // Если нет csrf_token, допишем
102      if (!formData.has("csrf_token")) {
103        formData.append("csrf_token", csrfToken);
104      }
105
106      fetch("/assets/php/send.php", {
107        method: "POST",
108        body: formData,
109        headers: { "X-Requested-With": "XMLHttpRequest" }
110      })
111        .then((response) => {
112          if (!response.ok) throw new Error("Ошибка при отправке");
113          return response.text();
114        })
115        .then((data) => {
116          console.log("Ответ от сервера:", data);
117          if (data.includes("Сообщение отправлено успешно")) {
118            // Показываем модалку с успехом
119            showModal(
120              "Ваше сообщение успешно отправлено! Мы свяжемся с вами в ближайшее время.",
121              true
122            );
123            // Сброс формы
124            form.reset();
125
126            // Если есть файл (Форма 2/3), сбрасываем кнопки
127            const fileInput = form.querySelector('input[type="file"]');
128            const fileText = form.querySelector(".contact-form-big__file-text");
129            const fileRemoveButton = form.querySelector(".contact-form-big__file-remove");
130            if (fileInput && fileText && fileRemoveButton) {
131              fileText.textContent = "Прикрепить файл";
132              fileRemoveButton.style.display = "none";
133            }
134          } else {
135            showModal("Ошибка при отправке: " + data, false);
136          }
137        })
138        .catch((error) => {
139          console.error("Ошибка отправки:", error);
140          showModal("Ошибка при отправке: " + error.message, false);
141        })
142        .finally(() => {
143          // Re-enable submit button
144          if (submitButton) {
145            submitButton.disabled = false;
146            submitButton.innerHTML = originalText;
147          }
148        });
149    });
150  }
151
152  // ===== 4) ИНИЦИАЛИЗАЦИЯ ФОРМ
153
154  // 4.1) Форма 1 (маленькая), класс .contact-form
155  const contactFormSmall = document.querySelector(".contact-form");
156  if (contactFormSmall) {
157    const csrfInputSmall = contactFormSmall.querySelector('input[name="csrf_token"]');
158    if (csrfInputSmall && csrfInputSmall.value.trim() === "") {
159      getCsrfToken((token) => {
160        csrfInputSmall.value = token;
161        handleFormSubmit(contactFormSmall, token);
162      });
163    } else {
164      const existingToken = csrfInputSmall ? csrfInputSmall.value : "";
165      handleFormSubmit(contactFormSmall, existingToken);
166    }
167  }
168
169  // 4.2) Форма 2 (большая), если есть
170  const contactFormBig = document.querySelector(".contact-form-big:not(.contact-form-big--modal)");
171  if (contactFormBig) {
172    const csrfInputBig = contactFormBig.querySelector('input[name="csrf_token"]');
173    if (csrfInputBig && csrfInputBig.value.trim() === "") {
174      getCsrfToken((token) => {
175        csrfInputBig.value = token;
176        handleFormSubmit(contactFormBig, token);
177      });
178    } else {
179      const existingToken = csrfInputBig ? csrfInputBig.value : "";
180      handleFormSubmit(contactFormBig, existingToken);
181    }
182  }
183
184  // 4.3) Формы 3 (большие, но модальные)
185  const modalForms = document.querySelectorAll(".contact-form-big--modal");
186  if (modalForms.length > 0) {
187    getCsrfToken((token) => {
188      modalForms.forEach((form) => {
189        const csrfInput = form.querySelector('input[name="csrf_token"]');
190        if (csrfInput && csrfInput.value.trim() === "") {
191          csrfInput.value = token;
192        }
193        handleFormSubmit(form, token);
194      });
195    });
196  }
197
198  // ===== 5) Если нужно обрабатывать поле "Прикрепить файл" (для больших форм)
199  function initFileField(form) {
200    const fileInput = form.querySelector('input[type="file"]');
201    const fileRemoveButton = form.querySelector(".contact-form-big__file-remove");
202    const fileText = form.querySelector(".contact-form-big__file-text");
203    if (fileInput && fileRemoveButton && fileText) {
204      fileRemoveButton.style.display = "none";
205      fileInput.addEventListener("change", () => {
206        if (fileInput.files.length > 0) {
207          fileText.textContent = fileInput.files[0].name;
208          fileRemoveButton.style.display = "inline-block";
209        } else {
210          fileText.textContent = "Прикрепить файл";
211          fileRemoveButton.style.display = "none";
212        }
213      });
214      fileRemoveButton.addEventListener("click", () => {
215        fileInput.value = "";
216        fileText.textContent = "Прикрепить файл";
217        fileRemoveButton.style.display = "none";
218      });
219    }
220  }
221
222  // Применяем к обычной большой форме
223  if (contactFormBig) {
224    initFileField(contactFormBig);
225  }
226  // Применяем к модальным формам
227  modalForms.forEach((form) => {
228    initFileField(form);
229  });
230});

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.