PageSourceSearch

https://www.northalabama.org/includes/public/managed/v_c8155e17_56…/common/virtuals/js/shared_footer.js

js northalabama.org collected 2026-09-24 18:39:58 UTC 9,844 bytes, 320 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", "domReady!"], function ($, gtm, UIWatcher, dynamic) {
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 ga4Data = {
54			eventName: event.value ==="Add" ? "add_to_favorites" : undefined,
55			itemType: event.itemType ? event.itemType : (widget.name ==="Coupons"? 'offers' : widget.name.toLowerCase()),
56			itemName: event.itemName ?? event.refTitle,
57			linkObject: event.linkObject || event.value ==="Add" ? "Add to Favorites" : undefined,
58			itemCategory : event?.crmc
59		}
60		if (event?.crmsc)
61			ga4Data.itemSubcategory = event?.crmsc;
62		if (ga4Data.eventName && ga4Data.itemType && ga4Data.itemName && ga4Data.linkObject)
63			gtm.sendEvents({tClient_ga4: ga4Data});
64	}
65
66	function handleQuickview(payload) {
67		var event = payload.eventContext,
68			widget = payload.widgetContext;
69		var eventCatName = widget.name;
70		switch (event.detailType) {
71			case "listings":
72				eventCatName = "Listings";
73				break;
74			case "events":
75				eventCatName = "Events";
76				break;
77			case "offers":
78				eventCatName = "Coupons";
79				break;
80			default:
81				eventCatName = widget.name;
82		}
83		var data = {
84			eventCategory: eventCatName,
85			eventAction: event.linkTo,
86			eventLabel: event.refTitle,
87			ot: event.type,
88			ltxt: event.displayText,
89			nonInteraction: false
90		}
91		if (data.eventCategory && data.eventAction && data.eventLabel)
92			gtm.sendEvents({ tClient: data });
93	}
94
95	function handleScrollIntoView(payload) {
96		var event = payload.eventContext,
97			widget = payload.widgetContext;
98		var data = {
99			eventCategory: widget.name,
100			eventAction: event.name,
101			eventLabel: "Widget - " + widget.name,
102			nonInteraction: true
103		}
104		if (data.eventCategory && data.eventAction && data.eventLabel)
105			gtm.sendEvents({ tClient: data });
106	}
107
108	function handleShowMoreToggle(payload) {
109		var event = payload.eventContext,
110			widget = payload.widgetContext;
111		var data = {
112			eventCategory: widget.name,
113			eventAction: event.name,
114			eventLabel: event.displayText + " | " + event.refTitle,
115			nonInteraction: false
116		}
117		if (data.eventCategory && data.eventAction && data.eventLabel)
118			gtm.sendEvents({ tClient: data });
119		// ga4
120		let ga4Data = {
121			eventName: "filter",
122			filterType: `${event?.refTitle} | ${event?.displayText}`,
123			itemType: event?.itemType
124		}
125		if (ga4Data.eventName && ga4Data.filterType && ga4Data.itemType)
126			gtm.sendEvents({tClient_ga4: ga4Data});
127	}
128
129	function handlePageChange(payload) {
130		var event = payload.eventContext,
131			widget = payload.widgetContext;
132		var data = {
133			eventCategory: widget.name,
134			eventAction: event.name,
135			eventLabel: event.refTitle + " | " + event.displayText,
136			nonInteraction: false
137		}
138		if (data.eventCategory && data.eventAction && data.eventLabel)
139			gtm.sendEvents({ tClient: data });
140		// ga4
141		let ga4Data = {
142			eventName: "filter",
143			filterType: `${event?.refTitle} | ${event?.displayText}`,
144			itemType: event?.itemType
145		}
146		if (ga4Data.eventName && ga4Data.filterType && ga4Data.itemType)
147			gtm.sendEvents({tClient_ga4: ga4Data});
148	}
149
150	function handleItemClick(payload){
151		var event = payload.eventContext,
152			widget = payload.widgetContext;
153		if(event.trackingType === "detail"){
154			var data = {
155				eventCategory: widget.name,
156				eventAction: event.linkTo,
157				eventLabel: event.refTitle,
158				catName: event.catName,
159				crmc: event.crmc,
160				crmsc: event.crmsc,
161				region: event.region,
162				ua: event.ua,
163				vt: event.vt,
164				et: event.displayText,
165				address: event.address,
166				href: event.href,
167				lt: event.lt,
168				ot: event.type,
169				recId: event.recId,
170				nonInteraction: false
171			}
172		}else{
173			var data = {
174				eventCategory: widget.name,
175				eventAction: event.linkTo,
176				eventLabel: event.refTitle,
177				ot: event.type,
178				crmc: event.crmc,
179				crmsc: event.crmsc,
180				address: event.address,
181				dtn: event.dtn,
182				et: event.refTitle,
183				row: event.row,
184				lt: event.lt,
185				recId: event.recId,
186				region: event.region,
187				ua: event.ua,
188				vt: event.vt,
189				nonInteraction: false
190			}
191		}
192		/* alter action for once there */
193		if (event.recId !== undefined && event.recId.toString().indexOf("ot") > -1) {
194			data.eventAction = "OnceThere";
195		}
196		if (data.eventCategory && data.eventAction && data.eventLabel)
197			gtm.sendEvents({tClient: data});
198
199		// ga4
200		if (event?.name === "Quick View") {
201			var ga4Data = {
202				eventName: "filter",
203				filterType: "Open Quick View",
204				itemType: event.itemType,
205				itemName: event.itemName ?? event.refTitle,
206			}
207			if (ga4Data.eventName && ga4Data.filterType && ga4Data.itemType)
208				gtm.sendEvents({tClient_ga4: ga4Data});
209		}
210		else {
211			var ga4Data = {
212				eventName: event.eventName,
213				itemType: event.itemType,
214				itemName: event.itemName ?? event.refTitle,
215				linkObject: event.linkObject,
216				itemCategory: event?.crmc
217			}
218			if (event?.crmsc)
219				ga4Data.itemSubcategory = event?.crmsc;
220			if (event.partnerReferralData)
221				ga4Data = {...ga4Data, ...event.partnerReferralData, value: 5};
222			if (ga4Data.eventName && ga4Data.itemType && ga4Data.itemName && ga4Data.linkObject)
223				gtm.sendEvents({tClient_ga4: ga4Data});
224		}
225	}
226
227	function handleMapPinClick(payload) {
228		var event = payload.eventContext,
229			widget = payload.widgetContext;
230		var data = {
231			eventCategory: widget.name,
232			eventAction: event.name,
233			eventLabel: event.refTitle,
234			ot: event.type,
235			nonInteraction: false
236		}
237		if (data.eventCategory && data.eventAction && data.eventLabel)
238			gtm.sendEvents({ tClient: data });
239	}
240
241	function handleFilterChange(payload) {
242		var event = payload.eventContext,
243			widget = payload.widgetContext;
244		var data = {
245			eventCategory: widget.name,
246			eventAction: "Filter Change",
247			eventLabel: event.refTitle + " | " + event.displayText,
248			nonInteraction: false
249		}
250		if (data.eventCategory && data.eventAction && data.eventLabel)
251			gtm.sendEvents({ tClient: data });
252		// ga4
253		let ga4Data = {
254			eventName: "filter",
255			filterType: `${event?.refTitle} | ${event?.displayText}`,
256			itemType: event?.itemType
257		}
258		if (ga4Data.eventName && ga4Data.filterType && ga4Data.itemType)
259			gtm.sendEvents({tClient_ga4: ga4Data});
260	}
261	// end SEM tracking
262});
263
264// Lazy-load FontAwesome
265(function () {
266	var css = document.createElement('link');
267	css.href = 'https://use.fontawesome.com/releases/v5.14.0/css/all.css';
268	css.rel = 'stylesheet';
269	css.type = 'text/css';
270	document.getElementsByTagName('head')[0].appendChild(css);
271})();
272
273// Lazy-load js for widgets that have the [data-js] attribute on their root node
274(function () {
275	function initDataJs(searchScope, selector = '[data-js]') {
276		require(['plugins_common_custom_lazyload'], function (lazyload) {
277			var widgetsToLoad = [];
278			let scope = searchScope ? searchScope : document;
279			var els = scope.querySelectorAll(selector);
280
281			for (var i = 0; i < els.length; i++) {
282				widgetsToLoad.push(els[i]);
283			}
284
285			lazyload.lazy(widgetsToLoad, function (entry, io) {
286				var target = entry.target;
287				var jsFile = target.dataset.js;
288				var guid = target.dataset.guid;
289
290				require([jsFile], function (widget) {
291					widget.init(guid);
292					io.unobserve(target);
293				});
294			});
295		});
296	};
297
298	initDataJs();
299
300	let eventToSelectorMap = {
301		// each event needs a slightly different selector
302		"dynamicContentLoaded": "[data-dynamic-chosen] > .contentRender > [data-js]",
303		"abContentLoaded": "[data-ab-chosen] > .contentRender > [data-js]"
304	}
305
306	Object.entries(eventToSelectorMap).forEach(event => {
307		const [eventName, selector] = event;
308		window.addEventListener(eventName, e => {
309			const collections = document.querySelector(`[data-guid="${e}"]`);
310			initDataJs(collections, selector);
311		});
312	});
313})();
314
315// Remove critical styles from head after all CSS files have loaded
316// This prevents a situation where the critical styles cause an override of the CSS in files
317const criticalStyles = document.querySelector('[data-critical-styles]');
318if (criticalStyles) {
319	window.addEventListener('load', e => criticalStyles.remove());
320}

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.