/* Jappix - An open social platform These are the roster JS scripts for Jappix ------------------------------------------------- License: AGPL Author: Valérian Saliou */ // Bundle var Roster = (function () { /** * Alias of this * @private */ var self = {}; /* Variables */ self.blist_all = false; /** * Gets the roster items * @public * @return {undefined} */ self.get = function() { try { var iq = new JSJaCIQ(); iq.setType('get'); iq.setQuery(NS_ROSTER); con.send(iq, self.handle); } catch(e) { Console.error('Roster.get', e); } }; /** * Handles the roster items * @public * @param {object} iq * @return {undefined} */ self.handle = function(iq) { try { // Parse the roster xml $(iq.getQuery()).find('item').each(function() { // Get user data var _this = $(this); var user_xid = _this.attr('jid'); var user_subscription = _this.attr('subscription'); // Parse roster data & display user self.parse($(this), 'load'); // Request user microblog (populates channel) if(user_xid && ((user_subscription == 'both') || (user_subscription == 'to'))) { // Openfire has an issue, forget about it! if(Features.getServerName() != 'openfire') { Microblog.request(user_xid, 1, null, Microblog.handleRoster); } } }); // Update our avatar (if changed), and send our presence Avatar.get(Common.getXID(), 'force', 'true', 'forget'); Console.log('Roster received.'); } catch(e) { Console.error('Roster.handle', e); } }; /** * Parses the group XML and display the roster * @public * @param {string} current * @param {string} mode * @return {undefined} */ self.parse = function(current, mode) { try { // Get the values xid = current.attr('jid'); dName = current.attr('name'); subscription = current.attr('subscription'); xidHash = hex_md5(xid); // Create an array containing the groups var groups = []; current.find('group').each(function() { var group_text = $(this).text(); if(group_text) groups.push(group_text); }); // No group? if(!groups.length) groups.push(Common._e("Unclassified")); // If no name is defined, we get the default nick of the buddy if(!dName) dName = Common.getXIDNick(xid); self.display(xid, xidHash, dName, subscription, groups, mode); } catch(e) { Console.error('Roster.parse', e); } }; /** * Updates the roster groups * @public * @return {undefined} */ self.updateGroups = function() { try { $('#roster .one-group').each(function() { // Current values var check = $(this).find('.buddy').size(); var hidden = $(this).find('.buddy:not(.hidden-buddy:hidden)').size(); // Special case: the filtering tool if(Search.search_filtered) hidden = $(this).find('.buddy:visible').size(); // If the group is empty if(!check) $(this).remove(); // If the group contains no online buddy (and is not just hidden) if(!hidden && $(this).find('a.group').hasClass('minus')) $(this).hide(); else $(this).show(); }); } catch(e) { Console.error('Roster.updateGroups', e); } }; /** * Displays a defined roster item * @public * @param {string} dXID * @param {string} dXIDHash * @param {string} dName * @param {string} dSubscription * @param {string} dGroup * @param {string} dMode * @return {undefined} */ self.display = function(dXID, dXIDHash, dName, dSubscription, dGroup, dMode) { try { // First remove the buddy $('#roster .' + dXIDHash).remove(); // Define some things around the groups var is_gateway = Common.isGateway(dXID); var gateway = ''; if(is_gateway) { gateway = ' gateway'; dGroup = new Array(Common._e("Gateways")); } // Remove request if(dSubscription == 'remove') { // Flush presence Presence.flush(dXID); Presence.funnel(dXID, dXIDHash); // Empty social channel $('#channel .mixed .one-update.update_' + dXIDHash).remove(); } // Other request else { // Is this buddy blocked? var privacy_class = ''; var privacy_state = Privacy.status('block', dXID); if(privacy_state == 'deny') privacy_class = ' blocked'; // For each group this buddy has $.each(dGroup, function(i, cGroup) { if(cGroup) { // Process some vars var groupHash = 'group' + hex_md5(cGroup); var groupContent = '#roster .' + groupHash; var groupBuddies = groupContent + ' .group-buddies'; // Is this group blocked? if((Privacy.status('block', cGroup) == 'deny') && (privacy_state != 'allow')) privacy_class = ' blocked'; // Group not yet displayed if(!Common.exists(groupContent)) { // Define some things var groupCont = '#roster .content'; var groupToggle = groupCont + ' .' + groupHash + ' a.group'; // Create the HTML markup of the group $(groupCont).prepend( '
' + '' + cGroup.htmlEnc() + '' + '
' + '
' ); // Create the click event which will hide and show the content $(groupToggle).click(function() { var group = $(groupBuddies); var group_toggle = $(groupContent + ' a.group'); // We must hide the buddies if(group_toggle.hasClass('minus')) { group.hide(); group_toggle.removeClass('minus').addClass('plus'); // Remove the group opened buddy-info Bubble.close(); } // We must show the buddies else { group_toggle.removeClass('plus').addClass('minus'); group.show(); } return false; }); } // Initialize the HTML code var name_code = '

