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.