1var AEC = (function() 2{ 3 return { 4 add: function(context, dataLayer) 5 { 6 let element = context, qty = 1, variant = [], variant_attribute_option = [], products = []; 7 8 document.querySelectorAll('input[name=qty]:checked, [name=qty]').forEach(element => 9 { 10 qty = element.value; 11 }); 12 13 qty = Math.abs(qty); 14 15 if (isNaN(qty)) 16 { 17 qty = 1; 18 } 19 20 if ('undefined' !== typeof jQuery) 21 { 22 var form = jQuery(context).closest('form'); 23 24 if (form.length) 25 { 26 if (!form.valid()) 27 { 28 return true; 29 } 30 } 31 } 32 33 if (!AEC.gtm()) 34 { 35 if (element.dataset.click) 36 { 37 AEC.Time.track(dataLayer, AEC.Const.TIMING_CATEGORY_ADD_TO_CART, element.dataset.name, element.dataset.category); 38 39 eval(element.dataset.click); 40 } 41 42 return true; 43 } 44 45 if(element.dataset.configurable) 46 { 47 var variants = []; 48 49 document.querySelectorAll('[name^="super_attribute"]').forEach(attribute => 50 { 51 if (attribute.matches('select')) 52 { 53 var name = attribute.getAttribute('name'), id = name.substring(name.indexOf('[') + 1, name.lastIndexOf(']')); 54 55 if (attribute.selectedIndex) 56 { 57 var option = attribute.options[attribute.selectedIndex]; 58 59 if (option) 60 { 61 variants.push( 62 { 63 id: id, 64 option: option.label, 65 text: option.text 66 }); 67 } 68 } 69 } 70 71 if (attribute.matches('input') && -1 != attribute.type.indexOf('radio')) 72 { 73 if (attribute.parentNode.classList.contains('swatch-option-selected') || attribute.checked) 74 { 75 Object.entries(AEC.SUPER).forEach(([key, super_attribute]) => 76 { 77 if (-1 != attribute.name.indexOf("super_attribute[" + super_attribute.id + "]")) 78 { 79 let variant = { 80 id: super_attribute.id, 81 text: super_attribute.label, 82 option: attribute.value 83 }; 84 85 variants.push(variant); 86 87 } 88 }); 89 } 90 } 91 }); 92 93 /** 94 * Colour Swatch support 95 */ 96 if (!variants.length) 97 { 98 Object.entries(AEC.SUPER).forEach(([key, attribute]) => 99 { 100 var swatch = document.querySelectorAll('div[attribute-code="' + attribute.code + '"], div[data-attribute-code="' + attribute.code + '"]'); 101 102 swatch.forEach(element => 103 { 104 let variant = 105 { 106 id: attribute.id, 107 text: '', 108 option: null 109 }; 110 111 var select = element.querySelector('select'); 112 113 if (select) 114 { 115 if (select.selectedIndex) 116 { 117 var option = select.options[select.selectedIndex]; 118 119 if (option) 120 { 121 variant.text = option.text; 122 variant.option = option.value; 123 } 124 } 125 } 126 else 127 { 128 var span = element.querySelector('span.swatch-attribute-selected-option'); 129 130 if (span) 131 { 132 variant.text = span.innerHTML; 133 variant.option = span.parentNode.dataset.optionSelected 134 } 135 } 136 137 variants.push(variant); 138 }); 139 }); 140 } 141 142 if (!variants.length) 143 { 144 AEC.EventDispatcher.trigger('ec.variants', variants); 145 } 146 147 var SUPER_SELECTED = []; 148 149 for (i = 0, l = variants.length; i < l; i++) 150 { 151 for (a = 0, b = AEC.SUPER.length; a < b; a++) 152 { 153 if (AEC.SUPER[a].id == variants[i].id) 154 { 155 var text = variants[i].text; 156 157 if (AEC.useDefaultValues) 158 { 159 AEC.SUPER[a].options.forEach(option => 160 { 161 if (parseInt(option.value_index) == parseInt(variants[i].option)) 162 { 163 if (option.hasOwnProperty('admin_label')) 164 { 165 text = option.admin_label; 166 } 167 else if (option.hasOwnProperty('store_label')) 168 { 169 text = option.store_label; 170 } 171 172 } 173 }); 174 } 175 176 variant.push([AEC.SUPER[a].label,text].join(AEC.Const.VARIANT_DELIMITER_ATT)); 177 178 variant_attribute_option.push( 179 { 180 attribute: variants[i].id, 181 option: variants[i].option 182 }) 183 } 184 } 185 } 186 187 if (!variant.length) 188 { 189 if (element.dataset.click) 190 { 191 AEC.Time.track(dataLayer, AEC.Const.TIMING_CATEGORY_ADD_TO_CART, element.dataset.name, element.dataset.category); 192 193 eval(element.dataset.click); 194 } 195 196 return true; 197 } 198 } 199 200 if (element.dataset.grouped) 201 { 202 for (u = 0, y = window.G.length; u < y; u++) 203 { 204 let field = document.querySelector('[name="super_group[' + window.G[u].id + ']"]'); 205 206 if (field) 207 { 208 (qty => 209 { 210 if (qty) 211 { 212 products.push( 213 { 214 'name': window.G[u].name, 215 'id': window.G[u].sku, 216 'price': window.G[u].price, 217 'category': window.G[u].category, 218 'brand': window.G[u].brand, 219 'quantity': qty 220 }); 221 } 222 })(Math.abs(field.value)); 223 } 224 } 225 } 226 else 227 {
228 products.push( 229 { 230 'name': element.dataset.name, 231 'id': 1 === parseInt(element.dataset.useSimple) ? element.dataset.simpleId : element.dataset.id, 232 'price': element.dataset.price, 233 'category': element.dataset.category, 234 'brand': element.dataset.brand, 235 'variant': variant.join(AEC.Const.VARIANT_DELIMITER), 236 'quantity': qty 237 }); 238 } 239 240 for (i = 0, l = products.length; i < l; i++) 241 { 242 (function(product) 243 { 244 Object.entries(AEC.parseJSON(element.dataset.attributes)).forEach(([key, value]) => 245 { 246 product[key] = value; 247 }); 248 249 })(products[i]); 250 } 251 252 var data = 253 { 254 'event': 'addToCart', 255 'eventLabel': element.dataset.name, 256 'ecommerce': 257 { 258 'currencyCode': AEC.currencyCode, 259 'add': 260 { 261 'actionField': 262 { 263 'list': element.dataset.list 264 }, 265 'products': products 266 }, 267 'options': variant_attribute_option 268 }, 269 'currentStore': element.dataset.store 270 }; 271 272 if (AEC.useDefaultValues) 273 { 274 data['currentStore'] = AEC.storeName; 275 } 276 277 /** 278 * Notify listeners 279 */ 280 this.EventDispatcher.trigger('ec.add.data', data); 281 282 /** 283 * Track event 284 */ 285 AEC.Cookie.add(data).push(dataLayer); 286 287 /** 288 * Save backreference 289 */ 290 if (AEC.localStorage) 291 { 292 (function(products) 293 { 294 for (var i = 0, l = products.length; i < l; i++) 295 { 296 AEC.Storage.reference().set( 297 { 298 id: products[i].id, 299 category: products[i].category 300 }); 301 } 302 })(products); 303 } 304 305 /** 306 * Track time 307 */ 308 AEC.Time.track(dataLayer, AEC.Const.TIMING_CATEGORY_ADD_TO_CART, element.dataset.name, element.dataset.category); 309 310 if (AEC.facebook) 311 { 312 if ("undefined" !== typeof fbq) 313 { 314 (function(product, products, fbq) 315 { 316 var content_ids = [], price = 0; 317 318 for (i = 0, l = products.length; i < l; i++) 319 { 320 content_ids.push(products[i].id); 321 322 price += parseFloat(products[i].price); 323 } 324 325 (function(callback) 326 { 327 if (AEC.Const.COOKIE_DIRECTIVE) 328 { 329 AEC.CookieConsent.queue(callback).process(); 330 } 331 else 332 { 333 callback.apply(window,[]); 334 } 335 }) 336 ( 337 (function(product, content_ids, price) 338 { 339 return function() 340 { 341 if ('undefined' === typeof variants) 342 { 343 variants = []; 344 } 345 346 fbq('track', 'AddToCart', 347 { 348 content_name: product, 349 content_ids: content_ids, 350 content_type: !variants.length ? 'product' : 'product_group', 351 value: price, 352 currency: AEC.currencyCode 353 }, 354 { eventID: AEC.UUID.generate({ event: 'AddToCart'}) }); 355 } 356 })(product, content_ids, price) 357 ); 358 359 })(element.dataset.name, products, fbq); 360 } 361 } 362 363 if (element.dataset.click) 364 { 365 eval(element.dataset.click); 366 } 367 368 return true; 369 }, 370 addSwatch: function(context,dataLayer) 371 { 372 var element = context; 373 374 if (window.jQuery) 375 { 376 jQuery(document).on('ajax:addToCart', function() 377 { 378 var attributes = []; 379 380 Object.entries(AEC.parseJSON(element.dataset.swatch)).forEach(([key, value]) => 381 { 382 attributes.push(value); 383 }); 384 385 var option = document.querySelector('.swatch-option.selected'); 386 387 if (!option) 388 { 389 return true; 390 } 391 392 var variant = [[attributes[0].attribute_label, option.getAttribute('aria-label')].join(AEC.Const.VARIANT_DELIMITER_ATT)].join(AEC.Const.VARIANT_DELIMITER); 393 394 var products = 395 [ 396 { 397 'name': element.dataset.name, 398 'id': element.dataset.id, 399 'price': element.dataset.price, 400 'category': element.dataset.category, 401 'brand': element.dataset.brand, 402 'variant': variant, 403 'quantity': 1 404 } 405 ]; 406 407 var data = 408 { 409 'event': 'addToCart', 410 'eventLabel': element.dataset.name, 411 'ecommerce': 412 { 413 'currencyCode': AEC.currencyCode, 414 'add': 415 { 416 'actionField': 417 { 418 'list': element.dataset.list 419 }, 420 'products': products 421 } 422 }, 423 'currentStore': element.dataset.store 424 }; 425 426 AEC.EventDispatcher.trigger('ec.add.swatch.data', data); 427 428 /** 429 * Track event 430 */ 431 AEC.Cookie.add(data).push(dataLayer); 432 433 /** 434 * Track time 435 */ 436 AEC.Time.track(dataLayer, AEC.Const.TIMING_CATEGORY_ADD_TO_CART, element.dataset.name, element.dataset.category); 437 }); 438 } 439 440 return true; 441 }, 442 click: function(context,dataLayer) 443 { 444 var element = context; 445
446 if (!AEC.gtm()) 447 { 448 AEC.Time.track(dataLayer, AEC.Const.TIMING_CATEGORY_PRODUCT_CLICK, element.dataset.name, element.dataset.category); 449 450 return true; 451 } 452 453 var item = 454 { 455 'name': element.dataset.name, 456 'id': element.dataset.id, 457 'price': element.dataset.price, 458 'category': element.dataset.category, 459 'brand': element.dataset.brand, 460 'quantity': element.dataset.quantity, 461 'position': element.dataset.position 462 }; 463 464 Object.entries(AEC.parseJSON(element.dataset.attributes)).forEach(([key, value]) => 465 { 466 item[key] = value; 467 }); 468 469 var data = 470 { 471 'event': 'productClick', 472 'eventLabel': element.dataset.name, 473 'ecommerce': 474 { 475 'click': 476 { 477 'actionField': 478 { 479 'list': element.dataset.list 480 }, 481 'products': 482 [ 483 item 484 ] 485 } 486 }, 487 'currentStore': element.dataset.store 488 }; 489 490 AEC.EventDispatcher.trigger('ec.click.data', data); 491 492 /** 493 * Push data 494 */ 495 AEC.Cookie.click(data).push(dataLayer); 496 497 /** 498 * Track time 499 */ 500 AEC.Time.track(dataLayer, AEC.Const.TIMING_CATEGORY_PRODUCT_CLICK, element.dataset.name, element.dataset.category); 501 502 if (element.dataset.click) 503 { 504 eval(element.dataset.click); 505 } 506 507 return true; 508 }, 509 remove: function(context, dataLayer) 510 { 511 var element = context; 512
513 if (!AEC.gtm()) 514 { 515 AEC.Time.track(dataLayer, AEC.Const.TIMING_CATEGORY_REMOVE_FROM_CART, element.dataset.name, element.dataset.category); 516 } 517 518 var item = 519 { 520 'name': element.dataset.name, 521 'id': element.dataset.id, 522 'price': element.dataset.price, 523 'category': element.dataset.category, 524 'brand': element.dataset.brand, 525 'quantity': element.dataset.quantity 526 }; 527 528 Object.entries(AEC.parseJSON(element.dataset.attributes)).forEach(([key, value]) => 529 { 530 item[key] = value; 531 }); 532 533 var data = 534 { 535 'event': 'removeFromCart', 536 'eventLabel': element.dataset.name, 537 'ecommerce': 538 { 539 'remove': 540 { 541 'actionField': 542 { 543 'list': element.dataset.list 544 }, 545 'products': 546 [ 547 item 548 ] 549 } 550 } 551 }; 552 553 AEC.EventDispatcher.trigger('ec.remove.data', data); 554 555 if (AEC.Message.confirm) 556 { 557 require(['Magento_Ui/js/modal/confirm'], function(confirmation) 558 { 559 confirmation( 560 { 561 title: AEC.Message.confirmRemoveTitle, 562 content: AEC.Message.confirmRemove, 563 actions: 564 { 565 confirm: function() 566 { 567 /** 568 * Track event 569 */ 570 AEC.Cookie.remove(data).push(dataLayer); 571 572 /** 573 * Track time 574 */ 575 AEC.Time.track(dataLayer, AEC.Const.TIMING_CATEGORY_REMOVE_FROM_CART, element.dataset.name); 576 577 /** 578 * Execute standard data-post 579 */ 580 (params => 581 { 582 let form = document.createElement("form"); 583 584 form.setAttribute('method', 'post'); 585 form.setAttribute('action', params.action); 586 587 let formKey = jQuery.cookie('form_key'); 588 589 if (formKey) 590 { 591 params.data['form_key'] = formKey; 592 } 593 594 Object.entries(params.data).forEach(([name, value]) => 595 { 596 let input = document.createElement('input'); 597 598 input.setAttribute('type', 'text'); 599 input.setAttribute('name', name); 600 input.setAttribute('value', value); 601 602 form.append(input); 603 }); 604 605 document.querySelector("body").appendChild(form); 606 607 /** 608 * Submit form 609 */ 610 form.submit(); 611 612 })(AEC.parseJSON(element.dataset.postAction)) 613 }, 614 cancel: function() 615 { 616 return false; 617 }, 618 always: function() 619 { 620 return false; 621 } 622 } 623 }); 624 }); 625 } 626 else 627 { 628 /** 629 * Track event 630 */ 631 AEC.Cookie.remove(data).push(dataLayer); 632 633 /** 634 * Track time 635 */ 636 AEC.Time.track(dataLayer, AEC.Const.TIMING_CATEGORY_REMOVE_FROM_CART, element.dataset.name); 637 } 638 639 return false; 640 }, 641 wishlist: function(context, dataLayer) 642 { 643 var element = context; 644 645 if (!AEC.gtm()) 646 { 647 /** 648 * Track time 649 */ 650 AEC.Time.track(dataLayer, AEC.Const.TIMING_CATEGORY_PRODUCT_WISHLIST, element.dataset.name,'Wishlist'); 651 652 return true; 653 } 654 655 let data = 656 { 657 event: element.dataset.event, 658 eventLabel: element.dataset.eventLabel 659 }; 660 661 AEC.EventDispatcher.trigger('ec.add.wishlist', data, { attributes: element.dataset.eventAttributes }); 662 663 /** 664 * Track event 665 */ 666 AEC.Cookie.wishlist(data).push(dataLayer); 667 668 return true; 669 }, 670 compare: function(context, dataLayer) 671 { 672 var element = context; 673 674 if (!AEC.gtm()) 675 { 676 /** 677 * Track time 678 */ 679 AEC.Time.track(dataLayer, AEC.Const.TIMING_CATEGORY_PRODUCT_COMPARE, element.dataset.name,'Compare'); 680 681 return true; 682 } 683 684 let data = 685 { 686 event: element.dataset.event, 687 eventLabel: element.dataset.eventLabel 688 }; 689 690 AEC.EventDispatcher.trigger('ec.add.compare', data, { attributes: element.dataset.eventAttributes } ); 691 692 /** 693 * Push data 694 */ 695 /** 696 * Track event 697 */ 698 AEC.Cookie.compare(data).push(dataLayer); 699 700 return true; 701 }, 702 Bind: (function() 703 { 704 return { 705 apply: function(parameters) 706 { 707 /** 708 * Merge persistent storage 709 */ 710 AEC.Persist.merge(); 711 712 /** 713 * Push private data 714 */ 715 AEC.Cookie.pushPrivate(); 716 717 document.addEventListener('DOMContentLoaded',() => 718 { 719 document.body.addEventListener('catalogCategoryAddToCartRedirect', () => 720 { 721 dataLayer.push( 722 { 723 event: AEC.Const.CATALOG_CATEGORY_ADD_TO_CART_REDIRECT_EVENT 724 }); 725 }); 726 }); 727 728 if (parameters) 729 { 730 if (parameters.performance) 731 { 732 if (window.performance) 733 { 734 window.onload = function() 735 { 736 setTimeout(function() 737 { 738 var time = performance.timing.loadEventEnd - performance.timing.responseEnd; 739 740 var timePayload = 741 { 742 'event':'performance', 743 'performance': 744 { 745 'timingCategory': 'Load times', 746 'timingVar': 'load', 747 'timingValue': (time % 60000) 748 } 749 }; 750 751 switch(window.google_tag_params.ecomm_pagetype) 752 { 753 case 'home': 754 755 timePayload.performance.timingLabel = 'Home'; 756 757 AEC.CookieConsent.queue(() => 758 { 759 dataLayer.push(timePayload); 760 }).process(); 761 762 break; 763 case 'product': 764 765 timePayload.performance.timingLabel = 'Product'; 766 767 AEC.CookieConsent.queue(() => 768 { 769 dataLayer.push(timePayload); 770 }).process(); 771 772 break; 773 774 case 'category': 775 776 timePayload.performance.timingLabel = 'Category'; 777 778 AEC.CookieConsent.queue(() => 779 { 780 dataLayer.push(timePayload); 781 }).process(); 782 783 break; 784 } 785 786 }, 0); 787 } 788 } 789 } 790 } 791 792 return this; 793 } 794 } 795 })(), 796 Time: (function() 797 { 798 var T = 799 {
800 event: 'trackTime', 801 timingCategory: '', 802 timingVar: '', 803 timingValue: -1, 804 timingLabel: '' 805 }; 806 807 var time = new Date().getTime(); 808 809 return { 810 track: function(dataLayer, category, variable, label) 811 { 812 T.timingValue = (new Date().getTime()) - time; 813 814 if (category) 815 { 816 T.timingCategory = category; 817 } 818 819 if (variable) 820 { 821 T.timingVar = variable; 822 } 823 824 if (label) 825 { 826 T.timingLabel = label; 827 } 828 829 (function(callback) 830 { 831 if (AEC.Const.COOKIE_DIRECTIVE) 832 { 833 AEC.CookieConsent.queue(callback).process(); 834 } 835 else 836 { 837 callback.apply(window,[]); 838 } 839 }) 840 ( 841 (function(dataLayer, T) 842 { 843 return function() 844 { 845 dataLayer.push(T); 846 } 847 })(dataLayer, T) 848 ); 849 }, 850 trackContinue: function(dataLayer, category, variable, label) 851 { 852 this.track(dataLayer, category, variable, label); 853 854 time = new Date().getTime(); 855 } 856 } 857 })(), 858 Persist:(function() 859 { 860 var DATA_KEY = 'persist'; 861 862 var proto = 'undefined' != typeof Storage ? 863 { 864 push: function(key, entity) 865 { 866 /** 867 * Get data 868 */ 869 var data = this.data(); 870 871 /** 872 * Push data 873 */ 874 data[key] = entity; 875 876 /** 877 * Save to local storage 878 */ 879 localStorage.setItem(DATA_KEY, JSON.stringify(data)); 880 881 return this; 882 }, 883 data: function() 884 { 885 var data = localStorage.getItem(DATA_KEY); 886 887 if (null !== data) 888 { 889 return JSON.parse(data); 890 } 891 892 return {}; 893 }, 894 merge: function() 895 { 896 var data = this.data(); 897 var push = 898 { 899 persist: {} 900 }; 901 902 for (var i in data) 903 { 904 push.persist[i] = data[i]; 905 } 906 907 dataLayer.push(push); 908 909 return this; 910 }, 911 clear: function() 912 { 913 /** 914 * Reset private local storage 915 */ 916 localStorage.setItem(DATA_KEY,JSON.stringify({})); 917 918 return this; 919 } 920 } : { 921 push: function(){}, 922 merge: function(){}, 923 clear: function(){} 924 }; 925 926 /** 927 * Constants 928 */ 929 proto.CONST_KEY_PROMOTION = 'persist_promotion'; 930 931 return proto; 932 933 })(), 934 Checkout: (function() 935 { 936 return { 937 init: false, 938 data: {}, 939 tracked: {}, 940 step: function(previous, current, currentCode) 941 { 942 if (!this.init) 943 { 944 return this.fail('Step tracking requires a checkout page.'); 945 } 946 947 if (this.data && this.data.hasOwnProperty('ecommerce')) 948 { 949 this.data.ecommerce.checkout.actionField.step = ++current; 950 951 /** 952 * Notify listeners 953 */ 954 AEC.EventDispatcher.trigger('ec.checkout.step.data', this.data); 955 956 /** 957 * Track checkout step 958 */ 959 AEC.Cookie.checkout(this.data).push(dataLayer); 960 } 961 962 return this; 963 }, 964 stepOption: function(step, option) 965 { 966 if (!option) 967 { 968 return this; 969 } 970 971 if (!this.init) 972 { 973 return this.fail('Step option tracking requires a checkout page.'); 974 } 975 976 977 if (!option.toString().length) 978 { 979 return this; 980 } 981 982 var data = 983 { 984 'event': 'checkoutOption', 985 'ecommerce': 986 { 987 'checkout_option': 988 { 989 'actionField': 990 { 991 'step': step, 992 'option': option 993 } 994 } 995 } 996 }; 997 998 /** 999 * Notify listeners 1000 */ 1001 AEC.EventDispatcher.trigger('ec.checkout.step.option.data', data); 1002 1003 /** 1004 * Track checkout option 1005 */ 1006 AEC.Cookie.checkoutOption(data).push(dataLayer); 1007 1008 return this; 1009 }, 1010 fail: function(message) 1011 { 1012 console.log(message); 1013 1014 return this; 1015 } 1016 1017 } 1018 })(), 1019 Cookie: (function() 1020 { 1021 return { 1022 data: null, 1023 privateData: null, 1024 reset: function() 1025 { 1026 if (AEC.reset) 1027 { 1028 dataLayer.push({ ecommerce: null }); 1029 } 1030 1031 return dataLayer; 1032 }, 1033 push: function(dataLayer, consent) 1034 { 1035 consent = typeof consent !== 'undefined' ? consent : true; 1036 1037 if (this.data) 1038 { 1039 if (consent) 1040 { 1041 if (AEC.Const.COOKIE_DIRECTIVE) 1042 { 1043 if (AEC.Const.COOKIE_DIRECTIVE_CONSENT_GRANTED) 1044 { 1045 this.reset().push(this.data); 1046 } 1047 } 1048 else 1049 { 1050 this.reset().push(this.data); 1051 } 1052 } 1053 else 1054 { 1055 this.reset().push(this.data); 1056 } 1057 1058 /** 1059 * Reset data to prevent further push 1060 */ 1061 this.data = null; 1062 } 1063 1064 return this; 1065 }, 1066 pushPrivate: function() 1067 { 1068 var data = this.getPrivateData(); 1069 1070 if (data) 1071 { 1072 dataLayer.push( 1073 { 1074 privateData: data 1075 }); 1076 } 1077 1078 return this; 1079 }, 1080 augment: function(products) 1081 { 1082 /** 1083 * Parse data & apply local reference 1084 */ 1085 var reference = AEC.Storage.reference().get(); 1086 1087 if (reference) 1088 { 1089 for (var i = 0, l = products.length; i < l; i++) 1090 { 1091 for (var a = 0, b = reference.length; a < b; a++) 1092 { 1093 if (products[i].id.toString().toLowerCase() === reference[a].id.toString().toLowerCase()) 1094 { 1095 products[i].category = reference[a].category; 1096 } 1097 } 1098 } 1099 } 1100 1101 return products; 1102 }, 1103 click: function(data) 1104 { 1105 AEC.EventDispatcher.trigger('ec.cookie.click.data', data); 1106 1107 this.data = data; 1108 1109 return this; 1110 }, 1111 add: function(data) 1112 { 1113 AEC.EventDispatcher.trigger('ec.cookie.add.data', data); 1114 1115 this.data = data; 1116 1117 return this; 1118 }, 1119 remove: function(data) 1120 { 1121 AEC.EventDispatcher.trigger('ec.cookie.remove.item.data', data); 1122 1123 this.data = data; 1124 1125 if (AEC.localStorage) 1126 { 1127 this.data.ecommerce.remove.products = this.augment(this.data.ecommerce.remove.products); 1128 } 1129 1130 return this; 1131 }, 1132 compare: function(data) 1133 { 1134 AEC.EventDispatcher.trigger('ec.cookie.compare.data', data); 1135 1136 this.data = data; 1137 1138 return this; 1139 }, 1140 wishlist: function(data) 1141 { 1142 AEC.EventDispatcher.trigger('ec.cookie.wishlist.data', data); 1143 1144 this.data = data; 1145 1146 return this; 1147 }, 1148 update: function(data) 1149 { 1150 AEC.EventDispatcher.trigger('ec.cookie.update.item.data', data); 1151 1152 this.data = data; 1153 1154 return this; 1155 }, 1156 visitor: function(data) 1157 { 1158 AEC.EventDispatcher.trigger('ec.cookie.visitor.data', data); 1159 1160 this.data = (function(data, privateData) 1161 { 1162 if (privateData) 1163 { 1164 if (privateData.hasOwnProperty('visitor')) 1165 { 1166 data.visitorId = privateData.visitor.visitorId; 1167 data.visitorLoginState = privateData.visitor.visitorLoginState; 1168 } 1169 } 1170 1171 return data; 1172 1173 })(data, AEC.Cookie.getPrivateData()); 1174 1175 return this; 1176 }, 1177 detail: function(data) 1178 { 1179 AEC.EventDispatcher.trigger('ec.cookie.detail.data', data); 1180 1181 this.data = data; 1182 1183 return this; 1184 }, 1185 purchase: function(data) 1186 { 1187 AEC.EventDispatcher.trigger('ec.cookie.purchase.data', data); 1188 1189 this.data = data; 1190 1191 if (AEC.localStorage) 1192 { 1193 this.data.ecommerce.purchase.products = this.augment(this.data.ecommerce.purchase.products); 1194 } 1195 1196 return this; 1197 }, 1198 impressions: function(data) 1199 { 1200 AEC.EventDispatcher.trigger('ec.cookie.impression.data', data); 1201 1202 this.data = data; 1203 1204 return this; 1205 }, 1206 checkout: function(data) 1207 { 1208 AEC.EventDispatcher.trigger('ec.cookie.checkout.step.data', data); 1209 1210 this.data = data; 1211 1212 if (AEC.localStorage) 1213 { 1214 this.data.ecommerce.checkout.products = this.augment(this.data.ecommerce.checkout.products); 1215 } 1216 1217 return this; 1218 }, 1219 checkoutOption: function(data) 1220 { 1221 AEC.EventDispatcher.trigger('ec.cookie.checkout.step.option.data', data); 1222 1223 this.data = data; 1224 1225 return this; 1226 }, 1227 promotion: function(data) 1228 { 1229 AEC.EventDispatcher.trigger('ec.cookie.promotion.data', data); 1230 1231 this.data = data; 1232 1233 return this; 1234 }, 1235 promotionClick: function(data, element) 1236 { 1237 AEC.EventDispatcher.trigger('ec.cookie.promotion.click', data, 1238 { 1239 element: element 1240 }); 1241 1242 this.data = data; 1243 1244 return this; 1245 }, 1246 remarketing: function(data) 1247 { 1248 AEC.EventDispatcher.trigger('ec.cookie.remarketing.data', data); 1249 1250 this.data = data; 1251 1252 return this; 1253 }, 1254 getPrivateData: function() 1255 { 1256 if (!this.privateData) 1257 { 1258 var cookie = this.get('privateData'); 1259 1260 if (cookie) 1261 { 1262 this.privateData = this.parse(cookie); 1263 } 1264 } 1265 1266 return this.privateData; 1267 }, 1268 set: function(name, value, days) 1269 { 1270 if (!days) 1271 { 1272 days = 30; 1273 } 1274 1275 let date = new Date(); 1276 1277 date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); 1278 1279 document.cookie = name + "=" + value + "; expires=" + date.toGMTString() + "; path=/"; 1280 1281 return this; 1282 }, 1283 get: function(name) 1284 { 1285 var start = document.cookie.indexOf(name + "="), len = start + name.length + 1; 1286 1287 if ((!start) && (name != document.cookie.substring(0, name.length))) 1288 { 1289 return null; 1290 } 1291 1292 if (start == -1) 1293 { 1294 return null; 1295 } 1296 1297 var end = document.cookie.indexOf(String.fromCharCode(59), len); 1298 1299 if (end == -1) 1300 { 1301 end = document.cookie.length; 1302 } 1303 1304 return decodeURIComponent(document.cookie.substring(len, end)); 1305 }, 1306 unset: function(name) 1307 { 1308 document.cookie = name + "=" + "; path=/; expires=" + (new Date(0)).toUTCString(); 1309 1310 return this; 1311 }, 1312 parse: function(json) 1313 { 1314 var json = decodeURIComponent(json.replace(/\+/g, ' ')); 1315 1316 return JSON.parse(json); 1317 } 1318 } 1319 })(), 1320 CookieConsent: (function() 1321 { 1322 return { 1323 chain: {}, 1324 queue: function(callback, event) 1325 { 1326 event = typeof event !== 'undefined' ? event : AEC.Const.COOKIE_DIRECTIVE_CONSENT_GRANTED_EVENT; 1327 1328 if (!this.chain.hasOwnProperty(event)) 1329 { 1330 this.chain[event] = []; 1331 } 1332 1333 this.chain[event].push(callback); 1334 1335 return this; 1336 }, 1337 dispatch: function(consent) 1338 { 1339 /** 1340 * Essential cookies 1341 */ 1342 AEC.Const.COOKIE_DIRECTIVE_CONSENT_GRANTED = true; 1343 1344 /** 1345 * Push consent to dataLayer 1346 */ 1347 dataLayer.push(consent); 1348 1349 return this.process(consent.event); 1350 }, 1351 process: function(event) 1352 { 1353 event = typeof event !== 'undefined' ? event : AEC.Const.COOKIE_DIRECTIVE_CONSENT_GRANTED_EVENT; 1354 1355 if (this.chain.hasOwnProperty(event) && this.getConsent(event)) 1356 { 1357 for (a = 0, b = this.chain[event].length; a < b; a++) 1358 { 1359 this.chain[event][a].apply(this,[]); 1360 } 1361 1362 this.chain[event] = []; 1363 } 1364 1365 return this; 1366 }, 1367 getConsent: function(event) 1368 {
1369 let consent = !AEC.Const.COOKIE_DIRECTIVE ? true : 1 == AEC.Cookie.get(event); 1370 1371 /** 1372 * Notify third parties for consent 1373 */ 1374 AEC.EventDispatcher.trigger('ec.consent', consent); 1375 1376 return consent; 1377 }, 1378 acceptGoogleConsent: function(segments) 1379 { 1380 if ('function' === typeof gtag) 1381 { 1382 const consentMode = 1383 { 1384 ad_storage: -1 !== segments.indexOf('cookieConsentMarketingGranted') ? 'granted' : 'denied', 1385 security_storage: -1 !== segments.indexOf('cookieConsentGranted') ? 'granted' : 'denied', 1386 functionality_storage: -1 !== segments.indexOf('cookieConsentGranted') ? 'granted' : 'denied', 1387 personalization_storage: -1 !== segments.indexOf('cookieConsentPreferencesGranted') ? 'granted' : 'denied', 1388 analytics_storage: -1 !== segments.indexOf('cookieConsentAnalyticsGranted') ? 'granted' : 'denied', 1389 }; 1390 1391 gtag('consent','updated',consentMode); 1392 1393 localStorage.setItem('consentMode', JSON.stringify(consentMode)); 1394 } 1395 1396 return this; 1397 }, 1398 acceptConsent: function(event) 1399 { 1400 return this.dispatch({ event:event }); 1401 }, 1402 declineConsent: function(event) 1403 { 1404 return this.dispatch({ event:event }); 1405 }, 1406 declineGoogleConsent: function() 1407 { 1408 const consentMode = 1409 { 1410 ad_storage: 'denied', 1411 security_storage: 'denied', 1412 functionality_storage: 'denied', 1413 personalization_storage: 'denied', 1414 analytics_storage: 'denied' 1415 }; 1416 1417 gtag('consent','updated',consentMode); 1418 1419 localStorage.setItem('consentMode', JSON.stringify(consentMode)); 1420 1421 return this; 1422 }, 1423 getConsentDialog: function(dataLayer, endpoints) 1424 { 1425 if (1 == AEC.Cookie.get(AEC.Const.COOKIE_DIRECTIVE_CONSENT_DECLINE_EVENT)) 1426 { 1427 return true; 1428 } 1429 1430 if (1 != AEC.Cookie.get(AEC.Const.COOKIE_DIRECTIVE_CONSENT_GRANTED_EVENT)) 1431 { 1432 AEC.Request.get(endpoints.cookieContent, {}, (response) => 1433 { 1434 var directive = (body => 1435 { 1436 body.insertAdjacentHTML('beforeend', response.cookieContent); 1437 1438 return body.lastElementChild; 1439 1440 })(document.body); 1441 1442 directive.querySelectorAll('a.ec-gtm-cookie-directive-note-toggle').forEach(element => 1443 { 1444 element.addEventListener('click', event => 1445 { 1446 event.target.nextElementSibling.style.display = 'block' === event.target.nextElementSibling.style.display ? 'none' : 'block'; 1447 }); 1448 }); 1449 1450 directive.querySelectorAll('a.accept').forEach(element => 1451 { 1452 element.addEventListener('click', event => 1453 { 1454 event.target.text = event.target.dataset.confirm; 1455 1456 var grant = [...directive.querySelectorAll('[name="cookie[]"]:checked')].map(element => { return element.value }); 1457 1458 grant.unshift('cookieConsentGranted'); 1459 1460 AEC.CookieConsent.acceptGoogleConsent(grant); 1461 1462 AEC.Request.post(endpoints.cookie, { cookie: grant }, response => 1463 { 1464 Object.keys(response).forEach(event => 1465 { 1466 AEC.CookieConsent.acceptConsent(event); 1467 }); 1468 1469 directive.remove(); 1470 }); 1471 }); 1472 }); 1473 1474 directive.querySelectorAll('a.accept-all').forEach(element => 1475 { 1476 element.addEventListener('click', event => 1477 { 1478 event.target.text = event.target.dataset.confirm; 1479 1480 [...directive.querySelectorAll('[name="cookie[]"]')].forEach(element => 1481 { 1482 element.checked = true; 1483 }); 1484 1485 element.parentNode.removeChild(element.previousElementSibling); 1486 1487 var grant = [...directive.querySelectorAll('[name="cookie[]"]:checked')].map(element => { return element.value }); 1488 1489 grant.unshift('cookieConsentGranted'); 1490 1491 AEC.CookieConsent.acceptGoogleConsent(grant); 1492 1493 AEC.Request.post(endpoints.cookie, { cookie: grant }, response => 1494 { 1495 Object.keys(response).forEach(event => 1496 { 1497 AEC.CookieConsent.acceptConsent(event); 1498 }); 1499 1500 directive.remove(); 1501 }); 1502 }); 1503 }); 1504 1505 directive.querySelectorAll('a.decline').forEach(element => 1506 { 1507 element.addEventListener('click', event => 1508 { 1509 AEC.CookieConsent.declineGoogleConsent(); 1510 1511 AEC.Request.post(endpoints.cookie, { decline: true }, response => 1512 { 1513 Object.keys(response).forEach(event => 1514 { 1515 AEC.CookieConsent.declineConsent(event); 1516 }); 1517 1518 directive.remove(); 1519 }); 1520 }); 1521 }); 1522 }); 1523 } 1524 else 1525 { 1526 if (AEC.Const.COOKIE_DIRECTIVE_SEGMENT_MODE) 1527 { 1528 (segments => 1529 { 1530 let grant = []; 1531 1532 for (i = 0, l = segments.length; i < l;i++) 1533 { 1534 if (1 == AEC.Cookie.get(segments[i])) 1535 { 1536 AEC.CookieConsent.acceptConsent(segments[i]); 1537 1538 grant.push(segments[i]); 1539 } 1540 } 1541 1542 AEC.CookieConsent.acceptGoogleConsent(grant); 1543 1544 })(AEC.Const.COOKIE_DIRECTIVE_SEGMENT_MODE_EVENTS); 1545 } 1546 else 1547 { 1548 AEC.CookieConsent.acceptConsent(AEC.Const.COOKIE_DIRECTIVE_CONSENT_GRANTED_EVENT); 1549 } 1550 } 1551 } 1552 } 1553 })(), 1554 Storage: (function(api) 1555 { 1556 return { 1557 set: function(property, value) 1558 { 1559 if ('undefined' !== typeof(Storage)) 1560 { 1561 localStorage.setItem(property, JSON.stringify(value)); 1562 } 1563 1564 return this; 1565 1566 }, 1567 get: function(property) 1568 { 1569 if ('undefined' !== typeof(Storage)) 1570 { 1571 return JSON.parse(localStorage.getItem(property)); 1572 } 1573 1574 return null; 1575 }, 1576 reference: function() 1577 { 1578 return (function(storage) 1579 { 1580 return { 1581 set: function(reference) 1582 { 1583 var current = storage.get('category.add') || []; 1584 1585 var exists = (function(current, reference) 1586 { 1587 for (i = 0, l = current.length; i < l; i++) 1588 { 1589 if (current[i].id.toString().toLowerCase() === reference.id.toString().toLowerCase()) 1590 { 1591 /** 1592 * Update category 1593 */ 1594 current[i].category = reference.category; 1595 1596 return true; 1597 } 1598 } 1599 1600 return false;
1601 1602 })(current, reference); 1603 1604 if (!exists) 1605 { 1606 current.push(reference); 1607 } 1608 1609 storage.set('category.add', current); 1610 1611 return this; 1612 }, 1613 get: function() 1614 { 1615 return storage.get('category.add'); 1616 } 1617 } 1618 })(this); 1619 } 1620 } 1621 })(), 1622 gtm: function() 1623 { 1624 if ("undefined" === typeof google_tag_manager) 1625 { 1626 /** 1627 * Log error to console 1628 */ 1629 console.log('Unable to detect Google Tag Manager. Please verify if GTM install snippet is available.'); 1630 1631 return false; 1632 } 1633 1634 return true; 1635 }, 1636 parseJSON: function(content) 1637 { 1638 if ('object' === typeof content) 1639 { 1640 return content; 1641 } 1642 1643 if ('string' === typeof content) 1644 { 1645 try 1646 { 1647 return JSON.parse(content); 1648 } 1649 catch (e){} 1650 } 1651 1652 return {}; 1653 }, 1654 getPayloadSize: function(object) 1655 { 1656 var objects = [object]; 1657 var size = 0; 1658 1659 for (var index = 0; index < objects.length; index++) 1660 { 1661 switch (typeof objects[index]) 1662 { 1663 case 'boolean': 1664 size += 4; 1665 break; 1666 case 'number': 1667 size += 8; 1668 break; 1669 case 'string': 1670 size += 2 * objects[index].length; 1671 break; 1672 case 'object': 1673 if (Object.prototype.toString.call(objects[index]) != '[object Array]') 1674 { 1675 for (var key in objects[index]) size += 2 * key.length; 1676 } 1677 for (var key in objects[index]) 1678 { 1679 var processed = false; 1680 1681 for (var search = 0; search < objects.length; search++) 1682 { 1683 if (objects[search] === objects[index][key]) { 1684 processed = true; 1685 break; 1686 } 1687 } 1688 if (!processed) objects.push(objects[index][key]); 1689 } 1690 } 1691 } 1692 return size; 1693 }, 1694 getPayloadChunks: function(arr, len) 1695 { 1696 var chunks = [],i = 0, n = arr.length; 1697 1698 while (i < n) 1699 { 1700 chunks.push(arr.slice(i, i += len)); 1701 } 1702 1703 return chunks; 1704 }, 1705 url: function(url) 1706 { 1707 return [this.Const.URL, url].join(''); 1708 }, 1709 EventDispatcher: (function() 1710 { 1711 return { 1712 events: {}, 1713 on: function(event, callback) 1714 { 1715 var handlers = this.events[event] || []; 1716 1717 handlers.push(callback); 1718 1719 this.events[event] = handlers; 1720 }, 1721 trigger: function() 1722 { 1723 /** 1724 * Cast arguments to array 1725 */ 1726 let args = [...arguments]; 1727 1728 /** 1729 * Get event 1730 */ 1731 let event = args ? args.shift() : null; 1732 1733 /** 1734 * Get handlers 1735 */ 1736 let handlers = this.events[event] || []; 1737 1738 /** 1739 * Get data 1740 */ 1741 let data = args ? args.shift() : {}; 1742 1743 /** 1744 * Get options 1745 */ 1746 let options = args ? args.shift() : {}; 1747 1748 /** 1749 * Quit if no handler 1750 */ 1751 if (!handlers || handlers.length < 1) 1752 { 1753 return; 1754 } 1755 1756 console.log(event + '(' + handlers.length + ' listeners)'); 1757 1758 handlers.forEach(function(handler) 1759 { 1760 handler(data, options); 1761 }); 1762 } 1763 } 1764 })(), 1765 Request: (function() 1766 { 1767 return { 1768 get: function(url, params, callback) 1769 { 1770 this.execute('GET', [url,this.serialize(params)].join('?'), callback).send(null); 1771 }, 1772 post: function(url, params, callback) 1773 { 1774 this.execute('POST', url, callback).send(this.serialize(params)); 1775 }, 1776 execute: function(method, url, callback) 1777 { 1778 try 1779 { 1780 var request = new XMLHttpRequest(); 1781 1782 request.open(method, url, true); 1783 1784 request.setRequestHeader('Content-Type','application/x-www-form-urlencoded'); 1785 request.setRequestHeader('X-Requested-With','XMLHttpRequest'); 1786 1787 request.addEventListener('load', () => 1788 { 1789 let response; 1790 1791 if ('application/json' === request.getResponseHeader("Content-Type")) 1792 { 1793 response = JSON.parse(request.responseText); 1794 } 1795 else 1796 { 1797 response = request.responseText; 1798 } 1799 1800 if ('function' === typeof callback) 1801 { 1802 callback(response); 1803 } 1804 }); 1805 } 1806 catch (e) 1807 { 1808 console.log(e.message); 1809 1810 return null; 1811 } 1812 1813 1814 return request; 1815 }, 1816 serialize: function(entity, prefix) 1817 { 1818 var query = []; 1819 1820 Object.keys(entity).map(key => 1821 { 1822 var k = prefix ? prefix + "[" + key + "]" : key, value = entity[key]; 1823 1824 query.push((value !== null && typeof value === "object") ? this.serialize(value, k) : encodeURIComponent(k) + "=" + encodeURIComponent(value)); 1825 }); 1826 1827 return query.join("&"); 1828 } 1829 } 1830 })(), 1831 UUID: (() => 1832 { 1833 return { 1834 generate: event => 1835 { 1836 event = event || {}; 1837 1838 if (-1 == ['AddToCart'].indexOf(event)) 1839 { 1840 try 1841 {
1842 let current = AEC.Cookie.get('facebook_latest_uuid'); 1843 1844 if (current) 1845 { 1846 current = JSON.parse(current); 1847 1848 if (current.hasOwnProperty('uuid') && current.hasOwnProperty('event')) 1849 { 1850 if (event.event === current.event) 1851 { 1852 return current.uuid; 1853 } 1854 } 1855 } 1856 } 1857 catch (e){} 1858 } 1859 1860 let uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) 1861 { 1862 var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); 1863 return v.toString(16); 1864 }); 1865 1866 event['uuid'] = uuid; 1867 1868 /** 1869 * Set facebook uuid cookie 1870 */ 1871 if (AEC.Const.COOKIE_DIRECTIVE) 1872 { 1873 if (AEC.Const.COOKIE_DIRECTIVE_CONSENT_GRANTED) 1874 { 1875 AEC.Cookie.set('facebook_latest_uuid', JSON.stringify(event)); 1876 } 1877 } 1878 else 1879 { 1880 AEC.Cookie.set('facebook_latest_uuid', JSON.stringify(event)); 1881 } 1882 1883 return uuid; 1884 } 1885 } 1886 })() 1887 } 1888})();
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.