/* Jappix - An open social platform These are the interface JS scripts for Jappix ------------------------------------------------- License: AGPL Author: Valérian Saliou */ // Bundle var Interface = (function () { /** * Alias of this * @private */ var self = {}; /* Variables */ self.chat_focus_hash = null; /** * Changes the title of the document * @public * @param {string} new_title * @return {undefined} */ self.title = function(title_type) { try { // Anonymous mode? var head_name = Name.get(); if(Utils.isAnonymous()) { head_name = ANONYMOUS_ROOM + ' (' + Common._e("anonymous mode") + ')'; } // We change the title to give essential informations switch(title_type) { case 'home': document.title = SERVICE_NAME + ' • ' + SERVICE_DESC; break; case 'talk': document.title = SERVICE_NAME + ' • ' + head_name; break; case 'new': document.title = '[' + self.pendingEvents() + '] ' + SERVICE_NAME + ' • ' + head_name; break; case 'wait': document.title = SERVICE_NAME + ' • ' + Common._e("Please wait..."); break; } } catch(e) { Console.error('Interface.title', e); } }; /** * Creates a general-wait item * @public * @return {boolean} */ self.showGeneralWait = function() { try { // Item exists? if(Common.exists('#general-wait')) return false; // Generate the HTML code var html = '
' + '
' + '
'; // Append the HTML code $('body').append(html); return true; } catch(e) { Console.error('Interface.showGeneralWait', e); } }; /** * Removes the general-wait item * @public * @return {undefined} */ self.removeGeneralWait = function() { try { $('#general-wait').remove(); } catch(e) { Console.error('Interface.removeGeneralWait', e); } }; /** * Generates a file upload valid form content * @public * @return {undefined} */ self.generateFileShare = function() { try { return '' + '' + '' + '' + '' + ''; } catch(e) { Console.error('Interface.generateFileShare', e); } }; /** * Switches to the given chan * @public * @param {string} id * @return {boolean} */ self.switchChan = function(id) { try { if(Common.exists('#' + id)) { // We show the page-engine content $('.page-engine-chan').hide(); $('#' + id).show(); // We edit the tab switcher $('#page-switch .switcher').removeClass('activechan').addClass('chan'); $('#page-switch .' + id).addClass('activechan').removeClass('chan'); // Scroll down to the last message if(id != 'channel') { self.autoScroll(id); } // Manage input focus self.inputFocus(); } } catch(e) { Console.error('Interface.switchChan', e); } finally { return false; } }; /** * Loads the complete chat switcher * @public * @return {undefined} */ self.loadChatSwitch = function() { try { // Path var more_content = '#page-switch .more-content'; // Yet displayed? if(Common.exists(more_content)) return Bubble.close(); // Add the bubble Bubble.show(more_content); // Append the content $('#page-switch .more').append( '
' + $('#page-switch .chans').html() + '
' ); } catch(e) { Console.error('Interface.loadChatSwitch', e); } finally { return false; } }; /** * Loads the groupchat joiner * @public * @return {undefined} */ self.loadJoinGroupchat = function() { try { // Path var join_content = '#page-switch .join-content'; var join_sel = $('#page-switch .join'); // Yet displayed? if(Common.exists(join_content)) return Bubble.close(); // Add the bubble Bubble.show(join_content); // Append the content join_sel.append( '
' + '' + '
' ); var input_sel = join_sel.find('input.join-groupchat-xid'); input_sel.keyup(function(e) { // Enter: continue if(e.keyCode == 13) { var this_sel = $(this); var xid = $.trim(this_sel.val()); if(xid) { // Generate a correct XID xid = Common.generateXID(xid, 'groupchat'); Bubble.close(); Chat.checkCreate(xid, 'groupchat'); } else { this_sel.addClass('please-complete'); } return false; } }); $(document).oneTime(10, function() { input_sel.focus(); }); } catch(e) { Console.error('Interface.loadJoinGroupchat', e); } finally { return false; } }; /** * Puts the selected smiley in the good page-engine input * @public * @param {string} smiley * @param {string} hash * @return {boolean} */ self.insertSmiley = function(smiley, hash) { try { // We define the variables var selector = $('#' + hash + ' .message-area'); var oValue = selector.val(); // Any old value? if(oValue && !oValue.match(/^(.+)(\s)+$/)) { oValue += ' '; } var nValue = oValue + smiley + ' '; // Put the new value and focus on it $(document).oneTime(10, function() { selector.val(nValue).focus(); }); } catch(e) { Console.error('Interface.insertSmiley', e); } }; /** * Deletes all the associated elements of the chat we want to remove * @public * @param {string} hash * @return {undefined} */ self.deleteThisChat = function(hash) { try { $('#' + hash + ', #page-switch .' + hash).remove(); } catch(e) { Console.error('Interface.deleteThisChat', e); } }; /** * Closes the given chat * @public * @param {string} xid * @param {string} hash * @param {string} type * @return {boolean} */ self.quitThisChat = function(xid, hash, type) { try { if(type == 'groupchat') { // Send our unavailable presence Presence.send(xid + '/' + Name.getMUCNick(hash), 'unavailable'); // Remove all presence database entries for this groupchat 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(current.match(db_regex)) { var cXID = RegExp.$1; // If the pointer is on a presence from this groupchat if(Common.bareXID(cXID) == xid) { // Generate the hash for the current XID var cHash = hex_md5(cXID); // Disable the message textarea $('#' + cHash + ' .message-area').attr('disabled', true); // Remove the presence for this XID DataStore.removeDB(Connection.desktop_hash, 'presence-stanza', cXID); DataStore.removeDB(Connection.desktop_hash, 'presence-resources', cXID); Presence.funnel(cXID, cHash); } } } } else { ChatState.send('gone', xid, hash); } // Clear MAM storage for this chat if(xid in MAM.map_states) { delete MAM.map_states[xid]; } // Get the chat ID which is before var previous = $('#' + hash).prev().attr('id'); // Remove the chat self.deleteThisChat(hash); // Reset the switcher if(!Common.exists('#page-switch .switcher.activechan')) { self.switchChan(previous); } // Reset the notifications self.chanCleanNotify(hash); } catch(e) { Console.error('Interface.quitThisChat', e); } finally { return false; } }; /** * Generates the chat logs * @public * @param {string} xid * @param {string} hash * @return {boolean} */ self.generateChatLog = function(xid, hash) { try { // Get the main values var path = '#' + hash + ' .'; var content = $(path + 'content').clone().contents(); var avatar = $(path + 'top .avatar-container:first').html(); var nick = $(path + 'top .bc-name').text(); var date = DateUtils.getXMPPTime('local'); var type = $('#' + hash).attr('data-type'); var direction = $('html').attr('dir') || 'ltr'; // Filter the content smileys $(content).find('img.emoticon').each(function() { $(this).replaceWith($(this).attr('alt')); }); // Remove the useless attributes $(content).removeAttr('data-type').removeAttr('data-stamp'); // Remove the content avatars $(content).find('.avatar-container').remove(); // Remove the content click events $(content).find('a').removeAttr('onclick'); // Extract the content HTML code content = $(content).parent().html(); // No avatar? if(!avatar || !avatar.match(/data:/)) avatar = 'none'; // POST the values to the server $.post('./server/generate-chat.php', { 'content': content, 'xid': xid, 'nick': nick, 'avatar': avatar, 'date': date, 'type': type, 'direction': direction }, function(data) { // Handled! $(path + 'tooltip-waitlog').replaceWith('' + Common._e("Download file!") + ''); }); } catch(e) { Console.error('Interface.generateChatLog', e); } finally { return false; } }; /** * Notifies the user from a new incoming message * @public * @param {string} hash * @param {string} type * @return {undefined} */ self.messageNotify = function(hash, type) { try { // Initialize the vars var chat_switch = '#page-switch .'; var tested = chat_switch + hash; var active = $(tested).hasClass('activechan'); // We notify the user if he has not the focus on the chat if(!active || !Common.isFocused() || (self.chat_focus_hash != hash)) { if(!active) { if(type == 'personal') { $(tested + ', ' + chat_switch + 'more-button').addClass('chan-newmessage'); } else if(type == 'unread') { $(tested).addClass('chan-unread'); } } // Count the number of pending messages var pending = 1; if(Common.exists('#' + hash + '[data-counter]')) { pending = parseInt($('#' + hash).attr('data-counter')) + 1; } $('#' + hash).attr('data-counter', pending); } // Update the page title self.updateTitle(); } catch(e) { Console.error('Interface.messageNotify', e); } }; /** * Returns the number of pending events * @public * @return {number} */ self.pendingEvents = function() { try { // Count the number of notifications var number = 0; $('.one-counter[data-counter]').each(function() { number = number + parseInt($(this).attr('data-counter')); }); return number; } catch(e) { Console.error('Interface.pendingEvents', e); } }; /** * Updates the page title * @public * @return {undefined} */ self.updateTitle = function() { try { // Any pending events? if(Common.exists('.one-counter[data-counter]')) self.title('new'); else self.title('talk'); } catch(e) { Console.error('Interface.updateTitle', e); } }; /** * Cleans the given chat notifications * @public * @param {string} hash * @return {undefined} */ self.chanCleanNotify = function(hash) { try { // We remove the class that tell the user of a new message var chat_switch = '#page-switch .'; $(chat_switch + hash).removeClass('chan-newmessage chan-unread'); // We reset the global notifications if no more unread messages if(!$(chat_switch + 'chans .chan-newmessage').size()) $(chat_switch + 'more-button').removeClass('chan-newmessage'); // We reset the chat counter $('#' + hash).removeAttr('data-counter'); // Update the page title self.updateTitle(); } catch(e) { Console.error('Interface.chanCleanNotify', e); } }; /** * Scrolls to the last chat message * @public * @param {string} hash * @return {undefined} */ self.autoScroll = function(hash) { try { // Avoid a JS error if(Common.exists('#' + hash)) { var container = document.getElementById('chat-content-' + hash); // Scroll down! container.scrollTop = container.scrollHeight; } } catch(e) { Console.error('Interface.autoScroll', e); } }; /** * Shows all the buddies in the roster * @public * @param {string} from * @return {undefined} */ self.showAllBuddies = function(from) { try { // Put a marker Roster.blist_all = true; // We switch the two modes $('.buddy-conf-more-display-unavailable').hide(); $('.buddy-conf-more-display-available').show(); // Security: reset all the groups toggle event $('#roster .group-buddies').show(); $('#roster .group span').text('-'); // We show the disconnected buddies $('.hidden-buddy').show(); // We show all the groups $('#roster .one-group').show(); if(Search.search_filtered) Search.funnelFilterBuddy(); // Store this in the options if((from == 'roster') && Options.loaded()) { DataStore.setDB(Connection.desktop_hash, 'options', 'roster-showall', '1'); Options.store(); } } catch(e) { Console.error('Interface.showAllBuddies', e); } }; /** * Shows only the online buddies in the roster * @public * @param {string} from * @return {undefined} */ self.showOnlineBuddies = function(from) { try { // Remove the marker Roster.blist_all = false; // We switch the two modes $('.buddy-conf-more-display-available').hide(); $('.buddy-conf-more-display-unavailable').show(); // Security: reset all the groups toggle event $('#roster .group-buddies').show(); $('#roster .group span').text('-'); // We hide the disconnected buddies $('.hidden-buddy').hide(); // We check the groups to hide Roster.updateGroups(); if(Search.search_filtered) { Search.funnelFilterBuddy(); } // Store this in the options if((from == 'roster') && Options.loaded()) { DataStore.setDB(Connection.desktop_hash, 'options', 'roster-showall', '0'); Options.store(); } } catch(e) { Console.error('Interface.showOnlineBuddies', e); } }; /** * Focuses on the right input * @public * @return {undefined} */ self.inputFocus = function() { try { // No popup shown if(!Common.exists('.popup')) { $(document).oneTime(10, function() { $('.focusable:visible:first').focus(); }); } } catch(e) { Console.error('Interface.inputFocus', e); } }; /** * Plugin launcher * @public * @return {undefined} */ self.launch = function() { try { $(document).ready(function() { // Focus on the first visible input $(window).focus(self.inputFocus); }); } catch(e) { Console.error('Interface.launch', e); } }; /** * Return class scope */ return self; })(); Interface.launch();