/* Jappix - An open social platform These are the chat JS scripts for Jappix ------------------------------------------------- License: AGPL Authors: Valérian Saliou, Eric, Maranda */ // Bundle var Chat = (function () { /** * Alias of this * @private */ var self = {}; /** * Apply generate events * @private * @param {string} path * @param {string} id * @param {string} xid * @return {undefined} */ self._generateEvents = function(path, id, xid) { try { // Click event: chat cleaner $(path + 'tools-clear').click(function() { self.clean(id); }); // Click event: call (audio) $(path + 'tools-jingle-audio').click(function() { Jingle.start(xid, 'audio'); }); // Click event: call (video) $(path + 'tools-jingle-video').click(function() { Jingle.start(xid, 'video'); }); // Click event: user-infos $(path + 'tools-infos').click(function() { UserInfos.open(xid); }); } catch(e) { Console.error('Chat._generateEvents', e); } }; /** * Apply generate events * @private * @param {object} input_sel * @param {string} xid * @param {string} hash * @return {undefined} */ self._createEvents = function(input_sel, xid, hash) { try { self._createEventsInput(input_sel, hash); self._createEventsKey(input_sel, xid, hash); self._createEventsMouse(xid, hash); } catch(e) { Console.error('Chat._createEvents', e); } }; /** * Apply generate events (input) * @private * @param {object} input_sel * @param {string} hash * @return {undefined} */ self._createEventsInput = function(input_sel, hash) { try { input_sel.focus(function() { // Clean notifications for this chat Interface.chanCleanNotify(hash); // Store focus on this chat! Interface.chat_focus_hash = hash; }); input_sel.blur(function() { // Reset storage about focus on this chat! if(Interface.chat_focus_hash == hash) { Interface.chat_focus_hash = null; } }); } catch(e) { Console.error('Chat._createEventsInput', e); } }; /** * Apply generate events (key) * @private * @param {object} input_sel * @param {string} xid * @param {string} hash * @return {undefined} */ self._createEventsKey = function(input_sel, xid, hash) { try { input_sel.keydown(function(e) { if(e.keyCode == 13) { // Enter key if(e.shiftKey || e.ctrlKey) { // Add a new line input_sel.val(input_sel.val() + '\n'); } else { if(Correction.isIn(xid) === true) { var corrected_value = input_sel.val().trim(); if(corrected_value) { // Send the corrected message Correction.send(xid, 'chat', corrected_value); } Correction.leave(xid); } else { // Send the message Message.send(hash, 'chat'); } // Reset the composing database entry DataStore.setDB(Connection.desktop_hash, 'chatstate', xid, 'off'); } return false; } else if(e.keyCode == 8) { // Leave correction mode? (another way, by flushing input value progressively) if(Correction.isIn(xid) === true && !input_sel.val()) { Correction.leave(xid); } } }); input_sel.keyup(function(e) { if(e.keyCode == 27) { // Escape key input_sel.val(''); // Leave correction mode? (simple escape way) if(Correction.isIn(xid) === true) { Correction.leave(xid); } } else { Correction.detect(xid, input_sel); } }); } catch(e) { Console.error('Chat._createEventsKey', e); } }; /** * Apply generate events (mouse) * @private * @param {string} xid * @param {string} hash * @return {undefined} */ self._createEventsMouse = function(xid, hash) { try { // Scroll in chat content $('#page-engine #' + hash + ' .content').scroll(function() { var self = this; if(Features.enabledMAM() && !(xid in MAM.map_pending)) { var has_state = xid in MAM.map_states; var rsm_count = has_state ? MAM.map_states[xid].rsm.count : 1; var rsm_before = has_state ? MAM.map_states[xid].rsm.first : ''; // Request more archives? if(rsm_count > 0 && $(this).scrollTop() < MAM.SCROLL_THRESHOLD) { var was_scroll_top = $(self).scrollTop() <= 32; var wait_mam = $('#' + hash).find('.wait-mam'); wait_mam.show(); MAM.getArchives({ 'with': xid }, { 'max': MAM.REQ_MAX, 'before': rsm_before }, function() { var wait_mam_height = was_scroll_top ? 0 : wait_mam.height(); wait_mam.hide(); // Restore scroll? if($(self).scrollTop() < MAM.SCROLL_THRESHOLD) { var sel_mam_chunk = $(self).find('.mam-chunk:first'); var cont_padding_top = parseInt($(self).css('padding-top').replace(/[^-\d\.]/g, '')); var cont_one_group_margin_bottom = parseInt(sel_mam_chunk.find('.one-group:last').css('margin-bottom').replace(/[^-\d\.]/g, '')); var cont_mam_chunk_height = sel_mam_chunk.height(); $(self).scrollTop(wait_mam_height + cont_padding_top + cont_one_group_margin_bottom + cont_mam_chunk_height); } }); } } }); } catch(e) { Console.error('Chat._createEventsMouse', e); } }; /** * Apply generate events * @private * @param {string} type * @param {string} id * @return {object} */ self._generateChatCode = function(type, id) { var code_args = {}; try { // Groupchat special code if(type == 'groupchat') { code_args.attributes = ' data-type="groupchat" data-correction="true"'; code_args.avatar = ''; code_args.name = '

