/** * 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 {Number} 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); // init tooltip contact.tipTip({ content: "", defaultPosition: "right", keepAlive: true }); }, /** * Update the roster when receiving a presence stanza * @param {XMLElement} presence The presence stanza * @returns {Boolean} */ 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 {XMLElement} 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(); } }, /** * Initialization after connection * * Set the interface and the handlers */ 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; } }; function log(msg, color) { $('#log').append($('
    ').css('background-color', color).text(msg)); } function rawInput(data) { log('RECV: ' + data, '#FBB6B4'); } function rawOutput(data) { log('SENT: ' + data, '#B5BBFB'); } jQuery.expr[':'].Contains = function(a,i,m){ return jQuery(a).text().toUpperCase().indexOf(m[3].toUpperCase())>=0; }; $(document).ready(function(){ var connection = new Strophe.Connection(BOSH_SERVICE); connection.rawInput = rawInput; connection.rawOutput = rawOutput; Alias.connection = connection; $('#connect').click(function () { Alias.connection.connect($('#jid').get(0).value, $('#pass').get(0).value, Alias.onStatusChanged); }); $('#bottomup').click(function(){ $(this).next().slideToggle(); }); $('#tabs').tabs(); $('#rosterfilter').keyup(function() { var filter = $(this).val(); $('#roster ul li div.roster-name:not(:Contains("' + filter + '"))').parent().hide(); $('#roster ul li div.roster-name:Contains("' + filter + '")').parent().show(); }); $('.roster-contact').live('click', function(){ var jid = Alias.getID($(this)); var name = Alias.getName($(this)); var id = Alias.jid_to_id(jid); if ( !$('#tabs').tabs('exist','#chat-' + id) ) { Alias.addChatTab(jid); } $('#tabs').tabs('select', '#chat-' + id ); $('#chat-' + id + ' input').focus(); }); $('.chat-input').live('keypress', function (ev) { var jid = $(this).parent().data('jid'); var id = Alias.jid_to_id(jid); var me = Alias.connection.jid; if (ev.which === 13) { ev.preventDefault(); var body = $(this).val(); var message = $msg({to: jid, "type": "chat"}) .c('body').t(body).up() .c('active', {xmlns: "http://jabber.org/protocol/chatstates"}); Alias.connection.send(message); Alias.addMessage(id, me, body); $(this).val(''); } }); $('#dialogs').dialog(); $('#register-link').click(function(){ $('#dialogs').dialog('show', 'register'); }); });