// Простая таблица цен за метр (подставишь свои) const fenceTypes = { prof_one_side: { name: "Профнастил односторонний", pricePerMeter: 1500 }, prof_two_side: { name: "Профнастил двусторонний", pricePerMeter: 1900 }, euro_chess: { name: "Евроштакет шахматный", pricePerMeter: 2100 }, rabitsa: { name: "Сетка рабица", pricePerMeter: 1200 } }; // Структура аналогична простым калькуляторам ограждений.[web:23] (function () { let sideId = 0; let gateId = 0; let optionId = 0; function formatMoney(v) { return Math.round(v).toLocaleString("ru-RU") + " ₽"; } function initFenceCalculator() { const root = document.querySelector(".fence-page"); if (!root) return; // Вкладки root.querySelectorAll(".fence-tab").forEach(tab => { tab.addEventListener("click", () => { root.querySelectorAll(".fence-tab").forEach(t => t.classList.remove("fence-tab-active")); tab.classList.add("fence-tab-active"); const name = tab.dataset.tab; root.querySelectorAll(".fence-panel").forEach(p => { p.style.display = p.id === "fence-panel-" + name ? "" : "none"; }); }); }); // Кнопки root.querySelector("#fence-btn-add-side")?.addEventListener("click", () => addSide(root)); root.querySelector("#fence-btn-add-gate")?.addEventListener("click", () => addGate(root)); root.querySelector("#fence-btn-add-option")?.addEventListener("click", () => addOption(root)); root.querySelector("#fence-delivery")?.addEventListener("input", () => recalc(root)); root.querySelector("#fence-discount")?.addEventListener("input", () => recalc(root)); root.querySelector("#fence-btn-send")?.addEventListener("click", () => { recalc(root); alert("Расчёт выполнен. Здесь можно повесить отправку формы."); }); // стартовая сторона addSide(root); } function createFenceTypeSelect(root) { const select = document.createElement("select"); select.name = "type"; const def = document.createElement("option"); def.value = ""; def.textContent = "Выбрать тип"; select.appendChild(def); Object.entries(fenceTypes).forEach(([key, val]) => { const opt = document.createElement("option"); opt.value = key; opt.textContent = val.name; select.appendChild(opt); }); select.addEventListener("change", () => recalc(root)); return select; } function addSide(root) { sideId++; const container = root.querySelector("#fence-sides-container"); if (!container) return; const card = document.createElement("div"); card.className = "fence-card"; const row = document.createElement("div"); row.className = "fence-row"; const typeWrap = document.createElement("div"); typeWrap.innerHTML = 'Тип забора'; const typeSelect = createFenceTypeSelect(root); typeWrap.appendChild(typeSelect); const lenWrap = document.createElement("div"); lenWrap.innerHTML = 'Длина, м'; const lengthInput = document.createElement("input"); lengthInput.type = "number"; lengthInput.name = "length"; lengthInput.min = "0"; lengthInput.step = "0.1"; lengthInput.addEventListener("input", () => recalc(root)); lenWrap.appendChild(lengthInput); const heightWrap = document.createElement("div"); heightWrap.innerHTML = 'Высота'; const heightInput = document.createElement("input"); heightInput.type = "number"; heightInput.name = "height"; heightInput.min = "0"; heightInput.step = "0.1"; heightInput.addEventListener("input", () => recalc(root)); heightWrap.appendChild(heightInput); const actionsWrap = document.createElement("div"); const removeBtn = document.createElement("button"); removeBtn.type = "button"; removeBtn.className = "fence-ghost-icon"; removeBtn.textContent = "×"; removeBtn.addEventListener("click", () => { card.remove(); recalc(root); }); actionsWrap.appendChild(removeBtn); row.appendChild(typeWrap); row.appendChild(lenWrap); row.appendChild(heightWrap); row.appendChild(actionsWrap); card.appendChild(row); container.appendChild(card); } function addGate(root) { gateId++; const container = root.querySelector("#fence-gates-container"); if (!container) return; const card = document.createElement("div"); card.className = "fence-card"; const row = document.createElement("div"); row.className = "fence-row"; const typeWrap = document.createElement("div"); typeWrap.innerHTML = 'Тип'; const select = document.createElement("select"); select.name = "gateType"; [["", "Выбрать"], ["swing", "Распашные ворота"], ["sliding", "Откатные"], ["wicket", "Калитка"]] .forEach(([v, t]) => { const opt = document.createElement("option"); opt.value = v; opt.textContent = t; select.appendChild(opt); }); select.addEventListener("change", () => recalc(root)); typeWrap.appendChild(select); const widthWrap = document.createElement("div"); widthWrap.innerHTML = 'Ширина, м'; const w = document.createElement("input"); w.type = "number"; w.name = "gateWidth"; w.min = "0"; w.step = "0.1"; w.addEventListener("input", () => recalc(root)); widthWrap.appendChild(w); const heightWrap = document.createElement("div"); heightWrap.innerHTML = 'Высота, м'; const h = document.createElement("input"); h.type = "number"; h.name = "gateHeight"; h.min = "0"; h.step = "0.1"; h.addEventListener("input", () => recalc(root)); heightWrap.appendChild(h); const actionsWrap = document.createElement("div"); const removeBtn = document.createElement("button"); removeBtn.type = "button"; removeBtn.className = "fence-ghost-icon"; removeBtn.textContent = "×"; removeBtn.addEventListener("click", () => { card.remove(); recalc(root); }); actionsWrap.appendChild(removeBtn); row.appendChild(typeWrap); row.appendChild(widthWrap); row.appendChild(heightWrap); row.appendChild(actionsWrap); card.appendChild(row); container.appendChild(card); } function addOption(root) { optionId++; const container = root.querySelector("#fence-options-container"); if (!container) return; const card = document.createElement("div"); card.className = "fence-card"; const row = document.createElement("div"); row.className = "fence-row-small"; const nameWrap = document.createElement("div"); nameWrap.innerHTML = 'Название опции'; const nameInput = document.createElement("input"); nameInput.type = "text"; nameInput.name = "optionName"; nameWrap.appendChild(nameInput); const priceWrap = document.createElement("div"); priceWrap.innerHTML = 'Стоимость, ₽'; const priceInput = document.createElement("input"); priceInput.type = "number"; priceInput.name = "optionPrice"; priceInput.min = "0"; priceInput.step = "100"; priceInput.addEventListener("input", () => recalc(root)); priceWrap.appendChild(priceInput); const removeBtn = document.createElement("button"); removeBtn.type = "button"; removeBtn.className = "fence-ghost-icon"; removeBtn.textContent = "×"; removeBtn.addEventListener("click", () => { card.remove(); recalc(root); }); row.appendChild(nameWrap); row.appendChild(priceWrap); row.appendChild(removeBtn); card.appendChild(row); container.appendChild(card); } function recalc(root) { let sidesSum = 0; let sidesLength = 0; root.querySelectorAll("#fence-sides-container .fence-card").forEach(card => { const typeSelect = card.querySelector('select[name="type"]'); const lengthInput = card.querySelector('input[name="length"]'); const key = typeSelect?.value; const length = parseFloat((lengthInput?.value || "").replace(",", ".")); if (!key || isNaN(length) || length <= 0 || !fenceTypes[key]) return; const price = fenceTypes[key].pricePerMeter; sidesSum += price * length; sidesLength += length; }); let gatesSum = 0; root.querySelectorAll("#fence-gates-container .fence-card").forEach(card => { const typeSelect = card.querySelector('select[name="gateType"]'); const wInput = card.querySelector('input[name="gateWidth"]'); const hInput = card.querySelector('input[name="gateHeight"]'); const type = typeSelect?.value; const w = parseFloat((wInput?.value || "").replace(",", ".")); const h = parseFloat((hInput?.value || "").replace(",", ".")); if (!type || isNaN(w) || isNaN(h) || w <= 0 || h <= 0) return; const base = type === "sliding" ? 3500 : type === "swing" ? 3000 : 2000; gatesSum += w * h * base; }); let optionsSum = 0; root.querySelectorAll("#fence-options-container .fence-card").forEach(card => { const priceInput = card.querySelector('input[name="optionPrice"]'); const price = parseFloat((priceInput?.value || "").replace(",", ".")); if (!isNaN(price) && price > 0) optionsSum += price; }); const deliveryInput = root.querySelector("#fence-delivery"); const discountInput = root.querySelector("#fence-discount"); const discountError = root.querySelector("#fence-discount-error"); const delivery = parseFloat((deliveryInput?.value || "0").replace(",", ".")); const deliverySum = !isNaN(delivery) && delivery > 0 ? delivery : 0; let discount = parseFloat((discountInput?.value || "0").replace(",", ".")); let discountSum = 0; if (discountError) discountError.style.display = "none"; let subtotal = sidesSum + gatesSum + optionsSum + deliverySum; if (discountInput) { if (isNaN(discount) || discount < 0 || discount > 10) { if (discountError) discountError.style.display = "block"; discount = 0; } if (subtotal > 0 && discount > 0) { discountSum = subtotal * (discount / 100); subtotal -= discountSum; } } const total = subtotal; root.querySelector("#fence-sides-sum").textContent = formatMoney(sidesSum); root.querySelector("#fence-gates-sum").textContent = formatMoney(gatesSum); root.querySelector("#fence-options-sum").textContent = formatMoney(optionsSum); root.querySelector("#fence-delivery-sum").textContent = formatMoney(deliverySum); root.querySelector("#fence-discount-sum").textContent = discountSum ? "-" + formatMoney(discountSum) : "0 ₽"; root.querySelector("#fence-total-sum").textContent = "Итого: " + formatMoney(total); const perMeterEl = root.querySelector("#fence-total-per-meter"); if (sidesLength > 0) { const perMeter = Math.round(total / sidesLength); perMeterEl.textContent = "Цена за метр: " + perMeter.toLocaleString("ru-RU") + " ₽/м"; } else { perMeterEl.textContent = "Цена за метр: 0 ₽/м"; } } // Ждём, пока Creatium отрисует HTML-блок if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", initFenceCalculator); } else { initFenceCalculator(); } })();