mirror of
https://github.com/OpenXE-org/OpenXE.git
synced 2024-11-16 13:07:14 +01:00
864 lines
30 KiB
JavaScript
864 lines
30 KiB
JavaScript
|
var Chat = function ($, PushJS) {
|
||
|
"use strict";
|
||
|
|
||
|
var me = {
|
||
|
|
||
|
settings: {
|
||
|
// Interval nach dem neue Nachrichten abgerufen werden (in Millisekunden)
|
||
|
fetchMessageInterval: 2000,
|
||
|
|
||
|
// Interval nach dem die Userliste aktualisiert wird (in Millisekunden)
|
||
|
fetchUserlistInterval: 15000,
|
||
|
|
||
|
// Zeit die zwischen zwei LazyLoading-Requests vergehen muss (in Millisekunden)
|
||
|
lazyLoadingBufferTime: 250,
|
||
|
|
||
|
// Zeit für die eine neue Nachricht als "NEU" markiert ist (in Millisekunden)
|
||
|
newTimeout: 5000
|
||
|
},
|
||
|
|
||
|
selector: {
|
||
|
// Nachrichtenbereich
|
||
|
messageArea: '#message-area',
|
||
|
|
||
|
// Eingabefeld für neue Nachrichten
|
||
|
inputField: '#nachricht',
|
||
|
|
||
|
// Container in dem die Benutzerliste angezeigt wird
|
||
|
userList: '#userlist',
|
||
|
|
||
|
// Container in dem die Raumliste angezeigt wird
|
||
|
roomList: '#roomlist',
|
||
|
|
||
|
// Bezeichner für den aktuellen Raum
|
||
|
roomName: '#message-header',
|
||
|
|
||
|
// Formular-Element
|
||
|
chatForm: '#chatform',
|
||
|
|
||
|
// Checkbox um Nachricht hervorzuheben
|
||
|
prioCheckbox: '#prio',
|
||
|
|
||
|
// InfoBox für Browser-Benachrichtigungen
|
||
|
notificationInfo: '#notification-info',
|
||
|
|
||
|
// Xentral-Sidebar
|
||
|
wawiSidebar: '#sidebar'
|
||
|
},
|
||
|
|
||
|
storage: {
|
||
|
// User-ID des aktuellen Chat-Partners
|
||
|
activeUserId: 0,
|
||
|
|
||
|
// Eigene User-ID
|
||
|
selfUserId: 0,
|
||
|
|
||
|
// ID der neuesten empfangenen Nachricht
|
||
|
newestMessageId: 0,
|
||
|
|
||
|
// ID der ältesten empfangenen Nachricht
|
||
|
oldestMessageId: null,
|
||
|
|
||
|
// ID der neuesten Gelesen-Markierung
|
||
|
newestReadmarkId: 0,
|
||
|
|
||
|
requestBuffer: 0,
|
||
|
|
||
|
// Gibt an ob die älteste Nachricht bereits geladen wurde
|
||
|
requestEOF: false,
|
||
|
|
||
|
// Array mit Nachrichten-IDs die als gelesen markiert werden sollen
|
||
|
readMark: [],
|
||
|
|
||
|
// Neuestes Datum; für Anzeige der Datumszeile (wenn zu neueren Nachrichten gescrollt wird)
|
||
|
newestDateString: '',
|
||
|
|
||
|
// Ältestes Datum; für Anzeige der Datumszeile (wenn zu älteren Nachrichten gescrollt wird)
|
||
|
oldestDateString: '',
|
||
|
|
||
|
// Datumswerte merken, die schonmal angezeigt wurden
|
||
|
dateStrings: [],
|
||
|
|
||
|
isStandaloneWindow: null,
|
||
|
|
||
|
fetchMessageInterval: null,
|
||
|
fetchUserlistInterval: null
|
||
|
},
|
||
|
|
||
|
elem: {
|
||
|
$window: null,
|
||
|
$wrapper: null,
|
||
|
$sidebarWrapper: null,
|
||
|
$sidebarScroller: null,
|
||
|
$messageWrapper: null,
|
||
|
$messageScroller: null
|
||
|
},
|
||
|
|
||
|
init: function () {
|
||
|
me.storage.isStandaloneWindow = ($(me.selector.wawiSidebar).length === 0);
|
||
|
|
||
|
me.elem.$window = $(window);
|
||
|
me.elem.$wrapper = $('#chat-wrapper');
|
||
|
me.elem.$messageWrapper = $('#message-wrapper');
|
||
|
me.elem.$messageScroller = $('#message-scroller');
|
||
|
me.elem.$sidebarWrapper = $('#sidebar-wrapper');
|
||
|
me.elem.$sidebarScroller = $('#sidebar-scroller');
|
||
|
|
||
|
me.checkNotificationPermission();
|
||
|
|
||
|
me.resizeElements();
|
||
|
me.attachEvents();
|
||
|
|
||
|
// Chat mit "Öffentlich"
|
||
|
me.switchToUser(0);
|
||
|
|
||
|
if (me.storage.isStandaloneWindow) {
|
||
|
var navigation = '<div id="submenu-wrapper" class="clearfix"><div class="back">';
|
||
|
navigation += '<a href="index.php?module=welcome&action=start"><svg xmlns="http://www.w3.org/2000/svg" width="7px" height="12px" viewBox="0 0 131.99 218.57"><path fill="none" stroke="#fff" stroke-miterlimit="10" stroke-width="33" d="M120.26 11.65l-97 97.21 97 98.11"/></svg></a>';
|
||
|
navigation += '</div><a href="index.php?module=welcome&action=start" style="display:block;padding: 7px 20px;">Zurück zur Startseite</a>';
|
||
|
navigation += '</div>';
|
||
|
$('#tabs').prepend(navigation);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Registriert alle benötigten Events und Timer
|
||
|
*/
|
||
|
attachEvents: function () {
|
||
|
|
||
|
// Formular-Absenden abfangen
|
||
|
$(me.selector.chatForm).on('submit', function (event) {
|
||
|
event.preventDefault();
|
||
|
me.sendMessage($(me.selector.inputField).val(), $(me.selector.prioCheckbox).prop('checked'));
|
||
|
});
|
||
|
|
||
|
// Klick auf User
|
||
|
$(document).on('click', me.selector.userList + ' li', function (e) {
|
||
|
e.preventDefault();
|
||
|
me.switchToUser(parseInt($(this).data('user-id')));
|
||
|
});
|
||
|
|
||
|
// Klick auf Raum
|
||
|
$(document).on('click', me.selector.roomList + ' li', function (e) {
|
||
|
e.preventDefault();
|
||
|
me.switchToUser(parseInt($(this).data('user-id')));
|
||
|
});
|
||
|
|
||
|
// Bei Klick auf InfoBox für Benachrichtigungen > Erlaubnis einholen
|
||
|
$(document).on('click', me.selector.notificationInfo, function () {
|
||
|
me.requestNotificationPermission();
|
||
|
});
|
||
|
|
||
|
// Fenstergrößen-Änderungen abfangen
|
||
|
// Vorallem der Nachrichtenbereich benötigt immer eine feste Breite; ansonsten
|
||
|
// können überlange Nachrichten ohne Leerzeichen nicht umgebrochen werden.
|
||
|
$(window).on('resize', function () {
|
||
|
me.debounce(me.resizeElements, 100);
|
||
|
});
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Startet die Intervale zum Abrufen der Nachrichten und Benutzerliste
|
||
|
*/
|
||
|
start: function () {
|
||
|
// Alle 30 Sekunden die Userliste aktualisieren
|
||
|
me.storage.fetchUserlistInterval = setInterval(function () {
|
||
|
me.updateUserList();
|
||
|
}, me.settings.fetchUserlistInterval);
|
||
|
|
||
|
// Alle 2 Sekunden die Nachrichten aktualisieren
|
||
|
me.storage.fetchMessageInterval = setInterval(function () {
|
||
|
me.fetchNewMessages(false);
|
||
|
me.setMessagesAsRead();
|
||
|
}, me.settings.fetchMessageInterval);
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Stop die Intervale zum Abrufen der Nachrichten und Benutzerliste
|
||
|
*/
|
||
|
stop: function () {
|
||
|
clearInterval(me.storage.fetchMessageInterval);
|
||
|
clearInterval(me.storage.fetchUserlistInterval);
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Ist Berechtigung zum Senden von Browser-Benachrichtigungen vorhanden?
|
||
|
*
|
||
|
* @return {boolean}
|
||
|
*/
|
||
|
checkNotificationPermission: function () {
|
||
|
var permissionStatus = PushJS.Permission.get();
|
||
|
|
||
|
// Falls Berechtigung nicht erteilt oder blockiert wurde > InfoBox anzeigen
|
||
|
if (permissionStatus === PushJS.Permission.DEFAULT) {
|
||
|
var content =
|
||
|
'<div class="info" id="notification-info">' +
|
||
|
'<table width="100%" border="0" cellpadding="0" cellspacing="0"><tr>' +
|
||
|
'<td>Aktuell können keine Browser-Benachrichtigungen zugestellt werden. ' +
|
||
|
'Bitte Klicken Sie hier um die Nachrichten für Xentral zu erlauben.</td>' +
|
||
|
'<td align="right"><input type="button" id="notification-button" value="Benachrichtigungen erlauben"></td>'+
|
||
|
'</tr></table></div>';
|
||
|
$('#tabs-1').prepend(content);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Browser-Dialog zum Erteilen der Berechtigung öffnen
|
||
|
*/
|
||
|
requestNotificationPermission: function () {
|
||
|
PushJS.Permission.request(
|
||
|
me.removeNotificationInfoBox, // Berechtigung erteilt
|
||
|
me.removeNotificationInfoBox // Berechtigung verweigert
|
||
|
);
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* InfoBox zu Browser-Benachrichtigungen entfernen
|
||
|
*/
|
||
|
removeNotificationInfoBox: function () {
|
||
|
$(me.selector.notificationInfo).remove();
|
||
|
me.resizeElements();
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Schickt eine neue Nachricht per AJAX ab
|
||
|
*
|
||
|
* @param {string} message
|
||
|
* @param {boolean} priority
|
||
|
*/
|
||
|
sendMessage: function (message, priority) {
|
||
|
if (typeof priority === 'undefined' || typeof priority !== 'boolean') {
|
||
|
priority = false;
|
||
|
}
|
||
|
|
||
|
$.ajax({
|
||
|
type: 'POST',
|
||
|
url: 'index.php?module=chat&action=list&cmd=sendmessage',
|
||
|
data: {
|
||
|
nachricht: message,
|
||
|
empfaenger: me.storage.activeUserId,
|
||
|
prio: (priority === true) ? '1' : '0'
|
||
|
},
|
||
|
success: function () {
|
||
|
me.emptyInput();
|
||
|
me.focusInput();
|
||
|
me.fetchNewMessages(true);
|
||
|
}
|
||
|
});
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Aktualisiert per AJAX die Userliste
|
||
|
*/
|
||
|
updateUserList: function () {
|
||
|
$.ajax({
|
||
|
type: 'POST',
|
||
|
dataType: 'json',
|
||
|
url: 'index.php?module=chat&action=list&cmd=userlist',
|
||
|
success: function (data) {
|
||
|
me.renderUserList(data.users);
|
||
|
me.renderRoomList(data.rooms)
|
||
|
}
|
||
|
});
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Rendert die JSON-Userliste zu HTML
|
||
|
*
|
||
|
* @param {array} data
|
||
|
*/
|
||
|
renderUserList: function (data) {
|
||
|
var content = '<ul>';
|
||
|
|
||
|
$(data).each(function (index, user) {
|
||
|
user.id = parseInt(user.id);
|
||
|
|
||
|
// Sich selbst nicht in Userliste anzeigen
|
||
|
if (user.self === true) {
|
||
|
me.storage.selfUserId = user.id;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (user.id === me.storage.activeUserId) {
|
||
|
var roomname = '<img src="index.php?module=ajax&action=profilbild&id=' + user.id + '" alt="' + user.name + '">';
|
||
|
roomname += '<span>Mit ' + user.name + '</span>';
|
||
|
$(me.selector.roomName).html(roomname).removeClass('public');
|
||
|
}
|
||
|
|
||
|
var classes = (user.online === true) ? 'online' : '';
|
||
|
classes += (user.id === me.storage.activeUserId) ? ' active' : '';
|
||
|
|
||
|
content += '<li class="' + classes + '" data-user-id="' + user.id + '">';
|
||
|
content += '<span class="name">' + user.name + '</span> ';
|
||
|
if (user.unread > 0) {
|
||
|
content += '<span class="' + (user.unread > 0 ? 'unread' : '') + '">(' + user.unread + ')</span>';
|
||
|
}
|
||
|
content += '</li>';
|
||
|
});
|
||
|
|
||
|
content += '</ul>';
|
||
|
|
||
|
$(me.selector.userList).html(content);
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Rendert die JSON-Raumliste zu HTML
|
||
|
*
|
||
|
* @param {array} data
|
||
|
*/
|
||
|
renderRoomList: function (data) {
|
||
|
var content = '<ul>';
|
||
|
|
||
|
$(data).each(function (index, room) {
|
||
|
var classes = (room.id === me.storage.activeUserId) ? ' active' : '';
|
||
|
if (room.id === me.storage.activeUserId) {
|
||
|
$(me.selector.roomName).html('<span>' + room.name + '</span>').addClass('public');
|
||
|
}
|
||
|
|
||
|
content += '<li class="' + classes + '" data-user-id="' + room.id + '">';
|
||
|
content += '<span class="name">' + room.name + '</span> ';
|
||
|
if (room.unread > 0) {
|
||
|
content += '<span class="' + (room.unread > 0 ? 'unread' : '') + '">(' + room.unread + ')</span>';
|
||
|
}
|
||
|
content += '</li>';
|
||
|
});
|
||
|
|
||
|
content += '</ul>';
|
||
|
|
||
|
$(me.selector.roomList).html(content);
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Ruft neue Nachrichten per AJAX ab
|
||
|
*
|
||
|
* @param {boolean} scrollDown Soll nach dem Aktualisieren der Nachrichten zur neuesten Nachricht gescrollt werden?
|
||
|
*/
|
||
|
fetchNewMessages: function (scrollDown) {
|
||
|
if (typeof scrollDown === 'undefined' || typeof scrollDown !== 'boolean') {
|
||
|
scrollDown = false;
|
||
|
}
|
||
|
|
||
|
$.ajax({
|
||
|
type: 'POST',
|
||
|
url: 'index.php?module=chat&action=list&cmd=messages',
|
||
|
data: {
|
||
|
user_id: me.storage.activeUserId,
|
||
|
after_message_id: me.storage.newestMessageId,
|
||
|
after_readmark_id: me.storage.newestReadmarkId
|
||
|
},
|
||
|
success: function (data) {
|
||
|
me.renderNewMessages(data.messages);
|
||
|
me.renderMessagesAsRead(data.readmark);
|
||
|
|
||
|
if (scrollDown === true) {
|
||
|
me.scrollToLatestMessage();
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Nachrichten als "Gelesen" markieren
|
||
|
*
|
||
|
* renderNewMessages() füllt das readMark-Array
|
||
|
*/
|
||
|
setMessagesAsRead: function () {
|
||
|
if (me.storage.readMark.length === 0) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
$.ajax({
|
||
|
type: 'POST',
|
||
|
url: 'index.php?module=chat&action=list&cmd=markread',
|
||
|
data: {
|
||
|
messages: me.storage.readMark
|
||
|
},
|
||
|
success: function (data) {
|
||
|
// PHP liefert die Nachrichten-IDs der Gelesen-markierten Nachrichten zurück
|
||
|
$(data).each(function (index, messageId) {
|
||
|
messageId = parseInt(messageId);
|
||
|
var pos = me.storage.readMark.indexOf(messageId);
|
||
|
if (pos !== -1) {
|
||
|
// Bestätigt-Gelesene Nachricht aus Array entfernen
|
||
|
me.storage.readMark.splice(pos, 1);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
});
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Setzt bereits gerenderte Nachrichten auf "Gelesen"
|
||
|
*
|
||
|
* @param {array} data
|
||
|
*/
|
||
|
renderMessagesAsRead: function (data) {
|
||
|
if (data.length === 0) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Im öffentlichen Chat gibt es keine Gelesen-Markierungen
|
||
|
if (me.isPublicChat()) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
$(data).each(function (index, readmark) {
|
||
|
if (readmark.id > me.storage.newestReadmarkId) {
|
||
|
me.storage.newestReadmarkId = readmark.id;
|
||
|
}
|
||
|
|
||
|
// Nachricht als Gelesen markieren
|
||
|
$(me.selector.messageArea)
|
||
|
.find('#message-' + readmark.message)
|
||
|
.removeClass('unread')
|
||
|
.addClass('read');
|
||
|
});
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Ruft ältere Nachrichten per AJAX ab; wenn man nach oben scrollt
|
||
|
*/
|
||
|
fetchOldMessages: function () {
|
||
|
// Die älteste Nachricht wurde bereits erreicht
|
||
|
if (me.storage.requestEOF === true) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Request-Puffer ist aktiv; du musst noch warten
|
||
|
if (me.storage.requestBuffer > window.performance.now()) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Puffer setzen; Nur ein Request alle 0,25 Sekunden
|
||
|
// Notwendig weil Scroll-Event mehrmals pro Sekunde ausgelöst wird.
|
||
|
me.storage.requestBuffer = window.performance.now() + me.settings.lazyLoadingBufferTime;
|
||
|
|
||
|
$.ajax({
|
||
|
type: 'POST',
|
||
|
url: 'index.php?module=chat&action=list&cmd=messages',
|
||
|
data: {
|
||
|
user_id: me.storage.activeUserId,
|
||
|
before_message_id: me.storage.oldestMessageId
|
||
|
},
|
||
|
success: function (data) {
|
||
|
if (data.messages.length === 0) {
|
||
|
// Ende wurde erreicht; es gibt keine älteren Nachrichten
|
||
|
me.renderDateString(me.storage.oldestDateString, 'DESC', true);
|
||
|
me.storage.requestEOF = true;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
me.renderOldMessages(data.messages);
|
||
|
}
|
||
|
});
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Rendert die übergebene JSON-Nachrichtenliste zu HTML
|
||
|
*
|
||
|
* @param {array} data
|
||
|
*/
|
||
|
renderNewMessages: function (data) {
|
||
|
var newMessages = false;
|
||
|
|
||
|
// Abbruch wenn keine neuen Nachrichten im JSON sind
|
||
|
if (data.length === 0) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (me.storage.oldestMessageId === null) {
|
||
|
me.storage.oldestMessageId = data[0].id;
|
||
|
}
|
||
|
|
||
|
$(data).each(function (index, msg) {
|
||
|
|
||
|
// Zeile mit Datum einfügen
|
||
|
me.renderDateString(msg.date, 'ASC', false);
|
||
|
|
||
|
// Nachricht in Nachrichtenbereich anfügen
|
||
|
me.renderSingleMessage(msg, 'ASC');
|
||
|
|
||
|
newMessages = true;
|
||
|
|
||
|
// Ungelesene Nachrichten für Gelesen-Markierung vormerken
|
||
|
if (msg.read === false) {
|
||
|
me.reserveMessageForReadMark(msg);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
// Nach unten scrollen, falls eine neue Nachricht dabei war
|
||
|
if (newMessages === true) {
|
||
|
me.scrollToLatestMessage();
|
||
|
|
||
|
setTimeout(function () {
|
||
|
me.enableScrollSpy();
|
||
|
}, 100);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Rendert die übergebene JSON-Nachrichtenliste zu HTML
|
||
|
*
|
||
|
* @param {array} data
|
||
|
*/
|
||
|
renderOldMessages: function (data) {
|
||
|
// Höhe des Nachrichtenbereich merken
|
||
|
var oldHeight = $(me.selector.messageArea).height();
|
||
|
|
||
|
data = data.reverse();
|
||
|
$(data).each(function (index, msg) {
|
||
|
me.renderDateString(msg.date, 'DESC', false);
|
||
|
me.renderSingleMessage(msg, 'DESC');
|
||
|
|
||
|
// Ungelesene Nachrichten für Gelesen-Markierung vormerken
|
||
|
if (msg.read === false) {
|
||
|
me.reserveMessageForReadMark(msg);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
// Scroll-Position vor dem Einfügen anzeigen
|
||
|
var newHeight = $(me.selector.messageArea).height();
|
||
|
var scrollTop = (newHeight - oldHeight) - 20;
|
||
|
me.elem.$messageScroller.scrollTop(scrollTop);
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Nachricht für Gelesen-Markierung vormerken
|
||
|
*
|
||
|
* @param {object} msg
|
||
|
*/
|
||
|
reserveMessageForReadMark: function (msg) {
|
||
|
if (msg.read === true) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Ungelesene Nachrichten für Gelesen-Markierung vormerken, wenn
|
||
|
// ... Chat mit User
|
||
|
if (me.isPrivateChat() && !me.isOwnMessage(msg.user)) {
|
||
|
me.storage.readMark.push(msg.id);
|
||
|
}
|
||
|
// .. Chat mit Öffentlich
|
||
|
if (me.isPublicChat()) {
|
||
|
me.storage.readMark.push(msg.id);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @param {object} msg
|
||
|
* @param {string} direction [ASC|DESC]
|
||
|
*/
|
||
|
renderSingleMessage: function (msg, direction) {
|
||
|
|
||
|
// Abbrechen, wenn Nachricht bereits vorhanden ist
|
||
|
if ($('#message-' + msg.id).length > 0) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// CSS-Klassen zusammenstellen
|
||
|
var classes = 'message';
|
||
|
if (me.isPrivateChat()) {
|
||
|
// Bei eigenen Nachrichten anzeigen ob Nachricht gelesen wurde
|
||
|
if (me.isOwnMessage(msg.user)) {
|
||
|
if (msg.read === false) {
|
||
|
classes += ' unread';
|
||
|
}
|
||
|
if (msg.read === true) {
|
||
|
classes += ' read';
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
// Fremde ungelesene Nachrichten als NEU markieren
|
||
|
if (!me.isOwnMessage(msg.user)) {
|
||
|
if (msg.read === false) {
|
||
|
classes += ' new';
|
||
|
}
|
||
|
}
|
||
|
// Prio-Nachrichten markieren
|
||
|
if (msg.prio === true) {
|
||
|
classes += ' prio';
|
||
|
}
|
||
|
|
||
|
// Nachrichten-HTML zusammenstellen
|
||
|
var content =
|
||
|
'<div data-id="{{id}}" id="{{elementId}}" class="{{classes}}">' +
|
||
|
' <div class="image">' +
|
||
|
' <img src="index.php?module=ajax&action=profilbild&id={{user}}" alt="{{alt}}">' +
|
||
|
' </div>' +
|
||
|
' <div class="head">' +
|
||
|
' <span class="sender">{{name}}</span>' +
|
||
|
' <span class="time">{{time}}</span>' +
|
||
|
' </div>' +
|
||
|
' <div class="text">{{text}}</div>' +
|
||
|
'</div>';
|
||
|
content = content.replace('{{id}}', msg.id);
|
||
|
content = content.replace('{{user}}', msg.user);
|
||
|
content = content.replace('{{alt}}', msg.name);
|
||
|
content = content.replace('{{name}}', msg.name);
|
||
|
content = content.replace('{{time}}', msg.time);
|
||
|
content = content.replace('{{text}}', msg.text);
|
||
|
content = content.replace('{{classes}}', classes);
|
||
|
content = content.replace('{{elementId}}', 'message-' + msg.id);
|
||
|
|
||
|
// Neue Nachrichten unten anhängen
|
||
|
if (direction === 'ASC') {
|
||
|
$(me.selector.messageArea).append(content);
|
||
|
}
|
||
|
// Ältere Nachrichten oben einfügen
|
||
|
if (direction === 'DESC') {
|
||
|
$(me.selector.messageArea).prepend(content);
|
||
|
}
|
||
|
|
||
|
// NEU-Markierung nach fünf Sekunden wieder entfernen
|
||
|
setTimeout(function () {
|
||
|
$('#message-' + msg.id + '.new').removeClass('new');
|
||
|
}, me.settings.newTimeout);
|
||
|
|
||
|
// ID der ältesten und neuesten Nachricht wegspeichern
|
||
|
if (msg.id > me.storage.newestMessageId) {
|
||
|
me.storage.newestMessageId = msg.id
|
||
|
}
|
||
|
if (msg.id < me.storage.oldestMessageId) {
|
||
|
me.storage.oldestMessageId = msg.id
|
||
|
}
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Zeile mit Datum in Nachrichtenbereich einfügen
|
||
|
*
|
||
|
* @param {string} dateString
|
||
|
* @param {string} direction [ASC|DESC]
|
||
|
* @param {boolean} force Datum immer ausgeben
|
||
|
*/
|
||
|
renderDateString: function (dateString, direction, force) {
|
||
|
if (typeof direction === 'undefined' || typeof direction !== 'string') {
|
||
|
direction = 'ASC';
|
||
|
}
|
||
|
if (typeof force === 'undefined' || typeof force !== 'boolean') {
|
||
|
force = false;
|
||
|
}
|
||
|
|
||
|
// Datum wurde bereits ausgegeben
|
||
|
if (me.storage.dateStrings.indexOf(dateString) !== -1) {
|
||
|
return;
|
||
|
}
|
||
|
// Merken welche Datumseinträge bereits angezeigt wurden
|
||
|
me.storage.dateStrings.push(dateString);
|
||
|
|
||
|
if (me.storage.newestDateString === '') {
|
||
|
me.storage.newestDateString = dateString;
|
||
|
}
|
||
|
if (me.storage.oldestDateString === '') {
|
||
|
me.storage.oldestDateString = dateString;
|
||
|
}
|
||
|
|
||
|
// Aufsteigend, wenn neue Nachrichten eingefügt werden
|
||
|
if (direction === 'ASC') {
|
||
|
if (me.storage.newestDateString !== dateString) {
|
||
|
$(me.selector.messageArea).append(
|
||
|
'<div class="date"><span>' + dateString + '</span></div>'
|
||
|
);
|
||
|
me.storage.newestDateString = dateString;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Absteigend, wenn ältere Nachrichten eingefügt werden
|
||
|
if (direction === 'DESC') {
|
||
|
if (me.storage.oldestDateString !== dateString || force === true) {
|
||
|
$(me.selector.messageArea).prepend(
|
||
|
'<div class="date"><span>' + me.storage.oldestDateString + '</span></div>'
|
||
|
);
|
||
|
me.storage.oldestDateString = dateString;
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Scrollt zur neuesten Nachricht
|
||
|
*/
|
||
|
scrollToLatestMessage: function () {
|
||
|
me.elem.$messageScroller.animate({
|
||
|
scrollTop: me.elem.$messageScroller.get(0).scrollHeight
|
||
|
}, 100);
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Wechselt den Chat-Partner
|
||
|
*
|
||
|
* @param {number} userId
|
||
|
*/
|
||
|
switchToUser: function (userId) {
|
||
|
// Storage-Variablen zurücksetzen
|
||
|
me.storage.activeUserId = userId;
|
||
|
me.storage.newestMessageId = 0;
|
||
|
me.storage.oldestMessageId = null;
|
||
|
me.storage.oldestDateString = '';
|
||
|
me.storage.newestDateString = '';
|
||
|
me.storage.newestReadmarkId = 0;
|
||
|
me.storage.readMark = [];
|
||
|
me.storage.dateStrings = [];
|
||
|
me.storage.requestBuffer = 0;
|
||
|
me.storage.requestEOF = false;
|
||
|
|
||
|
// Intervalle anhalten
|
||
|
me.stop();
|
||
|
|
||
|
me.updateUserList();
|
||
|
me.emptyMessageArea();
|
||
|
me.fetchNewMessages(true);
|
||
|
me.emptyInput();
|
||
|
me.focusInput();
|
||
|
|
||
|
// Intervalle nach zwei Sekunden starten.
|
||
|
// Ansonsten kann der Nachrichtenempfang des ersten Intervalls und das
|
||
|
// obige fetchNewMessages() zeitgleich passieren. Das führt zu leeren
|
||
|
// Datumseinträgen.
|
||
|
window.setTimeout(function () {
|
||
|
me.start();
|
||
|
}, 2000);
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Höhe und Breite von Elementen festlegen
|
||
|
*
|
||
|
* Methode wird beim Vergößern/-kleinern des Fensters aufgerufen.
|
||
|
*
|
||
|
* Vorallem der Nachrichtenbereich benötigt eine feste Breite, um überlangen Text
|
||
|
* ohne Whitespace zuverlässig umbrechen zu können.
|
||
|
*/
|
||
|
resizeElements: function () {
|
||
|
var windowHeight = me.elem.$window.height();
|
||
|
var wrapperWidth = me.elem.$wrapper.width();
|
||
|
var sidebarWidth = me.elem.$sidebarWrapper.outerWidth();
|
||
|
var $notificationInfo = $(me.selector.notificationInfo);
|
||
|
var notificationHeight = ($notificationInfo.outerHeight() !== null) ? $notificationInfo.outerHeight() + 10 : 0;
|
||
|
var newMessageWidth = 0;
|
||
|
var newMessageHeight = 0;
|
||
|
var newSidebarHeight = 0;
|
||
|
|
||
|
if (me.storage.isStandaloneWindow) {
|
||
|
newMessageWidth = wrapperWidth - sidebarWidth - 10;
|
||
|
newMessageHeight = windowHeight - 200;
|
||
|
newSidebarHeight = windowHeight - 90;
|
||
|
|
||
|
} else {
|
||
|
newMessageWidth = wrapperWidth - sidebarWidth - 10;
|
||
|
newMessageHeight = windowHeight - 360;
|
||
|
newSidebarHeight = windowHeight - 240;
|
||
|
}
|
||
|
|
||
|
newMessageHeight -= notificationHeight;
|
||
|
newSidebarHeight -= notificationHeight;
|
||
|
|
||
|
me.elem.$messageScroller.width(newMessageWidth);
|
||
|
me.elem.$messageScroller.height(newMessageHeight);
|
||
|
me.elem.$sidebarScroller.height(newSidebarHeight);
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Ältere Nachrichten beim Nach-Oben-Scrollen abrufen
|
||
|
*/
|
||
|
enableScrollSpy: function () {
|
||
|
// Ermitteln ob Nachrichtenbereich überhaupt einen Scrollbalken hat;
|
||
|
// Es gibt keinen Scrollbalken bei wenigen oder keinen Nachrichten.
|
||
|
var messageAreaHasScrollbar =
|
||
|
(me.elem.$messageScroller.height() < $(me.selector.messageArea).height());
|
||
|
|
||
|
// ScrollSpy wird nicht benötigt wenn kein Scrollbalken vorhanden
|
||
|
if (messageAreaHasScrollbar === false) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Ältere Nachrichten abrufen wenn oberer Nachrichtenbereich angezeigt wird
|
||
|
me.elem.$messageScroller.on('scroll', function () {
|
||
|
var scrollTop = $(this).scrollTop();
|
||
|
if (scrollTop < 50) {
|
||
|
me.fetchOldMessages();
|
||
|
}
|
||
|
});
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Scroll-Event auf Nachrichtenbereich entfernen
|
||
|
*/
|
||
|
disableScrollSpy: function () {
|
||
|
me.elem.$messageScroller.off('scroll');
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Setzt den Focus auf das Eingabefeld
|
||
|
*/
|
||
|
focusInput: function () {
|
||
|
$(me.selector.inputField).trigger('focus');
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Eingabefeld leeren
|
||
|
*/
|
||
|
emptyInput: function () {
|
||
|
$(me.selector.inputField).val('');
|
||
|
//$(me.selector.prioCheckbox).prop('checked', '');
|
||
|
// Prio-Checkbox nicht zurücksetzen, soll manuell durch Benutzer passieren.
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Leert den Nachrichtenbereich
|
||
|
*/
|
||
|
emptyMessageArea: function () {
|
||
|
// Eventuell vorhandenen Scroll-Event entfernen
|
||
|
me.disableScrollSpy();
|
||
|
|
||
|
// Nachrichtenbereich leeren
|
||
|
$(me.selector.messageArea).empty();
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @return {bool}
|
||
|
*/
|
||
|
isPublicChat: function () {
|
||
|
return me.storage.activeUserId === 0;
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @return {bool}
|
||
|
*/
|
||
|
isPrivateChat: function () {
|
||
|
return me.storage.activeUserId > 0;
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @param {number} senderId
|
||
|
* @return {bool}
|
||
|
*/
|
||
|
isOwnMessage: function (senderId) {
|
||
|
return senderId === me.storage.selfUserId;
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Puffer-Funktion um Events erst nach einer bestimmten Zeit auszuführen
|
||
|
*
|
||
|
* @param {function} callback
|
||
|
* @param {number} delay
|
||
|
*/
|
||
|
debounce: function (callback, delay) {
|
||
|
var context = this;
|
||
|
var args = arguments;
|
||
|
|
||
|
window.clearTimeout(me.storage.buffer);
|
||
|
me.storage.buffer = window.setTimeout(function () {
|
||
|
callback.apply(context, args);
|
||
|
}, delay || 250);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
return {
|
||
|
init: me.init,
|
||
|
start: me.start,
|
||
|
stop: me.stop
|
||
|
};
|
||
|
|
||
|
}(jQuery, Push);
|
||
|
|
||
|
$(document).ready(function () {
|
||
|
Chat.init();
|
||
|
});
|