' + dName.htmlEnc() + '

'; var presence_code = '

' + Common._e("Unavailable") + '

'; var html = '
' + '
'; // Display avatar if not gateway if(!is_gateway) { html += '
' + '' + '
'; } html += '
'; // Special gateway code if(is_gateway) html += presence_code + name_code; else html += name_code + presence_code; html += '
'; // Create the DOM element for this buddy $(groupBuddies).append(html); // Apply the hover event self.applyBuddyHover(dXID, dXIDHash, dName, dSubscription, dGroup, groupHash); } }); // Click event on this buddy $('#roster .' + dXIDHash + ' .buddy-click').click(function() { return Chat.checkCreate(dXID, 'chat'); }); // We get the user presence if necessary if(dMode == 'presence') { Presence.funnel(dXID, dXIDHash); } // If the buddy must be shown if(self.blist_all) { $('#roster .' + dXIDHash).show(); } } // We update our groups if(!Search.search_filtered) { self.updateGroups(); } else { Search.funnelFilterBuddy(); } } catch(e) { Console.error('Roster.display', e); } }; /** * Applies the buddy editing input events * @public * @param {string} xid * @return {undefined} */ self.applyBuddyInput = function(xid) { try { // Initialize var path = '#roster .buddy[data-xid="' + escape(xid) + '"]'; var rename = path + ' .bm-rename input'; var group = path + ' .bm-group input'; var manage_infos = path + ' .manage-infos'; var bm_choose = manage_infos + ' div.bm-choose'; // Keyup events $(rename).keyup(function(e) { if(e.keyCode == 13) { // Send the item self.send(xid, '', $.trim($(rename).val()), self.thisBuddyGroups(xid)); // Remove the buddy editor Bubble.close(); return false; } }); $(group).keyup(function(e) { if(e.keyCode == 13) { // Empty input? if(!$.trim($(this).val())) { // Send the item self.send(xid, '', $.trim($(rename).val()), self.thisBuddyGroups(xid)); // Remove the buddy editor Bubble.close(); return false; } // Get the values var this_value = $.trim($(this).val()); var escaped_value = escape(this_value); // Check if the group yet exists var group_exists = false; $(bm_choose + ' label span').each(function() { if($(this).text() == this_value) group_exists = true; }); // Create a new checked checkbox if(!group_exists) $(bm_choose).prepend(''); // Check the checkbox $(bm_choose + ' input[data-group="' + escaped_value + '"]').attr('checked', true); // Reset the value of this input $(this).val(''); return false; } }); // Click events $(manage_infos + ' p.bm-authorize a.to').click(function() { Bubble.close(); Presence.sendSubscribe(xid, 'subscribed'); return false; }); $(manage_infos + ' p.bm-authorize a.from').click(function() { Bubble.close(); Presence.sendSubscribe(xid, 'subscribe'); return false; }); $(manage_infos + ' p.bm-authorize a.unblock').click(function() { Bubble.close(); // Update privacy settings Privacy.push('block', ['jid'], [xid], ['allow'], [false], [true], [true], [true], '', 'roster'); $(path).removeClass('blocked'); // Enable the "block" list Privacy.change('block', 'active'); Privacy.change('block', 'default'); // Send an available presence Presence.send(xid, 'available', Presence.getUserShow(), getUserStatus()); return false; }); $(manage_infos + ' p.bm-remove a.remove').click(function() { Bubble.close(); // First unregister if gateway if(Common.isGateway(xid)) self.unregisterGateway(xid); // Then send roster removal query self.send(xid, 'remove'); return false; }); $(manage_infos + ' p.bm-remove a.prohibit').click(function() { Bubble.close(); Presence.sendSubscribe(xid, 'unsubscribed'); return false; }); $(manage_infos + ' p.bm-remove a.block').click(function() { Bubble.close(); // Update privacy settings Privacy.push('block', ['jid'], [xid], ['deny'], [false], [true], [true], [true], '', 'roster'); $(path).addClass('blocked'); // Enable the "block" list Privacy.change('block', 'active'); Privacy.change('block', 'default'); // Send an unavailable presence Presence.send(xid, 'unavailable'); // Remove the user presence var db_regex = new RegExp(('^' + Connection.desktop_hash + '_') + 'presence' + ('_(.+)')); for(var i = 0; i < DataStore.storageDB.length; i++) { // Get the pointer values var current = DataStore.storageDB.key(i); // If the pointer is on a stored presence if(current.match(db_regex)) { if(Common.bareXID(RegExp.$1) == xid) DataStore.storageDB.removeItem(current); } } // Manage his new presence Presence.funnel(xid, hex_md5(xid)); return false; }); $(manage_infos + ' a.save').click(function() { // Send the item self.send(xid, '', $.trim($(rename).val()), self.thisBuddyGroups(xid)); // Remove the buddy editor Bubble.close(); return false; }); } catch(e) { Console.error('Roster.applyBuddyInput', e); } }; /** * Applies the buddy editing hover events * @public * @param {string} xid * @param {string} hash * @param {string} nick * @param {string} subscription * @param {object} groups * @param {string} group_hash * @return {undefined} */ self.applyBuddyHover = function(xid, hash, nick, subscription, groups, group_hash) { try { // Generate the values var bPath = '#roster .' + group_hash + ' .buddy[data-xid="' + escape(xid) + '"]'; var iPath = bPath + ' .buddy-infos'; // Apply the hover event $(bPath).hover(function() { // Another bubble exist if(Common.exists('#roster .buddy-infos')) return false; $(bPath).oneTime(200, function() { // Another bubble exist if(Common.exists('#roster .buddy-infos')) return false; // Add this bubble! Bubble.show(iPath); // Create the buddy infos DOM element $(bPath).append( '
' + '
' + '
' + '
' + '

