Commit 6100aaf1 authored by JC Brand's avatar JC Brand

Refactor the API. updates #46

API methods now consist of simple accessors and mutators that are logically
grouped.
parent 36db4c8b
......@@ -4713,78 +4713,150 @@
'initiateOTR': $.proxy(chatbox.initiateOTR, chatbox),
'maximize': $.proxy(chatbox.maximize, chatbox),
'minimize': $.proxy(chatbox.minimize, chatbox),
'set': $.proxy(chatbox.set, chatbox)
'set': $.proxy(chatbox.set, chatbox),
'open': chatbox.trigger.bind(chatbox, 'show')
};
};
return {
'getBuddy': function (jid) {
var contact = converse.roster.get(Strophe.getBareJidFromJid(jid));
if (contact) {
return contact.attributes;
'initialize': function (settings, callback) {
converse.initialize(settings, callback);
},
'contacts': {
'get': function (jids) {
var _transform = function (jid) {
var contact = converse.roster.get(Strophe.getBareJidFromJid(jid));
if (contact) {
return contact.attributes;
}
return null;
};
if (typeof jids === "string") {
return _transform(jids);
}
return _.map(jids, _transform);
}
},
'getChatBox': function (jid) {
var chatbox = converse.chatboxes.get(jid);
if (chatbox) {
return wrappedChatBox(chatbox);
'chats': {
'get': function (jids) {
var _transform = function (jid) {
var chatbox = converse.chatboxes.get(jid);
if (!chatbox) {
var roster_item = converse.roster.get(jid);
if (roster_item === undefined) {
converse.log('Could not get roster item for JID '+jid, 'error');
return null;
}
chatbox = converse.chatboxes.create({
'id': jid,
'jid': jid,
'fullname': _.isEmpty(roster_item.get('fullname'))? jid: roster_item.get('fullname'),
'image_type': roster_item.get('image_type'),
'image': roster_item.get('image'),
'url': roster_item.get('url')
});
}
return wrappedChatBox(chatbox);
};
if (typeof jids === "string") {
return _transform(jids);
}
return _.map(jids, _transform);
}
},
'getRID': function () {
if (converse.expose_rid_and_sid && typeof converse.connection !== "undefined") {
return converse.connection.rid || converse.connection._proto.rid;
'tokens': {
'get': function (id) {
if (!converse.expose_rid_and_sid || typeof converse.connection === "undefined") {
return null;
}
if (id.toLowerCase() === 'rid') {
return converse.connection.rid || converse.connection._proto.rid;
} else if (id.toLowerCase() === 'sid') {
return converse.connection.sid || converse.connection._proto.sid;
}
}
return null;
},
'getSID': function () {
if (converse.expose_rid_and_sid && typeof converse.connection !== "undefined") {
return converse.connection.sid || converse.connection._proto.sid;
'listen': {
'once': function (evt, handler) {
converse.once(evt, handler);
},
'on': function (evt, handler) {
converse.on(evt, handler);
},
'not': function (evt, handler) {
converse.off(evt, handler);
},
},
'plugins': {
'add': function (name, callback) {
converse.plugins[name] = callback;
},
'remove': function (name) {
delete converse.plugins[name];
},
'override': function (obj, attributes) {
/* Helper method for overriding or extending Converse's Backbone Views or Models
*
* When a method is overriden, the original will still be available
* on the _super attribute of the object being overridden.
*
* obj: The Backbone View or Model
* attributes: A hash of attributes, such as you would pass to Backbone.Model.extend or Backbone.View.extend
*/
if (!obj.prototype._super) {
obj.prototype._super = {};
}
_.each(attributes, function (value, key) {
if (key === 'events') {
obj.prototype[key] = _.extend(value, obj.prototype[key]);
} else {
if (typeof key === 'function') {
obj.prototype._super[key] = obj.prototype[key];
}
obj.prototype[key] = value;
}
});
}
return null;
},
'initialize': function (settings, callback) {
converse.initialize(settings, callback);
'env': {
'jQuery': $,
'Strophe': Strophe,
'_': _
},
// Deprecated API methods
'getBuddy': function (jid) {
converse.log('WARNING: the "getBuddy" API method has been deprecated. Please use "contacts.get" instead');
return this.contacts.get(jid);
},
'getChatBox': function (jid) {
converse.log('WARNING: the "getChatBox" API method has been deprecated. Please use "chats.get" instead');
return this.chats.get(jid);
},
'jQuery': $,
'openChatBox': function (jid) {
var contact = converse.roster.get(Strophe.getBareJidFromJid(jid));
if (contact) {
return wrappedChatBox(converse.chatboxviews.showChat(contact.attributes));
}
converse.log('WARNING: the "openChatBox" API method has been deprecated. Please use "chats.get(jid).open()" instead');
var chat = this.chats.get(jid);
if (chat) { chat.open(); }
return chat;
},
'getRID': function () {
converse.log('WARNING: the "getRID" API method has been deprecated. Please use "tokens.get(\'rid\')" instead');
return this.tokens.get('rid');
},
'getSID': function () {
converse.log('WARNING: the "getSID" API method has been deprecated. Please use "tokens.get(\'sid\')" instead');
return this.tokens.get('sid');
},
'once': function (evt, handler) {
converse.once(evt, handler);
converse.log('WARNING: the "one" API method has been deprecated. Please use "listen.once" instead');
return this.listen.once(evt, handler);
},
'on': function (evt, handler) {
converse.on(evt, handler);
converse.log('WARNING: the "on" API method has been deprecated. Please use "listen.on" instead');
return this.listen.on(evt, handler);
},
'off': function (evt, handler) {
converse.off(evt, handler);
},
'override': function (obj, attributes) {
/* Helper method for overriding or extending Converse's Backbone Views or Models
*
* When a method is overriden, the original will still be available
* on the _super attribute of the object being overridden.
*
* obj: The Backbone View or Model
* attributes: A hash of attributes, such as you would pass to Backbone.Model.extend or Backbone.View.extend
*/
if (!obj.prototype._super) {
obj.prototype._super = {};
}
_.each(attributes, function (value, key) {
if (key === 'events') {
obj.prototype[key] = _.extend(value, obj.prototype[key]);
} else {
if (typeof key === 'function') {
obj.prototype._super[key] = obj.prototype[key];
}
obj.prototype[key] = value;
}
});
},
'registerPlugin': function (name, callback) {
converse.plugins[name] = callback;
converse.log('WARNING: the "off" API method has been deprecated. Please use "listen.not" instead');
return this.listen.not(evt, handler);
}
};
}));
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
......@@ -515,11 +515,38 @@ You can run both the tests and jshint in one go by calling:
Developer API
=============
.. note:: see also the `event api methods`_, not listed here.
.. note:: The API documented here is available in Converse.js 0.8.4 and higher.
Earlier versions of Converse.js might have different API methods or none at all.
In the Converse.js API, you traverse towards a logical grouping, from
which you can then call certain standardised accessors and mutators, like::
.get
.set
.add
.all
.remove
This is done to increase readability and to allow intuitive method chaining.
For example, to get a contact, you would do the following::
converse.contacts.get('jid@example.com');
To get multiple contacts, just pass in an array of jids::
converse.contacts.get(['jid1@example.com', 'jid2@example.com']);
**Here follows now a breakdown of all API groupings and methods**:
initialize
----------
.. note:: This method is the one exception of a method which is not logically grouped
as explained above.
Initializes converse.js. This method must always be called when using
converse.js.
......@@ -544,15 +571,18 @@ Example::
});
getBuddy
--------
"contacts" grouping
-------------------
get
~~~
Returns a map of attributes for a given buddy (i.e. roster contact), specified
by JID (Jabber ID).
Example::
converse.getBuddy('buddy@example.com')
converse.contacts.get('buddy@example.com')
The map of attributes:
......@@ -590,17 +620,19 @@ The map of attributes:
| vcard_updated | When last the buddy's VCard was updated. |
+----------------+--------------------------------------------------------------------------------------------------------------------------------------+
getChatBox
----------
"chats" grouping
----------------
get
~~~
Returns an object/map representing a chat box (without opening or affecting that chat box).
Example::
converse.getChatBox('buddy@example.com')
converse.chats.get('buddy@example.com')
The returned chat box contains the following methods:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*The returned chat box contains the following methods:*
+-------------+------------------------------------------+
| Method | Description |
......@@ -618,8 +650,7 @@ The returned chat box contains the following methods:
| set | Set an attribute (i.e. mutator). |
+-------------+------------------------------------------+
The get and set methods can be used to retrieve and change the following attributes:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*The get and set methods can be used to retrieve and change the following attributes:*
+-------------+-----------------------------------------------------+
| Attribute | Description |
......@@ -629,39 +660,25 @@ The get and set methods can be used to retrieve and change the following attribu
| url | The URL of the chat box heading. |
+-------------+-----------------------------------------------------+
getRID
------
Returns the current RID (request ID) value.
getSID
------
"tokens" grouping
-----------------
Returns the current SID (Session ID) value.
get
~~~
openChatBox
-----------
Opens a chat box and returns an object/map representating that chat box.
If the chat box is already open, its text area will be focused.
Returns a token, either the RID or SID token depending on what's asked for.
Example::
converse.openChatBox('buddy@example.com')
Refer to `getChatBox`_ for more information on the object returned by this
method (which is the same for both).
converse.tokens.get('rid')
Events
======
"listen" grouping
-----------------
Converse.js emits events to which you can subscribe from your own Javascript.
Concerning events, the following methods are available:
Event API Methods
-----------------
Concerning events, the following methods are available under the "listen"
grouping:
* **on(eventName, callback)**:
......@@ -676,7 +693,7 @@ Event API Methods
For example::
converse.on('message', function (messageXML) { ... });
converse.listen.on('message', function (messageXML) { ... });
* **once(eventName, callback)**:
......@@ -690,17 +707,25 @@ Event API Methods
For example::
converse.once('message', function (messageXML) { ... });
converse.listen.once('message', function (messageXML) { ... });
* **off(eventName, callback)**
* **not(eventName, callback)**
To stop listening to an event, you can use the ``off`` method.
To stop listening to an event, you can use the ``not`` method.
Parameters:
* ``eventName`` is the event name as a string.
* ``callback`` refers to the function that is to be no longer executed.
For example::
converse.listen.not('message', function (messageXML) { ... });
Events
======
.. note:: see also the `"listen" grouping`_ API section above.
Event Types
-----------
......@@ -750,7 +775,6 @@ Here are the different events that are emitted:
+--------------------------------+---------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+
Minification
============
......
......@@ -10,82 +10,130 @@
} (this, function ($, mock, test_utils) {
return describe("Converse", $.proxy(function(mock, test_utils) {
beforeEach($.proxy(function () {
test_utils.closeAllChatBoxes();
test_utils.clearBrowserStorage();
converse.rosterview.model.reset();
test_utils.createContacts('current');
describe("The \"tokens\" API", $.proxy(function () {
beforeEach($.proxy(function () {
test_utils.closeAllChatBoxes();
test_utils.clearBrowserStorage();
converse.rosterview.model.reset();
test_utils.createContacts('current');
}, converse));
it("has a method for retrieving the next RID", $.proxy(function () {
var old_connection = converse.connection;
converse.connection._proto.rid = '1234';
converse.expose_rid_and_sid = false;
expect(converse_api.tokens.get('rid')).toBe(null);
converse.expose_rid_and_sid = true;
expect(converse_api.tokens.get('rid')).toBe('1234');
converse.connection = undefined;
expect(converse_api.tokens.get('rid')).toBe(null);
// Restore the connection
converse.connection = old_connection;
}, converse));
it("has a method for retrieving the SID", $.proxy(function () {
var old_connection = converse.connection;
converse.connection._proto.sid = '1234';
converse.expose_rid_and_sid = false;
expect(converse_api.tokens.get('sid')).toBe(null);
converse.expose_rid_and_sid = true;
expect(converse_api.tokens.get('sid')).toBe('1234');
converse.connection = undefined;
expect(converse_api.tokens.get('sid')).toBe(null);
// Restore the connection
converse.connection = old_connection;
}, converse));
}, converse));
it("has an API method for retrieving the next RID", $.proxy(function () {
var old_connection = converse.connection;
converse.connection._proto.rid = '1234';
converse.expose_rid_and_sid = false;
expect(converse_api.getRID()).toBe(null);
describe("The \"contacts\" API", $.proxy(function () {
beforeEach($.proxy(function () {
test_utils.closeAllChatBoxes();
test_utils.clearBrowserStorage();
converse.rosterview.model.reset();
test_utils.createContacts('current');
}, converse));
converse.expose_rid_and_sid = true;
expect(converse_api.getRID()).toBe('1234');
it("has a method 'get' which returns a wrapped contact", $.proxy(function () {
// TODO: test multiple JIDs passed in
var jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
expect(converse_api.contacts.get('non-existing@jabber.org')).toBeFalsy();
var attrs = converse_api.contacts.get(jid);
expect(typeof attrs).toBe('object');
expect(attrs.fullname).toBe(mock.cur_names[0]);
expect(attrs.jid).toBe(jid);
}, converse));
}, converse));
converse.connection = undefined;
expect(converse_api.getRID()).toBe(null);
// Restore the connection
converse.connection = old_connection;
describe("The \"chats\" API", $.proxy(function() {
beforeEach($.proxy(function () {
test_utils.closeAllChatBoxes();
test_utils.clearBrowserStorage();
converse.rosterview.model.reset();
test_utils.createContacts('current');
}, converse));
it("has a method 'get' which returns a wrapped chat box object", $.proxy(function () {
// TODO: test multiple JIDs passed in
// FIXME: when a non-existing chat box is "get(ted)", it's
// opened, which we don't want...
expect(converse_api.chats.get('non-existing@jabber.org')).toBeFalsy(); // test on user that doesn't exist.
var jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
var box = converse_api.chats.get(jid);
expect(box instanceof Object).toBeTruthy();
expect(box.get('box_id')).toBe(b64_sha1(jid));
var chatboxview = this.chatboxviews.get(jid);
expect(chatboxview.$el.is(':visible')).toBeTruthy();
}, converse));
}, converse));
it("has an API method for retrieving the SID", $.proxy(function () {
var old_connection = converse.connection;
converse.connection._proto.sid = '1234';
converse.expose_rid_and_sid = false;
expect(converse_api.getSID()).toBe(null);
describe("The DEPRECATED API", $.proxy(function() {
beforeEach($.proxy(function () {
test_utils.closeAllChatBoxes();
test_utils.clearBrowserStorage();
converse.rosterview.model.reset();
test_utils.createContacts('current');
}, converse));
converse.expose_rid_and_sid = true;
expect(converse_api.getSID()).toBe('1234');
it("has a method for retrieving the next RID", $.proxy(function () {
var old_connection = converse.connection;
converse.connection._proto.rid = '1234';
converse.expose_rid_and_sid = false;
expect(converse_api.getRID()).toBe(null);
converse.connection = undefined;
expect(converse_api.getSID()).toBe(null);
// Restore the connection
converse.connection = old_connection;
}, converse));
converse.expose_rid_and_sid = true;
expect(converse_api.getRID()).toBe('1234');
it("has an API method for retrieving a buddy's attributes", $.proxy(function () {
var jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
expect(converse_api.getBuddy('non-existing@jabber.org')).toBeFalsy();
var attrs = converse_api.getBuddy(jid);
expect(typeof attrs).toBe('object');
expect(attrs.fullname).toBe(mock.cur_names[0]);
expect(attrs.jid).toBe(jid);
}, converse));
converse.connection = undefined;
expect(converse_api.getRID()).toBe(null);
// Restore the connection
converse.connection = old_connection;
}, converse));
it("has an API method, openChatBox, for opening a chat box for a buddy", $.proxy(function () {
expect(converse_api.openChatBox('non-existing@jabber.org')).toBeFalsy(); // test on user that doesn't exist.
var jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
var box = converse_api.openChatBox(jid);
expect(box instanceof Object).toBeTruthy();
expect(box.get('box_id')).toBe(b64_sha1(jid));
var chatboxview = this.chatboxviews.get(jid);
expect(chatboxview.$el.is(':visible')).toBeTruthy();
}, converse));
it("has a method for retrieving the SID", $.proxy(function () {
var old_connection = converse.connection;
converse.connection._proto.sid = '1234';
converse.expose_rid_and_sid = false;
expect(converse_api.getSID()).toBe(null);
it("will focus an already open chat box, if the openChatBox API method is called for it.", $.proxy(function () {
// Calling openChatBox on an already open chat will focus it.
var jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
var chatboxview = this.chatboxviews.get(jid);
spyOn(chatboxview, 'focus');
test_utils.openChatBoxFor(jid);
box = converse_api.openChatBox(jid);
expect(chatboxview.focus).toHaveBeenCalled();
expect(box.get('box_id')).toBe(b64_sha1(jid));
converse.expose_rid_and_sid = true;
expect(converse_api.getSID()).toBe('1234');
}, converse));
converse.connection = undefined;
expect(converse_api.getSID()).toBe(null);
// Restore the connection
converse.connection = old_connection;
}, converse));
it("has an API method, getChatBox, for retrieving chat box", $.proxy(function () {
var jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
expect(converse_api.getChatBox(jid)).toBeFalsy();
test_utils.openChatBoxFor(jid);
var box = converse_api.getChatBox(jid);
expect(box instanceof Object).toBeTruthy();
expect(box.get('box_id')).toBe(b64_sha1(jid));
it("has a method for retrieving a buddy's attributes", $.proxy(function () {
var jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
expect(converse_api.getBuddy('non-existing@jabber.org')).toBeFalsy();
var attrs = converse_api.getBuddy(jid);
expect(typeof attrs).toBe('object');
expect(attrs.fullname).toBe(mock.cur_names[0]);
expect(attrs.jid).toBe(jid);
}, converse));
}, converse));
}, converse, mock, test_utils));
}));
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment