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("item-click", handleItemClick); 17 uiEvents.on("tripbuilder", handleTripbuilder); 18 uiEvents.on("qv-tripbuilder", handleTripbuilder); 19 uiEvents.on("quick-view", handleQuickview); 20 21 // tracking handlers 22 function handleTripbuilder(payload){ 23 var event = payload.eventContext, 24 widget = payload.widgetContext; 25 let ga4Data = { 26 eventName: event?.value === "Add" ? "add_to_favorites" : undefined, 27 itemType: widget?.name === "Coupons" ? 'offers' : widget?.name.toLowerCase() !== "quickview" ? widget?.name.toLowerCase() : event?.itemType, 28 itemName: event?.refTitle, 29 linkObject: event?.linkObject, 30 itemCategory: event?.crmc, 31 interactionSource: event?.interactionSource, 32 interactionText: event?.interactionText, 33 interactionUrl: event?.interactionUrl, 34 itemCity: event?.itemCity, 35 itemRegion: event?.itemRegion, 36 itemId: event?.itemId, 37 acctId: event?.acctId, 38 } 39 if (event?.crmsc) 40 ga4Data.itemSubcategory = event?.crmsc; 41 // if (ga4Data.eventName && ga4Data.itemType && ga4Data.itemName && ga4Data.linkObject) 42 // gtm.sendEvents({ tClient_ga4: ga4Data }); 43 console.log(ga4Data) 44 } 45 46 function handleQuickview(payload){ 47 var event = payload.eventContext; 48 let ga4Data = { 49 eventName: event?.eventName, 50 itemType: event?.itemType, 51 itemName: event?.itemName ?? event?.refTitle, 52 linkObject: event?.linkObject, 53 itemCategory: event?.crmc, 54 interactionSource: event?.interactionSource, 55 interactionText: event?.interactionText, 56 interactionUrl: event?.interactionUrl, 57 itemCity: event?.itemCity, 58 itemRegion: event?.itemRegion, 59 itemId: event?.itemId, 60 acctId: event?.acctId, 61 referralType: event?.referralType, 62 } 63 if (event?.crmsc) 64 ga4Data.itemSubcategory = event?.crmsc; 65 if (event?.eventName === 'partner_referral') 66 ga4Data.value = 5; 67 // if (ga4Data.eventName && ga4Data.itemType && ga4Data.itemName && ga4Data.linkObject) 68 // gtm.sendEvents({ tClient_ga4: ga4Data }); 69 console.log(ga4Data) 70 } 71 72 function handleShowMoreToggle(payload){ 73 var event = payload.eventContext; 74 let ga4Data = { 75 eventName: "filter", 76 filterType: `${event?.refTitle} | ${event?.displayText}`, 77 itemType: event?.itemType, 78 interactionSource: event?.interactionSource, 79 interactionText: event?.interactionText, 80 } 81 // if (ga4Data.eventName && ga4Data.filterType && ga4Data.itemType) 82 // gtm.sendEvents({ tClient_ga4: ga4Data }); 83 console.log(ga4Data) 84 } 85 86 function handlePageChange(payload){ 87 var event = payload.eventContext; 88 let ga4Data = { 89 eventName: "filter", 90 filterType: `${event?.refTitle} | ${event?.displayText}`, 91 itemType: event?.itemType, 92 interactionSource: event?.interactionSource, 93 interactionText: event?.interactionText, 94 } 95 // if (ga4Data.eventName && ga4Data.filterType && ga4Data.itemType) 96 // gtm.sendEvents({ tClient_ga4: ga4Data }); 97 console.log(ga4Data) 98 } 99 100 function handleItemClick(payload){ 101 var event = payload.eventContext; 102 if (event?.name === "Quickview") { 103 var ga4Data = { 104 eventName: "filter", 105 filterType: "Open Quickview", 106 itemType: event?.itemType, 107 itemName: event?.itemName ?? event?.refTitle, 108 interactionSource: event?.interactionSource, 109 interactionText: event?.interactionText, 110 itemCategory: event?.crmc, 111 itemCity: event?.itemCity, 112 itemRegion: event?.itemRegion, 113 itemId: event?.itemId, 114 acctId: event?.acctId, 115 } 116 if (event?.crmsc) 117 ga4Data.itemSubcategory = event?.crmsc; 118 // if (ga4Data.eventName && ga4Data.filterType && ga4Data.itemType) 119 // gtm.sendEvents({tClient_ga4: ga4Data}); 120 console.log(ga4Data) 121 } 122 else { 123 var ga4Data = { 124 eventName: event?.eventName, 125 itemType: event?.itemType, 126 itemName: event?.itemName ?? event?.refTitle, 127 linkObject: event?.linkObject, 128 itemCategory: event?.crmc, 129 interactionSource: event?.interactionSource, 130 interactionText: event?.interactionText, 131 interactionUrl: event?.interactionUrl, 132 itemCity: event?.itemCity, 133 itemRegion: event?.itemRegion, 134 itemId: event?.itemId, 135 acctId: event?.acctId, 136 referralType: event?.referralType, 137 } 138 if (event?.crmsc) 139 ga4Data.itemSubcategory = event?.crmsc; 140 if (event?.eventName === 'partner_referral') 141 ga4Data.value = 5; 142 // if (ga4Data.eventName && ga4Data.itemType && ga4Data.itemName && ga4Data.linkObject) 143 // gtm.sendEvents({tClient_ga4: ga4Data}); 144 console.log(ga4Data) 145 } 146 } 147 148 function handleFilterChange (payload) { 149 var event = payload.eventContext; 150 let ga4Data = { 151 eventName: "filter", 152 filterType: `${event?.refTitle} | ${event?.displayText}`, 153 itemType: event?.itemType, 154 interactionSource: event?.interactionSource, 155 interactionText: event?.interactionText, 156 } 157 // if (ga4Data.eventName && ga4Data.filterType && ga4Data.itemType) 158 // gtm.sendEvents({ tClient_ga4: ga4Data }); 159 console.log(ga4Data) 160 } 161 // end SEM tracking 162 163 // Init quickview textboxes 164 if (site.siteConfig.custom[site.site].quickview.active) { 165 const textBoxes = document.querySelectorAll('[data-qv-enabled-textbox]'); 166 167 if (textBoxes.length) { 168 require(['plugins_common_custom_quickview_textbox'], function (qv) {
169 qv.init(); 170 }); 171 } 172 } 173}); 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// Remove critical styles from head after all CSS files have loaded 229// This prevents a situation where the critical styles cause an override of the CSS in files 230const criticalStyles = document.querySelector('[data-critical-styles]'); 231if (criticalStyles) { 232 window.addEventListener('load', e =>
232 criticalStyles.remove()); 233}
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.