var BOSH_SERVICE = 'http://localhost/http-bind';
var server_component = 'object.localhost';
/**
* Alias namespace
*/
var Alias = {
/**
* Status constants
*/
Status: {
ONLINE: 2,
AWAY: 1,
OFFLINE: 0
},
/**
* Strophe xmpp connection
*/
connection: null,
/**
* Send a roster request to server
*/
getRoster: function() {
var roster = $iq({type : 'get'}).c('query', {xmlns : Strophe.NS.ROSTER});
Alias.connection.sendIQ(roster, Alias.onRoster);
},
/**
* Return the status of a contact
* @param {jQuery} contact The contact
* @return {Int} The status' number
* @see Alias.Status
*/
getPresence: function(contact) {
if ( contact.hasClass("online") )
return Alias.Status["ONLINE"];
else if ( contact.hasClass("away") )
return Alias.Status["AWAY"];
else
return Alias.Status["OFFLINE"];
},
/**
* Convert a jid to an id string suitable for css id
* @param {String} jid
* @return {String} id
*/
jid_to_id: function(jid) {
return Strophe.getBareJidFromJid(jid).replace(/[@.]/g,'-');
},
/**
* Return the id of a contact
* @param contact jquery object
* @return {String} id
*/
getID: function(contact) {
return contact.find('.roster-jid').text();
},
/**
* Return the name of a contact
*/
getName : function(contact) {
return contact.find('.roster-name').text();
},
/**
* Get the home node of a contact
* @param contact jquery object
*/
getHome: function(contact) {
var name = Base64.encode(Alias.getID(contact)) + '@' + server_component;
var iq = $iq({type : 'get', to : name}).c('query', {xmlns : 'alias:query', type:'content'});
Alias.connection.sendIQ(iq, Alias.onHome);
},
/**
* Called when receiving home node, display in the main div
* @param iq XML object
*/
onHome: function(iq) {
var content = $(iq).find('content').text();
$('#main').html(content);
},
/**
* Insert a contact keeping the sorting of the roster
* The contacts are sorted based on their status and on their names
* @param {jQuery} contact The contact to insert
*/
insertContact: function(contact) {
var presence = Alias.getPresence(contact);
var jid = Alias.getID(contact);
var contacts = $('#roster li');
if (contacts.length > 0) {
var inserted = false;
contacts.each(function () {
var locpres = Alias.getPresence($(this));
var locjid = Alias.getID($(this));
if (presence > locpres)
{
$(this).before(contact);
inserted = true;
return false;
}
else if ( (presence == locpres) && (jid < locjid) )
{
$(this).before(contact);
inserted = true;
return false;
}
});
if (!inserted)
$('#roster ul').append(contact);
}
else
$('#roster ul').append(contact);
},
onPresence: function(presence) {
var who = $(presence).attr('from');
var type = $(presence).attr('type');
if (type !== 'error')
{
var contact = $('#' + Alias.jid_to_id(who));
contact.removeClass('online away offline');
if (type === 'unavailable')
{
contact.addClass('offline');
}
else
{
var show = $(presence).find('show').text();
if (show === '' || show === '')
{
contact.addClass('online');
}
else
{
contact.addClass('away');
}
}
contact.remove();
Alias.insertContact(contact);
}
return true;
},
/**
* Rebuild the contact list when receiving a roster iq
* @param iq
* @return {Boolean}
*/
onRoster: function(iq) {
$('#roster li').remove();
var elems = iq.getElementsByTagName('query');
var query = elems[0];
Strophe.forEachChild(query, 'item', function(item)
{
var jid = item.getAttribute('jid');
var name = item.getAttribute('name') || jid;
var id = Alias.jid_to_id(jid);
var contact = $("
"
+ "
" + name + "
"
+ "
" + jid + "
");
Alias.insertContact(contact);
});
Alias.connection.addHandler(Alias.onPresence,null,'presence', null, null, null, null);
Alias.connection.send($pres());
return true;
},
/**
* Called when the status of Strophe's connection changes.
* This function is passed to the Strophe's connect function
*
* @param {Int} status The new status
*/
onStatusChanged: function(status) {
var jid = $('#jid').get(0).value;
if ( status == Strophe.Status.CONNECTING ) {
log('Strophe is connecting.');
} else if ( status == Strophe.Status.CONNFAIL ) {
log('Strophe failed to connect.');
} else if ( status == Strophe.Status.DISCONNECTING ) {
log('Strophe is disconnecting.');
} else if ( status == Strophe.Status.DISCONNECTED ) {
log('Strophe is disconnected.');
} else if ( status == Strophe.Status.CONNECTED ) {
log('Strophe is connected.');
Alias.onConnect();
}
},
/**
* Alias initialization after connection
*/
onConnect: function() {
Alias.getRoster();
// hide the login dialog and load the interface
$('#login').hide();
$('#password').val('');
$('#left').show();
$('#right').show();
$('#status').append($('Disconnect'));
$('#disconnect').click(function(){
Alias.connection.disconnect();
$('#roster ul').empty();
$('#left').hide();
$('#right').hide();
$('#login').hide();
$(this).remove();
});
// handlers must be added only after connection is made
Alias.connection.addHandler(Alias.onMessage, null, "message", "chat");
},
/**
* Add a new chat tab
* @param {String} jid The jid of the contact to chat with
*/
addChatTab: function(jid) {
var jid_id = Alias.jid_to_id(jid);
$('#tabs').tabs('add', jid, 'chat-' + jid_id, true);
$('#chat-' + jid_id).addClass('chat-tab');
$('#chat-' + jid_id).append(""
+ "");
$('#chat-' + jid_id).data({jid: jid});
},
/**
* Add a chat message
* @param {String} chatId The id of the chat tab
* @param {String} authorId The jid of the message's author
* @param {String} body The text of the message
*/
addMessage: function(chatId, authorId, body) {
var author = Strophe.getNodeFromJid( authorId );
var message = $('
'
+ author + ''
+ body + '
');
if ( authorId == Alias.connection.jid ) {
message.find('.chat-name').addClass('me');
}
var chatArea = $('#chat-' + chatId).find('.chat-messages');
chatArea.append(message);
chatArea.scrollTop(chatArea.height());
},
/**
* Callback upon receiving a chat message
* @param {String} message The xml code of the message iq
* @return {Boolean}
*/
onMessage: function (message) {
var full_jid = $(message).attr('from');
var jid = Strophe.getBareJidFromJid(full_jid);
var jid_id = Alias.jid_to_id(jid);
if ( !$('#tabs').tabs('exist','#chat-' + jid_id) ) {
Alias.addChatTab(jid);
}
$('#chat-' + jid_id).data({jid: full_jid});
var body = $(message).find("html > body");
if (body.length === 0) {
body = $(message).find('body');
if (body.length > 0) {
body = body.text();
} else {
body = null;
}
} else {
body = body.contents();
var span = $("");
body.each(function () {
if (document.importNode) {
$(document.importNode(this, true)).appendTo(span);
} else {
// IE workaround
span.append(this.xml);
}
});
body = span;
}
if (body) {
Alias.addMessage( jid_id, jid , body);
}
return true;
}
};
/**
* Light jQuery tab plugin
*
* the html structure is:
*
*
*/
(function( $ ){
var methods = {
/**
* Initialise the general tab area
* @return this (to preserve chainability)
*/
init: function() {
var tabs = this;
this.find('ul.tabbar li').bind('click.tabs', function(event){
event.preventDefault();
tabs.tabs('select',$(this).find('a').attr('href'));
});
this.data('tabs',{});
return this;
},
/**
* Select a tab
* @param {String} id The tab id with #
* @return this
*/
select: function(id) {
var selectedId = this.data('tabs').selected;
if ( selectedId == id) {
return this;
}
this.find('ul.tabbar li a[href="' + selectedId + '"]').parent().removeClass('selected');
this.find('ul.tabbar li a[href="' + id + '"]').parent().addClass('selected');
$(selectedId).hide();
$(id).show();
this.data('tabs').selected = id;
return this;
},
/**
* Add a tab
* @param {String} name The tab Title
* @param {String} id The tab id without #
* @pram {Bool} remove Wether the tab should be closable
* return this
*/
add: function(name, id, remove) {
var tabs = this;
var li = $('