PageSourceSearch

https://mosrif.ru/components/com_qf3/assets/js/qf3.js?3.3.05

js mosrif.ru collected 2026-10-08 12:28:29 UTC 38,473 bytes, 1,182 lines download raw bytes

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.