PageSourceSearch

https://cream.shop/bitrix/templates/aspro_max/js/custom.js?178671388217813

js cream.shop collected 2026-09-29 13:10:10 UTC 17,813 bytes, 565 lines download raw bytes

1/*
2You can use this file with your scripts.
3It will not be overwritten when you upgrade solution.
4*/
5document.addEventListener("DOMContentLoaded", function() {
6  const mwid = 26317;
7  const showAtPageView = 5;
8  const delayMs = 2000;
9
10  let views = parseInt(localStorage.getItem("pageViews") || "0", 10);
11  views++;
12  localStorage.setItem("pageViews", views);
13
14  if (views == showAtPageView) {
15    const el = document.querySelector(`.dyn_mp_jqm[data-param-id="${mwid}"]`);
16    if (el) {
17      setTimeout(() => {
18        el.click();
19      }, delayMs);
20    }
21  }
22});
23
24/* filters for brands */
25
26document.addEventListener("DOMContentLoaded", function () {
27  const mediaQuery = window.matchMedia("(max-width: 767px)");
28
29  function removeMobileSectionClones() {
30    document.querySelectorAll(".cream-filter-sections-box").forEach(function (node) {
31      node.remove();
32    });
33  }
34
35  function getPlural(number, forms) {
36    const value = Math.abs(number) % 100;
37    const last = value % 10;
38
39    if (value > 10 && value < 20) {
40      return forms[2];
41    }
42
43    if (last > 1 && last < 5) {
44      return forms[1];
45    }
46
47    if (last === 1) {
48      return forms[0];
49    }
50
51    return forms[2];
52  }
53
54  let brandSortTemplate = null;
55
56  function getCatalogCount() {
57    const bottomNav = document.querySelector(".bottom_nav[data-all_count]");
58    const bottomNavCount = bottomNav ? parseInt(bottomNav.getAttribute("data-all_count"), 10) : 0;
59
60    if (bottomNavCount > 0) {
61      return bottomNavCount;
62    }
63
64    const elementCount = document.querySelector(".element-count");
65    const elementCountValue = elementCount
66      ? parseInt((elementCount.textContent || "").replace(/\D+/g, ""), 10)
67      : 0;
68
69    if (elementCountValue > 0) {
70      return elementCountValue;
71    }
72
73    const pageNumbers = Array.prototype.map.call(
74      document.querySelectorAll(".bottom_nav .module-pagination .nums a.dark_link"),
75      function (link) {
76        return parseInt((link.textContent || "").replace(/\D+/g, ""), 10);
77      }
78    ).filter(function (number) {
79      return number > 0;
80    });
81
82    const visibleItems = document.querySelectorAll(
83      ".catalog_block.items .item_block:not(.hidden), .catalog_block.items .item:not(.hidden)"
84    ).length;
85    const lastPage = pageNumbers.length ? Math.max.apply(null, pageNumbers) : 0;
86
87    if (lastPage > 1 && visibleItems > 0) {
88      return (lastPage - 1) * visibleItems;
89    }
90
91    return visibleItems;
92  }
93
94  function getMobileSortLabel(text) {
95    return text.replace(/По порядку сортировки/i, "По умолчанию").trim();
96  }
97
98  function enhanceMobileSort(sortNode) {
99    sortNode.querySelectorAll(".dropdown-select__title span, .dropdown-select__list-link span").forEach(function (node) {
100      const text = (node.textContent || "").trim();
101      const match = text.match(/^(.+?)\s*\((возрастание|убывание)\)$/i);
102
103      if (!match) {
104        node.textContent = getMobileSortLabel(text);
105        return;
106      }
107
108      const label = document.createElement("span");
109      label.className = "cream-mobile-sort-label";
110      label.textContent = getMobileSortLabel(match[1]);
111
112      const direction = document.createElement("i");
113      direction.className =
114        "cream-mobile-sort-direction " +
115        (match[2].toLowerCase() === "убывание" ? "is-desc" : "is-asc");
116      direction.setAttribute("aria-label", match[2].toLowerCase());
117
118      node.textContent = "";
119      node.appendChild(label);
120      node.appendChild(direction);
121    });
122  }
123
124  function getMobileFilterPanel() {
125    if (window.location.pathname.indexOf("/brands/") === 0) {
126      restoreBrandSortPanel();
127
128      const brandPanel = document.querySelector(
129        ".brand-products-block .brand-products-sort .filter-panel.sort_header, .brand-products-sort .filter-panel.sort_header"
130      );
131
132      if (brandPanel) {
133        return brandPanel;
134      }
135    }
136
137    return (
138      document.querySelector(".filter-panel.sort_header.show-compact") ||
139      document.querySelector(".brand-products-sort .filter-panel.sort_header")
140    );
141  }
142
143  function rememberBrandSortPanel() {
144    if (window.location.pathname.indexOf("/brands/") !== 0 || brandSortTemplate) {
145      return;
146    }
147
148    const brandSort = document.querySelector(".brand-products-sort");
149
150    if (brandSort) {
151      brandSortTemplate = brandSort.cloneNode(true);
152    }
153  }
154
155  function restoreBrandSortPanel() {
156    if (window.location.pathname.indexOf("/brands/") !== 0) {
157      return;
158    }
159
160    rememberBrandSortPanel();
161
162    if (document.querySelector(".brand-products-sort .filter-panel.sort_header") || !brandSortTemplate) {
163      return;
164    }
165
166    const productsBlock = document.querySelector(".brand-products-block");
167    const insertBefore =
168      document.querySelector(".brand-smart-filter") ||
169      document.querySelector(".brand-products-list.content_linked_goods") ||
170      document.querySelector(".content_linked_goods");
171
172    if (!productsBlock || !insertBefore) {
173      return;
174    }
175
176    const restoredSort = brandSortTemplate.cloneNode(true);
177    insertBefore.parentNode.insertBefore(restoredSort, insertBefore);
178  }
179
180  function ensureBrandFilterButton(panel) {
181    if (
182      !panel ||
183      panel.querySelector(".filter-panel__filter") ||
184      (
185        window.location.pathname.indexOf("/brands/") !== 0 &&
186        !document.querySelector(".brand-smart-filter .bx_filter")
187      )
188    ) {
189      return;
190    }
191
192    panel.classList.add("show-compact", "cream-brand-filter-panel");
193
194    const filter = document.createElement("div");
195    filter.className = "filter-panel__filter pull-left filter-compact cream-brand-filter-button";
196    filter.innerHTML =
197      '<div class="bx-filter-title filter_title">' +
198      '<i class="svg svg-inline-icon" aria-hidden="true">' +
199      '<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24">' +
200      '<path d="M4 5h16l-6.2 7.1V19l-3.6-1.8v-5.1L4 5z" fill="currentColor"/>' +
201      "</svg>" +
202      "</i>" +
203      '<span class="font_upper_md font-bold darken dotted">Фильтр</span>' +
204      "</div>" +
205      '<div class="controls-hr"></div>';
206
207    panel.insertAdjacentElement("afterbegin", filter);
208  }
209
210  function buildMobileCatalogMeta() {
211    rememberBrandSortPanel();
212
213    const panel = getMobileFilterPanel();
214
215    if (!panel) {
216      return;
217    }
218
219    panel.querySelectorAll(".cream-mobile-catalog-meta").forEach(function (node) {
220      node.remove();
221    });
222
223    if (!mediaQuery.matches) {
224      return;
225    }
226
227    ensureBrandFilterButton(panel);
228
229    const filterButton = panel.querySelector(".filter-panel__filter");
230    const sort = panel.querySelector(".filter-panel__sort .dropdown-select");
231
232    if (!filterButton || !sort) {
233      return;
234    }
235
236    const count = getCatalogCount();
237    const row = document.createElement("div");
238    row.className = "cream-mobile-catalog-meta";
239
240    const countNode = document.createElement("div");
241    countNode.className = "cream-mobile-catalog-count";
242    countNode.textContent = count
243      ? count + " " + getPlural(count, ["товар", "товара", "товаров"])
244      : "";
245
246    const sortNode = document.createElement("div");
247    sortNode.className = "cream-mobile-catalog-sort";
248    sortNode.appendChild(sort.cloneNode(true));
249    enhanceMobileSort(sortNode);
250
251    row.appendChild(countNode);
252    row.appendChild(sortNode);
253    filterButton.insertAdjacentElement("afterend", row);
254  }
255
256  let mobileCatalogMetaTimer = null;
257
258  function scheduleMobileCatalogMeta() {
259    if (mobileCatalogMetaTimer) {
260      window.clearTimeout(mobileCatalogMetaTimer);
261    }
262
263    mobileCatalogMetaTimer = window.setTimeout(function () {
264      restoreBrandSortPanel();
265      buildMobileCatalogMeta();
266      tuneMobileFilterSheet();
267    }, 80);
268  }
269
270  function tuneMobileFilterSheet() {
271    const filter = document.querySelector("#mobilefilter");
272
273    if (!filter) {
274      return;
275    }
276
277    const brandFilter = filter.querySelector(".brand-smart-filter .bx_filter, .bx_filter");
278    const filterParameters = filter.querySelector(".bx_filter_parameters");
279
280    if (brandFilter && filterParameters && !filter.querySelector(".bx_filter_parameters_box.title")) {
281      const titleBox = document.createElement("div");
282      titleBox.className = "bx_filter_parameters_box title cream-mobile-filter-title";
283      titleBox.innerHTML =
284        '<div class="bx_filter_parameters_box_title filter_title">' +
285        '<span class="font_upper_md font-bold">Фильтры</span>' +
286        '<i class="svg svg-inline-icon svg-close close-icons" aria-hidden="true">' +
287        '<svg xmlns="http://www.w3.org/2000/svg" width="12.031" height="12" viewBox="0 0 12.031 12">' +
288        '<path class="cls-1" d="M289.414,36.986l4.307,4.307a1,1,0,0,1-1.414,1.414L288,38.4l-4.307,4.307a1,1,0,0,1-1.415-1.414l4.308-4.307-4.294-4.294a1,1,0,0,1,1.414-1.414L288,35.572l4.294-4.294a1,1,0,0,1,1.414,1.414Z" transform="translate(-282 -31)"/>' +
289        "</svg>" +
290        "</i>" +
291        "</div>";
292
293      filterParameters.insertAdjacentElement("beforebegin", titleBox);
294    }
295
296    const title = filter.querySelector(".bx_filter_parameters_box.title .filter_title span");
297
298    if (title) {
299      title.textContent = "Фильтры";
300    }
301
302    const priceBox = filter.querySelector(".bx_filter_parameters_box.prices");
303
304    if (priceBox) {
305      priceBox.classList.add("active");
306      priceBox.setAttribute("data-expanded", "Y");
307
308      const priceBlock = priceBox.querySelector(".bx_filter_block");
309
310      if (priceBlock) {
311        priceBlock.style.display = "block";
312      }
313    }
314  }
315
316  function submitBrandMobileFilter(button) {
317    const form = button.closest("form.smartfilter");
318
319    if (
320      !form ||
321      !button.closest("#mobilefilter") ||
322      window.location.pathname.indexOf("/brands/") !== 0
323    ) {
324      return false;
325    }
326
327    const params = new URLSearchParams();
328
329    Array.prototype.forEach.call(form.elements, function (element) {
330      if (!element.name || element.disabled) {
331        return;
332      }
333
334      const type = (element.type || "").toLowerCase();
335
336      if ((type === "checkbox" || type === "radio") && !element.checked) {
337        return;
338      }
339
340      if ((type === "button" || type === "submit" || type === "reset") && element !== button) {
341        return;
342      }
343
344      const value = (element.value || "").trim();
345
346      if (value !== "") {
347        params.append(element.name, value);
348      }
349    });
350
351    params.set("set_filter", "Y");
352
353    const action = form.getAttribute("action") || window.location.pathname;
354    const target = action + (action.indexOf("?") === -1 ? "?" : "&") + params.toString();
355
356    const smartFilterInstance = window.smartFilterbrand || window.smartFilter;
357
358    if (smartFilterInstance && typeof smartFilterInstance.filterCatalog === "function") {
359      smartFilterInstance.filterCatalog(target, "Y");
360
361      if (typeof window.CloseMobileFilter === "function") {
362        window.CloseMobileFilter();
363      }
364
365      return true;
366    }
367
368    window.location.href = target;
369    return true;
370  }
371
372  function handleBrandMobileFilterSubmit(event) {
373    const button = event.target.closest("#mobilefilter .bx_filter_search_button");
374
375    if (!button) {
376      return;
377    }
378
379    const lastSubmit = parseInt(button.getAttribute("data-cream-mobile-submit-ts") || "0", 10);
380
381    if (lastSubmit && Date.now() - lastSubmit < 800) {
382      event.preventDefault();
383      event.stopPropagation();
384
385      if (typeof event.stopImmediatePropagation === "function") {
386        event.stopImmediatePropagation();
387      }
388
389      return;
390    }
391
392    button.setAttribute("data-cream-mobile-submit-ts", String(Date.now()));
393
394    if (!submitBrandMobileFilter(button)) {
395      button.removeAttribute("data-cream-mobile-submit-ts");
396      return;
397    }
398
399    event.preventDefault();
400    event.stopPropagation();
401
402    if (typeof event.stopImmediatePropagation === "function") {
403      event.stopImmediatePropagation();
404    }
405  }
406
407  function buildMobileSectionsBox(source) {
408    const box = document.createElement("div");
409    box.className = "bx_filter_parameters_box prop_type_L cream-filter-sections-box";
410    box.setAttribute("data-expanded", "N");
411    box.setAttribute("data-prop_code", "cream_catalog_sections");
412    box.setAttribute("data-prop_inline", "");
413    box.setAttribute("data-property_id", "CREAM_CATALOG_SECTIONS");
414
415    const modef = document.createElement("span");
416    modef.className = "bx_filter_container_modef";
417    modef.setAttribute("data-f", "\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c");
418    modef.setAttribute("data-fi", "\u0442\u043e\u0432\u0430\u0440");
419    modef.setAttribute("data-fr", "\u0442\u043e\u0432\u0430\u0440\u0430");
420    modef.setAttribute("data-frm", "\u0442\u043e\u0432\u0430\u0440\u043e\u0432");
421    box.appendChild(modef);
422
423    const title = document.createElement("div");
424    title.className = "bx_filter_parameters_box_title title rounded3 box-shadow-sm";
425    const titleText = document.createElement("div");
426    titleText.className = "text";
427    const titleSpan = document.createElement("span");
428    titleSpan.textContent = "\u0420\u0430\u0437\u0434\u0435\u043b\u044b";
429    const countSelected = document.createElement("span");
430    countSelected.className = "count_selected";
431    titleText.appendChild(titleSpan);
432    titleText.appendChild(countSelected);
433    title.appendChild(titleText);
434
435    const arrow = document.createElement("i");
436    arrow.className = "svg svg-inline-down colored_theme_hover_bg-el";
437    arrow.setAttribute("aria-hidden", "true");
438    arrow.innerHTML =
439      '<svg xmlns="http://www.w3.org/2000/svg" width="5" height="3" viewBox="0 0 5 3"><path class="cls-1" d="M250,80h5l-2.5,3Z" transform="translate(-250 -80)"/></svg>';
440    title.appendChild(arrow);
441
442    const block = document.createElement("div");
443    block.className = "bx_filter_block";
444
445    const container = document.createElement("div");
446    container.className = "bx_filter_parameters_box_container scrollblock";
447
448    const clone = source.cloneNode(true);
449    clone.classList.add("cream-filter-sections");
450    clone.querySelectorAll("[id]").forEach(function (node) {
451      node.removeAttribute("id");
452    });
453
454    container.appendChild(clone);
455    block.appendChild(container);
456    box.appendChild(title);
457    box.appendChild(block);
458
459    return box;
460  }
461
462  function placeSectionsInMobileFilter() {
463    removeMobileSectionClones();
464
465    if (!mediaQuery.matches) {
466      return;
467    }
468
469    const source = document.querySelector(".top-content-block > .section-block");
470    const filterParameters =
471      document.querySelector("#mobilefilter .bx_filter_parameters") ||
472      document.querySelector(".filter-compact-block .bx_filter_parameters");
473
474    if (!source || !filterParameters) {
475      return;
476    }
477
478    const priceBox = filterParameters.querySelector(".bx_filter_parameters_box.prices");
479    const sortBox = filterParameters.querySelector(".bx_sort_filter");
480    const sectionsBox = buildMobileSectionsBox(source);
481
482    if (priceBox && priceBox.parentNode === filterParameters) {
483      priceBox.insertAdjacentElement("afterend", sectionsBox);
484    } else if (sortBox && sortBox.parentNode === filterParameters) {
485      sortBox.insertAdjacentElement("afterend", sectionsBox);
486    } else {
487      filterParameters.insertAdjacentElement("afterbegin", sectionsBox);
488    }
489
490    tuneMobileFilterSheet();
491  }
492
493  placeSectionsInMobileFilter();
494  buildMobileCatalogMeta();
495  tuneMobileFilterSheet();
496
497  ["pointerdown", "touchstart", "mousedown", "click"].forEach(function (eventName) {
498    document.addEventListener(eventName, handleBrandMobileFilterSubmit, true);
499  });
500
501  document.addEventListener("click", function (event) {
502    if (event.target.closest(".bx-filter-title")) {
503      setTimeout(placeSectionsInMobileFilter, 0);
504      setTimeout(placeSectionsInMobileFilter, 150);
505      setTimeout(tuneMobileFilterSheet, 150);
506    }
507
508    const mobileSortTitle = event.target.closest(
509      ".cream-mobile-catalog-sort .dropdown-select__title"
510    );
511
512    document.querySelectorAll(".cream-mobile-catalog-sort .dropdown-select.opened").forEach(function (node) {
513      if (!mobileSortTitle || node !== mobileSortTitle.closest(".dropdown-select")) {
514        node.classList.remove("opened");
515      }
516    });
517
518    if (mobileSortTitle) {
519      event.preventDefault();
520      mobileSortTitle.closest(".dropdown-select").classList.toggle("opened");
521    }
522  });
523
524  window.addEventListener("resize", function () {
525    placeSectionsInMobileFilter();
526    scheduleMobileCatalogMeta();
527  });
528
529  if (window.jQuery) {
530    window.jQuery(document).ajaxComplete(function () {
531      setTimeout(placeSectionsInMobileFilter, 100);
532      [100, 300, 700].forEach(function (delay) {
533        setTimeout(scheduleMobileCatalogMeta, delay);
534      });
535    });
536  }
537
538  if (window.BX && typeof window.BX.addCustomEvent === "function") {
539    ["onAjaxSuccessFilter", "onCompleteAction"].forEach(function (eventName) {
540      window.BX.addCustomEvent(eventName, function () {
541        [50, 250, 600].forEach(function (delay) {
542          setTimeout(scheduleMobileCatalogMeta, delay);
543        });
544      });
545    });
546  }
547
548  if (window.MutationObserver && window.location.pathname.indexOf("/brands/") === 0) {
549    const observerTarget = document.querySelector(".middle > .container") || document.body;
550    const brandFilterObserver = new MutationObserver(function (mutations) {
551      const shouldRebuild = mutations.some(function (mutation) {
552        return mutation.type === "childList" && (mutation.addedNodes.length || mutation.removedNodes.length);
553      });
554
555      if (shouldRebuild) {
556        scheduleMobileCatalogMeta();
557      }
558    });
559
560    brandFilterObserver.observe(observerTarget, {
561      childList: true,
562      subtree: true,
563    });
564  }
565});

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.