PageSourceSearch

https://crlab.com/static/version1783065476/frontend/Crlab/crlab/en_US/Anowave_Ec/js/ec.js

js crlab.com collected 2026-09-24 12:29:03 UTC 38,559 bytes, 1,758 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				            	jQuery(document).dataPost('postData', AEC.parseJSON(element.dataset.postAction));
581				            },
582				            cancel: function()
583				            {
584				            	return false;
585				            },
586				            always: function()
587				            {
588				            	return false;
589				            }
590				        }
591				    });
592				});
593			}
594			else 
595			{
596				/**
597				 * Track event
598				 */
599				AEC.Cookie.remove(data).push(dataLayer);
600
601				/**
602				 * Track time 
603				 */
604				AEC.Time.track(dataLayer, AEC.Const.TIMING_CATEGORY_REMOVE_FROM_CART, element.dataset.name);
605			}
606			
607			return false;
608		},
609		wishlist: function(context, dataLayer)
610		{
611			var element = context;
612
613			if (!AEC.gtm())
614			{
615				/**
616				 * Track time 
617				 */
618				AEC.Time.track(dataLayer, AEC.Const.TIMING_CATEGORY_PRODUCT_WISHLIST, element.dataset.name,'Wishlist');
619				
620				return true;
621			}
622			
623			let data = 
624			{
625				event: 		element.dataset.event,
626				eventLabel: element.dataset.eventLabel
627			};
628			
629			AEC.EventDispatcher.trigger('ec.add.wishlist', data, { attributes: element.dataset.eventAttributes });
630			
631			/**
632			 * Push data
633			 */
634			dataLayer.push(data);
635
636			return true;
637		},
638		compare: function(context, dataLayer)
639		{
640			var element = context;
641
642			if (!AEC.gtm())
643			{
644				/**
645				 * Track time 
646				 */
647				AEC.Time.track(dataLayer, AEC.Const.TIMING_CATEGORY_PRODUCT_COMPARE, element.dataset.name,'Compare');
648				
649				return true;
650			}
651			
652			let data = 
653			{
654				event: 		element.dataset.event,
655				eventLabel: element.dataset.eventLabel
656			};
657			
658			AEC.EventDispatcher.trigger('ec.add.compare', data, { attributes: element.dataset.eventAttributes } );
659
660			/**
661			 * Push data
662			 */
663			dataLayer.push(data);
664			
665			return true;
666		},
667		Bind: (function()
668		{
669			return {
670				apply: function(parameters)
671				{	
672					/**
673					 * Merge persistent storage
674					 */
675					AEC.Persist.merge();
676					
677					/**
678					 * Push private data
679					 */
680					AEC.Cookie.pushPrivate();
681					
682					document.addEventListener('DOMContentLoaded',() => 
683					{
684						document.body.addEventListener('catalogCategoryAddToCartRedirect', () => 
685						{
686							dataLayer.push(
687							{
688								event: AEC.Const.CATALOG_CATEGORY_ADD_TO_CART_REDIRECT_EVENT
689							});
690						});
691					});
692
693					if (parameters)
694					{
695						if (parameters.performance)
696						{
697							if (window.performance)
698							{
699								window.onload = function()
700								{
701									setTimeout(function()
702									{
703									    var time = performance.timing.loadEventEnd - performance.timing.responseEnd;
704									    
705									    var timePayload = 
706									    {
707								    		'event':'performance',
708							    			'performance':
709							    			{
710							    				'timingCategory':	'Load times',
711							    				'timingVar':		'load',
712							    				'timingValue': 		(time % 60000)
713							    			}	
714									    };
715									    
716									    switch(window.google_tag_params.ecomm_pagetype)
717									    {
718									    	case 'home':
719									    		
720									    		timePayload.performance.timingLabel = 'Home';
721									    		
722									    		AEC.CookieConsent.queue(() => 
723									            {
724									            	dataLayer.push(timePayload);
725									            }).process();
726									    		
727									    		break;
728									    	case 'product':
729									    		
730									    		timePayload.performance.timingLabel = 'Product';
731									    		
732									    		AEC.CookieConsent.queue(() => 
733									            {
734									            	dataLayer.push(timePayload);
735									            }).process();
736									    		
737									    		break;
738									    	
739								    		case 'category':
740									    		
741									    		timePayload.performance.timingLabel = 'Category';
742									    		
743									    		AEC.CookieConsent.queue(() => 
744									            {
745									            	dataLayer.push(timePayload);
746									            }).process();
747									    		
748									    		break;
749									    }
750									    
751									}, 0);
752								}	
753							}
754						}
755					}
756					
757					return this;
758				}
759			}
760		})(),
761		Time: (function()
762		{
763			var T = 
764			{
765				event: 			'trackTime',
766				timingCategory:	'',
767				timingVar:		'',
768				timingValue:	-1,
769				timingLabel:	''
770			};
771
772			var time = new Date().getTime();
773			
774			return {
775				track: function(dataLayer, category, variable, label)
776				{
777					T.timingValue = (new Date().getTime()) - time;
778					
779					if (category)
780					{
781						T.timingCategory = category;
782					}
783
784					if (variable)
785					{
786						T.timingVar = variable;
787					}
788
789					if (label)
790					{
791						T.timingLabel = label;
792					}
793					
794					(function(callback)
795					{
796						if (AEC.Const.COOKIE_DIRECTIVE)
797						{
798							AEC.CookieConsent.queue(callback).process();
799						}
800						else 
801						{
802							callback.apply(window,[]);
803						}
804					})
805					(
806						(function(dataLayer, T)
807						{
808							return function()
809							{
810								dataLayer.push(T);
811							}
812						})(dataLayer, T)
813					);
814				},
815				trackContinue: function(dataLayer, category, variable, label)
816				{
817					this.track(dataLayer, category, variable, label);
818
819					time = new Date().getTime();
820				}
821			}
822		})(),
823		Persist:(function()
824		{
825			var DATA_KEY = 'persist'; 
826
827			var proto = 'undefined' != typeof Storage ? 
828			{
829				push: function(key, entity)
830				{
831					/**
832					 * Get data
833					 */
834					var data = this.data();
835
836					/**
837					 * Push data
838					 */
839					data[key] = entity;
840
841					/**
842					 * Save to local storage
843					 */
844					localStorage.setItem(DATA_KEY, JSON.stringify(data));
845
846					return this;
847				},
848				data: function()
849				{
850					var data = localStorage.getItem(DATA_KEY);
851					
852					if (null !== data)
853					{
854						return JSON.parse(data);
855					}
856
857					return {};
858				},
859				merge: function()
860				{
861					var data = this.data();
862					var push = 
863					{
864						persist: {}
865					};
866
867					for (var i in data)
868					{
869						push.persist[i] = data[i];
870					}
871
872					dataLayer.push(push);
873
874					return this;
875				},
876				clear: function()
877				{
878					/**
879					 * Reset private local storage
880					 */
881					localStorage.setItem(DATA_KEY,JSON.stringify({}));
882
883					return this;
884				}
885			} : {
886				push: 	function(){}, 
887				merge: 	function(){},
888				clear: 	function(){}
889			};
890
891			/**
892			 * Constants
893			 */
894			proto.CONST_KEY_PROMOTION = 'persist_promotion';
895
896			return proto;
897			
898		})(),
899		Checkout: (function()
900		{
901			return {
902				data: {},
903				tracked: {},
904				step: function(previous, current, currentCode)
905				{
906					if (this.data && this.data.hasOwnProperty('ecommerce'))
907					{	
908						this.data.ecommerce.checkout.actionField.step = ++current;
909
910						/**
911						 * Notify listeners
912						 */
913						AEC.EventDispatcher.trigger('ec.checkout.step.data', this.data);
914						
915						/**
916						 * Track checkout step
917						 */
918						AEC.Cookie.checkout(this.data).push(dataLayer);
919					}
920					
921					return this;
922				},
923				stepOption: function(step, option)
924				{
925					if (!option)
926					{
927						return this;
928					}
929					
930					if (!option.toString().length)
931					{
932						return this;
933					}
934					
935					var data = 
936					{
937	    				'event': 'checkoutOption',
938	    				'ecommerce': 
939	    				{
940	    					'checkout_option': 
941	    					{
942	    						'actionField': 
943	    						{
944	    							'step': step,
945	    							'option': option
946	    						}
947	    					}
948	    				}
949	        		};
950					
951					/**
952					 * Notify listeners
953					 */
954					AEC.EventDispatcher.trigger('ec.checkout.step.option.data', data);
955					
956					/**
957					 * Track checkout option
958					 */
959					AEC.Cookie.checkoutOption(data).push(dataLayer);
960					
961					return this;
962				}
963			}
964		})(),
965		Cookie: (function()
966		{
967			return {
968				data: null,
969				privateData: null,
970				reset: function()
971				{
972					if (AEC.reset)
973					{
974						dataLayer.push({ ecommerce: null });
975					}
976					
977					return dataLayer;
978				},
979				push: function(dataLayer, consent)
980				{
981					consent = typeof consent !== 'undefined' ? consent : true;
982					
983					if (this.data)
984					{
985						if (consent)
986						{
987							if (AEC.Const.COOKIE_DIRECTIVE)
988							{
989								if (AEC.Const.COOKIE_DIRECTIVE_CONSENT_GRANTED)
990								{
991									this.reset().push(this.data);
992								}
993							}
994							else 
995							{
996								this.reset().push(this.data);
997							}
998						}
999						else 
1000						{
1001							this.reset().push(this.data);
1002						}
1003						
1004						/**
1005						 * Reset data to prevent further push
1006						 */
1007						this.data = null;
1008					}
1009					
1010					return this;
1011				},
1012				pushPrivate: function()
1013				{
1014					var data = this.getPrivateData();
1015					
1016					if (data)
1017					{
1018						dataLayer.push(
1019						{
1020							privateData: data
1021						});
1022					}
1023					
1024					return this;
1025				},
1026				augment: function(products)
1027				{
1028					/**
1029					 * Parse data & apply local reference
1030					 */
1031					var reference = AEC.Storage.reference().get();
1032					
1033					if (reference)
1034					{
1035						for (var i = 0, l = products.length; i < l; i++)
1036						{
1037							for (var a = 0, b = reference.length; a < b; a++)
1038							{
1039								if (products[i].id.toString().toLowerCase() === reference[a].id.toString().toLowerCase())
1040								{
1041									products[i].category = reference[a].category;
1042								}
1043							}
1044						}
1045					}
1046					
1047					return products;
1048				},
1049				click: function(data)
1050				{
1051					AEC.EventDispatcher.trigger('ec.cookie.click.data', data);
1052					
1053					this.data = data;
1054					
1055					return this;
1056				},
1057				add: function(data)
1058				{
1059					AEC.EventDispatcher.trigger('ec.cookie.add.data', data);
1060					
1061					this.data = data;
1062					
1063					return this;
1064				},
1065				remove: function(data)
1066				{
1067					AEC.EventDispatcher.trigger('ec.cookie.remove.item.data', data);
1068					
1069					this.data = data;
1070					
1071					if (AEC.localStorage)
1072					{
1073						this.data.ecommerce.remove.products = this.augment(this.data.ecommerce.remove.products);
1074					}
1075
1076					return this;
1077				},
1078				update: function(data)
1079				{
1080					AEC.EventDispatcher.trigger('ec.cookie.update.item.data', data);
1081					
1082					this.data = data;
1083					
1084					return this;
1085				},
1086				visitor: function(data)
1087				{
1088					AEC.EventDispatcher.trigger('ec.cookie.visitor.data', data);
1089					
1090					this.data = (function(data, privateData)
1091					{
1092						if (privateData)
1093						{
1094							if (privateData.hasOwnProperty('visitor'))
1095							{
1096								data.visitorId 		   = privateData.visitor.visitorId;
1097								data.visitorLoginState = privateData.visitor.visitorLoginState;
1098							}
1099						}
1100						
1101						return data;
1102						
1103					})(data, AEC.Cookie.getPrivateData());
1104					
1105					return this;
1106				},
1107				detail: function(data)
1108				{
1109					AEC.EventDispatcher.trigger('ec.cookie.detail.data', data);
1110					
1111					this.data = data;
1112					
1113					return this;
1114				},
1115				purchase: function(data)
1116				{
1117					AEC.EventDispatcher.trigger('ec.cookie.purchase.data', data);
1118					
1119					this.data = data;
1120					
1121					if (AEC.localStorage)
1122					{
1123						this.data.ecommerce.purchase.products = this.augment(this.data.ecommerce.purchase.products);
1124					}
1125					
1126					return this;
1127				},
1128				impressions: function(data)
1129				{
1130					AEC.EventDispatcher.trigger('ec.cookie.impression.data', data);
1131					
1132					this.data = data;
1133					
1134					return this;
1135				},
1136				checkout: function(data)
1137				{
1138					AEC.EventDispatcher.trigger('ec.cookie.checkout.step.data', data);
1139					
1140					this.data = data;
1141					
1142					if (AEC.localStorage)
1143					{
1144						this.data.ecommerce.checkout.products = this.augment(this.data.ecommerce.checkout.products);
1145					}
1146					
1147					return this;
1148				},
1149				checkoutOption: function(data)
1150				{
1151					AEC.EventDispatcher.trigger('ec.cookie.checkout.step.option.data', data);
1152					
1153					this.data = data;
1154					
1155					return this;
1156				},
1157				promotion: function(data)
1158				{
1159					AEC.EventDispatcher.trigger('ec.cookie.promotion.data', data);
1160					
1161					this.data = data;
1162					
1163					return this;
1164				},
1165				promotionClick: function(data, element)
1166				{
1167					AEC.EventDispatcher.trigger('ec.cookie.promotion.click', data, 
1168				   {
1169						element: element
1170				   });
1171					
1172					this.data = data;
1173					
1174					return this;
1175				},
1176				remarketing: function(data)
1177				{
1178					AEC.EventDispatcher.trigger('ec.cookie.remarketing.data', data);
1179					
1180					this.data = data;
1181					
1182					return this;
1183				},
1184				getPrivateData: function()
1185				{
1186					if (!this.privateData)
1187					{
1188						var cookie = this.get('privateData');
1189						
1190						if (cookie)
1191						{
1192							this.privateData = this.parse(cookie);
1193						}
1194					}
1195					
1196					return this.privateData;
1197				},
1198				set: function(name, value, days)
1199				{
1200					if (!days)
1201					{
1202						days = 30;
1203					} 
1204				
1205					let date = new Date();
1206		            
1207		            date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
1208		            
1209			        document.cookie = name + "=" + value + "; expires=" + date.toGMTString() + "; path=/";
1210			        
1211			        return this;
1212				},
1213				get: function(name)
1214				{
1215					var start = document.cookie.indexOf(name + "="), len = start + name.length + 1;
1216					
1217					if ((!start) && (name != document.cookie.substring(0, name.length))) 
1218					{
1219					    return null;
1220					}
1221					
1222					if (start == -1) 
1223					{
1224						return null;
1225					}
1226										
1227					var end = document.cookie.indexOf(String.fromCharCode(59), len);
1228										
1229					if (end == -1) 
1230					{
1231						end = document.cookie.length;
1232					}
1233					
1234					return decodeURIComponent(document.cookie.substring(len, end));
1235				},
1236				unset: function(name) 
1237				{   
1238	                document.cookie = name + "=" + "; path=/; expires=" + (new Date(0)).toUTCString();
1239	                
1240	                return this;
1241	            },
1242				parse: function(json)
1243				{
1244					var json = decodeURIComponent(json.replace(/\+/g, ' '));
1245					
1246	                return JSON.parse(json);
1247				}
1248			}
1249		})(),
1250		CookieConsent: (function()
1251		{
1252			return {
1253				chain: {},
1254				queue: function(callback, event)
1255				{	
1256					event = typeof event !== 'undefined' ? event : AEC.Const.COOKIE_DIRECTIVE_CONSENT_GRANTED_EVENT;
1257					
1258					if (!this.chain.hasOwnProperty(event))
1259					{
1260						this.chain[event] = [];
1261					}
1262					
1263					this.chain[event].push(callback);
1264					
1265					return this;
1266				},
1267				dispatch: function(consent)
1268				{
1269					/**
1270					 * Essential cookies
1271					 */
1272					AEC.Const.COOKIE_DIRECTIVE_CONSENT_GRANTED = true;
1273					
1274					/**
1275					 * Push consent to dataLayer
1276					 */
1277					dataLayer.push(consent);
1278					
1279					return this.process(consent.event);
1280				},
1281				process: function(event)
1282				{
1283					event = typeof event !== 'undefined' ? event : AEC.Const.COOKIE_DIRECTIVE_CONSENT_GRANTED_EVENT;
1284					
1285					if (this.chain.hasOwnProperty(event) && this.getConsent(event))
1286					{
1287						for (a = 0, b = this.chain[event].length; a < b; a++)
1288						{
1289							this.chain[event][a].apply(this,[]);
1290						}
1291						
1292						this.chain[event] = [];
1293					}
1294				
1295					return this;
1296				},
1297				getConsent: function(event)
1298				{
1299					return 1 == AEC.Cookie.get(event);
1300				},
1301				acceptConsent: function(event)
1302				{
1303					return this.dispatch({ event:event });
1304				},
1305				declineConsent: function(event)
1306				{
1307					return this.dispatch({ event:event });
1308				},
1309				getConsentDialog: function(dataLayer, endpoints)
1310				{
1311					if (1 == AEC.Cookie.get(AEC.Const.COOKIE_DIRECTIVE_CONSENT_DECLINE_EVENT))
1312					{
1313						return true;
1314					}
1315					
1316					if (1 != AEC.Cookie.get(AEC.Const.COOKIE_DIRECTIVE_CONSENT_GRANTED_EVENT))
1317					{
1318						AEC.Request.get(endpoints.cookieContent, {}, (response) => 
1319						{
1320							var directive = (body => 
1321							{
1322								body.insertAdjacentHTML('beforeend', response.cookieContent);
1323								
1324								return body.lastElementChild;
1325								
1326							})(document.body);
1327							
1328							directive.querySelectorAll('a.ec-gtm-cookie-directive-note-toggle').forEach(element => 
1329							{
1330								element.addEventListener('click', event => 
1331								{
1332									event.target.nextElementSibling.style.display = 'block' === event.target.nextElementSibling.style.display ? 'none' : 'block';
1333								});
1334							});
1335							
1336							directive.querySelectorAll('a.accept').forEach(element => 
1337							{
1338								element.addEventListener('click', event => 
1339								{
1340									event.target.text = event.target.dataset.confirm;
1341	
1342									var grant = [...directive.querySelectorAll('[name="cookie[]"]:checked')].map(element => { return element.value });
1343
1344									AEC.Request.post(endpoints.cookie, { cookie: grant }, response => 
1345									{
1346										Object.keys(response).forEach(event => 
1347										{
1348											AEC.CookieConsent.acceptConsent(event);
1349										});
1350
1351										directive.remove();
1352									});
1353								});
1354							});
1355							
1356							directive.querySelectorAll('a.accept-all').forEach(element => 
1357							{
1358								element.addEventListener('click', event => 
1359								{
1360									event.target.text = event.target.dataset.confirm;
1361	
1362									[...directive.querySelectorAll('[name="cookie[]"]')].forEac
1362h(element => 
1363									{
1364										element.checked = true;
1365									});
1366									
1367									element.parentNode.removeChild(element.previousElementSibling);
1368
1369									var grant = [...directive.querySelectorAll('[name="cookie[]"]:checked')].map(element => { return element.value });
1370
1371									AEC.Request.post(endpoints.cookie, { cookie: grant }, response => 
1372									{
1373										Object.keys(response).forEach(event => 
1374										{
1375											AEC.CookieConsent.acceptConsent(event);
1376										});
1377
1378										directive.remove();
1379									});
1380								});
1381							});
1382							
1383							directive.querySelectorAll('a.decline').forEach(element => 
1384							{
1385								element.addEventListener('click', event => 
1386								{
1387									AEC.Request.post(endpoints.cookie, { decline: true }, response => 
1388									{
1389										Object.keys(response).forEach(event => 
1390										{
1391											AEC.CookieConsent.declineConsent(event);
1392										});
1393
1394										directive.remove();
1395									});
1396								});
1397							});
1398						});
1399					}
1400					else 
1401					{
1402						if (AEC.Const.COOKIE_DIRECTIVE_SEGMENT_MODE)
1403						{
1404							(segments => 
1405							{
1406								for (i = 0, l = segments.length; i < l;i++)
1407								{
1408									if (1 == AEC.Cookie.get(segments[i]))
1409									{
1410										AEC.CookieConsent.acceptConsent(segments[i]);	
1411									}
1412								}
1413								
1414							})(AEC.Const.COOKIE_DIRECTIVE_SEGMENT_MODE_EVENTS);
1415						}
1416						else 
1417						{
1418							AEC.CookieConsent.acceptConsent(AEC.Const.COOKIE_DIRECTIVE_CONSENT_GRANTED_EVENT);
1419						}
1420					}
1421				}
1422			}
1423		})(),
1424		Storage: (function(api)
1425		{
1426			return {
1427				set: function(property, value)
1428				{
1429					if ('undefined' !== typeof(Storage))
1430					{
1431						localStorage.setItem(property, JSON.stringify(value));
1432					}
1433					
1434					return this;
1435					
1436				},
1437				get: function(property)
1438				{
1439					if ('undefined' !== typeof(Storage))
1440					{
1441						return JSON.parse(localStorage.getItem(property));
1442					}
1443					
1444					return null;
1445				},
1446				reference: function()
1447				{
1448					return (function(storage)
1449					{
1450						return {
1451							set: function(reference)
1452							{
1453								var current = storage.get('category.add') || [];
1454								
1455								var exists = (function(current, reference)
1456								{
1457									for (i = 0, l = current.length; i < l; i++)
1458									{
1459										if (current[i].id.toString().toLowerCase() === reference.id.toString().toLowerCase())
1460										{
1461											/**
1462											 * Update category
1463											 */
1464											current[i].category = reference.category;
1465											
1466											return true;
1467										}
1468									}
1469									
1470									return false;
1471									
1472								})(current, reference);
1473								
1474								if (!exists)
1475								{
1476									current.push(reference);
1477								}
1478								
1479								storage.set('category.add', current);
1480								
1481								return this;
1482							},
1483							get: function()
1484							{
1485								return storage.get('category.add');
1486							}
1487						}
1488					})(this);
1489				}
1490			}
1491		})(),
1492		gtm: function()
1493		{
1494			if ("undefined" === typeof google_tag_manager)
1495			{
1496				/**
1497				 * Log error to console
1498				 */
1499				console.log('Unable to detect Google Tag Manager. Please verify if GTM install snippet is available.');
1500				
1501				return false;
1502			}
1503
1504			return true;
1505		},
1506		parseJSON: function(content)
1507		{
1508			if ('object' === typeof content)
1509			{
1510				return content;
1511			}
1512			
1513			if ('string' === typeof content)
1514			{
1515				try 
1516				{
1517					return JSON.parse(content);
1518				}
1519				catch (e){}
1520			}
1521			
1522			return {};
1523		}, 
1524		getPayloadSize: function(object)
1525		{
1526			var objects = [object];
1527		    var size = 0;
1528		
1529		    for (var index = 0; index < objects.length; index++) 
1530		    {
1531		        switch (typeof objects[index]) 
1532		        {
1533		            case 'boolean':
1534		                size += 4;
1535		                break;
1536		            case 'number':
1537		                size += 8;
1538		                break;
1539		            case 'string':
1540		                size += 2 * objects[index].length;
1541		                break;
1542		            case 'object':
1543		                if (Object.prototype.toString.call(objects[index]) != '[object Array]') 
1544		                {
1545		                    for (var key in objects[index]) size += 2 * key.length;
1546		                }
1547		                for (var key in objects[index]) 
1548		                {
1549		                    var processed = false;
1550		                    
1551		                    for (var search = 0; search < objects.length; search++) 
1552		                    {
1553		                        if (objects[search] === objects[index][key]) {
1554		                            processed = true;
1555		                            break;
1556		                        }
1557		                    }
1558		                    if (!processed) objects.push(objects[index][key]);
1559		                }
1560		        }
1561		    }
1562		    return size;
1563		},
1564		getPayloadChunks: function(arr, len)
1565		{
1566			var chunks = [],i = 0, n = arr.length;
1567			
1568			while (i < n) 
1569			{
1570			    chunks.push(arr.slice(i, i += len));
1571			}
1572	
1573			return chunks;
1574		},
1575		url: function(url)
1576		{
1577			return [this.Const.URL, url].join('');
1578		},
1579		EventDispatcher: (function()
1580		{
1581			return {
1582				events: {},
1583			    on: function(event, callback) 
1584			    {
1585			        var handlers = this.events[event] || [];
1586			        
1587			        handlers.push(callback);
1588			        
1589			        this.events[event] = handlers;
1590			    },
1591			    trigger: function() 
1592			    {
1593			    	/**
1594			    	 * Cast arguments to array
1595			    	 */
1596			    	let args = [...arguments];
1597			    	
1598			    	/**
1599			    	 * Get event
1600			    	 */
1601			    	let event = args ? args.shift() : null;
1602			    	
1603			    	/**
1604			    	 * Get handlers
1605			    	 */
1606			    	let handlers = this.events[event] || [];
1607			    	
1608			    	/**
1609			    	 * Get data
1610			    	 */
1611			    	let data = args ? args.shift() : {};
1612			    	
1613			    	/**
1614			    	 * Get options
1615			    	 */
1616			    	let options = args ? args.shift() : {};
1617
1618			    	/**
1619			    	 * Quit if no handler
1620			    	 */
1621			        if (!handlers || handlers.length < 1)
1622			        {
1623			            return;
1624			        }
1625			        
1626			        console.log(event + '(' + handlers.length + ' listeners)');
1627			        
1628			        handlers.forEach(function(handler)
1629			        {
1630			        	handler(data, options);
1631			        });
1632			    }
1633			}
1634		})(),
1635		Request: (function()
1636		{
1637			return {
1638				get: function(url, params, callback)
1639				{
1640					this.execute('GET', [url,this.serialize(params)].join('?'), callback).send(null);
1641				},
1642				post: function(url, params, callback) 
1643				{
1644					this.execute('POST', url, callback).send(this.serialize(params));
1645				},
1646				execute: function(method, url, callback)
1647				{
1648					try 
1649					{
1650						var request = new XMLHttpRequest();
1651	
1652						request.open(method, url, true);
1653	
1654						request.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
1655						request.setRequestHeader('X-Requested-With','XMLHttpRequest');
1656	
1657						request.addEventListener('load', () => 
1658						{
1659							let response;
1660							
1661							if ('application/json' === request.getResponseHeader("Content-Type"))
1662							{
1663								response = JSON.parse(request.responseText);
1664							}
1665							else
1666							{
1667								response = request.responseText;
1668							}
1669							
1670							if ('function' === typeof callback)
1671							{
1672								callback(response);
1673							}
1674						});
1675					}
1676					catch (e)
1677					{
1678						console.log(e.message);
1679						
1680						return null;
1681					}
1682					
1683
1684					return request;
1685				},
1686				serialize: function(entity, prefix) 
1687				{
1688	                var query = [];
1689
1690	                Object.keys(entity).map(key =>  
1691	                {
1692	                	var k = prefix ? prefix + "[" + key + "]" : key, value = entity[key];
1693
1694	                	query.push((value !== null && typeof value === "object") ? this.serialize(value, k) : encodeURIComponent(k) + "=" + encodeURIComponent(value));
1695	              	});
1696
1697	                return query.join("&");
1698	            }
1699			}
1700		})(),
1701		UUID: (() => 
1702		{
1703			return {
1704				generate: event => 
1705				{
1706					event = event || {};
1707					
1708					if (-1 == ['AddToCart'].indexOf(event))
1709					{
1710						try 
1711						{
1712							let current = AEC.Cookie.get('facebook_latest_uuid');
1713							
1714							if (current)
1715							{
1716								current = JSON.parse(current);
1717								
1718								if (current.hasOwnProperty('uuid') && current.hasOwnProperty('event'))
1719								{
1720									if (event.event === current.event)
1721									{
1722										return current.uuid;
1723									}
1724								}
1725							}
1726						}
1727						catch (e){}
1728					}
1729					
1730					let uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) 
1731					{
1732					    var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
1733					    return v.toString(16);
1734					});
1735					
1736					event['uuid'] = uuid;
1737					
1738					/**
1739					 * Set facebook uuid cookie
1740					 */
1741					if (AEC.Const.COOKIE_DIRECTIVE)
1742					{
1743						if (AEC.Const.COOKIE_DIRECTIVE_CONSENT_GRANTED)
1744						{
1745							AEC.Cookie.set('facebook_latest_uuid', JSON.stringify(event));
1746						}
1747					}
1748					else 
1749					{
1750						AEC.Cookie.set('facebook_latest_uuid', JSON.stringify(event));
1751					}
1752					
1753					return uuid;
1754				}
1755			}
1756		})()
1757	}
1758})();

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.