/* Jappix - An open social platform These are the groupchat JS scripts for Jappix ------------------------------------------------- License: AGPL Authors: Valérian Saliou, Maranda, Eric */ // Bundle var Groupchat = (function () { /** * Alias of this * @private */ var self = {}; /* Variables */ var JOIN_SUGGEST = []; /** * Apply generate events * @private * @param {object} input_sel * @param {string} hash * @param {string} room * @return {undefined} */ self._createEvents = function(input_sel, hash, room) { try { self._createEventsInput(input_sel, hash); self._createEventsKey(input_sel, hash, room); } catch(e) { Console.error('Groupchat._createEvents', e); } }; /** * Apply generate events (input) * @private * @param {object} input_sel * @param {string} hash * @return {undefined} */ self._createEventsInput = function(input_sel, hash) { try { // Focus event input_sel.focus(function() { // Clean notifications for this chat Interface.chanCleanNotify(hash); // Store focus on this chat! Interface.chat_focus_hash = hash; }); // Blur event input_sel.blur(function() { // Reset storage about focus on this chat! if(Interface.chat_focus_hash == hash) { Interface.chat_focus_hash = null; } // Reset autocompletion Autocompletion.reset(hash); }); } catch(e) { Console.error('Groupchat._createEventsInput', e); } }; /** * Apply generate events (key) * @private * @param {object} input_sel * @param {string} hash * @param {string} room * @return {undefined} */ self._createEventsKey = function(input_sel, hash, room) { try { // Lock to the input input_sel.keydown(function(e) { // Enter key if(e.keyCode == 13) { // If shift key (without any others modifiers) was pressed, add a new line if(e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey) { input_sel.val(input_sel.val() + '\n'); } else { if(Correction.isIn(room) === true) { var corrected_value = input_sel.val().trim(); if(corrected_value) { // Send the corrected message Correction.send(room, 'groupchat', corrected_value); } Correction.leave(room); } else { // Send the message Message.send(hash, 'groupchat'); // Reset the composing database entry DataStore.setDB(Connection.desktop_hash, 'chatstate', room, 'off'); } } return false; } // Remove chars (leave correction) else if(e.keyCode == 8) { // Leave correction mode? (another way, by flushing input value progressively) if(Correction.isIn(room) === true && !input_sel.val()) { Correction.leave(room); } } // Tabulation key (without any modifiers) else if(!e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey && e.keyCode == 9) { Autocompletion.create(hash); return false; } // Reset the autocompleter else { Autocompletion.reset(hash); } }); input_sel.keyup(function(e) { if(e.keyCode == 27) { // Escape key input_sel.val(''); // Leave correction mode? (simple escape way) if(Correction.isIn(room) === true) { Correction.leave(room); } } else { Correction.detect(room, input_sel); } }); } catch(e) { Console.error('Groupchat._createEventsKey', e); } }; /** * Apply suggest check events * @private * @return {undefined} */ self._suggestCheckEvents = function() { try { // Click events $('#suggest .content a.one').click(function() { var this_sel = $(this); // Add/remove the active class this_sel.toggleClass('active'); // We require at least one room to be chosen if(Common.exists('#suggest .content a.one.active')) { $('#suggest a.next').removeClass('disabled'); } else { $('#suggest a.next').addClass('disabled'); } return false; }); $('#suggest a.next').click(function() { var this_sel = $(this); // Disabled? if(this_sel.hasClass('disabled')) { return false; } // Store groupchats to join? if(this_sel.is('.continue')) { $('#suggest .content a.one.active').each(function() { JOIN_SUGGEST.push(this_sel.attr('data-xid')); }); } // Switch to talk UI $('#suggest').remove(); Connection.triggerConnected(); return false; }); } catch(e) { Console.error('Groupchat._suggestCheckEvents', e); } }; /** * Displays the MUC admin elements * @public * @param {string} affiliation * @param {string} id * @param {string} xid * @param {number} statuscode * @return {undefined} */ self.openAdmin = function(affiliation, id, xid, statuscode) { try { // We must be in the "login" mode if(Utils.isAnonymous()) { return; } // We check if the user is a room owner or administrator to give him privileges if(affiliation == 'owner' || affiliation == 'admin') { $('#' + id + ' .tools-mucadmin').show(); } // We check if the room hasn't been yet created if(statuscode == 201) { Board.openThisInfo(4); } // We add the click event $('#' + id + ' .tools-mucadmin').click(function() { MUCAdmin.open(xid, affiliation); }); } catch(e) { Console.error('Groupchat.openAdmin', e); } }; /** * Initializes a connection with a MUC groupchat * @public * @param {string} room * @param {string} nickname * @param {string} password * @return {boolean} */ self.getMUC = function(room, nickname, password) { try { // Room hash var hash = hex_md5(room); // Reset the elements $('#' + hash + ' .muc-ask').remove(); $('#' + hash + ' .compose').show(); // No nickname? if(!nickname) { // Get some values if(!Utils.isAnonymous()) { nickname = Name.getNick(); } else { nickname = ANONYMOUS_NICK; } // If the nickname could not be retrieved, ask it if(!nickname) { self.generateMUCAsk('nickname', room, hash, nickname, password); } } // Got our nickname? if(nickname) { // Get our general presence var show = DataStore.getDB(Connection.desktop_hash, 'presence-show', 1); var status = DataStore.getDB(Connection.desktop_hash, 'options', 'presence-status'); // Set my nick $('#' + hash).attr('data-nick', escape(nickname)); // Send the appropriate presence Presence.send(room + '/' + nickname, '', show, status, '', true, password, self.handleMUC); } } catch(e) { Console.error('Groupchat.getMUC', e); } finally { return false; } }; /** * Handles the MUC main elements * @public * @param {object} presence * @return {undefined} */ self.handleMUC = function(presence) { try { // We get the xml content var xml = presence.getNode(); var from = Common.fullXID(Common.getStanzaFrom(presence)); var room = Common.bareXID(from); var nickname = Common.thisResource(from); var hash = hex_md5(room); var id = presence.getID(); // No ID: must fix M-Link bug if(id === null) { id = 1; presence.setID(id); } Console.info('First MUC presence: ' + from); // Catch the errors if(!Errors.handle(xml)) { // Define some stuffs var muc_user = $(xml).find('x[xmlns="' + NS_MUC_USER + '"]'); var affiliation = muc_user.find('item').attr('affiliation'); var statuscode = parseInt(muc_user.find('status').attr('code')); // Handle my presence Presence.handle(presence); // Configure the new room if(affiliation == 'owner' || affiliation == 'admin') { console.debug('presence', presence.xml()); self._initialConfiguration(id, room); } // Check if I am a room owner self.openAdmin(affiliation, hash, room, statuscode); // Tell the MUC we can notify the incoming presences $(document).oneTime('15s', function() { $('#' + hash).attr('data-initial', 'true'); }); // Enable the chatting input $(document).oneTime(10, function() { $('#' + hash + ' .message-area').removeAttr('disabled').focus(); }); } // A password is required else if($(xml).find('error[type="auth"] not-authorized').size()) { self.generateMUCAsk('password', room, hash, nickname); } // There's a nickname conflict else if($(xml).find('error[type="cancel"] conflict').size()) { self.generateMUCAsk('nickname', room, hash); } } catch(e) { Console.error('Groupchat.handleMUC', e); } }; /** * Generates a correct MUC asker * @public * @param {string} type * @param {string} room * @param {string} hash * @param {string} nickname * @param {string} password * @return {undefined} */ self.generateMUCAsk = function(type, room, hash, nickname, password) { try { // Generate the path to the elements var path_to = '#' + hash + ' .muc-ask'; // Define the label text var label_text; switch(type) { case 'nickname': label_text = Common._e("Nickname"); break; case 'password': label_text = Common._e("Password"); break; } // Create the HTML markup $('#' + hash + ' .compose').hide(); $('#' + hash).append( '