PageSourceSearch

https://www.grapevinetexasusa.com/includes/public/managed/v_a2e6ae…/common/virtuals/js/shared_footer.js

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

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.