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_siteFoundation", "domReady!"], function($, gtm, UIWatcher, dynamic) { 7 $(document).foundation(); 8 gtm.update(); 9 10 // SEM tracking 11 var uiEvents = new UIWatcher({}, $, document); 12 uiEvents.on("change-page", handlePageChange); 13 uiEvents.on("view-change", handleFilterChange); 14 uiEvents.on("sort-change", handleFilterChange); 15 uiEvents.on("value-change", handleFilterChange); 16 uiEvents.on("toggle-show-more", handleShowMoreToggle); 17 uiEvents.on("scroll-into-view", handleScrollIntoView); 18 uiEvents.on("item-click", handleItemClick); 19 uiEvents.on("map-pin-click", handleMapPinClick); 20 uiEvents.on("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 data = { 28 eventCategory: widget.name, 29 eventAction: event.name +" - "+ event.value, 30 eventLabel: event.refTitle, 31 ot: event.type, 32 ltxt: event.displayText, 33 nonInteraction: false 34 } 35 if (data.eventCategory && data.eventAction && data.eventLabel) 36 gtm.sendEvents({tClient: data}); 37 38 //ga4 39 let crmCatSubcat = event?.crmc; 40 if (crmCatSubcat && event.crmsc) { 41 crmCatSubcat += " | " + event.crmsc; 42 } 43 let ga4Data = { 44 eventName: event.value ==="Add" ? "add_to_favorites" : undefined, 45 itemType: widget.name ==="Coupons"? 'offers' : widget.name.toLowerCase(), 46 itemName: event.refTitle, 47 linkObject: event.linkObject, 48 crmCatSubcat: crmCatSubcat 49 } 50 51 if (ga4Data.eventName && ga4Data.itemType && ga4Data.itemName && ga4Data.linkObject) 52 gtm.sendEvents({tClient_ga4: ga4Data}); 53 } 54 55 function handleQuickview(payload){ 56 var event = payload.eventContext, 57 widget = payload.widgetContext; 58 var eventCatName = widget.name; 59 switch(event.detailType) { 60 case "listings": 61 eventCatName = "Listings"; 62 break; 63 case "events": 64 eventCatName = "Events"; 65 break; 66 case "offers": 67 eventCatName = "Coupons"; 68 break; 69 default: 70 eventCatName = widget.name; 71 } 72 var data = { 73 eventCategory: eventCatName, 74 eventAction: event.linkTo, 75 eventLabel: event.refTitle, 76 ot: event.type, 77 ltxt: event.displayText, 78 nonInteraction: false 79 } 80 if (data.eventCategory && data.eventAction && data.eventLabel) 81 gtm.sendEvents({tClient: data}); 82 } 83 84 function handleScrollIntoView(payload){ 85 var event = payload.eventContext, 86 widget = payload.widgetContext; 87 var data = { 88 eventCategory: widget.name, 89 eventAction: event.name, 90 eventLabel: "Widget - "+widget.name, 91 nonInteraction: true 92 } 93 if (data.eventCategory && data.eventAction && data.eventLabel) 94 gtm.sendEvents({tClient: data}); 95 } 96 97 function handleShowMoreToggle(payload){ 98 var event = payload.eventContext, 99 widget = payload.widgetContext; 100 var data = { 101 eventCategory: widget.name, 102 eventAction: event.name, 103 eventLabel: event.displayText+" | "+event.refTitle, 104 nonInteraction: false 105 } 106 if (data.eventCategory && data.eventAction && data.eventLabel) 107 gtm.sendEvents({tClient: data}); 108 109 //ga4 110 let ga4Data = { 111 eventName: "filter", 112 filterType: event.displayText+" | "+event.refTitle, 113 itemType: event.itemType 114 } 115 116 if (ga4Data.eventName && ga4Data.filterType && ga4Data.itemType) 117 gtm.sendEvents({tClient_ga4: ga4Data}); 118 } 119 120 function handlePageChange(payload){ 121 var event = payload.eventContext, 122 widget = payload.widgetContext; 123 var data = { 124 eventCategory: widget.name, 125 eventAction: event.name, 126 eventLabel: event.refTitle+" | "+event.displayText, 127 nonInteraction: false 128 } 129 if (data.eventCategory && data.eventAction && data.eventLabel) 130 gtm.sendEvents({tClient: data}); 131 132 //ga4 133 let ga4Data = { 134 eventName: "filter", 135 filterType: event.refTitle+" | "+event.displayText, 136 itemType: event.itemType
137 } 138 139 if (ga4Data.eventName && ga4Data.filterType && ga4Data.itemType) 140 gtm.sendEvents({tClient_ga4: ga4Data}); 141 } 142 143 function handleItemClick(payload){ 144 var event = payload.eventContext, 145 widget = payload.widgetContext; 146 var data = { 147 eventCategory: widget.name, 148 eventAction: event.linkTo, 149 eventLabel: event.refTitle, 150 ot: event.type, 151 ltxt: event.displayText, 152 nonInteraction: false 153 } 154 /* alter action for once there */ 155 if (event.recId !== undefined && event.recId.toString().indexOf("ot") > -1) { 156 data.eventAction = "OnceThere"; 157 } 158 if (data.eventCategory && data.eventAction && data.eventLabel) 159 gtm.sendEvents({tClient: data}); 160 161 //ga4 162 let crmCatSubcat = event?.crmc; 163 if(event?.v_crmc){ 164 crmCatSubcat = event.v_crmc; 165 } else if (crmCatSubcat && event.crmsc) { 166 crmCatSubcat += " | " + event.crmsc; 167 } 168 let ga4Data = { 169 eventName: event.eventName, 170 itemType: event.itemType, 171 itemName: event.itemName ?? event.refTitle, 172 linkObject: event.linkObject, 173 crmCatSubcat: crmCatSubcat 174 } 175 176 if (ga4Data.eventName && ga4Data.itemType && ga4Data.itemName && ga4Data.linkObject) 177 gtm.sendEvents({tClient_ga4: ga4Data}); 178 } 179 180 function handleMapPinClick(payload){ 181 var event = payload.eventContext, 182 widget = payload.widgetContext; 183 var data = { 184 eventCategory: widget.name, 185 eventAction: event.name, 186 eventLabel: event.refTitle, 187 ot: event.type, 188 nonInteraction: false 189 } 190 if (data.eventCategory && data.eventAction && data.eventLabel) 191 gtm.sendEvents({tClient: data}); 192 } 193 194 function handleFilterChange (payload) { 195 var event = payload.eventContext, 196 widget = payload.widgetContext; 197 var data = { 198 eventCategory: widget.name, 199 eventAction: "Filter Change", 200 eventLabel: event.refTitle+" | "+event.displayText, 201 nonInteraction: false 202 } 203 if (data.eventCategory && data.eventAction && data.eventLabel) 204 gtm.sendEvents({tClient: data}); 205 206 //ga4 207 let ga4Data = { 208 eventName: "filter", 209 filterType: event.refTitle+" | "+event.displayText, 210 itemType: event.itemType 211 } 212 213 if (ga4Data.eventName && ga4Data.filterType && ga4Data.itemType) 214 gtm.sendEvents({tClient_ga4: ga4Data}); 215 } 216 // end SEM tracking 217}); 218 219// Lazy-load FontAwesome 220(function() { 221 var css = document.createElement('link'); 222 css.href = 'https://use.fontawesome.com/releases/v5.10.2/css/all.css'; 223 css.rel = 'stylesheet'; 224 css.type = 'text/css'; 225 document.getElementsByTagName('head')[0].appendChild(css); 226})(); 227 228// Lazy-load js for widgets that have the [data-js] attribute on their root node 229(function() { 230 function initDataJs(searchScope, selector = '[data-js]' ){ 231 require(['plugins_common_custom_lazyload'], function(lazyload) { 232 var widgetsToLoad = []; 233 let scope = searchScope ? searchScope : document; 234 var els = scope.querySelectorAll(selector); 235 236 for (var i = 0; i < els.length; i++) { 237 widgetsToLoad.push(els[i]); 238 } 239 240 lazyload.lazy(widgetsToLoad, function(entry, io) { 241 var target = entry.target; 242 var jsFile = target.dataset.js; 243 var guid = target.dataset.guid; 244 245 require([jsFile], function(widget) { 246 widget.init(guid); 247 io.unobserve(target); 248 }); 249 }); 250 }); 251 }; 252 253 initDataJs(); 254 255 let eventToSelectorMap = { 256 // each event needs a slightly different selector 257 "dynamicContentLoaded": "[data-dynamic-chosen] [data-js]", 258 "abContentLoaded": "[data-ab-chosen] [data-js]" 259 } 260 261 Object.entries(eventToSelectorMap).forEach( event => { 262 const [eventName, selector] = event; 263 window.addEventListener(eventName, e => { 264 const collections = document.querySelector(`[data-guid="${e}"]`); 265 initDataJs(collections, selector); 266 }); 267 }); 268})();
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.