PageSourceSearch

https://vecrus-beauty.com/bitrix/templates/aspro_max/js/autoload/item-action.js

js vecrus-beauty.com collected 2026-10-08 23:16:59 UTC 20,332 bytes, 729 lines download raw bytes

1if (typeof window.JItemAction === "undefined") {
2  // class JItemAction
3  JItemAction = function (node, config) {
4    node = typeof node === "object" && node && node instanceof Node ? node : null;
5    config = typeof config === "object" && config ? config : {};
6
7    this.node = node;
8
9    var _private = {
10      inited: false,
11      data: null,
12      config: {
13        bindEvents: true,
14        changeState: true,
15        fireGoals: true,
16      },
17    };
18
19    let _config = Object.assign({}, _private.config, config);
20
21    Object.defineProperties(this, {
22      inited: {
23        get: function () {
24          return _private.inited;
25        },
26        set: function (value) {
27          if (value) {
28            _private.inited = true;
29          }
30        },
31      },
32
33      config: {
34        get: function () {
35          return _config;
36        },
37      },
38
39      data: {
40        get: function () {
41          let data = null;
42
43          if (this.valid) {
44            data = this.node.dataset;
45          }
46
47          if (_private.data) {
48            data = _private.data;
49          }
50
51          return Object.assign({}, data);
52        },
53        set: function (data) {
54          _private.data = data;
55        },
56      },
57    });
58
59    this.init();
60  };
61
62  JItemAction.prototype = {
63    constructor: JItemAction,
64    busy: false,
65    parentNode: null,
66    prevState: null,
67    activeClass: "added in",
68
69    get class() {
70      return this.constructor.name;
71    },
72
73    get action() {
74      return "";
75    },
76
77    get requestUrl() {
78      return `aspro:max.ItemAction.${this.action}`;
79    },
80
81    get valid() {
82      return this.node && this.action;
83    },
84
85    get state() {
86      if (!this.config.changeState) {
87        return true;
88      }
89      return this.valid && BX.hasClass(this.node, this.activeClass);
90    },
91
92    set state(value) {
93      if (this.valid && this.config.changeState) {
94        this.node.removeAttribute("style"); //for sku
95        if (value != this.state) {
96          if (value) {
97            BX.addClass(this.node, this.activeClass);
98          } else {
99            BX.removeClass(this.node, this.activeClass);
100          }
101
102          let title = this.getStateTitle(value);
103          this.node.setAttribute("title", title);
104
105          let button = this.node.querySelector(".info-buttons__item-text");
106          if (button) {
107            button.setAttribute("title", title);
108          }
109
110          if (BX.hasClass(this.node, "btn")) {
111            const $likeText = this.node.querySelector(".like-text");
112            if ($likeText) {
113              $likeText.textContent = title;
114            }
115          }
116        }
117      }
118    },
119
120    init: function () {
121      if (!this.inited) {
122        this.inited = true;
123
124        if (this.valid) {
125          this.node.itemAction = this;
126          this.parentNode = this.node.parentElement;
127
128          if (this.data.offers === "Y") {
129            this.data = this.node.dataset;
130          }
131
132          if (this.config.bindEvents) {
133            this.unbindAllEvents();
134            this.bindEvents();
135          }
136        }
137      }
138    },
139
140    bindEvents: function () {
141      if (this.valid) {
142        if (typeof this.handlers.onClickNode === "function") {
143          BX.bind(this.node, "click", BX.proxy(this.handlers.onClickNode, this));
144        }
145      }
146    },
147
148    unbindEvents: function () {
149      if (this.valid) {
150        if (typeof this.handlers.onClickNode === "function") {
151          BX.unbind(this.node, "click", BX.proxy(this.handlers.onClickNode, this));
152        }
153      }
154    },
155
156    unbindAllEvents: function () {
157      if (this.valid) {
158        BX.unbindAll(this.node, "click");
159      }
160    },
161
162    fireEvent: function (event) {
163      if (this.valid && !this.busy && typeof event === "object" && event) {
164        let eventType = event.type;
165        if (eventType) {
166          if (eventType === "click") {
167            BX.proxy(this.handlers.onClickNode, this)(event);
168          }
169        }
170      }
171    },
172
173    isStateChanged: function () {
174      return this.prevState !== null && this.prevState != this.state;
175    },
176
177    isItemChanged: function () {
178      return this.node !== null && this.node.dataset["item"] != this.data.item;
179    },
180
181    getStateTitle: function (state) {
182      if (this.valid) {
183        if (state) {
184          return this.node.getAttribute("data-title_added") || "";
185        } else {
186          return this.node.getAttribute("data-title") || "";
187        }
188      }
189
190      return "";
191    },
192
193    getStateGoalCode: function (state) {
194      return "goal_" + this.action + (state ? "_add" : "_remove");
195    },
196
197    showStateNotice: function (state) {
198      this.showNotice([this.node], state);
199    },
200    showNotice: function (items, state = 1) {
201      if (this.valid && typeof JNoticeSurface === "function") {
202        let surface = JNoticeSurface.get();
203        let actionCapitalize = this.action.replace(/^\w/, (c) => c.toUpperCase());
204        let noticeFunc = "onAdd2" + actionCapitalize;
205
206        if (noticeFunc && typeof surface[noticeFunc] === "function") {
207          surface[noticeFunc](items, state);
208        }
209      }
210    },
211
212    updateState: function () {
213      if (this.valid && !this.busy) {
214        this.busy = true;
215
216        this.node.blur();
217
218        this.prevState = this.state;
219
220        this.sendRequest();
221      }
222    },
223
224    collectRequestData: async function () {
225      const data = { fields: {} };
226
227      data["fields"] = this.data;
228      data["fields"]["state"] = Number(this.state);
229
230      return data;
231    },
232
233    sendRequest: function () {
234      if (this.valid) {
235        this.collectRequestData()
236          .then((data) => {
237            BX.ajax.runAction(this.requestUrl, { data }).then(
238              (response) => {
239                if (typeof this.onRequestSuccess === "function") {
240                  this.onRequestSuccess(response);
241                }
242
243                if (typeof this.onRequestComplete === "function") {
244                  this.onRequestComplete(data);
245                }
246              },
247              (response) => {
248                if (typeof this.onRequestFailure === "function") {
249                  this.onRequestFailure(response);
250                }
251
252                if (typeof this.onRequestComplete === "function") {
253                  this.onRequestComplete(data);
254                }
255              }
256            );
257          })
258          .catch(() => {
259            setTimeout(() => {
260              if (this.isStateChanged()) {
261                // toggle state back
262                this.state = this.prevState;
263                this.prevState = null;
264              }
265
266              if (this.parentNode) {
267                BX.removeClass(this.parentNode, "loadings");
268              }
269
270              this.busy = false;
271            }, 0);
272          });
273      }
274    },
275
276    onRequestComplete: function (config) {
277      setTimeout(() => {
278        if (this.parentNode) {
279          BX.removeClass(this.parentNode, "loadings");
280        }
281        this.busy = false;
282      }, 0);
283    },
284
285    onRequestSuccess: function (response) {
286      if (response.status === "success") {
287        if (this.action && response.data) {
288          let actionUpper = this.action.toUpperCase();
289
290          if (typeof arAsproCounters !== "object") {
291            arAsproCounters = {};
292          }
293
294          if (typeof arAsproCounters[actionUpper] !== "object") {
295            arAsproCounters[actionUpper] = {};
296          }
297
298          const data = response.data;
299          if ("items" in data) {
300            arAsproCounters[actionUpper].ITEMS = data.items;
301          }
302
303          if ("count" in data) {
304            arAsproCounters[actionUpper].COUNT = data.count;
305          }
306
307          if ("title" in data) {
308            arAsproCounters[actionUpper].TITLE = data.title;
309          }
310
311          // update badges
312          if (
313            this.class &&
314            typeof window[this.class] === "function" &&
315            typeof window[this.class].markBadges === "function"
316          ) {
317            window[this.class].markBadges();
318          }
319
320          let state = this.state;
321
322          // mark items
323          if (
324            this.class &&
325            typeof window[this.class] === "function" &&
326            typeof window[this.class].markItems === "function"
327          ) {
328            window[this.class].markItems();
329          }
330
331          if (this.isStateChanged()) {
332            // show notice
333            this.showStateNotice(state);
334
335            if (this.config.fireGoals) {
336              // fire goal
337              BX.onCustomEvent("onCounterGoals", [
338                {
339                  goal: this.getStateGoalCode(state),
340                  params: {
341                    id: this.node.getAttribute("data-item"),
342                  },
343                },
344              ]);
345            }
346          }
347
348          this.onCompleteEvent();
349        }
350      } else {
351        console.error(response);
352
353        if (this.isStateChanged()) {
354          // toggle state back
355          this.state = this.prevState;
356        }
357
358        // show error notice
359        if (typeof JNoticeSurface === "function") {
360          let surface = JNoticeSurface.get();
361          response.error = this.getMessageFromErrors(response.errors);
362
363          surface.onResultError && surface.onResultError(response);
364        }
365      }
366    },
367
368    onRequestFailure: function (xhr) {
369      if (this.isStateChanged()) {
370        // toggle state back
371        this.state = this.prevState;
372      }
373
374      // show error notice
375      if (typeof JNoticeSurface === "function") {
376        let surface = JNoticeSurface.get();
377        xhr.statusText = this.getMessageFromErrors(xhr.errors);
378
379        surface.onRequestError && surface.onRequestError(xhr);
380      }
381    },
382
383    getMessageFromErrors: function (errors) {
384      let messages = [];
385      if (errors.length) {
386        errors.forEach((error) => {
387          messages.push(error.message);
388        });
389      }
390      return messages.join("<br>");
391    },
392
393    onCompleteEvent: function () {
394      this.finalAction();
395    },
396
397    finalAction: function () {
398      this.updateDropdownBlocks(this.action);
399    },
400
401    updateDropdownBlocks: function (action) {
402      document.querySelectorAll(`.dropdown-${action}`).forEach((node) => {
403        node.classList.remove("loaded");
404      });
405    },
406
407    handlers: {
408      onClickNode: function (event) {
409        if (this.valid && !this.busy) {
410          if (!event) {
411            event = window.event;
412          }
413
414          let target = event.target || event.srcElement;
415
416          if (typeof target !== "undefined" && target) {
417            this.busy = true;
418
419            this.node.blur();
420
421            this.prevState = this.state;
422            this.state = !this.state;
423
424            this.sendRequest();
425          }
426        }
427      },
428    },
429  };
430
431  JItemAction.checkItemAction = function (node) {
432    return node.itemAction && node.itemAction instanceof JItemAction;
433  };
434
435  JItemAction.getItemAction = function (node) {
436    return node.itemAction;
437  };
438
439  // factory: returns a concrete JItemAction instance
440  JItemAction.factory = function (node, config) {
441    if (typeof node === "object" && node && node instanceof Node) {
442      if (JItemAction.checkItemAction(node)) {
443        return JItemAction.getItemAction(node);
444      } else {
445        let action = (node.getAttribute("data-action") || "").trim();
446        if (action) {
447          let actionCapitalize = action.replace(/^\w/, (c) => c.toUpperCase());
448          let className = "JItemAction" + actionCapitalize;
449          if (typeof window[className] === "function") {
450            return new window[className](node, config);
451          }
452        }
453      }
454    }
455
456    return new window.JItemAction(node, config);
457  };
458
459  // class JItemActionFavorite
460  JItemActionFavorite = function (node, config) {
461    JItemAction.apply(this, arguments);
462  };
463
464  JItemActionFavorite.prototype = Object.create(JItemAction.prototype);
465  JItemActionFavorite.prototype.constructor = JItemActionFavorite;
466  Object.defineProperties(JItemActionFavorite.prototype, {
467    action: {
468      get() {
469        return "favorite";
470      },
471    },
472  });
473
474  JItemActionFavorite.prototype.getStateGoalCode = function (state) {
475    return "goal_wish" + (state ? "_add" : "_remove");
476  };
477
478  // set current count into badges
479  JItemActionFavorite.markBadges = function () {
480    if (
481      typeof arAsproCounters === "object" &&
482      arAsproCounters &&
483      typeof arAsproCounters.FAVORITE === "object" &&
484      arAsproCounters.FAVORITE &&
485      typeof arAsproCounters.FAVORITE.COUNT !== "undefined"
486    ) {
487      let blocks = Array.prototype.slice.call(document.querySelectorAll(".basket-link.delay .js-count"));
488      if (blocks.length) {
489        for (let i in blocks) {
490          blocks[i].textContent = arAsproCounters.FAVORITE.COUNT;
491          if (arAsproCounters.FAVORITE.COUNT > 0) {
492            BX.removeClass(blocks[i], "empted");
493            BX.addClass(blocks[i].closest(".basket-link.delay"), "basket-count");
494            BX.removeClass(blocks[i].closest(".basket-link.delay"), "counter-state--empty");
495          } else {
496            BX.addClass(blocks[i], "empted");
497            BX.removeClass(blocks[i].closest(".basket-link.delay"), "basket-count");
498            BX.addClass(blocks[i].closest(".basket-link.delay"), "counter-state--empty");
499          }
500        }
501
502        JItemAction.prototype.updateDropdownBlocks(JItemActionFavorite.prototype.action)
503      }
504    }
505  };
506
507  // setup active state for all current items
508  JItemActionFavorite.markItems = function () {
509    if (
510      typeof arAsproCounters === "object" &&
511      arAsproCounters &&
512      typeof arAsproCounters.FAVORITE === "object" &&
513      arAsproCounters.FAVORITE &&
514      typeof arAsproCounters.FAVORITE.ITEMS === "object" &&
515      arAsproCounters.FAVORITE.ITEMS
516    ) {
517      let blocks = Array.prototype.slice.call(
518        document.querySelectorAll('.js-item-action.added.in[data-action="favorite"]')
519      );
520      if (blocks.length) {
521        for (let y in blocks) {
522          let id = BX.data(blocks[y], "item");
523          if (id) {
524            if (!arAsproCounters.FAVORITE.ITEMS[id] || BX.data(blocks[y], "offers") === "Y") {
525              let itemAction = JItemAction.checkItemAction(blocks[y]) ? JItemAction.getItemAction(blocks[y]) : "";
526
527              if (BX.data(blocks[y], "offers") === "Y") {
528                if (itemAction && itemAction.isItemChanged()) {
529                  itemAction = new this(blocks[y]);
530                }
531              }
532
533              if (!itemAction) {
534                itemAction = new this(blocks[y]);
535              }
536
537              itemAction.state = false;
538            }
539          }
540        }
541      }
542
543      if (arAsproCounters.FAVORITE.ITEMS) {
544        for (let i in arAsproCounters.FAVORITE.ITEMS) {
545          let id = arAsproCounters.FAVORITE.ITEMS[i];
546          let blocks = Array.prototype.slice.call(
547            document.querySelectorAll('.js-item-action[data-action="favorite"][data-item="' + id + '"]:not(.added.in)')
548          );
549
550          if (blocks.length) {
551            for (let y in blocks) {
552              let itemAction = JItemAction.checkItemAction(blocks[y])
553                ? JItemAction.getItemAction(blocks[y])
554                : new this(blocks[y]);
555              itemAction.state = true;
556            }
557          }
558        }
559      }
560    }
561  };
562
563  // class JItemActionCompare
564  JItemActionCompare = function (node, config) {
565    JItemAction.apply(this, arguments);
566  };
567
568  JItemActionCompare.prototype = Object.create(JItemAction.prototype);
569  JItemActionCompare.prototype.constructor = JItemActionCompare;
570  Object.defineProperties(JItemActionCompare.prototype, {
571    action: {
572      get() {
573        return "compare";
574      },
575    },
576  });
577
578  // setup active state for all current items
579  JItemActionCompare.markItems = function () {
580    if (
581      typeof arAsproCounters === "object" &&
582      arAsproCounters &&
583      typeof arAsproCounters.COMPARE === "object" &&
584      arAsproCounters.COMPARE &&
585      typeof arAsproCounters.COMPARE.ITEMS === "object"
586    ) {
587      let blocks = Array.prototype.slice.call(
588        document.querySelectorAll('.js-item-action.added.in[data-action="compare"]')
589      );
590      if (blocks.length) {
591        for (let y in blocks) {
592          let id = BX.data(blocks[y], "item");
593          if (id) {
594            if (!arAsproCounters.COMPARE.ITEMS[id] || BX.data(blocks[y], "offers") === "Y") {
595              let itemAction = JItemAction.checkItemAction(blocks[y]) ? JItemAction.getItemAction(blocks[y]) : "";
596
597              if (BX.data(blocks[y], "offers") === "Y") {
598                if (itemAction && itemAction.isItemChanged()) {
599                  itemAction = new this(blocks[y]);
600                }
601              }
602
603              if (!itemAction) {
604                itemAction = new this(blocks[y]);
605              }
606
607              itemAction.state = false;
608            }
609          }
610        }
611      }
612
613      if (arAsproCounters.COMPARE.ITEMS) {
614        for (let i in arAsproCounters.COMPARE.ITEMS) {
615          let id = arAsproCounters.COMPARE.ITEMS[i];
616          let blocks = Array.prototype.slice.call(
617            document.querySelectorAll('.js-item-action[data-action="compare"][data-item="' + id + '"]:not(.added.in)')
618          );
619
620          if (blocks.length) {
621            for (let y in blocks) {
622              let itemAction = JItemAction.checkItemAction(blocks[y])
623                ? JItemAction.getItemAction(blocks[y])
624                : new this(blocks[y]);
625              itemAction.state = true;
626            }
627          }
628        }
629      }
630    }
631  };
632
633  // set current count into badges
634  JItemActionCompare.markBadges = function () {
635    if (
636      typeof arAsproCounters === "object" &&
637      arAsproCounters &&
638      typeof arAsproCounters.COMPARE === "object" &&
639      arAsproCounters.COMPARE &&
640      typeof arAsproCounters.COMPARE.COUNT !== "undefined"
641    ) {
642      let blocks = Array.prototype.slice.call(document.querySelectorAll(".compare .js-count"));
643      if (blocks.length) {
644        for (let i in blocks) {
645          blocks[i].textContent = arAsproCounters.COMPARE.COUNT;
646          if (arAsproCounters.COMPARE.COUNT > 0) {
647            BX.removeClass(blocks[i], "empted");
648            BX.addClass(blocks[i].closest(".compare"), "basket-count");
649            BX.removeClass(blocks[i].closest(".compare"), "counter-state--empty");
650          } else {
651            BX.addClass(blocks[i], "empted");
652            BX.removeClass(blocks[i].closest(".compare"), "basket-count");
653            BX.addClass(blocks[i].closest(".compare"), "counter-state--empty");
654          }
655        }
656        JItemAction.prototype.updateDropdownBlocks(JItemActionCompare.prototype.action)
657      }
658    }
659  };
660
661  JItemAction.actual = function () {
662    if (typeof JItemActionFavorite === "function") {
663      JItemActionFavorite.markItems();
664      JItemActionFavorite.markBadges();
665    }
666    if (typeof JItemActionCompare === "function") {
667      JItemActionCompare.markItems();
668      JItemActionCompare.markBadges();
669    }
670  };
671
672  // bind handler for click on .js-item-action
673  BX.bindDelegate(
674    document,
675    "click",
676    {
677      class: "js-item-action",
678    },
679    function (event) {
680      if (!event) {
681        event = window.event;
682      }
683
684      BX.PreventDefault(event);
685
686      let target = event.target || event.srcElement;
687
688      if (typeof target !== "undefined" && target) {
689        if (!target.closest(".opt_action")) {
690          JItemAction.factory(this).fireEvent(event);
691        }
692      }
693    }
694  );
695
696  // on complete loading content by ajax
697  BX.addCustomEvent("onCompleteAction", function (eventdata) {
698    try {
699      if (eventdata.action === "ajaxContentLoaded") {
700        JItemAction.actual();
701      }
702    } catch (e) {
703      console.error(e);
704    }
705  });
706
707  BX.addCustomEvent("onSetBasketStatusBtn", function (eventdata) {
708    JItemAction.actual();
709  });
710
711  BX.addCustomEvent("onSetItemButtonStatus", function (eventdata) {
712    JItemAction.actual();
713  });
714
715  BX.addCustomEvent("onAjaxResponesTabs", function (eventdata) {
716    JItemAction.actual();
717    setBasketStatusBtn(true);
718  });
719
720  BX.addCustomEvent("onFinalActionSKUInfo", function (eventdata) {
721    JItemAction.actual();
722  });
723
724  /*
725  // set current items states
726  readyDOM(function () {
727    JItemAction.actual();
728  }); */
729}

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.