1window.__ = function(key, replacements = {}) { 2 let translation = key.split('.').reduce((obj, i) => obj?.[i], Habersoft.translations); 3 4 let template = translation || key; 5 6 Object.entries(replacements).forEach(([placeholder, value]) => { 7 const regex = new RegExp(':' + placeholder, 'g'); 8 template = template.replace(regex, value); 9 }); 10 11 return template; 12}; 13 14window.throttle = function(func, wait) { 15 let timeout = null; 16 let lastArgs = null; 17 let lastContext = null; 18 let lastCallTime = 0; 19 20 function invoke() { 21 lastCallTime = Date.now(); 22 const args = lastArgs; 23 const context = lastContext; 24 lastArgs = null; 25 lastContext = null; 26 timeout = null; 27 func.apply(context, args); 28 } 29 30 return function(...args) { 31 const now = Date.now(); 32 const remaining = wait - (now - lastCallTime); 33 lastArgs = args; 34 lastContext = this; 35 36 if (remaining <= 0) { 37 if (timeout) { 38 clearTimeout(timeout); 39 timeout = null; 40 } 41 invoke(); 42 } 43 else if (!timeout) { 44 timeout = setTimeout(invoke, remaining); 45 } 46 }; 47};
48 49window.debounce = function(func, wait) { 50 let timeout; 51 return function() { 52 const context = this; 53 const args = arguments; 54 clearTimeout(timeout); 55 timeout = setTimeout(() => func.apply(context, args), wait); 56 }; 57}; 58 59window.showToast = function(type, message) { 60 let toastContainer = $('.toast-container'); 61 if (toastContainer.length === 0) { 62 toastContainer = $('<div class="toast-container position-fixed bottom-0 end-0 p-3" style="z-index: 1055;"></div>'); 63 $('body').append(toastContainer); 64 } else { 65 toastContainer.empty(); 66 } 67 if(type==='clear'){ 68 return; 69 } 70 let toastHtml = '<div class="toast align-items-center text-bg-' + type + ' border-0 show" role="alert" aria-live="assertive" aria-atomic="true" data-bs-autohide="true" data-bs-delay="1000">' + 71 '<div class="d-flex">' + 72 '<div class="toast-body">' + message + '</div>' + 73 '<button type="button" class="btn-close me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>' + 74 '</div>' + 75 '</div>'; 76 let $toast = $(toastHtml); 77 toastContainer.append($toast); 78 let bsToast = new bootstrap.Toast($toast[0]); 79 bsToast.show(); 80 $toast.on('hidden.bs.toast', function() { 81 $(this).remove(); 82 }); 83}; 84 85window.escapeHtml = function(str) { 86 if (str === null || str === undefined) return ''; 87 return String(str) 88 .replace(/&/g, '&') 89 .replace(/</g, '<') 90 .replace(/>/g, '>') 91 .replace(/"/g, '"') 92 .replace(/'/g, '''); 93};
94 95window.escapeAttr = function(str) { 96 if (str === null || str === undefined) return ''; 97 return String(str).replace(/"/g, '"'); 98};
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.