Code - How to Attach Stroph

How to Attach using Strophe.js

Strophe is a awesome script that allows you to connect to your jabber server from JavaScript. When i first started out with it, I had a tough time finding some documentation for the web project I was working on to guide. I hope I can help. You can choose to use the connect or attach function to get started. I used the attach since I didn't want to have passwords on the client. I'm not going to go into detail using any script library, but I have used it with Mootools and JQuery and both were pretty simple to use with Strophe.

Major tip - When starting out, I highly recommend using Firefox with Firebug and console.log everything to give you good insight on what's going on. There are also built in debugging options. Set them up when creating the connection.

First thing is to write yourself some code to connect to the jabber server. In my case I was writing c# and you can find an example of how I did that here. Once you make that happen, you'll need to create a new Strophe connection. Store your "myconnection" variable in your script so it is accessible to use later. Then call the attach method with your SID, RID and JID. In the attach call, you’ll need a callback function to manage your chat session.


myconnection = new Strophe.Connection([jabberservername])); 
//set up debugging 
myconnection.rawInput = rawInput; 
myconnection.rawOutput = rawOutput; 
myconnection.attach(jid, sid, rid, callbackfunctionname) 
//debugging 
rawInput = function (data) { console.log('RECV: ' + data); } 
rawOutput = function (data) { console.log('SEND: ' + data); } 

In your callback function, add status for a param and look for status where it equals Strophe.Status.ATTACHED. This is where you add your handlers to manage information as it comes from the jabber server. In a web environment, you’ll need to track the rid between page loads and increment accordingly. When a user changes pages, just fire the attach again. There are several statuses that Strophe offers. Check the docs and determine which ones you would like to use and handle them accordingly. Here's 2 that we're going to discuss.

 
onConnect = function (status) {
 if (status == Strophe.Status.ATTACHED) { 
//create handlers for managing chat stuff 
} else if (status == Strophe.Status.DISCONNECTED) { 
//no longer connected
 } 
} 

Your handlers are formatted as (handler func, namespace, name, type, id, from, options). Add your handlers in the onConnect function once your user is attached. You can also add handlers on certain events. You need to return true at the end of any handlers you want to reuse.

The handler func is what function gets called when the handler is triggered. The namespace tells Strophe what particular item to match based on what is put there (You’ll find a short list of them in Strophe or you can type the namespace).

The namespace is what is returned as the attribute xmlns in the elements.

The name is the element name you’re looking for. The type looks for a particular type (result, available, unavailable, etc). To add a handler, use the format: myconnection.addHandler(handler func, namespace, name).

Not all items are required, you can pass in null. For example, to watch for presence updates, myconnection.addHandler(onPresence, null, “presence”); - with onPresence being the function that handles the callback.

You can modify and add names, items, types to this handler to narrow down what you are looking for. To look for messages, you can use something like myconnection.addHandler(onMessage, null, “message”). The callback functions will get passed the tags you specify in the name parameter.

 
myconnection.addHandler(onPresence, null, 'presence');
onPresence = function (presence) { 
var type = presence.getAttribute('type'); 
var from = presence.getAttribute('from'); 
if (type && type === 'available') {
 //the roster person is now online
 } else if (type && type === 'unavailable') { 
//the roster person is no longer online 
} 
return true; 
} 

Depending on what your app does, you'll want handlers for messages and presence at the minimum. I also use ping. There are several plugins available for Strophe you can find and use for your app.

Roster/Presence - Once you’re connected, create a handler for watching presence. This will fire when someone on your roster does something that changes their presence (see example above). When you chat with someone, using the roster plugin will allow you to subscribe to someone’s presence (and vice-versa). For example, when I ping someone, I also request a subscription to them. When they agree to chat, they authorize and subscribe to me. We are now on each other’s roster. You can go further with roster items by groups, status’, etc. Note that status and show don’t seem to be kept by the jabber server if you change pages.

I use the roster also to keep track of the people I chat with because in a web environment, pages change, people leave ungracefully, browsers get closed, etc. The jabber server I’m using times out a user after 2 minutes of leaving. Then, when I’ve subscribed to someone, I’ll get an “unavailable” notification. I can then tell my chat window that the person has left. Depending on how you use your roster, you can let people know when friends come online as well (server send an “available”). I also use the roster to track who I’m in active chat with so when I change pages, I fetch the roster and look for active chats, then automatically reload the chats. I create groups that are not visible to determine who’s actively chatting and who’s not. You’ll probably find your presence listener (handler) is probably going to be the most important handler.

Message - Obviously you’ll need a message handler. You’ll get a from jid in which you can determine who it is from. Take the message and put it in the chat window. There are several types of messages. I suggest you research a little. For PMs, I look for the type "chat".

 
onMsg = function (msg) { 
var elems = msg.getElementsByTagName('body'); 
if (elems.length > 0) { 
var type = msg.getAttribute('type'); 
var from = msg.getAttribute('from'); 
if (type === "chat") { 
//add message to chat window 
}
}
} 

Archive - This isn’t so much as a handler, but functionality you’ll want. You’ll probably need to configure your jabber server to manage it. Using http://xmpp.org/extensions/xep-0136.html, You’ll need to get the collections first. Once you do that, you'll need to grab the messages and handle them to your liking.
 
var loadArchive = function (jid) { 
//only get last collection 
var rsm = new Strophe.RSM({ 'max': 1, 'before': '' }); 
myconnection.archive.listCollections(jid, rsm, function (collections, responseRsm) { 
//get last collection 
var lastCollection = collections[collections.length - 1]; 
//get last 10 msgs (or all if you please) 
rsm = new Strophe.RSM({ 'max': 10, 'before': '' }); 
lastCollection.retrieveMessages(rsm, function (messages, responseRsm) {
//iterate though the messages
 });
 } ); 
}


Ping - Ping is an awesome little plugin I use to see if the other person I want to initiate chat with is online. You click "chat", send a ping and if they are online, they send a pong. You can setup a handler to acknowledge a ping, reject the chat request, etc.
 
onPing = function (iq) { 
var from = iq.getAttribute('from'); 
//send a pong 
myconnection.ping.pong(iq); 
//open chat window 
return true; 
} 
onPong = function (iq) { 
var from = iq.getAttribute('from'); 
//open chat window 
return false;
 } 

That's the nutshell. Don''t forget to track and the RID in your webapp changes pages. When you try to re-attach on the next page, it'll fail if you don't. There's a lot more to the app (about 2k lines), which is mostly creating invite windows, chat windows, handling presences, messages and rosters. If you enable logging, you can figure it out pretty quickly. Start simple and go from there. I did find that versions of IE older than 10 can be problematic (surprise!), so be prepared for that. there is a plugin that deals with XDomainRequests for older versions of IE.