// Простая таблица цен за метр (подставишь свои)
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();
}
})();