1(function () { 2 "use strict"; 3 4 var PRICES_RUBLES = { 5 wallsAreaTotalPricePerSquareMeter: 3500, 6 wallPerimeterPricePerLinearMeter: 550, 7 innerCornerPricePerLinearMeter: 800, 8 outerCornerPricePerLinearMeter: 1200, 9 doorOpeningBypassPricePerUnit: 6000, 10 windowOpeningBypassPricePerUnit: 6000, 11 socketOrSwitchEmbeddedPricePerUnit: 850 12 }; 13 14 function getCalculatorRootElement() { 15 return document.querySelector('[data-calc="silent-walls"]'); 16 } 17 18 function querySelectorSafe(rootElement, selector) { 19 if (!rootElement) return null; 20 return rootElement.querySelector(selector); 21 } 22 23 function querySelectorAllSafe(rootElement, selector) { 24 if (!rootElement) return []; 25 return Array.prototype.slice.call(rootElement.querySelectorAll(selector)); 26 } 27 28 function normalizeNumericString(rawValue) { 29 if (rawValue === null || rawValue === undefined) return ""; 30 var normalizedString = String(rawValue).trim(); 31 normalizedString = normalizedString.replace(/\u00A0/g, " ").replace(/\s+/g, ""); 32 normalizedString = normalizedString.replace(/[^\d.,]/g, ""); 33 if (!normalizedString) return ""; 34 35 var hasDot = normalizedString.indexOf(".") !== -1; 36 var hasComma = normalizedString.indexOf(",") !== -1; 37 38 if (hasDot && hasComma) { 39 normalizedString = normalizedString.replace(/,/g, ""); 40 } else { 41 normalizedString = normalizedString.replace(",", "."); 42 } 43 44 return normalizedString; 45 } 46 47 function parseNumberFromInputValue(rawValue) { 48 var normalizedString = normalizeNumericString(rawValue); 49 if (!normalizedString) return 0; 50 var parsedValue = parseFloat(normalizedString); 51 if (!Number.isFinite(parsedValue)) return 0; 52 return parsedValue; 53 } 54 55 function parsePositiveIntegerFromInputValue(rawValue) { 56 var parsedInteger = Math.floor(parseNumberFromInputValue(rawValue)); 57 if (!Number.isFinite(parsedInteger)) return 0; 58 if (parsedInteger < 0) return 0; 59 return parsedInteger; 60 } 61 62 function roundToTwoDecimals(value) { 63 return Math.round(value * 100) / 100; 64 } 65 66 function formatDecimalWithComma(value) { 67 return String(roundToTwoDecimals(value)).replace(".", ","); 68 } 69 70 function formatValueWithUnit(value, unit, shouldBeInteger) { 71 if (shouldBeInteger) return String(Math.floor(value)) + " " + unit; 72 return formatDecimalWithComma(value) + " " + unit; 73 } 74 75 function formatRubles(value) { 76 var integerValue = Math.round(value); 77 return integerValue.toString().replace(/\B(?=(\d{3})+(?!\d))/g, " ") + " â½"; 78 } 79 80 function collectCalculatorInputs(calculatorRootElement) { 81 var inputElementsByFieldName = {}; 82 querySelectorAllSafe(calculatorRootElement, "[data-calc-field]").forEach(function (element) { 83 var fieldName = element.getAttribute("data-calc-field"); 84 if (!fieldName) return; 85 inputElementsByFieldName[fieldName] = element; 86 }); 87 88 var wallsAreaSquareMeters = parseNumberFromInputValue( 89 inputElementsByFieldName.wallsAreaSquareMeters ? inputElementsByFieldName.wallsAreaSquareMeters.value : 0 90 ); 91 92 var wallPerimeterLinearMeters = parseNumberFromInputValue( 93 inputElementsByFieldName.wallPerimeterLinearMeters ? inputElementsByFieldName.wallPerimeterLinearMeters.value : 0 94 ); 95 96 var innerCornerLinearMeters = parseNumberFromInputValue( 97 inputElementsByFieldName.innerCornerLinearMeters ? inputElementsByFieldName.innerCornerLinearMeters.value : 0 98 ); 99 100 var outerCornerLinearMeters = parseNumberFromInputValue( 101 inputElementsByFieldName.outerCornerLinearMeters ? inputElementsByFieldName.outerCornerLinearMeters.value : 0 102 ); 103 104 var doorOpeningsCount = parsePositiveIntegerFromInputValue( 105 inputElementsByFieldName.doorOpeningsCount ? inputElementsByFieldName.doorOpeningsCount.value : 0 106 ); 107 108 var windowOpeningsCount = parsePositiveIntegerFromInputValue( 109 inputElementsByFieldName.windowOpeningsCount ? inputElementsByFieldName.windowOpeningsCount.value : 0 110 ); 111 112 var socketAndSwitchEmbedsCount = parsePositiveIntegerFromInputValue( 113 inputElementsByFieldName.socketAndSwitchEmbedsCount ? inputElementsByFieldName.socketAndSwitchEmbedsCount.value : 0 114 ); 115 116 return { 117 wallsAreaSquareMeters: wallsAreaSquareMeters, 118 wallPerimeterLinearMeters: wallPerimeterLinearMeters, 119 innerCornerLinearMeters: innerCornerLinearMeters, 120 outerCornerLinearMeters: outerCornerLinearMeters, 121 doorOpeningsCount: doorOpeningsCount, 122 windowOpeningsCount: windowOpeningsCount, 123 socketAndSwitchEmbedsCount: socketAndSwitchEmbedsCount 124 }; 125 } 126 127 function calculateTotalPriceRubles(calculatorInputs) { 128 return ( 129 calculatorInputs.wallsAreaSquareMeters * PRICES_RUBLES.wallsAreaTotalPricePerSquareMeter + 130 calculatorInputs.wallPerimeterLinearMeters * PRICES_RUBLES.wallPerimeterPricePerLinearMeter + 131 calculatorInputs.innerCornerLinearMeters * PRICES_RUBLES.innerCornerPricePerLinearMeter + 132 calculatorInputs.outerCornerLinearMeters * PRICES_RUBLES.outerCornerPricePerLinearMeter + 133 calculatorInputs.doorOpeningsCount * PRICES_RUBLES.doorOpeningBypassPricePerUnit + 134 calculatorInputs.windowOpeningsCount * PRICES_RUBLES.windowOpeningBypassPricePerUnit + 135 calculatorInputs.socketAndSwitchEmbedsCount * PRICES_RUBLES.socketOrSwitchEmbeddedPricePerUnit 136 ); 137 } 138 139 function buildEnteredParametersRows(calculatorInputs) { 140 var rows = []; 141 142 if (calculatorInputs.wallsAreaSquareMeters > 0) rows.push("ÐлоÑÐ°Ð´Ñ ÐºÐ¾Ð¼Ð½Ð°ÑÑ: " + formatValueWithUnit(calculatorInputs.wallsAreaSquareMeters, "м²", false)); 143 if (calculatorInputs.wallPerimeterLinearMeters > 0) rows.push("ÐеÑимеÑÑ ÑÑен: " + formatValueWithUnit(calculatorInputs.wallPerimeterLinearMeters, "пог.м", false)); 144 if (calculatorInputs.innerCornerLinearMeters > 0) rows.push("ÐнÑÑÑенние ÑглÑ: " + formatValueWithUnit(calculatorInputs.innerCornerLinearMeters, "пог.м", false)); 145 if (calculatorInputs.outerCornerLinearMeters > 0) rows.push("ÐнеÑние ÑглÑ: " + formatValueWithUnit(calculatorInputs.outerCornerLinearMeters, "пог.м", false)); 146 if (calculatorInputs.doorOpeningsCount > 0) rows.push("ÐвеÑнÑе пÑоÑÐ¼Ñ 90Ã200: " + formatValueWithUnit(calculatorInputs.doorOpeningsCount, "ÑÑ.", true)); 147 if (calculatorInputs.windowOpeningsCount > 0) rows.push("ÐконнÑе пÑоÑÐ¼Ñ 140Ã140: " + formatValueWithUnit(calculatorInputs.windowOpeningsCount, "ÑÑ.", true)); 148 if (calculatorInputs.socketAndSwitchEmbedsCount > 0) rows.push("ÐакладнÑе под ÑозеÑки/вÑклÑÑаÑели: " + formatValueWithUnit(calculatorInputs.socketAndSwitchEmbedsCount, "ÑÑ.", true)); 149 150 return rows; 151 } 152 153 function renderCalculatorResult(calculatorRootElement, calculatorInputs, totalPriceRubles) { 154 var parametersInfoElement = querySelectorSafe(calculatorRootElement, '[data-calc="info"]') || querySelectorSafe(calculatorRootElement, ".calc__info"); 155 var totalElement = querySelectorSafe(calculatorRootElement, '[data-calc="total"]') || querySelectorSafe(calculatorRootElement, ".calc__total"); 156 157 var enteredParameterRows = buildEnteredParametersRows(calculatorInputs); 158 159 if (parametersInfoElement) { 160 if (enteredParameterRows.length === 0) { 161 parametersInfoElement.textContent = "*ÐÑ ÐµÑе не ввели паÑамеÑÑÑ"; 162 } else { 163 parametersInfoElement.innerHTML = enteredParameterRows.map(function (rowText) { 164 return "<div>" + rowText + "</div>"; 165 }).join(""); 166 } 167 } 168 169 if (totalElement) { 170 totalElement.textContent = "ÐТÐÐÐ: " + formatRubles(totalPriceRubles); 171 } 172 } 173
174 function setLeadPayload(totalPriceRubles, calculatorInputs) { 175 var enteredParameterRows = buildEnteredParametersRows(calculatorInputs); 176 177 var payload = { 178 totalPriceRubles: Math.round(totalPriceRubles), 179 wallsAreaSquareMeters: calculatorInputs.wallsAreaSquareMeters, 180 wallPerimeterLinearMeters: calculatorInputs.wallPerimeterLinearMeters, 181 innerCornerLinearMeters: calculatorInputs.innerCornerLinearMeters, 182 outerCornerLinearMeters: calculatorInputs.outerCornerLinearMeters, 183 doorOpeningsCount: calculatorInputs.doorOpeningsCount, 184 windowOpeningsCount: calculatorInputs.windowOpeningsCount, 185 socketAndSwitchEmbedsCount: calculatorInputs.socketAndSwitchEmbedsCount, 186 parametersText: enteredParameterRows.join("; ") 187 }; 188 189 try { 190 sessionStorage.setItem("qwalls_silent_walls_calculator_payload", JSON.stringify(payload)); 191 } catch (e) {} 192 193 window.qwallsSilentWallsCalculatorPayload = payload; 194 195 var hiddenTotalField = document.querySelector('input[name="calc_total"]'); 196 if (hiddenTotalField) hiddenTotalField.value = String(payload.totalPriceRubles); 197 198 var hiddenParametersField = document.querySelector('input[name="calc_params"]'); 199 if (hiddenParametersField) hiddenParametersField.value = payload.parametersText; 200 201 var hiddenPayloadField = document.querySelector('input[name="calc_payload"]'); 202 if (hiddenPayloadField) hiddenPayloadField.value = JSON.stringify(payload); 203 } 204 205 function isHiddenByCSS(element) { 206 if (!element) return true; 207 return element.offsetParent === null; 208 } 209 210 function initCalculator() { 211 var calculatorRootElement = getCalculatorRootElement(); 212 if (!calculatorRootElement) return; 213 214 function updateCalculator() { 215 if (isHiddenByCSS(calculatorRootElement)) return; 216 var calculatorInputs = collectCalculatorInputs(calculatorRootElement); 217 var totalPriceRubles = calculateTotalPriceRubles(calculatorInputs); 218 renderCalculatorResult(calculatorRootElement, calculatorInputs, totalPriceRubles); 219 setLeadPayload(totalPriceRubles, calculatorInputs); 220 } 221 222 querySelectorAllSafe(calculatorRootElement, "[data-calc-field]").forEach(function (inputElement) { 223 inputElement.addEventListener("input", updateCalculator); 224 inputElement.addEventListener("change", updateCalculator); 225 }); 226 227 var submitButtonElement = querySelectorSafe(calculatorRootElement, '[data-calc="submit"]'); 228 if (submitButtonElement) { 229 submitButtonElement.addEventListener("click", function () { 230 var calculatorInputs = collectCalculatorInputs(calculatorRootElement); 231 var totalPriceRubles = calculateTotalPriceRubles(calculatorInputs); 232 setLeadPayload(totalPriceRubles, calculatorInputs); 233 }); 234 } 235 236 updateCalculator(); 237 238 document.addEventListener("qwalls:calc:shown", function (e) { 239 if (!e || !e.detail) return; 240 if (e.detail === "silent-walls") updateCalculator(); 241 }); 242 } 243 244 if (document.readyState === "loading") { 245 document.addEventListener("DOMContentLoaded", initCalculator); 246 } else { 247 initCalculator(); 248 } 249})();
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.