Rewrote more functionality to use backbone.js
This commit is contained in:
parent
d82e72613a
commit
385eb834f8
314
chat.js
314
chat.js
@ -32,59 +32,6 @@ var xmppchat = (function (jarnxmpp, $, console) {
|
|||||||
ob.Messages = jarnxmpp.Messages || {};
|
ob.Messages = jarnxmpp.Messages || {};
|
||||||
ob.Presence = jarnxmpp.Presence || {};
|
ob.Presence = jarnxmpp.Presence || {};
|
||||||
|
|
||||||
ob.isOwnUser = function (jid) {
|
|
||||||
return (Strophe.getBareJidFromJid(jid) === Strophe.getBareJidFromJid(xmppchat.connection.jid));
|
|
||||||
};
|
|
||||||
|
|
||||||
ob.ChatPartners = (function () {
|
|
||||||
/* A mapping of bare JIDs to resources, to keep track of
|
|
||||||
* how many resources we have per chat partner.
|
|
||||||
*/
|
|
||||||
var storage = {};
|
|
||||||
var methods = {};
|
|
||||||
|
|
||||||
methods.add = function (bare_jid, resource) {
|
|
||||||
if (Object.prototype.hasOwnProperty.call(storage, bare_jid)) {
|
|
||||||
if (_.indexOf(storage[bare_jid], resource) == -1) {
|
|
||||||
storage[bare_jid].push(resource);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
storage[bare_jid] = [resource];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
methods.remove = function (bare_jid, resource) {
|
|
||||||
// Removes the resource for a user and returns the number of
|
|
||||||
// resources left over.
|
|
||||||
if (_.has(storage, bare_jid)) {
|
|
||||||
var idx = _.indexOf(storage[bare_jid], resource);
|
|
||||||
if (idx !== -1) {
|
|
||||||
storage[bare_jid].splice(idx, 1);
|
|
||||||
if (storage[bare_jid].length === 0) {
|
|
||||||
delete storage[bare_jid];
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return storage[bare_jid].length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
methods.removeAll = function (bare_jid) {
|
|
||||||
if (Object.prototype.hasOwnProperty.call(storage, bare_jid)) {
|
|
||||||
delete storage[bare_jid];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
methods.getTotal = function () {
|
|
||||||
return _.size(storage);
|
|
||||||
};
|
|
||||||
|
|
||||||
return methods;
|
|
||||||
})();
|
|
||||||
|
|
||||||
ob.Messages.ClientStorage = (function () {
|
ob.Messages.ClientStorage = (function () {
|
||||||
methods = {};
|
methods = {};
|
||||||
|
|
||||||
@ -212,59 +159,6 @@ var xmppchat = (function (jarnxmpp, $, console) {
|
|||||||
xmppchat.connection.send($pres({'type':type}));
|
xmppchat.connection.send($pres({'type':type}));
|
||||||
};
|
};
|
||||||
|
|
||||||
ob.Presence.presenceReceived = function (presence) {
|
|
||||||
var jid = $(presence).attr('from'),
|
|
||||||
bare_jid = Strophe.getBareJidFromJid(jid),
|
|
||||||
resource = Strophe.getResourceFromJid(jid),
|
|
||||||
ptype = $(presence).attr('type'),
|
|
||||||
status = '';
|
|
||||||
|
|
||||||
if (ob.isOwnUser(bare_jid)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ptype === 'subscribe') {
|
|
||||||
// User wants to subscribe to us. Always approve and
|
|
||||||
// ask to subscribe to him
|
|
||||||
xmppchat.Roster.authorize(bare_jid);
|
|
||||||
xmppchat.Roster.subscribe(bare_jid);
|
|
||||||
|
|
||||||
} else if (ptype === 'unsubscribe') {
|
|
||||||
if (_.indexOf(xmppchat.Roster.getCachedJids(), bare_jid) != -1) {
|
|
||||||
xmppchat.Roster.unauthorize(bare_jid);
|
|
||||||
xmppchat.Roster.unsubscribe(bare_jid);
|
|
||||||
$(document).trigger('jarnxmpp.presence', [jid, 'unsubscribe', presence]);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (ptype === 'unsubscribed') {
|
|
||||||
return;
|
|
||||||
|
|
||||||
} else if (ptype !== 'error') { // Presence has changed
|
|
||||||
if (ptype === 'unavailable') {
|
|
||||||
status = 'unavailable';
|
|
||||||
} else if (ptype === 'offline') {
|
|
||||||
status = 'offline';
|
|
||||||
} else if (ptype === 'busy') {
|
|
||||||
status = 'busy';
|
|
||||||
} else if (ptype === 'away') {
|
|
||||||
status = 'away';
|
|
||||||
} else {
|
|
||||||
status = ($(presence).find('show').text() === '') ? 'online' : 'away';
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((status !== 'offline')&&(status !== 'unavailable')) {
|
|
||||||
xmppchat.ChatPartners.add(bare_jid, resource);
|
|
||||||
$(document).trigger('jarnxmpp.presence', [jid, status, presence]);
|
|
||||||
} else {
|
|
||||||
if (xmppchat.ChatPartners.remove(bare_jid, resource) === 0) {
|
|
||||||
// Only notify offline/unavailable if there aren't any other resources for that user
|
|
||||||
$(document).trigger('jarnxmpp.presence', [jid, status, presence]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
ob.Taskbuffer = (function ($) {
|
ob.Taskbuffer = (function ($) {
|
||||||
// Executes tasks one after another (i.e next task is started only when
|
// Executes tasks one after another (i.e next task is started only when
|
||||||
// the previous one has been completed).
|
// the previous one has been completed).
|
||||||
@ -295,6 +189,15 @@ var xmppchat = (function (jarnxmpp, $, console) {
|
|||||||
})(jarnxmpp || {}, jQuery, console || {log: function(){}});
|
})(jarnxmpp || {}, jQuery, console || {log: function(){}});
|
||||||
|
|
||||||
|
|
||||||
|
xmppchat.ChatBox = Backbone.Model.extend({
|
||||||
|
});
|
||||||
|
|
||||||
|
xmppchat.ChatBoxes = Backbone.Collection.extend({
|
||||||
|
});
|
||||||
|
|
||||||
|
xmppchat.ChatBoxView = Backbone.View.extend({
|
||||||
|
});
|
||||||
|
|
||||||
xmppchat.RosterItem = Backbone.Model.extend({
|
xmppchat.RosterItem = Backbone.Model.extend({
|
||||||
/*
|
/*
|
||||||
* RosterItem: {
|
* RosterItem: {
|
||||||
@ -315,10 +218,8 @@ xmppchat.RosterItem = Backbone.Model.extend({
|
|||||||
});
|
});
|
||||||
|
|
||||||
xmppchat.RosterClass = (function (stropheRoster, _, $, console) {
|
xmppchat.RosterClass = (function (stropheRoster, _, $, console) {
|
||||||
var contacts = {},
|
var ob = _.clone(stropheRoster),
|
||||||
ob = _.clone(stropheRoster);
|
Collection = Backbone.Collection.extend({
|
||||||
|
|
||||||
var Collection = Backbone.Collection.extend({
|
|
||||||
model: xmppchat.RosterItem
|
model: xmppchat.RosterItem
|
||||||
});
|
});
|
||||||
var collection = new Collection();
|
var collection = new Collection();
|
||||||
@ -349,6 +250,10 @@ xmppchat.RosterClass = (function (stropheRoster, _, $, console) {
|
|||||||
return rank;
|
return rank;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ob.isSelf = function (jid) {
|
||||||
|
return (Strophe.getBareJidFromJid(jid) === Strophe.getBareJidFromJid(xmppchat.connection.jid));
|
||||||
|
};
|
||||||
|
|
||||||
ob.getRoster = function () {
|
ob.getRoster = function () {
|
||||||
return stropheRoster.get();
|
return stropheRoster.get();
|
||||||
};
|
};
|
||||||
@ -361,22 +266,43 @@ xmppchat.RosterClass = (function (stropheRoster, _, $, console) {
|
|||||||
var user_id = Strophe.getNodeFromJid(item.jid),
|
var user_id = Strophe.getNodeFromJid(item.jid),
|
||||||
model = new xmppchat.RosterItem(item.jid, item.subscription);
|
model = new xmppchat.RosterItem(item.jid, item.subscription);
|
||||||
ob.add(model);
|
ob.add(model);
|
||||||
/*
|
};
|
||||||
if (!item.name) {
|
|
||||||
// TODO: I think after a user has been added to the roster,
|
ob.addResource = function (bare_jid, resource) {
|
||||||
// his nickname needs to be calculated. This is only
|
var item = ob.getItem(bare_jid);
|
||||||
// feasible if the nickname is persisted. We cannot do this
|
if (item) {
|
||||||
// if we have to redo this upon every page load.
|
if (_.indexOf(item.resources, resource) == -1) {
|
||||||
xmppchat.Presence.getUserInfo(user_id, function (data) {
|
item.resources.push(resource);
|
||||||
ob.update(item.jid, data.fullname, [], function () {
|
}
|
||||||
// TODO Store in the model item.
|
} else {
|
||||||
model.fullname = data.fullname;
|
item.resources = [resource];
|
||||||
ob.add(model);
|
}
|
||||||
});
|
};
|
||||||
});
|
|
||||||
} else {
|
ob.removeResource = function (bare_jid, resource) {
|
||||||
ob.add(model);
|
var item = ob.getItem(bare_jid);
|
||||||
}*/
|
if (item) {
|
||||||
|
var idx = _.indexOf(item.resources, resource);
|
||||||
|
if (idx !== -1) {
|
||||||
|
item.resources.splice(idx, 1);
|
||||||
|
return item.resources.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
ob.clearResources = function (bare_jid) {
|
||||||
|
var item = ob.getItem(bare_jid);
|
||||||
|
if (item) {
|
||||||
|
item.resources = [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ob.getTotalResources = function (bare_jid) {
|
||||||
|
var item = ob.getItem(bare_jid);
|
||||||
|
if (item) {
|
||||||
|
return _.size(item.resources);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ob.updateHandler = function (items) {
|
ob.updateHandler = function (items) {
|
||||||
@ -396,78 +322,123 @@ xmppchat.RosterClass = (function (stropheRoster, _, $, console) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
/*
|
|
||||||
addResource: function (bare_jid, resource) {
|
|
||||||
},
|
|
||||||
|
|
||||||
removeResource: function (bare_jid, resource) {
|
ob.presenceHandler = function (presence) {
|
||||||
},
|
var jid = $(presence).attr('from'),
|
||||||
|
bare_jid = Strophe.getBareJidFromJid(jid),
|
||||||
|
resource = Strophe.getResourceFromJid(jid),
|
||||||
|
ptype = $(presence).attr('type'),
|
||||||
|
status = '';
|
||||||
|
|
||||||
removeAll: function (bare_jid) {
|
if (ob.isSelf(bare_jid)) { return true; }
|
||||||
// Remove all resources for bare_jid
|
|
||||||
},
|
|
||||||
|
|
||||||
getNumContacts: function () {
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
getJids: function () {
|
|
||||||
return _.keys(storage);
|
|
||||||
}*/
|
|
||||||
return ob;
|
return ob;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
xmppchat.RosterItemView = Backbone.View.extend({
|
xmppchat.RosterItemView = Backbone.View.extend({
|
||||||
tagName: 'li',
|
tagName: 'li',
|
||||||
|
|
||||||
|
initialize: function () {
|
||||||
|
this.el = this.make('li');
|
||||||
|
|
||||||
|
$(this.el).bind('click', function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
xmppchat.UI.getChatbox($(this).attr('data-recipient'));
|
||||||
|
});
|
||||||
|
|
||||||
|
this.options.model.on('change', function (item, changed) {
|
||||||
|
if (_.has(changed.changes, 'status')) {
|
||||||
|
$(this.el).attr('class', item.changed.status);
|
||||||
|
}
|
||||||
|
}, this);
|
||||||
|
},
|
||||||
|
|
||||||
render: function () {
|
render: function () {
|
||||||
var item = this.model,
|
var item = this.model,
|
||||||
jid = item.id,
|
jid = item.id,
|
||||||
bare_jid = Strophe.getBareJidFromJid(jid),
|
bare_jid = Strophe.getBareJidFromJid(jid),
|
||||||
user_id = Strophe.getNodeFromJid(jid),
|
user_id = Strophe.getNodeFromJid(jid),
|
||||||
fullname = (item.fullname) ? item.fullname : user_id;
|
fullname = (item.fullname) ? item.fullname : user_id;
|
||||||
|
$(this.el).addClass(item.status).attr('id', 'online-users-'+user_id).attr('data-recipient', bare_jid);
|
||||||
// FIXME: Here comes underscore templating
|
$(this.el).append($('<a title="Click to chat with this contact"></a>').text(fullname));
|
||||||
this.el = $('<li></li>').addClass(item.status).attr('id', 'online-users-'+user_id).attr('data-recipient', bare_jid);
|
$(this.el).append($('<a title="Click to remove this contact" href="#"></a>').addClass('remove-xmpp-contact'));
|
||||||
this.el.append($('<a title="Click to chat with this contact"></a>').addClass('user-details-toggle').text(fullname));
|
|
||||||
this.el.append($('<a title="Click to remove this contact" href="#"></a>').addClass('remove-xmpp-contact'));
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
xmppchat.RosterViewClass = (function (roster, _, $, console) {
|
xmppchat.RosterViewClass = (function (roster, _, $, console) {
|
||||||
ob = {};
|
|
||||||
var View = Backbone.View.extend({
|
var View = Backbone.View.extend({
|
||||||
tagName: 'ul',
|
tagName: 'ul',
|
||||||
el: $('#xmpp-contacts'),
|
el: $('#xmpp-contacts'),
|
||||||
model: roster,
|
model: roster,
|
||||||
|
|
||||||
// XXX: See if you can use the "events:" thingy here instead of
|
initialize: function () {
|
||||||
// manually registering the event subscribers below.
|
this.model.on("add", function (item) {
|
||||||
|
var view = new xmppchat.RosterItemView({
|
||||||
|
model: item
|
||||||
|
});
|
||||||
|
$(this.el).append(view.render().el);
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
this.model.on('change', function (item) {
|
||||||
|
this.render();
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
this.model.on("remove", function (msg) {
|
||||||
|
console.log('roster remove handler called!!!!!');
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
render: function () {
|
render: function () {
|
||||||
this.el.html($el.html());
|
var models = this.model.sort().models,
|
||||||
return this;
|
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));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
var view = new View();
|
var view = new View();
|
||||||
_.extend(ob, view);
|
return view;
|
||||||
|
|
||||||
// Event handlers
|
|
||||||
roster.on("add", function (item) {
|
|
||||||
console.log('roster add handler called');
|
|
||||||
var view = new xmppchat.RosterItemView({
|
|
||||||
model: item
|
|
||||||
});
|
|
||||||
$(ob.el).append(view.render().el);
|
|
||||||
});
|
|
||||||
|
|
||||||
roster.on("remove", function (msg) {
|
|
||||||
console.log('roster remove handler called!!!!!');
|
|
||||||
ob.render();
|
|
||||||
});
|
|
||||||
|
|
||||||
return ob;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// FIXME: Need to get some convention going for naming classes and instances of
|
// FIXME: Need to get some convention going for naming classes and instances of
|
||||||
@ -478,21 +449,14 @@ xmppchat.RosterViewClass = (function (roster, _, $, console) {
|
|||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
$(document).unbind('jarnxmpp.connected');
|
$(document).unbind('jarnxmpp.connected');
|
||||||
$(document).bind('jarnxmpp.connected', function () {
|
$(document).bind('jarnxmpp.connected', function () {
|
||||||
// Logging
|
|
||||||
xmppchat.connection.rawInput = xmppchat.rawInput;
|
|
||||||
xmppchat.connection.rawOutput = xmppchat.rawOutput;
|
|
||||||
// Messages
|
// Messages
|
||||||
xmppchat.connection.addHandler(xmppchat.Messages.messageReceived, null, 'message', 'chat');
|
xmppchat.connection.addHandler(xmppchat.Messages.messageReceived, null, 'message', 'chat');
|
||||||
//Roster
|
|
||||||
xmppchat.connection.addHandler(xmppchat.Roster.rosterResult, Strophe.NS.ROSTER, 'iq', 'result');
|
|
||||||
xmppchat.connection.addHandler(xmppchat.Roster.rosterSuggestedItem, 'http://jabber.org/protocol/rosterx', 'message', null);
|
|
||||||
// Presence
|
|
||||||
xmppchat.connection.addHandler(xmppchat.Presence.presenceReceived, null, 'presence', null);
|
|
||||||
|
|
||||||
xmppchat.UI.restoreOpenChats();
|
xmppchat.UI.restoreOpenChats();
|
||||||
|
|
||||||
xmppchat.Roster = xmppchat.RosterClass(Strophe._connectionPlugins.roster, _, $, console);
|
xmppchat.Roster = xmppchat.RosterClass(Strophe._connectionPlugins.roster, _, $, console);
|
||||||
xmppchat.RosterView = Backbone.View.extend(xmppchat.RosterViewClass(xmppchat.Roster, _, $, console));
|
xmppchat.RosterView = Backbone.View.extend(xmppchat.RosterViewClass(xmppchat.Roster, _, $, console));
|
||||||
|
|
||||||
|
xmppchat.connection.addHandler(xmppchat.Roster.presenceHandler, null, 'presence', null);
|
||||||
|
|
||||||
xmppchat.Roster.registerCallback(xmppchat.Roster.updateHandler);
|
xmppchat.Roster.registerCallback(xmppchat.Roster.updateHandler);
|
||||||
xmppchat.Roster.getRoster();
|
xmppchat.Roster.getRoster();
|
||||||
|
23
chatui.js
23
chatui.js
@ -98,9 +98,6 @@ xmppchat.UI = (function (xmppUI, $, console) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
ob.renderChatbox = function (bare_jid, callback) {
|
|
||||||
};
|
|
||||||
|
|
||||||
ob.insertCollectionMessages = function ($chat, bare_jid, recipient_name) {
|
ob.insertCollectionMessages = function ($chat, bare_jid, recipient_name) {
|
||||||
xmppchat.Collections.getLastMessages(bare_jid, function (result) {
|
xmppchat.Collections.getLastMessages(bare_jid, function (result) {
|
||||||
$('body').append($chat);
|
$('body').append($chat);
|
||||||
@ -533,21 +530,6 @@ $(document).ready(function () {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$(document).bind('xmppchat.roster_updated', function (event) {
|
|
||||||
$('#xmpp-contacts').empty();
|
|
||||||
$(xmppchat.Roster.getCached()).each(function (idx, contact) {
|
|
||||||
if (contact.subscription !== 'none') {
|
|
||||||
var user_id = Strophe.getNodeFromJid(contact.jid),
|
|
||||||
bare_jid = Strophe.getBareJidFromJid(contact.jid);
|
|
||||||
|
|
||||||
// FIXME: We should store the contact name on the jabber server!
|
|
||||||
xmppchat.Presence.getUserInfo(user_id, function (data) {
|
|
||||||
xmppchat.UI.addUserToRosterUI(user_id, bare_jid, data.fullname, 'offline');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$(document).unbind('jarnxmpp.message');
|
$(document).unbind('jarnxmpp.message');
|
||||||
$(document).bind('jarnxmpp.message', function (event) {
|
$(document).bind('jarnxmpp.message', function (event) {
|
||||||
xmppchat.UI.addMessageToChatbox(event);
|
xmppchat.UI.addMessageToChatbox(event);
|
||||||
@ -562,11 +544,6 @@ $(document).ready(function () {
|
|||||||
xmppchat.UI.updateOnPresence(jid, status, presence);
|
xmppchat.UI.updateOnPresence(jid, status, presence);
|
||||||
});
|
});
|
||||||
|
|
||||||
$('a.user-details-toggle').live('click', function (e) {
|
|
||||||
e.preventDefault();
|
|
||||||
xmppchat.UI.getChatbox($(this).parent().attr('data-recipient'));
|
|
||||||
});
|
|
||||||
|
|
||||||
$('textarea.chat-textarea').live('keypress', function (ev) {
|
$('textarea.chat-textarea').live('keypress', function (ev) {
|
||||||
xmppchat.UI.keyPressed(ev, this);
|
xmppchat.UI.keyPressed(ev, this);
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user