Skip to content

Commit 1af5b55

Browse files
committed
refactor(ui): Switched alert system to template cloning
- Replaced Handlebars-based alert rendering in `csk.ui.alert` with native `<template>` cloning. - Added `csk.ui.autoHideAlert()` to handle automatic hiding of dynamically added alerts. - Bumped version to `1.4.4`.
1 parent aba713f commit 1af5b55

File tree

3 files changed

+77
-72
lines changed

3 files changed

+77
-72
lines changed

js/admin.js

Lines changed: 75 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
*/
3030
csk.ui = {
3131
scrollToTopVisible: false,
32+
alertClasses: ["info", "success", "warning", "danger"],
33+
3234
/**
3335
* Confirmation alert using either bootbox or default alert.
3436
* @since 1.20
@@ -75,72 +77,73 @@
7577
falseCallback(true);
7678
}
7779
},
78-
/** Alert (Notification). */
79-
alert: function(message, type) {
80-
if (!message.length) {
81-
return false;
82-
}
83-
type = type || 'info';
84-
if (type === "error" || type === "critical") {
85-
type = "danger";
86-
}
8780

81+
/**
82+
* Alert (notification)
83+
* @since 1.20
84+
* @param {string} message Message to display.
85+
* @param {string} type Alert type('danger', 'warning', 'info', or 'success')
86+
* @return {void}
87+
*/
88+
alert: function(message, type = "info") {
89+
// Make sure a valid string message is passed.
90+
if (typeof message !== "string" || !message.length) return;
91+
92+
// Normalize and validate alert type
93+
type = type?.toLowerCase() || 'info';
94+
type = (type === "error" || type === "critical") ? "danger" : (csk.ui.alertClasses.includes(type) ? type : "info");
95+
96+
// Case 1: Toastr is available?
8897
if (typeof toastr !== "undefined") {
89-
switch (type) {
90-
case "success":
91-
toastr.success(message);
92-
break;
93-
case "error":
94-
case "danger":
95-
toastr.error(message);
96-
break;
97-
case "warning":
98-
toastr.warning(message);
99-
break;
100-
case "info":
101-
default:
102-
toastr.info(message);
103-
break;
104-
}
98+
(toastr[type] || toastr.info).call(toastr, message.trim());
10599
return;
106100
}
107101

108-
/**
109-
* If Handlebars is loaded, we already have an alert template
110-
* stored within the dashboard default layout. So we use it.
111-
*/
112-
if (typeof Handlebars === "object") {
113-
/** We store any old alert so we can remove it later. */
114-
var oldAlert = $("#csk-alert"),
115-
alertSource = document.getElementById("csk-alert-template").innerHTML,
116-
alertTemplate = Handlebars.compile(alertSource);
117-
118-
/** Compile the alert. */
119-
var alertCompiled = alertTemplate({
120-
message: message,
121-
type: type
122-
});
102+
// Case 2: Use provided alter template.
103+
const clone = document.getElementById("csk-alert-template")?.content?.querySelector('div')?.cloneNode(true);
104+
if (clone) {
105+
// Add alert Bootstrap alert classes then add message.
106+
clone.classList.add("alert", "alert-" + type, "alert-dismissible");
107+
clone.prepend(message.trim()); // Add message
123108

124-
/** If we have an old alert, remove it first. */
125-
if (oldAlert.length) {
126-
oldAlert.fadeOut(function() {
127-
$(this).remove();
128-
$(alertCompiled).prependTo("#wrapper > .container");
129-
});
130-
} else {
131-
$(alertCompiled).prependTo("#wrapper > .container");
132-
}
109+
// Prepend cloned alert to first '.container' inside '#wrapper'.
110+
(document.querySelector("#wrapper>.container") || document.body).prepend(clone);
111+
csk.ui.autoHideAlert($(clone));
112+
return;
113+
}
133114

115+
// Case 3: Strip any HTML from message use default 'alert()'.
116+
window.alert(message.replace(/(<([^>]+)>)/ig, "").trim());
117+
},
118+
119+
/**
120+
* Auto-hides alerts if needed.
121+
* @since 3.11.0
122+
* @param {HTMLElement} $alert
123+
* @return {void}
124+
*/
125+
autoHideAlert: function($alert) {
126+
// Skip keep/danger/warning
127+
if ($alert.hasClass("alert-keep") || $alert.hasClass("alert-danger") || $alert.hasClass("alert-warning")) {
134128
return;
135129
}
136130

137-
/**
138-
* Otherwise, we make sure to strip any HTML tags from the message
139-
* and simply use browser's default alert.
140-
*/
141-
alert(message.replace(/(<([^>]+)>)/ig, ""));
131+
let len = $alert.text().trim().length;
132+
let after = Math.min(10000, 4000 + (len * 50));
133+
134+
$alert.delay(after).slideUp(500, function () {
135+
$alert.alert("close").remove();
136+
});
142137
},
143-
/** Reload main page parts. */
138+
139+
/**
140+
* Reloads given element.
141+
* @since 1.20
142+
* @param {string} el Query selector.
143+
* @param {boolean} navbar Whether to reload navbar.
144+
* @param {Function} callback Callback to execute after reload.
145+
* @return {void}
146+
*/
144147
reload: function(el, navbar, callback) {
145148
/** If no element is provided, we use "#wrapper". */
146149
el = el || "#wrapper";
@@ -152,6 +155,7 @@
152155
}
153156
$(el).load(csk.config.currentURL + " " + el + " > *", callback);
154157
},
158+
155159
/**
156160
* Check if an element is in viewport.
157161
* @since 2.0
@@ -160,6 +164,7 @@
160164
var $that = el.getBoundingClientRect();
161165
return $that.bottom >= 0 && $that.right >= 0 && $that.top <= (window.innerHeight || document.documentElement.clientHeight) && $that.left <= (window.innerWidth || document.documentElement.clientWidth);
162166
},
167+
163168
/**
164169
* Function to add an event listener.
165170
* @since 2.0
@@ -171,6 +176,7 @@
171176
window.attachEvent("on" + event, callback);
172177
}
173178
},
179+
174180
/**
175181
* Adds a delegated event listener to the document.
176182
*
@@ -195,6 +201,7 @@
195201
}
196202
});
197203
},
204+
198205
/**
199206
* Lazy load images.
200207
* @since 2.0
@@ -216,6 +223,7 @@
216223
}
217224
}
218225
},
226+
219227
/**
220228
* Scroll to top.
221229
* @since 3.9.6
@@ -234,6 +242,7 @@
234242
}
235243
}
236244
},
245+
237246
/**
238247
* Element fade out.
239248
* @since 3.9.6
@@ -248,6 +257,7 @@
248257
}
249258
})();
250259
},
260+
251261
/**
252262
* Element fade in.
253263
* @since 3.9.6
@@ -263,6 +273,7 @@
263273
}
264274
})();
265275
},
276+
266277
/**
267278
* Splits given string into an array.
268279
* @since 2.16
@@ -277,6 +288,7 @@
277288
}
278289
return fields;
279290
},
291+
280292
/**
281293
* Returns an array of GET parameters.
282294
* @since 2.16
@@ -292,6 +304,7 @@
292304
}
293305
return params;
294306
},
307+
295308
/**
296309
* Returns a GET parameter.
297310
* @since 2.16
@@ -309,6 +322,7 @@
309322
}
310323
return false;
311324
},
325+
312326
/**
313327
* Copy to clipboard.
314328
* @since 2.18
@@ -321,6 +335,7 @@
321335
navigator.clipboard.writeText(copyText);
322336
csk.ui.alert(csk.i18n.media.copied, "success");
323337
},
338+
324339
/**
325340
* Disable selection.
326341
* @since 2.166
@@ -331,13 +346,15 @@
331346
document.body.style.userSelect = "none";
332347
}
333348
},
349+
334350
/**
335351
* Enable selection.
336352
* @since 2.166
337353
*/
338354
selectOn: function(e) {
339355
document.body.style.userSelect = "";
340356
},
357+
341358
/**
342359
* DataTable.
343360
* @since 3.9.8
@@ -363,6 +380,7 @@
363380
};
364381
return $(selector).DataTable($.extend(true, {}, defaults, options));
365382
},
383+
366384
/**
367385
* Highlights and element referenced by the URL hash (element ID).
368386
* Smooth scroll included. Silently bails if no match.
@@ -385,6 +403,7 @@
385403
// Remove the class after blink sequence
386404
setTimeout(() => target.classList.remove('highlight-focus'), 4000);
387405
},
406+
388407
/**
389408
* Enables or disable one or more elements.
390409
* @since 3.10.1
@@ -760,21 +779,7 @@
760779
* @since 2.16
761780
*/
762781
$(".alert-dismissible").each(function() {
763-
let $alert = $(this);
764-
765-
// Skip 'alert-keep', 'alert-danger' and 'alert-warning'
766-
if ($alert.hasClass("alert-keep") || $alert.hasClass("alert-danger") || $alert.hasClass("alert-warning")) {
767-
return;
768-
}
769-
770-
// Calculate display time based on content length
771-
let len = $alert.text().trim().length;
772-
let after = Math.min(10000, 4000 + (len * 50)); // Max 10 sec.
773-
774-
// Auto-close after calculated delay
775-
$alert.delay(after).slideUp(500, function() {
776-
$alert.alert("close").remove();
777-
});
782+
csk.ui.autoHideAlert($(this));
778783
});
779784

780785
/**

0 commit comments

Comments
 (0)