' + Common._e("unknown") + '

' + '

' + Common._e("unknown") + '

' + '

' + Common._e("unknown") + '

' + '

' + Common._e("unknown") + '

' + '

' + Common._e("unknown") + '

' + '

' + Common._e("Audio Call") + ' / ' + Common._e("Video Call") + '' + '

' + Common._e("Profile") + ' / ' + Common._e("Channel") + ' / ' + Common._e("Commands") + '

' + '

' + Common._e("Edit") + '

' + '
' + '
' + '
' ); // Sets the good position self.buddyInfosPosition(xid, group_hash); // Get the presence Presence.funnel(xid, hash); // Get the PEP infos PEP.displayAll(xid); // Click events $(bPath + ' .bi-view a').click(function() { // Renitialize the buddy infos Bubble.close(); // Profile if($(this).is('.profile')) UserInfos.open(xid); // Channel else if($(this).is('.channel')) Microblog.fromInfos(xid, hash); // Command else if($(this).is('.commands')) AdHoc.retrieve(xid); return false; }); // Jingle events $(bPath + ' .bi-jingle a').click(function() { // Renitialize the buddy infos Bubble.close(); // Audio call? if($(this).is('.audio')) Jingle.start(xid, 'audio'); // Video call? else if($(this).is('.video')) Jingle.start(xid, 'video'); return false; }); $(bPath + ' .bi-edit a').click(function() { self.buddyEdit(xid, nick, subscription, groups); return false; }); }); }, function() { if(!Common.exists(iPath + ' .manage-infos')) Bubble.close(); $(bPath).stopTime(); }); } catch(e) { Console.error('Roster.applyBuddyHover', e); } }; /** * Sets the good buddy-infos position * @public * @param {string} xid * @param {string} group_hash * @return {undefined} */ self.buddyInfosPosition = function(xid, group_hash) { try { // Paths var group = '#roster .' + group_hash; var buddy = group + ' .buddy[data-xid="' + escape(xid) + '"]'; var buddy_infos = buddy + ' .buddy-infos'; // Get the offset to define var offset = 3; if(Common.isGateway(xid)) offset = -8; // Process the position var v_position = $(buddy).position().top + offset; var h_position = $(buddy).width() - 10; // Apply the top position $(buddy_infos).css('top', v_position); // Apply the left/right position if($('html').attr('dir') == 'rtl') $(buddy_infos).css('right', h_position); else $(buddy_infos).css('left', h_position); } catch(e) { Console.error('Roster.buddyInfosPosition', e); } }; /** * Generates an array of the current groups of a buddy * @public * @param {string} xid * @return {undefined} */ self.thisBuddyGroups = function(xid) { try { var path = '#roster .buddy[data-xid="' + escape(xid) + '"] '; var array = []; // Each checked checkboxes $(path + 'div.bm-choose input[type="checkbox"]').filter(':checked').each(function() { array.push(unescape($(this).attr('data-group'))); }); // Entered input value (and not yet in the array) var value = $.trim($(path + 'p.bm-group input').val()); if(value && !Utils.existArrayValue(array, value)) array.push(value); return array; } catch(e) { Console.error('Roster.thisBuddyGroups', e); } }; /** * Adds a given contact to our roster * @public * @param {string} xid * @param {string} name * @return {undefined} */ self.addThisContact = function(xid, name) { try { Console.info('Add this contact: ' + xid + ', as ' + name); // Cut the resource of this XID xid = Common.bareXID(xid); // If the form is complete if(xid) { // We send the subscription Presence.sendSubscribe(xid, 'subscribe'); self.send(xid, '', name); // We hide the bubble Bubble.close(); } } catch(e) { Console.error('Roster.addThisContact', e); } }; /** * Gets an array of all the groups in the roster * @public * @param {type} name * @return {undefined} */ self.getAllGroups = function() { try { var groups = []; $('#roster .one-group').each(function() { var current = unescape($(this).attr('data-group')); if((current != Common._e("Unclassified")) && (current != Common._e("Gateways"))) groups.push(current); }); return groups.sort(); } catch(e) { Console.error('Roster.getAllGroups', e); } }; /** * Edits buddy informations * @public * @param {string} xid * @param {string} nick * @param {string} subscription * @param {object} groups * @return {undefined} */ self.buddyEdit = function(xid, nick, subscription, groups) { try { Console.info('Buddy edit: ' + xid); // Initialize var path = '#roster .buddy[data-xid="' + escape(xid) + '"] .'; var html = '
'; // Get the privacy state var privacy_state = Privacy.status('block', xid); var privacy_active = DataStore.getDB(Connection.desktop_hash, 'privacy-marker', 'available'); // Get the group privacy state for(var g in groups) { if((Privacy.status('block', groups[g]) == 'deny') && (privacy_state != 'allow')) privacy_state = 'deny'; } // The subscription with this buddy is not full if((subscription != 'both') || ((privacy_state == 'deny') && privacy_active)) { var authorize_links = ''; html += '

