PageSourceSearch

https://raystown.org/includes/public/managed/v_a2e6ae52_e8921115/c…/common/virtuals/js/shared_footer.js

js raystown.org collected 2026-10-02 05:12:27 UTC 10,200 bytes, 337 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
6require(["jquery", "site_gtm", "plugins_common_custom_ui_watcher", "sv_load!plugins_dynamic_content", "sv_site", "domReady!"], function($, gtm, UIWatcher, dynamic, site) {
7	gtm.update();
8
9	// SEM tracking
10	var uiEvents = new UIWatcher({}, $, document);
11	uiEvents.on("change-page", handlePageChange);
12	uiEvents.on("view-change", handleFilterChange);
13	uiEvents.on("sort-change", handleFilterChange);
14	uiEvents.on("value-change", handleFilterChange);
15	uiEvents.on("toggle-show-more", handleShowMoreToggle);
16	uiEvents.on("scroll-into-view", handleScrollIntoView);
17	uiEvents.on("item-click", handleItemClick);
18	uiEvents.on("map-pin-click", handleMapPinClick);
19	uiEvents.on("tripbuilder", handleTripbuilder);
20	uiEvents.on("qv-tripbuilder", handleTripbuilder);
21	uiEvents.on("quick-view", handleQuickview);
22
23	// tracking handlers
24	function handleTripbuilder(payload){
25		var event = payload.eventContext,
26			widget = payload.widgetContext;
27		var eventCatName = widget.name;
28		switch (event.detailType) {
29				case "listings":
30					eventCatName = "Listings";
31					break;
32				case "events":
33					eventCatName = "Events";
34					break;
35				case "offers":
36					eventCatName = "Coupons";
37					break;
38				default:
39					eventCatName = widget.name;
40		}
41		var data = {
42			eventCategory: eventCatName,
43			eventAction: event.name +" - "+ event.value,
44			eventLabel: event.refTitle,
45			ot: event.type,
46			ltxt: event.displayText,
47			nonInteraction: false
48		}
49		if (data.eventCategory && data.eventAction && data.eventLabel)
50			gtm.sendEvents({tClient: data});
51
52		// GA4
53		let crmCatSubcat = event?.crmc;
54		if (crmCatSubcat && event.crmsc) {
55			crmCatSubcat += " | " + event.crmsc;
56		}
57		let ga4Data = {
58			eventName: event.value ==="Add" ? "add_to_favorites" : undefined,
59			itemType: widget.name ==="Coupons"? 'offers' : widget.name.toLowerCase() !== "quick view" ? widget.name.toLowerCase() : event.itemType,
60			itemName: event.refTitle,
61			linkObject: event.linkObject,
62			crmCatSubcat: crmCatSubcat
63		}
64
65		if (ga4Data.eventName && ga4Data.itemType && ga4Data.itemName)
66			gtm.sendEvents({tClient_ga4: ga4Data});
67	}
68	
69	function handleQuickview(payload){
70		var event = payload.eventContext,
71			widget = payload.widgetContext;
72		var eventCatName = widget.name;
73		switch (event.detailType) {
74				case "listings":
75					eventCatName = "Listings";
76					break;
77				case "events":
78					eventCatName = "Events";
79					break;
80				case "offers":
81					eventCatName = "Coupons";
82					break;
83				default:
84					eventCatName = widget.name;
85		}
86		var data = {
87			eventCategory: eventCatName,
88			eventAction: event.linkTo,
89			eventLabel: event.refTitle,
90			ot: event.type,
91			ltxt: event.displayText,
92			nonInteraction: false
93		}
94		if (data.eventCategory && data.eventAction && data.eventLabel)
95			gtm.sendEvents({tClient: data});
96
97		// GA4
98		let crmCatSubcat = event?.crmc;
99		if (event?.v_crmc) {
100			crmCatSubcat = event.v_crmc;
101		} else if (crmCatSubcat && event.crmsc) {
102			crmCatSubcat += " | " + event.crmsc;
103		}
104
105		let ga4Data = {
106			eventName: event.eventName,
107			itemType: event.itemType,
108			itemName: event.itemName ?? event.refTitle,
109			linkObject: event.linkObject,
110			crmCatSubcat: crmCatSubcat
111		}
112		if (ga4Data.eventName && ga4Data.itemType && ga4Data.itemName && ga4Data.linkObject)
113			gtm.sendEvents({tClient_ga4: ga4Data});
114	}
115
116	function handleScrollIntoView(payload){
117		var event = payload.eventContext,
118			widget = payload.widgetContext;
119		var data = {
120			eventCategory: widget.name,
121			eventAction: event.name,
122			eventLabel: "Widget - "+widget.name,
123			nonInteraction: true
124		}
125		if (data.eventCategory && data.eventAction && data.eventLabel)
126			gtm.sendEvents({tClient: data});
127	}
128
129	function handleShowMoreToggle(payload){
130		var event = payload.eventContext,
131			widget = payload.widgetContext;
132		var data = {
133			eventCategory: widget.name,
134			eventAction: event.name,
135			eventLabel: event.displayText+" | "+event.refTitle,
136			nonInteraction: false
137		}
138		if (data.eventCategory && data.eventAction && data.eventLabel)
139			gtm.sendEvents({tClient: data});
140
141		// GA4
142		let ga4Data = {
143			eventName: "filter",
144			filterType: event.displayText+" | "+event.refTitle,
145			itemType: event.itemType
146		}
147		if (ga4Data.eventName && ga4Data.filterType && ga4Data.itemType)
148			gtm.sendEvents({tClient_ga4: ga4Data});
149	}
150
151	function handlePageChange(payload){
152		var event = payload.eventContext,
153			widget = payload.widgetContext;
154		var data = {
155			eventCategory: widget.name,
156			eventAction: event.name,
157			eventLabel: event.refTitle+" | "+event.displayText,
158			nonInteraction: false
159		}
160		if (data.eventCategory && data.eventAction && data.eventLabel)
161			gtm.sendEvents({tClient: data});
162
163		// GA4
164		let ga4Data = {
165			eventName: "filter",
166			filterType: event.refTitle+" | "+event.displayText,
167			itemType: event.itemType
168		}
169		if (ga4Data.eventName && ga4Data.filterType && ga4Data.itemType)
170			gtm.sendEvents({tClient_ga4: ga4Data});
171	}
172
173	function handleItemClick(payload){
174		var event = payload.eventContext,
175			widget = payload.widgetContext;
176		var data = {
177			eventCategory: widget.name,
178			eventAction: event.linkTo,
179			eventLabel: event.refTitle,
180			ot: event.type,
181			ltxt: event.displayText,
182			nonInteraction: false
183		}
184		/* alter action for once there */
185		if (event.recId !== undefined && event.recId.toString().indexOf("ot") > -1) {
186			data.eventAction = "OnceThere";
187		}
188		if (data.eventCategory && data.eventAction && data.eventLabel)
189			gtm.sendEvents({tClient: data});
190
191		// GA4
192		let crmCatSubcat = event?.crmc;
193		if (event?.v_crmc) {
194			crmCatSubcat = event.v_crmc;
195		} else if (crmCatSubcat && event.crmsc) {
196			crmCatSubcat += " | " + event.crmsc;
197		}
198
199		if (event?.name === "Quick View") {
200			var ga4Data = {
201				eventName: "filter",
202				filterType: "Open Quick View",
203				itemType: event.itemType,
204				itemName: event.itemName ?? event.refTitle,
205			}
206			if (ga4Data.eventName && ga4Data.filterType && ga4Data.itemType)
207				gtm.sendEvents({tClient_ga4: ga4Data});
208		}
209		else {
210			var ga4Data = {
211				eventName: event.eventName,
212				itemType: event.itemType,
213				itemName: event.itemName ?? event.refTitle,
214				linkObject: event.linkObject,
215				crmCatSubcat: crmCatSubcat
216			}
217			if (ga4Data.eventName && ga4Data.itemType && ga4Data.itemName && ga4Data.linkObject)
218				gtm.sendEvents({tClient_ga4: ga4Data});
219		}
220	}
221
222	function handleMapPinClick(payload){
223		var event = payload.eventContext,
224			widget = payload.widgetContext;
225		var data = {
226			eventCategory: widget.name,
227			eventAction: event.name,
228			eventLabel: event.refTitle,
229			ot: event.type,
230			nonInteraction: false
231		}
232		if (data.eventCategory && data.eventAction && data.eventLabel)
233			gtm.sendEvents({tClient: data});
234	}
235 
236	function handleFilterChange (payload) {
237		var event = payload.eventContext,
238			widget = payload.widgetContext;
239		var data = {
240			eventCategory: widget.name,
241			eventAction: "Filter Change",
242			eventLabel: event.refTitle+" | "+event.displayText,
243			nonInteraction: false
244		}
245		if (data.eventCategory && data.eventAction && data.eventLabel)
246			gtm.sendEvents({tClient: data});
247
248		// GA4
249		let ga4Data = {
250			eventName: "filter",
251			filterType: event.refTitle+" | "+event.displayText,
252			itemType: event.itemType
253		}
254		if (ga4Data.eventName && ga4Data.filterType && ga4Data.itemType)
255			gtm.sendEvents({tClient_ga4: ga4Data});
256	}
257	// end SEM tracking
258
259	// Init quickview textboxes
260	if (site.siteConfig.custom[site.site].quickview.active) {
261		const textBoxes = document.querySelectorAll('[data-qv-enabled-textbox]');
262	
263		if (textBoxes.length) {
264			require(['plugins_common_custom_quickview_textbox'], function (qv) {
265				qv.init();
266			});
267		}
268	}
269});
270
271// Lazy-load FontAwesome
272(function() {
273	var css = document.createElement('link');
274	css.href = 'https://use.fontawesome.com/releases/v5.14.0/css/all.css';
275	css.rel = 'stylesheet';
276	css.type = 'text/css';
277	document.getElementsByTagName('head')[0].appendChild(css);
278})();
279
280// Lazy-load js for widgets that have the [data-js] attribute on their root node
281(function() {
282	function initDataJs(searchScope, selector = '[data-js]' ){
283		require(['plugins_common_custom_lazyload'], function(lazyload) {
284			var widgetsToLoad = [];
285			let scope = searchScope ? searchScope : document;
286			var els = scope.querySelectorAll(selector);
287
288			for (var i = 0; i < els.length; i++) {
289				widgetsToLoad.push(els[i]);
290			}
291			
292			lazyload.lazy(widgetsToLoad, function(entry, io) {
293				var target = entry.target;
294				var jsFile = target.dataset.js;
295				var guid = target.dataset.guid;
296
297				require([jsFile], function(widget) {
298					widget.init(guid);
299					io.unobserve(target);
300				});
301			});
302		});
303	};
304
305	initDataJs();
306
307	let eventToSelectorMap = {
308		// each event needs a slightly different selector
309		"dynamicContentLoaded": "[data-dynamic-chosen] [data-js]",
310		"abContentLoaded": "[data-ab-chosen] [data-js]"
311	}
312	
313	Object.entries(eventToSelectorMap).forEach( event => {
314		const [eventName, selector] = event;
315		window.addEventListener(eventName, e => {
316			const collections = document.querySelector(`[data-guid="${e}"]`);
317			initDataJs(collections, selector);
318		});
319	});
320})();
321
322// Wrap core_textbox iframes to prevent horizontal overflow
323(function() {
324	const textBoxes = document.querySelectorAll('[data-sv-core-textbox]');
325	if (textBoxes.length) {
326		require(['plugins_common_custom_utils'], function(utils) {
327			textBoxes.forEach(utils.wrapIframes);
328		});
329	}
330})();
331
332// Remove critical styles from head after all CSS files have loaded
333// This prevents a situation where the critical styles cause an override of the CSS in files
334const criticalStyles = document.querySelector('[data-critical-styles]');
335if (criticalStyles) {
336	window.addEventListener('load', e => criticalStyles.remove());
337}

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.