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 console.log({ 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 console.log({ tClient_ga4: ga4Data }); 73 } 74 75 function handleScrollIntoView(payload){ 76 var event = payload.eventContext, 77 widget = payload.widgetContext; 78 var data = { 79 eventCategory: widget.name, 80 eventAction: event.name, 81 eventLabel: "Widget - "+widget.name, 82 nonInteraction: true 83 } 84 if (data.eventCategory && data.eventAction && data.eventLabel) 85 console.log({tClient: data}); 86 } 87 88 function handleShowMoreToggle(payload){ 89 var event = payload.eventContext; 90 let ga4Data = { 91 eventName: "filter", 92 filterType: `${event?.refTitle} | ${event?.displayText}`, 93 itemType: event?.itemType, 94 interactionSource: event?.interactionSource, 95 interactionText: event?.interactionText, 96 } 97 if (ga4Data.eventName && ga4Data.filterType && ga4Data.itemType) 98 console.log({ tClient_ga4: ga4Data }); 99 } 100 101 function handlePageChange(payload){ 102 var event = payload.eventContext; 103 let ga4Data = { 104 eventName: "filter", 105 filterType: `${event?.refTitle} | ${event?.displayText}`, 106 itemType: event?.itemType, 107 interactionSource: event?.interactionSource, 108 interactionText: event?.interactionText, 109 } 110 if (ga4Data.eventName && ga4Data.filterType && ga4Data.itemType) 111 console.log({ tClient_ga4: ga4Data }); 112 } 113
114 function handleItemClick(payload){ 115 var event = payload.eventContext; 116 if (event?.name === "Quickview" || event?.name === "Quick View") { 117 var ga4Data = { 118 eventName: "filter", 119 filterType: "Open Quickview", 120 itemType: event?.itemType, 121 itemName: event?.itemName ?? event?.refTitle, 122 interactionSource: event?.interactionSource, 123 interactionText: event?.interactionText, 124 itemCategory: event?.crmc, 125 itemCity: event?.itemCity, 126 itemRegion: event?.itemRegion, 127 itemId: event?.itemId, 128 acctId: event?.acctId, 129 itemVariant: event?.itemVariant, 130 price: event?.price, 131 } 132 if (event?.crmsc) 133 ga4Data.itemSubcategory = event?.crmsc; 134 if (ga4Data.eventName && ga4Data.filterType && ga4Data.itemType) 135 console.log({tClient_ga4: ga4Data}); 136 } else { 137 var ga4Data = { 138 eventName: event?.eventName, 139 itemType: event?.itemType, 140 itemName: event?.itemName ?? event?.refTitle, 141 linkObject: event?.linkObject, 142 itemCategory: event?.crmc, 143 interactionSource: event?.interactionSource, 144 interactionText: event?.interactionText, 145 interactionUrl: event?.interactionUrl, 146 itemCity: event?.itemCity, 147 itemRegion: event?.itemRegion, 148 itemId: event?.itemId, 149 acctId: event?.acctId, 150 itemVariant: event?.itemVariant, 151 price: event?.price, 152 referralType: event?.referralType, 153 } 154 if (event?.crmsc) 155 ga4Data.itemSubcategory = event?.crmsc; 156 if (event?.eventName === 'partner_referral') 157 ga4Data.value = 5; 158 if (ga4Data.eventName && ga4Data.itemType && ga4Data.itemName && ga4Data.linkObject) 159 console.log({tClient_ga4: ga4Data}); 160 } 161 } 162 163 function handleMapPinClick(payload){ 164 var event = payload.eventContext, 165 widget = payload.widgetContext; 166 var data = { 167 eventCategory: widget.name, 168 eventAction: event.name, 169 eventLabel: event.refTitle, 170 ot: event.type, 171 nonInteraction: false 172 } 173 if (data.eventCategory && data.eventAction && data.eventLabel) 174 console.log({tClient: data}); 175 } 176 177 function handleFilterChange (payload) { 178 var event = payload.eventContext; 179 let ga4Data = { 180 eventName: "filter", 181 filterType: `${event?.refTitle} | ${event?.displayText}`, 182 itemType: event?.itemType, 183 interactionSource: event?.interactionSource, 184 interactionText: event?.interactionText, 185 } 186 if (ga4Data.eventName && ga4Data.filterType && ga4Data.itemType) 187 console.log({ tClient_ga4: ga4Data }); 188 } 189 // end SEM tracking 190 191 // Open textbox links in new window if they are external links. 192 let allLinks = document.querySelectorAll(".contentRender_name_plugins_core_textbox a"); 193 for (let i = 0; i < allLinks.length; i++) { 194 let href = allLinks[i].getAttribute("href"); 195 if (href && !href.includes("visitflorida") && !href.includes("lovefl")) { 196 if (!href.startsWith("#") && !href.startsWith("javascript:history") && (href !== "/")) { 197 if (!allLinks[i].getAttribute("target")) { 198 allLinks[i].setAttribute("target", "_blank"); 199 } 200 } 201 } 202 } 203}); 204 205// Lazy-load FontAwesome 206(function() { 207 var css = document.createElement('link'); 208 css.href = 'https://use.fontawesome.com/releases/v6.4.2/css/all.css'; 209 css.rel = 'stylesheet'; 210 css.type = 'text/css'; 211 document.getElementsByTagName('head')[0].appendChild(css); 212})(); 213 214// Lazy-load js for widgets that have the [data-js] attribute on their root node 215(function() { 216 function initDataJs(searchScope, selector = '[data-js]' ){ 217 require(['plugins_common_custom_lazyload'], function(lazyload) { 218 var widgetsToLoad = []; 219 let scope = searchScope ? searchScope : document; 220 var els = scope.querySelectorAll(selector); 221 222 for (var i = 0; i < els.length; i++) { 223 widgetsToLoad.push(els[i]); 224 } 225 226 lazyload.lazy(widgetsToLoad, function(entry, io) { 227 var target = entry.target; 228 var jsFile = target.dataset.js; 229 var guid = target.dataset.guid; 230 231 require([jsFile], function(widget) { 232 widget.init(guid); 233 io.unobserve(target); 234 }); 235 }); 236 }); 237 }; 238 239 initDataJs(); 240 241 let eventToSelectorMap = { 242 // each event needs a slightly different selector 243 "dynamicContentLoaded": "[data-dynamic-chosen] > .contentRender > [data-js]", 244 "abContentLoaded": "[data-ab-chosen] > .contentRender > [data-js]" 245 } 246
247 Object.entries(eventToSelectorMap).forEach( event => { 248 const [eventName, selector] = event; 249 window.addEventListener(eventName, e => { 250 const collections = document.querySelector(`[data-guid="${e}"]`); 251 initDataJs(collections, selector); 252 }); 253 }); 254})(); 255 256// Remove critical styles from head after all CSS files have loaded 257// This prevents a situation where the critical styles cause an override of the CSS in files 258const criticalStyles = document.querySelector('[data-critical-styles]'); 259if (criticalStyles) { 260 window.addEventListener('load', e => criticalStyles.remove()); 261}
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.