1/** 2 * parent file: vendor/anowave/ec/view/frontend/web/js/ec.js 3 * line 216 - Pull "childsku" data attribute instead of variant description 4 */ 5var AEC = (function() 6{ 7 return { 8 add: function(context, dataLayer) 9 { 10 let element = context, qty = 1, variants = [], variant = [], variant_attribute_option = [], items = []; 11 12 document.querySelectorAll('input[name=qty]:checked, [name=qty]').forEach(element => 13 { 14 qty = element.value; 15 }); 16 17 qty = Math.abs(qty); 18 19 if (isNaN(qty)) 20 { 21 qty = 1; 22 } 23 24 if ('undefined' !== typeof jQuery) 25 { 26 var form = jQuery(context).closest('form'); 27 28 if (form.length) 29 { 30 if (!form.valid()) 31 { 32 return true; 33 } 34 } 35 } 36 37 if (!AEC.gtm()) 38 { 39 if (element.dataset.click) 40 { 41 AEC.Time.track(dataLayer, AEC.Const.TIMING_CATEGORY_ADD_TO_CART, element.dataset.name, element.dataset.category); 42 43 eval(element.dataset.click); 44 } 45 46 return true; 47 } 48 49 if(element.dataset.configurable) 50 { 51 document.querySelectorAll('[name^="super_attribute"]').forEach(attribute => 52 { 53 if (attribute.matches('select')) 54 { 55 var name = attribute.getAttribute('name'), id = name.substring(name.indexOf('[') + 1, name.lastIndexOf(']')); 56 57 if (attribute.selectedIndex) 58 { 59 var option = attribute.options[attribute.selectedIndex]; 60 61 if (option) 62 { 63 variants.push( 64 { 65 id: id, 66 option: option.label, 67 text: option.text 68 }); 69 } 70 } 71 } 72 73 if (attribute.matches('input') && -1 != attribute.type.indexOf('radio')) 74 { 75 if (attribute.parentNode.classList.contains('swatch-option-selected') || attribute.checked) 76 { 77 Object.entries(AEC.SUPER).forEach(([key, super_attribute]) => 78 { 79 if (-1 != attribute.name.indexOf("super_attribute[" + super_attribute.id + "]")) 80 { 81 let variant = 82 { 83 id: super_attribute.id, 84 text: super_attribute.label, 85 option: attribute.value 86 }; 87 88 variants.push(variant); 89 90 } 91 }); 92 } 93 } 94 }); 95 96 /** 97 * Colour Swatch support 98 */ 99 if (!variants.length) 100 { 101 Object.entries(AEC.SUPER).forEach(([key, attribute]) => 102 { 103 var swatch = document.querySelectorAll('div[attribute-code="' + attribute.code + '"], div[data-attribute-code="' + attribute.code + '"]'); 104 105 swatch.forEach(element => 106 { 107 let variant = 108 { 109 id: attribute.id, 110 text: '', 111 option: null 112 }; 113 114 var select = element.querySelector('select'); 115 116 if (select) 117 { 118 if (select.selectedIndex) 119 { 120 var option = select.options[select.selectedIndex]; 121 122 if (option) 123 { 124 variant.text = option.text; 125 variant.option = option.value; 126 } 127 } 128 } 129 else 130 { 131 var span = element.querySelector('span.swatch-attribute-selected-option'); 132 133 if (span) 134 { 135 variant.text = span.innerHTML; 136 variant.option = span.parentNode.dataset.optionSelected 137 } 138 } 139 140 variants.push(variant); 141 }); 142 }); 143 } 144 145 if (!variants.length) 146 { 147 AEC.EventDispatcher.trigger('ec.variants', variants); 148 } 149 150 var SUPER_SELECTED = []; 151 152 for (i = 0, l = variants.length; i < l; i++) 153 { 154 for (a = 0, b = AEC.SUPER.length; a < b; a++) 155 { 156 if (AEC.SUPER[a].id == variants[i].id) 157 { 158 var text = variants[i].text; 159 160 if (AEC.useDefaultValues) 161 { 162 AEC.SUPER[a].options.forEach(option => 163 { 164 if (parseInt(option.value_index) == parseInt(variants[i].option)) 165 { 166 if (option.hasOwnProperty('admin_label')) 167 { 168 text = option.admin_label; 169 } 170 else if (option.hasOwnProperty('store_label')) 171 { 172 text = option.store_label; 173 } 174 175 } 176 }); 177 } 178 179 variant.push([AEC.SUPER[a].label,text].join(AEC.Const.VARIANT_DELIMITER_ATT)); 180 181 let tier_price = Number.parseFloat(element.dataset.price).toFixed(2); 182 183 Object.entries(AEC.CONFIGURABLE_SIMPLES).forEac
183h(([key, simple]) => 184 { 185 if (simple.hasOwnProperty('configurations')) 186 { 187 Object.entries(simple.configurations).forEach(([key, configuration]) => 188 { 189 if (configuration.label === variants[i].option) 190 { 191 let prices = []; 192 193 Object.entries(simple.price_tier).forEach(([key, tier]) => 194 { 195 if (parseInt(qty) >= parseInt(tier.price_qty)) 196 { 197 prices.push(Number.parseFloat(tier.price)); 198 } 199 }); 200 201 if (prices.length) 202 { 203 tier_price = prices.sort(function(a,b) { return a < b; }).pop(); 204 } 205 } 206 }); 207 } 208 }); 209 210 variant_attribute_option.push( 211 { 212 attribute: variants[i].id, 213 option: variants[i].option, 214 price: tier_price 215 }) 216 } 217 } 218 } 219 220 if (!variant.length) 221 { 222 if (element.dataset.click) 223 { 224 AEC.Time.track(dataLayer, AEC.Const.TIMING_CATEGORY_ADD_TO_CART, element.dataset.name, element.dataset.category); 225 226 eval(element.dataset.click); 227 } 228 229 return true; 230 } 231 } 232 233 if (element.dataset.grouped) 234 { 235 for (u = 0, y = window.G.length; u < y; u++) 236 { 237 let field = document.querySelector('[name="super_group[' + window.G[u].id + ']"]'); 238 239 if (field) 240 { 241 (qty => 242 { 243 if (qty) 244 { 245 let item = 246 { 247 'item_name': window.G[u].name, 248 'item_id': window.G[u].sku, 249 'price': window.G[u].price, 250 'category': window.G[u].category, 251 'item_brand': window.G[u].brand, 252 'quantity': qty 253 }; 254 255 Object.assign(item, item, AEC.GA4.transformCategories(element.dataset.category)); 256 257 items.push(item); 258 } 259 })(Math.abs(field.value)); 260 } 261 } 262 } 263 else 264 { 265 let price = Number.parseFloat(element.dataset.price); 266 267 if (element.dataset.hasOwnProperty('selection')) 268 { 269 let selection = parseInt(element.dataset.selection); 270 271 Object.entries(AEC.CONFIGURABLE_SIMPLES).forEach(([key, simple]) => 272 { 273 if (key == selection) 274 { 275 if (simple.hasOwnProperty('price_tier')) 276 { 277 Object.entries(simple.configurations).forEach(([key, configuration]) => 278 { 279 let prices = []; 280 281 Object.entries(simple.price_tier).forEach(([key, tier]) => 282 { 283 if (parseInt(qty) >= parseInt(tier.price_qty)) 284 { 285 prices.push(Number.parseFloat(tier.price)); 286 } 287 }); 288 289 if (prices.length) 290 { 291 price = prices.sort(function(a,b) { return a < b; }).pop(); 292 } 293 }); 294 } 295 } 296 }); 297 } 298 299 let item = 300 { 301 'item_name': element.dataset.name, 302 'item_id': 1 === parseInt(element.dataset.useSimple) ? element.dataset.simpleId : element.dataset.id, 303 'price': price, 304 'item_brand': element.dataset.brand, 305 'item_variant': variant.join(AEC.Const.VARIANT_DELIMITER), 306 'category': element.dataset.category, 307 'quantity': qty, 308 'index': 0, 309 'item_list_id': element.dataset.list.toLowerCase().replace(/\s+/g, '_'), 310 'item_list_name': element.dataset.list, 311 }; 312 313 Object.assign(item, item, AEC.GA4.transformCategories(element.dataset.category)); 314 315 items.push(item); 316 } 317 318 let value_combined = 0; 319 320 for (i = 0, l = items.length; i < l; i++) 321 { 322 value_combined += (Number.parseFloat(items[i].price) * Number.parseInt(items[i].quantity)); 323 324 (function(item) 325 { 326 Object.entries(AEC.parseJSON(element.dataset.attributes)).forEac
326h(([key, value]) => 327 { 328 item[key] = value; 329 }); 330 331 let options = []; 332 333 Object.entries(AEC.parseJSON(element.dataset.options)).forEach(([key, name]) => 334 { 335 let option = document.querySelector('[name="options[' + key + ']"]'), value = null; 336 337 switch(true) 338 { 339 case option instanceof HTMLInputElement: 340 case option instanceof HTMLTextAreaElement: value = option.value; 341 break; 342 case option instanceof HTMLSelectElement: value = option.options[option.selectedIndex].text; 343 break; 344 } 345 346 if (value) 347 { 348 options.push({ name: name, value: value }); 349 } 350 351 }); 352 353 if (options.length) 354 { 355 item['options'] = options; 356 } 357 358 })(items[i]); 359 } 360 361 var data = 362 { 363 'event':'add_to_cart', 364 'eventLabel': element.dataset.name, 365 'ecommerce': 366 { 367 'currency': AEC.currencyCode, 368 'value': value_combined, 369 'item_list_id': element.dataset.list.toLowerCase().replace(/\s+/g, '_'), 370 'item_list_name': element.dataset.list, 371 'items': items, 372 }, 373 'currentStore': AEC.storeName, 374 'addToCartType': element.dataset.addtocarttype 375 }; 376 377 if (AEC.useDefaultValues) 378 { 379 data['currentStore'] = AEC.storeName; 380 } 381 382 /** 383 * Notify listeners 384 */ 385 this.EventDispatcher.trigger('ec.add.data', data); 386 387 /** 388 * Track event 389 */ 390 AEC.CookieConsent.queue(() => 391 { 392 AEC.Cookie.add(data).push(dataLayer); 393 394 }).process(); 395 396 /** 397 * Save backreference 398 */ 399 if (AEC.localStorage) 400 { 401 (function(items) 402 { 403 for (var i = 0, l = items.length; i < l; i++) 404 { 405 AEC.Storage.reference().set( 406 { 407 id: items[i].item_id, 408 category: items[i].category 409 }); 410 } 411 })(items); 412 } 413 414 /** 415 * Track time 416 */ 417 AEC.Time.track(dataLayer, AEC.Const.TIMING_CATEGORY_ADD_TO_CART, element.dataset.name, element.dataset.category); 418 419 if (AEC.facebook) 420 { 421 if ("undefined" !== typeof fbq) 422 { 423 (function(product, items, fbq) 424 { 425 var content_ids = [], price = 0; 426 427 for (i = 0, l = items.length; i < l; i++) 428 { 429 content_ids.push(items[i].item_id); 430 431 price += parseFloat(items[i].price); 432 } 433 434 (function(callback) 435 { 436 if (AEC.Const.COOKIE_DIRECTIVE) 437 { 438 AEC.CookieConsent.queue(callback).process(); 439 } 440 else 441 { 442 callback.apply(window,[]); 443 } 444 }) 445 ( 446 (function(product, content_ids, price) 447 { 448 return function() 449 { 450 if ('undefined' === typeof variants) 451 { 452 variants = []; 453 } 454 455 fbq('track', 'AddToCart', 456 { 457 content_name: product, 458 content_ids: content_ids, 459 content_type: !variants.length ? 'product' : 'product_group', 460 value: price, 461 currency: AEC.currencyCode 462 }, 463 { eventID: AEC.UUID.generate({ event: 'AddToCart'}) }); 464 } 465 })(product, content_ids, price) 466 ); 467 468 })(element.dataset.name, items, fbq); 469 } 470 } 471 472 if (element.dataset.click) 473 { 474 eval(element.dataset.click); 475 } 476 477 return true; 478 }, 479 addSwatch: function(context,dataLayer) 480 { 481 var element = context; 482 483 if (window.jQuery) 484 { 485 jQuery(document).on('ajax:addToCart', function() 486 { 487 var attributes = []; 488 489 Object.entries(AEC.parseJSON(element.dataset.swatch)).forEac
489h(([key, value]) => 490 { 491 attributes.push(value); 492 }); 493 494 var option = document.querySelector('.swatch-option.selected'); 495 496 if (!option) 497 { 498 return true; 499 } 500 501 var variant = [[attributes[0].attribute_label, option.getAttribute('aria-label')].join(AEC.Const.VARIANT_DELIMITER_ATT)].join(AEC.Const.VARIANT_DELIMITER); 502 503 let items = []; 504 505 let item = 506 { 507 'item_name': element.dataset.name, 508 'item_id': element.dataset.id, 509 'price': element.dataset.price, 510 'category': element.dataset.category, 511 'item_brand': element.dataset.brand, 512 'item_variant': variant, 513 'item_list_name': element.dataset.list, 514 'item_list_id': element.dataset.list.toLowerCase().replace(/\s+/g, '_'), 515 'quantity': 1, 516 'index': element.dataset.position 517 }; 518 519 Object.assign(item, item, AEC.GA4.transformCategories(element.dataset.category)); 520 521 /** 522 * Track event 523 */ 524 AEC.Cookie.add( 525 { 526 'event': 'add_to_cart', 527 'currency': AEC.currencyCode, 528 'eventLabel': element.dataset.name, 529 'item_list_id': element.dataset.list.toLowerCase().replace(/\s+/g, '_'), 530 'item_list_name': element.dataset.list, 531 'ecommerce': 532 { 533 'items': [item] 534 }, 535 'currentStore': element.dataset.store 536 }).push(dataLayer); 537 538 /** 539 * Track time 540 */ 541 AEC.Time.track(dataLayer, AEC.Const.TIMING_CATEGORY_ADD_TO_CART, element.dataset.name, element.dataset.category); 542 }); 543 } 544 545 return true; 546 }, 547 click: function(context,dataLayer) 548 { 549 var element = context; 550 551 if (!AEC.gtm()) 552 { 553 AEC.Time.track(dataLayer, AEC.Const.TIMING_CATEGORY_PRODUCT_CLICK, element.dataset.name, element.dataset.category); 554 555 return true; 556 } 557 558 var item = 559 { 560 'item_name': element.dataset.name, 561 'item_id': element.dataset.id, 562 'price': element.dataset.price, 563 'item_brand': element.dataset.brand, 564 'quantity': element.dataset.quantity, 565 'index': element.dataset.position, 566 'category': element.dataset.category, 567 'item_list_id': element.dataset.list.toLowerCase().replace(/\s+/g, '_'), 568 'item_list_name': element.dataset.list, 569 }; 570 571 Object.entries(AEC.parseJSON(element.dataset.attributes)).forEach(([key, value]) => 572 { 573 item[key] = value; 574 }); 575 576 Object.assign(item, item, AEC.GA4.augmentCategories(item)); 577 578 var data = 579 { 580 'event': 'select_item', 581 'eventLabel': element.dataset.name, 582 'item_list_id': element.dataset.list.toLowerCase().replace(/\s+/g, '_'), 583 'item_list_name': element.dataset.list, 584 'ecommerce': 585 { 586 'items': 587 [ 588 item 589 ] 590 }, 591 'currentStore': element.dataset.store 592 }; 593 594 595 /** 596 * Push data 597 */ 598 AEC.CookieConsent.queue(() => 599 { 600 AEC.Cookie.click(data).push(dataLayer); 601 602 }).process(); 603 604 /** 605 * Track time 606 */ 607 AEC.Time.track(dataLayer, AEC.Const.TIMING_CATEGORY_PRODUCT_CLICK, element.dataset.name, element.dataset.category); 608 609 if (element.dataset.click) 610 { 611 eval(element.dataset.click); 612 } 613 614 return true; 615 }, 616 remove: function(context, dataLayer) 617 { 618 var element = context; 619
620 if (!AEC.gtm()) 621 { 622 AEC.Time.track(dataLayer, AEC.Const.TIMING_CATEGORY_REMOVE_FROM_CART, element.dataset.name, element.dataset.category); 623 } 624 625 var item = 626 { 627 'item_name': element.dataset.name, 628 'item_id': element.dataset.id, 629 'price': element.dataset.price, 630 'category': element.dataset.category, 631 'item_brand': element.dataset.brand, 632 'quantity': element.dataset.quantity, 633 }; 634 635 Object.entries(AEC.parseJSON(element.dataset.attributes)).forEach(([key, value]) => 636 { 637 item[key] = value; 638 }); 639 640 Object.assign(item, item, AEC.GA4.augmentCategories(item)); 641 642 var data = 643 { 644 'event': 'remove_from_cart', 645 'eventLabel': element.dataset.name, 646 'ecommerce': 647 { 648 'item_list_id': element.dataset.list.toLowerCase().replace(/\s+/g, '_'), 649 'item_list_name': element.dataset.list, 650 'items': 651 [ 652 item 653 ], 654 } 655 }; 656 657 AEC.EventDispatcher.trigger('ec.remove.data', data); 658 AEC.Cookie.remove(data).push(dataLayer); 659 AEC.Time.track(dataLayer, AEC.Const.TIMING_CATEGORY_REMOVE_FROM_CART, element.dataset.name); 660 jQuery(document).dataPost('postData', AEC.parseJSON(element.dataset.postAction)); 661 return false; 662 663 return false; 664 }, 665 wishlist: function(context, dataLayer) 666 { 667 var element = context; 668 669 if (!AEC.gtm()) 670 { 671 /** 672 * Track time 673 */ 674 AEC.Time.track(dataLayer, AEC.Const.TIMING_CATEGORY_PRODUCT_WISHLIST, element.dataset.name,'Wishlist'); 675 676 return true; 677 } 678 679 let attributes = JSON.parse(element.dataset.eventAttributes); 680 681 /** 682 * Track event 683 */ 684 AEC.Cookie.wishlist( 685 { 686 event: element.dataset.event, 687 eventLabel: element.dataset.eventLabel, 688 ecommerce: 689 { 690 items: attributes.items 691 } 692 }).push(dataLayer); 693 694 return true; 695 }, 696 compare: function(context, dataLayer) 697 { 698 var element = context; 699 700 if (!AEC.gtm()) 701 { 702 /** 703 * Track time 704 */ 705 AEC.Time.track(dataLayer, AEC.Const.TIMING_CATEGORY_PRODUCT_COMPARE, element.dataset.name,'Compare'); 706 707 return true; 708 } 709 710 let attributes = JSON.parse(element.dataset.eventAttributes); 711 712 AEC.Cookie.compare( 713 { 714 event: element.dataset.event, 715 eventLabel: element.dataset.eventLabel, 716 ecommerce: 717 { 718 items: attributes.items 719 } 720 }).push(dataLayer); 721 722 return true; 723 }, 724 Bind: (function() 725 { 726 return { 727 apply: function(parameters) 728 { 729 /** 730 * Merge persistent storage 731 */ 732 AEC.Persist.merge(); 733 734 /** 735 * Push private data 736 */ 737 AEC.Cookie.pushPrivate(); 738 739 document.addEventListener('DOMContentLoaded',() => 740 { 741 document.body.addEventListener('catalogCategoryAddToCartRedirect', () => 742 { 743 dataLayer.push( 744 { 745 event: AEC.Const.CATALOG_CATEGORY_ADD_TO_CART_REDIRECT_EVENT 746 }); 747 }); 748 }); 749 750 if (parameters) 751 { 752 if (parameters.performance) 753 { 754 if (window.performance) 755 { 756 window.onload = function() 757 { 758 setTimeout(function() 759 { 760 var time = performance.timing.loadEventEnd - performance.timing.responseEnd; 761 762 var timePayload = 763 { 764 'event':'performance', 765 'performance': 766 { 767 'timingCategory': 'Load times', 768 'timingVar': 'load', 769 'timingValue': (time % 60000) 770 } 771 }; 772 773 switch(window.google_tag_params.ecomm_pagetype) 774 { 775 case 'home': 776 777 timePayload.performance.timingLabel = 'Home'; 778 779 AEC.CookieConsent.queue(() => 780 { 781 dataLayer.push(timePayload); 782 }).process(); 783 784 break; 785 case 'product': 786 787 timePayload.performance.timingLabel = 'Product'; 788 789 AEC.CookieConsent.queue(() => 790 { 791 dataLayer.push(timePayload); 792 }).process(); 793 794 break; 795 796 case 'category': 797 798 timePayload.performance.timingLabel = 'Category'; 799 800 AEC.CookieConsent.queue(() => 801 { 802 dataLayer.push(timePayload); 803 }).process(); 804 805 break; 806 } 807 808 }, 0); 809 } 810 } 811 } 812 } 813 814 return this; 815 } 816 } 817 })(), 818 Time: (function() 819 { 820 var T = 821 { 822 event: 'trackTime', 823 timingCategory: '', 824 timingVar: '', 825 timingValue: -1, 826 timingLabel: '' 827 }; 828 829 var time = new Date().getTime(); 830 831 return { 832 track: function(dataLayer, category, variable, label) 833 { 834 T.timingValue = (new Date().getTime()) - time; 835 836 if (category) 837 { 838 T.timingCategory = category; 839 } 840 841 if (variable) 842 { 843 T.timingVar = variable; 844 } 845 846 if (label) 847 { 848 T.timingLabel = label; 849 } 850 851 (function(callback) 852 { 853 if (AEC.Const.COOKIE_DIRECTIVE) 854 { 855 AEC.CookieConsent.queue(callback).process(); 856 } 857 else 858 { 859 callback.apply(window,[]); 860 } 861 }) 862 ( 863 (function(dataLayer, T) 864 { 865 return function() 866 { 867 dataLayer.push(T); 868 } 869 })(dataLayer, T) 870 ); 871 }, 872 trackContinue: function(dataLayer, category, variable, label) 873 { 874 this.track(dataLayer, category, variable, label); 875 876 time = new Date().getTime(); 877 } 878 } 879 })(), 880 Persist:(function() 881 { 882 var DATA_KEY = 'persist';
883 884 var proto = 'undefined' != typeof Storage ? 885 { 886 push: function(key, entity) 887 { 888 /** 889 * Get data 890 */ 891 var data = this.data(); 892 893 /** 894 * Push data 895 */ 896 data[key] = entity; 897 898 /** 899 * Save to local storage 900 */ 901 localStorage.setItem(DATA_KEY, JSON.stringify(data)); 902 903 return this; 904 }, 905 data: function() 906 { 907 var data = localStorage.getItem(DATA_KEY); 908 909 if (null !== data) 910 { 911 return JSON.parse(data); 912 } 913 914 return {}; 915 }, 916 merge: function() 917 { 918 var data = this.data(); 919 var push = 920 { 921 persist: {} 922 }; 923 924 for (var i in data) 925 { 926 push.persist[i] = data[i]; 927 } 928 929 dataLayer.push(push); 930 931 return this; 932 }, 933 clear: function() 934 { 935 /** 936 * Reset private local storage 937 */ 938 localStorage.setItem(DATA_KEY,JSON.stringify({})); 939 940 return this; 941 } 942 } : { 943 push: function(){}, 944 merge: function(){}, 945 clear: function(){} 946 }; 947 948 /** 949 * Constants 950 */ 951 proto.CONST_KEY_PROMOTION = 'persist_promotion'; 952 953 return proto; 954 955 })(), 956 Checkout: (function() 957 { 958 return { 959 init: false, 960 data: {}, 961 tracked: {}, 962 getData: function() 963 { 964 return this.data; 965 }, 966 getPayload: function() 967 { 968 if (this.data && this.data.hasOwnProperty('payload')) 969 { 970 return this.data.payload; 971 } 972 973 return { 974 error: 'Missing checkout payload data' 975 } 976 }, 977 step: function(previous, current, currentCode) 978 { 979 if (!this.init) 980 { 981 return this.fail('Step tracking requires a checkout page.'); 982 } 983 984 if (this.data && this.data.hasOwnProperty('ecommerce')) 985 { 986 this.data.ecommerce['step'] = ++current; 987 988 /** 989 * Notify listeners 990 */ 991 AEC.EventDispatcher.trigger('ec.checkout.step.data', this.data); 992 993 /** 994 * Track checkout step 995 */ 996 AEC.Cookie.checkout(this.data).push(dataLayer); 997 } 998 999 return this; 1000 }, 1001 stepOption: function(step, option) 1002 { 1003 if (!option) 1004 { 1005 return this; 1006 } 1007 1008 if (!this.init) 1009 { 1010 return this.fail('Step option tracking requires a checkout page.'); 1011 } 1012 1013 1014 if (!option.toString().length) 1015 { 1016 return this; 1017 } 1018 1019 var data = 1020 { 1021 'event': 'checkoutOption', 1022 'ecommerce': 1023 { 1024 'checkout_option': 1025 { 1026 'actionField': 1027 { 1028 'step': step, 1029 'option': option 1030 } 1031 } 1032 } 1033 }; 1034 1035 /** 1036 * Notify listeners 1037 */ 1038 AEC.EventDispatcher.trigger('ec.checkout.step.option.data', data); 1039 1040 /** 1041 * Track checkout option 1042 */ 1043 AEC.CookieConsent.queue(() => 1044 { 1045 AEC.Cookie.checkoutOption(data).push(dataLayer); 1046 1047 }).process(); 1048 1049 1050 return this; 1051 }, 1052 fail: function(message) 1053 { 1054 console.log(message); 1055 1056 return this; 1057 } 1058 1059 } 1060 })(),
1061 Cookie: (function() 1062 { 1063 return { 1064 data: null, 1065 privateData: null, 1066 reset: function() 1067 { 1068 if (AEC.reset) 1069 { 1070 dataLayer.push({ ecommerce: null }); 1071 } 1072 1073 return dataLayer; 1074 }, 1075 push: function(dataLayer, consent) 1076 { 1077 consent = typeof consent !== 'undefined' ? consent : true; 1078 1079 if (this.data) 1080 { 1081 if (consent) 1082 { 1083 this.reset().push(this.data); 1084 } 1085 else 1086 { 1087 this.reset().push(this.data); 1088 } 1089 1090 /** 1091 * Reset data to prevent further push 1092 */ 1093 this.data = null; 1094 } 1095 1096 return this; 1097 }, 1098 pushPrivate: function() 1099 { 1100 var data = this.getPrivateData(); 1101 1102 if (data) 1103 { 1104 dataLayer.push( 1105 { 1106 privateData: data 1107 }); 1108 } 1109 1110 return this; 1111 }, 1112 augment: function(products) 1113 { 1114 /** 1115 * Parse data & apply local reference 1116 */ 1117 var reference = AEC.Storage.reference().get(); 1118 1119 if (reference) 1120 { 1121 for (var i = 0, l = products.length; i < l; i++) 1122 { 1123 for (var a = 0, b = reference.length; a < b; a++) 1124 { 1125 if (products[i].item_id.toString().toLowerCase() === reference[a].id.toString().toLowerCase()) 1126 { 1127 products[i].category = reference[a].category; 1128 } 1129 } 1130 } 1131 } 1132 1133 return products; 1134 }, 1135 click: function(data) 1136 { 1137 AEC.EventDispatcher.trigger('ec.cookie.click.data', data); 1138 1139 this.data = data; 1140 1141 return this; 1142 }, 1143 add: function(data) 1144 { 1145 AEC.EventDispatcher.trigger('ec.cookie.add.data', data); 1146 1147 this.data = data; 1148 1149 return this; 1150 }, 1151 remove: function(data) 1152 { 1153 AEC.EventDispatcher.trigger('ec.cookie.remove.item.data', data); 1154 1155 this.data = data; 1156 1157 if (AEC.localStorage) 1158 { 1159 this.data.ecommerce.items = this.augment(this.data.ecommerce.items); 1160 } 1161 1162 return this; 1163 }, 1164 compare: function(data) 1165 { 1166 AEC.EventDispatcher.trigger('ec.cookie.compare.data', data); 1167 1168 this.data = data; 1169 1170 return this; 1171 }, 1172 wishlist: function(data) 1173 { 1174 AEC.EventDispatcher.trigger('ec.cookie.wishlist.data', data); 1175 1176 this.data = data; 1177 1178 return this; 1179 }, 1180 compare: function(data) 1181 { 1182 AEC.EventDispatcher.trigger('ec.cookie.compare.data', data); 1183 1184 this.data = data; 1185 1186 return this; 1187 }, 1188 wishlist: function(data) 1189 { 1190 AEC.EventDispatcher.trigger('ec.cookie.wishlist.data', data); 1191 1192 this.data = data; 1193 1194 return this; 1195 }, 1196 update: function(data) 1197 { 1198 AEC.EventDispatcher.trigger('ec.cookie.update.item.data', data); 1199 1200 this.data = data; 1201 1202 return this; 1203 }, 1204 visitor: function(data) 1205 { 1206 AEC.EventDispatcher.trigger('ec.cookie.visitor.data', data); 1207 1208 this.data = (function(data, privateData) 1209 { 1210 if (privateData) 1211 { 1212 if (privateData.hasOwnProperty('visitor')) 1213 { 1214 data.visitorId = privateData.visitor.visitorId; 1215 data.visitorLoginState = privateData.visitor.visitorLoginState; 1216 } 1217 } 1218 1219 return data; 1220 1221 })(data, AEC.Cookie.getPrivateData()); 1222 1223 return this; 1224 }, 1225 detail: function(data) 1226 { 1227 AEC.EventDispatcher.trigger('ec.cookie.detail.data', data); 1228 1229 this.data = data; 1230 1231 // Remove impressions array 1232 if (this.data.ecommerce.hasOwnProperty('impressions')) { 1233 delete this.data.ecommerce.impressions; 1234 } 1235 1236 // Remove specified properties from each item in ecommerce.items
1237 const propsToRemove = ['item_reviews_count', 'item_rating_summary', 'dimension10']; 1238 1239 this.data.ecommerce.items.forEach(item => { 1240 propsToRemove.forEach(prop => { 1241 if (item.hasOwnProperty(prop)) { 1242 delete item[prop]; 1243 } 1244 }); 1245 }); 1246 1247 return this; 1248 }, 1249 purchase: function(data) 1250 { 1251 AEC.EventDispatcher.trigger('ec.cookie.purchase.data', data); 1252 1253 this.data = data; 1254 1255 if (AEC.localStorage) 1256 { 1257 this.data.ecommerce.purchase.items = this.augment(this.data.ecommerce.purchase.items); 1258 } 1259 1260 // Move purchase properties to the ecommerce object instead of ecommerce.purchase 1261 const purchaseData = this.data.ecommerce.purchase; 1262 const keysToMove = ['transaction_id', 'affiliation', 'value', 'tax', 'shipping', 'coupon', 'discount']; 1263 1264 keysToMove.forEach(key => { 1265 this.data.ecommerce[key] = purchaseData[key]; 1266 }); 1267 1268 // Remove purchase object from ecommerce 1269 delete this.data.ecommerce.purchase; 1270 1271 // Remove specified properties from each item in ecommerce.items 1272 const propsToRemove = ['category', 'item_reviews_count', 'item_rating_summary', 'dimension10', 'variant_id']; 1273 1274 this.data.ecommerce.items.forEach(item => { 1275 propsToRemove.forEach(prop => { 1276 delete item[prop]; 1277 }); 1278 }); 1279 1280 return this; 1281 }, 1282 impressions: function(data) 1283 { 1284 AEC.EventDispatcher.trigger('ec.cookie.impression.data', data); 1285 1286 this.data = data; 1287 1288 return this; 1289 }, 1290 checkout: function(data) 1291 { 1292 AEC.EventDispatcher.trigger('ec.cookie.checkout.step.data', data); 1293 1294 this.data = data; 1295 1296 if (AEC.localStorage) 1297 { 1298 this.data.ecommerce.items = this.augment(this.data.ecommerce.items); 1299 } 1300 1301 return this; 1302 }, 1303 checkoutOption: function(data) 1304 { 1305 AEC.EventDispatcher.trigger('ec.cookie.checkout.step.option.data', data); 1306 1307 this.data = data; 1308 1309 return this; 1310 }, 1311 promotion: function(data) 1312 { 1313 AEC.EventDispatcher.trigger('ec.cookie.promotion.data', data); 1314 1315 this.data = data; 1316 1317 return this; 1318 }, 1319 promotionClick: function(data, element) 1320 { 1321 AEC.EventDispatcher.trigger('ec.cookie.promotion.click', data, 1322 { 1323 element: element 1324 }); 1325 1326 this.data = data; 1327 1328 return this; 1329 }, 1330 remarketing: function(data) 1331 { 1332 AEC.EventDispatcher.trigger('ec.cookie.remarketing.data', data); 1333 1334 this.data = data; 1335 1336 return this; 1337 }, 1338 getPrivateData: function() 1339 { 1340 if (!this.privateData) 1341 { 1342 var cookie = this.get('privateData'); 1343 1344 if (cookie) 1345 { 1346 this.privateData = this.parse(cookie); 1347 } 1348 } 1349 1350 return this.privateData; 1351 }, 1352 set: function(name, value, days) 1353 { 1354 if (!days) 1355 { 1356 days = 30; 1357 } 1358 1359 let date = new Date(); 1360 1361 date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); 1362 1363 document.cookie = name + "=" + value + "; expires=" + date.toGMTString() + "; path=/"; 1364 1365 return this; 1366 }, 1367 get: function(name) 1368 { 1369 var start = document.cookie.indexOf(name + "="), len = start + name.length + 1; 1370 1371 if ((!start) && (name != document.cookie.substring(0, name.length))) 1372 { 1373 return null; 1374 } 1375 1376 if (start == -1) 1377 { 1378 return null; 1379 } 1380 1381 var end = document.cookie.indexOf(String.fromCharCode(59), len); 1382 1383 if (end == -1) 1384 { 1385 end = document.cookie.length; 1386 } 1387 1388 return decodeURIComponent(document.cookie.substring(len, end)); 1389 }, 1390 unset: function(name) 1391 { 1392 document.cookie = name + "=" + "; path=/; expires=" + (new Date(0)).toUTCString(); 1393 1394 return this; 1395 }, 1396 parse: function(json) 1397 { 1398 var json = decodeURIComponent(json.replace(/\+/g, ' ')); 1399 1400 return JSON.parse(json); 1401 } 1402 } 1403 })(), 1404 CookieConsent: (function() 1405 { 1406 return { 1407 chain: {}, 1408 endpoints:{}, 1409 cookies: {}, 1410 widget: 1411 { 1412 display: false, 1413 color: 'rgba(0,0,0,1)', 1414 colorEnd: 'rgba(0,0,0,1)' 1415 }, 1416 queue: function(callback, event) 1417 { 1418 event = typeof event !== 'undefined' ? event : AEC.Const.COOKIE_DIRECTIVE_CONSENT_GRANTED_EVENT; 1419 1420 if (!this.chain.hasOwnProperty(event)) 1421 { 1422 this.chain[event] = []; 1423 } 1424 1425 this.chain[event].push(callback); 1426 1427 return this; 1428 }, 1429 dispatch: function(consent) 1430 { 1431 /** 1432 * Essential cookies 1433 */ 1434 AEC.Const.COOKIE_DIRECTIVE_CONSENT_GRANTED = true; 1435 1436 /** 1437 * Push consent to dataLayer 1438 */ 1439 dataLayer.push(consent); 1440 1441 return this.process(consent.event); 1442 }, 1443 process: function(event) 1444 { 1445 event = typeof event !== 'undefined' ? event : AEC.Const.COOKIE_DIRECTIVE_CONSENT_GRANTED_EVENT; 1446 1447 if (this.getConsent(event)) 1448 { 1449 this.dequeue(event); 1450 } 1451 else if (AEC.Const.COOKIE_DIRECTIVE_OVERRIDE_DECLINE) 1452 { 1453 this.dequeue(event); 1454 } 1455 1456 return this; 1457 }, 1458 dequeue: function(event) 1459 { 1460 if (this.chain.hasOwnProperty(event)) 1461 { 1462 for (a = 0, b = this.chain[event].length; a < b; a++) 1463 { 1464 this.chain[event][a].apply(this,[]); 1465 } 1466 1467 this.chain[event] = []; 1468 } 1469 1470 return this; 1471 }, 1472 getConsent: function(event) 1473 { 1474 return !AEC.Const.COOKIE_DIRECTIVE ? true : 1 == AEC.Cookie.get(event); 1475 }, 1476 acceptGoogleConsent: function(segments) 1477 { 1478 if ('function' === typeof gtag) 1479 { 1480 const consentMode = true === AEC.Const.COOKIE_DIRECTIVE_SEGMENT_MODE ? 1481 { 1482 ad_storage: -1 !== segments.indexOf('cookieConsentMarketingGranted') ? 'granted' : 'denied', 1483 security_storage: -1 !== segments.indexOf('cookieConsentGranted') ? 'granted' : 'denied', 1484 functionality_storage: -1 !== segments.indexOf('cookieConsentGranted') ? 'granted' : 'denied', 1485 personalization_storage: -1 !== segments.indexOf('cookieConsentPreferencesGranted') ? 'granted' : 'denied', 1486 analytics_storage: -1 !== segments.indexOf('cookieConsentAnalyticsGranted') ? 'granted' : 'denied', 1487 ad_user_data: -1 !== segments.indexOf('cookieConsentUserdata') ? 'granted' : 'denied', 1488 ad_personalization: -1 !== segments.indexOf('cookieConsentPersonalization') ? 'granted' : 'denied' 1489 } : 1490 { 1491 ad_storage: 'granted', 1492 security_storage: 'granted', 1493 functionality_storage: 'granted', 1494 personalization_storage: 'granted', 1495 analytics_storage: 'granted', 1496 ad_user_data: 'granted', 1497 ad_personalization: 'granted' 1498 } 1499 1500 /** 1501 * Update consent 1502 */ 1503 gtag('consent','update',consentMode); 1504 1505 /** 1506 * Update localStorage 1507 */ 1508 localStorage.setItem('consentMode', JSON.stringify(consentMode)); 1509 1510 /**
1511 * Dispatch custom event 1512 */ 1513 window.dispatchEvent(new CustomEvent("consent_accept", { detail: { consentMode: consentMode, segments: segments } })); 1514 } 1515 1516 return this; 1517 }, 1518 acceptConsent: function(event) 1519 { 1520 return this.dispatch({ event:event }); 1521 }, 1522 declineConsent: function(event) 1523 { 1524 return this.dispatch({ event:event }); 1525 }, 1526 declineGoogleConsent: function() 1527 { 1528 if ('function' === typeof gtag) 1529 { 1530 const consentMode = 1531 { 1532 ad_storage: 'denied', 1533 security_storage: 'denied', 1534 functionality_storage: 'denied', 1535 personalization_storage: 'denied', 1536 analytics_storage: 'denied', 1537 ad_user_data: 'denied', 1538 ad_personalization: 'denied' 1539 }; 1540 1541 /** 1542 * Update consent 1543 */ 1544 gtag('consent','update',consentMode); 1545 1546 /** 1547 * Update localStorage 1548 */ 1549 localStorage.setItem('consentMode', JSON.stringify(consentMode)); 1550 1551 /** 1552 * Dispatch custom event 1553 */ 1554 window.dispatchEvent(new CustomEvent("consent_decline",{ detail: { consentMode: consentMode } })); 1555 } 1556 1557 return this; 1558 }, 1559 setEndpoints: function(endpoints) 1560 { 1561 this.endpoints = endpoints; 1562 1563 return this; 1564 }, 1565 getConsentDialog: function(dataLayer) 1566 { 1567 var endpoints = this.endpoints; 1568 1569 if (1 == AEC.Cookie.get(AEC.Const.COOKIE_DIRECTIVE_CONSENT_DECLINE_EVENT)) 1570 { 1571 AEC.CookieConsent.declineGoogleConsent([AEC.Const.COOKIE_DIRECTIVE_CONSENT_DECLINE_EVEN]).getWidget(); 1572 1573 return true; 1574 } 1575 1576 if (1 != AEC.Cookie.get(AEC.Const.COOKIE_DIRECTIVE_CONSENT_GRANTED_EVENT)) 1577 { 1578 this.renderConsentDialog(dataLayer); 1579 } 1580 else 1581 { 1582 if (AEC.Const.COOKIE_DIRECTIVE_SEGMENT_MODE) 1583 { 1584 (segments => 1585 { 1586 let grant = []; 1587 1588 for (i = 0, l = segments.length; i < l;i++) 1589 { 1590 if (1 == AEC.Cookie.get(segments[i])) 1591 { 1592 AEC.CookieConsent.acceptConsent(segments[i]); 1593 1594 grant.push(segments[i]); 1595 } 1596 } 1597 1598 AEC.CookieConsent.acceptGoogleConsent(grant).getWidget(); 1599 1600 })(AEC.Const.COOKIE_DIRECTIVE_SEGMENT_MODE_EVENTS); 1601 } 1602 else 1603 { 1604 AEC.CookieConsent.acceptConsent(AEC.Const.COOKIE_DIRECTIVE_CONSENT_GRANTED_EVENT).getWidget(); 1605 } 1606 } 1607 }, 1608 closeConsentDialog: function(directive) 1609 { 1610 directive.remove(); 1611 1612 this.getWidget(); 1613 1614 return this; 1615 }, 1616 renderConsentDialog: function(dataLayer) 1617 { 1618 let template = document.querySelector('template[data-consent]'); 1619 1620 (endpoints => 1621 { 1622 var directive = (body => 1623 { 1624 body.insertAdjacentHTML('beforeend', template.innerHTML); 1625 1626 return body.lastElementChild; 1627 1628 })(document.body); 1629 1630 let uuid = AEC.Cookie.get('cookieUuid'); 1631 1632 if (uuid) 1633 { 1634 directive.querySelector('[data-consent-uuid').innerHTML = uuid; 1635 } 1636 1637 let check_default = Number(directive.dataset.check); 1638 1639 directive.querySelectorAll('input[type=checkbox][data-consent]').forEach(checkbox => 1640 { 1641 checkbox.checked = AEC.CookieConsent.getConsent(checkbox.dataset.consent) ? true : (!uuid && check_default ? true : false); 1642 }); 1643 1644 1645 directive.querySelector('[data-consent-uuid-wrapper]').style.display = uuid ? 'block' : 'none'; 1646 1647 (directive => 1648 { 1649 let listener = event => 1650 { 1651 if (event.key === 'Escape') 1652 { 1653 AEC.CookieConsent.closeConsentDialog(directive).acquireProxyCookies(); 1654 } 1655 }; 1656 document.addEventListener('keydown', event => 1657 { 1658 listener(event); 1659 1660 document.removeEventListener('keydown', listener); 1661 }); 1662 1663 })(directive); 1664 1665 directive.querySelectorAll('a.customize').forEach(element => 1666 { 1667 let customize = directive.querySelector('.ec-gtm-cookie-directive-customize'); 1668 1669 element.addEventListener('click', event => 1670 { 1671 if ('block' === customize.style.display) 1672 { 1673 directive.querySelector('a.action.accept').style.display = 'none'; 1674 1675 customize.style.display = 'none'; 1676 } 1677 else 1678 { 1679 directive.querySelector('a.action.accept').style.display = 'block'; 1680 1681 customize.style.display = 'block'; 1682 } 1683 1684 event.target.innerHTML = 'block' === customize.style.display ? event.target.dataset.hide : event.target.dataset.show; 1685 }); 1686 }); 1687 1688 directive.querySelectorAll('a.ec-gtm-cookie-directive-note-toggle').forEach(element => 1689 { 1690 element.addEventListener('click', event => 1691 { 1692 if ('block' === event.target.nextElementSibling.style.display) 1693 { 1694 event.target.nextElementSibling.style.display = 'none'; 1695 } 1696 else 1697 { 1698 directive.querySelectorAll('.ec-gtm-cookie-directive-note').forEach(note => 1699 { 1700 note.previousElementSibling.innerHTML = note.previousElementSibling.dataset.show; 1701 1702 note.style.display = 'none'; 1703 }); 1704 1705 event.target.nextElementSibling.style.display = 'block'; 1706 } 1707 1708 event.target.innerHTML = 'block' === event.target.nextElementSibling.style.display ? event.target.dataset.hide : event.target.dataset.show; 1709 1710 }); 1711 }); 1712 1713 directive.querySelectorAll('a.accept').forEach(element => 1714 { 1715 element.addEventListener('click', event => 1716 { 1717 event.target.text = event.target.dataset.confirm; 1718 1719 var grant = [...directive.querySelectorAll('[name="cookie[]"]:checked')].map(element => { return element.value }); 1720 1721 grant.unshift('cookieConsentGranted'); 1722 1723 AEC.CookieConsent.acceptGoogleConsent(grant); 1724 1725 AEC.Request.post(endpoints.cookie, { cookie: grant }, response => 1726 { 1727 Object.keys(response).forEach(event => 1728 { 1729 AEC.CookieConsent.acceptConsent(event); 1730 }); 1731 1732 AEC.CookieConsent.closeConsentDialog(directive).acquireProxyCookies(); 1733 }); 1734 }); 1735 }); 1736 1737 directive.querySelectorAll('a.accept-all').forEach(element => 1738 { 1739 element.addEventListener('click', event => 1740 { 1741 event.target.text = event.target.dataset.confirm; 1742 1743 [...directive.querySelectorAll('[name="cookie[]"]')].forEac
1743h(element => 1744 { 1745 element.checked = true; 1746 }); 1747 1748 var grant = [...directive.querySelectorAll('[name="cookie[]"]:checked')].map(element => { return element.value }); 1749 1750 grant.unshift('cookieConsentGranted'); 1751 1752 AEC.CookieConsent.acceptGoogleConsent(grant); 1753 1754 AEC.Request.post(endpoints.cookie, { cookie: grant }, response => 1755 { 1756 Object.keys(response).forEach(event => 1757 { 1758 AEC.CookieConsent.acceptConsent(event); 1759 }); 1760 1761 AEC.CookieConsent.closeConsentDialog(directive).acquireProxyCookies(); 1762 }); 1763 }); 1764 }); 1765 1766 directive.querySelectorAll('a.decline').forEach(element => 1767 { 1768 element.addEventListener('click', event => 1769 { 1770 [...directive.querySelectorAll('[name="cookie[]"]')].forEach(element => 1771 { 1772 element.checked = false; 1773 }); 1774 1775 AEC.CookieConsent.declineGoogleConsent(); 1776 1777 AEC.Request.post(endpoints.cookie, { decline: true }, response => 1778 { 1779 Object.keys(response).forEach(event => 1780 { 1781 AEC.CookieConsent.declineConsent(event); 1782 }); 1783 1784 AEC.CookieConsent.closeConsentDialog(directive).acquireProxyCookies(); 1785 }); 1786 }); 1787 }); 1788 1789 directive.querySelectorAll('a.close').forEach(element => 1790 { 1791 element.style.display = AEC.Const.COOKIE_DIRECTIVE_CONSENT_GRANTED ? 'block' : 'none'; 1792 1793 element.addEventListener('click', event => 1794 { 1795 AEC.CookieConsent.closeConsentDialog(directive).acquireProxyCookies(); 1796 }); 1797 }); 1798 })(this.endpoints); 1799 1800 return this; 1801 }, 1802 acquireProxyCookies: function() 1803 { 1804 const acquire = localStorage.getItem("acquire"); 1805 1806 if (!acquire) 1807 { 1808 document.cookie.split(';').map(e => e.trim()).forEach(cookie => 1809 { 1810 let name = cookie.substr(0, cookie.indexOf('=')); 1811 1812 if (!this.cookies.hasOwnProperty(name)) 1813 { 1814 this.cookies[name] = true; 1815 } 1816 }); 1817 1818 AEC.Request.post(this.endpoints.cookieConsent, { cookies: this.cookies }, response => 1819 { 1820 return true; 1821 }); 1822 1823 localStorage.setItem("acquire", true); 1824 } 1825 1826 return this; 1827 }, 1828 setProxy: function() 1829 { 1830 if (true) 1831 { 1832 let cookieDesc = Object.getOwnPropertyDescriptor(Document.prototype, 'cookie') || Object.getOwnPropertyDescriptor(HTMLDocument.prototype, 'cookie'); 1833 1834 function checkStorage() 1835 { 1836 return [].concat.apply([], []); 1837 } 1838 1839 window.addEventListener('captured_cookie', event => 1840 { 1841 this.cookies[event.detail.cookie.name] = event.detail.cookie.value; 1842 }); 1843 1844 if (cookieDesc && cookieDesc.configurable) 1845 { 1846 Object.defineProperty(document, 'cookie', 1847 { 1848 get: function() 1849 { 1850 return cookieDesc.get.call(document); 1851 }, 1852 set: function(val) 1853 { 1854 var c = val.split('=')[0]; 1855 1856 if (val[0] === '!') 1857 { 1858 cookieDesc.set.call(document, val.slice(1)); 1859 } 1860 else if (-1 == checkStorage().indexOf(c)) 1861 { 1862 cookieDesc.set.call(document, val); 1863 1864 window.dispatchEvent(new CustomEvent("captured_cookie",{ detail: { cookie: { name: c, value: val } }})); 1865 } 1866 else 1867 { 1868 blocked.push(val); 1869 } 1870 } 1871 }); 1872 } 1873 } 1874 1875 return this; 1876 }, 1877 setWidget: function(options) 1878 { 1879 (() => 1880 { 1881 let block = {}; 1882 1883 let materialize = script => 1884 { 1885 let tag = document.createElement('script'); 1886 1887 tag.type = "text/javascript"; 1888 tag.innerHTML = script.innerHTML; 1889 1890 if (script.getAttribute('src')) 1891 { 1892 tag.src = script.src; 1893 } 1894 1895 script.parentNode.appendChild(tag); 1896 script.parentNode.removeChild(script); 1897 }; 1898 1899 let pickup = event => 1900 { 1901 document.querySelectorAll('script[data-consent]').forEach(script => 1902 { 1903 let segment = script.dataset.segment; 1904 1905 if (-1 != event.detail.segments.indexOf(segment)) 1906 { 1907 delete script.dataset.consent; 1908 delete script.dataset.segment; 1909 1910 materialize(script); 1911 } 1912 }); 1913 }; 1914 1915 window.addEventListener('consent_accept', event => 1916 { 1917 pickup(event); 1918 1919 (e => 1920 { 1921 window.addEventListener('load', event => 1922 { 1923 pickup(e); 1924 }); 1925 1926 })(event); 1927 }); 1928 })(); 1929 1930 this.widget = {...this.widget, ...options }; 1931 1932 return this; 1933 }, 1934 getWidget: function() 1935 {
1936 if (this.widget.display) 1937 { 1938 let svg = (node => 1939 { 1940 return (text => 1941 { 1942 let styles = 1943 { 1944 position: 'fixed', 1945 bottom: '10px', 1946 left: '10px', 1947 'z-index': '9999', 1948 cursor: 'pointer' 1949 }; 1950 1951 let style = Object.entries(styles).map(([key, value]) => 1952 { 1953 return [key,value].join(':'); 1954 }); 1955 1956 let svg = node('svg', { id: 'consentWidget', width:50, height: 50, style: style.join(';') }); 1957 1958 let gradient = node('linearGradient', { id: 'gradient', gradientTransform: 'rotate(90)'}); 1959 1960 let filter = node('filter', { id: 'shadow' }); 1961 1962 [ 1963 node('feDropShadow', { dx: '0', dy: '0', stdDeviation: '0.7','flood-opacity': 0.5 }), 1964 1965 ].forEach(element => 1966 { 1967 filter.appendChild(element); 1968 }); 1969 1970 let count = parseInt(text); 1971 1972 [ 1973 node('stop', { offset: '0%', 'stop-color': this.widget.color }), 1974 node('stop', { offset: '100%', 'stop-color': this.widget.colorEnd }) 1975 1976 ].forEach(element => 1977 { 1978 gradient.appendChild(element); 1979 }); 1980 1981 1982 if (0) 1983 { 1984 svg.appendChild(filter); 1985 } 1986 1987 svg.appendChild(gradient); 1988 1989 let transform = 'scale(1.5 1.5) translate(1 10)'; 1990 1991 [ 1992 node('path', { id: 'a', d: 'M22.6004 0H7.40039C3.50039 0 0.400391 3.1 0.400391 7C0.400391 10.9 3.50039 14 7.40039 14H22.6004C26.5004 14 29.6004 10.9 29.6004 7C29.6004 3.1 26.4004 0 22.6004 0ZM1.60039 7C1.60039 3.8 4.20039 1.2 7.40039 1.2H17.3004L14.2004 12.8H7.40039C4.20039 12.8 1.60039 10.2 1.60039 7Z', filter: 'url(#shadow)', fill: 'url(#gradient)', transform: transform }), 1993 node('path', { id: 'b', d: 'M24.6012 4.0001C24.8012 4.2001 24.8012 4.6001 24.6012 4.8001L22.5012 7.0001L24.7012 9.2001C24.9012 9.4001 24.9012 9.8001 24.7012 10.0001C24.5012 10.2001 24.1012 10.2001 23.9012 10.0001L21.7012 7.8001L19.5012 10.0001C19.3012 10.2001 18.9012 10.2001 18.7012 10.0001C18.5012 9.8001 18.5012 9.4001 18.7012 9.2001L20.8012 7.0001L18.6012 4.8001C18.4012 4.6001 18.4012 4.2001 18.6012 4.0001C18.8012 3.8001 19.2012 3.8001 19.4012 4.0001L21.6012 6.2001L23.8012 4.0001C24.0012 3.8001 24.4012 3.8001 24.6012 4.0001Z', fill: 'rgba(255,255,255,1)', transform: transform }), 1994 node('path', { id: 'c', d: 'M12.7 4.1002C12.9 4.3002 13 4.7002 12.8 4.9002L8.6 9.8002C8.5 9.9002 8.4 10.0002 8.3 10.0002C8.1 10.1002 7.8 10.1002 7.6 9.9002L5.4 7.7002C5.2 7.5002 5.2 7.
19941002 5.4 6.9002C5.6 6.7002 6 6.7002 6.2 6.9002L8 8.6002L11.8 4.1002C12 3.9002 12.4 3.9002 12.7 4.1002Z', fill: 'url(#gradient)', transform: transform, filter: 'url(#shadow)' }) 1995 1996 ].forEach(element => 1997 { 1998 svg.appendChild(element); 1999 }); 2000 2001 let loader = node('circle', { id: 'd', cx: 13, cy:25.5, r: 6, fill:'transparent', stroke:'url(#gradient)', 'stroke-width':2, 'stroke-dasharray':'60 40', 'stroke-dashoffset': 40, filter: 'url(#shadow)', style: 'display:none' }); 2002 2003 [ 2004 node('animateTransform', 2005 { 2006 attributeName: "transform", 2007 attributeType: "XML", 2008 type: "rotate", 2009 dur: "1s", 2010 from: "0 13 25.5", 2011 to: "360 13 25.5", 2012 repeatCount: "indefinite" 2013 }) 2014 2015 ].forEach(element => 2016 { 2017 loader.appendChild(element); 2018 }); 2019 2020 svg.appendChild(loader); 2021 2022 return svg; 2023 }); 2024 2025 })((n, v) => 2026 { 2027 n = document.createElementNS("http://www.w3.org/2000/svg", n); 2028 2029 for (var p in v) 2030 { 2031 n.setAttributeNS(null, p, v[p]); 2032 } 2033 2034 return n; 2035 }); 2036 2037 let widget = svg(); 2038 2039 /** 2040 * Remove widget 2041 */ 2042 this.deleteWidget(); 2043 2044 /** 2045 * Add widget 2046 */ 2047 document.body.appendChild(widget); 2048 2049 /** 2050 * Render widget 2051 */ 2052 document.body.querySelectorAll('[id=consentWidget]').forEach(element => 2053 { 2054 element.addEventListener('click', event => 2055 { 2056 AEC.CookieConsent.renderConsentDialog(dataLayer); 2057 }); 2058 }); 2059 2060 return widget; 2061 } 2062 2063 return null; 2064 }, 2065 deleteWidget: function() 2066 { 2067 document.body.querySelectorAll('[id=consentWidget]').forEach(element => 2068 { 2069 element.parentNode.removeChild(element); 2070 }); 2071 2072 return this; 2073 }, 2074 loader: (function() 2075 { 2076 return { 2077 show: function() 2078 { 2079 document.querySelectorAll('[id=c]').forEach(e => { e.style.display = 'none' }); 2080 document.querySelectorAll('[id=d]').forEach(e => { e.style.display = 'block' }); 2081 }, 2082 hide: function() 2083 { 2084 document.querySelectorAll('[id=c]').forEach(e => { e.style.display = 'block' }); 2085 document.querySelectorAll('[id=d]').forEach(e => { e.style.display = 'none' }); 2086 } 2087 } 2088 })() 2089 } 2090 })(), 2091 Storage: (function(api) 2092 { 2093 return { 2094 set: function(property, value) 2095 { 2096 if ('undefined' !== typeof(Storage)) 2097 { 2098 localStorage.setItem(property, JSON.stringify(value)); 2099 } 2100 2101 return this; 2102 2103 }, 2104 get: function(property) 2105 { 2106 if ('undefined' !== typeof(Storage)) 2107 { 2108 return JSON.parse(localStorage.getItem(property)); 2109 } 2110 2111 return null; 2112 }, 2113 reference: function() 2114 { 2115 return (function(storage) 2116 { 2117 return { 2118 set: function(reference) 2119 { 2120 var current = storage.get('category.add') || []; 2121 2122 2123 var exists = (function(current, reference) 2124 { 2125 for (i = 0, l = current.length; i < l; i++) 2126 { 2127 if (current[i].id.toString().toLowerCase() === reference.id.toString().toLowerCase()) 2128 { 2129 /** 2130 * Update category 2131 */ 2132 current[i].category = reference.category; 2133 2134 return true; 2135 } 2136 } 2137 2138 return false;
2139 2140 })(current, reference); 2141 2142 if (!exists) 2143 { 2144 current.push(reference); 2145 } 2146 2147 storage.set('category.add', current); 2148 2149 return this; 2150 }, 2151 get: function() 2152 { 2153 return storage.get('category.add'); 2154 } 2155 } 2156 })(this); 2157 } 2158 } 2159 })(), 2160 gtm: function() 2161 { 2162 if ("undefined" === typeof google_tag_manager) 2163 { 2164 /** 2165 * Log error to console 2166 */ 2167 console.log('Unable to detect Google Tag Manager. Please verify if GTM install snippet is available.'); 2168 2169 return false; 2170 } 2171 2172 return true; 2173 }, 2174 parseJSON: function(content) 2175 { 2176 if ('object' === typeof content) 2177 { 2178 return content; 2179 } 2180 2181 if ('string' === typeof content) 2182 { 2183 try 2184 { 2185 return JSON.parse(content); 2186 } 2187 catch (e){} 2188 } 2189 2190 return {}; 2191 }, 2192 getPayloadSize: function(object) 2193 { 2194 var objects = [object]; 2195 var size = 0; 2196 2197 // Do not trigger view_item_list in category or search pages 2198 if (object.event === 'view_item_list') { 2199 return; 2200 } 2201 2202 for (var index = 0; index < objects.length; index++) 2203 { 2204 switch (typeof objects[index]) 2205 { 2206 case 'boolean': 2207 size += 4; 2208 break; 2209 case 'number': 2210 size += 8; 2211 break; 2212 case 'string': 2213 size += 2 * objects[index].length; 2214 break; 2215 case 'object': 2216 if (Object.prototype.toString.call(objects[index]) != '[object Array]') 2217 { 2218 for (var key in objects[index]) size += 2 * key.length; 2219 } 2220 for (var key in objects[index]) 2221 { 2222 var processed = false; 2223 2224 for (var search = 0; search < objects.length; search++) 2225 { 2226 if (objects[search] === objects[index][key]) { 2227 processed = true; 2228 break; 2229 } 2230 } 2231 if (!processed) objects.push(objects[index][key]); 2232 } 2233 } 2234 } 2235 return size; 2236 }, 2237 getPayloadChunks: function(arr, len) 2238 { 2239 var chunks = [],i = 0, n = arr.length; 2240 2241 while (i < n) 2242 { 2243 chunks.push(arr.slice(i, i += len)); 2244 } 2245 2246 return chunks; 2247 }, 2248 url: function(url) 2249 { 2250 return [this.Const.URL, url].join(''); 2251 }, 2252 EventDispatcher: (function() 2253 { 2254 return { 2255 events: {}, 2256 on: function(event, callback) 2257 { 2258 var handlers = this.events[event] || []; 2259 2260 handlers.push(callback); 2261 2262 this.events[event] = handlers; 2263 }, 2264 trigger: function() 2265 { 2266 /** 2267 * Cast arguments to array 2268 */ 2269 let args = [...arguments]; 2270 2271 /** 2272 * Get event 2273 */ 2274 let event = args ? args.shift() : null; 2275 2276 /** 2277 * Get handlers 2278 */ 2279 let handlers = this.events[event] || []; 2280 2281 /** 2282 * Get data 2283 */ 2284 let data = args ? args.shift() : {}; 2285 2286 /** 2287 * Get options 2288 */ 2289 let options = args ? args.shift() : {}; 2290 2291 /** 2292 * Quit if no handler 2293 */ 2294 if (!handlers || handlers.length < 1) 2295 { 2296 return; 2297 } 2298 2299 console.log(event + '(' + handlers.length + ' listeners)'); 2300
2301 handlers.forEach(function(handler) 2302 { 2303 handler(data, options); 2304 }); 2305 } 2306 } 2307 })(), 2308 Request: (function() 2309 { 2310 return { 2311 get: function(url, params, callback) 2312 { 2313 this.execute('GET', [url,this.serialize(params)].join('?'), callback).send(null); 2314 }, 2315 post: function(url, params, callback) 2316 { 2317 this.execute('POST', url, callback).send(this.serialize(params)); 2318 }, 2319 execute: function(method, url, callback) 2320 { 2321 try 2322 { 2323 var request = new XMLHttpRequest(); 2324 2325 request.open(method, url, true); 2326 2327 request.setRequestHeader('Content-Type','application/x-www-form-urlencoded'); 2328 request.setRequestHeader('X-Requested-With','XMLHttpRequest'); 2329 2330 request.addEventListener('load', () => 2331 { 2332 let response; 2333 2334 if ('application/json' === request.getResponseHeader("Content-Type")) 2335 { 2336 response = JSON.parse(request.responseText); 2337 } 2338 else 2339 { 2340 response = request.responseText; 2341 } 2342 2343 if ('function' === typeof callback) 2344 { 2345 callback(response); 2346 } 2347 }); 2348 } 2349 catch (e) 2350 { 2351 console.log(e.message); 2352 2353 return null; 2354 } 2355 2356 2357 return request; 2358 }, 2359 serialize: function(entity, prefix) 2360 { 2361 var query = []; 2362 2363 Object.keys(entity).map(key => 2364 { 2365 var k = prefix ? prefix + "[" + key + "]" : key, value = entity[key]; 2366 2367 query.push((value !== null && typeof value === "object") ? this.serialize(value, k) : encodeURIComponent(k) + "=" + encodeURIComponent(value)); 2368 }); 2369 2370 return query.join("&"); 2371 } 2372 } 2373 })(), 2374 UUID: (() => 2375 { 2376 return { 2377 generate: event => 2378 { 2379 event = event || {}; 2380 2381 let uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) 2382 { 2383 var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); 2384 return v.toString(16); 2385 }); 2386 2387 if (-1 == ['AddToCart'].indexOf(event)) 2388 { 2389 try 2390 { 2391 let current = AEC.Cookie.get('facebook_latest_uuid'); 2392 2393 if (current) 2394 { 2395 current = JSON.parse(current); 2396 2397 if (current.hasOwnProperty('uuid') && current.hasOwnProperty('event')) 2398 { 2399 if (event.event === current.event) 2400 { 2401 uuid = current.uuid; 2402 } 2403 } 2404 } 2405 } 2406 catch (e){} 2407 } 2408 2409 event['uuid'] = uuid; 2410 2411 /** 2412 * Set facebook uuid cookie 2413 */ 2414 if (AEC.Const.COOKIE_DIRECTIVE) 2415 { 2416 if (AEC.Const.COOKIE_DIRECTIVE_CONSENT_GRANTED) 2417 { 2418 AEC.Cookie.set('facebook_latest_uuid', JSON.stringify(event)); 2419 } 2420 } 2421 else 2422 { 2423 AEC.Cookie.set('facebook_latest_uuid', JSON.stringify(event)); 2424 } 2425 2426 return uuid; 2427 } 2428 } 2429 })() 2430 } 2431})();
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.