'; // Link to allow to see our status if((subscription == 'to') || (subscription == 'none')) authorize_links += '' + Common._e("Authorize") + ''; // Link to ask to see his/her status if((subscription == 'from') || (subscription == 'none')) { if(authorize_links) authorize_links += ' / '; authorize_links += '' + Common._e("Ask for authorization") + ''; } // Link to unblock this buddy if((privacy_state == 'deny') && privacy_active) { if(authorize_links) authorize_links += ' / '; html += '' + Common._e("Unblock") + ''; } html += authorize_links + '

'; } // Complete the HTML code var remove_links = ''; html += '

'; remove_links = '' + Common._e("Remove") + ''; // This buddy is allowed to see our presence, we can show a "prohibit" link if((subscription == 'both') || (subscription == 'from')) remove_links += ' / ' + Common._e("Prohibit") + ''; // Complete the HTML code if((privacy_state != 'deny') && privacy_active) { if(remove_links) remove_links += ' / '; remove_links += '' + Common._e("Block") + ''; } // Complete the HTML code html += remove_links + '

' + '

'; // Only show group tool if not a gateway if(!Common.isGateway(xid)) html += '

' + '
' + '
' + '
'; // Close the DOM element html += '' + Common._e("Save") + '' + '
'; // We update the DOM elements $(path + 'pep-infos').replaceWith(html); // Gets all the existing groups var all_groups = self.getAllGroups(); var all_groups_dom = ''; for(var a in all_groups) { // Current group var all_groups_current = all_groups[a]; // Is the current group checked? var checked = ''; if(Utils.existArrayValue(groups, all_groups_current)) checked = ' checked="true"'; // Add the current group HTML all_groups_dom += ''; } // Prepend this in the DOM var bm_choose = path + 'manage-infos div.bm-choose'; $(bm_choose).prepend(all_groups_dom); // Apply the editing input events self.applyBuddyInput(xid); } catch(e) { Console.error('Roster.buddyEdit', e); } }; /** * Unregisters from a given gateway * @public * @param {string} xid * @return {undefined} */ self.unregisterGateway = function(xid) { try { var iq = new JSJaCIQ(); iq.setType('set'); iq.setTo(xid); var query = iq.setQuery(NS_REGISTER); query.appendChild(iq.buildNode('remove', {'xmlns': NS_REGISTER})); con.send(iq); } catch(e) { Console.error('Roster.unregisterGateway', e); } }; /** * Updates the roster items * @public * @param {string} xid * @param {string} subscription * @param {string} name * @param {string} group * @return {undefined} */ self.send = function(xid, subscription, name, group) { try { // We send the new buddy name var iq = new JSJaCIQ(); iq.setType('set'); var iqQuery = iq.setQuery(NS_ROSTER); var item = iqQuery.appendChild(iq.buildNode('item', {'xmlns': NS_ROSTER, 'jid': xid})); // Any subscription? if(subscription) item.setAttribute('subscription', subscription); // Any name? if(name) item.setAttribute('name', name); // Any group? if(group && group.length) { for(var i in group) item.appendChild(iq.buildNode('group', {'xmlns': NS_ROSTER}, group[i])); } con.send(iq); Console.info('Roster item sent: ' + xid); } catch(e) { Console.error('Roster.send', e); } }; /** * Adapts the roster height, depending of the window size * @public * @return {undefined} */ self.adapt = function() { try { // Process the new height var new_height = $('#left-content').height() - $('#my-infos').height() - 97; // New height too small if(new_height < 211) new_height = 211; // Apply the new height $('#roster .content').css('height', new_height); } catch(e) { Console.error('Roster.adapt', e); } }; /** * Gets all the buddies in our roster * @public * @return {object} */ self.getAllBuddies = function() { try { var buddies = []; $('#roster .buddy').each(function() { var xid = unescape($(this).attr('data-xid')); if(xid) { buddies.push(xid); } }); return buddies; } catch(e) { Console.error('Roster.getAllBuddies', e); } }; /** * Returns whether given XID is in buddy list or not * @public * @param {string} xid * @return {boolean} */ self.isFriend = function(xid) { try { return Common.exists('#roster .buddy[data-xid="' + escape(xid) + '"]'); } catch(e) { Console.error('Roster.isFriend', e); } }; /** * Gets the user gateways * @public * @return {object} */ self.getGateways = function() { try { // New array var gateways = []; var buddies = self.getAllBuddies(); // Get the gateways for(var c in buddies) { if(Common.isGateway(buddies[c])) { gateways.push(buddies[c]); } } return gateways; } catch(e) { Console.error('Roster.getGateways', e); } }; /** * Instanciate the roster * @public * @return {undefined} */ self.instance = function() { try { // Filtering tool var iFilter = $('#roster .filter input'); var aFilter = $('#roster .filter a'); iFilter.placeholder() .blur(function() { // Nothing is entered, put the placeholder instead if(!$.trim($(this).val())) aFilter.hide(); else aFilter.show(); }) .keyup(function(e) { Search.funnelFilterBuddy(e.keyCode); }); aFilter.click(function() { // Reset the input $(this).hide(); iFilter.val(''); iFilter.placeholder(); // Security: show all the groups, empty or not $('#roster .one-group').show(); // Reset the filtering tool Search.resetFilterBuddy(); return false; }); // When the user click on the add button, show the contact adding tool $('#roster .foot .add').click(function() { // Yet displayed? if(Common.exists('#buddy-conf-add')) return Bubble.close(); // Add the bubble Bubble.show('#buddy-conf-add'); // Append the content $('#roster .roster-add').append( '
' + '
' + '
' + '

