PageSourceSearch

https://www.justrite.com/static/version1790759712/frontend/Shero/justrite/en_US/Anowave_Ec/js/ec.js

js justrite.com collected 2026-10-09 21:41:45 UTC 91,628 bytes, 2,431 lines download raw bytes

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.