1window.helper = (() => { 2 const alertTimeouts = {}; 3 4 function showAlert({ 5 message, 6 type = 'info', 7 autoDismiss = 5000, 8 containerSelector = 'body', 9 dismissible = true, 10 additionalClasses = '', 11 id = 'custom-alert', 12 refresh = false, 13 }) { 14 if (!message){ 15 return; 16 } 17 18 const container = document.querySelector(containerSelector); 19 if (!container){ 20 return; 21 } 22 23 const isSuccess = type === 'success'; 24 const iconClass = isSuccess ? 'fa-check-circle' : 'fa-ban'; 25 const alertClass = isSuccess ? 'alert-success' : 'alert-danger'; 26 27 // Remove existing alert if present 28 const existingAlert = document.getElementById(id); 29 if (existingAlert) { 30 clearTimeout(alertTimeouts[id]); 31 existingAlert.remove(); 32 } 33 34 const alertDiv = document.createElement('div'); 35 alertDiv.id = id; 36 alertDiv.className = `alert ${alertClass} ${dismissible ? 'alert-dismissible' : ''} ${additionalClasses}`; 37 alertDiv.setAttribute('role', 'alert'); 38 39 // Create icon element 40 const iconElement = document.createElement('i'); 41 iconElement.className = `fa ${iconClass} mr-1`; 42 43 // Create message text node to prevent HTML injection 44 const messageText = document.createTextNode(` ${message}`); 45 46 // Append icon and message safely 47 alertDiv.appendChild(iconElement); 48 alertDiv.appendChild(messageText); 49 50 // Dismiss button 51 if (dismissible) { 52 const btn = document.createElement('button'); 53 btn.type = 'button'; 54 btn.className = 'close'; 55 btn.setAttribute('data-dismiss', 'alert'); 56 btn.setAttribute('aria-hidden', 'true'); 57 btn.innerHTML = '×'; 58 btn.onclick = () => { 59 alertDiv.remove(); 60 if (refresh) { 61 window.location.reload(true); 62 } 63 }; 64 alertDiv.appendChild(btn); 65 } 66 67 container.prepend(alertDiv); 68 69 // Auto-dismiss after timeout 70 if (autoDismiss !== null && !isNaN(autoDismiss) && autoDismiss > 0) { 71 alertTimeouts[id] = setTimeout(() => { 72 alertDiv.classList.remove('show'); 73 alertDiv.classList.add('hide'); 74 setTimeout(() => { 75 alertDiv.remove(); 76 if (refresh) { 77 window.location.reload(true); 78 } 79 }, 200); 80 }, autoDismiss); 81 } 82 } 83 84 const globalLoader = { 85 show: function () { 86 const loader = document.getElementById('global-loader'); 87 if (loader) { 88 loader.style.display = 'flex'; 89 } 90 }, 91 92 hide: function () { 93 const loader = document.getElementById('global-loader'); 94 if (loader) { 95 loader.style.display = 'none'; 96 } 97 } 98 }; 99 100 /** 101 * Input restrictions 102 */ 103 const restrictions = { 104 "only-numbers": "0-9", 105 "only-letters": "a-zA-Z", 106 "only-alphanum": "a-zA-Z0-9", 107 "only-decimal": "0-9\\.", // numbers + dot 108 "only-hex": "0-9a-fA-F", // hexadecimal
109 "only-username": "a-zA-Z0-9_-", // username chars 110 }; 111 112 function applyRestriction(el, pattern) { 113 if (!pattern) return; 114 el.value = el.value.replace(new RegExp(`[^${pattern}]`, 'g'), ''); 115 } 116 117 function getPattern(el) { 118 // Priority: class restriction â data-allow attribute 119 for (let cls in restrictions) { 120 if (el.classList.contains(cls)) return restrictions[cls]; 121 } 122 return el.getAttribute("data-allow"); 123 } 124 125 function initRestrictions() { 126 ["input", "paste"].forEach(evt => { 127 document.addEventListener(evt, (e) => { 128 const el = e.target; 129 if (!(el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement)) return; 130 131 const pattern = getPattern(el); 132 if (pattern) { 133 // Use setTimeout for paste to allow value update 134 evt === "paste" ? setTimeout(() => applyRestriction(el, pattern), 0) : applyRestriction(el, pattern); 135 } 136 }); 137 }); 138 } 139 140 // Run immediately 141 initRestrictions(); 142 143 return { 144 showAlert, 145 globalLoader, 146 addRestriction: (className, regex) => { restrictions[className] = regex; }, 147 }; 148})();
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.