![]() |
Cisco AJAX XMPP Library Developer Guide |
The Cisco AJAX XMPP Library is a JavaScript XMPP client library that allows you to integrate instant messaging, availability and roster management services from Cisco WebEx and Cisco Unified Presence to your web-based application.
The Cisco AJAX XMPP Library is an object-oriented, client-side library which communicates with a BOSH server component. BOSH (Bidirectional-streams Over Synchronous HTTP) technology is used as a HTTP binding for XMPP communications that is useful in situations where a device or client is unable to maintain a long-lived TCP connection to an XMPP server e.g. in a web browser.
The Cisco AJAX XMPP Library is comprised of the following modules:
You can use the Cisco AJAX XMPP Library as an API or as a web UI or both. The core Cisco AJAX XMPP Library API does not depend on use of the Cisco AJAX XMPP Library UI API. The internals of the library use jQuery for low-level JavaScript tasks but there is no dependency on any JavaScript UI framework for the UI components.
Cisco provides a minimal distribution of the core library for applications that do not need typical IM functionality.
The minimal library, jabberwerx.min.js, provides client session management, authentication, stanza sending and eventing when a stanza is received. IM centric functionality like 1-1 chat sessions, text conferencing rooms and publish/subscribe is not available. A list of classes included in the minimal library can be found in the API documentation delivered with the library.
You can load the Cisco AJAX XMPP Library either statically or dynamically. To load statically, simply include a standard <script> tag that references the library file directly:
<script type='text/javascript' src='../../jabberwerx.js'> </script>
You can load dynamically via a number of JavaScript loaders. Simply reference the library file according to your loader's documentation. When the load complete handler returns, the Cisco AJAX XMPP Library is ready for use.
For example, if using the Yahoo! Toolkit, the following would load the library:
YAHOO.util.Get.script('../../jabberwerx.js', {
onSuccess: function(){
// do something interesting...
}
});
Cisco provides two distributions of the Cisco AJAX XMPP Library, the Debug distribution (for troubleshooting purposes), and the Release distribution.
Note! Do not use the Debug distribution in the final end-user product. The Debug distribution is for troubleshooting purposes only. While functionally equivalent, the Debug distribution may load and run significantly slower than the Release distribution.
The Cisco AJAX XMPP Library is delivered as one of two distributions: Release and Debug. Both distributions include the library code, resources, examples, and documentation. The Release distribution provides a "minified" library code file, where all core code and dependencies are in a single, standalone file for each target (jabberwerx.js for the core non-UI library; jabberwerx.ui.js for the UI library). The Debug distribution provides the library code as a set of individual javascript files, with jabberwerx.js and jabberwerx.ui.js acting as dependency loaders. The two distributions are interchangable, and require no changes in how the library loads or operates.
To use the Debug distribution in parallel with the Release distribution, first unpackage the Release distribution into its own directory, called "caxl". Then unpackage the Debug distribution into its own directory, called "caxl-debug". These two directories must be in the same parent directory for your web site.
To load the release builds, the <script> tag that loads the Cisco AJAX XMPP Library should be set to "caxl/jabberwerx.js" (for core) or "caxl/jabberwerx.ui.js" (for UI) to load the release builds (assuming the HTML is in the same directory that holds the Cisco AJAX XMPP Library sub-directories). To switch to the debug builds, change the path to "caxl-debug/jabberwerx.js" or "caxl-debug/jabberwerx.ui.js".
To remove the Debug distribution, delete the "caxl-debug" directory.
JWBase class. JWBase defines the object-oriented structure of the classes and also the common object behaviors and
properties.
![]() |
|
jabberwerx.JIDjabberwerx.Entityjabberwerx.EntitySetjabberwerx.Userjabberwerx.Contactjabberwerx.ChatSessionjabberwerx.MUCRoomjabberwerx.Clientjabberwerx.RosterControllerjabberwerx.ChatControllerjabberwerx.MUCControllerjabberwerx.CapabilitiesControllerjabberwerx.$jabberwerx.JWModel type object, the applyEvent(eventName) method is called. This creates a new
event and returns a jabberwerx.EventNotifier object.
jabberwerx.JWModel objects contain an event(eventName) method to return the associated jabberwerx.EventNotifier for an
existing event. To register for the event, there are two available methods on the jabberwerx.EventNotifier object:
bind(callback): register a callback method which is invoked when the event triggers. The callback method is passed
an jabberwerx.EventObject.bindWhen(selector, callback): similar to bind() but with the additional selector (jQuery string or
method) which is a filter to determine whether to trigger the event or notjabberwerx.EventNotifier object provides a trigger() method.
var client = jabberwerx.client;
var notifier = client.event('presenceReceived');
// callback for event
var cb = function(eventObject) {
// some interesting properties ...
// event name
eventObject.name
// event notifier object (can be used to unbind)
eventObject.notifier
// event source
eventObject.source
// optional data object that may be passed via trigger
eventObject.data
};
// register a callback with the event notifier
notifier.bind(cb);
// this will invoke the callback
notifier.trigger();
// this will invoke the callback with an additional object
var obj = 'new string';
notifier.trigger(obj);
// unregister callback
notifier.unbind(cb);
// this should not trigger the callback now
notifier.trigger();
The following is an eventing call flow for the 'chatReceived' event.
jabberwerx.EntitySet used by the client and controllers to cache entities during
sessions. It is accessible through the client: client.entitySet. The entity cache provides a type and
controller agnostic way of accessing entities. That is, a user does not need to know what controller
creates jabberwerx.Contact entities in order to use them.
jabberwerx.RosterController performs a fetch at connection time and is cleared on disconnect.
Creating, adding, removing and destroying entities fire events, flooding listeners during connection and disconnection.
To make these large entity adds and removes more efficient the entity cache will combine all events together into one set of
batch events; batchUpdateStarted and batchUpdateEnded.
See the jabberwerx.EntitySet.startBatch documentation for a detailed discussion of batching.
cleanupEntity method. A controller that creates entities should override the
jabberwerx.Controller.cleanupEntity method and dispose of the given entity (usually by calling entity.remove()).
cleanupEntities will only be called with entities the controller created.
The Client allows interested Controllers to delay the final "connected" event from triggering until they have finished initializing. This is especially useful if such initialization is asynchronous, such as <iq/> requests. For example, this lets the DiscoController request information on the server and any directly associated services it has, and allows the RosterController to fetch and process the user's roster.
This feature is implemented via the Rendezvousable mixin. An interested controller applies this mixin, then overrides the startRendezvous(ctx) function to begin its login work (e.g. request roster, get disco#info and disco#items, etc). When the initialization work is complete, the controller calls finishRendezvous() on itself. Once all Rendezvousable controllers have finished, the Client then continues on, triggering the "clientStatusChanged" for the connected status.
TypeError instance is created and thrown
from the method.
jabberwerx.util.Error, and all other error classes extend from this base
error class. In addition to a unique error class name, each error instance contains an error message string that is stored in the message property of an error object.
The error classes do not use error codes. This is a code
snippet which catches an exception from the PrivacyListController.fetch() method:
try {
var notConnectedClient = new jabberwerx.Client('notconnected');
var privacyListController = new jabberwerx.PrivacyListController(notConnectedClient);
privacyListController.fetch("myList",onFetch);
} catch (ex) {
alert("thrown exception is jabberwerx.Client.NotConnectedError");
}
var errorMessage = jabberwerx.errorReporter.getMessage(errorElement);
In this example, errorElement is either an Element object that looks like this:
<error xmlns="jabber:client" code="503" type="cancel">
<service-unavailable xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/>
</error>
or it is a string in the format of:
"{urn:ietf:params:xml:ns:xmpp-stanzas}service-unavailable"
Either case returns the same error message.
jabberwerx.errorReporter.addMessage(errorCondition, errorMessage);
errorCondition is the string representation of the error. An example of this is:
"{urn:ietf:params:xml:ns:xmpp-stanzas}service-unavailable"
getMessage returns the string errorMessage when that error is passed in
By default, when a user adds or updates a contact on a client application using the RosterController, the group attribute for the contact is empty (i.e. they have no group). However, some client applications do not display contacts without a group attribute. Therefore, the RosterController class contains a property to facilitate a client application (using the Cisco AJAX XMPP Library) that wants any contacts added or updated to be members of a group. This property is jabberwerx.RosterController.defaultGroup. You can set this property as follows:
var rosterCtrl = new jabberwerx.RosterController(....);
rosterCtrl.defaultGroup = "Buddies";
The Cisco AJAX XMPP Library uses this property when an add or update contact call is made without a groups
parameter, or where the groups parameter is null or empty.
Note: This is not the same as the default grouping name in jabberwerx.ui.RosterView . The RosterView default group name refers to the group display name for entities that belong to no group (i.e. contacts with an empty group attribute). This is purely a visual setting.
XHTML-IM conversion and cleaning is handled automatically when using accessor methods jabberwerx.Message.getHTML and jabberwerx.Message.setHTML. By default XHTML-IM cleaning uses XEP-0071 Recommended Profile to decide what HTML tags, attributes and style properties are allowed. Any not allowed are removed from the message's xhtml-im as described in XEP-0071. "Allowable" may be modified using the jabberwerx.xhtmlim.allowedTags map and the jabberwerx.xhtmlim.allowedStyles array. allowedTags maps allowed tags to allowed attributes. Here is a partial definition of allowedTags:
jabberwerx.xhtmlim.allowedTags = {
...
strong: [],
a: ["style","href","type"],
blockquote: ["style"],
...
}
The strong tag is allowed but all attributes are removed, anchor tags may have a style, href or type etc.
To disallow a tag, delete it from the map. Modify attributes by adding or removing them from the tag's array.
Style properties are much the same. Their default value is from XEP-0071 Recommended Profile. Modify allowed properties by changing jabberwerx.xhtmlim.allowedStyles. For example to remove font size add
delete jabberwerx.xhtmlim.allowedStyles[jabberwerx.xhtmlim.allowedStyles.indexOf("font-size")] ;
to startup code.
jabberwerx.cisco adds a Table Module to allowedTags. This is implemented in the proprietary library to keep the base library complient with the XEP.
The BOSH interface is not aware when the browser, or tab, in which the Cisco AJAX XMPP Library is running closes or the page refreshs. This is due to the nature of BOSH traffic. The interface waits a predefined number of seconds before it declares the connection is dead. During this intervening time all messages that the server sends to the client are lost.
To avoid these "stray" messages, you can disconnect the client when the window is unloaded. Do this by binding a handler for the windows beforeUnload event:
// The beforeUnload event handler. Forces the client to disconnect.
var unloadHandler = function() {
client.disconnect();
};
client.event("clientStatusChanged").bind(function(evt) {
if (evt.data.next == jabberwerx.Client.status_connected) {
// Upon connecting bind the handler
$(window).bind("beforeunload", unloadHandler);
} else if (evt.data.next == jabberwerx.Client.status_disconnected) {
// Upon disconnecting unbind the handler
$(window).unbind("beforeunload", unloadHandler);
}
});
There are a number of sample applications packaged as part of the Cisco AJAX XMPP Library. These sample are contained in the /doc/examples folder. The following description outlines the various different types of sample apps:
var client = new jabberwerx.Client('sampleclient');
var username = "jwtest1@example.com";
var password = "test";
var connectArgs = {
// the proxy url to the BOSH server
httpBindingURL: '/httpbinding',
// onConnected is the success callback method
successCallback: onConnected,
// onClientError is the error callback method
errorCallback: onClientError
};
client.connect(username, password, connectArgs);
// set show state and the user-defined status message
client.sendPresence('away', 'gone to lunch');
// register for an incoming presence stanza
jabberwerx.globalEvents.bind ("presenceReceived", "onPresenceReceived");
// callback method for the 'presenceReceived' event
function onPresenceReceived (event) {
// get the associated jabberwerx.Presence object data
var presence = event.data;
var type = presence.getType();
var show = presence.getShow();
var status = presence.getStatus();
var priority = String(presence.getPriority());
var fromJID = presence.getFromJID();
var toJID = presence.getToJID();
}
var chatController = new jabberwerx.ChatController(client);
var chatSession = chatController.openSession(jid);
chatSession.event('chatReceived').bind(onChatReceived);
// Callback method for the 'chatReceived' event
function onChatReceived(event) {
var message = event.data;
var from = message.getFrom()
var text = message.getBody()
}
Another simple example can be seen in the Getting Started Guide.