1(function(window, $) { 2 if(!$) { 3 return; 4 } 5 6 var persistentStore = { 7 getItem: getCookie, 8 setItem: setCookie, 9 removeItem: removeCookie 10 }; 11 var sessionStore = { 12 getItem: getCookie, 13 setItem: function(key, value) { 14 setCookie(key, value); 15 }, 16 removeItem: removeCookie 17 }; 18 var popupModalZIndex = 2147483000; 19 var popupBackdropZIndex = 2147482990; 20 21 function cookieAttributes(expiresAt) { 22 var attributes = ['path=/', 'SameSite=Lax']; 23 24 if(expiresAt) { 25 attributes.push('expires=' + expiresAt.toUTCString()); 26 } 27 28 if(window.location.protocol == 'https:') { 29 attributes.push('Secure'); 30 } 31 32 return attributes.join('; '); 33 } 34 35 function getCookie(key) { 36 var keyPrefix = encodeURIComponent(key) + '='; 37 var cookies = document.cookie ? document.cookie.split('; ') : []; 38 var i; 39 40 for(i = 0; i < cookies.length; i++) { 41 if(cookies[i].indexOf(keyPrefix) === 0) { 42 return decodeURIComponent(cookies[i].substring(keyPrefix.length)); 43 } 44 } 45 46 return ''; 47 } 48 49 function setCookie(key, value, expiresAt) { 50 document.cookie = encodeURIComponent(key) + '=' + encodeURIComponent(value) + '; ' + cookieAttributes(expiresAt); 51 } 52 53 function removeCookie(key) { 54 setCookie(key, '', new Date(0)); 55 } 56 57 function foreverCookieDate() { 58 var expiryDate = new Date(); 59 expiryDate.setFullYear(expiryDate.getFullYear() + 10); 60 return expiryDate; 61 } 62 63 function ensurePopupLayerStyles() { 64 var popupLayerStyles; 65 66 if($('#wf-popup-layer-styles').length) { 67 return; 68 } 69 70 popupLayerStyles = '#popup-modal{z-index:' + popupModalZIndex + ' !important;}'; 71 popupLayerStyles += '.modal-backdrop.wf-popup-modal-backdrop{z-index:' + popupBackdropZIndex + ' !important;}'; 72 popupLayerStyles += '#popup-modal .modal-dialog{position:relative;}'; 73 popupLayerStyles += '#popup-modal .wf-popup-floating-close{position:absolute;top:-12px;right:-12px;z-index:3;width:34px;height:34px;padding:0;border-radius:50%;background:rgba(255,255,255,.95);box-shadow:0 2px 10px rgba(0,0,0,.25);float:none;line-height:1;opacity:.9;display:flex;align-items:center;justify-content:center;}'; 74 popupLayerStyles += '#popup-modal .wf-popup-floating-close:hover,#popup-modal .wf-popup-floating-close:focus{opacity:1;}'; 75 popupLayerStyles += '#popup-modal .modal-dialog.modal-xl{max-width:calc(100vw - 20px);}'; 76 popupLayerStyles += '@media (min-width:992px){#popup-modal .modal-dialog.modal-xl{width:900px;}}'; 77 popupLayerStyles += '@media (min-width:1200px){#popup-modal .modal-dialog.modal-xl{width:1140px;}}'; 78 79 $('head').append('<style id="wf-popup-layer-styles">' + popupLayerStyles + '</style>'); 80 } 81 82 function liftPopupBackdrop() { 83 $('.modal-backdrop').last() 84 .addClass('wf-popup-modal-backdrop') 85 .css('z-index', popupBackdropZIndex); 86 } 87 88 function popupKey(config, suffix) { 89 return 'wf_popup_' + config.siteId + '_' + config.pageId + '_' + suffix; 90 } 91 92 function getStored(store, key) { 93 if(!store) { 94 return ''; 95 } 96 return store.getItem(key); 97 } 98 99 function setStored(store, key, value, expiresAt) { 100 if(store) { 101 store.setItem(key, value, expiresAt); 102 } 103 } 104 105 function removeStored(store, key) { 106 if(store) { 107 store.removeItem(key); 108 } 109 } 110 111 function daysToMs(days) { 112 return parseInt(days, 10) * 24 * 60 * 60 * 1000; 113 } 114 115 function frequencyMs(config) { 116 switch(config.frequency) { 117 case 'day': 118 return daysToMs(1); 119 case 'week': 120 return daysToMs(7); 121 case 'custom': 122 return daysToMs(config.frequencyDays || 1); 123 default: 124 return 0; 125 } 126 } 127 128 function frequencyExpiresAt(config) { 129 if(config.frequency == 'once') { 130 return foreverCookieDate(); 131 } 132 133 if(frequencyMs(config) > 0) { 134 return new Date(Date.now() + frequencyMs(config)); 135 } 136 137 return null; 138 } 139 140 function acceptanceExpiryDate(config) { 141 var expiryDate = new Date(); 142 143 if((config.acceptanceExpiry || 'forever') == 'today') { 144 expiryDate.setHours(23, 59, 59, 999); 145 return expiryDate; 146 } 147 148 if(config.acceptanceExpiry == 'week') { 149 expiryDate.setDate(expiryDate.getDate() + 7); 150 return expiryDate; 151 } 152 153 if(config.acceptanceExpiry == 'month') { 154 expiryDate.setMonth(expiryDate.getMonth() + 1); 155 return expiryDate; 156 } 157 158 if(config.acceptanceExpiry == 'year') { 159 expiryDate.setFullYear(expiryDate.getFullYear() + 1); 160 return expiryDate; 161 } 162 163 return foreverCookieDate(); 164 } 165 166 function acceptanceExpiresAt(config) { 167 if((config.acceptanceExpiry || 'forever') == 'forever') { 168 return 'forever'; 169 } 170 171 return String(acceptanceExpiryDate(config).getTime()); 172 } 173 174 function acceptanceStatus(config) { 175 var accepted = getStored(persistentStore, popupKey(config, 'accepted')); 176 var acceptedUntil; 177 178 if(!accepted) { 179 return 'none'; 180 } 181 182 if((config.acceptanceExpiry || 'forever') == 'forever') { 183 return 'accepted'; 184 } 185 186 if(accepted == 'forever') { 187 removeStored(persistentStore, popupKey(config, 'accepted')); 188 return 'expired'; 189 } 190 191 acceptedUntil = parseInt(accepted, 10); 192 if(acceptedUntil > Date.now()) { 193 return 'accepted'; 194 } 195 196 removeStored(persistentStore, popupKey(config, 'accepted')); 197 return 'expired'; 198 } 199 200 function shouldShow(config) { 201 var requiredAcceptanceStatus; 202 203 if(config.requireChoice) { 204 requiredAcceptanceStatus = acceptanceStatus(config); 205 206 if(requiredAcceptanceStatus == 'accepted') { 207 return false;
208 } 209 210 if(requiredAcceptanceStatus == 'expired') { 211 return true; 212 } 213 214 if(config.showUntilAccepted) { 215 return true; 216 } 217 } 218 219 if(config.frequency == 'every') { 220 return true; 221 } 222 223 if(config.frequency == 'session') { 224 return getStored(sessionStore, popupKey(config, 'shown')) != '1'; 225 } 226 227 if(config.frequency == 'once') { 228 return getStored(persistentStore, popupKey(config, 'shown')) == ''; 229 } 230 231 var lastShown = parseInt(getStored(persistentStore, popupKey(config, 'shown')), 10); 232 if(!lastShown) { 233 return true; 234 } 235 236 return Date.now() - lastShown > frequencyMs(config); 237 } 238 239 function markShown(config) { 240 if(config.frequency == 'session') { 241 setStored(sessionStore, popupKey(config, 'shown'), '1'); 242 } else if(config.frequency == 'once') { 243 setStored(persistentStore, popupKey(config, 'shown'), '1', frequencyExpiresAt(config)); 244 } else if(config.frequency != 'every') { 245 setStored(persistentStore, popupKey(config, 'shown'), String(Date.now()), frequencyExpiresAt(config)); 246 } 247 } 248 249 function markAccepted(config) { 250 setStored(persistentStore, popupKey(config, 'accepted'), acceptanceExpiresAt(config), acceptanceExpiryDate(config)); 251 } 252 253 window.wfShowPopup = function(pageId, options) { 254 var config = $.extend({ 255 pageId: pageId, 256 siteId: window.wfPopupSiteId || 0, 257 automatic: false, 258 requireChoice: false, 259 acceptanceExpiry: 'forever' 260 }, options || {}); 261 262 if(!config.pageId) { 263 return; 264 } 265 266 $('#popup-modal').load('/templates/includes/popup-modal-content?page_id=' + encodeURIComponent(config.pageId), function() { 267 config.requireChoice = config.requireChoice || $('#popup-modal').find('[data-popup-choice-required]').length > 0; 268 var modalOptions = { 269 keyboard: !config.requireChoice, 270 backdrop: config.requireChoice ? 'static' : true 271 }; 272 273 $('#popup-modal') 274 .data('wf-popup-config', config) 275 .modal(modalOptions); 276 277 liftPopupBackdrop(); 278 279 if(config.automatic) { 280 markShown(config); 281 } 282 }); 283 }; 284 285 $(document).on('click', '[data-wf-popup-id]', function(event) { 286 event.preventDefault(); 287 window.wfShowPopup($(this).data('wf-popup-id'), { 288 automatic: false 289 }); 290 }); 291 292 $(document).on('show.bs.modal shown.bs.modal', '#popup-modal', function() { 293 ensurePopupLayerStyles(); 294 $(this).css('z-index', popupModalZIndex); 295 window.setTimeout(liftPopupBackdrop, 0); 296 }); 297 298 $(document).on('click', '[data-popup-accept]', function(event) { 299 event.preventDefault(); 300 var config = $('#popup-modal').data('wf-popup-config') || {}; 301 if(config.pageId) { 302 markAccepted(config); 303 } 304 $('#popup-modal').modal('hide'); 305 }); 306 307 $(document).on('click', '[data-popup-reject]', function(event) { 308 event.preventDefault(); 309 var rejectUrl = $(this).data('popup-reject-url'); 310 var behaviour = $(this).data('popup-reject-behaviour') || (rejectUrl ? 'redirect' : 'close'); 311 if(behaviour == 'message') { 312 $('#popup-modal').find('[data-popup-reject-message]').removeClass('hidden').trigger('focus'); 313 return; 314 } 315 if(behaviour == 'redirect') { 316 var destination = document.createElement('a'); 317 destination.href = rejectUrl || ''; 318 if(rejectUrl && (destination.protocol == 'https:' || destination.protocol == 'http:')) { 319 window.location.href = destination.href; 320 } 321 return; 322 } 323 $('#popup-modal').modal('hide'); 324 }); 325 326 $(function() { 327 var queue = window.wfAutoPopups || []; 328 for(var i = 0; i < queue.length; i++) { 329 if(shouldShow(queue[i])) { 330 window.setTimeout(function(config) { 331 window.wfShowPopup(config.pageId, $.extend({}, config, { 332 automatic: true 333 })); 334 }, 500, queue[i]); 335 break; 336 } 337 } 338 }); 339})(window, window.jQuery); 340 341// Structural site dialogs use the current page route so page/site visibility stays authoritative. 342(function(window, $) { 343 if(!$) { return; } 344 window.wfShowWebshopOptionsWarning = function(form) { 345 var modal = $('#webshop-options-warning'); 346 if(!modal.length) { 347 modal = $('<div class="modal fade" id="webshop-options-warning" tabindex="-1" role="dialog" aria-labelledby="webshop-options-title" aria-describedby="webshop-options-description" data-site-modal-index="webshop-options" data-site-modal-preserve></div>').appendTo('body'); 348 } 349 if(modal.hasClass('in') || modal.data('site-modal-loading')) { return; } 350 var trigger = $(form).find('button[type="submit"], input[type="submit"]').first()[0]; 351 modal.modal({show:false, backdrop:'static', keyboard:true}).modal('show', trigger); 352 }; 353 function preserveParent(modal, parent) { 354 if(!parent.length) { modal.css('z-index', ''); return; } 355 var state = { 356 parent:parent, focus:document.activeElement, scrollTop:parent.scrollTop(), scrollLeft:parent.scrollLeft(),
357 inert:parent.attr('inert'), hidden:parent.attr('aria-hidden'), padding:document.body.style.paddingRight 358 }; 359 modal.data('site-modal-parent', state); 360 $(document).off('focusin.bs.modal'); 361 parent.attr({'inert':'', 'aria-hidden':'true'}).on('hide.bs.modal.siteSupportingDialog', function(event) { 362 if(event.target === this) { event.preventDefault(); } 363 }); 364 modal.css('z-index', (parseInt(parent.css('z-index'), 10) || 1050) + 20); 365 } 366 function restoreParent(modal) { 367 var state = modal.data('site-modal-parent'); 368 if(!state) { return false; } 369 modal.removeData('site-modal-parent'); 370 var parent = state.parent; 371 parent.off('.siteSupportingDialog'); 372 $.each({inert:state.inert, 'aria-hidden':state.hidden}, function(name, value) { 373 if(value === undefined) { parent.removeAttr(name); } else { parent.attr(name, value); } 374 }); 375 if(parent.hasClass('in') && $.contains(document, parent[0])) { 376 $('body').addClass('modal-open'); 377 document.body.style.paddingRight = state.padding; 378 var instance = parent.data('bs.modal'); 379 if(instance) { instance.enforceFocus(); instance.resize(); } 380 var trigger = modal.data('site-modal-trigger'); 381 var focus = trigger && trigger[0] && $.contains(parent[0], trigger[0]) ? trigger[0] : state.focus; 382 if(focus && $.contains(parent[0], focus)) { focus.focus({preventScroll:true}); } 383 else { parent[0].focus({preventScroll:true}); } 384 parent.scrollTop(state.scrollTop).scrollLeft(state.scrollLeft); 385 } 386 return true; 387 } 388 function eachDraftField(modal, callback) { 389 var occurrences = {}; 390 modal.find('input[name]:not([type="hidden"]):not([type="password"]):not([type="submit"]):not([type="button"]), textarea[name], select[name]').each(function() { 391 var form = this.form; 392 var formKey = form ? (form.id || form.getAttribute('name') || modal.find('form').index(form)) : ''; 393 var choice = this.type === 'checkbox' || this.type === 'radio'; 394 var key = JSON.stringify([formKey, this.name, this.type, choice ? this.value : '']); 395 var occurrence = occurrences[key] || 0; 396 occurrences[key] = occurrence + 1; 397 callback(this, key + ':' + occurrence); 398 }); 399 } 400 $(document).on('show.bs.modal', '[data-site-modal-index]', function(event) { 401 if(event.target !== this) { return; } 402 var modal = $(this); 403 if(modal.data('site-modal-ready')) { return; } 404 event.preventDefault(); 405 if(modal.data('site-modal-loading')) { return; } 406 var trigger = $(event.relatedTarget); 407 var parent = modal.is('[data-site-modal-preserve]') ? $('.modal.in').not(modal).last() : $(); 408 var originalHTML = trigger.html(); 409 var url = new URL(window.location.href); 410 url.hash = ''; 411 url.searchParams.set('site_modal', modal.attr('data-site-modal-index')); 412 if(modal.attr('data-site-modal-page-uid')) { url.searchParams.set('site_modal_page_uid', modal.attr('data-site-modal-page-uid')); } 413 modal.data('site-modal-loading', true); 414 modal.data('site-modal-trigger', trigger); 415 trigger.attr('aria-busy', 'true'); 416 if(trigger.length) { trigger.text('Loading...'); } 417 $('[data-site-modal-error]').remove(); 418 $.ajax({url:url.toString(), dataType:'html', cache:false, timeout:30000}).done(function(html) { 419 try { 420 var response = $('<div>').append($.parseHTML(html, document, true)); 421 var loaded = response.children('.modal').filter(function() { return this.id === modal.attr('id'); }); 422 if(response.children().length !== 1 || loaded.length !== 1 || loaded.children('.modal-dialog').length !== 1) { showError(); return; } 423 if(parent.length && (!parent.hasClass('in') || !$.contains(document, parent[0]))) { showError(); return; } 424 modal.empty().append(loaded.contents()); 425 // Bootstrap 3 caches this node when the empty target is first opened. 426 var instance = modal.data('bs.modal'); 427 if(instance) { instance.$dialog = modal.children('.modal-dialog'); } 428 var draft = modal.data('site-modal-draft') || {}; 429 eachDraftField(modal, function(field, key) { 430 var value = draft[key]; 431 if(!value) { return; } 432 if(field.type === 'file') { 433 if(value.file && field.accept === value.file.accept && field.multiple === value.file.multiple) { $(field).replaceWith(value.file); } 434 } else if(field.type === 'checkbox' || field.type === 'radio') { field.checked = value.checked; } 435 else { $(field).val(value.value); } 436 }); 437 if($.fn.validator) { modal.find('form[data-toggle="validator"]').validator(); } 438 if($.fn.selectpicker) { modal.find('.selectpicker').selectpicker(); } 439 modal.find('.popupme').popover(); 440 modal.find('.tooltipme').tooltip(); 441 if(modal.is('[data-site-modal-preserve]')) { preserveParent(modal, parent); } 442 modal.data('site-modal-ready', true).modal('show', event.relatedTarget); 443 if(parent.length && instance && instance.$backdrop) { instance.$backdrop.css('z-index', (parseInt(modal.css('z-index'), 10) || 1070) - 10); } 444 } catch(error) { modal.removeData('site-modal-ready'); restoreParent(modal); showError(); } 445 }
445).fail(showError).always(function() { 446 modal.removeData('site-modal-loading'); 447 trigger.removeAttr('aria-busy'); 448 if(trigger.length) { trigger.html(originalHTML); } 449 }); 450 function showError() { 451 var error = $('<div class="alert alert-warning" role="alert" tabindex="-1" data-site-modal-error>Unable to load this dialog. Please try again.</div>'); 452 if(trigger.length) { error.insertAfter(trigger); trigger.trigger('focus'); } 453 else { error.insertBefore(modal).trigger('focus'); } 454 } 455 }).on('hidden.bs.modal', '[data-site-modal-index]', function(event) { 456 if(event.target !== this) { return; } 457 var modal = $(this), draft = {}; 458 eachDraftField(modal, function(field, key) { 459 draft[key] = {value:$(field).val(), checked:field.checked, file:field.type === 'file' && field.files.length ? field : null}; 460 }); 461 modal.data('site-modal-draft', draft).removeData('site-modal-ready'); 462 if(restoreParent(modal)) { return; } 463 var trigger = modal.data('site-modal-trigger'); 464 if(trigger) { trigger.trigger('focus'); } 465 }); 466})(window, window.jQuery);
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.