PageSourceSearch

https://www.livnightclub.com/wp-content/themes/uvtheme/js/global-egt.js?ver=10125

js livnightclub.com collected 2026-09-24 22:42:39 UTC 80,714 bytes, 2,416 lines download raw bytes

1let uv_poploader;
2var uvEventsFromProxy;
3
4// [UWS-6651]
5var uvTicketingLowest;
6var uvTicketingLowestValue;
7var uvTicketingValue; //---
8var uvTcktSelectionVal;
9var uvTcktUpgradeValue;
10var uvTcktSavingsValue;
11var uvTcktTotalValue;
12var uvTcktMinimumValue;
13var uvVisibleTicketing;
14
15var uvShowUpcoming = true;
16
17uvDOMReady(function () {
18	var uvIsEvent = document.querySelector("body:has(.uws-event)");
19	var uvIsEvents = document.querySelector("body:has(.uws-events)");
20	var uvIsHomeSection = document.querySelector("body:has(.homepage-section)");
21    var uvSpecialEventMap = document.querySelector(".uws-map .uwseventinfo");
22    var uvSpecialEventForm = document.querySelector(".uv-special-event-form .uv-form");
23	
24	// uvGLoaderAux();
25
26	if(uvIsHomeSection || uvIsEvent || uvIsEvents)
27		getCustomEventsProxy();
28
29	if(uvIsEvent) {
30		uvItemObserverFix();
31		miamiAddress();
32		uvItemDescObserver();
33	}
34
35	uvToggleMobmenu();
36
37	if(uvSpecialEventMap)
38		uvMapSpecialEventObserver();
39
40	// uvFixMetaTags();
41	
42	if(uvIsEvent) {
43		uvTicketsObserver();
44		// uvUniverseIFrameObserver();
45	}
46	
47	if(uvSpecialEventForm)
48		uvSpecialEventFormObserver();
49
50	uvSetBannerBackground();
51
52	//@egt [UWS-7154]
53	uvUpdateVenueDirection();
54
55	//@egt [UWS-6654]
56	uvPastEventObserver();
57});
58
59//adds the country code select to the phone input on special event forms [SE Form styles] @egt
60function uvWrapCountryCode() {
61	var uvCode = document.querySelector(".uv-phone-country-code");
62	var uvCnt = document.querySelector(".phone-container .nf-field-element");
63
64	if(uvCode && uvCnt) {
65		uvCnt.insertAdjacentElement("afterbegin", uvCode);
66		uvCnt.classList.add("uv-phone-cnt");
67			
68		var uvInput = uvCnt.querySelector("input");
69
70		if(uvInput) {
71			uvInput.setAttribute("type", "tel");
72			uvInput.setAttribute("maxlength", "15");
73
74			uvInput.addEventListener("input", function(){
75				this.value = this.value.replace(/[^\d]/g, "");
76			});
77		}
78	}
79}
80
81// needed for the loader animation [SE Form styles] @egt
82function uvSpecialEventFormObserver() {
83	const uvTarget = '.uv-special-event-form .uv-form';
84    const uvQueryElement = document.querySelector(uvTarget);
85    const uvObConfig = { attributes: true, childList: true, subtree: true };
86
87    if (!uvQueryElement) {
88        //console.log(uvTarget + " not found. Waiting for it to appear...");
89        
90        return;
91    }
92
93	var uvTries = 0;
94	const uvMaxTries = 5;
95
96    const uvObserver = new MutationObserver((mutations) => {
97        let executed = false;
98
99        mutations.forEach((mutation) => {
100            // const { target } = mutation;
101            if (executed) return; // Skip further execution
102                // if (mutation.target.classList.contains(".uwsjs-invitem-inquireform"))
103					executed = true; // Prevent further execution for this batch
104					
105					uvObserver.disconnect();
106
107					uvWrapCountryCode();
108
109					if(uvTries >= uvMaxTries) {
110						if(uvObserver) uvObserver.disconnect();
111						uvLogDebug("uvSpecialEventFormObserver shutdown");
112					}
113        });
114    });
115
116    uvObserver.observe(uvQueryElement, uvObConfig);
117}
118
119//Create Poploader [added by @egt]
120function uvGLoaderAux() {
121    uv_poploader = document.createElement("div");
122    uv_poploader.id = "uws-gloader";
123    uv_poploader.classList.add("uws-gloader-cont");
124
125    let uvloaderinn = document.createElement("div");
126    uvloaderinn.classList.add("uws-loader-uvicon");
127    uv_poploader.appendChild(uvloaderinn);
128
129    let uvloadermsg = document.createElement("div");
130    uvloadermsg.classList.add("uwsloadermsg");
131    uv_poploader.appendChild(uvloadermsg);
132
133    document.body.appendChild(uv_poploader);
134}
135
136// added @egt
137function uvShortHash(uvString = "", uvTarget) {
138  let hash = 0;
139
140  for (let i = 0; i < uvTarget.length; i++) {
141	hash = (hash << 5) - hash + uvTarget.charCodeAt(i);
142	hash |= 0; // convert to 32-bit integer
143  }
144
145  return uvString + Math.abs(hash).toString(36);
146}
147
148//creates a custom event from the values on a json @egt
149function uvCreateCustomEventsInitial(custom_events) {
150	// var url, flyer, targetNextTo, eventTitle, calLocation, location, urlParameters, forVenue, venueEventsClass;
151	var customEvent, getSwiper;
152	
153	if(custom_events){
154		getSwiper = getCurrentSwiper();
155
156		if(getSwiper != null)
157			removeSwiperDuplicates(getSwiper.swiper, getSwiper.loopDuplicates);
158
159		custom_events.forEach(event => {
160			customEvent = {
161				eventTitle: event.eventTitle,
162				calLocation: event.calLocation,
163				url: event.url,
164				flyer: event.flyer,
165				// placeAfter: event.placeAfter,
166				// placeBefore: event.placeBefore,
167				eventDate: event.eventDate,
168				isEnabled: event.isEnabled,
169				forVenue: event.venue,
170				venueEventsClass: event.eventsClass,
171				targetNextTo: event.targetNextTo,
172				location: event.elementLocation,
173				urlParameters: event.opensOnNewTab,
174			};
175
176			createCustomAtCarousel(customEvent);
177		});
178
179		if(getSwiper != null)
180			reinitializeSwiper(getSwiper.swiper, getSwiper.options);
181	}
182}
183
184//same as uvCreateCustomEventsInitial but called more than once if it is necessary @egt
185function uvCreateCustomEventsDynamic(custom_events) {
186	// var url, flyer, targetNextTo, eventTitle, calLocation, location, urlParameters, forVenue, venueEventsClass;
187	var customEvent;
188	
189	if(custom_events){
190		custom_events.forEach(event => {
191			customEvent = {
192				eventTitle: event.eventTitle,
193				calLocation: event.calLocation,
194				url: event.url,
195				flyer: event.flyer,
196				// placeAfter: event.placeAfter,
197				// placeBefore: event.placeBefore,
198				eventDate: event.eventDate,
199				isEnabled: event.isEnabled,
200				forVenue: event.venue,
201				venueEventsClass: event.eventsClass,
202				targetNextTo: event.targetNextTo,
203				location: event.elementLocation,
204				urlParameters: event.opensOnNewTab,
205			};
206
207			createCustomAtAgenda(customEvent);
208            createCustomAtList(customEvent);
209			// createCustomAtEventsCalendar(customEvent);
210		});
211	}
212}
213
214//create the custom event in events @egt isEnabled, placeAfter, placeBefore
215function createCustomAtAgenda(event) {
216	var isEvents = document.querySelectorAll(".uws-events");
217    var isVenue = document.querySelector('body[data-venue="'+event.forVenue+'"]');
218    var events = document.querySelectorAll(".uws-events-view-agenda .uv-carousel-lat.uws-venuekey-liv"+event.venueEventsClass+".uws-event-agenda-box a.hd-link");
219    var target, mFlyerMobile, mFlyerDesktop, lvFlyerMobile, lvFlyerDesktop, eventName; 
220	var uvFlyer;
221
222	var elementLocation;
223	var eventDate = event.eventDate;
224	var validDate = new Date(eventDate);
225	var currentDate = new Date();
226	//necessary for comparing the dates
227	validDate.setHours(0, 0, 0, 0);
228    currentDate.setHours(0, 0, 0, 0);
229	
230	var dayName, dayNumber, month, auxDate;
231
232	var itemPosition;
233	
234	var isValidEvent = event.isEnabled;
235			
236	var uvAuxDay = uvGetDay();
237	
238	var uvUniqueClass, uvUniqueCard;
239
240    if(isVenue && isEvents && events && isValidEvent && validDate >= currentDate) {
241		uvUniqueClass = event.eventDate + event.eventTitle;
242		uvUniqueClass = uvShortHash('uv-custom-agenda-event-', uvUniqueClass);
243
244		uvUniqueCard = document.querySelector("." + uvUniqueClass);
245
246		if(uvUniqueCard) return;
247
248        for (let item of events) {
249			itemPosition = compareEventDate(item.getAttribute("href"), validDate);
250
251			if(itemPosition){
252				target = item.closest(".uv-carousel-lat.uws-venuekey-liv"+event.venueEventsClass+".uws-event-agenda-box"); 
253				elementLocation = uvOrderSpecialEvent(item.getAttribute("href"), validDate);
254				break;
255			}
256		}
257
258		if(target){
259			dupe = document.createElement("div");
260
261			dupe.innerHTML = target.innerHTML;
262
263			target.insertAdjacentElement(elementLocation, dupe);
264
265			dupe.classList.add("uws-event-list-item");
266			dupe.classList.add("uv-carousel-lat");
267			dupe.classList.add("uws-venuekey-liv"+event.venueEventsClass);
268			dupe.classList.add("uws-event-agenda-box");
269			dupe.classList.add("uv-custom-event");
270			dupe.classList.add(uvUniqueClass);
271
272			eventName = event.eventTitle;
273			dupe.querySelector(".uv-event-name-title").innerHTML = eventName;
274
275			uvFlyer = '.uws-agenda-default .uwsflyercont img';
276			
277			dupe.querySelector(uvFlyer).setAttribute("src", event.flyer);
278			dupe.querySelector(uvFlyer).setAttribute("alt", eventName);
279			dupe.querySelector(uvFlyer).style.objectFit = "contain";
280
281			//UWS-4769 @egt commented for optimization
282			// mFlyerMobile = '.uws-agenda-default .uwsflyercont.uv-miami-flyer-format[data-flyer-type="mobile"] img';
283			// dupe.querySelector(mFlyerMobile).setAttribute("src", event.flyer);
284			// dupe.querySelector(mFlyerMobile).setAttribute("alt", eventName);
285			// dupe.querySelector(mFlyerMobile).style.objectFit = "contain";
286			
287			// mFlyerDesktop = '.uws-agenda-default .uwsflyercont.uv-miami-flyer-format[data-flyer-type="desktop"] img';
288			// dupe.querySelector(mFlyerDesktop).setAttribute("src", event.flyer);
289			// dupe.querySelector(mFlyerDesktop).setAttribute("alt", eventName);
290			// dupe.querySelector(mFlyerDesktop).style.objectFit = "contain";
291
292			// lvFlyerMobile = '.uws-agenda-default .uwsflyercont.uv-vegas-flyer-format[data-flyer-type="mobile"] img';
293			// dupe.querySelector(lvFlyerMobile).setAttribute("src", event.flyer);
294			// dupe.querySelector(lvFlyerMobile).setAttribute("alt", eventName);
295			// dupe.querySelector(lvFlyerMobile).style.objectFit = "contain";
296			
297			// lvFlyerDesktop = '.uws-agenda-default .uwsflyercont.uv-vegas-flyer-format[data-flyer-type="desktop"] img';
298			// dupe.querySelector(lvFlyerDesktop).setAttribute("src", event.flyer);
299			// dupe.querySelector(lvFlyerDesktop).setAttribute("alt", eventName);
300			// dupe.querySelector(lvFlyerDesktop).style.objectFit = "contain";
301
302			dupe.querySelector('a.hd-link').setAttribute("href", event.url);
303
304			dupe.querySelector('.uwsflyercont').style.background = "black";
305
306			dupe.querySelector("a:first-of-type").setAttribute("href", event.url);
307			dupe.querySelector('a:first-of-type').setAttribute("aria-label", eventName);
308
309			auxDate = new Date(eventDate);
310
311			dayNumber = auxDate.getDate();
312			dayName = auxDate.toLocaleString('en-US', { weekday: 'short' });
313			month = auxDate.toLocaleString('en-US', { month: 'short' });
314			
315			dupe.querySelector('.uv-ev-date .uv-ev-weekday').innerHTML = dayName;
316			dupe.querySelector('.uv-ev-date .uv-ev-month').innerHTML = month;
317			dupe.querySelector('.uv-ev-date .uv-ev-day').innerHTML = dayNumber;
318
319			if(event.urlParameters && event.urlParameters == 1) {
320				dupe.querySelector('a.hd-link').setAttribute("target", "_blank");
321				dupe.querySelector("a:first-of-type").setAttribute("target", "_blank");
322			}
323
324			// if((uvAuxDay && dayName == uvAuxDay) || uvAuxDay == null)
325			// 	uvDoCustomEventAnimation(dupe, 1);
326			
327			uvFilterCustomEventOnStart(uvAuxDay, dayName, dupe);
328		}
329	}
330}
331
332//create the custom event in events calendar @egt isEnabled, placeAfter, placeBefore
333function createCustomAtEventsCalendar(event) {
334	var isEvents = document.querySelectorAll(".uws-events");
335    var isVenue = document.querySelector('body[data-venue="'+event.forVenue+'"]');
336	var calItems = document.querySelectorAll(".uws-events-view-calendar .uws-cal-box a");
337	var target, clone, calCell, eventName;
338    
339    var eventLocation, eventFlyers;
340    var locationClass = ".uws-cal-date-";
341    
342	var eventDate = event.eventDate;
343	var validDate = new Date(eventDate);
344	var currentDate = new Date();
345
346	//necessary for comparing the dates
347	validDate.setHours(0, 0, 0, 0);
348    currentDate.setHours(0, 0, 0, 0);
349
350	var priorityPosition = eventDate; 
351	priorityPosition = priorityPosition.replace(/\//g, "");
352
353	var itemPosition;
354
355	var isValidEvent = event.isEnabled;
356
357	var uvUniqueClass, uvUniqueCard;
358
359	if(isVenue && isEvents && calItems && isValidEvent && validDate >= currentDate) {
360		uvUniqueClass = event.eventDate + event.eventTitle;
361		uvUniqueClass = uvShortHash('uv-custom-calendar-event-', uvUniqueClass);
362
363		uvUniqueCard = document.querySelector("." + uvUniqueClass);
364
365		if(uvUniqueCard) return;
366
367        for (let item of calItems) {
368			itemPosition = compareEventDate(item.getAttribute("href"), validDate);
369
370			if(itemPosition){
371				target = item;
372				// console.log("found");
373				// console.log(target);
374				
375				break;
376			}
377		}
378
379        // get the location on the calendar
380        locationClass = locationClass + priorityPosition;
381        eventLocation = document.querySelector(locationClass);
382
383		if(target){
384			eventName = event.eventTitle;
385
386			clone = document.createElement("a");
387			clone.innerHTML = target.innerHTML;
388
389			uvDoCustomEventAnimation(clone, 1);
390
391			clone.setAttribute("aria-label", eventName);
392			clone.setAttribute("href", event.url);
393			if(clone.querySelector('.uws-cal-single-default .uwsinfo .uwsname'))
394				clone.querySelector('.uws-cal-single-default .uwsinfo .uwsname').innerHTML = eventName;
395			if(clone.querySelector('.uws-cal-single-default .uwsinfo .uwsvenuename'))
396				clone.querySelector('.uws-cal-single-default .uwsinfo .uwsvenuename').innerHTML = event.calLocation;
397            
398            eventFlyers = clone.querySelectorAll(".uwsflyercont .uwsimgloading");
399            eventFlyers.forEach(flyer => {
400                flyer.setAttribute("src", event.flyer);
401            });
402
403            if(eventLocation){
404                calCell = eventLocation.querySelector(".uws-cal-box");
405
406                if(calCell){
407                    if(calCell.innerHTML.trim() != "") { //if there are event already it must have the next class to "crop" the cards and show them stacked 
408                        clone.classList.add("uv-cal-custom-event-item");
409                        clone.classList.add(uvUniqueClass);
410
411                        calCell.classList.add("uv-cal-custom-event-box");
412                    } else
413                        eventLocation.classList.add("uws-cal-cell-single");
414
415                    calCell.insertAdjacentElement("beforeend", clone);
416                }
417            }
418
419			if(event.urlParameters && event.urlParameters == 1) {
420				clone.setAttribute("target", "_blank");
421			}
422
423			uvDoCustomEventAnimation(clone, 0);
424		}
425	}
426}
427
428//create the custom event on the carousel @egt isEnabled, placeAfter, placeBefore
429function createCustomAtCarousel(event) {
430	var isVenue = document.querySelector('body[data-venue="'+event.forVenue+'"]');
431	var carouselItems = document.querySelectorAll(".uv-eventscarousel .eventitem .uv-boxitem"); 
432	var target, clone;
433	var isEventCarousel = document.querySelector("body:is(.uv-event-details)");
434
435	var auxLocation = document.location.href;
436	var excludeLocation1 = "/miami/special-events/nye2024/";
437	var excludeLocation2 = "/miami/special-events/new-years-week-2025";
438
439	var elementLocation;
440	var eventDate = event.eventDate;
441	var validDate = new Date(eventDate);
442	var currentDate = new Date();
443	//necessary for comparing the dates
444	validDate.setHours(0, 0, 0, 0);
445    currentDate.setHours(0, 0, 0, 0);
446	
447	var dayName, dayNumber, month, auxDate;
448	
449	var itemPosition;
450	var auxTarget;
451
452	var swiperComponent = document.querySelector("body .uv-eventscarousel .swiper-container.uv-scroll-horizontal");
453
454	var isValidEvent = event.isEnabled;
455
456	if(swiperComponent)
457		if(isVenue && carouselItems && !auxLocation.includes(excludeLocation1) && !auxLocation.includes(excludeLocation2) && isValidEvent && validDate >= currentDate) {
458			//makes sure it finds an item as reference for insertion (date order)
459			for (let item of carouselItems) {
460				itemPosition = compareEventDate(item.getAttribute("href"), validDate);
461				
462				auxTarget = item.closest(".swiper-slide.uv-carousel-lat");
463
464				if(itemPosition && !auxTarget.classList.contains("swiper-slide-duplicate")){
465					target = item.closest(".swiper-slide.uv-carousel-lat");
466					elementLocation = "beforebegin";
467					
468					break;
469				}
470			}
471
472			//once found it creates a clone of that item and changes the attributes
473			if(target){
474				clone = document.createElement("div");
475				clone.innerHTML = target.innerHTML;
476
477				// uvDoCustomEventAnimation(clone, 1);
478
479				clone.classList.add("swiper-slide");
480				clone.classList.add("uv-carousel-lat");
481				
482				if(isEventCarousel)
483					clone.setAttribute("style", target.getAttribute("style"));
484				else
485					clone.setAttribute("style", target.getAttribute("style"));
486				
487				clone.setAttribute("role", "group");
488				clone.querySelector(".uv-event-name-title").innerHTML = event.eventTitle;
489				clone.querySelector(".uv-boxitem").setAttribute("href", event.url);
490				clone.querySelector(".hd-link").setAttribute("href", event.url);
491				clone.querySelector(".uv-boxitem .bg").setAttribute("style", "");
492				clone.querySelector(".uv-boxitem .bg").style.backgroundImage = `url(${event.flyer})`;
493				clone.querySelector(".uv-boxitem .bg").style.backgroundRepeat = "no-repeat";
494				clone.querySelector(".uv-boxitem .bg").style.backgroundSize = "cover";
495
496				auxDate = new Date(eventDate);
497
498				dayNumber = auxDate.getDate();
499				dayName = auxDate.toLocaleString('en-US', { weekday: 'short' });
500				month = auxDate.toLocaleString('en-US', { month: 'short' });
501				
502				clone.querySelector('.uv-ev-date .uv-ev-weekday').innerHTML = dayName;
503				clone.querySelector('.uv-ev-date .uv-ev-month').innerHTML = month;
504				clone.querySelector('.uv-ev-date .uv-ev-day').innerHTML = dayNumber;
505
506				target = target.closest(".swiper-slide.uv-carousel-lat");
507
508				if(target){
509					target.insertAdjacentElement(elementLocation, clone);
510				}
511
512				if(event.urlParameters && event.urlParameters == 1) {
513					clone.querySelector(".uv-boxitem").setAttribute("target", "_blank");
514					clone.querySelector(".hd-link").setAttribute("target", "_blank");
515				}
516				
517				clone.querySelector(".eventitem").setAttribute("data-performer", "");
518
519				// uvDoCustomEventAnimation(clone, 0);
520			}
521		}
522}
523
524//create the custom event in events @egt isEnabled, placeAfter, placeBefore
525function createCustomAtList(event) {
526	var isEvents = document.querySelectorAll(".uws-events");
527    var isVenue = document.querySelector('body[data-venue="'+event.forVenue+'"]');
528    var events = document.querySelectorAll(".uws-list-default div a");
529    var target, mFlyerMobile, mFlyerDesktop, lvFlyerMobile, lvFlyerDesktop, eventName; 
530
531	var elementLocation, venueName;
532	var eventDate = event.eventDate;
533	var validDate = new Date(eventDate);
534	var currentDate = new Date();
535	//necessary for comparing the dates
536	validDate.setHours(0, 0, 0, 0);
537    currentDate.setHours(0, 0, 0, 0);
538
539	var dayName, dayNumber, month, auxDate;
540	
541	var itemPosition;
542			
543	var uvAuxDay = uvGetDay();
544
545	var uvUniqueClass, uvUniqueCard;
546
547    if(isVenue && isEvents && events && event.isEnabled && validDate >= currentDate){
548		uvUniqueClass = event.eventDate + event.eventTitle;
549		uvUniqueClass = uvShortHash('uv-custom-list-event-', uvUniqueClass);
550
551		uvUniqueCard = document.querySelector("." + uvUniqueClass);
552
553		if(uvUniqueCard) return;
554
555        for (let item of events) {
556			itemPosition = compareEventDate(item.getAttribute("href"), validDate);
557
558			if(itemPosition){
559                target = item.parentNode;
560				elementLocation = uvOrderSpecialEvent(item.getAttribute("href"), validDate);
561				break;
562			}
563		}
564
565		if(target){
566			dupe = document.createElement("div");
567
568			dupe.innerHTML = target.innerHTML;
569
570			target.insertAdjacentElement(elementLocation, dupe);
571            
572			dupe.classList.add("uws-event-list-item");
573			dupe.classList.add("uv-custom-event");
574			dupe.classList.add(uvUniqueClass);
575
576			eventName = event.eventTitle;
577			dupe.querySelector(".uws-list-item-default .uwsinfo .uwsname").innerHTML = eventName;
578
579			dupe.querySelector('a').setAttribute("href", event.url);
580			dupe.querySelector('a').setAttribute("aria-label", eventName);
581
582			dupe.querySelector('.uwsimgloading').setAttribute("src", event.flyer);
583			dupe.querySelector('.uwsimgloading').setAttribute("alt", eventName);
584
585			auxDate = new Date(eventDate);
586
587			dayNumber = auxDate.getDate();
588			dayName = auxDate.toLocaleString('en-US', { weekday: 'short' });
589			month = auxDate.toLocaleString('en-US', { month: 'short' });
590			
591			dupe.querySelector('.uws-list-item-default .uwsdedate .uwsdsday').innerHTML = dayName;
592			dupe.querySelector('.uws-list-item-default .uwsdedate .uwsdday').innerHTML = dayNumber;
593			dupe.querySelector('.uws-list-item-default .uwsdedate .uwsdsmonth').innerHTML = month;
594			dupe.querySelector('.uws-list-item-default .uwsinfo .uwsddate').innerHTML = dayName + ", " + month + " " + dayNumber;
595            
596            venueName = dupe.querySelectorAll('.uws-list-item-default .uwsvenuename');
597            
598            if(venueName)
599                venueName.forEach(name => {
600                    name.innerHTML = event.calLocation;
601                });
602
603			if(event.urlParameters && event.urlParameters == 1) {
604				dupe.querySelector('a').setAttribute("target", "_blank");
605			}
606
607			// if((uvAuxDay && dayName == uvAuxDay) || uvAuxDay == null)
608			// 	uvDoCustomEventAnimation(dupe, 1);
609			
610			uvFilterCustomEventOnStart(uvAuxDay, dayName, dupe);
611		}
612	}
613}
614
615//gets data on the url so each filter is unique and has their own data @egt
616function getDynamicUrl() {
617    var isLV = document.querySelector('body[data-venue="las-vegas"]');
618	var response;
619
620	if(isLV)
621		response = "lv";
622	else
623		response = "miami";
624
625	return response;
626}
627
628//gets custom events acf data @egt
629function getCustomEventsProxy() {
630	// if (document.querySelector('')) {
631        const action = "_getcustomevents";
632        const version = Math.floor(Math.random() * 101);
633		const uvgetlocurl = uws_proxy + action + "&type=" + getDynamicUrl() + "&v=" + version;
634
635		let uvrequest = new XMLHttpRequest();
636		uvrequest.open('GET', uvgetlocurl, true);
637		uvrequest.onload = function () {
638			if (this.status >= 200 && this.status < 400) {
639				let uvresponse = this.response;
640				uvresponse = JSON.parse(uvresponse);
641
642				if (uvresponse["status"] === 200 && uvresponse["data"]) {
643					uvEventsFromProxy = uvresponse["data"]["events"];
644                    
645                    if(uvEventsFromProxy) {
646						uvCreateCustomEventsInitial(uvEventsFromProxy);
647						uvCreateCustomEventsDynamic(uvEventsFromProxy);
648					}
649				}
650			}
651		};
652
653		uvrequest.onerror = function () {
654			console.log("UVJS Error: Request Error");
655		};
656
657		uvrequest.send();
658	// }
659}
660
661//lets us call the function when loadmore is clicked @egt
662//added interval in order to wait for the loading to stop and then finally add the custom event 
663uwsClickListener(".uws-events-actions.uwsactive .uwsjs-events-loadmore", function (e) {
664    // e.preventDefault();
665	var uvTarget = document.querySelector(".uws-events-actions");
666
667	const uvInterval = setInterval(() => {
668        if (!uvTarget.classList.contains("uwsloading")) {
669            clearInterval(uvInterval);
670            uvCreateCustomEventsDynamic(uvEventsFromProxy);
671        }
672    }, 200);
673});
674
675//compares the custom event date with the rest of the event dates in order to get the position @egt
676function compareEventDate(target, date) {
677	const match = target.match(/EVE\d+/);
678	var compareStatus = 0;
679
680	if(match) {
681		var eventID = match[0];
682		var dateStr = eventID.slice(-8);
683
684		var year = dateStr.slice(0, 4);
685		var month = dateStr.slice(4, 6);
686			month = month -1;
687		var day = dateStr.slice(6, 8);
688		
689		var formattedDate = new Date(year, month, day);
690
691		if(date <= formattedDate)
692			compareStatus = 1;
693	}
694
695	return compareStatus;
696}
697
698//get the js position @egt
699function uvOrderSpecialEvent(uvExistingTarget, uvCustomDate) {
700	const uvMatch = uvExistingTarget.match(/EVE\d+/);
701	var uvCompareStatus = "beforebegin";
702
703	if(uvMatch) {
704		var uvEventID = uvMatch[0];
705		var uvDateStr = uvEventID.slice(-8);
706
707		var uvYear = uvDateStr.slice(0, 4);
708		var uvMonth = uvDateStr.slice(4, 6);
709			uvMonth = uvMonth -1;
710		var uvDay = uvDateStr.slice(6, 8);
711		
712		var uvFormattedDate = new Date(uvYear, uvMonth, uvDay);
713		uvFormattedDate.setHours(0, 0, 0, 0);
714
715		if(uvCustomDate.getTime() < uvFormattedDate.getTime())
716			uvCompareStatus = "beforebegin";
717		
718		if(uvCustomDate.getTime() == uvFormattedDate.getTime())
719			uvCompareStatus = "afterend";
720	}
721
722	return uvCompareStatus;
723}
724
725/* 
726	the swiper has the loop option so it adds some duplicates in order to make the loop, 
727	these are removed for adding items in order and then they are added again on the reinitialize
728	@egt
729*/
730function removeSwiperDuplicates(swiperComponent, swiperLoopDuplicates) {
731	if(swiperComponent){
732		//remove duplicates (loop swiper) before insertion of new elements
733		if(swiperLoopDuplicates){
734			swiperLoopDuplicates.forEach(slide => {
735				slide.remove()
736			});
737
738			swiperComponent.update();
739		}
740	}
741}
742
743// once the new items are added to the swiper we need to reinitialize it in order to get the loop property back and indexes corrected @egt
744function reinitializeSwiper(swiperComponent, swiperOptions) {
745	//once inserted we need to update the swiper, destroy it and reinitialize it
746	if(swiperComponent){
747		//updates the swiper once elements where added then rebuilds the component
748		swiperComponent.update();
749		swiperComponent.destroy(true, true);
750		swiperComponent = new Swiper('.swiper-container', swiperOptions);
751	}
752}
753
754//gets the swiper, the swiper parameters/options and the duplicates (from spiwer loop) @egt
755function getCurrentSwiper() {
756	var swiperComponent = document.querySelector("body .uv-eventscarousel .swiper-container.uv-scroll-horizontal");
757	var swiperLoopDuplicates = document.querySelectorAll('body .uv-eventscarousel .swiper-container.uv-scroll-horizontal .swiper-slide-duplicate');
758	var swiperOptions;
759	var swiperData;
760	var response = null;
761
762	if(swiperComponent && swiperLoopDuplicates) {
763		swiperComponent = swiperComponent.swiper;
764		swiperOptions = { ...swiperComponent.params };
765
766		swiperData = {
767			swiper: swiperComponent,
768			options: swiperOptions,
769			loopDuplicates: swiperLoopDuplicates
770		};
771
772		response = swiperData;
773	}
774
775	return response;
776}
777
778//open table sections with restaurant items are missing book type name among other things 
779//this should fix the name to be able to recognize this item sections @egt
780function fixOTSection(observer) {
781	var booktype = document.querySelectorAll(".uwsbooktypename");
782
783	if(booktype)
784		booktype.forEach(type => { 
785			if(type.innerHTML == "Restaurants") 
786				type.closest(".uws-booktype").setAttribute("data-booktypename", "Restaurants");
787		});
788
789	// console.log("booktypename restored");
790
791	// if(observer)
792	// 	observer.disconnect();
793}
794
795//function that works along fixOTSection() @egt
796function uvItemObserverFix() {
797    const observeTarget = ".uv-event-details .uws-event-maincol";
798    const element = document.querySelector(observeTarget);
799    const config = { attributes: true, childList: true, subtree: true };
800
801    if (!element) {
802        // console.log(observeTarget + " not found. Waiting for it to appear...");
803        return;
804    }
805
806	var uvTries = 0;
807	const uvMaxTries = 5;
808
809    const observer = new MutationObserver((mutations) => {
810        let executed = false;
811
812        mutations.forEach((mutation) => {
813            // const { target } = mutation;
814            if (executed) return; // Skip further execution
815                // if (mutation.target.classList.contains(uvTarget))
816                    if (mutation.attributeName === "class") {
817                        executed = true; // Prevent further execution for this batch
818                        
819						uvRenameRestaurantOptions();
820						fixOTSection(observer);
821
822						uvTries = uvTries + 1;
823
824						if(uvTries >= uvMaxTries) {
825							if(observer) observer.disconnect();
826							uvLogDebug("uvItemObserverFix shutdown");
827						}
828                    }
829        });
830    });
831
832    observer.observe(element, config);
833}
834
835//replaces the old format of the address with the new one for MIAMI @egt
836function miamiAddress() {
837	var addressTarget = document.querySelector('body[data-venue="miami"] .uws-event-info .uwsinfobox .uwsvenueinfo .uwsaddresscont');
838	var venueNameTarget = document.querySelector('body[data-venue="miami"] .uws-event-info .uwsinfobox .uwsvenueinfo .uws-venuename');
839	// var hasRestaurant = document.querySelector('.uws-booktype.uws-booktype-item[data-booktypename="Restaurants"]');
840	var newAddress = "4441 Collins Avenue, Miami Beach, FL 33140";
841	var newName = "LIV Nightclub Fontainebleau Miami Beach";
842
843	if(addressTarget)
844		addressTarget.innerHTML = newAddress;
845
846	if(venueNameTarget){
847		venueNameTarget.innerHTML = newName;
848		// console.log("found");
849	}
850}
851
852//changes the names to the correct ones on sevenrooms section @egt
853function uvRenameRestaurantOptions() {
854    var uvNames = document.querySelectorAll(".seven-rooms-section .uwsname");
855    
856	if(uvNames)
857		uvNames.forEach(name => {
858			if(name.innerHTML.includes("Komodo LV")) {
859				name.innerHTML = name.innerHTML.replace("Komodo LV", "Komodo Las Vegas");
860			}
861			if(name.innerHTML.includes("Steaklv")) {
862				name.innerHTML = name.innerHTML.replace("Steaklv", "Steak Las Vegas");
863			}
864		});
865}
866
867//adds the missing descriptions in the open table section @egt
868function uvAddDescriptions(observer) {
869	var uvItems = document.querySelectorAll(".ot-section .uwsname"); 
870	var uvAux, uvDescCnt, uvDesc, uvTarget;
871
872	// console.log("started");
873
874	if(uvItems) {
875		// console.log(uvItems);
876
877		uvItems.forEach(item => { 
878			// console.log("hey");
879			
880			uvTarget = item.innerHTML;
881			
882			uvInsertDescription(uvTarget, uvDescCnt, uvDesc, uvAux, item, "Hakkasan", "Enjoy award-winning modern Cantonese prepared with premium ingredients and an innovative perspective.");
883			uvInsertDescription(uvTarget, uvDescCnt, uvDesc, uvAux, item, "Mirabella", "Mirabella redefines Mediterranean dining at Fontainebleau Miami Beach. Guests are immersed in the freshest flavors from land and sea, showcasing the vibrant heritage of coastal Italian cuisine.");
884			uvInsertDescription(uvTarget, uvDescCnt, uvDesc, uvAux, item, "Prime 54", "Enjoy creative twists on upscale classics from aged quality cuts to fresh seafood to handmade pastas.");
885			uvInsertDescription(uvTarget, uvDescCnt, uvDesc, uvAux, item, "Papi Steak", `Papi Steak Miami is an intimate, high-energy steakhouse located in the heart of Miami Beach's South of Fifth neighborhood. The restaurant fuses Golden Era Hollywood glamour with modern-day Miami flair, offering elevated twists on classic chophouse dishes. Signature offerings include the namesake 32-ounce Tomahawk "Papi Steak" with its secret sauce, and the theatrical "Beef Case" presentation-a 55-ounce Australian Wagyu tomahawk served in a rhinestone-encrusted briefcase. With its bold design, curated cocktails, and vibrant atmosphere, Papi Steak delivers a one-of-a-kind dining experience.`);
886			uvInsertDescription(uvTarget, uvDescCnt, uvDesc, uvAux, item, "Casadonna", `Casadonna is a coastal Italian restaurant in the heart of Miami, offering a vibrant dining experience inspired by the flavors and romance of the Mediterranean. Nestled by the water, it's the perfect escape for handcrafted martinis, refined small plates, and elevated Italian classics. The ambiance blends timeless elegance with lively energy, making it ideal for everything from happy hour to late-night celebrations. Whether you're soaking in the sunset or savoring fresh pasta, Casadonna invites you to indulge in la dolce vita.`);
887			uvInsertDescription(uvTarget, uvDescCnt, uvDesc, uvAux, item, "Komodo", `Komodo Miami is an indoor/outdoor restaurant located in the heart of Brickell, serving bold Southeast Asian cuisine with a South Florida twist. With 300 seats, including signature floating "birds' nests," the space offers a unique and immersive dining atmosphere. The menu features standout dishes like Peking Duck, Lobster Dynamite, and a full sushi bar, paired with inventive cocktails. Whether for dinner or a special occasion, Komodo delivers a dynamic and memorable culinary experience.`);
888			uvInsertDescription(uvTarget, uvDescCnt, uvDesc, uvAux, item, "Gekko", `Gekko is a stylish Japanese steakhouse and lounge located in the heart of Miami's Brickell neighborhood. Co-owned by David Grutman and Bad Bunny, it offers a luxurious dining experience that blends elevated cuisine with a vibrant atmosphere. Signature dishes include premium steaks, inventive sushi, and bold cocktails. With its sultry interiors and lively energy, Gekko is where Miami's dining scene meets nightlife glamour.`);
889			uvInsertDescription(uvTarget, uvDescCnt, uvDesc, uvAux, item, "Arkadia Grill", "Kick back amidst table games and pumping music with an approachable menu of pizza, burgers, salads and small plates.");
890			uvInsertDescription(uvTarget, uvDescCnt, uvDesc, uvAux, item, "La Cote", "Indulge in the flavors of France’s mediterranean coast amidst refreshing poolside breezes.");
891		});
892
893		if(uvItems.length > 0 && observer) {
894			// console.log("disconnected");
895			observer.disconnect();
896		}
897	}
898
899}
900
901//creates the description for the item @egt
902function uvInsertDescription(uvTarget, uvDescCnt, uvDesc, uvAux, item, uvName, uvDescStr) {
903	if(uvTarget.includes(uvName)) {
904		uvAux = item.closest(".uwsinfo"); 
905
906		if(uvAux && !uvAux.querySelector(".uwsextrainfo")) {
907			uvDescCnt = document.createElement("div");
908			uvDescCnt.classList.add("uwsextrainfo");
909
910			uvDesc = document.createElement("div");
911			uvDesc.classList.add("uwshighlight");
912			uvDesc.style.maxWidth = "90%";
913
914			uvAux.insertAdjacentElement("beforeend", uvDescCnt);
915			uvDescCnt.insertAdjacentElement("beforeend", uvDesc);
916			
917			uvDesc.innerHTML = uvDescStr;
918		}
919	}
920}
921
922//@egt
923function uvItemDescObserver() {
924    const observeTarget = ".uv-event-details .uws-event-maincol";
925    const element = document.querySelector(observeTarget);
926    const config = { attributes: true, childList: true, subtree: true };
927
928    if (!element) {
929        // console.log(observeTarget + " not found. Waiting for it to appear...");
930        return;
931    }
932
933	var uvTries = 0;
934	const uvMaxTries = 5;
935
936    const observer = new MutationObserver((mutations) => {
937        let executed = false;
938
939        mutations.forEach((mutation) => {
940            // const { target } = mutation;
941            if (executed) return; // Skip further execution
942                // if (mutation.target.classList.contains(uvTarget))
943                    if (mutation.attributeName === "class") {
944                        executed = true; // Prevent further execution for this batch
945                        
946						uvOTParams();
947						uvAddDescriptions(observer);
948
949						if(uvTries >= uvMaxTries) {
950							if(observer) observer.disconnect();
951							uvLogDebug("uvItemDescObserver shutdown");
952						}
953                    }
954        });
955    });
956
957    observer.observe(element, config);
958}
959
960//@egt
961function uvToggleMobmenu() {
962	var uvMobMenu = document.querySelector(".uv-overmenu-menu .uv-events-mob");
963
964	if(uvMobMenu) uvMobMenu.classList.add("active");
965}
966
967//@egt
968uvClickListener(".uv-overmenu-menu .uv-events-mob > a", function (e) {
969	e.preventDefault();
970
971	//code to keep ref or discount on them
972	const uvRef = uvGetRef();
973	const uvDisc = uvGetDiscount();
974
975	const url = new URL(this.href);
976	const params = url.searchParams;
977	let modified = false;
978
979	if (uvRef && !params.has("ref")) {
980		params.set("ref", uvRef);
981		modified = true;
982	}
983
984	if (uvDisc && !params.has("unii-discount-code")) {
985		params.set("unii-discount-code", uvDisc);
986		modified = true;
987	}
988
989	if (modified) {
990		this.href = url.toString();
991	}
992
993	//fix for clicking the target when they have nested options
994	var uvParent = this.parentNode;
995	uvParent.classList.add("active");
996
997	if (uvParent.classList.contains("active") && e.target === this) {
998		window.location.href = this.href;
999	}
1000});
1001
1002//@egt
1003function uvReplaceMapInfoBtn(observer) {
1004	var uvHeader = document.querySelector("body:has(.uv-rufusdusol-se) .uv-main-image a");
1005	var uvMapInfoBtn = document.querySelectorAll("body:has(.uv-rufusdusol-se) .uwsdy-map-eventinfo .uwsactions a");
1006
1007	if(uvHeader && uvMapInfoBtn) {
1008		uvMapInfoBtn.forEach(e => {
1009			e.setAttribute("href", uvHeader.getAttribute("href"));
1010		});
1011	}
1012
1013	if(observer) {
1014		observer.disconnect();
1015	}
1016}
1017
1018//@egt
1019function uvMapSpecialEventObserver() {
1020    const observeTarget = ".uws-map .uwseventinfo";
1021    const element = document.querySelector(observeTarget);
1022    const config = { attributes: true, childList: true, subtree: true };
1023
1024    if (!element) {
1025        // console.log(observeTarget + " not found. Waiting for it to appear...");
1026        return;
1027    }
1028
1029	var uvTries = 0;
1030	const uvMaxTries = 5;
1031
1032    const observer = new MutationObserver((mutations) => {
1033        let executed = false;
1034
1035        mutations.forEach((mutation) => {
1036            // const { target } = mutation;
1037            if (executed) return; // Skip further execution
1038                // if (mutation.target.classList.contains(uvTarget))
1039                    if (mutation.attributeName === "class") {
1040                        // executed = true; // Prevent further execution for this batch
1041                        // uvRemoveScrollFromMap();
1042						
1043						uvReplaceMapInfoBtn(observer);
1044						
1045						if(uvTries >= uvMaxTries) {
1046							if(observer) observer.disconnect();
1047							uvLogDebug("uvMapSpecialEventObserver shutdown");
1048						}
1049                    }
1050        });
1051    });
1052
1053    observer.observe(element, config);
1054} 
1055
1056//@egt 
1057function uvRemoveScrollFromMap() {
1058	const map = document.querySelector('.uws-map-graph');
1059
1060	let isDragging = false;
1061	let startY;
1062
1063	map.addEventListener('touchstart', e => {
1064		if (e.touches.length === 1) {
1065			isDragging = true;
1066			startY = e.touches[0].clientY;
1067		}
1068	}, { passive: true });
1069
1070	map.addEventListener('touchmove', e => {
1071		const deltaY = e.touches[0].clientY - startY;
1072		if (isDragging && Math.abs(deltaY) > 10) {
1073			// Let the page scroll instead of dragging the map
1074			e.preventDefault(); // optionally block default drag behavior
1075		}
1076	}, { passive: false });
1077
1078	map.addEventListener('touchend', () => {
1079		isDragging = false;
1080	});
1081}
1082
1083//@egt 
1084function uvToggleVideoVolume() {
1085	const video = document.querySelector('.uv-venue-video-file');
1086
1087	if(video) {
1088		video.muted = !video.muted;
1089
1090		const muteIcon = document.querySelector('.uvicon-volume-strike');
1091		const unmuteIcon = document.querySelector('.uvicon-volume-up');
1092
1093		if (video.muted) {
1094			muteIcon.style.display = 'inline';
1095			unmuteIcon.style.display = 'none';
1096		} else {
1097			muteIcon.style.display = 'none';
1098			unmuteIcon.style.display = 'inline';
1099		}
1100	}
1101}
1102
1103//@egt
1104function uvDoCustomEventAnimation(target, action) {
1105	if(action == 1)
1106		target.classList.add('uv-ce-fade-in-start');
1107
1108	if(action == 0)
1109		requestAnimationFrame(() => {
1110			target.classList.add('uv-ce-fade-in-end');
1111		});
1112}
1113
1114//filter custom event on start if there is the day parameter @egt
1115function uvFilterCustomEventOnStart(uvAuxDay, dayName, target) {
1116	if(uvAuxDay && dayName != uvAuxDay) 
1117		target.classList.add("uv-day-filtered");
1118	// else
1119	// 	uvDoCustomEventAnimation(target, 0);
1120}
1121
1122// @egt
1123function uvFixMetaTags() {
1124	var uvImg = document.querySelector(".uwsjs-show-image");
1125	var uvIsEvent = document.querySelector("body:has(.uws-event)");
1126	var uvOGTag = document.querySelector('meta[property="og:image"]');
1127	var uvXTag = document.querySelector('meta[name="twitter:image"]');
1128
1129	if(uvIsEvent && uvImg){
1130		if(uvOGTag)
1131			uvOGTag.setAttribute("content", uvImg.getAttribute("href"));
1132		if(uvXTag)
1133			uvXTag.setAttribute("content", uvImg.getAttribute("href"));
1134	}
1135}
1136
1137//adds OT parameters to the iframes UWS-5914 @egt
1138//clone and replace added in order to create the new click listener 
1139// added if(!uvVenue) validation in order to prevent empty strings and broken listeners
1140function uvOTParams() {
1141    var uvTargets = document.querySelectorAll('.ot-section .uwsinv-item.uws-inventory-item');
1142	var uvRestaurants = document.querySelector('.uws-booktype.uws-booktype-item.uws-booktype-nodetype-Booktype[data-booktypename="Restaurants"] a.uwsjs-booktypetoggle');
1143	// var uvNewBtn;
1144	// var uvVenue;
1145	var uvBtn;
1146
1147	if(uvRestaurants && uvRestaurants.getAttribute("href") == "#opentable")
1148		if(uvTargets && uvTargets.length > 0) {
1149			// console.log("OT");
1150			
1151			uvTargets.forEach(function(uvSingleTarget) {
1152				uvBtn = uvSingleTarget.querySelector("a.uwsjs-inv-item-select.uws-btn.uws-btn-s");
1153				var uvNewBtn = uvBtn.cloneNode(true);
1154				uvBtn.replaceWith(uvNewBtn);
1155
1156				var uvVenue = uvNewBtn.getAttribute("data-venue");
1157
1158				if(!uvVenue)
1159					uvVenue = uvSingleTarget.querySelector(".uwsname").textContent;
1160
1161				if(uvVenue)
1162					uvNewBtn.addEventListener('click', function (e) {
1163						e.preventDefault();
1164						
1165						var uvParams = uvGetOTRid(uvVenue);
1166
1167						if(uvParams)
1168							uvOTPopParams(uvParams[0], uvVenue, uvParams[1]);
1169					});
1170			});
1171		}
1172}
1173
1174// Extract the restaurant ID from the parameters @egt
1175function uvGetOTRid(uvVenue) {
1176	switch (uvVenue) {
1177		case "Hakkasan":
1178			return [33808, "&ot_source=LIV%20&ot_campaign=LIV-Hakkasan"];
1179		case "Mirabella":
1180			return [1318453, "&ot_source=LIV%20&ot_campaign=LIV-Mirabella"];
1181		case "Prime 54":
1182			return [33820, "&ot_source=LIV%20&ot_campaign=LIV-Prime54"];
1183		case "Papi Steak":
1184			return [1051921, "&ot_source=LIV&ot_campaign=LIV-Papi%20Steak"];
1185		case "Casadonna":
1186			return [1206961, "&ot_source=LIV&ot_campaign=LIV-Casadonna"];
1187		case "Komodo":
1188			return [193948, "&ot_source=LIV&ot_campaign=LIV-Komodo"];
1189		case "Gekko":
1190			return [1267918, "&ot_source=LIV&ot_campaign=LIV-Gekko"];
1191		case "Arkadia Grill":
1192			return [114739, "&ot_source=Liv&ot_campaign=LIV-Arkadia%20Grill"];
1193		case "La Cote":
1194			return [33817, "&ot_source=LIV&ot_campaign=LIV-La%20Cote"];
1195		default:
1196			break;
1197	}
1198}
1199
1200//borrowed from uwsinventory.js - opens the OpenTable popup with the reservation details @egt
1201function uvOTPopParams(rid, displayName, otParams) {
1202    // Initialize the formatted reservation date
1203    let reservationDate = null;
1204
1205    // Extract the event code from the URL path or query parameters
1206    const url = new URL(window.location.href);
1207    let eventCode = null;
1208
1209    // Check for event code in the path (e.g., /event/EVE...)
1210    const pathMatch = url.pathname.match(/\/event\/(EVE\d{18})/);
1211    if (pathMatch) {
1212        eventCode = pathMatch[1];
1213    } else {
1214        // Check for event code in the query parameters (e.g., ?eventcode=EVE...)
1215        eventCode = url.searchParams.get('eventcode');
1216    }
1217
1218    // If event code is found, extract the date from it
1219    if (eventCode) {
1220        const rawDate = eventCode.slice(-8); // Last 8 digits contain the date
1221        reservationDate = `${rawDate.substring(0, 4)}-${rawDate.substring(4, 6)}-${rawDate.substring(6, 8)}`;
1222    } else {
1223        console.error('Event code not found in URL.');
1224        return; // Exit if no valid event code is found
1225    }
1226
1227    // Construct the OpenTable iframe URL with the extracted date
1228    const iframeUrl = `https://www.opentable.com/restref/client/?rid=${rid}&restref=${rid}&lang=en-US&color=1&r3uid=cfe&dark=false&partysize=2&datetime=${encodeURIComponent(reservationDate)}T00%3A00${otParams}`;
1229	// console.log(iframeUrl);
1230
1231    // Create overlay to block interactions outside the popup
1232    const overlay = document.createElement('div');
1233    overlay.classList.add('overlay');
1234
1235    // Create popup container
1236    const popup = document.createElement('div');
1237    popup.classList.add('popup', 'opentablepop');
1238
1239    // Create close button
1240    const closeButton = document.createElement('button');
1241    closeButton.innerHTML = 'X';
1242    closeButton.classList.add('popup-close-btn');
1243
1244    // Close popup and remove overlay when the close button is clicked
1245    closeButton.addEventListener('click', function () {
1246        document.body.removeChild(popup);
1247        document.body.removeChild(overlay);
1248    });
1249
1250    // Create the iframe with the constructed URL
1251    const iframe = document.createElement('iframe');
1252    iframe.setAttribute('title', `${displayName} Reservation`);
1253    iframe.setAttribute('alt', `${displayName} Reservation`);
1254    iframe.setAttribute('src', iframeUrl);
1255    iframe.setAttribute("allow", "accelerometer; gyroscope; magnetometer");
1256    iframe.classList.add('popup-iframe');
1257
1258    // Append close button and iframe to the popup
1259    popup.appendChild(closeButton);
1260    popup.appendChild(iframe);
1261
1262    // Append overlay and popup to the body
1263    document.body.appendChild(overlay);
1264    document.body.appendChild(popup);
1265}
1266
1267//gets the id of the universe link @egt
1268function uvGetUniverseId(observer) {
1269	var uvTarget = document.querySelector(".uws-event a.uws-btn.uws-extticketsbtn.uv-universe");
1270	var uvCleanUrl;
1271	
1272	if (uvTarget) {
1273		uvUniverseUrl = uvTarget.getAttribute("href");
1274
1275		uvCleanUrl = new URL(uvUniverseUrl);
1276		uvCleanUrl.searchParams.delete("ref");
1277		uvCleanUrl.searchParams.delete("unii-discount-code");
1278
1279		uvUniverseUrl = uvCleanUrl.toString().replace("https://www.universe.com/events/", "");
1280		
1281		// console.log("uvUniverseUrl: " + uvUniverseUrl);
1282		
1283		uvGetUniverseSwitch(uvUniverseUrl);
1284
1285		// console.log(uvUniverseUrl);
1286
1287		if(observer) {
1288			observer.disconnect();
1289		}
1290	}
1291}
1292
1293//once loaded the inventory gets the url for universe so we can call the api and stuff @egt
1294function uvTicketsObserver() {
1295	const uvTarget = '.uws-event-cont';
1296    const uvQueryElement = document.querySelector(uvTarget);
1297    const uvObConfig = { attributes: true, childList: true, subtree: true };
1298
1299    if (!uvQueryElement) {
1300        // console.log(uvTarget + " not found. Waiting for it to appear...");
1301        
1302        return;
1303    }
1304
1305	var uvTries = 0;
1306	const uvMaxTries = 5;
1307
1308    const uvObserver = new MutationObserver((mutations) => {
1309        let executed = false;
1310
1311        mutations.forEach((mutation) => {
1312            // const { target } = mutation;
1313            if (executed) return; // Skip further execution
1314                // if (mutation.target.classList.contains(".uwsjs-invitem-inquireform"))
1315                    if (mutation.attributeName === "class") {
1316                        executed = true; // Prevent further execution for this batch
1317						
1318						uvPastEventTickets();
1319						uvTicketsType(uvObserver);
1320
1321						uvTries = uvTries + 1;
1322
1323						if(uvTries >= uvMaxTries) {
1324							if(uvObserver) uvObserver.disconnect();
1325							uvLogDebug("uvTicketsObserver shutdown");
1326						}
1327                    }
1328        });
1329    });
1330
1331    uvObserver.observe(uvQueryElement, uvObConfig);
1332}
1333
1334//calls the api in order to get universe listing @egt
1335function uvGetUniverseListing(id) {
1336	const action = "_getuniverselisting";
1337	const version = Math.floor(Math.random() * 101);
1338	const uvgetlocurl = uws_proxy + action + "&listings_id=" + id + "&v=" + version;
1339	
1340	let uvrequest = new XMLHttpRequest();
1341	uvrequest.open('GET', uvgetlocurl, true);
1342	uvrequest.onload = function () {
1343		if (this.status >= 200 && this.status < 400) {
1344			let uvresponse = this.response;
1345			uvresponse = JSON.parse(uvresponse);
1346
1347			if (uvresponse["status"] === 200 && uvresponse["data"]) {
1348				const uvEventRates = uvresponse["data"]["rates"];
1349				const uvCapacities = uvresponse["data"]["capacities"];
1350				
1351				var uvEvents = uvresponse["data"]["events"];
1352				var uvListingState = uvresponse["data"]["listing"]["state"];
1353
1354				// var uvCnt = document.querySelector(".uv-universe-tickets .uws-bootypelist-body");
1355				var uvBooktypeName = document.querySelector(".uws-booktype-tickets.uv-universe-tickets span.uwsbooktypename");
1356				var uvTickets = document.querySelector(".uws-booktype-tickets.uv-universe-tickets");
1357
1358				var uvStartTime;
1359				var uvEndTime;
1360				var uvCurrentTime = new Date();
1361				var uvUnavailableOnline = 0;
1362
1363				// sets data for dates and state and adds the message
1364				if(uvTickets) {
1365					if(uvEvents != null && uvEvents) {
1366						if(uvresponse["data"]["events"][0]["start_time"]) {
1367							if(uvTestTicketsDate(0))
1368								uvStartTime = uvTestTicketsDate(0);
1369							else
1370								uvStartTime = uvresponse["data"]["events"][0]["start_time"];
1371							
1372							uvStartTime = new Date(uvStartTime);
1373							uvTickets.setAttribute("data-start", uvStartTime);
1374						}
1375						if(uvresponse["data"]["events"][0]["end_time"]) {
1376							if(uvTestTicketsDate(1))
1377								uvEndTime = uvTestTicketsDate(1);
1378							else
1379								uvEndTime = uvresponse["data"]["events"][0]["end_time"];
1380
1381							uvEndTime = new Date(uvEndTime);
1382							uvTickets.setAttribute("data-end", uvEndTime);
1383						}
1384
1385						if(uvStartTime && uvEndTime)
1386							if(uvCurrentTime >= uvStartTime && uvCurrentTime < uvEndTime) {
1387								uvTickets.classList.add("uv-disabled-online");
1388								uvUnavailableOnline = 1;
1389								uvAddTicketsMessage(uvBooktypeName, "Sale Over Tickets Available at Door");
1390							}
1391							
1392							if(uvCurrentTime >= uvEndTime) {
1393								uvTickets.classList.add("uv-disabled-online");
1394								uvUnavailableOnline = 1;
1395								uvAddTicketsMessage(uvBooktypeName, "Ticket Sales Have Ended");
1396							}
1397					}
1398
1399					uvTickets.setAttribute("data-state", uvListingState);
1400				}
1401
1402				//[UWS-6654]
1403				var uvTicketsQS = document.querySelector("body .uws-event .uws-booktype-tickets.uv-universe-tickets");
1404				
1405				if(uvTicketsQS && uvTicketsQS.getAttribute("data-state") == "expired")
1406					uvEventOverMsg(1);
1407
1408				if(uvEvents == null || !uvEvents) {
1409					if(uvTickets) {
1410						uvTickets.classList.add("uv-empty-events");
1411						uvTickets.classList.add("uv-disabled-online");
1412						uvUnavailableOnline = 1;
1413						uvAddTicketsMessage(uvBooktypeName, "Ticket Sales Have Ended");
1414
1415						return;
1416					}
1417				}
1418
1419				var eventsFilter = uvEvents[0].rate_ids;
1420
1421				var uvUrgencyIndicator = uvresponse["data"]["listing"]["urgency_indicator_enabled"];
1422				var uvUrgencyMessage = uvEvents[0]["urgency_message_checkout"];
1423
1424				var uvWaitlist = uvresponse["data"]["listing"]["allow_waitlist"];
1425				var uvAvailable = uvEvents[0]["count_available"];
1426
1427				if(uvWaitlist && uvAvailable == 0) {
1428					//add Waitlist message to the booktype name
1429					uvAddTicketsMessage(uvBooktypeName, "Waitlist");
1430
1431					if(uvTickets) {
1432						uvTickets.classList.add("uv-waitlist");
1433					}
1434				} else {
1435					if(uvUnavailableOnline != 1)
1436						if(uvEvents != null && uvEvents) {
1437							if(uvEventRates && uvCapacities){
1438								if(eventsFilter)
1439									uvGetTicketListing(uvEventRates, eventsFilter, uvCapacities);
1440								else { //added /juno on the api url so we get other data structure
1441									eventsFilter = uvresponse["data"]["rates"];
1442									
1443									uvGetTicketListing(uvEventRates, eventsFilter, uvCapacities);
1444								}
1445							}
1446							
1447							//adds urgency message as a separate div
1448							// if(uvCnt && uvUrgencyIndicator == true && uvUrgencyMessage != null) {
1449							// 	let uvMsgHtml = "<div class='uv-urgency-cnt uv-hide'><h4 class='uv-urgency-message'>"+uvUrgencyMessage+"</h4></div>";
1450							// 	uvCnt.insertAdjacentHTML("afterbegin", uvMsgHtml);
1451							// }
1452
1453							//add urgency message to the booktype name
1454							if(uvUrgencyIndicator && uvUnavailableOnline == 0)
1455								uvAddTicketsMessage(uvBooktypeName, uvUrgencyMessage);
1456						}
1457				}
1458			}
1459		} else {
1460			console.log(this.status);
1461			console.log(this.message);
1462		}
1463	};
1464
1465	uvrequest.onerror = function () {
1466		console.log("UVJS Error: Request Error");
1467	};
1468
1469	uvrequest.send();
1470}
1471
1472//calls the api in order to get universe integration switch value @egt
1473function uvGetUniverseSwitch() {
1474	const action = "_getuniverseswitch";
1475	const version = Math.floor(Math.random() * 101);
1476	const uvgetlocurl = uws_proxy + action + "&v=" + version;
1477	var uvIsEnabled;
1478
1479	let uvrequest = new XMLHttpRequest();
1480	uvrequest.open('GET', uvgetlocurl, true);
1481	uvrequest.onload = function () {
1482		if (this.status >= 200 && this.status < 400) {
1483			let uvresponse = this.response;
1484			uvresponse = JSON.parse(uvresponse);
1485
1486			if (uvresponse["status"] === 200 && uvresponse["active_integration"] == true) {
1487				uvIsEnabled = uvresponse["active_integration"];
1488
1489				uvGetTicketsBooktype();
1490
1491				setTimeout(() => {
1492					uvToggleUniverseVisibility(".uws-event .uws-booktype-tickets.uv-universe-tickets");
1493					uvGetUniverseListing(uvUniverseUrl);
1494				}, 50);
1495			} else if(uvresponse["status"] != 200 && uvresponse["active_integration"] != true) {
1496				uvIsEnabled = uvresponse["active_integration"];
1497
1498				uvToggleUniverseVisibility(".uws-event a.uws-btn.uws-extticketsbtn.uv-universe");
1499			}
1500		} else {
1501			console.log(this.status);
1502			console.log(this.message);
1503		}
1504	};
1505
1506	uvrequest.onerror = function () {
1507		console.log("UVJS Error: Request Error");
1508	};
1509
1510	uvrequest.send();
1511}
1512
1513// @egt
1514function uvPastEventTickets() {
1515	var uvEventDate = document.querySelector(".uv-title-info-date");
1516	var uvInventoryList = document.querySelector(".uws-inventory-list");
1517	var uvCurrent = new Date();
1518
1519	if(uvEventDate && uvInventoryList) {
1520		uvEventDate = uvEventDate.getAttribute("data-date");
1521		uvEventDate = new Date(uvEventDate);
1522
1523		if(uvCurrent > uvEventDate) {
1524			uvInventoryList.classList.add("uv-passed-event-tickets-display");
1525		}
1526	}
1527}
1528
1529// @egt
1530function uvEventOverMsg(uvHideTickets) {
1531	var uvEventDate = document.querySelector(".uv-title-info-date");
1532	var uvInventoryList = document.querySelector(".uws-inventory-list");
1533	var uvMap = document.querySelector(".uws-inventory-3dmaplink");
1534	var uvDesc = document.querySelector(".uws-event-cont .uwseventdescr");
1535	var uvTicketCnt = document.querySelector(".uv-tickets-cnt.uv-tickets-loading");
1536	var uvCurrent = new Date();
1537
1538	if(uvEventDate && uvInventoryList) {
1539		uvEventDate = uvEventDate.getAttribute("data-date");
1540		uvEventDate = new Date(uvEventDate + "T23:59:00"); // Set to end of the day for better accuracy
1541
1542		if(uvCurrent > uvEventDate) {
1543			uvInventoryList.classList.add("uv-passed-event");
1544			if(uvMap) uvMap.classList.add("uv-hide");
1545			if(uvDesc) uvDesc.classList.add("uv-hide");
1546		}
1547	}
1548
1549	if(uvTicketCnt && uvHideTickets) uvTicketCnt.classList.add("uv-hide");
1550}
1551
1552//@egt
1553function uvToggleUniverseVisibility(uvTarget) {
1554	var uvTicketsQuery = document.querySelector(uvTarget);
1555
1556	if(uvTicketsQuery)
1557		uvTicketsQuery.classList.add("uv-universe-visible");
1558}
1559
1560//adds messages to the tickets booktype @egt 
1561function uvAddTicketsMessage(uvBooktypeName, uvMessage) {
1562	var uvPercentage;
1563	var uvSpanMsg;
1564	var uvSpanMsgSeparator = "<div class='uv-tickets-message-separator'></div>";
1565
1566	if (uvBooktypeName && uvMessage != null) {
1567		if (!uvBooktypeName.querySelector('.uv-tickets-message')) {
1568			uvSpanMsg = document.createElement('span');
1569			uvSpanMsg.className = 'uv-tickets-message';
1570
1571			uvSpanMsg.textContent = uvMessage;
1572
1573			if(uvMessage.includes("%")) {
1574				uvPercentage = uvMessage.match(/\d+%/)[0];
1575
1576				uvSpanMsg.textContent = uvPercentage + " SOLD OUT";
1577			}
1578
1579			uvBooktypeName.appendChild(uvSpanMsg);
1580
1581			uvSpanMsg.insertAdjacentHTML("beforebegin", uvSpanMsgSeparator);
1582
1583			setTimeout(() => {
1584				requestAnimationFrame(() => {
1585					uvSpanMsg.classList.add('uv-tickets-label-fade-in');
1586
1587					uvSpanMsgSeparator = document.querySelector(".uv-tickets-message-separator");
1588					
1589					if(uvSpanMsgSeparator)
1590						uvSpanMsgSeparator.classList.add('uv-tickets-label-fade-in');
1591				});
1592			}, 100);
1593		}
1594	}
1595}
1596
1597//creates the container before inserting tickets html inside @egt
1598function uvGetTicketsBooktype() {
1599	var uvHTML = "";
1600	var uvTicketsWidget = document.querySelector(".uws-extticketsbtn");
1601
1602	uvHTML = `
1603		<div class="uws-booktype uws-booktype-item uws-booktype-tickets uws-booktype-nodetype- uv-universe-tickets" data-booktypecode="tickets" data-booktypename="Tickets">
1604			<a class="uwsjs-booktypetoggle" href="#uvinv-tickets">
1605				<span class="uwsbooktypenamenamecont">
1606					<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512">
1607						<path fill="#ffffff" d="M64 64C28.7 64 0 92.7 0 128l0 64c0 8.8 7.4 15.7 15.7 18.6C34.5 217.1 48 235 48 256s-13.5 38.9-32.3 45.4C7.4 304.3 0 311.2 0 320l0 64c0 35.3 28.7 64 64 64l448 0c35.3 0 64-28.7 64-64l0-64c0-8.8-7.4-15.7-15.7-18.6C541.5 294.9 528 277 528 256s13.5-38.9 32.3-45.4c8.3-2.9 15.7-9.8 15.7-18.6l0-64c0-35.3-28.7-64-64-64L64 64zm64 112l0 160c0 8.8 7.2 16 16 16l288 0c8.8 0 16-7.2 16-16l0-160c0-8.8-7.2-16-16-16l-288 0c-8.8 0-16 7.2-16 16zM96 160c0-17.7 14.3-32 32-32l320 0c17.7 0 32 14.3 32 32l0 192c0 17.7-14.3 32-32 32l-320 0c-17.7 0-32-14.3-32-32l0-192z"/>
1608					</svg>
1609					<span class="uwsbooktypename">Tickets</span>
1610				</span> 
1611				<div class="uv-toggle-display uv-is-loading">
1612					<i class="uwsicon-right-open"></i>
1613					<div class="uws-loader-uvicon"></div>
1614				</div>
1615			</a>
1616			<div class="uws-bootypelist-body" style="max-height: 0;">
1617				<div class="uws-bootypelist-inner">
1618					<div id="uws-ticket-listing" class="uws-invitems-list">
1619
1620					</div>
1621				</div>
1622			</div>
1623		</div>
1624	`;
1625
1626	if(uvTicketsWidget)
1627		uvTicketsWidget.insertAdjacentHTML("afterend", uvHTML);
1628}
1629
1630//gets ticket html and inserts it @egt
1631function uvGetTicketListing(uvEventRates, uvEventsFilter, uvCapacities) {
1632	var uvTicketsHTML = "";
1633	var uvTicketListing = document.querySelector("#uws-ticket-listing");
1634	var uvTicketsWidget = document.querySelector(".uws-extticketsbtn");
1635	var uvStatus = document.querySelector(".uv-universe-tickets .uv-toggle-display");
1636	var uvMainCnt = document.querySelector(".uv-tickets-cnt");
1637
1638	uvEventRates.forEach(event => {
1639		//if event.id in array uvEventsFilter do next
1640		// if (uvEventsFilter.includes(event.id))
1641			uvTicketsHTML += uvGetTicketItemHTML(event.id, event.name, event.description, event.display_price, event.raw_src_price, uvTicketsWidget.getAttribute("href"), event.capacity_ids, uvCapacities, event.promotion_pill);
1642	});
1643
1644	if(uvTicketListing && uvStatus) {
1645		uvTicketListing.insertAdjacentHTML("beforeend", uvTicketsHTML);
1646		uvChangeMobileUnBehavior(false);
1647		uvStatus.classList.remove("uv-is-loading");
1648		uvStatus.classList.add("uv-loaded");
1649		
1650		if(uvMainCnt) uvMainCnt.classList.remove("uv-tickets-loading");
1651	}
1652}
1653
1654//pop function
1655function uvClearPopup(uvpoptarget, uvpopcontent) {
1656    uvpopcontent = uvpopcontent != undefined ? uvpopcontent : "";
1657
1658    let uvpopchargetarget = uvpoptarget.querySelectorAll(".uv-pop-charge");
1659    uvpopchargetarget = uvpopchargetarget[0];
1660
1661    if (!uvpopchargetarget) uvpopchargetarget = uvpopchargetarget;
1662
1663    if (uvpopchargetarget) {
1664        uvpopchargetarget.innerHTML = "";
1665        uvpopchargetarget.insertAdjacentHTML("beforeend", uvpopcontent);
1666    }
1667}
1668
1669//pop function
1670function uvHidePopup(uvpoptarget, uvpopforceclose) {
1671    uvpopforceclose = (uvpopforceclose != undefined) ? uvpopforceclose : false;
1672
1673    let uvpopbox = uvpoptarget.querySelectorAll(".uv-pop-box");
1674    uvpopbox = uvpopbox[0];
1675
1676    if ((uvpopforceclose) || (!uvpopbox.matches(":hover") && !uvpoptarget.classList.contains("uv-noareaclose"))) {
1677        uvpoptarget.classList.remove("visible");
1678        setTimeout(function () {
1679            let uvpopnoclear = (uvpoptarget.classList.contains("uvnoclear")) ? 1 : 0;
1680
1681            uvpoptarget.className = "uv-pop-cont";
1682
1683            //Check if there are popups opened
1684            let uvopenedpopups = 0;
1685            let uvpopupselems = document.querySelectorAll(".uv-pop-cont");
1686
1687            Array.prototype.forEach.call(uvpopupselems, function (el, i) {
1688                if (el.classList.contains("visible"))
1689                uvopenedpopups++;
1690            });
1691
1692            if (uvopenedpopups == 0)
1693                document.getElementsByTagName("html")[0].classList.remove("uv-pop-open");
1694
1695            if (!uvpopnoclear)
1696                uvClearPopup(uvpoptarget);
1697            else {
1698                uvpoptarget.classList.add("uvnoclear");
1699                setTimeout(function () {
1700                uvpoptarget.classList.add("uvnoclear");
1701                }, 10);
1702            }
1703        }, 300);
1704    }
1705}
1706
1707//pop function
1708function uvFadePopup(uvpoptarget) {
1709    uvpoptarget.classList.add("visible");
1710    document.getElementsByTagName("html")[0].classList.add("uv-pop-open");
1711}
1712
1713//pop function
1714function uvShowGLoader(uvmsg) {
1715    if (typeof uvmsg == "undefined") var uvmsg = "";
1716
1717    let uvpoploadermsg = uv_poploader.getElementsByClassName("uwsloadermsg")[0];
1718
1719    uvpoploadermsg.innerHTML = uvmsg;
1720    uvFadePopup(uv_poploader);
1721}
1722
1723//@egt
1724// uvClickListener(".uv-universe-tickets .uv-universe-btn", function (e) {
1725//     if (typeof uvShowGLoader === "function") {
1726// 		uvShowGLoader();
1727
1728// 		setTimeout(() => {
1729// 			uvHidePopup(uv_poploader, true);
1730// 		}, 2000);
1731// 	}
1732// });
1733
1734//creates the ticket item html for the universe tickets @egt
1735function uvGetTicketItemHTML(uvId, uvName, uvDescription, uvDisplayPrice, uvRawSrcPrice, uvUrl, uvCapId, uvCapacities, uvPromPill) {
1736	var uvGuests = 0;
1737	
1738	var uvPromPillHTML;
1739	var uvVIPClass = "";
1740	var uvTarget = 'target="_blank"';
1741	var uvIsFree = "";
1742	
1743	uvUrl = `href="${uvUrl}"`;
1744
1745	if(uvPromPill != null)
1746		uvPromPillHTML = `<div class="uv-promotion-pill">${uvPromPill}</div>`;
1747	else
1748		uvPromPillHTML = `<div class="uv-promotion-pill uv-hide"></div>`;
1749
1750	// [UWS-6651]
1751	if(uvName == "VIP Expedited Admission"){
1752		// uvUrl = "";
1753		// uvVIPClass = "uv-vip-adm";
1754		// uvTarget = "";
1755		uvTicketingValue = uvRawSrcPrice;
1756	}
1757
1758	if(uvRawSrcPrice == 0 && uvDisplayPrice == 0) uvIsFree = "uv-free-ticket";
1759
1760	var uvTicketAvailability = `
1761		<div class="uwspaynow">
1762			<span>Admission</span>
1763			<span class="uwsprice {pricetypeclass}
1763" data-symbol="$">${uvRawSrcPrice}</span>
1764		</div>
1765		<div class="uwspriceitem">
1766			<a class="uwspricebreakdown uwspricing" aria-label="Pricing Breakdown ${uvName}" data-mascode="${uvId}">
1767				<i class="uwsicon-iteminfo uv-hide"></i>
1768				<span>Pay Now</span>
1769			</a>
1770			<div class="uwsprice " data-symbol="$">${uvDisplayPrice}</div>
1771		</div>
1772		<div class="uwsactions">
1773			<a class="uws-btn uws-btn-p uv-universe-btn ${uvVIPClass}" ${uvUrl} ${uvTarget} aria-label="Select ${uvName}" data-mascode="${uvId}" data-keepcont="" data-ticket="${uvName}">
1774				<span>Book</span>
1775			</a>
1776		</div>
1777	`;
1778	
1779	var uvCapacity;
1780	var uvAvailable;
1781
1782	// uvCapId = uvCapId[0];
1783	uvCapId = uvId;
1784	
1785	if(uvCapacities && uvCapacities.length > 0) {
1786		uvCapacity = uvCapacities.find(capacity => capacity.id === uvCapId);
1787		
1788		if(uvCapacity && uvCapacity.events[0])
1789			uvAvailable = uvCapacity.events[0].count_available;
1790		
1791		if(uvCapacity && uvAvailable === 0) {
1792			uvTicketAvailability = `
1793				<br><span class="uv-sold-out">Sold Out</span><br>
1794				<div class="uwsactions uv-hide">
1795					<a class="uws-btn uws-btn-p uv-universe-btn uv-hide" ${uvUrl} ${uvTarget} aria-label="Select ${uvName}" data-mascode="${uvId}" data-keepcont="" style="pointer-events: none;">
1796						<span class="uv-hide">Book</span>
1797					</a>
1798				</div>
1799			`;
1800		}
1801	}
1802
1803	var uvHTML = `
1804		<div class="uwsinv-item uws-inventory-item uws-inv-item-${uvId} uws-globaltye-seating uws-paytype-deposit" data-mastercode="${uvId}">
1805			<div class="uwsinfo uv-tickets-info">
1806				<div class="uwsbadge"></div>
1807				<div class="uwsname">
1808					${uvName}
1809					<div class="uv-promotion-pill-desktop">
1810						${uvPromPillHTML}
1811					</div>
1812				</div>
1813				<div class="uwsbubbles uv-hide">
1814					<div class="uwsbubble">
1815						<i class="uwsicon-itemguests"></i> 
1816						<span>${uvGuests}</span>
1817					</div>
1818				</div>
1819				<div class="uwsextrainfo">
1820					${uvDescription}
1821					<a href="javascript:;" class="uwsjs-inv-ecoitem-showinfo uv-hide" data-mascode="${uvId}" aria-label="View More Info">
1822						<span>More Info.</span>
1823					</a>
1824					<div class="uv-promotion-pill-mobile">
1825						${uvPromPillHTML}
1826					</div>
1827				</div>
1828			</div>
1829			<div class="uwspricecont ${uvIsFree}">
1830				${uvTicketAvailability}
1831				<div class="uwsdisclaimer uv-hide">
1832					<div class="uwsitemdisclaimer">
1833						<span class="uwsasteric">*</span>
1834						<span>Pricing based on ${uvGuests} guests</span>
1835					</div>
1836				</div>
1837			</div>
1838		</div>
1839	`;
1840
1841	return uvHTML;
1842}
1843
1844//makes universe urls open on a new tab for mobile @egt
1845function uvChangeMobileUnBehavior(uvActiveBehavior) {
1846	var uvTargets = document.querySelectorAll('a.uws-btn.uws-btn-p.uv-universe-btn');
1847
1848	if(uvTargets && window.matchMedia("(max-width: 768px)").matches && uvActiveBehavior)
1849		uvTargets.forEach(element => {
1850			element.addEventListener('click', function (e) {
1851				e.preventDefault();//stop default iframe behavior
1852
1853				const uvTargetSrc = element.getAttribute('href');
1854
1855				if(uvTargetSrc) {
1856					window.open(uvTargetSrc, '_blank'); // forces open in new tab
1857				}
1858			});
1859		});
1860}
1861
1862// needed for the loader animation @egt
1863function uvUniverseIFrameObserver() {
1864	const uvTarget = 'body';
1865    const uvQueryElement = document.querySelector(uvTarget);
1866    const uvObConfig = { attributes: true, childList: true, subtree: true };
1867
1868    if (!uvQueryElement) {
1869        // console.log(uvTarget + " not found. Waiting for it to appear...");
1870        
1871        return;
1872    }
1873
1874	var uvTries = 0;
1875	const uvMaxTries = 5;
1876
1877    const uvObserver = new MutationObserver((mutations) => {
1878        let executed = false;
1879
1880        mutations.forEach((mutation) => {
1881            // const { target } = mutation;
1882            if (executed) return; // Skip further execution
1883                // if (mutation.target.classList.contains(".uwsjs-invitem-inquireform"))
1884                    if (mutation.attributeName === "class") {
1885						var uvTarget = uvQueryElement.querySelector("iframe.tmjs-iframe");
1886
1887						if(uvTarget) {
1888                        	executed = true; // Prevent further execution for this batch
1889							
1890							uvObserver.disconnect();
1891							
1892							var uvId = uvTarget.getAttribute("id");
1893							
1894							if(uvId.startsWith("universe-"))
1895								setTimeout(() => {
1896									uvHidePop(uvObserver, uvQueryElement);
1897								}, 1500);
1898
1899							uvTries = uvTries + 1;
1900
1901							if(uvTries >= uvMaxTries) {
1902								if(uvObserver) uvObserver.disconnect();
1903								uvLogDebug("uvUniverseIFrameObserver shutdown");
1904							}
1905						}
1906                    }
1907        });
1908    });
1909
1910    uvObserver.observe(uvQueryElement, uvObConfig);
1911}
1912
1913//@egt
1914function uvHidePop(uvObserver, uvTarget) {
1915	uvHidePopup(uv_poploader, true);
1916
1917	if(uvObserver && uvTarget)
1918        uvObserver.observe(uvTarget, {
1919            attributes: true,
1920            childList: true,
1921            subtree: true
1922        });
1923}
1924
1925//gets the type of the tickets in order to add classes and make the changes for universe integration @egt
1926function uvTicketsType(uvObserver) {
1927	var uvTarget = document.querySelector(".uws-event a.uws-btn.uws-extticketsbtn");
1928	var uvEvent = document.querySelector(".uws-event");
1929	var uvCnt;
1930
1931	if(uvEvent) {
1932		if(uvTarget && uvTarget.getAttribute("href").includes("www.universe.com")) {
1933			uvTarget.classList.add("uv-universe");
1934
1935			uvCnt = document.createElement("div");
1936			uvCnt.classList.add("uv-tickets-cnt");
1937			uvCnt.classList.add("uv-tickets-loading");
1938
1939			uvTarget.insertAdjacentElement("beforebegin", uvCnt);
1940			uvCnt.appendChild(uvTarget);
1941
1942			uvGetUniverseId(uvObserver);
1943		}
1944
1945		if(uvTarget) {// && uvTarget.getAttribute("href").includes("www.tixr.com")
1946			if(uvTarget.getAttribute("href").includes("www.tixr.com")) uvTarget.classList.add("uv-tixr");
1947			if(uvTarget.getAttribute("href").includes("www.speakeasygo.com")) uvTarget.classList.add("uv-speakeasygo");
1948
1949			if(uvObserver) {
1950				uvObserver.disconnect();
1951			}
1952		}
1953	}
1954}
1955
1956//just for testing purposes uses uv-test-event-started and uv-test-end-date as parameters @egt
1957function uvTestTicketsDate(uvType) {
1958    var url = new URL(window.location.href);
1959	var uvStartDate = url.searchParams.get('uv-test-event-started');
1960	var uvEndDate = url.searchParams.get('uv-test-end-date');
1961	var uvDate = new Date();
1962
1963	if(uvType == 0 && uvStartDate)
1964		return uvDate;
1965	if(uvType == 1 && uvEndDate)
1966		return uvDate.setDate(uvDate.getDate() - 1);
1967}
1968
1969// @egt
1970uvClickListener(".uws-booktype.uws-booktype-item.uws-booktype-tickets.uv-universe-tickets.uv-waitlist", function (e) {
1971	// e.preventDefault();
1972	uvDefaultToTicketsBtn();
1973});
1974
1975// @egt
1976uvClickListener(".uv-tickets-cnt.uv-tickets-loading", function (e) {
1977	// e.preventDefault();
1978	uvDefaultToTicketsBtn();
1979});
1980
1981// @egt default click on hidden original tickets button
1982function uvDefaultToTicketsBtn() {
1983	var uvUniverseTgt = document.querySelector(".uws-extticketsbtn.uv-universe");
1984	
1985	if(uvUniverseTgt) uvUniverseTgt.click();
1986}
1987
1988// @egt [UWS-6651]
1989uvClickListener("a.uws-btn.uws-btn-p.uv-universe-btn.uv-vip-adm", function (e) {
1990	// e.preventDefault();
1991	
1992	uvVisibleTicketing = 1;
1993	uvOpenTicketingModal();
1994});
1995
1996// @egt [UWS-6651]
1997uvClickListener("a.uws-closepop.uwsjs-closepop", function (e) {
1998	uvHideTicketing();
1999});
2000
2001// @egt [UWS-6651]
2002// uvClickListener(".uws-pop-cont-cell", function (e) {
2003// 	uvHideTicketing();
2004// });
2005
2006// @egt [UWS-6651]
2007function uvHideTicketing(){
2008	// console.log("uvHideTicketing");
2009
2010	var uvCnt = document.querySelector(".uv-event-details .uv-ticketing-cnt");
2011
2012	if(uvCnt) uvCnt.classList.remove("uv-ticketing-visible");
2013}
2014
2015// @egt [UWS-6651]
2016function uvShowTicketing(){
2017	var uvCnt = document.querySelector(".uv-event-details .uv-ticketing-cnt");
2018
2019	if(uvCnt) uvCnt.classList.add("uv-ticketing-visible");
2020}
2021
2022// @egt gets the eventcode and calls functions in order to open ticketing pop [UWS-6651]
2023function uvOpenTicketingModal() {
2024	var uvTarget = document.querySelector(".uv-event-with-eventcode");
2025
2026	if(uvTarget && uvTarget.getAttribute("data-eventcode")) uvGetTicketingInventory(uvTarget.getAttribute("data-eventcode"));
2027}
2028
2029//calls the api in order to get ticketing values @egt [UWS-6651]
2030function uvGetTicketingInventory(uvEventcode) {
2031	const action = "_getticketinginv";
2032	const version = Math.floor(Math.random() * 101);
2033	const uvgetlocurl = uws_proxy + action + "&eventcode=" + uvEventcode + "&v=" + version;
2034	
2035	let uvrequest = new XMLHttpRequest();
2036	uvrequest.open('GET', uvgetlocurl, true);
2037	uvrequest.onload = function () {
2038		if (this.status >= 200 && this.status < 400) {
2039			let uvresponse = this.response;
2040			uvresponse = JSON.parse(uvresponse);
2041
2042			uvTicketingLowest = uvresponse["lowest"];
2043			uvTicketingLowestValue = uvresponse["lowest_value"];
2044
2045			if (uvresponse["status"] === 200 && uvTicketingLowest) {
2046				uvOpenTicketingPop();
2047			}
2048		} else {
2049			console.log(this.status);
2050			console.log(this.message);
2051		}
2052	};
2053
2054	uvrequest.onerror = function () {
2055		console.log("UVJS Error: Request Error");
2056	};
2057
2058	uvrequest.send();
2059}
2060
2061//@egt opens the pop up with ticketing information [UWS-6651]
2062function uvOpenTicketingPop() {
2063	var uvBtn = ".uwsactions a.uwsjs-inv-ecoitem-select.uws-btn.uws-btn-p[";
2064	uvBtn = uvBtn + 'data-mascode="' + uvTicketingLowest + '"]';
2065	uvBtn = document.querySelector(uvBtn);
2066
2067	if(uvBtn) uvBtn.click();
2068
2069	uvTicketingObserver();
2070}
2071
2072//@egt sets the information for ticketing and shows it [UWS-6651]
2073function uvSetTicketingValues() {
2074	var uvLabelSelectionValue = document.querySelector(".uv-selection-value");
2075	var uvLabelUpgradeValue = document.querySelector(".uv-upgrade-value");
2076	var uvLabelSavingsValue = document.querySelector(".uv-savings-value");
2077	var uvLabelTotalValue = document.querySelector(".uv-total-value");
2078	var uvLabelMinimumValue = document.querySelector(".uv-minimum-spend-value");
2079
2080	if(uvLabelSelectionValue) uvLabelSelectionValue.innerHTML = uvTcktSelectionValue = uvTicketingValue;
2081	if(uvLabelUpgradeValue) uvLabelUpgradeValue.innerHTML = uvTcktUpgradeValue = (uvTicketingLowestValue - uvTicketingValue);
2082	if(uvLabelSavingsValue) uvLabelSavingsValue.innerHTML = uvTcktSavingsValue = uvTicketingLowestValue;
2083	if(uvLabelTotalValue) uvLabelTotalValue.innerHTML = uvTcktTotalValue = uvTicketingLowestValue;
2084	if(uvLabelMinimumValue) uvLabelMinimumValue.innerHTML = uvTcktMinimumValue = uvTicketingLowestValue;
2085
2086	uvTicketingSetMinGuest();
2087}
2088
2089// sets gets to 1 or the minimum in order to make the user add to the qty and display ticketing changes @egt[UWS-6651]
2090function uvTicketingSetMinGuest() {
2091	var uvMinus = document.querySelector(".uwsitemselbox button.uwsjs-selnum-minus");
2092
2093    var uvDoc = document.querySelector("#uws-invitem-pop");
2094
2095    if (uvMinus) {
2096        if (uvDoc.classList.contains("visible")) {
2097            uvDoc.classList.add("uws-noareaclose");
2098
2099			if(uvMinus)
2100				while(!uvMinus.classList.contains("uwsdisabled")){
2101					uvMinus.click();
2102				}
2103
2104            setTimeout(() => {
2105                uvDoc.classList.remove("uws-noareaclose");
2106            }, 50);
2107        }
2108    }
2109}
2110
2111// needed for the loader animation @egt [UWS-6651]
2112function uvTicketingObserver() {
2113	const uvTarget = 'html';
2114    const uvQueryElement = document.querySelector(uvTarget);
2115    const uvObConfig = { attributes: true, childList: false, subtree: false };
2116
2117    if (!uvQueryElement) {
2118        // console.log(uvTarget + " not found. Waiting for it to appear...");
2119        
2120        return;
2121    }
2122
2123	var uvTries = 0;
2124	const uvMaxTries = 5;
2125
2126    const uvObserver = new MutationObserver((mutations) => {
2127        let executed = false;
2128
2129        mutations.forEach((mutation) => {
2130            // const { target } = mutation;
2131            if (executed) return; // Skip further execution
2132                if (mutation.target.classList.contains("uws-pop-open"))
2133                    if (mutation.attributeName === "class") {
2134						executed = true; // Prevent further execution for this batch
2135						
2136						if(uvVisibleTicketing == 1) {
2137							uvSetTicketingValues();
2138							uvShowTicketing();
2139
2140							uvVisibleTicketing = 0;
2141						}
2142
2143						uvTries = uvTries + 1;
2144
2145						if(uvTries >= uvMaxTries) {
2146							if(uvObserver) uvObserver.disconnect();
2147							uvLogDebug("uvTicketingObserver shutdown");
2148						}
2149                    }
2150        });
2151    });
2152
2153    uvObserver.observe(uvQueryElement, uvObConfig);
2154}
2155
2156// gets and sets the background in order to stylize it on events for the banner @egt [UWS-6706]
2157function uvSetBannerBackground() {
2158	var uvIsEvents = document.querySelector(".uws-events");
2159	var uvHeaderParent = document.querySelector(".uv-pagetitlewbg.uv-global-header"); 
2160	var uvHeaderImg = document.querySelector(".uv-section-bg"); 
2161	
2162	if(uvIsEvents && uvHeaderParent && uvHeaderImg) 
2163		setTimeout(() => {
2164			uvHeaderParent.style.backgroundImage = uvHeaderImg.style.backgroundImage;
2165		}, 50);
2166}
2167
2168//@egt [UWS-7154]
2169function uvUpdateVenueDirection() {
2170	var uvLocation = "https://maps.app.goo.gl/dnjUxoMRtX2dxhx66";
2171	var uvVenue = document.querySelector("body :is(.uws-event-EVE112156100120260206, .uws-event-EVE112156100120260207) .uwsvenueinfo a");
2172
2173	if(uvVenue) uvVenue.setAttribute("href", uvLocation);
2174}
2175
2176// helps adding the message if the event is over and gets upcoming ones @egt [UWS-6654]
2177function uvIsPastEvent() {
2178	var uvEventDate = document.querySelector("h2.uv-title-info-date");
2179	var uvTime = document.querySelector(".uv-time-info .uwsdtime");
2180	var uvCurrentDate = new Date();
2181	var uvEventDuration = 6;
2182	var uvHeader = document.querySelector(".uws-integration.uws-event header");
2183	var uvUpcoming = document.querySelector(".uv-event-completion.uv-upcoming-events");
2184
2185	if(uvEventDate && uvEventDate.getAttribute("data-date")) {
2186		// uvEventDate = new Date(uvEventDate.getAttribute("data-date"));
2187
2188		if(uvTime && uvTime.textContent != "") {
2189			uvEventDate = uvEventDate.getAttribute("data-date");
2190			uvEventDate = uvGetEventTime(uvEventDate, uvTime.textContent);
2191		} else {
2192			const [y, m, d] = uvEventDate.getAttribute("data-date").split("-");
2193			uvEventDate = new Date(y, m - 1, d);
2194		}
2195
2196		if(uvCurrentDate > uvEventDate && uvCurrentDate.getHours() >= uvEventDuration) {
2197			uvEventOverMsg();
2198
2199			if(uvHeader && uvHeader.getAttribute("data-eventcode") && !uvUpcoming) {
2200				uvGetUpcomingEvents(uvHeader.getAttribute("data-eventcode"));
2201				uvShowUpcoming = false;
2202			}
2203		}
2204	}
2205}
2206
2207// observer for uvIsPastEvent() @egt [UWS-6654]
2208function uvPastEventObserver() {
2209	const uvTarget = '.uws-integration.uws-event';
2210    const uvQueryElement = document.querySelector(uvTarget);
2211    const uvObConfig = { attributes: true, childList: false, subtree: true };
2212
2213    if (!uvQueryElement) {
2214        // console.log(uvTarget + " not found. Waiting for it to appear...");
2215        
2216        return;
2217    }
2218	
2219	var uvTries = 0;
2220	const uvMaxTries = 5;
2221
2222	const uvObserver = new MutationObserver((mutations) => {
2223        let executed = false;
2224
2225        mutations.forEach((mutation) => {
2226            // const { target } = mutation;
2227            if (executed) return; // Skip further execution
2228                // if (mutation.target.classList.contains(".uv-title-info-date"))
2229                    if (mutation.attributeName === "class") {
2230                        executed = true; // Prevent further execution for this batch
2231                        
2232						if(uvQueryElement.querySelector(".uv-title-info-date")) {
2233							uvIsPastEvent();
2234						}
2235					
2236						uvTries = uvTries + 1;
2237
2238						if(uvTries >= uvMaxTries) {
2239							if(uvObserver) uvObserver.disconnect();
2240							uvLogDebug("uvPastEventObserver shutdown");
2241						}
2242                    }
2243        });
2244    });
2245
2246    uvObserver.observe(uvQueryElement, uvObConfig);
2247}
2248
2249//calls the api in order to get upcoming events [UWS-6654] @egt
2250function uvGetUpcomingEvents(eventcode) {
2251	const action = "_getupcomingevents";
2252	const version = Math.floor(Math.random() * 101);
2253	var uvLocation = document.querySelector("body").getAttribute("data-venue");
2254	var uvLocationAtt = (uvLocation) ? "&location=" + uvLocation : "";
2255	const uvgetlocurl = uws_proxy + action + "&eventcode=" + eventcode + uvLocationAtt + "&v=" + version;
2256	var uvEventCnt = document.querySelector(".uws-integration.uws-event .uws-event-maincol");
2257	var uvUpcoming = document.querySelector(".uv-event-completion.uv-upcoming-events");
2258	
2259	if(!uvUpcoming && uvShowUpcoming == true) {
2260		let uvrequest = new XMLHttpRequest();
2261		uvrequest.open('GET', uvgetlocurl, true);
2262		uvrequest.onload = function () {
2263			if (this.status >= 200 && this.status < 400) {
2264				let uvresponse = this.response;
2265				uvresponse = JSON.parse(uvresponse);
2266
2267				if (uvresponse["status"] === 200 && uvresponse["upcomingevents"]) {
2268					if(uvresponse["upcomingevents"] != "" && uvEventCnt) {
2269						uvEventCnt.insertAdjacentHTML("beforeend", uvresponse["upcomingevents"]);
2270
2271						if(uvresponse["viewtype"] == "carousel") {
2272							// uvLogDebug("is carousel");
2273							
2274							let uvCarousel = uvresponse["carousel"];
2275							let uvLoop = uvresponse["enabledloop"];
2276							let uvCount = uvresponse["cardcount"];
2277
2278							uvBuildUpcomingCarousel(uvCarousel, uvLoop, uvCount);
2279						}
2280					}
2281				}
2282			} else {
2283				console.log(this.status);
2284				console.log(this.message);
2285			}
2286		};
2287
2288		uvrequest.onerror = function () {
2289			console.log("UVJS Error: Request Error");
2290		};
2291
2292		uvrequest.send();
2293	} 
2294	// else console.log("Cnt already exists");
2295}
2296
2297// function that logs only for dv / stg @egt
2298function uvLogDebug(uvMsg) {
2299	if(window.location.href.includes("livnightclubdv") || window.location.href.includes("livnightclubst"))
2300		console.log("[DEV][LOG] " + uvMsg);
2301}
2302
2303// added by @egt [UWS-6654]
2304function uvGetEventTime(uvDateStr, uvTimeStr) {
2305	const [y, m, d] = uvDateStr.split("-");
2306
2307	// parse time
2308	const [, h, min, meridiem] = uvTimeStr
2309	.trim()
2310	.toLowerCase()
2311	.match(/(\d{1,2}):(\d{2})\s*(am|pm)/);
2312
2313	let uvHours = parseInt(h, 10);
2314	const uvMinutes = parseInt(min, 10);
2315
2316	// convert to 24h
2317	if (meridiem === "pm" && uvHours !== 12) uvHours += 12;
2318	if (meridiem === "am" && uvHours === 12) uvHours = 0;
2319
2320	// create local date
2321	const uvDate = new Date(y, m - 1, d, uvHours, uvMinutes);
2322
2323	return uvDate;
2324}
2325
2326// @egt [UWS-6654]
2327function uvBuildUpcomingCarousel(uvCarousel, uvLoop, uvCount) {
2328	uvCarousel = document.querySelector(uvCarousel);
2329	var uvSlideCount;
2330	var uvDesktopSlidesPerView;
2331	var uvCarouselClass = "uv-upcoming-multiple";
2332	var uvSpaceBetween = 20;
2333	var uvMobSpaceBetween = 10;
2334	var uvMobSlidesPerView = 1.35;
2335
2336	if(uvCarousel) {
2337		uvSlideCount = uvCount;
2338		// uvSlideCount = uvCarousel.querySelectorAll('.swiper-slide').length;
2339
2340		if(uvSlideCount == 1){
2341			uvCarouselClass = "uv-upcoming-single";
2342			uvMobSlidesPerView = 1;
2343			uvSpaceBetween = uvMobSpaceBetween = 0;
2344		}
2345
2346		uvDesktopSlidesPerView = 2; //set as minimum
2347		uvLoop = uvLoop && uvSlideCount > 1; // loops only and creates duplicates only if > 1
2348
2349		var uvUpcomingCarousel = new Swiper(uvCarousel,  {
2350			slidesPerView: uvDesktopSlidesPerView,
2351			spaceBetween: uvSpaceBetween,
2352			loop: uvLoop,
2353			watchOverflow: false,
2354			preloadImages: true,
2355			// centerInsufficientSlides: true,
2356			lazy: {
2357				loadPrevNext: true
2358			},
2359			breakpoints: {
2360				1024: { slidesPerView: uvDesktopSlidesPerView },
2361				300:  { slidesPerView: uvMobSlidesPerView },
2362				0:    { slidesPerView: 1, spaceBetween: uvMobSpaceBetween }
2363			},
2364			navigation: {
2365				prevEl: '.uv-upcoming-events-carousel .swiper-button-prev',
2366				nextEl: '.uv-upcoming-events-carousel .swiper-button-next'
2367			},
2368			on: {
2369				init(swiper) {
2370					swiper.el.classList.add(uvCarouselClass);
2371				}
2372			}
2373		});
2374	}
2375}
2376
2377// @egt [UWS-7959] closes the popup when clicking on the buttons
2378uwsClickListener(".uv-yn-btn.uv-close-city-pop", function (e) {
2379	e.preventDefault();
2380
2381	const uvpopelem = this.closest(".uws-pop-cont");
2382	const uvCnt = document.querySelector(".uv-special-events");
2383	//change " for grave accent
2384
2385	const uvCntHTML = `
2386		<style>
2387			/* @egt [UWS-7959] */
2388			.uv-special-events::after {
2389				content: "";
2390				display: flex;
2391				height: 100%;
2392				width: 100%;
2393				background: #000000de;
2394				position: absolute;
2395				top: 0;
2396				z-index: 12;
2397			}
2398			
2399			/* @egt [UWS-7959] */
2400			.uv-special-events {
2401				position: relative;
2402			}
2403		</style>
2404	`;
2405
2406	if (uvpopelem)
2407		uwsHidePopup(uvpopelem, true);
2408
2409	if (e.target.getAttribute("data-type") && e.target.getAttribute("data-type") == "no") {
2410		// setCookie('persist-citypop', '1', 1);
2411
2412		if (uvCnt) {
2413			uvCnt.insertAdjacentHTML("beforeend", uvCntHTML);
2414		}
2415	}
2416});

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.