Initial xentral_oss_20.3.c9ffacf
This commit is contained in:
@@ -0,0 +1,863 @@
|
||||
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();
|
||||
});
|
||||
Reference in New Issue
Block a user