1(function () { 2 'use strict'; 3 4 var selector = '[data-resource-gate]'; 5 var dialog; 6 var frame; 7 var lastTrigger; 8 9 function sameSitePdf(value) { 10 try { 11 var url = new URL(value, window.location.href); 12 return /(^|\.)tricliniclabs\.com$/i.test(url.hostname) && 13 /\.pdf$/i.test(url.pathname) ? url.href : ''; 14 } catch (error) { 15 return ''; 16 } 17 } 18 19 function buildGateUrl(trigger) { 20 var id = (trigger.getAttribute('data-resource-id') || '').trim(); 21 var catalog = window.TriclinicResourceCatalog || {}; 22 var resource = catalog[id]; 23 if (!resource || !sameSitePdf(resource.url) || !resource.title) { 24 return ''; 25 } 26 27 var gate = new URL('/resource-access.html', window.location.origin); 28 gate.searchParams.set('resource_id', id); 29 gate.searchParams.set('source_page', window.location.pathname); 30 var attribution = window.TriclinicAttribution || {}; 31 [ 32 'gclid', 33 'gbraid', 34 'wbraid', 35 'utm_source', 36 'utm_medium', 37 'utm_campaign', 38 'utm_term', 39 'utm_content', 40 'landing_page', 41 'referrer' 42 ].forEach(function (key) { 43 var value = (attribution[key] || '').trim(); 44 if (value) { 45 gate.searchParams.set(key, value); 46 } 47 }); 48 return gate.href; 49 } 50 51 function ensureDialog() { 52 if (dialog) { 53 return; 54 } 55 56 dialog = document.createElement('dialog'); 57 dialog.className = 'resource-gate-dialog'; 58 dialog.setAttribute('aria-labelledby', 'resource-gate-dialog-title'); 59 dialog.innerHTML = 60 '<div class="resource-gate-dialog-shell">' + 61 '<div class="resource-gate-dialog-header">' + 62 '<strong id="resource-gate-dialog-title">Access technical resource</strong>' + 63 '<button class="resource-gate-close" type="button" aria-label="Close resource access form">Ã</button>' + 64 '</div>' + 65 '<iframe class="resource-gate-frame" title="Technical resource access form"></iframe>' + 66 '</div>'; 67 document.body.appendChild(dialog); 68 frame = dialog.querySelector('.resource-gate-frame'); 69 70 dialog.querySelector('.resource-gate-close').addEventListener('click', function () { 71 dialog.close(); 72 }); 73 dialog.addEventListener('close', function () { 74 document.documentElement.classList.remove('resource-gate-lock'); 75 frame.removeAttribute('src'); 76 if (lastTrigger) { 77 lastTrigger.focus(); 78 } 79 }); 80 dialog.addEventListener('cancel', function () { 81 document.documentElement.classList.remove('resource-gate-lock'); 82 }); 83 } 84 85 document.addEventListener('click', function (event) { 86 var trigger = event.target.closest(selector); 87 if (!trigger) { 88 return; 89 } 90 91 var gateUrl = buildGateUrl(trigger); 92 if (!gateUrl || typeof HTMLDialogElement === 'undefined') { 93 return; 94 } 95 96 event.preventDefault(); 97 ensureDialog(); 98 lastTrigger = trigger; 99 frame.src = gateUrl; 100 document.documentElement.classList.add('resource-gate-lock'); 101 dialog.showModal(); 102 }); 103 104 window.addEventListener('message', function (event) { 105 if (event.origin !== window.location.origin || !event.data || event.data.type !== 'triclinic-resource-ready') { 106 return; 107 } 108 var resourceUrl = sameSitePdf(event.data.resourceUrl || ''); 109 if (!resourceUrl) { 110 return; 111 } 112 if (dialog && dialog.open) { 113 dialog.close(); 114 } 115 window.location.assign(resourceUrl); 116 }); 117})();
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.