1function ready(callbackFunc) { 2 if (document.readyState !== 'loading') { 3 // Document is already ready, call the callback directly 4 callbackFunc(); 5 } else if (document.addEventListener) { 6 // All modern browsers to register DOMContentLoaded 7 document.addEventListener('DOMContentLoaded', callbackFunc); 8 } 9} 10 11// global loading state 12document.onreadystatechange = function () { 13 if (document.readyState !== "complete") { 14 document.querySelector("body").classList.add('is-loading'); 15 } else { 16 document.querySelector("body").classList.remove('is-loading'); 17 } 18}; 19 20function formatBytes(a,b=2,k=1024){with(Math){let d=floor(log(a)/log(k));return 0==a?"0 Bytes":parseFloat((a/pow(k,d)).toFixed(max(0,b)))+" "+["Bytes","KB","MB","GB","TB","PB","EB","ZB","YB"][d]}} 21 22function formatMetricUnit(n, unit, b=2) { 23 with(Math) { 24 if(unit == 'g') { 25 var ranges = [ 26 { divider: 1e6 , suffix: 't' }, 27 { divider: 1e3 , suffix: 'kg' }, 28 { divider: 1 , suffix: 'g' } 29 ]; 30 } 31 if(unit == 'Ah') { 32 var ranges = [ 33 { divider: 1e6 , suffix: 'MAh' }, 34 { divider: 1e3 , suffix: 'kAh' }, 35 { divider: 1 , suffix: 'Ah' }, 36 { divider: 0.001 , suffix: 'mAh' } 37 ]; 38 } 39 for (var i = 0; i < ranges.length; i++) { 40 if (n >= ranges[i].divider) { 41 return ((n / ranges[i].divider).toFixed(max(0,b))).toString() + ' ' + ranges[i].suffix; 42 } 43 } 44 return n.toString(); 45 } 46} 47 48function rawurlencode (str) { 49 // discuss at: https://locutus.io/php/rawurlencode/ 50 // original by: Brett Zamir (https://brett-zamir.me) 51 // input by: travc 52 // input by: Brett Zamir (https://brett-zamir.me) 53 // input by: Michael Grier 54 // input by: Ratheous 55 // bugfixed by: Kevin van Zonneveld (https://kvz.io) 56 // bugfixed by: Brett Zamir (https://brett-zamir.me) 57 // bugfixed by: Joris 58 // reimplemented by: Brett Zamir (https://brett-zamir.me) 59 // reimplemented by: Brett Zamir (https://brett-zamir.me) 60 // note 1: This reflects PHP 5.3/6.0+ behavior 61 // note 1: Please be aware that this function expects \ 62 // note 1: to encode into UTF-8 encoded strings, as found on 63 // note 1: pages served as UTF-8 64 // example 1: rawurlencode('Kevin van Zonneveld!') 65 // returns 1: 'Kevin%20van%20Zonneveld%21' 66 // example 2: rawurlencode('https://kvz.io/') 67 // returns 2: 'https%3A%2F%2Fkvz.io%2F' 68 // example 3: rawurlencode('https://www.google.nl/search?q=Locutus&ie=utf-8') 69 // returns 3: 'https%3A%2F%2Fwww.google.nl%2Fsearch%3Fq%3DLocutus%26ie%3Dutf-8' 70 str = (str + '') 71 // Tilde should be allowed unescaped in future versions of PHP (as reflected below), 72 // but if you want to reflect current 73 // PHP behavior, you would need to add ".replace(/~/g, '%7E');" to the following. 74 return encodeURIComponent(str) 75 .replace(/!/g, '%21') 76 .replace(/'/g, '%27') 77 .replace(/\(/g, '%28') 78 .replace(/\)/g, '%29') 79 .replace(/\*/g, '%2A') 80} 81 82async function trafficSubreportLoader(tr_id, url) { 83 element = document.getElementById(tr_id); 84 if(element.classList.contains("is-subreported")) { 85 return false; 86 } else { 87 try { 88 element.classList.add('is-loading'); 89 const response = await fetch(url, { 90 method: "get", 91 headers: { 92 "Content-Type": "application/json", 93 "X-Requested-With": "XMLHttpRequest" 94 } 95 }); 96 const html = await response.text(); 97 element.classList.remove('is-loading'); 98 element.classList.add('is-subreported'); 99 element.insertAdjacentHTML("afterend", html); 100 } catch (error) { 101 console.error('Error:', error); 102 element.classList.remove('is-loading'); 103 } 104 } 105} 106 107ready(function() { 108 109 /* captcha reload controls */ 110 function reloadCaptchaImage(image) { 111 const source = image.getAttribute('data-captcha-url') || image.getAttribute('src'); 112 if (!source) { 113 return; 114 } 115 116 const url = new URL(source, window.location.href); 117 url.searchParams.set('_', Date.now().toString()); 118 image.setAttribute('src', url.toString()); 119 } 120 121 document.querySelectorAll('[data-captcha-image]').forEach(image => { 122 image.addEventListener('click', function() { 123 reloadCaptchaImage(image); 124 }); 125 }); 126 127 document.querySelectorAll('[data-captcha-reload]').forEach(button => { 128 button.addEventListener('click', function() { 129 const target = button.getAttribute('data-captcha-target'); 130 const image = target ? document.querySelector(target) : null; 131 if (image) { 132 reloadCaptchaImage(image); 133 } 134 }); 135 }); 136 137 /* toggle [data-toggle-id] */ 138 const idToggles = document.querySelectorAll('[data-toggle-id]');
139 idToggles.forEach(element => { 140 element.addEventListener('click', function() { 141 element.classList.toggle('toggled'); 142 container = element.getAttribute('data-toggle-id'); 143 document.getElementById(container).classList.toggle('toggled'); 144 }); 145 }); 146 147 /* accordion dt[data-toggle] */ 148 const dtToggle = document.querySelectorAll('dt[data-toggle]'); 149 dtToggle.forEach(element => { 150 element.classList.add('toggable'); 151 element.addEventListener('click', function() { 152 element.classList.toggle('toggled'); 153 toggleName = element.getAttribute('data-toggle'); 154 document.querySelectorAll('dd[data-toggle='+toggleName+']').forEach(e => { 155 e.classList.toggle('toggled'); 156 }); 157 }); 158 }); 159 160 /* fetch me if you can [data-fetch] */ 161 const fetches = document.querySelectorAll('[data-fetch]'); 162 fetches.forEach(element => { 163 fetchReplace(element.getAttribute('data-fetch'), element); 164 }); 165 166 async function fetchReplace(url, element) { 167 element.classList.add('fetching'); 168 try { 169 const response = await fetch(url, { 170 method: "get", 171 headers: { 172 "Content-Type": "application/json", 173 "X-Requested-With": "XMLHttpRequest" 174 } 175 }); 176 const html = await response.text(); 177 element.classList.toggle('fetching'); 178 element.innerHTML = html; 179 } catch (error) { 180 element.classList.toggle('fetching'); 181 console.error('Error:', error); 182 } 183 } 184 185 // toggle project attribute 186 document.querySelectorAll('.toggle-attribute').forEach(function(element) { 187 element.addEventListener('change', function() { 188 const dataProjectUuid = this.getAttribute('data-project-uuid'); 189 const dataAttributeKey = this.getAttribute('data-attribute-key'); 190 const dataAttributeValue = this.type === 'checkbox' ? (this.checked ? '1' : '0') : this.value; 191 const dataUrl = this.getAttribute('data-url'); 192 fetch(dataUrl, { 193 method: 'POST', 194 headers: { 195 'Content-Type': 'application/json', 196 'X-Requested-With': 'XMLHttpRequest', 197 //'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content') 198 }, 199 body: JSON.stringify({ 200 project_uuid: dataProjectUuid, 201 attribute_key: dataAttributeKey, 202 attribute_value: dataAttributeValue 203 }) 204 }).then(response => response.json()) 205 .then(data => { 206 if (!data.success) { 207 alert(data.message); 208 } 209 }); 210 }); 211 }); 212 213 /* fix for 100vh on mobile */ 214 const appHeight = () => { 215 const doc = document.documentElement 216 doc.style.setProperty('--app-height', '${window.innerHeight}px') 217 } 218 window.addEventListener('resize', appHeight) 219 appHeight(); 220 221});
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.