295 lines
9.0 KiB
JavaScript
295 lines
9.0 KiB
JavaScript
(function(context,$) {
|
|
|
|
"use strict";
|
|
context.JK = context.JK || {};
|
|
context.JK.TextMessageDialog = function(app) {
|
|
var logger = context.JK.logger;
|
|
var rest = context.JK.Rest();
|
|
var $dialog = null;
|
|
var $previousMessages = null;
|
|
var $previousMessagesScroller = null;
|
|
var $sendTextMessage = null;
|
|
var $form = null;
|
|
var $textBox = null;
|
|
var userLookup = null;
|
|
var otherId = null;
|
|
var offset = 0;
|
|
var sendingMessage = false;
|
|
var LIMIT = 20;
|
|
var showing = false;
|
|
var fullyInitialized = false;
|
|
var user = null;
|
|
var renderQueue = []; // to handle race condition between dialog showing and populated using REST, and messages coming in
|
|
|
|
var remainingCap = 400;
|
|
|
|
function reset() {
|
|
fullyInitialized = false;
|
|
renderQueue = [];
|
|
sendingMessage = false;
|
|
offset = 0;
|
|
userLookup = {};
|
|
$previousMessages.empty();
|
|
$textBox.val('');
|
|
$sendTextMessage.unbind('click');
|
|
}
|
|
|
|
function buildParams() {
|
|
return { type: 'TEXT_MESSAGE', receiver: otherId, offset: offset, limit: LIMIT};
|
|
}
|
|
|
|
function buildMessage() {
|
|
var message = {};
|
|
|
|
message['message'] = $textBox.val();
|
|
message['receiver'] = otherId;
|
|
|
|
return message;
|
|
}
|
|
|
|
function sendMessage() {
|
|
var msg = $textBox.val();
|
|
if(!msg || msg == '') {
|
|
// don't bother the server with empty messages
|
|
return;
|
|
}
|
|
|
|
if(!sendingMessage) {
|
|
sendingMessage = true;
|
|
|
|
$sendTextMessage.text('SENDING...')
|
|
|
|
rest.createTextMessage(buildMessage())
|
|
.done(function() {
|
|
$textBox.val('');
|
|
renderMessage(msg, user.id, user.name, new Date().toISOString(), true);
|
|
})
|
|
.fail(function(jqXHR) {
|
|
app.notifyServerError(jqXHR, 'Unable to Send Message');
|
|
})
|
|
.always(function() {
|
|
sendingMessage = false;
|
|
$sendTextMessage.text('SEND');
|
|
})
|
|
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function scrollToBottom(instant) {
|
|
$previousMessagesScroller.animate({scrollTop: $previousMessagesScroller[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-previous-message').html(), options, { variable: 'data' }));
|
|
txt.find('.timeago').timeago();
|
|
if(append) {
|
|
$previousMessages.append(txt);
|
|
scrollToBottom();
|
|
}
|
|
else {
|
|
$previousMessages.prepend(txt);
|
|
}
|
|
}
|
|
|
|
function drainQueue() {
|
|
context._.each(renderQueue, function(msg) {
|
|
renderMessage(msg.msg, msg.senderId, msg.senderName, msg.sent, true);
|
|
});
|
|
renderQueue = [];
|
|
}
|
|
|
|
function formatTextMessage(msg, sender_id, sender_name, clipped_msg) {
|
|
var markedUpMsg = $('<span><span class="sender-name"></span> says: <span class="text-message"></span><a href="#" class="more-text-available"></a></span>');
|
|
markedUpMsg.find('.sender-name').text(sender_name)
|
|
markedUpMsg.find('.text-message').text(clipped_msg ? msg + "... " : msg).attr('data-is-clipped', clipped_msg)
|
|
var moreTextLink = markedUpMsg.find('.more-text-available').attr('data-sender-id', sender_id);
|
|
|
|
if(clipped_msg) {
|
|
moreTextLink.text('more').show();
|
|
moreTextLink.click(function(e) {
|
|
app.layout.showDialog('text-message', {d1: $(this).attr('data-sender-id')});
|
|
return false;
|
|
});
|
|
}
|
|
else {
|
|
moreTextLink.hide();
|
|
}
|
|
return markedUpMsg;
|
|
}
|
|
|
|
// we handled the notification, meaning the dialog showed this message as a chat message
|
|
function handledNotification(payload) {
|
|
return showing && payload.description == "TEXT_MESSAGE" && payload.sender_id == otherId;
|
|
}
|
|
|
|
function afterShow(args) {
|
|
$textBox.focus();
|
|
}
|
|
|
|
function beforeShow(args) {
|
|
|
|
app.layout.closeDialog('text-message') // ensure no others are showing. this is a singleton dialog
|
|
|
|
app.user()
|
|
.done(function(userDetail) {
|
|
user = userDetail;
|
|
|
|
var other = args.d1;
|
|
|
|
if(!other) throw "other must be specified in TextMessageDialog"
|
|
otherId = other;
|
|
|
|
showing = true;
|
|
|
|
userLookup[user.id] = user;
|
|
|
|
rest.getUserDetail({id: otherId})
|
|
.done(function(otherUser) {
|
|
|
|
userLookup[otherUser.id] = otherUser;
|
|
$dialog.find('.receiver-name').text(otherUser.name);
|
|
$dialog.find('textarea').attr('placeholder', 'enter a message to ' + otherUser.name + '...');
|
|
$dialog.find('.offline-tip').text('An email will be sent if ' + otherUser.name + ' is offline');
|
|
$sendTextMessage.click(sendMessage);
|
|
|
|
rest.getNotifications(buildParams())
|
|
.done(function(response) {
|
|
context._.each(response, function(textMessage) {
|
|
renderMessage(textMessage.message, textMessage.source_user_id, userLookup[textMessage.source_user_id].name, textMessage.created_at);
|
|
})
|
|
|
|
scrollToBottom(true);
|
|
fullyInitialized = true;
|
|
drainQueue();
|
|
})
|
|
.fail(function(jqXHR) {
|
|
app.notifyServerError(jqXHR, 'Unable to Load Conversation')
|
|
})
|
|
})
|
|
.fail(function(jqXHR) {
|
|
app.notifyServerError(jqXHR, 'Unable to Load Other User')
|
|
})
|
|
})
|
|
}
|
|
|
|
function afterHide() {
|
|
showing = false;
|
|
reset();
|
|
}
|
|
|
|
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) {
|
|
pasteIntoInput(this, "\n");
|
|
evt.preventDefault();
|
|
}
|
|
else if(evt.keyCode == 13 && !evt.shiftKey){
|
|
sendMessage();
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function events() {
|
|
$form.submit(sendMessage)
|
|
|
|
// http://stackoverflow.com/questions/6014702/how-do-i-detect-shiftenter-and-generate-a-new-line-in-textarea
|
|
$textBox.keydown(handleEnter);
|
|
}
|
|
|
|
|
|
function respondTextInvitation(args) {
|
|
app.layout.showDialog('text-message', {d1: args.sender_id}) ;
|
|
}
|
|
|
|
// called from sidebar when messages come in
|
|
function messageReceived(payload) {
|
|
if(showing && otherId == payload.sender_id) {
|
|
if(fullyInitialized) {
|
|
renderMessage(payload.msg, payload.sender_id, payload.sender_name, payload.created_at, true);
|
|
}
|
|
else {
|
|
// the dialog caught a message as it was initializing... queue it for later once dialog is showing
|
|
renderQueue.push({msg: payload.msg, senderId: payload.sender_id, senderName: payload.sender_name, sent: msg.created_at});
|
|
}
|
|
}
|
|
else {
|
|
payload.msg = formatTextMessage(payload.msg, payload.sender_id, payload.sender_name, payload.clipped_msg);
|
|
|
|
app.notify({
|
|
"title": "Message from " + payload.sender_name,
|
|
"text": payload.msg,
|
|
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
|
}, {
|
|
"ok_text": "REPLY",
|
|
"ok_callback": respondTextInvitation,
|
|
"ok_callback_args": {
|
|
"sender_id": payload.sender_id,
|
|
"notification_id": payload.notification_id
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
function showDialog(_other) {
|
|
|
|
app.layout.closeDialog('text-message') // this dialog is implemented as a singleton, so must enforce this
|
|
|
|
reset();
|
|
|
|
if(!_other) throw "other must be specified in TextMessageDialog"
|
|
otherId = _other;
|
|
|
|
app.layout.showDialog('text-message')
|
|
}*/
|
|
|
|
function initialize() {
|
|
var dialogBindings = {
|
|
'beforeShow' : beforeShow,
|
|
'afterShow' : afterShow,
|
|
'afterHide': afterHide
|
|
};
|
|
|
|
|
|
app.bindDialog('text-message', dialogBindings);
|
|
|
|
$dialog = $('#text-message-dialog');
|
|
$previousMessagesScroller = $dialog.find('.previous-messages-scroller');
|
|
$previousMessages = $dialog.find('.previous-messages');
|
|
$sendTextMessage = $dialog.find('.btn-send-text-message');
|
|
$form = $dialog.find('form');
|
|
$textBox = $form.find('textarea');
|
|
|
|
events();
|
|
}
|
|
|
|
this.initialize = initialize;
|
|
this.messageReceived = messageReceived;
|
|
this.formatTextMessage = formatTextMessage;
|
|
this.handledNotification = handledNotification;
|
|
}
|
|
|
|
return this;
|
|
})(window,jQuery);
|