PageSourceSearch

https://www.visitgreaterpalmsprings.com/includes/public/managed/v_…/common/virtuals/js/shared_footer.js

js visitgreaterpalmsprings.com collected 2026-09-24 17:51:57 UTC 9,502 bytes, 274 lines download raw bytes

1// This file will be run in the footer on every page.
2// It should be used for content that relates
3// to your site as a whole, it should not be used for
4// plugin-specific js
5
6const docbody = document.querySelector('body');
7if (window.location.pathname.includes('/includes/plugins/')) {
8	docbody.classList.add('is-preview');
9}
10
11if (window.self !== window.top) {
12	docbody.classList.add('is-frame');
13}
14
15require(["jquery", "site_gtm", "sv_load!plugins_dynamic_content", "plugins_common_custom_ui_watcher", "sv_site",  "sv_siteFoundation", "domReady!"], function($, gtm, dynamicContent, UIWatcher, site) {
16
17	var publishStart = $("[data-publish-start]").attr("data-publish-start");
18	var cmsTags = $("[data-cms-tags]").attr("data-cms-tags");
19
20	if (dynamicContent) {
21		var user = getUserFields(["created", "type", "personas", "page_views"], dynamicContent.getUser());
22	
23		function getUserFields(fields, dcUser){
24			var user = {};
25			fields.some(function(field) {
26				if (dcUser !== undefined && dcUser[field] !== undefined) user[field] = dcUser[field];
27			});
28			return user;
29		}
30	
31		gtm.sendCustomPageview({ tClient_pageview: { dynamic_content: user, publish_start: publishStart, cms_tags: cmsTags }, tCore_pageview : {}}, "shared_footerJs");
32	}
33	else {
34		gtm.sendCustomPageview({ tClient_pageview: { publish_start: publishStart, cms_tags: cmsTags }, tCore_pageview : {}}, "shared_footerJs");
35	}
36
37	$(document).foundation();
38
39	gtm.update();
40
41	// SEM tracking
42	var uiEvents = new UIWatcher({}, $, document);
43	uiEvents.on("change-page", handlePageChange);
44	uiEvents.on("view-change", handleFilterChange);
45	uiEvents.on("sort-change", handleFilterChange);
46	uiEvents.on("value-change", handleFilterChange);
47	uiEvents.on("toggle-show-more", handleShowMoreToggle);
48	uiEvents.on("scroll-into-view", handleScrollIntoView);
49	uiEvents.on("item-click", handleItemClick);
50	uiEvents.on("map-pin-click", handleMapPinClick);
51	uiEvents.on("tripbuilder", handleTripbuilder);
52	uiEvents.on("qv-tripbuilder", handleTripbuilder);
53	uiEvents.on("quick-view", handleQuickview);
54
55	// tracking handlers
56	function handleTripbuilder(payload){
57		var event = payload.eventContext,
58			widget = payload.widgetContext;
59		let ga4Data = {
60			eventName: event?.value === "Add" ? "add_to_favorites" : undefined,
61			itemType: event?.itemType ?? (widget?.name === "Coupons" ? 'offers' : !["quickview", "quick view"].includes(widget?.name.toLowerCase()) ? widget?.name.toLowerCase() : undefined),
62			itemName: event.itemName ?? event.refTitle,
63			linkObject: event.linkObject || event.value ==="Add" ? "Add to Favorites" : undefined,
64			itemCategory: event?.crmc,
65			interactionSource: event?.interactionSource,
66			interactionText: event?.interactionText,
67			interactionUrl: event?.interactionUrl,
68			itemCity: event?.itemCity,
69			itemRegion: event?.itemRegion,
70			itemId: event?.itemId,
71			acctId: event?.acctId,
72			itemVariant: event?.itemVariant,
73			price: event?.price,
74		}
75		if (event?.crmsc) 
76			ga4Data.itemSubcategory = event?.crmsc;
77		if (ga4Data.eventName && ga4Data.itemType && ga4Data.itemName && ga4Data.linkObject)
78			gtm.sendEvents({ tClient_ga4: ga4Data });
79	}
80
81	function handleQuickview(payload){
82		var event = payload.eventContext;
83		let ga4Data = {
84			eventName: event?.eventName,
85			itemType: event.itemType ?? event.detailType,
86			itemName: event?.itemName ?? event?.refTitle,
87			linkObject: event.linkObject ?? event.linkTo,
88			itemCategory: event?.crmc,
89			interactionSource: event?.interactionSource,
90			interactionText: event?.interactionText,
91			interactionUrl: event?.interactionUrl,
92			itemCity: event?.itemCity,
93			itemRegion: event?.itemRegion,
94			itemId: event?.itemId,
95			acctId: event?.acctId,
96			itemVariant: event?.itemVariant,
97			price: event?.price,
98			referralType: event?.referralType,
99		}
100		if (event?.crmsc) 
101			ga4Data.itemSubcategory = event?.crmsc;
102		if (event?.eventName === 'partner_referral')
103			ga4Data.value = 5;
104		if (ga4Data.eventName && ga4Data.itemType && ga4Data.itemName && ga4Data.linkObject)
105			gtm.sendEvents({ tClient_ga4: ga4Data });
106			
107	}
108
109	function handleScrollIntoView(payload){
110		var event = payload.eventContext,
111			widget = payload.widgetContext;
112	}
113
114	function handleShowMoreToggle(payload){
115		var event = payload.eventContext;
116		let ga4Data = {
117			eventName: "filter",
118			filterType: event.displayText+" | "+event.refTitle,
119			itemType: event.itemType,
120			interactionSource: event?.interactionSource,
121			interactionText: event?.interactionText,
122		}
123		if (ga4Data.eventName && ga4Data.filterType && ga4Data.itemType)
124			gtm.sendEvents({tClient_ga4: ga4Data});
125	}
126
127	function handlePageChange(payload){
128		var event = payload.eventContext;
129		let ga4Data = {
130			eventName: "filter",
131			filterType: event.refTitle+" | "+event.displayText,
132			itemType: event.itemType,
133			interactionSource: event?.interactionSource,
134			interactionText: event?.interactionText,
135		}
136		if (ga4Data.eventName && ga4Data.filterType && ga4Data.itemType)
137			gtm.sendEvents({tClient_ga4: ga4Data});
138	}
139
140	function handleItemClick(payload){
141		var event = payload.eventContext;
142		if (event?.name === "Quickview" || event?.name === "Quick View") {
143			var ga4Data = {
144				eventName: "filter",
145				filterType: "Open Quick View",
146				itemType: event?.itemType,
147				itemName: event?.itemName ?? event?.refTitle,
148				interactionSource: event?.interactionSource,
149				interactionText: event?.interactionText,
150				itemCategory: event?.crmc,
151				itemCity: event?.itemCity,
152				itemRegion: event?.itemRegion,
153				itemId: event?.itemId,
154				acctId: event?.acctId,
155				itemVariant: event?.itemVariant,
156				price: event?.price,
157			}
158			if (event?.crmsc)
159				ga4Data.itemSubcategory = event?.crmsc;
160			if (ga4Data.eventName && ga4Data.filterType && ga4Data.itemType)
161				gtm.sendEvents({tClient_ga4: ga4Data});
162		} else {
163			var ga4Data = {
164				eventName: event?.eventName,
165				itemType: event?.itemType,
166				itemName: event?.itemName ?? event?.refTitle,
167				linkObject: event?.linkObject,
168				itemCategory: event?.crmc,
169				interactionSource: event?.interactionSource,
170				interactionText: event?.interactionText,
171				interactionUrl: event?.interactionUrl,
172				itemCity: event?.itemCity,
173				itemRegion: event?.itemRegion,
174				itemId: event?.itemId,
175				acctId: event?.acctId,
176				itemVariant: event?.itemVariant,
177				price: event?.price,
178				referralType: event?.referralType,
179			}
180			if (event?.crmsc)
181				ga4Data.itemSubcategory = event?.crmsc;
182			if (event?.eventName === 'partner_referral')
183				ga4Data.value = 5;
184			if (ga4Data.eventName && ga4Data.itemType && ga4Data.itemName && ga4Data.linkObject)
185				gtm.sendEvents({tClient_ga4: ga4Data});
186		}
187	}
188
189	function handleMapPinClick(payload){
190		var event = payload.eventContext,
191			widget = payload.widgetContext;
192	}
193
194	function handleFilterChange (payload) {
195		var event = payload.eventContext;
196		let ga4Data = {
197			eventName: "filter",
198			filterType: event.refTitle+" | "+event.displayText,
199			itemType: event.itemType,
200			interactionSource: event?.interactionSource,
201			interactionText: event?.interactionText,
202		}
203		if (ga4Data.eventName && ga4Data.filterType && ga4Data.itemType)
204			gtm.sendEvents({tClient_ga4: ga4Data});
205	}
206	// end SEM tracking
207
208	if (site.siteConfig.custom[site.site].quickview.active) {
209		const textBoxes = document.querySelectorAll('[data-qv-enabled-textbox]');
210
211		if (textBoxes.length) {
212			require(['plugins_common_custom_quickview_textbox'], function (qv) {
213				qv.init();
214			});
215		}
216	}
217
218	if (site.siteConfig.plugins.maps.active) {
219		// wait for the map iframe to load, then watch for changes on the details panel
220		// info link elements are added to the page dynamically when the details panel is opened
221		// update the info links to open in a new tab
222
223		const watchMap = (map) => {
224			const mapObserver = new MutationObserver((mutationsList, observer) => {
225				for (let mutation of mutationsList) {
226					if (mutation.type === 'childList') {
227						for (let node of mutation.addedNodes) {
228							if (node.classList !== undefined && node.classList.contains('infoTray')) {
229								for (let anchor of node.querySelectorAll('.contentItem > a')) {
230									anchor.setAttribute('target', '_blank');
231								}
232							}
233						}
234					}
235				}
236			});
237
238			mapObserver.observe(map.contentDocument, {
239				subtree: true,
240				childList: true,
241			});
242		};
243
244		const mapFrame = document.querySelector('.contentRender_name_plugins_maps_embed_widget > iframe');
245		let checkCount = 0;
246		let waitForMap = setInterval(() => {
247			checkCount++;
248			if (checkCount > 9 || mapFrame !== null) {
249				clearInterval(waitForMap);
250
251				if (mapFrame !== null) {
252					watchMap(mapFrame);
253				}
254			}
255		}, 1000);
256	}
257});
258
259// Lazy-load FontAwesome
260(function() {
261	var css = document.createElement('link');
262	css.href = 'https://use.fontawesome.com/releases/v5.15.4/css/all.css';
263	css.rel = 'stylesheet';
264	css.type = 'text/css';
265	document.getElementsByTagName('head')[0].appendChild(css);
266})();
267
268
269// Remove critical styles from head after all CSS files have loaded
270// This prevents a situation where the critical styles cause an override of the CSS in files
271const criticalStyles = document.querySelector('[data-critical-styles]');
272if (criticalStyles) {
273	window.addEventListener('load', e => criticalStyles.remove());
274}

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.