mirror of
https://github.com/OpenXE-org/OpenXE.git
synced 2024-12-28 15:40:28 +01:00
663 lines
21 KiB
JavaScript
663 lines
21 KiB
JavaScript
/**
|
|
* @example Notify.create('Normale Nachricht');
|
|
* @example Notify.create('Fehler Benachrichtgung', 'error', true);
|
|
*/
|
|
var Notify = function ($, PushJS) {
|
|
'use strict';
|
|
|
|
var me = {
|
|
|
|
validTypes: ['default', 'notice', 'success', 'warning', 'error', 'push'],
|
|
|
|
settings: {
|
|
storageKeyPrefix: 'notification_',
|
|
storageKeyProgressBar: 'notification_progressbar'
|
|
},
|
|
|
|
defaults: {
|
|
layout: 'topRight',
|
|
theme: 'notification',
|
|
maxVisible: 5,
|
|
timeout: 10000,
|
|
progressBar: true,
|
|
animation: {
|
|
open: {height: 'toggle'},
|
|
close: {height: 'toggle'},
|
|
easing: 'swing',
|
|
speed: 250
|
|
},
|
|
closeWith: [], // Überschreiben
|
|
template: '<div class="noty_message noselect"><div class="noty_text"></div><div class="close-icon"></div></div>'
|
|
},
|
|
|
|
init: function () {
|
|
// Notifications nicht in IFrames anzeigen
|
|
if (me.isIframe()) {
|
|
return;
|
|
}
|
|
|
|
// Eigene Default-Einstellungen in Noty-Defaults integrieren
|
|
$.noty.defaults = $.extend({}, $.noty.defaults, me.defaults);
|
|
$.noty.defaults.callback.onClose = function () {
|
|
me.closeNotificationInOtherTabs(this.options.id);
|
|
};
|
|
|
|
// Init abbrechen, wenn in Beleg-Positionen oder Positionen-Popup
|
|
var action = $('body').data('action');
|
|
if (typeof action === 'undefined' || action === 'positionen' || action === 'positioneneditpopup') {
|
|
return;
|
|
}
|
|
|
|
// Wenn Seite geladen wird > Geöffnete Benachrichtigungen aus LocalStorage wiederherstellen
|
|
me.restoreFromLocalStorage();
|
|
|
|
// Auf Änderungen im LocalStorage horchen
|
|
window.addEventListener('storage', me.storageHandler, false);
|
|
|
|
$(document).on('click', '.notification .close-icon', function () {
|
|
var notiId = $(this).parents('.noty_bar').prop('id');
|
|
me.close(notiId);
|
|
});
|
|
},
|
|
|
|
/**
|
|
* @param {string} key
|
|
*
|
|
* @return {boolean}
|
|
*/
|
|
has: function (key) {
|
|
return $.noty.get(key) !== false;
|
|
},
|
|
|
|
/**
|
|
* @param {string} key
|
|
*
|
|
* @return {object} noty-Objekt
|
|
*/
|
|
get: function (key) {
|
|
return $.noty.get(key);
|
|
},
|
|
|
|
/**
|
|
* @return {string[]}
|
|
*/
|
|
keys: function () {
|
|
return Object.keys($.noty.store);
|
|
},
|
|
|
|
/**
|
|
* @param {string|null} type [default|notice|success|warning|error|push]
|
|
* @param {string|null} title
|
|
* @param {string|null} message
|
|
* @param {boolean|null} hasPriority
|
|
* @param {object|null} options
|
|
*/
|
|
create: function (type, title, message, hasPriority, options) {
|
|
if (typeof options !== 'object' || options === null) {
|
|
options = {};
|
|
}
|
|
var data = options;
|
|
|
|
if (typeof type === 'undefined' || type === null) {
|
|
type = 'default';
|
|
}
|
|
if (me.validTypes.indexOf(type) === -1) {
|
|
type = 'default';
|
|
}
|
|
if (typeof title === 'undefined' || title === null) {
|
|
title = '';
|
|
}
|
|
if (typeof message === 'undefined' || message === null) {
|
|
message = '';
|
|
}
|
|
if (typeof hasPriority === 'undefined' || hasPriority === null) {
|
|
hasPriority = false;
|
|
}
|
|
if (title === '' && message === '') {
|
|
return;
|
|
}
|
|
|
|
if (hasPriority === true) {
|
|
me.playSound();
|
|
data.progressBar = false;
|
|
data.timeout = false; // Sticky machen
|
|
data.sticky = true;
|
|
data.force = true; // An den Anfang setzen
|
|
}
|
|
|
|
data.text = '';
|
|
if (title !== '') {
|
|
data.text += '<h6>' + title + '</h6>';
|
|
}
|
|
if (message !== '') {
|
|
data.text += message;
|
|
}
|
|
|
|
data.type = type;
|
|
|
|
// Buttons aufbereiten
|
|
if (typeof data.buttons !== 'undefined' && typeof data.buttons === 'object') {
|
|
data.buttons.forEach(function (button) {
|
|
if (typeof button.text === 'undefined' || typeof button.link === 'undefined') {
|
|
console.warn('Could not create Notify button. Required property \'text\' oder \'link\' is missing');
|
|
return;
|
|
}
|
|
if (typeof button.addClass === 'undefined') {
|
|
button.addClass = 'btn notification-button';
|
|
} else {
|
|
button.addClass += ' btn notification-button';
|
|
}
|
|
});
|
|
}
|
|
|
|
if (data.type === 'push') {
|
|
me.createPushNotification(title, message, hasPriority);
|
|
} else {
|
|
me.createFromData(data);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Benachrichtigung erzeugen
|
|
*
|
|
* @param {object} data
|
|
*/
|
|
createFromData: function (data) {
|
|
// ID, zur Wiedererkennung über alle Tabs/Fenster, generieren und zuweisen
|
|
if (typeof data.id === 'undefined' || data.id === null) {
|
|
data.id = me.generateRandomId();
|
|
}
|
|
if (typeof data.timestamp === 'undefined' || data.timestamp === null) {
|
|
data.timestamp = Date.now();
|
|
}
|
|
if (typeof data.type === 'undefined') {
|
|
data.type = 'default';
|
|
}
|
|
|
|
switch (data.type) {
|
|
case 'default':
|
|
data.type = 'alert';
|
|
break;
|
|
case 'notice':
|
|
data.type = 'information';
|
|
break;
|
|
case 'push':
|
|
return;
|
|
}
|
|
|
|
if (me.has(data.id)) {
|
|
// Es gibt schon eine Notification mit dieser ID > Notification aktualisieren
|
|
me.updateNotificationInOwnTab(data.id, data);
|
|
me.updateNotificationInOtherTabs(data.id, data);
|
|
} else {
|
|
// Neue Notification anlegen
|
|
me.createNotificationInOwnTab(data.id, data);
|
|
me.createNotificationInOtherTabs(data.id, data);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Benachrichtigung schließen
|
|
*
|
|
* @param {string} key
|
|
*/
|
|
close: function (key) {
|
|
me.closeNotificationInOwnTab(key);
|
|
me.closeNotificationInOtherTabs(key);
|
|
},
|
|
|
|
/**
|
|
* Alle Benachrichtigungen schließen
|
|
*/
|
|
closeAll: function () {
|
|
me.closeAllNotificationsInOwnTab();
|
|
me.closeAllNotificationsInOtherTabs();
|
|
},
|
|
|
|
/* ------\/------ Private Methoden ------\/------ */
|
|
|
|
|
|
/**
|
|
* Geöffnete Benachrichtigungen wiederherstellen
|
|
*/
|
|
restoreFromLocalStorage: function () {
|
|
var restored = me.collectFromLocalStorage();
|
|
|
|
// Zeitliche Reihenfolge wiederherstellen
|
|
restored.sort(function (a, b) {
|
|
return a.timestamp - b.timestamp;
|
|
});
|
|
|
|
// Benachrichtigungen erzeugen
|
|
restored.forEach(function (data) {
|
|
me.createNotificationInOwnTab(data.id, data);
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Benachrichtigungen aus LocalStorage holen
|
|
*
|
|
* @return {Array}
|
|
*/
|
|
collectFromLocalStorage: function () {
|
|
var notifications = [];
|
|
|
|
for (var key in localStorage) {
|
|
if (key === me.settings.storageKeyProgressBar) {
|
|
continue;
|
|
}
|
|
if (key.substr(0, 13) !== me.settings.storageKeyPrefix) {
|
|
continue;
|
|
}
|
|
if (localStorage.hasOwnProperty(key)) {
|
|
var store = localStorage.getItem(key);
|
|
var data = JSON.parse(store);
|
|
|
|
// Push-Benachrichtigungen nicht wiederherstellen
|
|
if (typeof data.type !== 'undefined' && data.type === 'push') {
|
|
continue;
|
|
}
|
|
|
|
notifications.push(data);
|
|
}
|
|
}
|
|
|
|
return notifications;
|
|
},
|
|
|
|
/**
|
|
* Ton abspielen
|
|
*/
|
|
playSound: function () {
|
|
try {
|
|
var bell = new Audio('./sound/pling.mp3');
|
|
bell.play();
|
|
} catch (e) {
|
|
// Sound abspielen funktioniert auf neueren Chromes nicht mehr:
|
|
// https://developers.google.com/web/updates/2017/09/autoplay-policy-changes
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Benachrichtigung im eigenen Fenster/Tab erstellen
|
|
*
|
|
* @param {string} key
|
|
* @param {object} data
|
|
*/
|
|
createNotificationInOwnTab: function (key, data) {
|
|
if (typeof key === 'string' && typeof data === 'object') {
|
|
var item = noty(data);
|
|
if (data.sticky === true) {
|
|
item.$bar.addClass('sticky');
|
|
}
|
|
|
|
// Events für Fortschrittsbalken
|
|
if (item.$progressBar && item.options.progressBar) {
|
|
item.$bar.on('mouseenter', function () {
|
|
me.resetProgressBarInOtherTabs(item.options.id);
|
|
});
|
|
item.$bar.on('mouseleave', function () {
|
|
me.startProgressBarInOtherTabs(item.options.id);
|
|
});
|
|
}
|
|
|
|
// Buttons wiederherstellen
|
|
if (typeof item.options.buttons !== 'undefined' && typeof item.options.buttons === 'object') {
|
|
item.options.buttons.forEach(function (button) {
|
|
|
|
// Data-Attribute wiederherstellen
|
|
var $button = $('#' + button.id);
|
|
$.each(button, function (property, value) {
|
|
if (property.substr(0, 5) !== 'data-') {
|
|
return;
|
|
}
|
|
var dataName = property.substr(5);
|
|
$button.data(dataName, value);
|
|
});
|
|
|
|
// onClick-Methode wiederherstellen
|
|
button.onClick = function ($noty) {
|
|
var event = jQuery.Event('notification-button:clicked');
|
|
$(document).trigger(event, button);
|
|
|
|
if (!event.isDefaultPrevented()) {
|
|
$noty.close();
|
|
window.location.href = button.link;
|
|
}
|
|
};
|
|
});
|
|
}
|
|
|
|
// Custom Event feuern
|
|
$(document).trigger('notification:created', data);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Benachrichtigung in allen anderen Fenstern/Tabs erstellen
|
|
*
|
|
* @param {string} key
|
|
* @param {object} data
|
|
*/
|
|
createNotificationInOtherTabs: function (key, data) {
|
|
if (typeof key === 'string' && typeof data === 'object') {
|
|
localStorage.setItem(key, JSON.stringify(data));
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Browser-Benachrichtigung erzeugen
|
|
*
|
|
* @param {string} title
|
|
* @param {string|null} message
|
|
* @param {boolean} hasPriority
|
|
*/
|
|
createPushNotification: function (title, message, hasPriority) {
|
|
if (typeof PushJS === 'undefined') {
|
|
throw 'push.js wurde nicht gefunden!';
|
|
}
|
|
if (typeof title === 'undefined' || title === null) {
|
|
message = '';
|
|
}
|
|
if (typeof message === 'undefined' || message === null) {
|
|
message = '';
|
|
}
|
|
if (typeof hasPriority === 'undefined') {
|
|
hasPriority = false;
|
|
}
|
|
if (title === '' && message === '') {
|
|
return;
|
|
}
|
|
|
|
var data = {
|
|
icon: './js/pushjs/icon.png',
|
|
onClick: function () {
|
|
window.focus();
|
|
this.close();
|
|
}
|
|
};
|
|
if (message !== '') {
|
|
data.body = message;
|
|
}
|
|
if (hasPriority === false) {
|
|
data.tag = 'default';
|
|
}
|
|
|
|
// Nicht-Prio-Nachrichten löschen
|
|
// (Prio-Nachrichten werden gestacked)
|
|
PushJS.close('default');
|
|
|
|
// Push-Nachricht erzeugen
|
|
PushJS.create(title, data);
|
|
},
|
|
|
|
/**
|
|
* Vorhandene Benachrichtigung aktualisieren
|
|
*
|
|
* @param {string} notifyId ID der Notification
|
|
* @param {object} notifyData
|
|
*/
|
|
updateNotificationInOwnTab: function (notifyId, notifyData) {
|
|
me.updateNotificationType(notifyId, notifyData.type);
|
|
me.updateNotificationText(notifyId, notifyData.text);
|
|
// @todo me.updateNotificationButtons(notifyId, notifyData.buttons);
|
|
},
|
|
|
|
/**
|
|
* Vorhandene Benachrichtigung aktualisieren
|
|
*
|
|
* @param {string} key ID der Notification
|
|
* @param {object} data
|
|
*/
|
|
updateNotificationInOtherTabs: function (key, data) {
|
|
if (typeof key === 'string' && typeof data === 'object') {
|
|
localStorage.setItem(key, JSON.stringify(data));
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Benachrichtigung im eigenen Fenster/Tab schließen
|
|
*
|
|
* @param {string} key
|
|
*/
|
|
closeNotificationInOwnTab: function (key) {
|
|
if (typeof key === 'undefined') {
|
|
return;
|
|
}
|
|
$.noty.close(key);
|
|
},
|
|
|
|
/**
|
|
* Benachrichtigung in allen anderen Fenstern/Tabs schließen
|
|
*
|
|
* @param {string} key
|
|
*/
|
|
closeNotificationInOtherTabs: function (key) {
|
|
localStorage.removeItem(key);
|
|
},
|
|
|
|
/**
|
|
* Alle Benachrichtigungen im eigenen Fenster/Tab schließen
|
|
*/
|
|
closeAllNotificationsInOwnTab: function () {
|
|
$.noty.closeAll();
|
|
},
|
|
|
|
/**
|
|
* Alle Benachrichtigungen in allen anderen Fenstern/Tabs schließen
|
|
*/
|
|
closeAllNotificationsInOtherTabs: function () {
|
|
for (var key in localStorage) {
|
|
if (key.substr(0, 13) !== me.settings.storageKeyPrefix) {
|
|
continue;
|
|
}
|
|
if (localStorage.hasOwnProperty(key)) {
|
|
me.closeNotificationInOtherTabs(key);
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Text einer vorhandenen Benachrichtigung aktualisieren
|
|
*
|
|
* @param {string} notifyId
|
|
* @param {string} text
|
|
*/
|
|
updateNotificationText: function(notifyId, text) {
|
|
var existing = me.get(notifyId);
|
|
if (existing === false) {
|
|
return;
|
|
}
|
|
|
|
existing.$message.find('.noty_text').html(text);
|
|
},
|
|
|
|
/**
|
|
* Typ einer vorhandenen Benachrichtigung aktualisieren
|
|
*
|
|
* @param {string} notifyId
|
|
* @param {string} type
|
|
*/
|
|
updateNotificationType: function(notifyId, type) {
|
|
var existing = me.get(notifyId);
|
|
if (existing === false) {
|
|
return;
|
|
}
|
|
|
|
var newOuterClassName = 'noty_container_type_' + type;
|
|
var $outer = existing.$bar;
|
|
if (!$outer.hasClass(newOuterClassName)) {
|
|
var classList = $outer.attr('class').split(/\s+/);
|
|
$.each(classList, function(index, className) {
|
|
if (className.substring(0, 20) === 'noty_container_type_') {
|
|
$outer.removeClass(className);
|
|
}
|
|
});
|
|
$outer.addClass(newOuterClassName);
|
|
}
|
|
|
|
var newInnerClassName = 'noty_type_' + type;
|
|
var $inner = existing.$bar.find('.noty_bar');
|
|
if (!$inner.hasClass(newInnerClassName)) {
|
|
var innerClasses = $inner.attr('class').split(/\s+/);
|
|
$.each(innerClasses, function (index, className) {
|
|
if (className.substring(0, 10) === 'noty_type_') {
|
|
$inner.removeClass(className);
|
|
}
|
|
});
|
|
$inner.addClass(newInnerClassName);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Fortschrittsbalken im eigenen Tab/Fenster zurücksetzen
|
|
*
|
|
* @param {string} notifyId
|
|
*/
|
|
resetProgressBarInOwnTab: function (notifyId) {
|
|
var $noty = $.noty.get(notifyId);
|
|
if (typeof $noty !== 'object') {
|
|
return;
|
|
}
|
|
|
|
// Nicht alle Benachrichtigungen haben einen Fortschrittsbalken
|
|
if ($noty.options.progressBar && $noty.$progressBar) {
|
|
$noty.dequeueClose();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Fortschrittsbalken im eigenen Tab/Fenster wieder starten
|
|
*
|
|
* @param {string} notifyId
|
|
*/
|
|
startProgressBarInOwnTab: function (notifyId) {
|
|
var $noty = $.noty.get(notifyId);
|
|
if (typeof $noty !== 'object') {
|
|
return;
|
|
}
|
|
|
|
// Nicht alle Benachrichtigungen haben einen Fortschrittsbalken
|
|
if ($noty.options.progressBar && $noty.$progressBar) {
|
|
$noty.queueClose($noty.options.timeout);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Fortschrittsbalken in anderen Tabs/Fenstern zurücksetzen
|
|
*
|
|
* @param {string} notifyId
|
|
*/
|
|
resetProgressBarInOtherTabs: function (notifyId) {
|
|
var data = {
|
|
id: notifyId,
|
|
date: Date.now(),
|
|
action: 'reset'
|
|
};
|
|
|
|
localStorage.setItem(me.settings.storageKeyProgressBar, JSON.stringify(data));
|
|
},
|
|
|
|
/**
|
|
* Fortschrittsbalken in anderen Tabs/Fenstern wieder starten
|
|
*
|
|
* @param {string} notifyId
|
|
*/
|
|
startProgressBarInOtherTabs: function (notifyId) {
|
|
var data = {
|
|
id: notifyId,
|
|
date: Date.now(),
|
|
action: 'start'
|
|
};
|
|
|
|
localStorage.setItem(me.settings.storageKeyProgressBar, JSON.stringify(data));
|
|
},
|
|
|
|
/**
|
|
* Horcht auf Änderungen im LocalStorage
|
|
*
|
|
* @param {StorageEvent} e
|
|
*/
|
|
storageHandler: function (e) {
|
|
// LocalStorage wurde komplett geleert
|
|
if (typeof e === 'undefined') {
|
|
return;
|
|
}
|
|
|
|
// Fortschrittsbalken zurücksetzen/neustarten
|
|
if (e.key === me.settings.storageKeyProgressBar) {
|
|
if (e.newValue === null) {
|
|
return;
|
|
}
|
|
var progressData = JSON.parse(e.newValue);
|
|
if (progressData.action === 'reset') {
|
|
me.resetProgressBarInOwnTab(progressData.id);
|
|
}
|
|
if (progressData.action === 'start') {
|
|
me.startProgressBarInOwnTab(progressData.id);
|
|
}
|
|
|
|
localStorage.removeItem(me.settings.storageKeyProgressBar);
|
|
return;
|
|
}
|
|
|
|
// Nur auf bestimmten Key horchen
|
|
if (e.key.substr(0, 13) !== me.settings.storageKeyPrefix) {
|
|
return;
|
|
}
|
|
|
|
// LocalStorage(-Key) wurde gelöscht > Notification schließen
|
|
if (e.newValue === null) {
|
|
me.close(e.key);
|
|
return;
|
|
}
|
|
|
|
var received = JSON.parse(e.newValue);
|
|
if (received === null) {
|
|
return;
|
|
}
|
|
|
|
// Daten wurden empfangen
|
|
if (typeof received === 'object' && typeof received.id === 'string') {
|
|
if (me.has(received.id)) {
|
|
// Vorhandene Notification aktualisieren
|
|
me.updateNotificationInOwnTab(received.id, received);
|
|
} else {
|
|
// Notification erstellen
|
|
me.createNotificationInOwnTab(received.id, received);
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Zufällige ID generieren
|
|
*
|
|
* @return {string}
|
|
*/
|
|
generateRandomId: function () {
|
|
return me.settings.storageKeyPrefix + Math.floor(Math.random() * Math.floor(9999999999));
|
|
},
|
|
|
|
/**
|
|
* @return {boolean}
|
|
*/
|
|
isIframe: function () {
|
|
return window.location !== window.parent.location;
|
|
}
|
|
};
|
|
|
|
return {
|
|
has: me.has,
|
|
get: me.get,
|
|
keys: me.keys,
|
|
init: me.init,
|
|
create: me.create,
|
|
createFromData: me.createFromData,
|
|
close: me.close,
|
|
closeAll: me.closeAll
|
|
};
|
|
|
|
}(jQuery, Push);
|
|
|
|
$(document).ready(Notify.init);
|