fradrive/static/js/utils/alerts.js
2019-04-10 20:19:49 +02:00

157 lines
4.2 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_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_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();
// 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);
});
element.classList.add(ALERTS_INITIALIZED_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);
}
alertElement.classList.add(ALERTS_INITIALIZED_CLASS);
}
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);
}
return init();
};
if (UtilRegistry) {
UtilRegistry.register({
name: ALERTS_UTIL_NAME,
selector: ALERTS_UTIL_SELECTOR,
setup: alertsUtil,
});
}
})();