eac8200c7d
For better notification visibility, add notification highlight animation around the screen. Signed-off-by: Victor Seiji Hariki <victorseijih@gmail.com>
201 lines
5.5 KiB
JavaScript
201 lines
5.5 KiB
JavaScript
/**
|
|
* Enum representing the location of the notifications
|
|
* @readonly
|
|
* @enum {string}
|
|
*/
|
|
const NotificationLocation = {
|
|
TOPLEFT: "top-left",
|
|
TOPCENTER: "top-center",
|
|
TOPRIGHT: "top-right",
|
|
BOTTOMLEFT: "bottom-left",
|
|
BOTTOMCENTER: "bottom-center",
|
|
BOTTOMRIGHT: "bottom-right",
|
|
};
|
|
|
|
/**
|
|
* Enum representing notification types
|
|
* @readonly
|
|
* @enum {string}
|
|
*/
|
|
const NotificationType = {
|
|
INFO: "info",
|
|
ERROR: "error",
|
|
WARN: "warn",
|
|
SUCCESS: "success",
|
|
};
|
|
|
|
/**
|
|
* Responsible for the notification system
|
|
*/
|
|
const notifications = {
|
|
/** @type {NotificationLocation} */
|
|
_location: NotificationLocation.BOTTOMLEFT,
|
|
/** @type {NotificationLocation} */
|
|
get location() {
|
|
return this.location;
|
|
},
|
|
/** @type {NotificationLocation} */
|
|
set location(location) {
|
|
this._location = location;
|
|
},
|
|
|
|
// Notification Area Element
|
|
_areaEl: null,
|
|
|
|
// Dialog BG Element
|
|
_dialogBGEl: null,
|
|
// Dialog Element
|
|
_dialogEl: null,
|
|
|
|
/**
|
|
* Creates a simple notification for the user. Equivalent to alert()
|
|
*
|
|
* @param {string | HTMLElement} message Message to display to the user.
|
|
* @param {Object} options Extra options for the notification.
|
|
* @param {NotificationType} options.type Notification type
|
|
* @param {boolean} options.collapsed Whether notification is collapsed by default
|
|
* @param {number} options.timeout Timeout for the notification
|
|
*/
|
|
notify(message, options = {}) {
|
|
defaultOpt(options, {
|
|
type: NotificationType.INFO,
|
|
collapsed: false,
|
|
timeout: config.notificationTimeout,
|
|
});
|
|
|
|
const notificationEl = document.createElement("div");
|
|
notificationEl.classList.add("notification", options.type);
|
|
if (!options.collapsed) notificationEl.classList.add("expanded");
|
|
notificationEl.title = new Date().toISOString();
|
|
notificationEl.addEventListener("click", () =>
|
|
notificationEl.classList.toggle("expanded")
|
|
);
|
|
|
|
const contentEl = document.createElement("div");
|
|
contentEl.classList.add("notification-content");
|
|
contentEl.innerHTML = message;
|
|
|
|
notificationEl.append(contentEl);
|
|
|
|
const closeBtn = document.createElement("button");
|
|
closeBtn.classList.add("notification-closebtn");
|
|
closeBtn.addEventListener("click", () => notificationEl.remove());
|
|
|
|
notificationEl.append(closeBtn);
|
|
|
|
if (
|
|
config.notificationHighlightAnimationDuration &&
|
|
config.notificationHighlightAnimationDuration > 0
|
|
) {
|
|
const notificationHighlightEl = document.createElement("div");
|
|
notificationHighlightEl.style.animationDuration = `${config.notificationHighlightAnimationDuration}ms`;
|
|
notificationHighlightEl.classList.add(
|
|
"notification-highlight",
|
|
`notification-${options.type}`
|
|
);
|
|
|
|
document.body.appendChild(notificationHighlightEl);
|
|
setTimeout(() => {
|
|
notificationHighlightEl.remove();
|
|
}, config.notificationHighlightAnimationDuration);
|
|
}
|
|
|
|
this._areaEl.prepend(notificationEl);
|
|
if (options.timeout)
|
|
setTimeout(() => {
|
|
if (this._areaEl.contains(notificationEl)) {
|
|
notificationEl.remove();
|
|
}
|
|
}, options.timeout);
|
|
},
|
|
|
|
/**
|
|
* Creates a dialog box for the user with set options.
|
|
*
|
|
* @param {string} title The title of the dialog box to be displayed to the user.
|
|
* @param {string | HTMLElement} message The message to be displayed to the user.
|
|
* @param {Object} options Extra options for the dialog.
|
|
* @param {Array<{label: string, value: any}>} options.choices The choices to be displayed to the user.
|
|
*/
|
|
async dialog(title, message, options = {}) {
|
|
defaultOpt(options, {
|
|
// By default, it is a await notifications.dialogation dialog
|
|
choices: [
|
|
{label: "No", value: false},
|
|
{label: "Yes", value: true},
|
|
],
|
|
});
|
|
|
|
const titleEl = this._dialogEl.querySelector(".dialog-title");
|
|
titleEl.textContent = title;
|
|
|
|
const contentEl = this._dialogEl.querySelector(".dialog-content");
|
|
contentEl.innerHTML = message;
|
|
|
|
const choicesEl = this._dialogEl.querySelector(".dialog-choices");
|
|
while (choicesEl.firstChild) {
|
|
choicesEl.firstChild.remove();
|
|
}
|
|
|
|
return new Promise((resolve, reject) => {
|
|
options.choices.forEach((choice) => {
|
|
const choiceBtn = document.createElement("button");
|
|
choiceBtn.textContent = choice.label;
|
|
choiceBtn.addEventListener("click", () => {
|
|
this._dialogBGEl.style.display = "none";
|
|
this._dialogEl.style.display = "none";
|
|
|
|
resolve(choice.value);
|
|
});
|
|
|
|
choicesEl.append(choiceBtn);
|
|
});
|
|
|
|
this._dialogBGEl.style.display = "flex";
|
|
this._dialogEl.style.display = "block";
|
|
});
|
|
},
|
|
};
|
|
var k = 0;
|
|
|
|
window.addEventListener("DOMContentLoaded", () => {
|
|
// Creates the notification area
|
|
const notificationArea = document.createElement("div");
|
|
notificationArea.classList.add(
|
|
"notification-area",
|
|
NotificationLocation.BOTTOMLEFT
|
|
);
|
|
|
|
notifications._areaEl = notificationArea;
|
|
|
|
document.body.appendChild(notificationArea);
|
|
|
|
// Creates the dialog box element
|
|
const dialogBG = document.createElement("div");
|
|
dialogBG.classList.add("dialog-bg");
|
|
dialogBG.style.display = "none";
|
|
|
|
const dialogEl = document.createElement("div");
|
|
dialogEl.classList.add("dialog");
|
|
dialogEl.style.display = "none";
|
|
|
|
const titleEl = document.createElement("div");
|
|
titleEl.classList.add("dialog-title");
|
|
|
|
const contentEl = document.createElement("div");
|
|
contentEl.classList.add("dialog-content");
|
|
|
|
const choicesEl = document.createElement("div");
|
|
choicesEl.classList.add("dialog-choices");
|
|
|
|
dialogEl.append(titleEl);
|
|
dialogEl.append(contentEl);
|
|
dialogEl.append(choicesEl);
|
|
|
|
dialogBG.append(dialogEl);
|
|
|
|
notifications._dialogEl = dialogEl;
|
|
notifications._dialogBGEl = dialogBG;
|
|
|
|
document.body.appendChild(dialogBG);
|
|
});
|