Initial xentral_oss_20.3.c9ffacf

This commit is contained in:
Alex
2021-05-21 08:49:41 +02:00
parent 5406e4a551
commit 34e5ac43d9
18884 changed files with 2109867 additions and 0 deletions
+57
View File
@@ -0,0 +1,57 @@
{extends file='layout.tpl'}
{namespace key='chat'}
{block name='page'}
<div id="tabs">
<ul>
<li><a href="#tabs-1">{translate key='overview'}{$tabText|default:'Übersicht'}{/translate}</a></li>
</ul>
<div id="tabs-1" class="{$chatStandaloneClass}">
<div id="chat-wrapper">
<div id="sidebar-wrapper">
<div id="sidebar-scroller">
<div>
<h3>{translate key='users'}Benutzer{/translate}</h3>
<div id="userlist"></div>
</div>
<div>
<h3>{translate key='rooms'}Räume{/translate}</h3>
<div id="roomlist"></div>
</div>
</div>
</div>
<div id="message-wrapper">
<fieldset class="white">
<legend id="message-header"></legend>
<div id="message-scroller">
<div id="message-area"></div>
</div>
</fieldset>
<form id="chatform">
<fieldset class="white">
<legend></legend>
<div class="input-wrapper">
<div class="input-message">
<input type="text" placeholder="{translate key='message_placeholder'}Nachricht{/translate}"
name="nachricht" id="nachricht" autocomplete="off" tabindex="1">
</div>
<div class="input-prio">
<label>
<input type="checkbox" name="prio" id="prio" value="1" tabindex="2">
{translate key='priority_message'}Prio-Nachricht{/translate}
</label>
</div>
{block name='module_chat_list_form_button'}
<div class="input-button">
<input type="submit" name="submit" class="btnGreen"
value="{translate key='submit_button_text'}absenden{/translate}" tabindex="3">
</div>
{/block}
</div>
</fieldset>
</form>
</div>
</div>
</div>
</div>
{/block}
+286
View File
@@ -0,0 +1,286 @@
body > #tabs {
overflow: hidden;
}
#page_container #tabs-1 {
margin-bottom: 0;
}
#tabs-1.chat-standalone {
padding: 0;
margin: 8px;
}
/**
PUSH NOTIFICATIONS
*/
#notification-info {
box-sizing: border-box;
cursor: pointer;
width: 100%;
}
#tabs-1 #notification-info {
margin: 0 0 5px 0;
}
#notification-button {
cursor: pointer;
margin-left: 20px;
}
/**
LAYOUT
*/
#chat-wrapper {
display: flex;
flex: 1;
font-size: 15px;
line-height: 1.1em;
}
#sidebar-wrapper {
flex-direction: column;
flex-basis: 220px;
max-width: 240px;
background-color: #ECECEC;
padding: 10px;
}
#sidebar-wrapper h3 {
color: var(--grey);
font-size: 12px;
text-transform: uppercase;
margin-top: 10px;
padding: 5px 10px;
}
#sidebar-scroller {
overflow-y: auto;
min-height: 100px;
/*overflow: auto;*/
}
#sidebar-scroller > div {
width: 100%;
}
#message-wrapper {
flex-direction: column;
flex-grow: 1;
}
#message-wrapper fieldset {
margin: 0;
padding-right: 0;
}
#message-scroller {
min-width: 270px;
min-height: 180px;
overflow-y: scroll;
border-top: 3px solid var(--body-background);
border-bottom: 3px solid var(--body-background);
}
/**
SIDEBAR
*/
#roomlist,
#userlist {
}
#roomlist ul,
#userlist ul {
width: 100%;
list-style-type: none;
padding: 0;
margin: 0;
}
#roomlist li,
#userlist li {
white-space: nowrap;
overflow: hidden;
cursor: pointer;
color: #999;
list-style-type: none;
padding: 6px;
margin: 0;
vertical-align: baseline;
}
#roomlist li.active,
#userlist li.active {
padding: 6px;
background-color: #FFF;
}
#roomlist li:before,
#userlist li:before {
content: '\25CB';
display: inline-block;
width: 20px;
font-size: 170%;
line-height: 15px;
vertical-align: top;
text-align: center;
}
#userlist li.online {
color: var(--grey);
}
#userlist li.online:before {
content: '\2022';
font-size: 2.8em;
color: #a9ca45;
}
#roomlist span,
#userlist span {
display: inline-block;
}
#roomlist .unread,
#userlist .unread {
font-weight: bold;
color: orangered;
}
/**
MESSAGE AREA
*/
#message-area .date {
box-sizing: border-box;
position: relative;
height: 0;
border-bottom: 1px solid #ECECEC;
margin: 20px 0;
text-align: center;
}
#message-area .date span {
position: absolute;
top: -8px;
display: inline-block;
background-color: #FFF;
padding: 0 12px;
font-size: 13px;
font-weight: bold;
}
/**
MESSAGE AREA HEADER
*/
#message-header {
width: 100%;
padding: 5px 10px;
margin-top: 0;
background-color: #ECECEC;
}
#message-header.public {
color: orangered;
}
#message-header img {
float: left;
width: auto;
height: 36px;
padding: 0;
}
#message-header span {
display: inline-block;
margin-left: 6px;
padding: 10px 0;
}
/**
SINGLE MESSAGE
*/
.message {
box-sizing: content-box;
min-height: 36px;
padding: 0;
margin: 9px;
background-color: #FFF;
-webkit-transition: background-color 5000ms linear;
-ms-transition: background-color 5000ms linear;
transition: background-color 5000ms linear;
}
.message:hover {
}
.message .image {
float: left;
min-height: 36px;
margin-right: 8px;
margin-top: 2px;
}
.message .image img {
width: auto;
height: 36px;
padding: 0;
}
.message.unread .text:after {
content: ' (ungelesen)';
display: inline;
font-size: 80%;
color: #999;
}
.message.read .text:after {
}
.message.new {
background-color: #dfffff;
}
.message.new .time:after {
content: ' NEU';
display: inline;
color: var(--tabs-background);
font-weight: bold;
}
.message.prio {
background-image: url('../themes/new/images/chat_prio.png');
background-position: 99% center;
background-repeat: no-repeat;
}
.message .head {
padding-left: 44px;
}
.message .time {
color: #999;
font-size: 80%;
margin: 0 5px;
}
.message .sender {
font-weight: bold;
}
.message .text {
width: 100%;
box-sizing: border-box;
word-wrap: break-word;
overflow-wrap: break-word;
word-break: break-word;
padding: 0 44px;
line-height: 1.4em;
}
/**
MESSAGE INPUT
*/
.input-wrapper {
display: table;
width: 100%;
padding: 0 0 0 8px;
}
.input-wrapper .input-message,
.input-wrapper .input-prio,
.input-wrapper .input-button {
display: table-cell;
text-align: left;
vertical-align: baseline;
}
.input-wrapper .input-message {
width: 85%;
}
.input-wrapper .input-prio {
width: 10%;
white-space: nowrap;
padding: 0 6px;
}
.input-wrapper .input-button {
width: 5%;
}
#nachricht {
box-sizing: border-box;
width: 100%;
padding: 8px;
}
+863
View File
@@ -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();
});