/* ========================================================================== Главная страница (tpl/blocks/home.tpl, styles/home.css). Проверка и отправка форм, доступ к PDF-каталогу, «Все партнеры». Перенесено из вёрстки task3/script.js; шапка сайта прежняя, её код не нужен. ========================================================================== */ (function () { 'use strict'; /* ------------------------------------------------------------------------ Формы: проверка полей ------------------------------------------------------------------------ */ var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/; var errorId = 0; function isPhone(value) { if (!/^[+\d\s()\-]+$/.test(value)) return false; var digits = value.replace(/\D/g, ''); return digits.length >= 10 && digits.length <= 15; } function isPhoneOrEmail(value) { return EMAIL_RE.test(value) || isPhone(value); } function setError(input, message) { var wrapper = input.closest('.hp-field') || input.closest('.hp-consent'); var isConsent = wrapper.classList.contains('hp-consent'); var error = wrapper._error; wrapper.classList.add('is-invalid'); input.setAttribute('aria-invalid', 'true'); if (!error) { error = document.createElement(isConsent ? 'p' : 'span'); error.className = isConsent ? 'hp-consent-error' : 'hp-field__error'; error.id = 'hp-form-error-' + (++errorId); if (isConsent) { wrapper.insertAdjacentElement('afterend', error); } else { wrapper.appendChild(error); } wrapper._error = error; } error.textContent = message; input.setAttribute('aria-describedby', error.id); } function clearError(input) { var wrapper = input.closest('.hp-field') || input.closest('.hp-consent'); if (!wrapper || !wrapper.classList.contains('is-invalid')) return; wrapper.classList.remove('is-invalid'); input.removeAttribute('aria-invalid'); input.removeAttribute('aria-describedby'); if (wrapper._error) { wrapper._error.remove(); wrapper._error = null; } } function validate(form) { var errors = []; var name = form.elements.name; var contact = form.elements.contact; var consent = form.elements.consent; if (name.value.trim().length < 2) { errors.push([name, 'Укажите ваше имя']); } var contactValue = contact.value.trim(); if (!contactValue) { errors.push([contact, 'Укажите телефон или e-mail']); } else if (!isPhoneOrEmail(contactValue)) { errors.push([contact, 'Введите корректный телефон или e-mail']); } if (!consent.checked) { errors.push([consent, 'Необходимо согласие с политикой конфиденциальности']); } [name, contact, consent].forEach(clearError); errors.forEach(function (item) { setError(item[0], item[1]); }); if (errors.length) errors[0][0].focus(); return errors.length === 0; } function showStatus(form, type, message) { var status = form.querySelector('.hp-form-status'); if (!status) return; status.hidden = false; status.className = 'hp-form-status hp-form-status--' + type; status.textContent = message; } function hideStatus(form) { var status = form.querySelector('.hp-form-status'); if (status) status.hidden = true; } function setBusy(form, busy) { var button = form.querySelector('[type="submit"]'); form.dataset.busy = busy ? '1' : ''; button.disabled = busy; button.classList.toggle('is-loading', busy); button.setAttribute('aria-busy', String(busy)); } // Отправка на обработчик сайта (CtaController): ответ — JSON {success, message} function send(form) { return fetch(form.dataset.endpoint, { method: 'POST', body: new FormData(form), headers: { 'X-Requested-With': 'XMLHttpRequest' }, credentials: 'same-origin' }).then(function (response) { if (!response.ok) throw new Error('HTTP ' + response.status); return response.json(); }).then(function (data) { if (!data || !data.success) { var error = new Error('server'); error.serverMessage = data && data.message; throw error; } return data; }); } function initForm(form, onSuccess, errorMessage) { // ошибка поля снимается, как только его исправляют form.addEventListener('input', function (event) { clearError(event.target); }); form.addEventListener('change', function (event) { if (event.target.type === 'checkbox') clearError(event.target); }); form.addEventListener('submit', function (event) { event.preventDefault(); if (form.dataset.busy) return; // защита от повторного нажатия hideStatus(form); if (!validate(form)) return; setBusy(form, true); send(form) .then(function () { onSuccess(form); }) .catch(function (error) { showStatus(form, 'error', error.serverMessage || errorMessage); }) .then(function () { setBusy(form, false); }); }); } /* ------------------------------------------------------------------------ Форма «Изготовим по вашим размерам» ------------------------------------------------------------------------ */ var orderForm = document.querySelector('.hp [data-form="order"]'); if (orderForm) { var fileInput = orderForm.querySelector('[data-file-input]'); var fileList = orderForm.querySelector('[data-file-list]'); var renderFiles = function () { var names = Array.prototype.map.call(fileInput.files, function (file) { return file.name; }); fileList.hidden = names.length === 0; fileList.textContent = names.length ? 'Прикреплено: ' + names.join(', ') : ''; }; fileInput.addEventListener('change', renderFiles); initForm(orderForm, function (form) { form.reset(); renderFiles(); showStatus(form, 'success', 'Спасибо! Заявка отправлена — мы рассчитаем стоимость и свяжемся с вами.'); }, 'Не удалось отправить заявку. Данные и файлы сохранены — попробуйте ещё раз.'); } /* ------------------------------------------------------------------------ Форма каталога: доступ к PDF ------------------------------------------------------------------------ */ var ACCESS_KEY = 'cporu_catalog_access'; var catalogForm = document.querySelector('.hp [data-form="catalog"]'); var catalogAccess = document.querySelector('.hp [data-catalog-access]'); // признак доступа храним и в localStorage, и в cookie — чтобы он пережил очистку одного из них function hasAccess() { try { if (window.localStorage.getItem(ACCESS_KEY) === '1') return true; } catch (e) { /* хранилище недоступно */ } return document.cookie.split('; ').indexOf(ACCESS_KEY + '=1') !== -1; } function grantAccess() { try { window.localStorage.setItem(ACCESS_KEY, '1'); } catch (e) { /* хранилище недоступно */ } document.cookie = ACCESS_KEY + '=1; max-age=31536000; path=/; SameSite=Lax'; } function unlockCatalogs() { document.documentElement.classList.add('has-catalog-access'); if (catalogForm) catalogForm.hidden = true; if (catalogAccess) catalogAccess.hidden = false; } function downloadPdf(url) { var link = document.createElement('a'); link.href = url; link.download = ''; document.body.appendChild(link); link.click(); link.remove(); } if (catalogForm) { if (hasAccess()) unlockCatalogs(); initForm(catalogForm, function (form) { grantAccess(); unlockCatalogs(); if (form.dataset.pdf) downloadPdf(form.dataset.pdf); }, 'Не удалось отправить данные. Проверьте соединение и попробуйте ещё раз.'); } /* ------------------------------------------------------------------------ «Все партнеры»: показать логотипы сверх первых восьми ------------------------------------------------------------------------ */ var partnersToggle = document.querySelector('.hp [data-partners-toggle]'); if (partnersToggle) { partnersToggle.addEventListener('click', function () { var open = partnersToggle.getAttribute('aria-expanded') !== 'true'; Array.prototype.forEach.call(document.querySelectorAll('.hp .hp-partners__extra'), function (item) { item.hidden = !open; }); partnersToggle.setAttribute('aria-expanded', String(open)); }); } })();