' + Common._e("Subject") + ' ' + Common._e("no subject defined for this room.") + '

'; code_args.code = '
' + '

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

' + '

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

' + '

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

' + '

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

'; code_args.link = ''; code_args.style = ''; // Is this a gateway? if(xid.match(/%/)) { code_args.disabled = ''; } else { code_args.disabled = ' disabled=""'; } } else { code_args.mam = '
'; code_args.attributes = ' data-type="chat"'; code_args.avatar = '
'; code_args.name = '

'; code_args.code = '
' + code_args.mam + '
'; code_args.link = '' + '' + ''; code_args.style = ' style="display: none;"'; code_args.disabled = ''; } // Not a groupchat private chat, we can use the buddy add icon if((type == 'chat') || (type == 'groupchat')) { var title; if(type == 'chat') { title = Common._e("Add this contact to your friends"); } else { title = Common._e("Add this groupchat to your favorites"); } code_args.link += ''; } // IE DOM parsing bug fix code_args.style_picker = '
' + '' + '
'; if((BrowserDetect.browser == 'Explorer') && (BrowserDetect.version < 9)) { code_args.style_picker = ''; } } catch(e) { Console.error('Chat._generateChatCode', e); } finally { return code_args; } }; /** * Correctly opens a new chat * @public * @param {string} xid * @param {string} type * @param {string} nickname * @param {string} password * @param {string} title * @return {boolean} */ self.checkCreate = function(xid, type, nickname, password, title) { try { // No XID? if(!xid) { return false; } // We generate some stuffs var hash = hex_md5(xid); var name; // Gets the name of the user/title of the room if(title) { name = title; } else { // Private groupchat chat if(type == 'private') { name = Common.thisResource(xid); } // XMPP-ID else if(xid.indexOf('@') != -1) { name = Name.getBuddy(xid); } // Gateway else { name = xid; } } // If the target div does not exist if(!Common.exists('#' + hash)) { // We check the type of the chat to open if((type == 'chat') || (type == 'private')) { self.create(hash, xid, name, type); } else if(type == 'groupchat') { // Try to read the room stored configuration if(!Utils.isAnonymous() && (!nickname || !password || !title)) { // Catch the room data var fData = $(Common.XMLFromString(DataStore.getDB(Connection.desktop_hash, 'favorites', xid))); var fNick = fData.find('nick').text(); var fPwd = fData.find('password').text(); var fName = fData.find('name').text(); // Apply the room data if(!nickname && fNick) nickname = fNick; if(!password && fPwd) password = fPwd; if(!title && fName) name = fName; } Groupchat.create(hash, xid, name, nickname, password); } } // Switch to the newly-created chat Interface.switchChan(hash); } catch(e) { Console.error('Chat.checkCreate', e); } finally { return false; } }; /** * Generates the chat DOM elements * @public * @param {string} type * @param {string} id * @param {string} xid * @param {string} nick * @return {undefined} */ self.generate = function(type, id, xid, nick) { try { // Generate some stuffs var path = '#' + id + ' .'; var escaped_xid = escape(xid); // Special code var chat_args = self._generateChatCode(type, id); // Append the chat HTML code $('#page-engine').append( '
' + '
' + chat_args.avatar + '
' + '

' + nick.htmlEnc() + '