' + Common._e("Add a friend") + '

' + '' + '' + '' + '' + Common._e("Getting the name...") + '' + '

' + '' + Common._e("Search a friend") + '' + '

' + '
' + '
' ); // Add the gateways var gateways = self.getGateways(); // Any gateway? if(gateways.length) { // Append the gateways for(var i in gateways) { $('.add-contact-gateway').append(''); } // Show the gateway selector $('.add-contact-gateway').parent().show(); } else { $('.add-contact-gateway').parent().hide(); } // Blur event on the add contact input $('.add-contact-jid').blur(function() { // Read the value var value = $.trim($(this).val()); // Try to catch the buddy name if(value && !$.trim($('.add-contact-name').val()) && ($('.add-contact-gateway').val() == 'none')) { // User XID var xid = Common.generateXID(value, 'chat'); // Notice for the user $('.add-contact-name-get').attr('data-for', escape(xid)).show(); // Request the user vCard Name.getAddUser(xid); } }); // When a key is pressed... $('#buddy-conf-add input, #buddy-conf-add select').keyup(function(e) { // Enter : continue if(e.keyCode == 13) { // Get the values var xid = $.trim($('.add-contact-jid').val()); var name = $.trim($('.add-contact-name').val()); var gateway = unescape($('.add-contact-gateway').val()); // Generate the XID to add if((gateway != 'none') && xid) xid = xid.replace(/@/g, '%') + '@' + gateway; else xid = Common.generateXID(xid, 'chat'); // Submit the form if(xid && Common.getXIDNick(xid) && (xid != Common.getXID())) self.addThisContact(xid, name); else $(document).oneTime(10, function() { $('.add-contact-jid').addClass('please-complete').focus(); }); return false; } // Escape : quit if(e.keyCode == 27) Bubble.close(); }); // Click event on search link $('.buddy-conf-add-search').click(function() { Bubble.close(); return Directory.open(); }); // Focus on the input $(document).oneTime(10, function() { $('.add-contact-jid').focus(); }); return false; }); // When the user click on the join button, show the chat joining tool $('#roster .foot .join').click(function() { // Yet displayed? if(Common.exists('#buddy-conf-join')) return Bubble.close(); // Add the bubble Bubble.show('#buddy-conf-join'); // Append the content $('#roster .roster-join').append( '
' + '
' + '' + '
' ); // Input vars var destination = '#buddy-conf-join .search'; var dHovered = destination + ' ul li.hovered:first'; // When a key is pressed... $('#buddy-conf-join input, #buddy-conf-join select').keyup(function(e) { // Enter: continue if(e.keyCode == 13) { // Select something from the search if(Common.exists(dHovered)) { Search.addBuddy(destination, $(dHovered).attr('data-xid')); } // Join something else { var xid = $.trim($('.join-jid').val()); var type = $('.buddy-conf-join-select').val(); if(xid && type) { // Generate a correct XID xid = Common.generateXID(xid, type); // Not me if(xid != Common.getXID()) { // Update some things $('.join-jid').removeClass('please-complete'); Bubble.close(); // Create a new chat Chat.checkCreate(xid, type); } else { $('.join-jid').addClass('please-complete'); } } else { $('.join-jid').addClass('please-complete'); } } return false; } // Escape: quit else if(e.keyCode == 27) Bubble.close(); // Buddy search? else if($('.buddy-conf-join-select').val() == 'chat') { // New buddy search if((e.keyCode != 40) && (e.keyCode != 38)) Search.createBuddy(destination); // Navigating with keyboard in the results Search.arrowsBuddy(e, destination); } }); // Buddy search lost focus $('#buddy-conf-join input').blur(function() { if(!$(destination + ' ul').attr('mouse-hover')) Search.resetBuddy(destination); }); // Re-focus on the text input $('#buddy-conf-join select').change(function() { $(document).oneTime(10, function() { $('#buddy-conf-join input').focus(); }); }); // We focus on the input $(document).oneTime(10, function() { $('#buddy-conf-join .join-jid').focus(); }); return false; }); // When the user click on the groupchat button, show the groupchat menu $('#roster .foot .groupchat').click(function() { // Yet displayed? if(Common.exists('#buddy-conf-groupchat')) return Bubble.close(); // Add the bubble Bubble.show('#buddy-conf-groupchat'); // Append the content $('#roster .roster-groupchat').append( '
' + '
' + '
' + '

