PageSourceSearch

https://kagoafrica.com/transporter/assets/js/CustomAlertify.js?version=3.0.9.1

js kagoafrica.com collected 2026-09-24 14:16:03 UTC 7,162 bytes, 191 lines download raw bytes

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.