PageSourceSearch

https://www.bouldercoloradousa.com/includes/public/managed/v_a2e6a…/common/virtuals/js/shared_footer.js

js bouldercoloradousa.com collected 2026-10-02 04:09:05 UTC 7,993 bytes, 231 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("quick-view", handleQuickview);
21
22	// tracking handlers
23	function handleTripbuilder(payload) {
24		var event = payload.eventContext,
25			widget = payload.widgetContext;
26		let ga4Data = {
27			eventName: event?.value === "Add" ? "add_to_favorites" : undefined,
28			itemType: event?.itemType ?? (widget?.name === "Coupons" ? 'offers' : !["quickview", "quick view"].includes(widget?.name.toLowerCase()) ? widget?.name.toLowerCase() : undefined),
29			itemName: event.itemName ?? event.refTitle,
30			linkObject: event?.linkObject,
31			itemCategory: event?.crmc,
32			interactionSource: event?.interactionSource,
33			interactionText: event?.interactionText,
34			interactionUrl: event?.interactionUrl,
35			itemCity: event?.itemCity,
36			itemRegion: event?.itemRegion,
37			itemId: event?.itemId,
38			acctId: event?.acctId,
39			itemVariant: event?.itemVariant,
40			price: event?.price,
41		}
42		if (event?.crmsc) 
43			ga4Data.itemSubcategory = event?.crmsc;
44		if (ga4Data.eventName && ga4Data.itemType && ga4Data.itemName && ga4Data.linkObject)
45			gtm.sendEvents({ tClient_ga4: ga4Data });
46	}
47
48	function handleQuickview(payload) {
49		var event = payload.eventContext;
50		let ga4Data = {
51			eventName: event?.eventName,
52			itemType: event?.itemType,
53			itemName: event?.itemName ?? event?.refTitle,
54			linkObject: event?.linkObject,
55			itemCategory: event?.crmc,
56			interactionSource: event?.interactionSource,
57			interactionText: event?.interactionText,
58			interactionUrl: event?.interactionUrl,
59			itemCity: event?.itemCity,
60			itemRegion: event?.itemRegion,
61			itemId: event?.itemId,
62			acctId: event?.acctId,
63			itemVariant: event?.itemVariant,
64			price: event?.price,
65			referralType: event?.referralType,
66		}
67		if (event?.crmsc) 
68			ga4Data.itemSubcategory = event?.crmsc;
69		if (event?.eventName === 'partner_referral')
70			ga4Data.value = 5;
71		if (ga4Data.eventName && ga4Data.itemType && ga4Data.itemName && ga4Data.linkObject)
72			gtm.sendEvents({ tClient_ga4: ga4Data });
73	}
74
75	function handleScrollIntoView(payload) {
76		var event = payload.eventContext,
77			widget = payload.widgetContext;
78	}
79
80	function handleShowMoreToggle(payload) {
81		var event = payload.eventContext;
82		let ga4Data = {
83			eventName: "filter",
84			filterType: `${event?.refTitle} | ${event?.displayText}`,
85			itemType: event?.itemType,
86			interactionSource: event?.interactionSource,
87			interactionText: event?.interactionText,
88		}
89		if (ga4Data.eventName && ga4Data.filterType && ga4Data.itemType)
90			gtm.sendEvents({ tClient_ga4: ga4Data });
91	}
92
93	function handlePageChange(payload) {
94		var event = payload.eventContext;
95		let ga4Data = {
96			eventName: "filter",
97			filterType: `${event?.refTitle} | ${event?.displayText}`,
98			itemType: event?.itemType,
99			interactionSource: event?.interactionSource,
100			interactionText: event?.interactionText,
101		}
102		if (ga4Data.eventName && ga4Data.filterType && ga4Data.itemType)
103			gtm.sendEvents({ tClient_ga4: ga4Data });
104	}
105
106	function handleItemClick(payload) {
107		var event = payload.eventContext;
108		if (event?.name === "Quickview" || event?.name === "Quick View") {
109			var ga4Data = {
110				eventName: "filter",
111				filterType: "Open Quickview",
112				itemType: event?.itemType,
113				itemName: event?.itemName ?? event?.refTitle,
114				interactionSource: event?.interactionSource,
115				interactionText: event?.interactionText,
116				itemCategory: event?.crmc,
117				itemCity: event?.itemCity,
118				itemRegion: event?.itemRegion,
119				itemId: event?.itemId,
120				acctId: event?.acctId,
121				itemVariant: event?.itemVariant,
122				price: event?.price,
123			}
124			if (event?.crmsc)
125				ga4Data.itemSubcategory = event?.crmsc;
126			if (ga4Data.eventName && ga4Data.filterType && ga4Data.itemType)
127				gtm.sendEvents({tClient_ga4: ga4Data});
128		} else {
129			var ga4Data = {
130				eventName: event?.eventName,
131				itemType: event?.itemType,
132				itemName: event?.itemName ?? event?.refTitle,
133				linkObject: event?.linkObject,
134				itemCategory: event?.crmc,
135				interactionSource: event?.interactionSource,
136				interactionText: event?.interactionText,
137				interactionUrl: event?.interactionUrl,
138				itemCity: event?.itemCity,
139				itemRegion: event?.itemRegion,
140				itemId: event?.itemId,
141				acctId: event?.acctId,
142				itemVariant: event?.itemVariant,
143				price: event?.price,
144				referralType: event?.referralType,
145			}
146			if (event?.crmsc)
147				ga4Data.itemSubcategory = event?.crmsc;
148			if (event?.eventName === 'partner_referral')
149				ga4Data.value = 5;
150			if (ga4Data.eventName && ga4Data.itemType && ga4Data.itemName && ga4Data.linkObject)
151				gtm.sendEvents({tClient_ga4: ga4Data});
152		}
153	}
154
155	function handleMapPinClick(payload) {
156		var event = payload.eventContext,
157			widget = payload.widgetContext;
158	}
159
160	function handleFilterChange(payload) {
161		var event = payload.eventContext;
162		let ga4Data = {
163			eventName: "filter",
164			filterType: `${event?.refTitle} | ${event?.displayText}`,
165			itemType: event?.itemType,
166			interactionSource: event?.interactionSource,
167			interactionText: event?.interactionText,
168		}
169		if (ga4Data.eventName && ga4Data.filterType && ga4Data.itemType)
170			gtm.sendEvents({ tClient_ga4: ga4Data });
171	}
172	// end SEM tracking
173});
174
175// Lazy-load FontAwesome
176(function () {
177	var css = document.createElement('link');
178	css.href = 'https://use.fontawesome.com/releases/v5.14.0/css/all.css';
179	css.rel = 'stylesheet';
180	css.type = 'text/css';
181	document.getElementsByTagName('head')[0].appendChild(css);
182})();
183
184// Lazy-load js for widgets that have the [data-js] attribute on their root node
185(function () {
186	function initDataJs(searchScope, selector = '[data-js]') {
187		require(['plugins_common_custom_lazyload'], function (lazyload) {
188			var widgetsToLoad = [];
189			let scope = searchScope ? searchScope : document;
190			var els = scope.querySelectorAll(selector);
191
192			for (var i = 0; i < els.length; i++) {
193				widgetsToLoad.push(els[i]);
194			}
195
196			lazyload.lazy(widgetsToLoad, function (entry, io) {
197				var target = entry.target;
198				var jsFile = target.dataset.js;
199				var guid = target.dataset.guid;
200
201				require([jsFile], function (widget) {
202					widget.init(guid);
203					io.unobserve(target);
204				});
205			});
206		});
207	};
208
209	initDataJs();
210
211	let eventToSelectorMap = {
212		// each event needs a slightly different selector
213		"dynamicContentLoaded": "[data-dynamic-chosen] [data-js]",
214		"abContentLoaded": "[data-ab-chosen] [data-js]"
215	}
216	
217	Object.entries(eventToSelectorMap).forEach( event => {
218		const [eventName, selector] = event;
219		window.addEventListener(eventName, e => {
220			const collections = document.querySelector(`[data-guid="${e}"]`);
221			initDataJs(collections, selector);
222		});
223	});
224})();
225
226// Remove critical styles from head after all CSS files have loaded
227// This prevents a situation where the critical styles cause an override of the CSS in files
228const criticalStyles = document.querySelector('[data-critical-styles]');
229if (criticalStyles) {
230	window.addEventListener('load', e => criticalStyles.remove());
231}

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.