1var fbUserData = null; 2var numAttendingFriends = 0; 3var dripCartCreated = false; 4 5//fallback in case global translated strings are not in memory 6if (typeof shareText == 'undefined') { 7 var shareText = 'Share on'; 8 var calendarText = 'Calendar'; 9 var cookieText = 'Please enable cookies in your browser to proceed.'; 10} 11 12$(document).ready(function() { 13 14 $(".galleryPhoto a").fancybox(); 15 $(".classicEventLogo a").fancybox(); 16 $(".activity-preview a").fancybox({type: 'ajax'}); 17 18 // Disable Fancybox hash/history updates to avoid browser navigation / page refreshing when closing a fancybox opened from an <a> link 19 if ($.fancybox && $.fancybox.defaults) { 20 $.fancybox.defaults.hash = false; 21 } 22 23 $('.sharethisArea a.btn_share_facebook').on("click",function(e) { 24 e.preventDefault(); 25 PopupCenter($(this).attr('href'), shareText + ' Facebook', 550, 450); 26 return false; 27 }); 28 29 $('#fb-whos-going-area a#btn-fb-connect-share').on("click",function(e) { 30 e.preventDefault(); 31 PopupCenter($(this).attr('href'), shareText + ' Facebook', 550, 450); 32 return false; 33 }); 34 35 $('.sharethisArea a.btn_share_twitter').on("click",function(e) { 36 e.preventDefault(); 37 PopupCenter($(this).attr('href'), shareText + ' Twitter', 550, 450); 38 return false; 39 }); 40 41 $('.sharethisArea a.btn_share_google-plus').on("click",function(e) { 42 e.preventDefault(); 43 PopupCenter($(this).attr('href'), shareText + ' Google+', 680, 460); 44 return false; 45 }); 46 47 $('.sharethisArea a.btn_share_linkedin').on("click",function(e) { 48 e.preventDefault(); 49 PopupCenter($(this).attr('href'), shareText + ' LinkedIn', 680, 460); 50 return false; 51 }); 52 53 // <!-- AddThisEvent Settings --> 54 addthisevent.settings({ 55 mouse : false, 56 css : false, 57 outlook : {show:true, text:"Outlook " + calendarText}, 58 google : {show:true, text:"Google " + calendarText}, 59 yahoo : {show:true, text:"Yahoo " + calendarText}, 60 ical : {show:true, text:"iCal " + calendarText}, 61 hotmail : {show:true, text:"Hotmail " + calendarText}, 62 facebook : {show:true, text:"Facebook " + calendarText} 63 }); 64 65 $('input[required="required"]').addClass('required'); 66 $('select[required="required"]').addClass('required'); 67 68 $(".btn_help").fancybox({ 69 'transitionIn' : 'elastic', 70 'transitionOut' : 'elastic', 71 'speedIn' : 1000, 72 'speedOut' : 1000, 73 'overlayShow' : false, 74 'autoSize' : false, 75 'afterClose' : function(){cancelmessage();} 76 }); 77 78 var sendCartAbandonEmail = typeof abandonEnabled !== 'undefined' && abandonEnabled; 79 80 // Handle abandonment / drip triggers on tickets page 81 $("#orderForm #OrderEmail").on('focusout', function() { 82 // check that is a valid email format 83 var testEmail = /^[A-Z0-9._%+-]+@([A-Z0-9-]+\.)+[A-Z]{2,4}$/i; 84 if (testEmail.test($(this).val())){ 85 recordOrderAttempt(sendCartAbandonEmail); 86 } 87 }); 88 89}); 90 91// Meta browser (_fbp) and click (_fbc) IDs, both formatted fb.<subdomainIndex>.<creationMs>.<value> 92const META_BROWSER_ID_COOKIE = '_fbp'; 93const META_CLICK_ID_COOKIE = '_fbc'; 94const META_CLICK_ID_MAX_AGE_SECONDS = 90 * 24 * 60 * 60; 95const META_BROWSER_ID_POLL_ATTEMPTS = 10; 96const META_BROWSER_ID_POLL_DELAY_MS = 100; 97 98/** 99 * Reads a cookie value by name. 100 * @param {string} name cookie name 101 * @return {string} the decoded value, or '' when the cookie is not set or its value is malformed 102 */ 103function readCookieValue(name) { 104 const escapedName = name.replace(/[-.^$*+?()[\]{}|\\]/g, '\\$&'); 105 const match = document.cookie.match(new RegExp(`(?:^|;\\s*)${escapedName}=([^;]*)`)); 106 if (!match) { 107 return ''; 108 } 109 110 try { 111 return decodeURIComponent(match[1]); 112 } catch { 113 // A malformed value written by another script must not break the calling handler 114 return ''; 115 } 116} 117 118/** 119 * Resolves the Meta click ID (_fbc). Builds it from the fbclid URL parameter 120 * when the cookie is missing or holds an older click, which happens when an ad 121 * blocker stops fbevents.js from loading (the Pixel would otherwise write and 122 * refresh the cookie itself). Persists what it builds so later steps in the 123 * checkout funnel still carry the click ID. 124 * @return {string} the _fbc value, or '' when there is no click to attribute 125 */ 126function resolveMetaClickId() { 127 const fbclid = new URLSearchParams(window.location.search).get('fbclid'); 128 const existingClickId = readCookieValue(META_CLICK_ID_COOKIE); 129 130 // A differing fbclid means a newer ad click: refresh the cookie the way the 131 // Pixel would, rather than letting a stale click ID win for its 90-day life 132 if (!fbclid || (existingClickId && existingClickId.endsWith(`.${fbclid}`))) { 133 return existingClickId; 134 } 135 136 // Meta specifies a subdomain index of 1 when the value is generated outside the Pixel.
137 // No domain attribute, so this stays host-only: the registrable domain cannot be derived 138 // safely in JS across this platform's white-label domains. 139 const clickId = `fb.1.${Date.now()}.${fbclid}`; 140 const secureFlag = window.location.protocol === 'https:' ? '; secure' : ''; 141 document.cookie = `${META_CLICK_ID_COOKIE}=${encodeURIComponent(clickId)}; max-age=${META_CLICK_ID_MAX_AGE_SECONDS}; path=/; samesite=lax${secureFlag}`; 142 143 return clickId; 144} 145 146/** 147 * Reads the Meta browser ID (_fbp), retrying briefly because the Meta Pixel 148 * writes it only once fbevents.js has loaded, which can land after our first 149 * ViewContent call. 150 * @param {number} attemptsLeft remaining reads before giving up 151 * @param {function} onResolved receives the _fbp value, or '' if it never appears 152 */ 153function readMetaBrowserId(attemptsLeft, onResolved) { 154 const browserId = readCookieValue(META_BROWSER_ID_COOKIE); 155 if (browserId || attemptsLeft <= 1) { 156 onResolved(browserId); 157 return; 158 } 159 160 setTimeout(() => readMetaBrowserId(attemptsLeft - 1, onResolved), META_BROWSER_ID_POLL_DELAY_MS); 161} 162 163// XHR call for Meta Conversions API 164function postMetaConversions(metaData) { 165 // Copy so the fbc/fbp writes below stay off the caller's object, and so a 166 // caller that later mutates its payload can't race the _fbp wait 167 const payload = Object.assign({}, metaData); 168 169 // Resolved up front so the _fbc cookie is written even if the visitor 170 // navigates away while we are still waiting on _fbp 171 payload.fbc = resolveMetaClickId(); 172 173 readMetaBrowserId(META_BROWSER_ID_POLL_ATTEMPTS, (browserId) => { 174 payload.fbp = browserId; 175 176 $.ajax({ 177 type: "POST", 178 url: buildURL('/external_apis/ajax_post_meta_conversions'), 179 data: payload, 180 dataType: "json" 181 }); 182 }); 183} 184 185// adds partner channel and track to a javascript-written URL if needed 186function buildURL(sURL) { 187 if(partnerTrack) { 188 sURL = '/' + partnerTrack + sURL; 189 } 190 if(partnerChannel) { 191 sURL = '/' + partnerChannel + sURL; 192 } 193 return sURL; 194} 195 196 197 198function PopupCenter(url, title, w, h) { 199 // Fixes dual-screen position Most browsers Firefox 200 var dualScreenLeft = window.screenLeft != undefined ? window.screenLeft : screen.left; 201 var dualScreenTop = window.screenTop != undefined ? window.screenTop : screen.top; 202 203 width = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width; 204 height = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height; 205 206 var left = ((width / 2) - (w / 2)) + dualScreenLeft; 207 var top = ((height / 2) - (h / 2)) + dualScreenTop; 208 var newWindow = window.open(url, title, 'scrollbars=yes, status=no, toolbar=no, location=no, menubar=no, directories=no, width=' + w + ', height=' + h + ', top=' + top + ', left=' + left); 209
210 // Puts focus on the newWindow 211 if (window.focus) { 212 newWindow.trigger("focus"); 213 } 214} 215 216/** 217 * When a video thumbnail is selected in the video module, this highlights it, and loads it into the top iframe 218 * @param {[type]} youtubeUrl [description] 219 * @return {[type]} [description] 220 */ 221function loadTopVideo(galleryId, videoId, videoType, videoPlayerId) { 222 switch(videoType){ 223 case 'youtube': 224 $('#' + galleryId + '_iframe').attr('src', '//www.youtube.com/embed/' + videoId); 225 $('#' + galleryId + ' .thumb').removeClass('at'); 226 $('#' + galleryId + '_thumb'+youtubeUrl).addClass('at'); 227 break; 228 case 'brightcove': 229 $('#' + galleryId + '_iframe').attr('src', 'https://players.brightcove.net/' + videoPlayerId + '/default_default/index.html?videoId=' + videoId); 230 $('#' + galleryId + ' .thumb').removeClass('at'); 231 $('#' + galleryId + '_thumb'+youtubeUrl).addClass('at'); 232 break; 233 } 234} 235 236/** 237 * [wideReloadVideoFrame video selection UI controls for the Wide Format Layout] 238 * @param {[type]} videoId [description] 239 * @return {[type]} [description] 240 */ 241function wideReloadVideoFrame(type, videoId, playerId){ 242 switch(type){ 243 case "youtube": 244 $("#videoFrame").attr("src", "https://www.youtube.com/embed/" + videoId); 245 break; 246 case "brightcove": 247 $("#videoFrame").attr("src", "https://players.brightcove.net/" + playerId + "/default_default/index.html?videoId=" + videoId); 248 break; 249 } 250 $("#thumb_" + videoId).addClass("v_active"); 251 $(".video_thumb").not("#thumb_" + videoId).removeClass("v_active"); 252 var hgt = $('.video_thumb').height() * ($('#videoFrame').width() / $('.video_thumb').width()); 253 //using .css to avoid a bug in MS Edge - the .height() attribute doesn't set reliably that way 254 $('#videoFrame').css('height',hgt); 255 $('.player').css('height',hgt); 256} 257 258/** 259 * [alertCookiesRequired] 260 * @return {[type]} [description] 261 */ 262function alertCookiesRequired() { 263 if (!navigator.cookieEnabled) { 264 alert(cookieText); 265 } 266} 267 268/** 269 * Send Cart data to Drip and/or CartAbandonment email 270 * if we haven't already done so for this email address 271 * @param {[type]} videoId [description] 272 * @return {[type]} [description] 273 */ 274async function recordOrderAttempt(sendCartAbandonEmail) { 275 var runAjax = false; 276 if($('#OrderEmail').length > 0){ 277 // check if we need to run the ajax call 278 if($('#OrderEmailBackedUp').length > 0 && $('#OrderEmailBackedUp').val() == $('#OrderEmail').val()){ 279 // do not need to run the ajax again 280 } else { 281 // it has changed, need to run the ajax again 282 runAjax = true; 283 } 284 } else { 285 // run the ajax call 286 runAjax = true; 287 } 288 if (!runAjax) { 289 return; 290 } 291 if (sendCartAbandonEmail) { 292 $.ajax({ 293 type: "POST", 294 url: buildURL("/abandonments/ajax_record_order_attempt"), 295 data: $("#orderForm").serialize(), 296 dataType: "json", 297 success: function (data) { 298 if(data.success) { 299 if($('#OrderEmailBackedUp').length > 0 && $('#OrderEmailBackedUp').val()){ 300 $('#OrderEmailBackedUp').val(data.email); 301 } else { 302 $('<input>', { 303 type: 'hidden', 304 id: 'OrderEmailBackedUp', 305 name: 'data[Order][email_backed_up]', 306 value: data.email 307 }).appendTo('#orderForm'); 308 } 309 } else { 310 // did not process 311 } 312 // if we need to do anything on this side 313 } 314 }); 315 } 316 317 if (dripEnabled) { 318 sendCartDataToDrip('created', 'cart'); 319 } 320} 321 322function sendCartDataToDrip(action, type) { 323 if (action == 'created' && dripCartCreated) { 324 // runAjax check above doesn't always seem to work 325 return false; 326 } 327 328 // custom drip payload 329 const dripParams = { 330 dripEntity: type, 331 dripAction: action, 332 ticketsPage: window.location.href, 333 currency: currency, // defined on ticket page(s) 334 } 335 336 const additionalParams = Object.keys(dripParams) 337 .map(k => `&${k}=${dripParams[k]}`) 338 .join(''); 339 340 // Send to Drip 341 $.ajax({ 342 type: "POST", 343 url: buildURL("/external_apis/ajax_post_drip_cart_activity"), 344 data: $("#orderForm").serialize() + additionalParams, 345 dataType: "json", 346 success: function () { 347 if (!dripCartCreated) { 348 dripCartCreated = true; 349 } 350 return true; 351 } 352 }); 353} 354 355function updateDripCart() { 356 if (!dripCartCreated || !dripEnabled) { 357 return; 358 } 359 360 sendCartDataToDrip('updated', 'cart'); 361}
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.