(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 = true; var renderQueue = []; var sidebar = null; var user = null; var currentPage = 0; var LIMIT = 20; var next = null; function reset() { fullyInitialized = true; 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); }*/ } // called from sidebar when messages come in function chatMessageReceived(payload) { if (fullyInitialized) { if (isChatPanelVisible()) { } else { highlightCount(); incrementChatCount(); context.jamClient.UserAttention(true); } } } 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); context.ChatActions.msgReceived(payload); handledNotification(payload); }); } else { context.JK.JamServer.registerMessageCallback(context.JK.MessageType.CHAT_MESSAGE, null); } } function opened() { lowlightCount(); setCount(0); drainQueue(); } function fullyOpened() { context.ChatActions.fullyOpened() } function sessionStarted(e, data) { $sessionId = data.session.id; var lessonId = null; if (data.session.lesson_session) { lessonId = data.session.lesson_session.id } // open chat panel //$chatSender.show(); //$chatMessagesScroller.show(); $errorMsg.hide(); $panel.find('.panel-header').trigger('click'); $panel.find('.btn-next-pager').attr('href', '/api/sessions/' + $sessionId + '/chats?page=1'); reset(); context.ChatActions.sessionStarted($sessionId, lessonId); showing = true fullyInitialized = true; drainQueue(); 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'); 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: $('
Loading ...
'), 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'); $errorMsg = $panel.find('.chat-status'); $errorMsg.show(); $panel.on('open', opened); $panel.on('fullyOpen', fullyOpened); app.user() .done(function (userDetail) { user = userDetail; registerChatMessage(true); }); } this.initialize = initialize; this.sessionStarted = sessionStarted; this.sessionStopped = sessionStopped; this.registerChatMessage = registerChatMessage; }; return this; })(window, jQuery);