2012-06-23 14:26:04 +02:00
|
|
|
var helpers = (function (helpers) {
|
|
|
|
helpers.oc = function (a) {
|
|
|
|
// Thanks to Jonathan Snook: http://snook.ca
|
|
|
|
var o = {};
|
|
|
|
for(var i=0; i<a.length; i++) {
|
|
|
|
o[a[i]]='';
|
|
|
|
}
|
|
|
|
return o;
|
|
|
|
};
|
2012-06-24 11:24:10 +02:00
|
|
|
|
|
|
|
helpers.hash = function (str) {
|
2012-06-23 14:26:04 +02:00
|
|
|
// FIXME
|
|
|
|
if (str == 'online-users-container') {
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
var shaobj = new jsSHA(str);
|
|
|
|
return shaobj.getHash("HEX");
|
|
|
|
};
|
|
|
|
return helpers;
|
|
|
|
})(helpers || {});
|
|
|
|
|
2012-07-08 12:27:13 +02:00
|
|
|
|
2012-06-23 14:26:04 +02:00
|
|
|
var xmppchat = (function (jarnxmpp, $, console) {
|
|
|
|
var ob = jarnxmpp;
|
2012-06-24 13:16:19 +02:00
|
|
|
/* FIXME: XEP-0136 specifies 'urn:xmpp:archive' but the mod_archive_odbc
|
|
|
|
* add-on for ejabberd wants the URL below. This might break for other
|
|
|
|
* Jabber servers.
|
|
|
|
*/
|
|
|
|
ob.Collections = {
|
|
|
|
'URI': 'http://www.xmpp.org/extensions/xep-0136.html#ns'
|
|
|
|
};
|
2012-06-23 14:26:04 +02:00
|
|
|
ob.Messages = jarnxmpp.Messages || {};
|
|
|
|
ob.Presence = jarnxmpp.Presence || {};
|
|
|
|
|
2012-07-01 12:03:43 +02:00
|
|
|
ob.Messages.ClientStorage = (function () {
|
|
|
|
methods = {};
|
|
|
|
|
|
|
|
methods.addMessage = function (jid, msg, direction) {
|
|
|
|
var bare_jid = Strophe.getBareJidFromJid(jid),
|
|
|
|
now = new Date().toISOString(),
|
|
|
|
msgs = store.get(bare_jid) || [];
|
|
|
|
if (msgs.length >= 30) {
|
2012-07-01 19:48:18 +02:00
|
|
|
msgs.shift();
|
2012-07-01 12:03:43 +02:00
|
|
|
}
|
|
|
|
msgs.push(now+' '+direction+' '+msg);
|
|
|
|
store.set(bare_jid, msgs);
|
|
|
|
};
|
|
|
|
|
|
|
|
methods.getMessages = function (jid) {
|
|
|
|
return store.get(jid) || [];
|
|
|
|
};
|
|
|
|
return methods;
|
|
|
|
})();
|
|
|
|
|
|
|
|
ob.Messages.getMessages = function (jid, callback) {
|
|
|
|
var bare_jid = Strophe.getBareJidFromJid(jid),
|
|
|
|
msgs = this.ClientStorage.getMessages(bare_jid);
|
|
|
|
callback(msgs);
|
|
|
|
};
|
|
|
|
|
2012-07-01 12:44:38 +02:00
|
|
|
ob.Messages.sendMessage = function (jid, text, callback) {
|
2012-06-23 14:26:04 +02:00
|
|
|
// TODO: Look in ChatPartners to see what resources we have for the recipient.
|
|
|
|
// if we have one resource, we sent to only that resources, if we have multiple
|
|
|
|
// we send to the bare jid.
|
2012-07-01 12:03:43 +02:00
|
|
|
// FIXME: see if @@content-transform is required
|
|
|
|
var message,
|
|
|
|
that = this;
|
2012-06-23 14:26:04 +02:00
|
|
|
$.getJSON(portal_url + '/content-transform?', {text: text}, function (data) {
|
2012-07-01 12:44:38 +02:00
|
|
|
message = $msg({to: jid, type: 'chat'})
|
|
|
|
.c('body').t(data.text).up()
|
|
|
|
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'});
|
2012-06-23 14:26:04 +02:00
|
|
|
xmppchat.connection.send(message);
|
2012-07-01 12:44:38 +02:00
|
|
|
that.ClientStorage.addMessage(jid, data.text, 'to');
|
2012-06-23 14:26:04 +02:00
|
|
|
callback();
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
ob.Messages.messageReceived = function (message) {
|
|
|
|
var jid = $(message).attr('from'),
|
|
|
|
bare_jid = Strophe.getBareJidFromJid(jid),
|
|
|
|
resource = Strophe.getResourceFromJid(jid),
|
2012-07-01 13:12:02 +02:00
|
|
|
delayed = $(message).find('delay').length > 0,
|
|
|
|
body = $(message).children('body').text(),
|
2012-06-23 14:26:04 +02:00
|
|
|
event = jQuery.Event('jarnxmpp.message');
|
|
|
|
|
2012-07-01 13:12:02 +02:00
|
|
|
if (body !== "") {
|
|
|
|
var xhtml_body = $(message).find('html > body').contents();
|
|
|
|
if (xhtml_body.length > 0) {
|
|
|
|
event.mtype = 'xhtml';
|
|
|
|
event.body = xhtml_body.html();
|
|
|
|
} else {
|
|
|
|
event.body = body;
|
|
|
|
event.mtype = 'text';
|
|
|
|
}
|
|
|
|
}
|
2012-06-23 14:26:04 +02:00
|
|
|
event.from = jid;
|
|
|
|
event.delayed = delayed;
|
2012-07-01 13:12:02 +02:00
|
|
|
event.message = message;
|
|
|
|
ob.ChatPartners.add(bare_jid, resource);
|
|
|
|
if (event.body) {
|
|
|
|
ob.Messages.ClientStorage.addMessage(jid, event.body, 'from');
|
2012-06-23 14:26:04 +02:00
|
|
|
}
|
2012-07-01 19:48:18 +02:00
|
|
|
if ((xmppchat.Storage.get(xmppchat.username+'-xmpp-status') || 'online') !== 'offline') {
|
|
|
|
// Only trigger the UI event if the user is not offline.
|
|
|
|
$(document).trigger(event);
|
|
|
|
}
|
2012-06-23 14:26:04 +02:00
|
|
|
return true;
|
|
|
|
};
|
|
|
|
|
2012-06-24 13:16:19 +02:00
|
|
|
ob.Collections.getLastCollection = function (jid, callback) {
|
|
|
|
var bare_jid = Strophe.getBareJidFromJid(jid),
|
|
|
|
iq = $iq({'type':'get'})
|
|
|
|
.c('list', {'xmlns': this.URI,
|
|
|
|
'with': bare_jid
|
2012-06-23 14:26:04 +02:00
|
|
|
})
|
|
|
|
.c('set', {'xmlns': 'http://jabber.org/protocol/rsm'})
|
2012-06-24 13:16:19 +02:00
|
|
|
.c('before').up()
|
2012-06-23 14:26:04 +02:00
|
|
|
.c('max')
|
2012-06-24 13:16:19 +02:00
|
|
|
.t('1');
|
|
|
|
|
|
|
|
xmppchat.connection.sendIQ(iq,
|
|
|
|
callback,
|
|
|
|
function () {
|
|
|
|
console.log('Error while retrieving collections');
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
ob.Collections.getLastMessages = function (jid, callback) {
|
|
|
|
var that = this;
|
|
|
|
this.getLastCollection(jid, function (result) {
|
2012-06-25 09:28:24 +02:00
|
|
|
// Retrieve the last page of a collection (max 30 elements).
|
2012-06-24 13:16:19 +02:00
|
|
|
var $collection = $(result).find('chat'),
|
|
|
|
jid = $collection.attr('with'),
|
|
|
|
start = $collection.attr('start'),
|
|
|
|
iq = $iq({'type':'get'})
|
|
|
|
.c('retrieve', {'start': start,
|
|
|
|
'xmlns': that.URI,
|
|
|
|
'with': jid
|
|
|
|
})
|
|
|
|
.c('set', {'xmlns': 'http://jabber.org/protocol/rsm'})
|
|
|
|
.c('max')
|
|
|
|
.t('30');
|
2012-06-25 09:28:24 +02:00
|
|
|
xmppchat.connection.sendIQ(iq, callback);
|
2012-06-24 13:16:19 +02:00
|
|
|
});
|
2012-06-23 14:26:04 +02:00
|
|
|
};
|
|
|
|
|
2012-07-01 21:12:51 +02:00
|
|
|
ob.Presence.getOwnStatus = function () {
|
|
|
|
return xmppchat.Storage.get(xmppchat.username+'-xmpp-status');
|
|
|
|
};
|
|
|
|
|
2012-06-24 11:24:10 +02:00
|
|
|
ob.Presence.onlineCount = function () {
|
|
|
|
return xmppchat.ChatPartners.getTotal();
|
|
|
|
};
|
|
|
|
|
2012-06-23 14:26:04 +02:00
|
|
|
ob.Presence.sendPresence = function (type) {
|
|
|
|
if (type === undefined) {
|
2012-07-01 21:12:51 +02:00
|
|
|
type = this.getOwnStatus() || 'online';
|
2012-06-23 14:26:04 +02:00
|
|
|
}
|
|
|
|
xmppchat.connection.send($pres({'type':type}));
|
|
|
|
};
|
|
|
|
|
|
|
|
ob.Taskbuffer = (function ($) {
|
2012-07-04 11:28:43 +02:00
|
|
|
// Executes tasks one after another (i.e next task is started only when
|
|
|
|
// the previous one has been completed).
|
2012-06-23 14:26:04 +02:00
|
|
|
buffer = {};
|
2012-07-04 11:28:43 +02:00
|
|
|
// Tasks must be objects with keys: 'that', 'method' and 'parameters'
|
|
|
|
// 'that' the context for the method, while 'parameters' is the list of arguments
|
|
|
|
// passed to it.
|
2012-06-23 14:26:04 +02:00
|
|
|
buffer.tasks = [];
|
|
|
|
buffer.deferred = $.when();
|
|
|
|
buffer.handleTasks = function () {
|
|
|
|
var task;
|
|
|
|
// If the current deferred task is resolved and there are more tasks
|
|
|
|
if (buffer.deferred.isResolved() && buffer.tasks.length > 0) {
|
|
|
|
// Get the next task in the queue and set the new deferred.
|
|
|
|
task = buffer.tasks.shift();
|
|
|
|
|
|
|
|
buffer.deferred = $.when(task.method.apply(task.that, task.parameters));
|
|
|
|
|
|
|
|
if (buffer.tasks.length > 0) {
|
|
|
|
buffer.deferred.done(buffer.handleTasks);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
return buffer;
|
|
|
|
})(jQuery);
|
|
|
|
|
|
|
|
return ob;
|
|
|
|
})(jarnxmpp || {}, jQuery, console || {log: function(){}});
|
|
|
|
|
2012-07-08 12:27:13 +02:00
|
|
|
|
2012-07-08 22:18:49 +02:00
|
|
|
xmppchat.ChatBox = Backbone.Model.extend({
|
2012-07-09 18:47:50 +02:00
|
|
|
|
|
|
|
hash: function (str) {
|
|
|
|
var shaobj = new jsSHA(str);
|
|
|
|
return shaobj.getHash("HEX");
|
|
|
|
},
|
|
|
|
|
|
|
|
initialize: function () {
|
|
|
|
this.set({
|
|
|
|
'user_id' : Strophe.getNodeFromJid(this.get('jid')),
|
|
|
|
'chat_id' : this.hash(this.get('jid'))
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
xmppchat.ChatBoxView = Backbone.View.extend({
|
|
|
|
|
2012-07-09 22:22:08 +02:00
|
|
|
tagName: 'div',
|
|
|
|
className: 'chatbox',
|
|
|
|
|
|
|
|
events: {
|
2012-07-11 16:16:17 +02:00
|
|
|
'click .close-chatbox-button': 'closeChat'
|
2012-07-09 22:22:08 +02:00
|
|
|
},
|
|
|
|
|
2012-07-11 16:16:17 +02:00
|
|
|
addChatToCookie: function () {
|
|
|
|
var cookie = jQuery.cookie('chats-open-'+xmppchat.username),
|
|
|
|
jid = this.model.get('jid'),
|
|
|
|
new_cookie,
|
|
|
|
open_chats = [];
|
|
|
|
|
|
|
|
if (cookie) {
|
|
|
|
open_chats = cookie.split('|');
|
|
|
|
}
|
|
|
|
if (!_.has(open_chats, jid)) {
|
|
|
|
// Update the cookie if this new chat is not yet in it.
|
|
|
|
open_chats.push(jid);
|
|
|
|
new_cookie = open_chats.join('|');
|
|
|
|
jQuery.cookie('chats-open-'+xmppchat.username, new_cookie, {path: '/'});
|
|
|
|
console.log('updated cookie = ' + new_cookie + '\n');
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
removeChatFromCookie: function () {
|
|
|
|
var cookie = jQuery.cookie('chats-open-'+xmppchat.username),
|
|
|
|
open_chats = [],
|
|
|
|
new_chats = [];
|
|
|
|
|
|
|
|
if (cookie) {
|
|
|
|
open_chats = cookie.split('|');
|
|
|
|
}
|
|
|
|
for (var i=0; i < open_chats.length; i++) {
|
|
|
|
if (open_chats[i] != this.model.get('jid')) {
|
|
|
|
new_chats.push(open_chats[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (new_chats.length) {
|
|
|
|
jQuery.cookie('chats-open-'+xmppchat.username, new_chats.join('|'), {path: '/'});
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
jQuery.cookie('chats-open-'+xmppchat.username, null, {path: '/'});
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
closeChat: function () {
|
2012-07-09 22:22:08 +02:00
|
|
|
var that = this;
|
|
|
|
$('#'+this.model.get('chat_id')).hide('fast', function () {
|
2012-07-11 16:16:17 +02:00
|
|
|
that.removeChatFromCookie(that.model.get('id'));
|
|
|
|
// Only reorder chats if it wasn't the last chat being closed.
|
|
|
|
var offset = parseInt($(that.el).css('right'), 10) + xmppchat.chatboxesview.chatbox_width;
|
|
|
|
if ($("div[style*='right: "+offset+"px']").length > 0) {
|
|
|
|
xmppchat.chatboxesview.reorderChats();
|
|
|
|
}
|
2012-07-09 22:22:08 +02:00
|
|
|
});
|
|
|
|
},
|
|
|
|
|
2012-07-09 18:47:50 +02:00
|
|
|
initialize: function (){
|
|
|
|
$('body').append($(this.el).hide());
|
|
|
|
},
|
|
|
|
|
|
|
|
template: _.template('<div class="chat-head chat-head-chatbox">' +
|
|
|
|
'<div class="chat-title"> <%= user_id %> </div>' +
|
|
|
|
'<a href="javascript:void(0)" class="chatbox-button close-chatbox-button">X</a>' +
|
|
|
|
'<br clear="all"/>' +
|
|
|
|
'</div>' +
|
|
|
|
'<div class="chat-content"></div>' +
|
|
|
|
'<form class="sendXMPPMessage" action="" method="post">' +
|
|
|
|
'<textarea ' +
|
|
|
|
'type="text" ' +
|
|
|
|
'class="chat-textarea" ' +
|
|
|
|
'placeholder="Personal message"/>'),
|
|
|
|
|
|
|
|
render: function () {
|
|
|
|
$(this.el).attr('id', this.model.get('chat_id'));
|
|
|
|
$(this.el).html(this.template(this.model.toJSON()));
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
2012-07-09 22:22:08 +02:00
|
|
|
isVisible: function () {
|
|
|
|
return $(this.el).is(':visible');
|
|
|
|
},
|
|
|
|
|
|
|
|
focus: function () {
|
|
|
|
$(this.el).find('.chat-textarea').focus();
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
2012-07-11 16:16:17 +02:00
|
|
|
show: function () {
|
2012-07-09 22:22:08 +02:00
|
|
|
var that = this;
|
|
|
|
$(this.el).show('fast', function () {
|
|
|
|
that.focus();
|
|
|
|
});
|
|
|
|
return this;
|
2012-07-09 18:47:50 +02:00
|
|
|
}
|
2012-07-11 16:16:17 +02:00
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
xmppchat.ControlBox = xmppchat.ChatBox.extend({
|
|
|
|
|
|
|
|
initialize: function () {
|
|
|
|
this.set({
|
|
|
|
'chat_id' : 'online-users-container'
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
xmppchat.ControlBoxView = xmppchat.ChatBoxView.extend({
|
|
|
|
|
|
|
|
el: '#online-users-container',
|
|
|
|
events: {
|
|
|
|
'click a.close-controlbox-button': 'closeChat'
|
|
|
|
},
|
|
|
|
|
|
|
|
render: function () {
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
|
|
|
show: function () {
|
|
|
|
$(this.el).show();
|
|
|
|
return this;
|
|
|
|
}
|
2012-07-08 22:18:49 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
xmppchat.ChatBoxes = Backbone.Collection.extend({
|
|
|
|
});
|
|
|
|
|
2012-07-09 18:47:50 +02:00
|
|
|
xmppchat.ChatBoxesView = Backbone.View.extend({
|
2012-07-09 22:22:08 +02:00
|
|
|
|
2012-07-11 16:16:17 +02:00
|
|
|
chatbox_width: 212,
|
|
|
|
chatbox_padding: 15,
|
|
|
|
|
|
|
|
restoreOpenChats: function () {
|
|
|
|
var cookie = jQuery.cookie('chats-open-'+xmppchat.username),
|
|
|
|
open_chats = [];
|
|
|
|
|
|
|
|
jQuery.cookie('chats-open-'+xmppchat.username, null, {path: '/'});
|
|
|
|
if (cookie) {
|
|
|
|
open_chats = cookie.split('|');
|
|
|
|
if (_.indexOf(open_chats, 'online-users-container') != -1) {
|
|
|
|
this.createChat('online-users-container');
|
|
|
|
}
|
|
|
|
for (var i=0; i<open_chats.length; i++) {
|
|
|
|
if (open_chats[i] === 'online-users-container') {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
this.createChat(open_chats[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
2012-07-09 22:22:08 +02:00
|
|
|
|
2012-07-11 16:16:17 +02:00
|
|
|
createChat: function (jid) {
|
|
|
|
if (jid === 'online-users-container') {
|
|
|
|
chatbox = new xmppchat.ControlBox({'id': jid, 'jid': jid});
|
|
|
|
view = new xmppchat.ControlBoxView({
|
|
|
|
model: chatbox
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
chatbox = new xmppchat.ChatBox({'id': jid, 'jid': jid});
|
|
|
|
view = new xmppchat.ChatBoxView({
|
|
|
|
model: chatbox
|
|
|
|
});
|
2012-07-09 22:22:08 +02:00
|
|
|
}
|
2012-07-11 16:16:17 +02:00
|
|
|
this.views[jid] = view.render();
|
|
|
|
this.options.model.add(chatbox);
|
|
|
|
},
|
|
|
|
|
|
|
|
closeChat: function (jid) {
|
|
|
|
var view = this.views[jid];
|
|
|
|
if (view) {
|
|
|
|
view.closeChat();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
openChat: function (jid) {
|
|
|
|
if (!this.model.get(jid)) {
|
|
|
|
this.createChat(jid);
|
|
|
|
} else {
|
|
|
|
this.positionNewChat(jid);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
positionNewChat: function (jid) {
|
|
|
|
//FIXME: Sort the deferred stuff out
|
|
|
|
var view = this.views[jid],
|
|
|
|
that = this,
|
|
|
|
open_chats = 0,
|
|
|
|
offset;
|
|
|
|
|
|
|
|
|
|
|
|
if (view.isVisible()) {
|
|
|
|
view.focus();
|
|
|
|
} else {
|
|
|
|
if (jid === 'online-users-container') {
|
|
|
|
offset = this.chatbox_padding;
|
|
|
|
$(view.el).css({'right': (offset+'px')});
|
|
|
|
$(view.el).show('fast', function () {
|
|
|
|
view.el.focus();
|
|
|
|
that.reorderChats();
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
for (var i=0; i<this.model.models.length; i++) {
|
|
|
|
if ($("#"+this.model.models[i].get('chat_id')).is(':visible')) {
|
|
|
|
open_chats++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
offset = (open_chats)*(this.chatbox_width)+this.chatbox_padding;
|
|
|
|
$(view.el).css({'right': (offset+'px')});
|
|
|
|
$(view.el).show('fast', function () {
|
|
|
|
view.el.focus();
|
|
|
|
});
|
2012-07-09 22:22:08 +02:00
|
|
|
}
|
2012-07-11 16:16:17 +02:00
|
|
|
view.addChatToCookie();
|
2012-07-09 22:22:08 +02:00
|
|
|
}
|
2012-07-11 16:16:17 +02:00
|
|
|
return view;
|
2012-07-09 22:22:08 +02:00
|
|
|
},
|
|
|
|
|
2012-07-11 16:16:17 +02:00
|
|
|
reorderChats: function () {
|
2012-07-09 22:22:08 +02:00
|
|
|
var index = 0,
|
|
|
|
offset,
|
2012-07-11 16:16:17 +02:00
|
|
|
chat_id,
|
2012-07-09 22:22:08 +02:00
|
|
|
$chat;
|
2012-07-09 18:47:50 +02:00
|
|
|
|
2012-07-11 16:16:17 +02:00
|
|
|
if (this.model.get('online-users-container')) {
|
|
|
|
$chat = $("#online-users-container");
|
|
|
|
if ($chat.is(':visible')) {
|
|
|
|
offset = (index)*(this.chatbox_width)+this.chatbox_padding;
|
|
|
|
$chat.animate({'right': offset +'px'});
|
|
|
|
index = 1;
|
|
|
|
}
|
2012-07-09 22:22:08 +02:00
|
|
|
}
|
|
|
|
for (var i=0; i<this.model.models.length; i++) {
|
2012-07-11 16:16:17 +02:00
|
|
|
chat_id = this.model.models[i].get('chat_id');
|
|
|
|
if (chat_id === 'online-users-container') {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
$chat = $("#"+chat_id);
|
2012-07-09 22:22:08 +02:00
|
|
|
if ($chat.is(':visible')) {
|
|
|
|
if (index === 0) {
|
|
|
|
$chat.animate({'right': '15px'});
|
|
|
|
}
|
|
|
|
else {
|
2012-07-11 16:16:17 +02:00
|
|
|
offset = (index)*(this.chatbox_width)+this.chatbox_padding;
|
2012-07-09 22:22:08 +02:00
|
|
|
$chat.animate({'right': offset +'px'});
|
|
|
|
}
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
}
|
2012-07-09 18:47:50 +02:00
|
|
|
},
|
|
|
|
|
2012-07-09 22:22:08 +02:00
|
|
|
initialize: function () {
|
2012-07-11 16:16:17 +02:00
|
|
|
this.options.model.on("add", function (item) {
|
|
|
|
this.positionNewChat(item.get('id'));
|
|
|
|
}, this);
|
|
|
|
|
2012-07-09 22:22:08 +02:00
|
|
|
this.views = {};
|
2012-07-11 16:16:17 +02:00
|
|
|
this.restoreOpenChats();
|
2012-07-09 22:22:08 +02:00
|
|
|
|
2012-07-09 18:47:50 +02:00
|
|
|
}
|
2012-07-08 22:18:49 +02:00
|
|
|
});
|
|
|
|
|
2012-07-09 18:47:50 +02:00
|
|
|
|
2012-07-08 12:27:13 +02:00
|
|
|
xmppchat.RosterItem = Backbone.Model.extend({
|
2012-07-09 22:22:08 +02:00
|
|
|
|
2012-07-08 12:27:13 +02:00
|
|
|
initialize: function (jid, subscription) {
|
2012-07-09 22:22:08 +02:00
|
|
|
// FIXME: the fullname is set to user_id for now...
|
|
|
|
var user_id = Strophe.getNodeFromJid(jid);
|
|
|
|
|
|
|
|
this.set({
|
|
|
|
'id': jid,
|
|
|
|
'jid': jid,
|
|
|
|
'bare_jid': Strophe.getBareJidFromJid(jid),
|
|
|
|
'user_id': user_id,
|
|
|
|
'subscription': subscription,
|
|
|
|
'fullname': user_id,
|
|
|
|
'resources': [],
|
|
|
|
'status': 'offline'
|
|
|
|
}, {'silent': true});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
xmppchat.RosterItemView = Backbone.View.extend({
|
|
|
|
|
|
|
|
tagName: 'li',
|
|
|
|
events: {
|
2012-07-11 16:16:17 +02:00
|
|
|
'click': 'openChat'
|
2012-07-09 22:22:08 +02:00
|
|
|
},
|
|
|
|
|
2012-07-11 16:16:17 +02:00
|
|
|
openChat: function (e) {
|
2012-07-09 22:22:08 +02:00
|
|
|
e.preventDefault();
|
|
|
|
var jid = this.model.get('jid');
|
2012-07-11 16:16:17 +02:00
|
|
|
xmppchat.chatboxesview.openChat(jid);
|
2012-07-09 22:22:08 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
initialize: function () {
|
|
|
|
var that = this;
|
|
|
|
this.options.model.on('change', function (item, changed) {
|
|
|
|
if (_.has(changed.changes, 'status')) {
|
|
|
|
$(this.el).attr('class', item.changed.status);
|
|
|
|
}
|
|
|
|
}, this);
|
|
|
|
},
|
2012-07-08 12:27:13 +02:00
|
|
|
|
2012-07-09 22:22:08 +02:00
|
|
|
template: _.template(
|
|
|
|
'<a title="Click to chat with this contact"><%= fullname %></a>' +
|
|
|
|
'<a title="Click to remove this contact" class="remove-xmpp-contact" href="#"></a>'),
|
|
|
|
|
|
|
|
render: function () {
|
|
|
|
var item = this.model;
|
|
|
|
$(this.el).addClass(item.get('status')).attr('id', 'online-users-'+item.get('user_id'));
|
|
|
|
$(this.el).html(this.template(item.toJSON()));
|
|
|
|
return this;
|
2012-07-08 12:27:13 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2012-07-09 22:22:08 +02:00
|
|
|
|
2012-07-08 12:27:13 +02:00
|
|
|
xmppchat.RosterClass = (function (stropheRoster, _, $, console) {
|
2012-07-08 22:18:49 +02:00
|
|
|
var ob = _.clone(stropheRoster),
|
|
|
|
Collection = Backbone.Collection.extend({
|
2012-07-09 18:47:50 +02:00
|
|
|
model: xmppchat.RosterItem,
|
|
|
|
stropheRoster: stropheRoster,
|
|
|
|
|
|
|
|
initialize: function () {
|
|
|
|
this.stropheRoster._connection = xmppchat.connection;
|
|
|
|
},
|
|
|
|
|
|
|
|
comparator : function (rosteritem) {
|
|
|
|
var status = rosteritem.get('status'),
|
|
|
|
rank = 4;
|
|
|
|
switch(status) {
|
|
|
|
case 'offline':
|
|
|
|
rank = 4;
|
|
|
|
break;
|
|
|
|
case 'unavailable':
|
|
|
|
rank = 3;
|
|
|
|
break;
|
|
|
|
case 'away':
|
|
|
|
rank = 2;
|
|
|
|
break;
|
|
|
|
case 'busy':
|
|
|
|
rank = 1;
|
|
|
|
break;
|
|
|
|
case 'online':
|
|
|
|
rank = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return rank;
|
|
|
|
},
|
|
|
|
|
|
|
|
isSelf: function (jid) {
|
|
|
|
return (Strophe.getBareJidFromJid(jid) === Strophe.getBareJidFromJid(xmppchat.connection.jid));
|
|
|
|
},
|
|
|
|
|
|
|
|
getRoster: function () {
|
|
|
|
return stropheRoster.get();
|
|
|
|
},
|
|
|
|
|
|
|
|
getItem: function (id) {
|
|
|
|
return Backbone.Collection.prototype.get.call(this, id);
|
|
|
|
},
|
|
|
|
|
2012-07-09 22:22:08 +02:00
|
|
|
addRosterItem: function (jid, subscription) {
|
|
|
|
var model = new xmppchat.RosterItem(jid, subscription);
|
2012-07-09 18:47:50 +02:00
|
|
|
this.add(model);
|
|
|
|
},
|
|
|
|
|
|
|
|
addResource: function (bare_jid, resource) {
|
|
|
|
var item = this.getItem(bare_jid);
|
2012-07-09 22:22:08 +02:00
|
|
|
resources;
|
2012-07-09 18:47:50 +02:00
|
|
|
if (item) {
|
2012-07-09 22:22:08 +02:00
|
|
|
resources = item.get('resources');
|
|
|
|
if (_.indexOf(resources, resource) == -1) {
|
|
|
|
resources.push(resource);
|
|
|
|
item.set({'resources': resources});
|
2012-07-09 18:47:50 +02:00
|
|
|
}
|
|
|
|
} else {
|
2012-07-09 22:22:08 +02:00
|
|
|
item.set({'resources': [resource]});
|
2012-07-09 18:47:50 +02:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
removeResource: function (bare_jid, resource) {
|
2012-07-09 22:22:08 +02:00
|
|
|
var item = this.getItem(bare_jid),
|
|
|
|
resources,
|
|
|
|
idx;
|
2012-07-09 18:47:50 +02:00
|
|
|
if (item) {
|
2012-07-09 22:22:08 +02:00
|
|
|
resources = item.get('resources');
|
|
|
|
idx = _.indexOf(resources, resource);
|
2012-07-09 18:47:50 +02:00
|
|
|
if (idx !== -1) {
|
2012-07-09 22:22:08 +02:00
|
|
|
resources.splice(idx, 1);
|
|
|
|
item.set({'resources': resources});
|
|
|
|
return resources.length;
|
2012-07-09 18:47:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
},
|
2012-07-04 11:28:43 +02:00
|
|
|
|
2012-07-09 18:47:50 +02:00
|
|
|
clearResources: function (bare_jid) {
|
|
|
|
var item = this.getItem(bare_jid);
|
|
|
|
if (item) {
|
2012-07-09 22:22:08 +02:00
|
|
|
item.set({'resources': []});
|
2012-07-09 18:47:50 +02:00
|
|
|
}
|
|
|
|
},
|
2012-07-08 22:18:49 +02:00
|
|
|
|
2012-07-09 18:47:50 +02:00
|
|
|
getTotalResources: function (bare_jid) {
|
|
|
|
var item = this.getItem(bare_jid);
|
|
|
|
if (item) {
|
2012-07-09 22:22:08 +02:00
|
|
|
return _.size(item.get('resources'));
|
2012-07-09 18:47:50 +02:00
|
|
|
}
|
2012-07-08 22:18:49 +02:00
|
|
|
}
|
2012-07-09 18:47:50 +02:00
|
|
|
});
|
2012-07-08 22:18:49 +02:00
|
|
|
|
2012-07-09 18:47:50 +02:00
|
|
|
var collection = new Collection();
|
|
|
|
_.extend(ob, collection);
|
|
|
|
_.extend(ob, Backbone.Events);
|
2012-07-08 12:27:13 +02:00
|
|
|
|
|
|
|
ob.updateHandler = function (items) {
|
|
|
|
var model;
|
2012-07-04 11:28:43 +02:00
|
|
|
for (var i=0; i<items.length; i++) {
|
|
|
|
if (items[i].subscription === 'none') {
|
2012-07-08 12:27:13 +02:00
|
|
|
model = ob.getItem(jid);
|
|
|
|
ob.remove(model);
|
2012-07-04 11:28:43 +02:00
|
|
|
} else {
|
2012-07-08 12:27:13 +02:00
|
|
|
if (ob.getItem(items[i].jid)) {
|
|
|
|
// Update the model
|
|
|
|
model = ob.getItem(jid);
|
|
|
|
model.subscription = item.subscription;
|
|
|
|
} else {
|
2012-07-09 22:22:08 +02:00
|
|
|
ob.addRosterItem(items[i].jid, items[i].subscription);
|
2012-07-08 12:27:13 +02:00
|
|
|
}
|
2012-07-04 11:28:43 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-07-08 22:18:49 +02:00
|
|
|
ob.presenceHandler = function (presence) {
|
|
|
|
var jid = $(presence).attr('from'),
|
|
|
|
bare_jid = Strophe.getBareJidFromJid(jid),
|
|
|
|
resource = Strophe.getResourceFromJid(jid),
|
|
|
|
ptype = $(presence).attr('type'),
|
|
|
|
status = '';
|
2012-07-08 12:27:13 +02:00
|
|
|
|
2012-07-08 22:18:49 +02:00
|
|
|
if (ob.isSelf(bare_jid)) { return true; }
|
2012-07-08 12:27:13 +02:00
|
|
|
|
2012-07-08 22:18:49 +02:00
|
|
|
if (ptype === 'subscribe') {
|
|
|
|
// FIXME: User wants to subscribe to us. Always approve and
|
|
|
|
// ask to subscribe to him
|
|
|
|
stropheRoster.authorize(bare_jid);
|
|
|
|
stropheRoster.subscribe(bare_jid);
|
|
|
|
|
|
|
|
} else if (ptype === 'unsubscribe') {
|
|
|
|
if (_.indexOf(xmppchat.Roster.getCachedJids(), bare_jid) != -1) {
|
|
|
|
stropheRoster.unauthorize(bare_jid);
|
|
|
|
stropheRoster.unsubscribe(bare_jid);
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if (ptype === 'unsubscribed') {
|
|
|
|
return;
|
|
|
|
|
|
|
|
} else if (ptype !== 'error') { // Presence has changed
|
|
|
|
if (_.indexOf(['unavailable', 'offline', 'busy', 'away'], ptype) != -1) {
|
|
|
|
status = ptype;
|
|
|
|
} else {
|
|
|
|
status = ($(presence).find('show').text() === '') ? 'online' : 'away';
|
|
|
|
}
|
|
|
|
if ((status !== 'offline')&&(status !== 'unavailable')) {
|
|
|
|
ob.addResource(bare_jid, resource);
|
|
|
|
model = ob.getItem(bare_jid);
|
|
|
|
model.set({'status': status});
|
|
|
|
} else {
|
|
|
|
if (ob.removeResource(bare_jid, resource) === 0) {
|
|
|
|
model = ob.getItem(bare_jid);
|
|
|
|
model.set({'status': status});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
};
|
2012-07-08 12:27:13 +02:00
|
|
|
return ob;
|
|
|
|
});
|
|
|
|
|
|
|
|
|
2012-07-09 22:22:08 +02:00
|
|
|
xmppchat.RosterView= (function (roster, _, $, console) {
|
2012-07-08 12:27:13 +02:00
|
|
|
var View = Backbone.View.extend({
|
|
|
|
el: $('#xmpp-contacts'),
|
|
|
|
model: roster,
|
2012-07-09 22:22:08 +02:00
|
|
|
rosteritemviews: [],
|
2012-07-08 12:27:13 +02:00
|
|
|
|
2012-07-08 22:18:49 +02:00
|
|
|
initialize: function () {
|
|
|
|
this.model.on("add", function (item) {
|
2012-07-09 22:22:08 +02:00
|
|
|
$(this.el).append((new xmppchat.RosterItemView({model: item})).render().el);
|
2012-07-08 22:18:49 +02:00
|
|
|
}, this);
|
|
|
|
|
|
|
|
this.model.on('change', function (item) {
|
|
|
|
this.render();
|
|
|
|
}, this);
|
|
|
|
|
|
|
|
this.model.on("remove", function (msg) {
|
|
|
|
console.log('roster remove handler called!!!!!');
|
|
|
|
});
|
|
|
|
},
|
2012-07-08 12:27:13 +02:00
|
|
|
|
|
|
|
render: function () {
|
2012-07-08 22:18:49 +02:00
|
|
|
var models = this.model.sort().models,
|
|
|
|
children = $(this.el).children(),
|
|
|
|
that = this;
|
|
|
|
|
|
|
|
$(models).each(function (idx, model) {
|
|
|
|
var user_id = Strophe.getNodeFromJid(model.id);
|
|
|
|
$(that.el).append(children.filter('#online-users-'+user_id));
|
|
|
|
});
|
2012-07-08 12:27:13 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
var view = new View();
|
2012-07-08 22:18:49 +02:00
|
|
|
return view;
|
2012-07-04 11:28:43 +02:00
|
|
|
});
|
|
|
|
|
2012-06-23 14:26:04 +02:00
|
|
|
|
2012-07-03 13:15:45 +02:00
|
|
|
// Event handlers
|
|
|
|
// --------------
|
|
|
|
$(document).ready(function () {
|
2012-07-11 16:16:17 +02:00
|
|
|
var chatdata = jQuery('span#babble-client-chatdata'),
|
|
|
|
$toggle = $('a#toggle-online-users');
|
|
|
|
|
|
|
|
$toggle.unbind('click');
|
|
|
|
|
|
|
|
xmppchat.username = chatdata.attr('username');
|
|
|
|
xmppchat.base_url = chatdata.attr('base_url');
|
|
|
|
|
2012-07-03 13:15:45 +02:00
|
|
|
$(document).unbind('jarnxmpp.connected');
|
|
|
|
$(document).bind('jarnxmpp.connected', function () {
|
2012-07-11 16:16:17 +02:00
|
|
|
// FIXME: Need to get some convention going for naming classes and instances of
|
|
|
|
// models and views.
|
|
|
|
|
2012-07-03 13:15:45 +02:00
|
|
|
// Messages
|
|
|
|
xmppchat.connection.addHandler(xmppchat.Messages.messageReceived, null, 'message', 'chat');
|
2012-07-08 12:27:13 +02:00
|
|
|
xmppchat.Roster = xmppchat.RosterClass(Strophe._connectionPlugins.roster, _, $, console);
|
2012-07-09 22:22:08 +02:00
|
|
|
xmppchat.rosterview = Backbone.View.extend(xmppchat.RosterView(xmppchat.Roster, _, $, console));
|
2012-07-08 22:18:49 +02:00
|
|
|
|
|
|
|
xmppchat.connection.addHandler(xmppchat.Roster.presenceHandler, null, 'presence', null);
|
2012-07-08 12:27:13 +02:00
|
|
|
|
|
|
|
xmppchat.Roster.registerCallback(xmppchat.Roster.updateHandler);
|
|
|
|
xmppchat.Roster.getRoster();
|
2012-07-03 13:15:45 +02:00
|
|
|
xmppchat.Presence.sendPresence();
|
2012-07-09 18:47:50 +02:00
|
|
|
|
|
|
|
xmppchat.chatboxes = new xmppchat.ChatBoxes();
|
|
|
|
|
|
|
|
xmppchat.chatboxesview = new xmppchat.ChatBoxesView({
|
|
|
|
'model': xmppchat.chatboxes
|
|
|
|
});
|
2012-07-11 16:16:17 +02:00
|
|
|
|
|
|
|
$toggle.bind('click', function (e) {
|
|
|
|
e.preventDefault();
|
|
|
|
if ($("div#online-users-container").is(':visible')) {
|
|
|
|
xmppchat.chatboxesview.closeChat('online-users-container');
|
|
|
|
} else {
|
|
|
|
xmppchat.chatboxesview.openChat('online-users-container');
|
|
|
|
}
|
|
|
|
});
|
2012-07-03 13:15:45 +02:00
|
|
|
});
|
|
|
|
});
|