' + Common._e("Your groupchats") + '

' + '' + '

' + '- ' + Common._e("Manage your favorite groupchats") + '' + '

' + '
' + '
' ); // When the user wants to edit his groupchat favorites $('.buddy-conf-groupchat-edit').click(function() { Favorites.open(); Bubble.close(); return false; }); // Change event $('.buddy-conf-groupchat-select').change(function() { var groupchat = $.trim($(this).val()); if(groupchat != 'none') { // We hide the bubble Bubble.close(); // Create the chat Chat.checkCreate(groupchat, 'groupchat'); // We reset the select value $(this).val('none'); } }); // Load the favorites Favorites.load(); return false; }); // When the user click on the more button, show the more menu $('#roster .foot .more').click(function() { // Yet displayed? if(Common.exists('#buddy-conf-more')) return Bubble.close(); // Add the bubble Bubble.show('#buddy-conf-more'); // Append the content $('#roster .roster-more').append( '
' + '
' + '
' + '

' + Common._e("More stuff") + '

' + '

' + '- ' + Common._e("Show all friends") + '' + '' + Common._e("Only show connected friends") + '' + '

' + '

' + '- ' + Common._e("Privacy") + '' + '

' + '

' + '- ' + Common._e("Service discovery") + '' + '

' + '

' + '- ' + Common._e("Commands") + '' + '

