1(function (global) { 2 'use strict'; 3 4 // Inject Base Styles 5 const style = document.createElement('style'); 6 style.textContent = ` 7 .custom-alertify-overlay { 8 position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; 9 background: rgba(0, 0, 0, 0.4); display: flex; align-items: center; 10 justify-content: center; z-index: 9999; opacity: 0; 11 transition: opacity 0.2s ease; 12 } 13 .custom-alertify-overlay.show { opacity: 1; } 14 .custom-alertify-dialog { 15 background: #fff; width: 90%; max-width: 400px; padding: 20px; 16 border-radius: 4px; box-shadow: 0 4px 12px rgba(0,0,0,0.15); 17 font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; 18 transform: translateY(-20px); transition: transform 0.2s ease; 19 } 20 .custom-alertify-overlay.show .custom-alertify-dialog { transform: translateY(0); } 21 .custom-alertify-title { font-size: 18px; font-weight: 600; margin: 0 0 10px 0; color: #333; } 22 .custom-alertify-message { font-size: 14px; color: #555; margin-bottom: 20px; line-height: 1.4; } 23 .custom-alertify-buttons { text-align: right; } 24 .custom-alertify-btn { 25 padding: 8px 16px; border: none; border-radius: 3px; font-size: 14px; 26 cursor: pointer; margin-left: 8px; transition: all 0.2s ease; 27 display: inline-flex; align-items: center; gap: 8px; line-height: 1; 28 } 29 .custom-alertify-btn:disabled { opacity: 0.7; cursor: not-allowed; } 30 31 /* Default Button Styles */ 32 .custom-alertify-btn-ok { background: #007bff; color: #fff; } 33 .custom-alertify-btn-ok:hover:not(:disabled) { filter: brightness(0.9); } 34 .custom-alertify-btn-cancel { background: #6c757d; color: #fff; } 35 .custom-alertify-btn-cancel:hover:not(:disabled) { filter: brightness(0.9); } 36 37 /* Loading Spinner */ 38 .custom-alertify-spinner { 39 width: 12px; height: 12px; border: 2px solid rgba(255, 255, 255, 0.4); 40 border-top-color: currentColor; border-radius: 50%; 41 animation: custom-alertify-spin 0.6s linear infinite; 42 } 43 @keyframes custom-alertify-spin { 44 to { transform: rotate(360deg); } 45 } 46 47 /* Toasts */ 48 .custom-alertify-logs { 49 position: fixed; bottom: 16px; right: 16px; z-index: 10000; 50 display: flex; flex-direction: column; gap: 8px; 51 } 52 .custom-alertify-log { 53 padding: 12px 20px; color: #fff; font-size: 14px; border-radius: 4px; 54 font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; 55 box-shadow: 0 2px 8px rgba(0,0,0,0.2); opacity: 0; transform: translateY(20px); 56 transition: all 0.3s ease; max-width: 300px; 57 } 58 .custom-alertify-log.show { opacity: 1; transform: translateY(0); } 59 .custom-alertify-log.success { background: #28a745; } 60 .custom-alertify-log.error { background: #dc3545; } 61 .custom-alertify-log.info { background: #17a2b8; } 62 `; 63 document.head.appendChild(style); 64 65 let logContainer = null; 66 function getLogContainer() { 67 if (!logContainer) { 68 logContainer = document.createElement('div'); 69 logContainer.className = 'custom-alertify-logs'; 70 document.body.appendChild(logContainer); 71 } 72 return logContainer; 73 } 74 75 const CustomAlertify = { 76 _showDialog(title, message, options = {}) { 77 const config = { 78 okText: 'OK', 79 cancelText: 'Cancel', 80 showCancel: true, 81 okColor: null, // e.g., '#dc3545' or 'red' 82 okTextColor: null, // e.g., '#fff' 83 okClass: '', // custom class name 84 onOk: null, 85 ...options 86 }; 87 88 return new Promise((resolve) => { 89 const overlay = document.createElement('div'); 90 overlay.className = 'custom-alertify-overlay'; 91 92 const cancelButtonHtml = config.showCancel 93 ? `<button class="custom-alertify-btn custom-alertify-btn-cancel">${config.cancelText}</button>` 94 : ''; 95 96 // Build inline styles dynamically if custom colors are provided 97 let customStyles = ''; 98 if (config.okColor) customStyles += `background-color: ${config.okColor}; `; 99 if (config.okTextColor) customStyles += `color: ${config.okTextColor}; `; 100 101 overlay.innerHTML = ` 102 <div class="custom-alertify-dialog"> 103 <h3 class="custom-alertify-title">${title}</h3> 104 <div class="custom-alertify-message">${message}</div> 105 <div class="custom-alertify-buttons"> 106 ${cancelButtonHtml} 107 <button class="custom-alertify-btn custom-alertify-btn-ok ${config.okClass}" style="${customStyles}">
108 <span class="btn-text">${config.okText}</span> 109 </button> 110 </div> 111 </div> 112 `; 113 114 document.body.appendChild(overlay); 115 requestAnimationFrame(() => overlay.classList.add('show')); 116 117 const okBtn = overlay.querySelector('.custom-alertify-btn-ok'); 118 const cancelBtn = overlay.querySelector('.custom-alertify-btn-cancel'); 119 120 const close = (result) => { 121 overlay.classList.remove('show'); 122 setTimeout(() => { 123 document.body.removeChild(overlay); 124 resolve(result); 125 }, 200); 126 }; 127 128 okBtn.addEventListener('click', async () => { 129 if (typeof config.onOk === 'function') { 130 okBtn.disabled = true; 131 if (cancelBtn) cancelBtn.disabled = true; 132 133 const spinner = document.createElement('span'); 134 spinner.className = 'custom-alertify-spinner'; 135 okBtn.prepend(spinner); 136 137 try { 138 const result = await config.onOk(); 139 if (result !== false) { 140 close(true); 141 } else { 142 spinner.remove(); 143 okBtn.disabled = false; 144 if (cancelBtn) cancelBtn.disabled = false; 145 } 146 } catch (err) { 147 spinner.remove(); 148 okBtn.disabled = false; 149 if (cancelBtn) cancelBtn.disabled = false; 150 console.error(err); 151 } 152 } else { 153 close(true); 154 } 155 }); 156 157 if (config.showCancel) { 158 cancelBtn.addEventListener('click', () => close(false)); 159 } 160 }); 161 }, 162 163 alert(title, message, options = {}) { 164 return this._showDialog(title, message, { showCancel: false, ...options }); 165 }, 166 167 confirm(title, message, options = {}) { 168 return this._showDialog(title, message, { showCancel: true, ...options }); 169 }, 170 171 message(msg, type = 'info', wait = 3000) { 172 const container = getLogContainer(); 173 const log = document.createElement('div'); 174 log.className = `custom-alertify-log ${type}`; 175 log.innerHTML = msg; 176 177 container.appendChild(log); 178 requestAnimationFrame(() => log.classList.add('show')); 179 180 setTimeout(() => { 181 log.classList.remove('show'); 182 setTimeout(() => log.remove(), 300); 183 }, wait); 184 }, 185 186 success(msg, wait) { this.message(msg, 'success', wait); }, 187 error(msg, wait) { this.message(msg, 'error', wait); } 188 }; 189 190 global.customAlertify = CustomAlertify; 191})(window);
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.