' + chat_args.name + '
' + '
' + chat_args.code + '
' + '' + '
' + '' + '
' + '
' + '
' ); self._generateEvents(path, id, xid); } catch(e) { Console.error('Chat.generate', e); } }; /** * Generates the chat switch elements * @public * @param {string} type * @param {string} id * @param {string} xid * @param {string} nick * @return {undefined} */ self.generateSwitch = function(type, id, xid, nick) { try { // Path to the element var chat_switch = '#page-switch .'; // Special code var special_class = ' unavailable'; var show_close = true; // Groupchat if(type == 'groupchat') { special_class = ' groupchat-default'; if(Utils.isAnonymous() && (xid == Common.generateXID(ANONYMOUS_ROOM, 'groupchat'))) { show_close = false; } } // Generate the HTML code var html = '
' + '
' + '
' + nick.htmlEnc() + '
'; // Show the close button if not MUC and not anonymous if(show_close) { html += '
' + 'x' + '
'; } // Close the HTML html += '
'; // Append the HTML code $(chat_switch + 'chans, ' + chat_switch + 'more-content').append(html); } catch(e) { Console.error('Chat.generateSwitch', e); } }; /** * Cleans given the chat lines * @public * @param {string} chat * @return {undefined} */ self.clean = function(chat) { try { // Remove the messages $('#page-engine #' + chat + ' .content .one-group').remove(); // Clear the history database Message.removeLocalArchive(chat); // Focus again $(document).oneTime(10, function() { $('#page-engine #' + chat + ' .text .message-area').focus(); }); } catch(e) { Console.error('Chat.clean', e); } }; /** * Returns whether chat exists or not * @public * @param {string} hash * @return {boolean} */ self.exists = function(hash) { exists = false; try { if(hash) { exists = Common.exists('#' + hash + '.page-engine-chan[data-type="chat"]'); } } catch(e) { Console.error('Chat.exists', e); } finally { return exists; } }; /** * Creates a new chat * @public * @param {string} hash * @param {string} xid * @param {string} nick * @param {string} type * @return {undefined} */ self.create = function(hash, xid, nick, type) { try { Console.info('New chat: ' + xid); // Create the chat content self.generate(type, hash, xid, nick); // Create the chat switcher self.generateSwitch(type, hash, xid, nick); // Is this a chat? if(type == 'chat') { // MAM? Get archives from there! if(Features.enabledMAM()) { MAM.getArchives({ 'with': xid }, { 'max': MAM.REQ_MAX, 'before': '' }); } else { // Restore the chat history var chat_history = Message.readLocalArchive(hash); if(chat_history) { // Generate hashs var my_hash = hex_md5(Common.getXID()); var friend_hash = hex_md5(xid); // Add chat history HTML var path_sel = $('#' + hash); path_sel.find('.content').append(chat_history); // Filter old groups & messages var one_group_sel = path_sel.find('.one-group'); one_group_sel.filter('[data-type="user-message"]').addClass('from-history').attr('data-type', 'old-message'); path_sel.find('.user-message').removeClass('user-message').addClass('old-message'); // Regenerate user names one_group_sel.filter('.' + my_hash + ' b.name').text( Name.getBuddy(Common.getXID()) ); one_group_sel.filter('.' + friend_hash + ' b.name').text( Name.getBuddy(xid) ); // Regenerate group dates one_group_sel.each(function() { var current_stamp = parseInt($(this).attr('data-stamp'), 10); $(this).find('span.date').text(DateUtils.relative(current_stamp)); }); // Regenerate avatars if(Common.exists('#' + hash + ' .one-group.' + my_hash + ' .avatar-container')) { Avatar.get(Common.getXID(), 'cache', 'true', 'forget'); } if(Common.exists('#' + hash + ' .one-group.' + friend_hash + ' .avatar-container')) { Avatar.get(xid, 'cache', 'true', 'forget'); } } } // Add button if(!Roster.isFriend(xid)) { $('#' + hash + ' .tools-add').click(function() { // Hide the icon (to tell the user all is okay) $(this).hide(); // Send the subscribe request Roster.addThisContact(xid, nick); }).show(); } } // We catch the user's informations (like this avatar, vcard, and so on...) UserInfos.get(hash, xid, nick, type); // The icons-hover functions Tooltip.icons(xid, hash); // The event handlers var input_sel = $('#page-engine #' + hash + ' .message-area'); self._createEvents(input_sel, xid, hash); // Input events ChatState.events(input_sel, xid, hash, 'chat'); Markers.events(input_sel, xid, hash, 'chat'); } catch(e) { Console.error('Chat.create', e); } }; /** * Return class scope */ return self; })();