1/** 2 * ÐонÑÑÑÑкÑÐ¾Ñ Ð·Ð°Ð¿ÑоÑа на ÑÑÑаниÑе-инÑÑÑÑменÑе (studio/engine.php). 3 * 4 * ÐонÑиг Ð»ÐµÐ¶Ð¸Ñ Ð² <script type="application/json" class="al-studio__cfg">: 5 * fields â Ð¿Ð¾Ð»Ñ (chips, select, lang, switch, range, text, textarea); 6 * tpl â Ñаблон запÑоÑа: ÑÑÑоки Ñ Ð¿Ð¾Ð´ÑÑановками {клÑÑ} и ÑÑловнÑе ÑаÑÑи 7 * {"t": "â¦", "if": "клÑÑ", "eq"/"in"/"not": â¦}. 8 * ЧаÑÑÑ Ñаблона Ñ Ð¿ÑÑÑÑм необÑзаÑелÑнÑм полем вÑÐ¿Ð°Ð´Ð°ÐµÑ Ñеликом; пÑÑÑое 9 * обÑзаÑелÑное поле показÑваеÑÑÑ Ð² пÑевÑÑ ÐºÐ°Ðº [подпиÑÑ], а запÑÐ¾Ñ Ð½Ðµ ÑÑ Ð¾Ð´Ð¸Ñ. 10 * ÐÑпÑавка â ÑеÑез ÐºÐ½Ð¾Ð¿ÐºÑ .aliviy-prompt[data-prompt] (chat-prompts.php). 11 */ 12(function () { 13 "use strict"; 14 var root = document.querySelector(".al-studio[data-slug]"); 15 if (!root) { return; } 16 var cfgEl = root.querySelector(".al-studio__cfg"); 17 var CFG; 18 try { CFG = JSON.parse(cfgEl.textContent); } catch (e) { return; } 19 20 var SLUG = root.getAttribute("data-slug"); 21 var STORE = "alStudio:" + SLUG + ":v1"; 22 function $(s, el) { return (el || root).querySelector(s); } 23 function $$(s, el) { return Array.prototype.slice.call((el || root).querySelectorAll(s)); } 24 function goal(name) { 25 if (window.ym) { try { window.ym(97565126, "reachGoal", name, { page: SLUG }); } catch (x) {} } 26 } 27 28 /* ---------- Ð¿Ð¾Ð»Ñ ---------- */ 29 var F = {}; // клÑÑ â опиÑание Ð¿Ð¾Ð»Ñ 30 CFG.fields.forEach(function (f) { F[f.k] = f; }); 31 function def(f) { 32 if (f.type === "switch") { return !!f.def; } 33 if (f.type === "range") { return f.def != null ? f.def : f.min; } 34 if (f.type === "lang") { return "Ð ÑÑÑкий"; } 35 if (f.type === "chips" && f.multi) { return [].concat(f.def || []).map(String); } 36 if (f.type === "select" && f.def == null && f.options && f.options.length) { return String(f.options[0].v); } 37 if (f.type === "chips" || f.type === "select") { return f.def != null ? String(f.def) : ""; } 38 return ""; 39 } 40 var DEF = {}, state = {}; 41 Object.keys(F).forEach(function (k) { DEF[k] = def(F[k]); }); 42 function reset() { state = JSON.parse(JSON.stringify(DEF)); } 43 reset(); 44 45 // ÑÐ¾Ñ ÑанÑннÑй вÑбоÑ: ÑолÑко ваÑианÑÑ, ÑиÑла и пеÑеклÑÑаÑели (ÑекÑÑÑ â неÑ, Ñам лиÑное) 46 try { 47 var saved = JSON.parse(localStorage.getItem(STORE) || "{}"); 48 Object.keys(saved).forEach(function (k) { 49 var f = F[k], v = saved[k]; 50 if (!f || f.type === "text" || f.type === "textarea") { return; } 51 if (f.type === "switch") { state[k] = !!v; } 52 else if (f.type === "range") { v = parseFloat(v); if (v >= f.min && v <= f.max) { state[k] = v; } } 53 else if (f.type === "lang") { if ($('select[data-k="' + k + '"] option[value="' + String(v).replace(/"/g, "") + '"]')) { state[k] = v; } } 54 else if (f.multi) { if (Array.isArray(v)) { state[k] = v.map(String).filter(function (x) { return opt(f, x); }); } } 55 else if ((f.options || []).some(function (o) { return String(o.v) === String(v); })) { state[k] = String(v); } 56 }); 57 } catch (x) {} 58 function save() { 59 try { 60 var o = {}; 61 Object.keys(F).forEach(function (k) { if (F[k].type !== "text" && F[k].type !== "textarea") { o[k] = state[k]; } }); 62 localStorage.setItem(STORE, JSON.stringify(o)); 63 } catch (x) {} 64 } 65 66 function opt(f, v) { 67 return (f.options || []).filter(function (o) { return String(o.v) === String(v); })[0]; 68 } 69 function visible(k) { 70 var row = $('.al-studio__row[data-k="' + k + '"]'); 71 return !row || !row.hidden; 72 } 73 function clean(v) { return String(v == null ? "" : v).replace(/[ \t]+/g, " ").replace(/\n{3,}/g, "\n\n").trim(); } 74 /** ÐнаÑение Ð´Ð»Ñ Ð¿Ð¾Ð´ÑÑановки в запÑÐ¾Ñ ("" â поле пÑÑÑое или ÑкÑÑÑо). */ 75 function phrase(k) { 76 var f = F[k]; 77 if (!f || !visible(k)) { return ""; } 78 var v = state[k]; 79 switch (f.type) { 80 case "chips": case "select": 81 if (f.multi) { 82 var ps = (f.options || []).filter(function (o) { return v.indexOf(String(o.v)) >= 0; }).map(function (o) { return o.p != null ? o.p : o.t; }); 83 return ps.length > 1 ? ps.slice(0, -1).join(", ") + " и " + ps[ps.length - 1] : ps.join(""); 84 } 85 var o = opt(f, v); 86 return o ? (o.p != null ? o.p : o.t) : ""; 87 case "lang": 88 var el = $('select[data-k="' + k + '"]'), op = el && el.options[el.selectedIndex]; 89 return op ? op.getAttribute("data-p") : ""; 90 case "switch": return v ? (f.p != null ? f.p : f.on) : "";
91 case "range": return Number(v).toLocaleString("ru-RU"); 92 default: 93 if (f.type === "textarea") { 94 // код и ÑекÑÑÑ: оÑÑÑÑÐ¿Ñ Ð¸ поÑледний знак («;» в коде) ÑÐ¾Ñ ÑанÑем, ÑбиÑаем ÑолÑко пÑÑÑÑе ÑÑÑоки по кÑаÑм 95 return String(v == null ? "" : v).replace(/^\s*\n/, "").replace(/\s+$/, ""); 96 } 97 v = clean(v); 98 // внеÑние кавÑÑки Ñнимаем, ÑолÑко еÑли веÑÑ ÑекÑÑ â одна ÑиÑаÑа: «Ñлово «маÑк»» не ÑÑогаем 99 if (/^[«"ââ]/.test(v) && /[»"â]$/.test(v) && (v.match(/[«»"âââ]/g) || []).length === 2) { v = v.slice(1, -1).trim(); } 100 // ÑекÑÑовое поле без ÑоÑки в конÑе: Ñаблон Ñам ÑÑÐ°Ð²Ð¸Ñ Ð·Ð½Ð°ÐºÐ¸ 101 return v.replace(/[.;,\s]+$/, ""); 102 } 103 } 104 function truthy(k) { 105 var f = F[k]; 106 if (!f || !visible(k)) { return false; } 107 if (f.type === "switch") { return !!state[k]; } 108 return phrase(k) !== ""; 109 } 110 function passes(c) { 111 if (c.all && !c.all.every(passes)) { return false; } 112 if (c.any && !c.any.some(passes)) { return false; } 113 if (c.if && !truthy(c.if)) { return false; } 114 if (c.not && truthy(c.not)) { return false; } 115 var key = c.key || c.if; 116 // ÑкÑÑÑое поле Ð´Ð»Ñ ÑÑловий â пÑÑÑое, инаÑе его ÑÑаÑое знаÑение пÑоÑÐµÐºÐ°ÐµÑ Ð² ÑÑжой Ñежим 117 var sv = key && !visible(key) ? (F[key] && F[key].multi ? [] : "") : state[key], has = function (x) { return Array.isArray(sv) ? sv.indexOf(String(x)) >= 0 : String(sv) === String(x); }; 118 if (c.eq != null && !has(c.eq)) { return false; } 119 if (c.in && !c.in.some(has)) { return false; } 120 if (c.nin && c.nin.some(has)) { return false; } 121 if (c.ne != null && has(c.ne)) { return false; } 122 var nv = Array.isArray(sv) ? sv.length : parseFloat(sv); 123 if (c.gt != null && !(nv > c.gt)) { return false; } 124 if (c.lt != null && !(nv < c.lt)) { return false; } 125 return true; 126 } 127 128 /* ---------- ÑбоÑка запÑоÑа ---------- */ 129 function esc(s) { return String(s).replace(/[&<>"]/g, function (c) { return { "&": "&", "<": "<", ">": ">", '"': """ }[c]; }); } 130 function build() { 131 var text = [], html = [], missing = []; 132 CFG.tpl.forEach(function (part) { 133 var t = typeof part === "string" ? part : part.t; 134 if (typeof part !== "string" && !passes(part)) { return; } 135 t = t.replace(/([^\n ]) {2,}/g, "$1 "); 136 var drop = false, miss = []; 137 var tt = t.replace(/\{([a-z0-9_]+)(?:\|(ug|u|len|words)(?:\*([\d.]+))?)?\}/g, function (m, k, mod, mul) { 138 // {today} / {year} â даÑа из бÑаÑзеÑа: Ð±Ð¾Ñ Ñам ÑекÑÑÑÑ Ð´Ð°ÑÑ Ð½Ðµ Ð·Ð½Ð°ÐµÑ 139 if (k === "today" && !F[k]) { return new Date().toLocaleDateString("ru-RU", { day: "numeric", month: "long", year: "numeric" }).replace(/\s*г\.?$/, ""); } 140 if (k === "year" && !F[k]) { return String(new Date().getFullYear()); } 141 var v = phrase(k); 142 // {k|u} â ÑиÑло Ñ ÐµÐ´Ð¸Ð½Ð¸Ñей в нÑжном падеже: «3 года», «5 ваÑианÑов» 143 if (mod === "u" && v !== "" && F[k] && F[k].units) { v += " " + plural(state[k], F[k].units[0], F[k].units[1], F[k].units[2]); } 144 // {k|ug} â ÑодиÑелÑнÑй падеж по unitsG: Â«Ð´Ð»Ñ 1 игÑока», Â«Ð´Ð»Ñ 5 игÑоков» 145 if (mod === "ug" && v !== "" && F[k] && F[k].unitsG) { v += " " + plural(state[k], F[k].unitsG[0], F[k].unitsG[1], F[k].unitsG[2]); } 146 // {k|len*0.33} / {k|words*0.5} â длина вÑÑавленного ÑекÑÑа в Ð·Ð½Ð°ÐºÐ°Ñ /ÑÐ»Ð¾Ð²Ð°Ñ Ã Ð´Ð¾Ð»Ñ: боÑÑ Ð´Ð°Ñм гоÑовое ÑиÑло 147 if ((mod === "len" || mod === "words") && v !== "") { 148 var n = mod === "len" ? v.length : (v.match(/[A-Za-zÐ-Яа-ÑÐÑ0-9]+(?:[-'â][A-Za-zÐ-Яа-ÑÐÑ0-9]+)*/g) || []).length; 149 v = Math.max(1, Math.round(n * (mul ? parseFloat(mul) : 1))).toLocaleString("ru-RU"); 150 } 151 if (v === "") { 152 if (F[k] && F[k].req && visible(k)) { miss.push(k); return "\u0000" + k + "\u0000"; } 153 drop = true; 154 } 155 return v; 156 }); 157 if (drop) { return; } 158 miss.forEach(function (k) { if (missing.indexOf(k) < 0) { missing.push(k); } }); 159 text.push(tt.replace(/\u0000([a-z0-9_]+)\u0000/g, function (m, k) { return "[" + curLabel(k).toLowerCase() + "]"; })); 160 html.push(esc(tt).replace(/\u0000([a-z0-9_]+)\u0000/g, function (m, k) { return '<span class="is-empty">[' + esc(curLabel(k).toLowerCase()) + "]</span>"; })); 161 }); 162 // многоÑÑÑоÑнÑе вÑÑавки (код, ÑекÑÑ Ð´Ð»Ñ Ð¿ÐµÑевода) â оÑделÑнÑм абзаÑем 163 // Ñклейка ÑаÑÑей: пеÑед ÑаÑÑÑÑ Ñ Ð¿ÐµÑеноÑа ÑÑÑоки пÑобел не ÑÑавим 164 function glue(list) { return list.reduce(function (acc, x) { return !acc ? x : acc + (/^\n/.test(x) ? "" : " ") + x; }, ""); } 165 var s = glue(text).replace(/([.!?â¦])([»"])\./g, "$1$2").trim();
166 var h = glue(html).replace(/([.!?â¦])([»"])\./g, "$1$2").trim(); 167 return { text: s, html: h, missing: missing }; 168 } 169 170 var out = $(".al-studio__prompt"), send = $(".al-studio__send"), err = $(".al-studio__err"), lenEl = $(".al-studio__len"); 171 var tipEl = $(".al-studio__tip"), copyBtn = $(".al-studio__copy"), resetBtn = $(".al-studio__reset"); 172 function render() { 173 applyWhen(); 174 var r = build(); 175 out.innerHTML = r.html || '<span class="is-empty">ÐÑбеÑиÑе ваÑианÑÑ Ñлева â запÑÐ¾Ñ ÑобеÑÑÑÑÑ Ð·Ð´ÐµÑÑ.</span>'; 176 lenEl.textContent = r.text ? r.text.length + " зн." : ""; 177 send.setAttribute("data-prompt", r.missing.length ? "" : r.text); 178 copyBtn.disabled = !r.text; 179 paintMore(); 180 // помоÑникам: знаÑÐµÐ½Ð¸Ñ ÐºÐ¾Ð½ÑÑÑÑкÑоÑа изменилиÑÑ (root.addEventListener("al-studio:change", â¦)) 181 try { root.dispatchEvent(new CustomEvent("al-studio:change")); } catch (x) {} 182 } 183 184 /* ---------- видимоÑÑÑ Ð¿Ð¾Ð»ÐµÐ¹: when = {"клÑÑ": ["знаÑение", â¦]} ---------- */ 185 function applyWhen() { 186 $$(".al-studio__row[data-when]").forEach(function (row) { 187 var w; try { w = JSON.parse(row.getAttribute("data-when")); } catch (x) { return; } 188 var ok = Object.keys(w).every(function (k) { 189 var need = [].concat(w[k]).map(String), v = state[k]; 190 var filled = Array.isArray(v) ? v.length > 0 : typeof v === "boolean" ? v : clean(v) !== ""; 191 if (need[0] === "*") { return filled; } 192 if (need[0] === "!") { return !filled; } 193 return [].concat(v).some(function (x) { return need.indexOf(String(x)) >= 0; }); 194 }); 195 row.hidden = !ok; 196 }); 197 // паÑа, Ñ ÐºÐ¾ÑоÑой ÑпÑÑÑÐ°Ð½Ñ Ð¾Ð±Ðµ половинÑ, не должна оÑÑавлÑÑÑ Ð¿ÑÑÑÑÑ ÑÑÑÐ¾ÐºÑ 198 $$(".al-studio__pair").forEach(function (p) { 199 p.hidden = $$(".al-studio__row", p).every(function (r) { return r.hidden; }); 200 }); 201 applyBy(); 202 } 203 204 /* ---------- подпиÑÑ, подÑказка и плейÑÑ Ð¾Ð»Ð´ÐµÑ Ð¿Ð¾ вÑбоÑÑ: by = {"k": "task", "v": {"code": {"label", "ph", "tip"}}} ---------- */ 205 function byOf(k) { 206 var f = F[k]; 207 if (!f || !f.by || !f.by.v) { return null; } 208 var v = state[f.by.k]; 209 return f.by.v[String(Array.isArray(v) ? v[0] : v)] || null; 210 } 211 function curLabel(k) { var b = byOf(k); return b && b.label ? b.label : F[k].label; } 212 function applyBy() { 213 Object.keys(F).forEach(function (k) { 214 var f = F[k]; 215 if (!f.by) { return; } 216 var b = byOf(k) || {}, row = $('.al-studio__row[data-k="' + k + '"]'); 217 if (!row) { return; } 218 var lab = row.querySelector(".al-studio__label"), q = row.querySelector(".al-q"), inp = row.querySelector(".al-studio__input"); 219 var label = b.label || f.label, tip = b.tip != null ? b.tip : (f.tip || ""), ph = b.ph != null ? b.ph : (f.ph || ""); 220 if (lab && lab.firstChild && lab.firstChild.nodeType === 3 && lab.firstChild.nodeValue !== label) { lab.firstChild.nodeValue = label; } 221 if (q && q.getAttribute("data-tip") !== tip) { q.setAttribute("data-tip", tip); q.setAttribute("aria-label", "ÐодÑказка: " + tip); q.hidden = !tip; } 222 if (inp && inp.getAttribute("placeholder") !== ph) { inp.setAttribute("placeholder", ph); } 223 }); 224 } 225 226 /* ---------- подÑказка под вÑбоÑом ---------- */ 227 function showTip(t) { tipEl.textContent = t || ""; tipEl.hidden = !t; } 228 function hintFor(k) { 229 var f = F[k]; 230 if (!f) { return ""; } 231 if (f.type === "chips" || f.type === "select") { var o = opt(f, f.multi ? state[k][state[k].length - 1] : state[k]); return o && o.hint ? o.hint : ""; } 232 if (f.type === "switch") { return state[k] ? (f.hintOn || "") : (f.hintOff || ""); } 233 return ""; 234 } 235 236 /* ---------- ÑлеменÑÑ ---------- */ 237 function paintChips(k) { 238 $$('.al-chip[data-k="' + k + '"]').forEach(function (c) { 239 var v = c.getAttribute("data-v"); 240 c.setAttribute("aria-pressed", (Array.isArray(state[k]) ? state[k].indexOf(v) >= 0 : v === String(state[k])) ? "true" : "false"); 241 }); 242 } 243 function paintSwitch(k) { 244 var b = $('.al-switch[data-k="' + k + '"]'); 245 if (!b) { return; } 246 b.setAttribute("aria-checked", state[k] ? "true" : "false"); 247 b.querySelector(".al-switch__txt").textContent = state[k] ? F[k].on : F[k].off; 248 } 249 function zone(f, v) { 250 var z = (f.zones || []).filter(function (x) { return v <= x.max; })[0]; 251 return z ? z.t : ""; 252 } 253 function plural(n, a, b, c) { 254 var d = n % 10, e = n % 100; 255 return d === 1 && e !== 11 ? a : d >= 2 && d <= 4 && (e < 12 || e > 14) ? b : c; 256 } 257 function paintRange(k) { 258 var f = F[k], rng = $('input[type=range][data-k="' + k + '"]'), num = $('[data-num="' + k + '"]'); 259 if (!rng) { return; } 260 rng.value = state[k]; 261 if (document.activeElement !== num) { num.value = state[k]; } 262 var suf = num.parentNode.querySelector(".al-range__suf"); 263 if (suf && f.units) { suf.textContent = plural(state[k], f.units[0], f.units[1], f.units[2]); } 264 var p = (rng.value - rng.min) / (rng.max - rng.min) * 100; 265 rng.style.setProperty("--p", Math.max(0, Math.min(100, p)) + "%"); 266 var z = rng.closest(".al-range").querySelector(".al-range__zone"); 267 if (z) { z.textContent = zone(f, state[k]); } 268 } 269 function paintAll() {
270 Object.keys(F).forEach(function (k) { 271 var f = F[k]; 272 if (f.type === "chips") { paintChips(k); } 273 else if (f.type === "switch") { paintSwitch(k); } 274 else if (f.type === "range") { paintRange(k); } 275 else if (f.type === "select" || f.type === "lang") { var s = $('select[data-k="' + k + '"]'); if (s) { s.value = state[k]; } } 276 else { var i = $('[data-k="' + k + '"].al-studio__input'); if (i && i.value !== state[k]) { i.value = state[k]; } } 277 }); 278 } 279 280 $$(".al-chip[data-k]").forEach(function (c) { 281 c.addEventListener("click", function () { 282 var k = c.getAttribute("data-k"); 283 var v = c.getAttribute("data-v"); 284 if (F[k].multi) { 285 var i = state[k].indexOf(v); 286 if (i >= 0) { state[k].splice(i, 1); } else { state[k].push(v); } 287 } else { state[k] = v; } 288 paintChips(k); showTip(hintFor(k)); hideErr(); save(); render(); 289 }); 290 }); 291 $$("select[data-k]").forEach(function (s) { 292 s.addEventListener("change", function () { 293 var k = s.getAttribute("data-k"); 294 state[k] = s.value; 295 showTip(F[k].type === "lang" ? (s.value === "Ð ÑÑÑкий" ? "" : "ÐÑовеÑÑÑе ÑекÑÑ Ñ Ð½Ð¾ÑиÑÐµÐ»Ñ ÑзÑка пеÑед пÑбликаÑией â оÑобенно ÑеÑминÑ.") : hintFor(k)); 296 save(); render(); 297 }); 298 }); 299 $$(".al-switch[data-k]").forEach(function (b) { 300 b.addEventListener("click", function () { 301 var k = b.getAttribute("data-k"); 302 state[k] = !state[k]; 303 paintSwitch(k); showTip(hintFor(k)); save(); render(); 304 }); 305 }); 306 $$('input[type=range][data-k]').forEach(function (rng) { 307 var k = rng.getAttribute("data-k"), f = F[k], num = $('[data-num="' + k + '"]'); 308 rng.addEventListener("input", function () { state[k] = parseFloat(rng.value); paintRange(k); render(); }); 309 rng.addEventListener("change", save); 310 num.addEventListener("input", function () { 311 var v = parseFloat(String(num.value).replace(",", ".")); 312 if (isNaN(v) || v < f.min || v > f.max) { num.classList.add("is-out"); return; } 313 num.classList.remove("is-out"); 314 state[k] = v; paintRange(k); render(); 315 }); 316 function commit() { 317 var v = parseFloat(String(num.value).replace(",", ".")); 318 if (isNaN(v)) { v = state[k]; } 319 v = Math.max(f.min, Math.min(f.max, v)); 320 num.classList.remove("is-out"); 321 state[k] = v; num.value = v; paintRange(k); render(); save(); 322 } 323 num.addEventListener("change", commit); 324 num.addEventListener("blur", commit); 325 num.addEventListener("keydown", function (e) { if (e.key === "Enter") { e.preventDefault(); num.blur(); } }); 326 num.addEventListener("wheel", function () { if (document.activeElement === num) { num.blur(); } }, { passive: true }); 327 }); 328 $$(".al-studio__input[data-k]:not(select)").forEach(function (i) { 329 var k = i.getAttribute("data-k"); 330 i.addEventListener("input", function () { state[k] = i.value; if (i.classList.contains("is-err") && clean(i.value)) { hideErr(); } render(); }); 331 if (i.tagName === "INPUT") { 332 i.addEventListener("keydown", function (e) { if (e.key === "Enter") { e.preventDefault(); send.click(); } }); 333 } 334 }); 335 336 /* ---------- «ÐÑÑ Ð½Ð°ÑÑÑойки»: ÑколÑко заполнено ---------- */ 337 function paintMore() { 338 var box = $(".al-more"); 339 if (!box) { return; } 340 var n = $$(".al-studio__row", box).filter(function (r) { 341 var k = r.getAttribute("data-k"), f = F[k]; 342 if (!f || r.hidden) { return false; } 343 if (f.type === "text" || f.type === "textarea") { return clean(state[k]) !== ""; } 344 return JSON.stringify(state[k]) !== JSON.stringify(DEF[k]); 345 }).length; 346 var c = $(".al-more__count"); 347 c.textContent = n; c.hidden = !n; 348 } 349 350 /* ---------- оÑпÑавка, копиÑование, ÑбÑÐ¾Ñ ---------- */ 351 function showErr(msg, el) { 352 err.textContent = msg; err.hidden = false; 353 if (el) { el.classList.add("is-err"); el.focus(); } 354 } 355 function hideErr() { 356 err.hidden = true; 357 $$(".is-err").forEach(function (e) { e.classList.remove("is-err"); }); 358 } 359 // пÑÑÑой запÑÐ¾Ñ Ð½Ðµ ÑÑ Ð¾Ð´Ð¸Ñ: гаÑим ÑобÑÑие до обÑего обÑабоÑÑика в chat-prompts.php 360 send.addEventListener("click", function (e) { 361 if (!send.getAttribute("data-prompt")) { 362 e.preventDefault(); e.stopPropagation(); 363 var k = build().missing[0], el = k && $('[data-k="' + k + '"].al-studio__input'); 364 showErr(k ? "ÐаполниÑе поле «" + curLabel(k) + "» â без него запÑÐ¾Ñ Ð½Ðµ ÑобÑаÑÑ." : "ÐÑбеÑиÑе ваÑианÑÑ â запÑÐ¾Ñ Ð¿Ð¾ÐºÐ° пÑÑÑой.", el); 365 return; 366 } 367 goal("studio_send"); 368 }); 369 copyBtn.addEventListener("click", function () { 370 var t = build().text; 371 if (!t) { return; } 372 function done() { copyBtn.textContent = "СкопиÑовано â"; setTimeout(function () { copyBtn.textContent = "СкопиÑоваÑÑ Ð·Ð°Ð¿ÑоÑ"; }, 1800); } 373 if (navigator.clipboard && navigator.clipboard.writeText) { navigator.clipboard.writeText(t).then(done, function () {}); } 374 else { 375 var ta = document.createElement("textarea"); 376 ta.value = t; ta.style.position = "fixed"; ta.style.opacity = "0"; 377 document.body.appendChild(ta); ta.select(); 378 try { document.execCommand("copy"); done(); } catch (x) {} 379 document.body.removeChild(ta); 380 } 381 goal("studio_copy"); 382 }); 383 resetBtn.addEventListener("click", function () { 384 reset(); 385 try { localStorage.removeItem(STORE); } catch (x) {} 386 paintAll(); hideErr(); render(); 387 showTip("ÐаÑÑÑойки ÑбÑоÑенÑ."); 388 }); 389 390 /* ---------- вкладки ---------- */ 391 var helperDone = false;
392 function openTab(key) { 393 $$(".al-studio__tab").forEach(function (t) { 394 var on = t.getAttribute("data-tab") === key; 395 t.setAttribute("aria-selected", on ? "true" : "false"); 396 t.setAttribute("tabindex", on ? "0" : "-1"); 397 $("#" + t.getAttribute("aria-controls")).hidden = !on; 398 }); 399 if (key === "help" && helperDone) { $("#al-sp-help").dispatchEvent(new CustomEvent("al-studio:open")); } 400 if (key === "help" && !helperDone) { 401 var p = $("#al-sp-help"), h; 402 try { h = JSON.parse(p.getAttribute("data-helper")); } catch (x) { h = null; } 403 var fn = h && window.AliviyStudioHelpers && window.AliviyStudioHelpers[h.type]; 404 if (fn) { fn(p, h, api); helperDone = true; } 405 goal("studio_helper"); 406 } 407 if (key === "ex") { goal("studio_examples"); } 408 } 409 $$(".al-studio__tab").forEach(function (t) { 410 t.addEventListener("click", function () { openTab(t.getAttribute("data-tab")); }); 411 }); 412 var tabsEl = $(".al-studio__tabs"); 413 if (tabsEl) { 414 tabsEl.addEventListener("keydown", function (e) { 415 var tabs = $$(".al-studio__tab"), i = tabs.indexOf(document.activeElement), n = -1; 416 if (i < 0) { return; } 417 if (e.key === "ArrowRight") { n = (i + 1) % tabs.length; } 418 else if (e.key === "ArrowLeft") { n = (i - 1 + tabs.length) % tabs.length; } 419 else if (e.key === "Home") { n = 0; } 420 else if (e.key === "End") { n = tabs.length - 1; } 421 if (n < 0) { return; } 422 e.preventDefault(); 423 openTab(tabs[n].getAttribute("data-tab")); 424 tabs[n].focus(); 425 }); 426 } 427 428 /* ---------- пÑимеÑÑ ---------- */ 429 $$("[data-ex]").forEach(function (c) { 430 c.addEventListener("click", function () { 431 var k = c.getAttribute("data-ex"); 432 $$("[data-ex]").forEach(function (x) { x.setAttribute("aria-pressed", x === c ? "true" : "false"); }); 433 $$("[data-ex-panel]").forEach(function (p) { p.hidden = p.getAttribute("data-ex-panel") !== k; }); 434 }); 435 }); 436 $$("[data-use]").forEach(function (b) { 437 var set = CFG.examples[+b.getAttribute("data-use")]; 438 if (!set) { b.hidden = true; return; } 439 b.addEventListener("click", function () { 440 reset(); 441 Object.keys(set).forEach(function (k) { if (F[k]) { state[k] = set[k]; } }); 442 paintAll(); render(); save(); 443 openTab("build"); 444 root.scrollIntoView({ behavior: "smooth", block: "start" }); 445 showTip("ÐаÑÑÑойки пÑимеÑа подÑÑÐ°Ð²Ð»ÐµÐ½Ñ â поменÑйÑе под ÑÐ²Ð¾Ñ Ð·Ð°Ð´Ð°ÑÑ."); 446 }); 447 }); 448 449 /* ---------- вÑплÑваÑÑие подÑказки «?» ---------- */ 450 var bubble = null, bubbleFor = null, bubbleY = 0; 451 function closeBubble() { if (bubble) { bubble.hidden = true; } if (bubbleFor) { bubbleFor.setAttribute("aria-expanded", "false"); } bubbleFor = null; } 452 function openBubble(b) { 453 if (!bubble) { 454 bubble = document.createElement("div"); 455 bubble.className = "al-bubble"; bubble.setAttribute("role", "tooltip"); bubble.id = "al-bubble"; 456 document.body.appendChild(bubble); 457 } 458 if (bubbleFor === b) { closeBubble(); return; } 459 closeBubble(); 460 bubble.textContent = b.getAttribute("data-tip"); 461 bubble.hidden = false; bubbleFor = b; bubbleY = window.scrollY; 462 b.setAttribute("aria-expanded", "true"); b.setAttribute("aria-describedby", "al-bubble"); 463 var r = b.getBoundingClientRect(), w = Math.min(300, window.innerWidth - 24); 464 bubble.style.width = w + "px"; 465 var left = Math.max(12, Math.min(r.left + r.width / 2 - w / 2, window.innerWidth - w - 12)), top = r.bottom + 8; 466 if (top + bubble.offsetHeight > window.innerHeight - 8) { top = r.top - bubble.offsetHeight - 8; } 467 bubble.style.left = Math.round(left) + "px"; bubble.style.top = Math.round(top) + "px"; 468 } 469 $$(".al-q").forEach(function (b) { 470 b.setAttribute("aria-expanded", "false"); 471 b.addEventListener("click", function (e) { e.preventDefault(); e.stopPropagation(); openBubble(b); }); 472 }); 473 document.addEventListener("click", function (e) { if (bubble && !bubble.hidden && !e.target.closest(".al-bubble")) { closeBubble(); } }); 474 document.addEventListener("keydown", function (e) { if (e.key === "Escape") { closeBubble(); } }); 475 // закÑÑваем ÑолÑко пÑи замеÑной пÑокÑÑÑке: на ÑелеÑоне ÑÑÑаниÑа «вздÑагиваеÑ» Ð¾Ñ Ð°Ð´ÑеÑной ÑÑÑоки 476 window.addEventListener("scroll", function () { if (bubbleFor && Math.abs(window.scrollY - bubbleY) > 60) { closeBubble(); } }, { passive: true }); 477 window.addEventListener("resize", closeBubble); 478 479 document.addEventListener("aliviy:greetlink", function () { goal("studio_from_greeting"); }); 480 481 /* ---------- API Ð´Ð»Ñ Ð¿Ð¾Ð¼Ð¾Ñников ---------- */ 482 var api = { 483 root: root, 484 goal: goal, 485 /** ÐодÑÑавиÑÑ ÑекÑÑ Ð² конÑÑÑÑкÑÐ¾Ñ Ð¸/или оÑпÑавиÑÑ Ð² ÑÐ°Ñ ÑеÑез обÑий обÑабоÑÑик. */ 486 toChat: function (text) { 487 var b = document.createElement("button"); 488 b.type = "button"; b.className = "aliviy-prompt"; b.hidden = true; 489 b.setAttribute("data-prompt", text); 490 root.appendChild(b); b.click(); root.removeChild(b); 491 goal("studio_helper_send"); 492 }, 493 /** ТекÑÑее знаÑение Ð¿Ð¾Ð»Ñ ÐºÐ¾Ð½ÑÑÑÑкÑоÑа. */ 494 get: function (k) { return state[k]; }, 495 set: function (k, v) { if (F[k]) { state[k] = v; paintAll(); render(); save(); } }, 496 /** ÐÑкÑÑÑÑ Ð²ÐºÐ»Ð°Ð´ÐºÑ: "build" | "ex" | "help". */
497 openTab: function (key) { openTab(key); } 498 }; 499 window.AliviyStudio = api; 500 501 paintAll(); 502 render(); 503 // helper.first: вкладка помоÑника оÑкÑÑÑа Ñ Ð·Ð°Ð³ÑÑзки â ÑиÑÑем его ÑÑÐ°Ð·Ñ 504 var hp0 = $("#al-sp-help"); 505 if (hp0 && !hp0.hidden) { openTab("help"); } 506 var first = Object.keys(F)[0]; 507 showTip(hintFor(first)); 508})();
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.