' + '
' + '
' ); // Close bubble when link clicked $('#buddy-conf-more a').click(function() { Bubble.close(); }); // When the user wants to display all his buddies $('.buddy-conf-more-display-unavailable').click(function() { Interface.showAllBuddies('roster'); return false; }); // When the user wants to display only online buddies $('.buddy-conf-more-display-available').click(function() { Interface.showOnlineBuddies('roster'); return false; }); // When the user click on the privacy link $('.buddy-conf-more-privacy').click(Privacy.open); // When the user click on the service discovery link $('.buddy-conf-more-service-disco').click(Discovery.open); // When the user click on the command link $('.buddy-conf-more-commands').click(function() { AdHoc.server(con.domain); return false; }); // Manage the displayed links if(self.blist_all) { $('.buddy-conf-more-display-unavailable').hide(); $('.buddy-conf-more-display-available').show(); } if(Features.enabledCommands()) $('.buddy-conf-more-commands').parent().show(); if(DataStore.getDB(Connection.desktop_hash, 'privacy-marker', 'available')) $('.buddy-conf-more-privacy').parent().show(); return false; }); // When the user scrolls the buddy list $('#roster .content').scroll(function() { // Close the opened buddy infos bubble Bubble.close(); }); } catch(e) { Console.error('Roster.instance', e); } }; /** * Plugin launcher * @public * @return {undefined} */ self.launch = function() { try { // Window resize event handler $(window).resize(self.adapt); } catch(e) { Console.error('Roster.launch', e); } }; /** * Return class scope */ return self; })(); Roster.launch();