213 lines
5.9 KiB
JavaScript
213 lines
5.9 KiB
JavaScript
(function() {
|
|
'use strict';
|
|
|
|
/**
|
|
*
|
|
* Alerts Utility
|
|
* makes alerts interactive
|
|
*
|
|
* Attribute: uw-alerts
|
|
*
|
|
* Types of alerts:
|
|
* [default]
|
|
* Regular Info Alert
|
|
* Disappears automatically after 30 seconds
|
|
* Disappears after x seconds if explicitly specified via data-decay='x'
|
|
* Can be told not to disappear with data-decay='0'
|
|
*
|
|
* [success]
|
|
* Currently no special visual appearance
|
|
* Disappears automatically after 30 seconds
|
|
*
|
|
* [warning]
|
|
* Will be coloured warning-orange regardless of user's selected theme
|
|
* Does not disappear
|
|
*
|
|
* [error]
|
|
* Will be coloured error-red regardless of user's selected theme
|
|
* Does not disappear
|
|
*
|
|
* Example usage:
|
|
* <div .alerts uw-alerts>
|
|
* <div .alerts__toggler>
|
|
* <div .alert.alert-info>
|
|
* <div .alert__closer>
|
|
* <div .alert__icon>
|
|
* <div .alert__content>
|
|
* This is some information
|
|
*
|
|
*/
|
|
|
|
var ALERTS_UTIL_NAME = 'alerts';
|
|
var ALERTS_UTIL_SELECTOR = '[uw-alerts]';
|
|
|
|
var ALERTS_INITIALIZED_CLASS = 'alerts--initialized';
|
|
var ALERTS_ELEVATED_CLASS = 'alerts--elevated';
|
|
var ALERTS_TOGGLER_CLASS = 'alerts__toggler';
|
|
var ALERTS_TOGGLER_VISIBLE_CLASS = 'alerts__toggler--visible';
|
|
var ALERTS_TOGGLER_APPEAR_DELAY = 120;
|
|
|
|
var ALERT_CLASS = 'alert';
|
|
var ALERT_INITIALIZED_CLASS = 'alert--initialized';
|
|
var ALERT_CLOSER_CLASS = 'alert__closer';
|
|
var ALERT_ICON_CLASS = 'alert__icon';
|
|
var ALERT_CONTENT_CLASS = 'alert__content';
|
|
var ALERT_INVISIBLE_CLASS = 'alert--invisible';
|
|
var ALERT_AUTO_HIDE_DELAY = 10;
|
|
var ALERT_AUTOCLOSING_MATCHER = '.alert-info, .alert-success';
|
|
|
|
var alertsUtil = function(element) {
|
|
var togglerCheckRequested = false;
|
|
var togglerElement;
|
|
var alertElements;
|
|
|
|
function init() {
|
|
if (!element) {
|
|
throw new Error('Alerts util has to be called with an element!');
|
|
}
|
|
|
|
if (element.classList.contains(ALERTS_INITIALIZED_CLASS)) {
|
|
return false;
|
|
}
|
|
|
|
togglerElement = element.querySelector('.' + ALERTS_TOGGLER_CLASS);
|
|
alertElements = gatherAlertElements();
|
|
|
|
initToggler();
|
|
initAlerts();
|
|
|
|
// register http client interceptor to filter out Alerts Header
|
|
setupHttpInterceptor();
|
|
|
|
// mark initialized
|
|
element.classList.add(ALERTS_INITIALIZED_CLASS);
|
|
|
|
return {
|
|
name: ALERTS_UTIL_NAME,
|
|
element: element,
|
|
destroy: function() {},
|
|
};
|
|
}
|
|
|
|
function gatherAlertElements() {
|
|
return Array.from(element.querySelectorAll('.' + ALERT_CLASS)).filter(function(alert) {
|
|
return !alert.classList.contains(ALERT_INITIALIZED_CLASS);
|
|
});
|
|
}
|
|
|
|
function initToggler() {
|
|
togglerElement.addEventListener('click', function() {
|
|
alertElements.forEach(function(alertEl) {
|
|
toggleAlert(alertEl, true);
|
|
});
|
|
togglerElement.classList.remove(ALERTS_TOGGLER_VISIBLE_CLASS);
|
|
});
|
|
}
|
|
|
|
function initAlerts() {
|
|
alertElements.forEach(initAlert);
|
|
}
|
|
|
|
function initAlert(alertElement) {
|
|
var autoHideDelay = ALERT_AUTO_HIDE_DELAY;
|
|
if (alertElement.dataset.decay) {
|
|
autoHideDelay = parseInt(alertElement.dataset.decay, 10);
|
|
}
|
|
|
|
var closeEl = alertElement.querySelector('.' + ALERT_CLOSER_CLASS);
|
|
closeEl.addEventListener('click', function() {
|
|
toggleAlert(alertElement);
|
|
});
|
|
|
|
if (autoHideDelay > 0 && alertElement.matches(ALERT_AUTOCLOSING_MATCHER)) {
|
|
window.setTimeout(function() {
|
|
toggleAlert(alertElement);
|
|
}, autoHideDelay * 1000);
|
|
}
|
|
}
|
|
|
|
function toggleAlert(alertEl, visible) {
|
|
alertEl.classList.toggle(ALERT_INVISIBLE_CLASS, !visible);
|
|
checkToggler();
|
|
}
|
|
|
|
function checkToggler() {
|
|
if (togglerCheckRequested) {
|
|
return;
|
|
}
|
|
|
|
var alertsHidden = alertElements.reduce(function(acc, alert) {
|
|
return acc && alert.classList.contains(ALERT_INVISIBLE_CLASS);
|
|
}, true);
|
|
|
|
window.setTimeout(function() {
|
|
togglerElement.classList.toggle(ALERTS_TOGGLER_VISIBLE_CLASS, alertsHidden);
|
|
togglerCheckRequested = false;
|
|
}, ALERTS_TOGGLER_APPEAR_DELAY);
|
|
}
|
|
|
|
function setupHttpInterceptor() {
|
|
if (HttpClient) {
|
|
HttpClient.addResponseInterceptor(responseInterceptor.bind(this));
|
|
}
|
|
}
|
|
|
|
function elevateAlerts() {
|
|
element.classList.add(ALERTS_ELEVATED_CLASS);
|
|
}
|
|
|
|
function responseInterceptor(response) {
|
|
var alerts;
|
|
for (var header of response.headers) {
|
|
if (header[0] === 'alerts') {
|
|
var decodedHeader = decodeURIComponent(header[1]);
|
|
alerts = JSON.parse(decodedHeader);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (alerts) {
|
|
alerts.forEach(function(alert) {
|
|
var alertElement = createAlertElement(alert.status, alert.content);
|
|
element.appendChild(alertElement);
|
|
alertElements.push(alertElement);
|
|
initAlert(alertElement);
|
|
});
|
|
|
|
elevateAlerts();
|
|
}
|
|
}
|
|
|
|
function createAlertElement(type, content) {
|
|
var alertElement = document.createElement('div');
|
|
alertElement.classList.add(ALERT_CLASS, 'alert-' + type);
|
|
|
|
var alertCloser = document.createElement('div');
|
|
alertCloser.classList.add(ALERT_CLOSER_CLASS);
|
|
|
|
var alertIcon = document.createElement('div');
|
|
alertIcon.classList.add(ALERT_ICON_CLASS);
|
|
|
|
var alertContent = document.createElement('div');
|
|
alertContent.classList.add(ALERT_CONTENT_CLASS);
|
|
alertContent.innerHTML = content;
|
|
|
|
alertElement.appendChild(alertCloser);
|
|
alertElement.appendChild(alertIcon);
|
|
alertElement.appendChild(alertContent);
|
|
|
|
return alertElement;
|
|
}
|
|
|
|
return init();
|
|
};
|
|
|
|
if (UtilRegistry) {
|
|
UtilRegistry.register({
|
|
name: ALERTS_UTIL_NAME,
|
|
selector: ALERTS_UTIL_SELECTOR,
|
|
setup: alertsUtil,
|
|
});
|
|
}
|
|
})();
|