PageSourceSearch

https://www.polyperformance.com/static/version1789045122/frontend/…/porto_ppi/en_US/Anowave_Ec/js/ec.js

js polyperformance.com collected 2026-10-06 15:22:34 UTC 42,244 bytes, 1,888 lines download raw bytes

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

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.