1(function () { 2 "use strict"; 3 if (window.__EDATOP_DIETQUIZ_V2__) return; 4 window.__EDATOP_DIETQUIZ_V2__ = true; 5 6 function onReady(fn) { 7 if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", fn); 8 else fn(); 9 } 10 function qs(sel, root) { return (root || document).querySelector(sel); } 11 function qsa(sel, root) { return Array.prototype.slice.call((root || document).querySelectorAll(sel)); } 12 function clamp(n, a, b) { return Math.max(a, Math.min(b, n)); } 13 14 function cleanDietQuizUrl() { 15 try { 16 var u = new URL(window.location.href); 17 var changed = false; 18 Array.from(u.searchParams.keys()).forEach(function (key) { 19 if (/^dq_/i.test(key)) { u.searchParams.delete(key); changed = true; } 20 }); 21 if (changed && window.history && history.replaceState) { 22 history.replaceState({}, document.title, u.pathname + (u.search ? u.search : "") + u.hash); 23 } 24 } catch (e) {} 25 } 26 27 function replaceQuizFromHtml(html, currentWrap, userInitiated) { 28 var doc = new DOMParser().parseFromString(html, "text/html"); 29 var next = doc.getElementById("dietquiz"); 30 if (!next) throw new Error("DietQuiz fragment not found"); 31 currentWrap.replaceWith(next); 32 cleanDietQuizUrl(); 33 initDietQuiz(next, !!userInitiated); 34 return next; 35 } 36 37 function loadQuizFragment(url, wrap, fetchOptions) { 38 var opts = fetchOptions || {}; 39 opts.credentials = "same-origin"; 40 opts.headers = Object.assign({ "X-Requested-With": "XMLHttpRequest" }, opts.headers || {}); 41 return fetch(url, opts) 42 .then(function (r) { if (!r.ok) throw new Error("HTTP " + r.status); return r.text(); }) 43 .then(function (html) { return replaceQuizFromHtml(html, wrap, true); }); 44 } 45 46 function submitQuizFormAjax(form, wrap) { 47 var method = String(form.getAttribute("method") || "get").toLowerCase(); 48 var action = form.getAttribute("action") || window.location.href; 49 var fd = new FormData(form); 50 if (method === "post") { 51 return loadQuizFragment(action, wrap, { method: "POST", body: fd }); 52 } 53 var u = new URL(action, window.location.href); 54 fd.forEach(function (v, k) { u.searchParams.set(k, v); }); 55 return loadQuizFragment(u.toString(), wrap); 56 } 57 58 function enhanceStatusSelect(select, wrap, markUserInitiated) { 59 if (!select || select.dataset.dqEnhanced === "1") return; 60 select.dataset.dqEnhanced = "1"; 61 select.classList.add("dq-status-select-native"); 62 63 var shell = document.createElement("div"); 64 shell.className = "dq-status-select"; 65 var button = document.createElement("button"); 66 button.type = "button"; 67 button.className = "dq-status-select__button"; 68 button.setAttribute("aria-haspopup", "listbox"); 69 button.setAttribute("aria-expanded", "false"); 70 var menu = document.createElement("div"); 71 menu.className = "dq-status-select__menu"; 72 menu.setAttribute("role", "listbox"); 73 74 function selectedText() { 75 var opt = select.options[select.selectedIndex]; 76 return opt ? opt.textContent.trim() : "Ðез ÑÑаÑÑÑа"; 77 } 78 function closeMenu() { 79 shell.classList.remove("is-open"); 80 var card = shell.closest ? shell.closest(".dq-citem") : null; 81 if (card) card.classList.remove("dq-citem--status-open"); 82 button.setAttribute("aria-expanded", "false"); 83 } 84 function render() { 85 button.textContent = selectedText(); 86 menu.innerHTML = ""; 87 Array.prototype.forEach.call(select.options, function (opt) { 88 var item = document.createElement("button"); 89 item.type = "button"; 90 item.className = "dq-status-select__option" + (opt.selected ? " is-selected" : ""); 91 item.setAttribute("role", "option"); 92 item.setAttribute("aria-selected", opt.selected ? "true" : "false"); 93 item.textContent = opt.textContent; 94 item.addEventListener("click", function (ev) { 95 ev.preventDefault(); 96 ev.stopPropagation(); 97 if (select.value === opt.value) { closeMenu(); return; } 98 markUserInitiated(); 99 select.value = opt.value; 100 closeMenu(); 101 select.dispatchEvent(new Event("change", { bubbles: true, cancelable: true })); 102 }); 103 menu.appendChild(item); 104 }); 105 } 106 button.addEventListener("click", function (ev) { 107 ev.preventDefault(); 108 ev.stopPropagation(); 109 var open = !shell.classList.contains("is-open");
110 qsa(".dq-status-select.is-open", wrap).forEach(function (x) { 111 if (x !== shell) { 112 x.classList.remove("is-open"); 113 var oldCard = x.closest ? x.closest(".dq-citem") : null; 114 if (oldCard) oldCard.classList.remove("dq-citem--status-open"); 115 var b = qs(".dq-status-select__button", x); 116 if (b) b.setAttribute("aria-expanded", "false"); 117 } 118 }); 119 shell.classList.toggle("is-open", open); 120 var card = shell.closest ? shell.closest(".dq-citem") : null; 121 if (card) card.classList.toggle("dq-citem--status-open", open); 122 button.setAttribute("aria-expanded", open ? "true" : "false"); 123 }); 124 shell.appendChild(button); 125 shell.appendChild(menu); 126 select.insertAdjacentElement("afterend", shell); 127 render(); 128 } 129 130 function initDietQuiz(wrap, userInitiatedFromAjax) { 131 if (!wrap || wrap.dataset.dqInitV2 === "1") return; 132 wrap.dataset.dqInitV2 = "1"; 133 134 var AUTOSCROLL_KEY = "dq_autoscroll"; 135 var userInitiated = false; 136 function markUserInitiated() { 137 userInitiated = true; 138 try { sessionStorage.setItem(AUTOSCROLL_KEY, "1"); } catch (e) {} 139 } 140 function consumeUserInitiated() { 141 try { 142 var v = sessionStorage.getItem(AUTOSCROLL_KEY); 143 sessionStorage.removeItem(AUTOSCROLL_KEY); 144 return v === "1"; 145 } catch (e) {} 146 return false; 147 } 148 userInitiated = !!userInitiatedFromAjax || consumeUserInitiated(); 149 150 function getFixedHeaderOffset() { 151 var pad = 16; 152 try { 153 var header = document.querySelector(".head-line"); 154 if (header) { 155 var cs = window.getComputedStyle(header); 156 if (cs && (cs.position === "fixed" || cs.position === "sticky")) pad += header.getBoundingClientRect().height || 0; 157 } 158 } catch (e) {} 159 return Math.max(0, Math.round(pad)); 160 } 161 162 qsa("img[data-dq-fallback]", wrap).forEach(function (img) { 163 var raw = img.getAttribute("data-dq-fallback") || ""; 164 if (!raw) return; 165 var list = raw.split("|").map(function (s) { return s.trim(); }).filter(Boolean); 166 function applyFallback() { if (list.length) { var next = list.shift(); if (next && img.src !== next) img.src = next; } } 167 img.addEventListener("error", applyFallback); 168 try { if (img.complete && img.naturalWidth === 0) applyFallback(); } catch (e) {} 169 }); 170 171 var goalInput = qs("[data-dq-goal-input]", wrap); 172 var serverStep = parseInt(wrap.getAttribute("data-dq-server-step") || "1", 10); 173 var els = { 174 steps: qsa("[data-dq-step]", wrap), 175 progress: qs(".dq-progress__bar", wrap), 176 progressLabel: qs(".dq-progress__label", wrap), 177 prevBtns: qsa("[data-dq-prev]", wrap), 178 goalCards: qsa("[data-dq-goal]", wrap) 179 }; 180 181 function scrollToQuizTop() { 182 try { 183 var rect = wrap.getBoundingClientRect(); 184 var top = rect.top + window.pageYOffset - getFixedHeaderOffset(); 185 window.scrollTo({ top: Math.max(0, top), behavior: "smooth" }); 186 } catch (e) {} 187 } 188 function scrollToStepLabel() { 189 try { 190 var el = els.progressLabel || wrap.querySelector(".dq-progress__label"); 191 if (!el) return scrollToQuizTop(); 192 var rect = el.getBoundingClientRect(); 193 var top = rect.top + window.pageYOffset - getFixedHeaderOffset(); 194 window.scrollTo({ top: Math.max(0, top), behavior: "smooth" }); 195 } catch (e) {} 196 } 197 function setStep(n, doScroll) { 198 n = clamp(n, 1, 3); 199 els.steps.forEach(function (s) { s.style.display = parseInt(s.getAttribute("data-dq-step"), 10) === n ? "" : "none"; }); 200 var pct = Math.round(((n - 1) / 2) * 100); 201 if (els.progress) els.progress.style.width = pct + "%"; 202 if (els.progressLabel) els.progressLabel.textContent = "Шаг " + n + "/3"; 203 if (doScroll && userInitiated) { if (n === 2) scrollToStepLabel(); else scrollToQuizTop(); } 204 } 205 206 els.goalCards.forEach(function (card) { 207 card.addEventListener("click", function () { 208 markUserInitiated(); 209 els.goalCards.forEach(function (c) { c.classList.remove("is-active"); }); 210 card.classList.add("is-active"); 211 if (goalInput) goalInput.value = card.getAttribute("data-dq-goal"); 212 setStep(2, true); 213 }); 214 }); 215 els.prevBtns.forEach(function (btn) { 216 btn.addEventListener("click", function () { 217 markUserInitiated(); 218 var visibleStep = 1; 219 els.steps.forEach(function (s) { if (s.style.display !== "none") visibleStep = parseInt(s.getAttribute("data-dq-step"), 10); }); 220 setStep(visibleStep - 1, true); 221 }); 222 }); 223
224 qsa('a[href*="dq_"]', wrap).forEach(function (a) { 225 var serverUrl = a.href; 226 a.setAttribute("rel", "nofollow"); 227 a.setAttribute("href", "#dietquiz"); 228 a.addEventListener("click", function (ev) { 229 ev.preventDefault(); 230 markUserInitiated(); 231 loadQuizFragment(serverUrl, wrap).catch(function () { /* keep the page in place on AJAX failure */ }); 232 }); 233 }); 234 235 var calcForm = wrap.querySelector("form.dq-formwrap"); 236 if (calcForm) { 237 calcForm.addEventListener("submit", function (ev) { 238 ev.preventDefault(); 239 markUserInitiated(); 240 submitQuizFormAjax(calcForm, wrap).catch(function () {}); 241 }); 242 } 243 244 /* Status changes: intercept before inline onchange/form.submit can reload the page. */ 245 wrap.addEventListener("change", function (ev) { 246 var select = ev.target && ev.target.closest ? ev.target.closest(".dq-statusform select") : null; 247 if (!select || !wrap.contains(select)) return; 248 ev.preventDefault(); 249 ev.stopPropagation(); 250 if (ev.stopImmediatePropagation) ev.stopImmediatePropagation(); 251 var form = select.form || select.closest("form"); 252 if (!form) return; 253 markUserInitiated(); 254 form.classList.add("is-saving"); 255 var shell = select.nextElementSibling && select.nextElementSibling.classList.contains("dq-status-select") ? select.nextElementSibling : null; 256 if (shell) shell.classList.add("is-loading"); 257 submitQuizFormAjax(form, wrap).catch(function () { 258 form.classList.remove("is-saving"); 259 if (shell) shell.classList.remove("is-loading"); 260 }); 261 }, true); 262 263 qsa(".dq-statusform select", wrap).forEach(function (select) { enhanceStatusSelect(select, wrap, markUserInitiated); }); 264 265 document.addEventListener("click", function () { 266 qsa(".dq-status-select.is-open", wrap).forEach(function (x) { 267 x.classList.remove("is-open"); 268 var card = x.closest ? x.closest(".dq-citem") : null; 269 if (card) card.classList.remove("dq-citem--status-open"); 270 var b = qs(".dq-status-select__button", x); 271 if (b) b.setAttribute("aria-expanded", "false"); 272 }); 273 }); 274 document.addEventListener("keydown", function (ev) { 275 if (ev.key === "Escape") qsa(".dq-status-select.is-open", wrap).forEach(function (x) { 276 x.classList.remove("is-open"); 277 var card = x.closest ? x.closest(".dq-citem") : null; 278 if (card) card.classList.remove("dq-citem--status-open"); 279 }); 280 }); 281 282 if (serverStep === 3) setStep(3, userInitiated); 283 else setStep(1, false); 284 } 285 286 onReady(function () { 287 cleanDietQuizUrl(); 288 initDietQuiz(document.getElementById("dietquiz"), false); 289 }); 290})();
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.