1(function () { 2 'use strict'; 3 4 var config = window.HKE_MCM_V2_CONTACT || {}; 5 var endpoint = config.endpoint || ''; 6 var selector = '[data-hke-mcm-contact="1"]'; 7 8 if (!endpoint || !window.fetch) { 9 return; 10 } 11 12 function getPayload(el) { 13 return { 14 type: el.getAttribute('data-hke-mcm-type') || '', 15 context: el.getAttribute('data-hke-mcm-context') || 'profile', 16 route: el.getAttribute('data-hke-mcm-route') || '', 17 geo: el.getAttribute('data-hke-mcm-geo') || 'HongKong', 18 mode: 'js', 19 ref_page: window.location.href 20 }; 21 } 22 23 function extractUrl(payload) { 24 if (!payload) { 25 return ''; 26 } 27 28 if (typeof payload.url === 'string') { 29 return payload.url; 30 } 31 32 if (payload.data && typeof payload.data.url === 'string') { 33 return payload.data.url; 34 } 35 36 return ''; 37 } 38 39 function openBlankWindow() { 40 var popup = null; 41 42 try { 43 popup = window.open('about:blank', '_blank'); 44 if (popup) { 45 popup.opener = null; 46 } 47 } catch (error) { 48 popup = null; 49 } 50 51 return popup; 52 } 53 54 function encodePayload(payload) { 55 var pairs = []; 56 57 Object.keys(payload).forEach(function (key) { 58 pairs.push(encodeURIComponent(key) + '=' + encodeURIComponent(payload[key])); 59 }); 60 61 return pairs.join('&'); 62 } 63 64 function withQuery(url, payload) { 65 var query = encodePayload(payload); 66 var separator = url.indexOf('?') === -1 ? '?' : '&'; 67 68 return url + separator + query; 69 } 70 71 function navigateTo(url, popup) { 72 if (!url) { 73 if (popup) { 74 popup.close(); 75 } 76 return; 77 } 78 79 if (popup) { 80 popup.location.href = url; 81 return; 82 } 83 84 window.location.href = url; 85 } 86 87 function resolveContact(el) { 88 if (el.getAttribute('aria-busy') === 'true') { 89 return; 90 } 91 92 el.setAttribute('aria-busy', 'true'); 93 var popup = openBlankWindow(); 94 95 fetch(withQuery(endpoint, getPayload(el)), { 96 method: 'POST', 97 credentials: 'same-origin', 98 headers: { 99 'Accept': 'application/json' 100 } 101 }) 102 .then(function (response) { 103 if (!response.ok) { 104 throw new Error('MCM contact request failed'); 105 } 106 107 return response.json(); 108 }) 109 .then(function (payload) { 110 navigateTo(extractUrl(payload), popup); 111 }) 112 .catch(function () { 113 if (popup) { 114 popup.close(); 115 } 116 }) 117 .finally(function () { 118 el.removeAttribute('aria-busy'); 119 }); 120 } 121 122 document.addEventListener('click', function (event) { 123 var el = event.target.closest(selector); 124 if (!el) { 125 return; 126 } 127 128 event.preventDefault(); 129 resolveContact(el); 130 }); 131 132 document.addEventListener('keydown', function (event) { 133 if (event.key !== 'Enter' && event.key !== ' ') { 134 return; 135 } 136 137 var el = event.target.closest(selector); 138 if (!el) { 139 return; 140 } 141 142 event.preventDefault(); 143 resolveContact(el); 144 }); 145}());
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.