jam-cloud/web/app/assets/javascripts/chatPanel.js

346 lines
9.5 KiB
JavaScript

(function(context,$) {
"use strict";
context.JK = context.JK || {};
context.JK.ChatPanel = function(app) {
var logger = context.JK.logger;
var rest = context.JK.Rest();
var $panel = null;
var $contents = null;
var $count = null;
var $chatMessages = null;
var $chatMessagesScroller = null;
var $sendChatMessageBtn = null;
var $chatSender = null;
var $form = null;
var $textBox = null;
var $sessionId = null;
var $errorMsg = null;
var sendingMessage = false;
var showing = false;
var fullyInitialized = false;
var renderQueue = [];
var sidebar = null;
var user = null;
var currentPage = 0;
var LIMIT = 20;
var next = null;
function reset() {
fullyInitialized = false;
renderQueue = [];
sendingMessage = false;
$chatMessages.empty();
$textBox.val('');
}
function buildMessage() {
var message = {};
message['message'] = $textBox.val();
message['music_session'] = $sessionId;
message['client_id'] = app.clientId;
return message;
}
function sendMessage() {
if(!context.JK.JamServer.connected) {
return false;
}
var msg = $textBox.val();
if(!msg || msg == '') {
// don't bother the server with empty messages
return false;
}
if(!sendingMessage) {
sendingMessage = true;
rest.createChatMessage(buildMessage())
.done(function() {
$textBox.val('');
renderMessage(msg, user.id, user.name, new Date().toISOString(), true);
})
.fail(function(jqXHR) {
app.notifyServerError(jqXHR, 'Unable to Send Chat Message');
})
.always(function() {
sendingMessage = false;
})
}
return false;
}
function scrollToBottom(instant) {
$chatMessagesScroller.animate({scrollTop: $chatMessagesScroller[0].scrollHeight}, instant ? 0 : 'slow');
}
function renderMessage(msg, senderId, senderName, sent, append) {
var options = {
msg: msg,
sender: senderId == user.id ? 'me' : senderName,
sent: sent
};
var txt = $(context._.template($('#template-chat-message').html(), options, { variable: 'data' }));
txt.find('.timeago').timeago();
if(append) {
$chatMessages.append(txt);
scrollToBottom();
}
else {
$chatMessages.prepend(txt);
}
}
function drainQueue() {
context._.each(renderQueue, function(msg) {
renderMessage(msg.message, msg.user_id, msg.user_name, msg.sent, true);
});
renderQueue = [];
}
// we handled the notification, meaning the dialog showed this message as a chat message
function handledNotification(payload) {
return showing && payload.description == "TEXT_MESSAGE";
}
function pasteIntoInput(el, text) {
el.focus();
if (typeof el.selectionStart == "number"
&& typeof el.selectionEnd == "number") {
var val = el.value;
var selStart = el.selectionStart;
el.value = val.slice(0, selStart) + text + val.slice(el.selectionEnd);
el.selectionEnd = el.selectionStart = selStart + text.length;
} else if (typeof document.selection != "undefined") {
var textRange = document.selection.createRange();
textRange.text = text;
textRange.collapse(false);
textRange.select();
}
}
function handleEnter(evt) {
if (evt.keyCode == 13 && evt.shiftKey) {
evt.preventDefault();
pasteIntoInput(this, "\n");
}
else if(evt.keyCode == 13 && !evt.shiftKey){
sendMessage();
return false;
}
}
function events(bind) {
if (bind) {
$form.submit(sendMessage);
$textBox.keydown(handleEnter);
$sendChatMessageBtn.click(sendMessage);
}
else {
$form.submit(null);
$textBox.keydown(null);
$sendChatMessageBtn.click(null);
}
registerChatMessage(bind);
}
// called from sidebar when messages come in
function chatMessageReceived(payload) {
if(fullyInitialized) {
if (isChatPanelVisible()) {
renderMessage(payload.msg, payload.sender_id, payload.sender_name, payload.created_at, true);
}
else {
highlightCount();
incrementChatCount();
renderQueue.push({message: payload.msg, user_id: payload.sender_id, user_name: payload.sender_name, sent: payload.created_at});
context.jamClient.UserAttention(true);
}
}
else {
renderQueue.push({message: payload.msg, user_id: payload.sender_id, user_name: payload.sender_name, sent: payload.created_at});
}
}
function registerChatMessage(bind) {
if (bind && bind == true) {
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.CHAT_MESSAGE, function(header, payload) {
logger.debug("Handling CHAT_MESSAGE msg " + JSON.stringify(payload));
chatMessageReceived(payload);
handledNotification(payload);
});
}
else {
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.CHAT_MESSAGE, null);
}
}
function opened() {
lowlightCount();
setCount(0);
drainQueue();
}
function sessionStarted(e, data) {
$sessionId = data.session.id;
// open chat panel
$chatSender.show();
$chatMessagesScroller.show();
$errorMsg.hide();
$panel.find('.panel-header').trigger('click');
$panel.on('open', opened);
$panel.find('.btn-next-pager').attr('href', '/api/sessions/' + $sessionId + '/chats?page=1');
reset();
// load previous chat messages
rest.getChatMessages(buildQuery())
.done(function (response) {
handleChatResponse(response);
scrollToBottom(true);
showing = true;
fullyInitialized = true;
drainQueue();
})
.fail(function (jqXHR) {
app.notifyServerError(jqXHR, 'Unable to Load Session Conversations')
});
events(true);
}
function sessionStopped(e, data) {
// open chat panel
$chatSender.hide();
$chatMessagesScroller.hide();
$errorMsg.show();
reset();
events(false);
}
function isChatPanelVisible() {
return $contents.is(':visible');
}
function incrementChatCount() {
var count = parseInt($count.text());
setCount(count + 1);
}
function setCount(count) {
$count.text(count);
}
function lowlightCount() {
$count.removeClass('highlighted');
}
function highlightCount() {
$count.addClass('highlighted');
}
function buildQuery() {
var query = {type: 'CHAT_MESSAGE', music_session: $sessionId, limit:LIMIT, page:currentPage};
if(next) {
query.start = next;
}
return query;
}
function renderChats(chats) {
context._.each(chats, function (chatMessage) {
renderMessage(chatMessage.message, chatMessage.user_id, chatMessage.user.name, chatMessage.created_at);
});
}
function handleChatResponse(response) {
next = response.next;
renderChats(response.chats);
if(response.next == null) {
// if we less results than asked for, end searching
$chatMessagesScroller.infinitescroll('pause');
logger.debug("end of chatss");
if(currentPage > 0) {
// there are bugs with infinitescroll not removing the 'loading'.
// it's most noticeable at the end of the list, so whack all such entries
$('.infinite-scroll-loader').remove();
}
}
else {
currentPage++;
buildQuery();
// registerInfiniteScroll();
}
}
function registerInfiniteScroll() {
$chatMessagesScroller.infinitescroll({
behavior: 'local',
navSelector: '.chat-sender .btn-next-pager',
nextSelector: '.chat-sender .btn-next-pager',
binder: $chatMessagesScroller,
dataType: 'json',
appendCallback: false,
prefill: false,
bufferPx: 100,
loading: {
msg: $('<div class="infinite-scroll-loader">Loading ...</div>'),
img: '/assets/shared/spinner-32.gif'
},
path: function(page) {
return '/api/sessions/' + $sessionId + '/chats?' + $.param(buildQuery());
}
},function(json, opts) {
handleChatResponse(json);
});
$chatMessagesScroller.infinitescroll('resume');
}
function initialize(sidebarInstance) {
sidebar = sidebarInstance;
$panel = $('[layout-id="panelChat"]');
$contents = $panel.find('.chatcontents');
$chatMessagesScroller = $panel.find('.chat-list-scroller');
$count = $panel.find('#sidebar-chat-count');
$chatMessages = $panel.find('.previous-chat-list');
$sendChatMessageBtn = $panel.find('.btn-send-chat-message');
$chatSender = $panel.find('.chat-sender');
$form = $panel.find('.chat-message-form');
$textBox = $form.find('textarea');
$errorMsg = $panel.find('.chat-status');
$errorMsg.show();
$chatSender.hide();
$chatMessagesScroller.hide();
app.user()
.done(function (userDetail) {
user = userDetail;
});
}
this.initialize = initialize;
this.sessionStarted = sessionStarted;
this.sessionStopped = sessionStopped;
this.registerChatMessage = registerChatMessage;
};
return this;
})(window,jQuery);