xmppchat.UI = (function (xmppUI, $, console) { var ob = xmppUI; ob.chats = []; ob.chat_focus = []; ob.chatbox_width = 205; ob.sanitizePath = function (call) { return xmppchat.base_url + call; }; ob.updateOnPresence = function (jid, status, presence) { // TODO: When a presence indicator shows that a resource has // gone offline, we need to look in the ChatPartners storage to see // if there are more storages before we mark the user as offline in the UI. var user_id = Strophe.getNodeFromJid(jid), barejid = Strophe.getBareJidFromJid(jid), existing_user_element = $('#online-users-' + user_id), online_count; if (barejid === Strophe.getBareJidFromJid(jarnxmpp.connection.jid)) { return; } if (existing_user_element.length) { if (status === 'offline' && jarnxmpp.Presence.online.hasOwnProperty(user_id)) { existing_user_element.attr('class', status); return; } existing_user_element.attr('class', status); } else { $.get(portal_url + '/xmpp-userDetails?jid=' + barejid, function (user_details) { // FIXME: this ajax call returns a bunch of unnecessary stuff... if ($('#online-users-' + user_id).length > 0) { return; } user_details = $(user_details); $('#online-users').append(user_details); $('#online-users li[data-userid]').sortElements(function (a, b) { return $('a.user-details-toggle', a).text().trim() > $('a.user-details-toggle', b).text().trim() ? 1 : -1; }); }); // Pre-fetch user info if we have a session storage. if (jarnxmpp.Storage.storage !== null) { jarnxmpp.Presence.getUserInfo(user_id, function (data) {}); } } online_count = jarnxmpp.Presence.onlineCount(); if (online_count > 0) { $('#no-users-online').hide(); } else { $('#no-users-online').show(); } $('#online-count').text(online_count); }; ob.positionNewChat = function ($chat) { var open_chats = 0, offset; for (var i=0; i 0) { chat_content.scrollTop(chat_content[0].scrollHeight); } } if (!(jid in helpers.oc(this.chats))) { this.chats.push(jid); } this.addChatToCookie(jid); }; ob.getChatbox = function (jid, callback) { // Get a chatbox. Either it exists, then just ensure // that it's visible and return it. Otherwise, create it. // // This method can be deferred. // http://www.erichynds.com/jquery/using-deferreds-in-jquery/ var chat_content, chat_id = helpers.hash(jid), $chat = $("#"+chat_id), that = this, dfd = $.Deferred(); if (callback === undefined) { callback = function () {}; } if ($chat.length > 0) { if ($chat.is(':visible')) { callback($chat); dfd.resolve(); } else { // The chatbox exists, merely hidden $chat.show('fast', function () { that.prepNewChat(this, jid); that.reorderChats(); callback(this); dfd.resolve(); }); } } else { this.createChatbox(jid, function ($chat) { // that.retrieveCollections(); that.positionNewChat($chat); $chat.show('fast', function () { that.prepNewChat(this, jid); that.handleChatEvents(chat_id); callback(this); dfd.resolve(); }); }); } return dfd.promise(); }; ob.reorderChats = function () { var index = 0, chat_id, offset, $chat; if ('online-users-container' in helpers.oc(this.chats)) { index = 1; $chat = $("#"+helpers.hash(helpers.oc(this.chats)['online-users-container'])); if ($chat.is(':visible')) { $chat.animate({'right': '15px'}); } } for (var i=0; i < this.chats.length; i++) { chat_id = this.chats[i]; if (chat_id === 'online-users-container') { continue; } $chat = $("#"+helpers.hash(this.chats[i])); if ($chat.is(':visible')) { if (index === 0) { $chat.animate({'right': '15px'}); } else { offset = (index)*(this.chatbox_width+7)+15; $chat.animate({'right': offset +'px'}); } index++; } } }; ob.addChatToCookie = function (jid) { var cookie = jQuery.cookie('chats-open-'+xmppchat.username), new_cookie, open_chats = []; if (cookie) { open_chats = cookie.split('|'); } if (!(jid in helpers.oc(open_chats))) { // Update the cookie if this new chat is not yet in it. open_chats.push(jid); new_cookie = open_chats.join('|'); jQuery.cookie('chats-open-'+xmppchat.username, new_cookie, {path: '/'}); console.log('updated cookie = ' + new_cookie + '\n'); } }; ob.removeChatFromCookie = function (jid) { var cookie = jQuery.cookie('chats-open-'+xmppchat.username), open_chats = [], new_chats = []; if (cookie) { open_chats = cookie.split('|'); } for (var i=0; i < open_chats.length; i++) { if (open_chats[i] != jid) { new_chats.push(open_chats[i]); } } if (new_chats.length) { jQuery.cookie('chats-open-'+xmppchat.username, new_chats.join('|'), {path: '/'}); } else { jQuery.cookie('chats-open-'+xmppchat.username, null, {path: '/'}); } }; ob.addMessageToChatbox = function (event) { /* XXX: event.mtype should be 'xhtml' for XHTML-IM messages, but I only seem to get 'text'. XXX: Some messages might be delayed, we must get the time from the event. */ var user_id = Strophe.getNodeFromJid(event.from), jid = Strophe.getBareJidFromJid(event.from), text = event.body.replace(/
/g, ""), that = this; xmppchat.Presence.getUserInfo(user_id, function (data) { that.getChatbox(jid, function (chat) { var chat_content = $(chat).find(".chat-content"), now = new Date(), time = now.toLocaleTimeString().substring(0,5), div = $('
'); if (event.delayed) { div.addClass('delayed'); } if (user_id == that.username) { message_html = div.append( ''+time+' me:  ' + ''+text+'' ); } else { message_html = div.append( ''+time+' '+data.fullname+':  ' + ''+text+'' ); } chat_content.append(message_html); chat_content.scrollTop(chat_content[0].scrollHeight); xmppchat.UI.msg_counter += 1; xmppchat.UI.updateMsgCounter(); }); }); }; ob.closeChat = function (jid) { var chat_id = helpers.hash(jid), that = this; jQuery('#'+chat_id).hide('fast', function () { var idx = that.chats.indexOf(jid); if (idx !== undefined) { that.chats.splice(idx, 1); } that.removeChatFromCookie(jid); that.reorderChats(); }); }; ob.restoreOpenChats = function () { /* Check the open-chats cookie and re-open all the chatboxes it mentions. * We need to wait for current chatbox creation to finish before we create the * next, so we use a task buffer to make sure the next task is only * executed after the previous is done. */ var cookie = jQuery.cookie('chats-open-'+xmppchat.username), open_chats = []; jQuery.cookie('chats-open-'+xmppchat.username, null, {path: '/'}); if (cookie) { open_chats = cookie.split('|'); // FIXME: Change this so that the online contacts box is always created first. for (var i=0; i/g,">").replace(/\"/g,"""); list = message.match(/\b(http:\/\/www\.\S+\.\w+|www\.\S+\.\w+|http:\/\/(?=[^w]){3}\S+[\.:]\S+)[^ ]+\b/g); if (list) { for (i = 0; i < list.length; i++) { message = message.replace( list[i], ""+ list[i] + "" ); } } now = new Date(); minutes = now.getMinutes().toString(); if (minutes.length==1) {minutes = '0'+minutes;} time = now.toLocaleTimeString().substring(0,5); chat_content = jQuery('#'+helpers.hash(jid)+' .chat-content'); chat_content.append( '
' + ''+time+' me:  ' + ''+message+'' + '
'); chat_content.scrollTop(chat_content[0].scrollHeight); }); } } }; return ob; })(xmppchat.UI || {}, jQuery, console || {log: function(){}} ); // Event handlers // -------------- $(document).ready(function () { var chatdata = jQuery('span#babble-client-chatdata'), $toggle = $('a#toggle-online-users'); xmppchat.username = chatdata.attr('username'); xmppchat.base_url = chatdata.attr('base_url'); $toggle.unbind('click'); $toggle.bind('click', function (e) { e.preventDefault(); if ($("div#online-users-container").is(':visible')) { xmppchat.UI.closeChat('online-users-container'); } else { xmppchat.UI.getChatbox('online-users-container'); } }); $(document).unbind('jarnxmpp.message'); $(document).bind('jarnxmpp.message', function (event) { xmppchat.UI.addMessageToChatbox(event); }); $(document).bind('xmppchat.send_presence', function (event, jid, type) { xmppchat.connection.send($pres({'type':type})); }); $(document).unbind('jarnxmpp.presence'); $(document).bind('jarnxmpp.presence', function (event, jid, status, presence) { xmppchat.UI.updateOnPresence(jid, status, presence); }); $(document).unbind('jarnxmpp.connected'); $(document).bind('jarnxmpp.connected', function () { // Logging xmppchat.connection.rawInput = xmppchat.rawInput; xmppchat.connection.rawOutput = xmppchat.rawOutput; // Messages xmppchat.connection.addHandler(xmppchat.Messages.messageReceived, null, 'message', 'chat'); //Roster xmppchat.connection.addHandler(xmppchat.Roster.rosterResult, Strophe.NS.ROSTER, 'iq', 'result'); xmppchat.connection.addHandler(xmppchat.Roster.rosterSuggestedItem, 'http://jabber.org/protocol/rosterx', 'message', null); // Presence xmppchat.connection.addHandler(xmppchat.Presence.presenceReceived, null, 'presence', null); xmppchat.UI.restoreOpenChats(); xmppchat.Presence.sendPresence(); }); $('a.user-details-toggle').live('click', function (e) { var $field = $('[name="message"]:input', $(this).parent()[0]), jid = $field.attr('data-recipient'); e.preventDefault(); xmppchat.UI.getChatbox(jid); }); $('textarea.chat-textarea').live('keypress', function (ev) { xmppchat.UI.keyPressed(ev, this); }); $('a.close-chatbox-button').live('click', function (ev) { var jid = $(ev.target).parent().parent().attr('data-recipient'); xmppchat.UI.closeChat(jid); }); $('ul.tabs').tabs('div.panes > div'); $('select#select-xmpp-status').bind('change', function (ev) { var jid = xmppchat.connection.jid, value = ev.target.value; xmppchat.Presence.sendPresence(value); xmppchat.Storage.set(xmppchat.username+'-xmpp-status', value); }); });