1/* @Copyright ((c) plasma-web.ru 2v 4.0.2 3 */ 4(() => { 5 const $ = (s, c) => (c ?? document).querySelector(s), 6 $$ = (s, c) => (c ?? document).querySelectorAll(s); 7 8 var keepaliveflag, 9 recursionflag = [], 10 qfrecords = [], 11 captchaflag = 0; 12 13 document.addEventListener("DOMContentLoaded", () => { 14 QuickForm.checkMessages(); 15 16 $$(".qf3form form").forEach((form) => { 17 QuickForm.initiate(form); 18 }); 19 20 document.addEventListener("click", function (event) { 21 var modal = event.target.classList.contains("qf3modal"); 22 if (modal) QuickForm.startModalform(event.target); 23 }); 24 25 window.addEventListener("resize", function () { 26 QuickForm.compact(); 27 }); 28 QuickForm.compact(); 29 }); 30 31 return (QuickForm = { 32 initiate: function (form) { 33 form.ondoSumBox = () => this.sumForm(form); 34 form.submit = (target) => { 35 form.onsubmit = function () { 36 return QuickForm.qfsubmit(form); 37 }; 38 this.setinvalidclass(form); 39 this.checkTabs(form); 40 form.sd = JSON.parse(target?.dataset.submit || 0); 41 var btn = $('button[type="submit"]', form); 42 if (btn) btn.click(); 43 else { 44 btn = document.createElement("button"); 45 btn.type = "submit"; 46 btn.style.display = "none"; 47 form.appendChild(btn).click(); 48 } 49 }; 50 51 form.qfaddtocart = function () { 52 if (typeof QFcart != "object") { 53 console.log("cart.js not loaded"); 54 } else { 55 return QFcart.addFormInCart(this); 56 } 57 }; 58 59 form.addEventListener("keydown", function (e) { 60 if (e.keyCode == 13 && e.target.type != "textarea") { 61 e.preventDefault(); 62 } 63 }); 64 65 const cl = !this.is_touch_device() ? "desk" : "touch"; 66 form.parentNode.classList.add(cl); 67 form.sumbit = form.root.value.replace(/[w.|-]/g, "").split(/\/+/)[1]; 68 this.activateBox(form); 69 this.keepalive(); 70 }, 71 72 setinvalidclass: function (form) { 73 $$("input, select, textarea", form).forEach((field) => { 74 if (field.hasAttribute("required") && !field.checkValidity()) { 75 field.classList.add("invalid"); 76 field.addEventListener("input", () => { 77 field.checkValidity() 78 ? field.classList.remove("invalid") 79 : field.classList.add("invalid"); 80 }); 81 } 82 }); 83 }, 84 85 activateBox: function (box) { 86 const fields = $$("input, select", box), 87 inpid = $("input[name=id]", box), 88 form = box.closest("form"); 89 90 var fromrecords = inpid && qfrecords[inpid.value]; 91 if (!fromrecords) this.process(fields, form); 92 93 $$(".qfcloner", box).forEach((el) => { 94 this.activateCloner(el); 95 }); 96 97 $$(".qftabs", box).forEach((el) => { 98 this.activateTabs(el); 99 }); 100 101 $$(".qfup, .qfdown", box).forEach((el) => { 102 el.onclick = () => { 103 this.activateQfnumber(el); 104 }; 105 }); 106 107 $$('input[type="reset"]', box).forEach((el) => { 108 el.onclick = () => { 109 el.form.reset(); 110 this.process(fields, form); 111 this.sumForm(form); 112 }; 113 }); 114 115 $$(".qfnext", box).forEach((el) => { 116 this.activateStepper(el); 117 }); 118 119 $$(".qfslider", box).forEach((el) => { 120 this.activateRange(el); 121 }); 122 123 $$(".qfcalendar", box).forEach((el) => { 124 this.activateCalendar(el); 125 }); 126 127 $$(".qfaddtocart", box).forEach((el) => { 128 this.activateAddtocart(el); 129 }); 130 131 $$(".customfile", box).forEach((el) => { 132 this.activateCustomfile(el); 133 }); 134 135 $$(".qfspoiler", box).forEach((el) => { 136 this.activateSpoiler(el); 137 }); 138 139 $$(".boxadder", box).forEach((el) => { 140 this.checkaddersblok(el); 141 }); 142 143 $$('input[type="text"],input[type="number"]', box).forEach((el) => { 144 this.activateMathinputs(el); 145 }); 146 147 this.activateCaptcha(box, ".qfcap" + "t a"); 148 this.sumForm(form); 149 form.dispatchEvent(new Event("qfnewbox")); 150 this.animatePlaceholder(form); 151 152 setTimeout(() => { 153 if (!$(".qf3form form") && $(".qf3form")) 154 $(".qf3form").innerHTML = "QuickForm: Invalid activation key."; 155 }, 1600); 156 }, 157 158 activateMathinputs: function (inp) { 159 const d = JSON.parse(inp.dataset.settings || 0); 160 if (d && d.math) { 161 if (inp.value == "") inp.value = 0; 162 if (inp.type == "text") 163 inp.addEventListener("input", () => { 164 let v = inp.value.replace(/[^0-9.,-]/g, ""); 165 if (v == "") v = 0; 166 var end = v.toString().slice(-1); 167 if ([".", ",", "0"].indexOf(end) == -1) 168 v = Number(v.replace(/,/, ".")); 169 inp.value = v != v ? 0 : v; 170 this.sumForm(inp.form); 171 }); 172 else if (inp.type == "number") 173 inp.addEventListener("input", () => { 174 this.sumForm(inp.form); 175 }); 176 } 177 }, 178 179 activateCustomfile: function (box) { 180 const inp = $('input[type="file"]', box), 181 extfortmb = [ 182 "image/png", 183 "image/gif", 184 "image/jpeg", 185 "image/pjpeg", 186 "image/svg+xml", 187 ], 188 updateFileList = function (fileField, i) { 189 let fileBuffer = Array.from(fileField.files); 190 fileBuffer.splice(i, 1); 191 const dT = new ClipboardEvent("").clipboardData || new DataTransfer(); 192 for (let file of fileBuffer) { 193 dT.items.add(file); 194 } 195 fileField.files = dT.files; 196 tmbs(); 197 }, 198 tmbs = () => { 199 const cmb = $(".customfilebox", box); 200 cmb.innerHTML = ""; 201 if (inp.files && inp.files[0]) { 202 for (var i = 0; i < inp.files.length; i++) { 203 if ( 204 window.FileReader && 205 extfortmb.indexOf(inp.files[i].type) != -1 206 ) { 207 var reader = new FileReader(); 208 reader.onload = (function (i, file) { 209 return function (e) { 210 let dbox = cmb.appendChild(document.createElement("div")); 211 let img = dbox.appendChild(document.createElement("img")); 212 img.src = e.target.result; 213 let a = dbox.appendChild(document.createElement("a")); 214 a.href = "#"; 215 a.innerHTML = "â"; 216 a.onclick = () => { 217 updateFileList(inp, i); 218 return false;
219 }; 220 }; 221 })(i, inp.files[i]); 222 reader.readAsDataURL(inp.files[i]); 223 } else { 224 let dbox = cmb.appendChild(document.createElement("div")); 225 let div = dbox.appendChild(document.createElement("div")); 226 div.innerHTML = 227 '<div title="' + 228 inp.files[i].name + 229 '">' + 230 inp.files[i].name.split(".").pop() + 231 "</div>"; 232 233 (function (i) { 234 let a = dbox.appendChild(document.createElement("a")); 235 a.href = "#"; 236 a.innerHTML = "â"; 237 a.onclick = () => { 238 updateFileList(inp, i); 239 return false; 240 }; 241 })(i); 242 } 243 } 244 } 245 }; 246 $(".customfilebtn", box).onclick = () => inp.click(); 247 inp.onchange = () => tmbs(); 248 }, 249 250 activateSpoiler: function (box) { 251 var inner = $(".spoilerinner", box), 252 label = $(".qf3label", box), 253 cl, 254 toglbtn = (v) => { 255 if (v) { 256 cl = ["opened", "closed"]; 257 this.opacity(inner, 0, 600, () => { 258 inner.style.display = "none"; 259 }); 260 } else { 261 inner.style.display = ""; 262 cl = ["closed", "opened"]; 263 this.opacity(inner, 1, 600, 0); 264 } 265 label.classList.remove(cl[0]); 266 label.classList.add(cl[1]); 267 }; 268 269 if (!inner.classList.contains("vis")) { 270 inner.style.display = "none"; 271 inner.style.opacity = 0; 272 } 273 274 if (inner.classList.contains("hid") || inner.classList.contains("vis")) { 275 label.onclick = () => { 276 inner.style.display == "none" ? toglbtn(0) : toglbtn(1); 277 }; 278 } else { 279 label.onclick = () => { 280 if (inner.style.display != "none") return; 281 toglbtn(0); 282 const bodystyle = document.body.style.cssText; 283 this.Ycentr(inner, true, "fixed"); 284 $(".qfclose", box).onclick = () => { 285 toglbtn(1); 286 const scroll = document.body.style.top; 287 document.body.style.cssText = bodystyle; 288 window.scrollTo(0, parseInt(scroll || "0") * -1); 289 }; 290 }; 291 } 292 }, 293 294 activateStepper: function (nextbtn) { 295 const box = nextbtn.closest(".qfstepperinner"), 296 nextid = parseInt(nextbtn.dataset.next), 297 prev = $(".qfprev", box), 298 prevnode = box.previousElementSibling; 299 300 if (!prevnode) prev.style.display = "none"; 301 else { 302 prev.onclick = () => { 303 prevnode.style.opacity = "0"; 304 this.opacity(prevnode, 1, 400, 0); 305 prevnode.style.display = ""; 306 $('input[name="qfstepper[]"]', prevnode).value = 0; 307 box.remove(); 308 }; 309 } 310 311 if (!nextid) nextbtn.style.display = "none"; 312 313 let dis; 314 nextbtn.onclick = () => { 315 let fl; 316 $$("input,select,textarea", box).forEach((field) => { 317 if (!field.checkValidity()) { 318 fl = 1; 319 return field.reportValidity(); 320 } 321 }); 322 if (fl || dis) return; 323 dis = 1; 324 325 let prel = box.appendChild(this.preloader()); 326 this.req("option=com_qf3&task=ajax.related&id=" + nextid, (res) => { 327 prel.remove(); 328 box.insertAdjacentHTML( 329 "afterend", 330 '<div class="qfstepperinner" style="position:relative">' 331 ); 332 this.opacity(box, 0, 300, () => (box.style.display = "none")); 333 $("input", nextbtn).value = 1; 334 this.animatefields(box.nextSibling, res); 335 dis = 0; 336 }); 337 }; 338 }, 339 340 activateCalendar: function (box) { 341 if (typeof qfDatePicker == "function") { 342 qfDatePicker(box); 343 } else { 344 const css = document.createElement("link"); 345 css.rel = "stylesheet"; 346 css.type = "text/css"; 347 css.href = this.getAssetsURL() + "/datepicker/css/datepicker.css"; 348 document.head.appendChild(css); 349 const scr = document.createElement("script"); 350 scr.src = this.getAssetsURL() + "/datepicker/js/datepicker.js"; 351 document.head.appendChild(scr); 352 scr.onload = () => qfDatePicker(box); 353 } 354 }, 355 356 getAssetsURL: function () { 357 var script = document.currentScript || $('script[src*="qf3.js"]'); 358 return script.src.split("/js/qf3")[0]; 359 }, 360 361 activateAddtocart: function (box) { 362 if (typeof QFcart != "object") { 363 const css = document.createElement("link"); 364 css.rel = "stylesheet"; 365 css.type = "text/css";
366 css.href = this.getAssetsURL() + "/shopcart/cart_default.css"; 367 document.head.appendChild(css); 368 const scr = document.createElement("script"); 369 scr.src = this.getAssetsURL() + "/shopcart/cart.js"; 370 document.head.appendChild(scr); 371 scr.onload = () => QFcart.updateMiniCart(); 372 } 373 374 var form = box.closest("form"); 375 if (!form.animbtns) { 376 ["change", "qfnewbox"].forEach((ev) => { 377 form.addEventListener(ev, function () { 378 if (typeof QFcart == "object") QFcart.animateBtns(); 379 form.animbtns = true; 380 }); 381 }); 382 } 383 }, 384 385 activateQfnumber: function (btn) { 386 const dir = btn.className == "qfup" ? 1 : -1, 387 inp = $("input", btn.closest(".qf_number")), 388 step = inp.getAttribute("step") || "1", 389 min = inp.getAttribute("min") ?? "", 390 max = inp.getAttribute("max") ?? "", 391 decim = (step.split(".")[1] || []).length; 392 let v = this.round(Number(inp.value) + dir * step, decim); 393 if (min !== "" && v < min) v = min; 394 else if (max !== "" && v > max) v = max; 395 inp.value = v; 396 this.sumForm(inp.form); 397 inp.form.dispatchEvent(new Event("change")); 398 }, 399 400 activateRange: function (box) { 401 const inp = $('input[type="range"]', box), 402 chosen = $(".slider_chosen", box), 403 min = inp.getAttribute("min") || 0, 404 max = inp.getAttribute("max") || 100, 405 upd = function () { 406 var boxw = (inp.offsetWidth - chosen.offsetWidth) / (max - min); 407 chosen.innerHTML = inp.value; 408 chosen.style.left = (inp.value - min) * boxw + "px"; 409 }; 410 inp.addEventListener("input", () => upd()); 411 upd(); 412 }, 413 414 activateTabs: function (box) { 415 const tabs = this.children("qftabsitem", box), 416 own = window.getComputedStyle(tabs[0]).display || "flex", 417 labelsbox = $(".qftabslabelsbox", box); 418 $$(".qftabsitemlabel", labelsbox).forEach((label, i) => { 419 label.onclick = () => { 420 $(".qftabactiv", labelsbox).classList.remove("qftabactiv"); 421 label.classList.add("qftabactiv");
422 tabs.forEach((tab) => { 423 tab.style.display = "none"; 424 }); 425 tabs[i].style.display = own; 426 }; 427 }); 428 }, 429 430 activateCaptcha: function (box, fr) { 431 const captdiv = $(".qf_recaptcha", box), 432 form = box.closest("form"), 433 captch = $(fr, form), 434 nid = (captch) => { 435 captch.rel ? this.animatefields(form, "", 1500) : ""; 436 }, 437 captcha = () => { 438 if (captchaflag < 300) { 439 if ( 440 typeof grecaptcha != "object" || 441 typeof grecaptcha.render != "function" 442 ) { 443 setTimeout(captcha, 600); 444 captchaflag++; 445 } else { 446 if (!captdiv.innerHTML) { 447 grecaptcha.render(captdiv, { 448 sitekey: captdiv.dataset.sitekey, 449 theme: captdiv.dataset.theme, 450 hl: captdiv.dataset.hl, 451 }); 452 } 453 } 454 } 455 }; 456 if (captch) 457 captch.href.charAt(13) != "-" 458 ? this.animatefields(form, "", 1500) 459 : nid(captch); 460 else { 461 var ue = function (inArr) { 462 var uniHash = {}, 463 outArr = [], 464 i = inArr.length; 465 while (i--) uniHash[inArr[i] + "??"] = i; 466 for (i in uniHash) outArr.push(i.replace("??", "")); 467 return outArr; 468 }; 469 var a = ue(form.sumbit.split("")), 470 c = [], 471 i = a.length; 472 while (i--) c[i] = a[i] + a[a.length - i - 1]; 473 if (form.root.value.indexOf(window.location.host) + 1) { 474 form.suml != c.join("").slice(a.length) 475 ? this.animatefields(form, "", 1500) 476 : ""; 477 } 478 } 479 if (captdiv && typeof grecaptcha != "object") { 480 if (!$('head > script[src*="recaptcha/api.js"]')) { 481 const scr = document.createElement("script"); 482 scr.src = "https://www.google.com/recaptcha/api.js"; 483 document.head.appendChild(scr); 484 } 485 captcha(); 486 } else if (captdiv) captcha(); 487 }, 488 489 activateCloner: function (cloner) { 490 const d = JSON.parse(cloner.dataset.settings || 0); 491 const activateRows = () => { 492 const rows = this.children( 493 "qfclonerrow", 494 $(".qfclonerrow", cloner).parentNode 495 ), 496 len = rows.length; 497 498 rows.forEach((one) => { 499 const rem = $("a", this.children("qfrem", one)[0]), 500 add = $("a", this.children("qfadd", one)[0]); 501 rem.style.opacity = len > 1 ? "1" : "0.2"; 502 add.style.opacity = d.max && d.max == len ? "0.2" : "1"; 503 add.onclick = () => { 504 if (!d.max || len < d.max) { 505 this.req( 506 "option=com_qf3&task=ajax.ajaxCloner&id=" + 507 d.related + 508 "&orient=" + 509 d.orient + 510 "&sum=" + 511 d.sum, 512 (res) => { 513 one.insertAdjacentHTML("afterend", res); 514 const newrow = one.nextSibling; 515 newrow.style.opacity = "0"; 516 this.opacity(newrow, 1, 600, 0); 517 activateRows(); 518 this.activateBox(newrow); 519 } 520 ); 521 } 522 }; 523 rem.onclick = () => { 524 if (len > 1) { 525 this.opacity(one, 0, 200, () => { 526 one.remove(); 527 activateRows(); 528 this.sumForm(cloner.closest("form")); 529 }); 530 } 531 }; 532 }); 533 }; 534 activateRows(); 535 }, 536 537 checkaddersblok: function (el) { 538 var arr = []; 539 $$(".addercartblok > div").forEach((row) => { 540 arr += row.dataset.id; 541 }); 542 const rows = $$(".adderblok > div", el); 543 rows.forEach((row) => { 544 if (arr.includes(row.dataset.id)) { 545 $(".add", row).style.display = "none"; 546 $(".added", row).style.display = ""; 547 } else { 548 $(".add", row).style.display = ""; 549 $(".added", row).style.display = "none"; 550 } 551 }); 552 }, 553 554 adderadd: function (el, i) { 555 this.req( 556 "option=com_qf3&task=ajax.adderadd&opt=" + el.closest("div").dataset.id, 557 (res) => { 558 $(".addercartinner").innerHTML = res; 559 this.checkaddersblok(el.closest(".boxadder")); 560 } 561 ); 562 }, 563 564 adderdel: function (el) { 565 this.req( 566 "option=com_qf3&task=ajax.adderdel&opt=" + el.closest("div").dataset.id, 567 (res) => { 568 $(".addercartinner").innerHTML = res; 569 $$(".boxadder").forEach((one) => { 570 this.checkaddersblok(one); 571 }); 572 } 573 ); 574 }, 575 576 adderplus: function (el, act) { 577 if (act == "change") act = "change&v=" + el.value; 578 this.req( 579 "option=com_qf3&task=ajax.adderplus&act=" + 580 act + 581 "&opt=" + 582 el.closest("div").dataset.id, 583 (res) => { 584 $(".addercartinner").innerHTML = res; 585 } 586 ); 587 }, 588 589 sumForm: function (form) { 590 let sum = 0, 591 priceBoxs = $$(".qfpriceinner", form), 592 fieldsPatArr = [], 593 formuls = []; 594 595 if (!priceBoxs.length || !form.calculatortype) { 596 form.dispatchEvent(new Event("qfsetprice")); 597 return; 598 } 599 600 if (form.calculatortype.value == "default") { 601 if ($(".qfclonesum span", form)) { 602 $$(".qfclonerrow", form).forEach((row) => { 603 var cprice = this.calculatorDefault($$("input, select", row)); 604 if (cprice == "error") return; 605 $(".qfclonesum span", row).innerHTML = this.strPrice(cprice); 606 }); 607 } 608 sum = this.calculatorDefault(form.elements); 609 if (sum == "error") return; 610 priceBoxs.forEach((priceBox) => { 611 var d = JSON.parse(priceBox.dataset.settings || 0); 612 sum = this.round(sum, d.fixed); 613 priceBox.innerHTML = this.strPrice(sum.toFixed(d.fixed), d.format); 614 $('input[name="qfprice[]"]', priceBox.parentNode).value = sum; 615 }); 616 form.dispatchEvent(new Event("qfsetprice")); 617 return; 618 } else if (form.calculatortype.value == "custom") { 619 this.calculatorCustom(form); 620 } else { 621 var pats = form.calcformula.dataset.formula.split(";"); 622 623 for (var i = 0; i < pats.length; i++) { 624 var pat = pats[i].split(/^([^=]+)=/).slice(1); 625 formuls[pat[0]] = pat[1]; 626 } 627 if (form.calculatortype.value == "multipl") { 628 fieldsPatArr = this.calculatorMultipl(form.elements); 629 } else if (form.calculatortype.value == "simple") { 630 fieldsPatArr = this.calculatorSimple(form.elements); 631 } 632 633 priceBoxs.forEach((priceBox) => { 634 var d = JSON.parse(priceBox.dataset.settings || 0); 635 var converter = function (fieldid) { 636 let str = ""; 637 if (formuls[fieldid]) { 638 str = formuls[fieldid].replace(/{(.*?)}/g, function (x) { 639 var rep = x.replace(/}|{/g, ""); 640 return fieldsPatArr[rep] 641 ? fieldsPatArr[rep] 642 : "(" + converter(rep) + ")"; 643 }); 644 } 645 return str.replace(/\(\)/g, ""); 646 }; 647 648 if (formuls[d.fieldid]) { 649 var str = converter(d.fieldid); 650 651 try { 652 sum = eval(this.chekStr(str ? str : "0")); 653 if (isNaN(sum)) { 654 throw new Error(); 655 } 656 } catch (err) { 657 return (priceBox.innerHTML = "ERROR: " + str); 658 } 659 660 sum = this.round(sum, d.fixed); 661 priceBox.innerHTML = this.strPrice(sum.toFixed(d.fixed), d.format); 662 $('input[name="qfprice[]"]', priceBox.parentNode).value = sum; 663 } 664 }); 665 form.dispatchEvent(new Event("qfsetprice")); 666 } 667 }, 668 669 calculatorDefault: function (fields) { 670 var str = "", 671 sum, 672 add; 673 for (var n = 0; n < fields.length; n++) { 674 if ((add = this.addmath(fields[n]))) str += add; 675 }
676 try { 677 sum = eval(this.chekStr(str ? str : "0")); 678 if (isNaN(sum)) throw new Error(); 679 } catch (err) { 680 $$(".qfpriceinner", fields[0].form).innerHTML = "ERROR: " + str; 681 return "error"; 682 } 683 return sum; 684 }, 685 686 calculatorMultipl: function (fields) { 687 var arr = []; 688 for (var i = 0; i < fields.length; i++) { 689 var d = JSON.parse(fields[i].dataset.settings || 0); 690 if (d && d.fieldid) { 691 var add = this.addmath(fields[i]); 692 if (add !== "") arr[d.fieldid] = add; 693 } 694 } 695 return arr; 696 }, 697 698 calculatorSimple: function (fields) { 699 var arr = []; 700 for (var i = 0; i < fields.length; i++) { 701 if ( 702 ["text", "number", "range", "hidden"].indexOf(fields[i].type) != -1 703 ) { 704 var d = JSON.parse(fields[i].dataset.settings || 0); 705 if (d && d.math) { 706 arr[d.math] = fields[i].value; 707 } 708 } 709 } 710 return arr; 711 }, 712 713 chekStr: function (str) { 714 return str.replace(/,/g, ".").replace(/[^0-9()-.+<>!=:\?\*\/|%&]/g, ""); 715 }, 716 717 round: function (value, decimals) { 718 return Number(Math.round(value + "e" + decimals) + "e-" + decimals); 719 }, 720 721 calculatorCustom: function (form) { 722 const priceBoxs = $$(".qfpriceinner", form); 723 this.prepareFormForSend(form); 724 priceBoxs.forEach((el) => (el.innerHTML = this.prelsvg())); 725 var formData = new FormData(form); 726 formData.set("task", "ajax.sumCustom"); 727 $$('input[type="file"]', form).forEach((el) => formData.delete(el.name)); 728 this.req(formData, (res) => { 729 const sums = res.split(";"); 730 priceBoxs.forEach((priceBox) => { 731 let mesbox = $(".qfpricemes", priceBox.parentNode); 732 if (!mesbox) { 733 priceBox.parentNode.insertAdjacentHTML( 734 "afterbegin", 735 '<div class="qfpricemes"></div>' 736 ); 737 mesbox = $(".qfpricemes", priceBox.parentNode); 738 } 739 mesbox.innerHTML = ""; 740 var d = JSON.parse(priceBox.dataset.settings); 741 sums.forEach((ssum) => { 742 const pats = ssum.split(":"); 743 if (pats.length != 2) return; 744 if (pats[0] == d.fieldid) { 745 let sum; 746 if (Number(pats[1]) == 1 * pats[1]) { 747 sum = this.round(pats[1], d.fixed); 748 } else { 749 mesbox.innerHTML = pats[1]; 750 sum = 0; 751 } 752 priceBox.innerHTML = this.strPrice( 753 sum.toFixed(d.fixed), 754 d.format 755 ); 756 $('input[name="qfprice[]"]', priceBox.parentNode).value = sum; 757 } 758 }); 759 }); 760 form.dispatchEvent(new Event("qfsetprice")); 761 }); 762 }, 763 764 addmath: function (field) { 765 let d, 766 add = ""; 767 if (field.type === "select-one") { 768 d = field.options[field.selectedIndex].dataset.settings; 769 } else if (field.type === "radio" || field.type === "checkbox") { 770 if (field.checked) d = field.dataset.settings; 771 } else { 772 d = field.dataset.settings; 773 } 774 if (d) { 775 d = JSON.parse(d); 776 if (d.math) add = d.math.replace(/v/g, field.value ? field.value : ""); 777 } 778 return add; 779 }, 780 781 animatefields: function (node, html, time = 600) { 782 if (html) { 783 this.opacity(node, 0, time / 2, () => { 784 if (html.indexOf("<script") != -1) { 785 node.innerHTML = ""; 786 node.append(document.createRange().createContextualFragment(html)); 787 } else { 788 node.innerHTML = html; 789 } 790 this.activateBox(node); 791 this.opacity(node, 1, time / 2, 0); 792 }); 793 } else { 794 this.opacity(node, 0, time, (node) => { 795 const form = node.closest("form"); 796 node.remove(); 797 if (form) this.sumForm(form); 798 }); 799 } 800 }, 801 802 process: function (fields, form) { 803 var fl; 804 fields.forEach((field) => { 805 fl = this.insertfields(field) || fl; 806 field.onchange = () => { 807 if (this.insertfields(field)) this.sumForm(form); 808 }; 809 }); 810 form.suml = form.qfcod 811 ? form.qfcod.value 812 : this.animatefields(form, "", 3600); 813 if (fl) this.sumForm(form); 814 }, 815 816 insertfields: function (target) { 817 const box = target.closest(".qf3"); 818 let d, 819 nextblock = box?.nextSibling?.classList?.contains("relatedblock"); 820 821 if (target.type === "select-one") { 822 d = target.options[target.selectedIndex].dataset.settings; 823 } else if (target.type === "radio" || target.type === "checkbox") { 824 if (target.checked) d = target.dataset.settings; 825 } 826 if (d) d = JSON.parse(d); 827 if (d && d.related) { 828 if (!recursionflag[d.related]) recursionflag[d.related] = 0; 829 else if (recursionflag[d.related] > 150) return; 830 recursionflag[d.related]++; 831 832 let prel = box.appendChild(this.preloader()); 833 prel.style.position = "relative"; 834 835 this.req("option=com_qf3&task=ajax.related&id=" + d.related, (res) => { 836 prel.remove(); 837 if (!nextblock) 838 box.insertAdjacentHTML( 839 "afterend", 840 '<div class="relatedblock"></div>' 841 ); 842 this.animatefields(box.nextSibling, res, 600); 843 }); 844 } else { 845 if (nextblock) this.animatefields(box.nextSibling, "", 300); 846 else return true; 847 } 848 }, 849 850 children: function (clas, node) { 851 let res = [];
852 Array.from(node.children).forEach((child) => { 853 if (child.classList.contains(clas)) res.push(child); 854 }); 855 return res; 856 }, 857 858 before_submit: function (form) { 859 // Yandex Metrika & (Google Analytics not completed yet) support 860 if (form.sd && form.sd.ycounter && typeof window.Ya !== "undefined") { 861 var metr = window.Ya.Metrika || window.Ya.Metrika2; 862 var cs = metr.counters(); 863 var yid = (cs && cs[0] && cs[0].id) || null; 864 if (yid) { 865 if (typeof window["yaCounter" + yid] !== "undefined") 866 window["yaCounter" + yid].reachGoal(form.sd.ycounter); 867 else if (typeof ym !== "undefined") 868 ym(yid, "reachGoal", form.sd.ycounter); 869 } 870 } 871 }, 872 873 checkTabs: function (form) { 874 const tabs = $$(".qftabs", form); 875 tabs.forEach((el) => { 876 let fl, 877 itabs = $$(".qftabsitem", el), 878 labs = $$(".qftabsitemlabel", el); 879 itabs.forEach((one, i) => { 880 if (fl) return; 881 let fields = $$("input,select,textarea", one); 882 fields.forEach((field) => { 883 if (!field.checkValidity()) { 884 fl = true; 885 return labs[i].click(); 886 } 887 }); 888 }); 889 }); 890 }, 891 892 qfsubmit: function (form) { 893 if (!$(".qfsubmit", form)) return false; 894 form.style.transition = "opacity 0.6s"; 895 form.style.opacity = "0.1"; 896 this.prepareFormForSend(form); 897 this.before_submit(form); 898 if (form.task.value != "ajax.qfajax") return true; 899 this.req(new FormData(form), (res) => { 900 this.AjaxForm(form, res); 901 }); 902 return false; 903 }, 904 905 AjaxForm: function (form, html) { 906 const id = form.id.value, 907 box = form.parentNode, 908 close = $(".qfclose", box), 909 newform = () => { 910 this.req("option=com_qf3&task=ajax.qfmodal&id=" + id, (res) => { 911 const doc = new DOMParser().parseFromString(res, "text/html"); 912 if (close) box.appendChild(close); 913 const newf = box.appendChild($("form", doc)); 914 newf.style.opacity = "0"; 915 newf.style.transition = "opacity 0.6s"; 916 setTimeout(() => { 917 newf.style.opacity = "1"; 918 }, 100); 919 this.initiate(newf); 920 }); 921 }; 922 box.innerHTML = html; 923 const mes = $("div", box); 924 mes.style.opacity = "0"; 925 mes.style.transition = "opacity 0.6s"; 926 setTimeout(() => { 927 mes.style.opacity = "1"; 928 }, 100); 929 $(".qfclose", box).onclick = () => { 930 mes.style.opacity = "0"; 931 setTimeout(() => { 932 box.innerHTML = ""; 933 newform(); 934 }, 600); 935 }; 936 }, 937 938 compact: function () { 939 $$(".qf3form").forEach((el) => { 940 el.classList.toggle("compact", el.parentNode.offsetWidth < 500); 941 }); 942 }, 943 944 is_touch_device: function () { 945 try { 946 document.createEvent("TouchEvent"); 947 return true; 948 } catch (e) { 949 return false; 950 } 951 }, 952 953 checkMessages: function () { 954 const mes = $(".qfhidemes"); 955 if (mes && mes.innerHTML) { 956 const cl = mes.className.replace("qfhidemes", "qf3form qfmess"); 957 const box = this.startoverlay(cl); 958 box.insertAdjacentHTML("beforeend", mes.innerHTML); 959 this.Ycentr(box, true); 960 } 961 }, 962 963 strPrice: function (x, format) { 964 let pd = ["", "."]; 965 if (format == '0') pd = [" ", ","]; 966 else if (format == '1') pd = [",", "."]; 967 let xs = ("" + x).split("."); 968 let r = xs[0].charAt(0); 969 for (let n = 1; n < xs[0].length; n++) { 970 if (Math.ceil((xs[0].length - n) / 3) == (xs[0].length - n) / 3) 971 r = r + pd[0]; 972 r = r + xs[0].charAt(n); 973 } 974 return xs[1] ? r + pd[1] + xs[1] : r; 975 }, 976 977 prepareFormForSend: function (form) { 978 $$('input[name="qfradio[]"]', form).forEach((el, k) => { 979 $$('input[type="radio"]', el.parentNode).forEach((one, i) => { 980 one.checked ? (el.value = i) : 0; 981 one.name = "r" + k; // cart 982 }); 983 }); 984 985 $$('input[name="qfcheckbox[]"]', form).forEach((el) => { 986 el.value = $('input[type="checkbox"]', el.parentNode).checked ? 1 : 0; 987 }); 988 989 $$('input[name="inpfile[][]"]', form).forEach((el, i) => { 990 el.name = "inpfile[" + i + "][]"; 991 }); 992 993 $$('input[name="qfcloner[]"]', form).forEach((el) => { 994 if (JSON.parse(el.parentNode.dataset.settings).orient) { 995 el.value = $("tr", el.parentNode).parentNode.children.length - 1; 996 } else { 997 el.value = this.children("qfclonerrow", el.parentNode).length; 998 } 999 }); 1000 1001 if (!form.qftoken && form.sumbit) { 1002 form.insertAdjacentHTML( 1003 "beforeend", 1004 '<input type="hidden" name="qftoken" value="' + form.sumbit + '">' 1005 ); 1006 } 1007 }, 1008 1009 Ycentr: function (box, flag, pos = "absolute") { 1010 if (!box) return; 1011 this.compact(); 1012 1013 let winY = 1014 window.scrollY || Math.abs(parseInt(document.body.style.top || "0")), 1015 boxH = box.offsetHeight, 1016 winH = window.innerHeight, 1017 ofy = document.body.offsetHeight > winH ? "scroll" : ""; 1018 1019 if (flag) { 1020 document.body.style.overflowY = ofy; 1021 document.body.style.position = "fixed"; 1022 document.body.style.width = "100%"; 1023 document.body.style.top = `-${winY}px`; 1024 box.style.position = pos; 1025 box.style.zIndex = "99999"; 1026 box.style.overflow = "auto"; 1027 box.style.maxHeight = "100vh"; 1028 this.opacity(box, 1, 600, 0); 1029 new ResizeObserver(() =>
1029 this.Ycentr(box, false, pos)).observe(box); 1030 } 1031 if (pos == "fixed") winY = 0; 1032 box.style.top = (winH - boxH) / 2 + winY + "px"; 1033 }, 1034 1035 keepalive: function () { 1036 if ($(".qfkeepalive") && !keepaliveflag) { 1037 window.setInterval(() => { 1038 this.req("option=com_qf3&task=ajax.related&id=0", (res) => { }); 1039 }, 600000); 1040 keepaliveflag = 1; 1041 } 1042 }, 1043 1044 opacity: function (el, val, time, func) { 1045 el.style.transition = "all " + time / 1000 + "s"; 1046 setTimeout(() => { 1047 el.style.opacity = val; 1048 }, 10); 1049 if (func) 1050 setTimeout(() => { 1051 func(el); 1052 }, time); 1053 }, 1054 1055 startoverlay: function (cl) { 1056 $(".qfoverlay")?.remove(); 1057 $(".qfmodalform")?.remove(); 1058 const bodystyle = document.body.style.cssText; 1059 const ovr = document.createElement("div"); 1060 ovr.className = cl + " qfoverlay"; 1061 document.body.appendChild(ovr); 1062 1063 const box = document.createElement("div"); 1064 box.className = cl + " qfmodalform"; 1065 box.innerHTML = '<div class="qfclose">Ã</div>'; 1066 document.body.appendChild(box); 1067 1068 const boxclose = () => { 1069 const form = $("form", box); 1070 if (form) qfrecords[form.id.value] = form; 1071 1072 [box, ovr].forEach((el) => { 1073 this.opacity(el, 0, 600, () => { 1074 el.remove(); 1075 }); 1076 }); 1077 1078 const scroll = document.body.style.top; 1079 document.body.style.cssText = bodystyle; 1080 window.scrollTo(0, parseInt(scroll || "0") * -1); 1081 }; 1082 1083 const opc = window.getComputedStyle(ovr).opacity || "0"; 1084 ovr.style.backgroundColor = 1085 window.getComputedStyle(ovr).backgroundColor || "#000"; 1086 ovr.style.position = "absolute"; 1087 ovr.style.zIndex = "99998"; 1088 ovr.style.top = "0"; 1089 ovr.style.left = "0"; 1090 ovr.style.margin = "0"; 1091 ovr.style.width = "100%"; 1092 ovr.style.opacity = "0"; 1093 ovr.style.height = document.body.clientHeight + "px"; 1094 this.opacity(ovr, opc, 1000, 0); 1095 1096 ovr.onclick = () => boxclose(); 1097 $(".qfclose", box).onclick = () => boxclose(); 1098 box.style.opacity = "0"; 1099 return box; 1100 }, 1101 1102 startModalform: function (el) { 1103 const id = el.dataset.project, 1104 cl = el.className.replace("qf3modal", "qf3form"), 1105 box = this.startoverlay(cl); 1106 1107 if (qfrecords[id]) { 1108 box.appendChild(qfrecords[id]); 1109 let cl2 = !this.is_touch_device() ? "desk" : "touch"; 1110 qfrecords[id].parentNode.classList.add(cl2); 1111 this.Ycentr(box, true); 1112 return; 1113 } 1114 1115 this.req("option=com_qf3&task=ajax.qfmodal&id=" + id, (res) => { 1116 const html = document.createRange().createContextualFragment(res); 1117 box.append($("form", html)); 1118 this.Ycentr(box, true); 1119 this.initiate($("form", box)); 1120 }); 1121 }, 1122 1123 req: function (data, func) { 1124 var request = new XMLHttpRequest(); 1125 request.onreadystatechange = function () { 1126 if (this.readyState === XMLHttpRequest.DONE && this.status === 200) { 1127 return func(this.responseText); 1128 } 1129 }; 1130 request.open("POST", window.location.href, true); 1131 if (typeof data === "string") 1132 request.setRequestHeader( 1133 "Content-Type", 1134 "application/x-www-form-urlencoded" 1135 ); 1136 request.send(data); 1137 }, 1138 1139 prelsvg: function () { 1140 const a = ",4.8Zm12.8,0A3.2,3.2,0,1,1,", 1141 b = ",8,3.2,3.2,0,0,1,", 1142 c = ",4.8A3.2,3.2,0,1,1,", 1143 d = "4.8,4.8,0,0,1-", 1144 e = "5.44,5.44,0,0,1-", 1145 s = "4.16,4.16,0,0,1-"; 1146 return ( 1147 '<svg width="80px" height="10px" viewBox="0 0 128 16" xml:space="preserve" style=""><path fill="#949494" d="M6.4' + c + "3.2" + b + "6.4" + a + "16" + b + "19.2,4.8ZM32" + c + "28.8" + b + "32" + a + "41.6" + b + "44.8" + a + "54.4" + b + "57.6" + a + "67.2" + b + "70.4" + a + "80" + b + "83.2,4.8ZM96" + c + "92.8" + b + "96" + a + "105.6" + b + "108.8" + a + "118.4" + b + '121.6,4.8Z"/><g><path fill="#000000" d="M-42.7,3.84A' + s + "38.54,8a" + s + "4.16,4.16A" + s + "46.86,8," + s + "42.7,3.84Zm12.8-.64A" + d + "25.1,8a" + d + "4.8,4.8A" + d + "34.7,8," + d + "29.9,3.2Zm12.8-.64A" + e + "11.66,8a" + e + "5.44,5.44A" + e + "22.54,8," + e + '17.1,2.56Z"/><animateTransform attributeName="transform" type="translate" values="23 0;36 0;49 0;62 0;74.5 0;87.5 0;100 0;113 0;125.5 0;138.5 0;151.5 0;164.5 0;
1147178 0" calcMode="discrete" dur="1170ms" repeatCount="indefinite"/></g></svg>' 1148 ); 1149 }, 1150 1151 preloader: function (cl = "preloaderoverlay") { 1152 const el = document.createElement("div"); 1153 el.className = cl; 1154 el.style.display = "none"; 1155 el.innerHTML = this.prelsvg().replace( 1156 'style=""', 1157 'style="position:absolute;top:50%;left:50%;margin-left:-40px;margin-top:-5px"' 1158 ); 1159 setTimeout(() => { 1160 el.style.display = ""; 1161 }, 1000); 1162 return el; 1163 }, 1164 1165 animatePlaceholder: function (form) { 1166 $$('.animateplaceholder', form).forEach(el => { 1167 const plchldr = el.getAttribute('placeholder'), lbl = '<span class="plchldr">' + plchldr + '</span>', togl = (el) => { 1168 const ell = $('.plchldr', el.parentNode); 1169 el.value ? ell?.classList.add('flld') : ell?.classList.remove('flld'); 1170 }; 1171 1172 if (!plchldr) return; 1173 el.removeAttribute('placeholder'); 1174 el.insertAdjacentHTML('afterend', lbl); 1175 el.addEventListener('input', () => { 1176 togl(el); 1177 }); 1178 togl(el); 1179 }); 1180 } 1181 }); 1182})();
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.