/* Jappix - An open social platform These are the inbox JS script for Jappix ------------------------------------------------- License: AGPL Author: Valérian Saliou */ // Bundle var Inbox = (function () { /** * Alias of this * @private */ var self = {}; /** * Opens the inbox popup * @public * @return {boolean} */ self.open = function() { try { // Popup HTML content var html = '
' + Common._e("Your inbox") + '
' + '
' + '
' + '
' + Common._e("Available actions") + '
' + '' + '
' + '
' + '

' + Common._e("Your inbox is empty.") + '

' + '
' + '
' + '
' + '' + '
' + '

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

' + '' + '
' + '
' + '

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

' + '' + '
' + '
' + '

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

' + Interface.generateFileShare() + '
' + '' + '
' + '
' + '
' + '
' + '' + Common._e("Close") + '' + '
'; // Create the popup Popup.create('inbox', html); // Associate the events self.instance(); // Load the messages self.load(); } catch(e) { Console.error('Inbox.open', e); } finally { return false; } }; /** * Closes the inbox popup * @public * @return {boolean} */ self.close = function() { try { // Destroy the popup Popup.destroy('inbox'); } catch(e) { Console.error('Inbox.close', e); } finally { return false; } }; /** * Opens the message compose tool * @public * @param {string} xid * @return {boolean} */ self.composeMessage = function(xid) { try { // Open things self.open(); self.newMessage(); // Apply XID $('#inbox .inbox-new-to-input').val(xid); // Focus to the next item $(document).oneTime(10, function() { $('#inbox .inbox-new-subject-input').focus(); }); } catch(e) { Console.error('Inbox.composeMessage', e); } finally { return false; } }; /** * Stores the inbox * @public * @return {undefined} */ self.store = function() { try { var iq = new JSJaCIQ(); iq.setType('set'); var query = iq.setQuery(NS_PRIVATE); var storage = query.appendChild(iq.buildNode('storage', {'xmlns': NS_INBOX})); var db_regex = new RegExp(('^' + Connection.desktop_hash + '_') + 'inbox' + ('_(.+)')); 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 message if(current.match(db_regex)) { // Get the values var value = $(Common.XMLFromString(DataStore.storageDB.getItem(current))); // Create the storage node storage.appendChild(iq.buildNode('message', { 'id': value.find('id').text().revertHtmlEnc(), 'from': value.find('from').text().revertHtmlEnc(), 'subject': value.find('subject').text().revertHtmlEnc(), 'status': value.find('status').text().revertHtmlEnc(), 'date': value.find('date').text().revertHtmlEnc(), 'xmlns': NS_INBOX }, value.find('content').text().revertHtmlEnc() )); } } con.send(iq); } catch(e) { Console.error('Inbox.store', e); } }; /** * Creates a new normal message * @public * @return {boolean} */ self.newMessage = function() { try { // Init var mPath = '#inbox .'; // Reset the previous buddy search Search.resetBuddy('#inbox .inbox-new-to'); // We switch the divs $(mPath + 'inbox-results, #inbox .a-new-message, #inbox .a-delete-messages').hide(); $(mPath + 'inbox-new, #inbox .a-show-messages').show(); // We focus on the first input $(document).oneTime(10, function() { $(mPath + 'inbox-new-to-input').focus(); }); // We reset some stuffs self.cleanNewMessage(); } catch(e) { Console.error('Inbox.newMessage', e); } finally { return false; } }; /** * Cleans the inbox * @public * @return {undefined} */ self.cleanNewMessage = function() { try { // Init var mPath = '#inbox .'; // We reset the forms $(mPath + 'inbox-new-block:not(form) input, ' + mPath + 'inbox-new textarea').val('').removeClass('please-complete'); $(mPath + 'inbox-new-file a').remove(); $(mPath + 'inbox-new-file input').show(); // We close an eventual opened message $(mPath + 'message-content').remove(); $(mPath + 'one-message').removeClass('message-reading'); } catch(e) { Console.error('Inbox.cleanNewMessage', e); } }; /** * Sends a normal message * @public * @param {string} to * @param {string} subject * @param {string} body * @return {undefined} */ self.sendMessage = function(to, subject, body) { try { // We send the message var mess = new JSJaCMessage(); // Main attributes mess.setTo(to); mess.setSubject(subject); mess.setType('normal'); // Any file to attach? var attached = '#inbox .inbox-new-file a.file'; if(Common.exists(attached)) { body += '\n' + '\n' + $(attached).attr('data-attachedtitle') + ' - ' + $(attached).attr('data-attachedhref'); } // Set body mess.setBody(body); con.send(mess, Errors.handleReply); } catch(e) { Console.error('Inbox.sendMessage', e); } }; /** * Performs the normal message sender checks * @public * @return {boolean} */ self.checkMessage = function() { try { // We get some informations var mPath = '#inbox '; var to = $(mPath + '.inbox-new-to-input').val(); var body = $(mPath + '.inbox-new-textarea').val(); var subject = $(mPath + '.inbox-new-subject-input').val(); if(to && body && subject) { // New array of XID var xid = new Array(to); // More than one XID if(to.indexOf(',') != -1) { xid = to.split(','); } for(var i in xid) { var current = xid[i]; // No current value? if(!current || current.match(/^(\s+)$/)) continue; // Edit the XID if needed current = current.replace(/ /g, ''); current = Common.generateXID(current, 'chat'); // We send the message self.sendMessage(current, subject, body); // We clean the inputs self.cleanNewMessage(); Console.info('Inbox message sent: ' + current); } // Close the inbox self.close(); } else { $(mPath + 'input[type="text"], ' + mPath + 'textarea').each(function() { var current = this; if(!$(current).val()) { $(document).oneTime(10, function() { $(current).addClass('please-complete').focus(); }); } else { $(current).removeClass('please-complete'); } }); } } catch(e) { Console.error('Inbox.checkMessage', e); } finally { return false; } }; /** * Shows the inbox messages * @public * @return {boolean} */ self.showMessage = function() { try { // Init var mPath = '#inbox .'; // We switch the divs $(mPath + 'inbox-new').hide(); $(mPath + 'inbox-results').show(); // We show a new link in the menu $(mPath + 'a-show-messages').hide(); $(mPath + 'a-delete-messages').show(); $(mPath + 'a-new-message').show(); // We reset some stuffs self.cleanNewMessage(); } catch(e) { Console.error('Inbox.showMessage', e); } finally { return false; } }; /** * Displays a normal message * @public * @param {string} from * @param {string} subject * @param {string} content * @param {string} status * @param {string} id * @param {string} date * @return {boolean} */ self.displayMessage = function(from, subject, content, status, id, date) { try { // Generate some paths var inbox = '#inbox .'; var one_message = inbox + 'one-message.' + id; // Message yet displayed! if(Common.exists(one_message)) { return false; } // Get the nearest element var stamp = DateUtils.extractStamp(Date.jab2date(date)); var nearest = Search.sortElementByStamp(stamp, '#inbox .one-message'); // Get the buddy name var name = Name.getBuddy(from).htmlEnc(); // We generate the html code var nContent = '
' + '
' + '
' + '' + '
' + '
' + name + '
' + '
' + subject.htmlEnc() + '
' + '
' + Utils.truncate(Utils.noLines(content), 90).htmlEnc() + '
' + '
' + '
'; // Display the message if(nearest === 0) { $(inbox + 'inbox-results .inbox').append(nContent); } else { $('#inbox .one-message[data-stamp="' + nearest + '"]:first').before(nContent); } // Click events $(one_message + ' .message-head').click(function() { if(!Common.exists(one_message + ' .message-content')) self.revealMessage(id, from, subject, content, name, date, status); else self.hideMessage(id); return false; }); // Get the user avatar Avatar.get(from, 'cache', 'true', 'forget'); return true; } catch(e) { Console.error('Inbox.displayMessage', e); } }; /** * Stores an inbox message * @public * @param {string} from * @param {string} subject * @param {string} content * @param {string} status * @param {string} id * @param {string} date * @return {undefined} */ self.storeMessage = function(from, subject, content, status, id, date) { try { // Initialize the XML data var xml = '' + id.htmlEnc().htmlEnc() + '' + date.htmlEnc().htmlEnc() + '' + from.htmlEnc().htmlEnc() + '' + subject.htmlEnc().htmlEnc() + '' + status.htmlEnc().htmlEnc() + '' + content.htmlEnc().htmlEnc() + ''; // End the XML data xml += ''; // Store this message! DataStore.setDB(Connection.desktop_hash, 'inbox', id, xml); } catch(e) { Console.error('Inbox.storeMessage', e); } }; /** * Removes a given normal message * @public * @param {string} id * @return {boolean} */ self.deleteMessage = function() { try { // Remove the message from the inbox $('#inbox .one-message.' + id).remove(); // Remove the message from the database DataStore.removeDB(Connection.desktop_hash, 'inbox', id); // Check the unread messages self.checkMessages(); // Store the new inbox self.store(); } catch(e) { Console.error('Inbox.deleteMessage', e); } finally { return false; } }; /** * Removes all the inbox messages * @public * @return {boolean} */ self.purge = function() { try { // Remove all the messages from the database var db_regex = new RegExp(('^' + Connection.desktop_hash + '_') + 'inbox' + ('_(.+)')); 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 message if(current.match(db_regex)) { DataStore.removeDB(Connection.desktop_hash, 'inbox', RegExp.$1); } } // Prevent the database lag $(document).oneTime(100, function() { // Store the new inbox self.store(); // Remove all the messages from the inbox $('#inbox .one-message').remove(); // Reload the inbox self.load(); }); } catch(e) { Console.error('Inbox.purge', e); } finally { return false; } }; /** * Checks if there are new messages to be notified * @public * @return {boolean} */ self.checkMessages = function() { try { // Selectors var inbox_link = '#top-content a.inbox-hidable'; var no_results = '#inbox .inbox-noresults'; // Marker var has_messages = false; // Read the number of unread messages var unread = 0; // Read the local inbox database var db_regex = new RegExp(('^' + Connection.desktop_hash + '_') + 'inbox' + ('_(.+)')); for(var i = 0; i < DataStore.storageDB.length; i++) { // Database pointer var current = DataStore.storageDB.key(i); // Check inbox messages if(current.match(db_regex)) { // Read the current status var status = $(Common.XMLFromString(DataStore.storageDB.getItem(current))).find('status').text(); // Found an unread message if(status == 'unread') { unread++; } // Update the marker has_messages = true; } } // No message? if(!has_messages) { $(no_results).show(); } else { $(no_results).hide(); } // Reset notifications $(inbox_link + ' .notify').remove(); // Any unread message? if(unread) { // Notify the user $(inbox_link).prepend('
' + unread + '
'); // Update the title Interface.updateTitle(); return true; } // Anyway, update the title Interface.updateTitle(); } catch(e) { Console.error('Inbox.checkMessages', e); } finally { return false; } }; /** * Reveal a normal message content * @public * @param {string} id * @param {string} from * @param {string} subject * @param {string} content * @param {string} name * @param {string} date * @param {string} status * @return {undefined} */ self.revealMessage = function(id, from, subject, content, name, date, status) { try { // Message path var all_message = '#inbox .one-message'; var one_message = all_message + '.' + id; var one_content = one_message + ' .message-content'; // We reset all the other messages $(all_message + ' .message-content').remove(); $(all_message).removeClass('message-reading'); // Message content var html = '
' + '
' + Filter.message(content, name, true) + '
' + '
' + '' + DateUtils.parse(date) + '' + '' + Common._e("Reply") + '' + '' + Common._e("Delete") + '' + '
' + '
' + '
'; // Message content html += '
'; $(one_message).append(html).addClass('message-reading'); // Click events $(one_content + ' a.reply').click(function() { return self.replyMessage(id, from, subject, content); }); $(one_content + ' a.remove').click(function() { return self.deleteMessage(id); }); // Unread message if(status == 'unread') { // Update our database var xml = DataStore.getDB(Connection.desktop_hash, 'inbox', id).replace(/unread<\/status>/i,'read'); DataStore.setDB(Connection.desktop_hash, 'inbox', id, xml); // Remove the unread class $(one_message).removeClass('message-unread'); // Send it to the server! self.store(); } // Check the unread messages self.checkMessages(); } catch(e) { Console.error('Inbox.revealMessage', e); } }; /** * Hides a normal message content * @public * @param {string} id * @return {undefined} */ self.hideMessage = function(id) { try { // Define the paths var inbox = '#inbox .'; var one_message = inbox + 'one-message.' + id; // Reset this message $(one_message).removeClass('message-reading'); $(one_message + ' .message-content').remove(); } catch(e) { Console.error('Inbox.hideMessage', e); } }; /** * Replies to a given normal message * @public * @param {type} name * @return {boolean} */ self.replyMessage = function(id, from, subject, body) { try { // We switch to the writing div self.newMessage(); // Inbox path var inbox = '#inbox .'; // Generate the body body = '\n' + '____________' + '\n\n' + Utils.truncate(body, 120); // We apply the generated values to the form $(inbox + 'inbox-new-to-input').val(from); $(inbox + 'inbox-new-subject-input').val(subject); $(document).oneTime(10, function() { $(inbox + 'inbox-new-textarea').val(body).focus().selectRange(1, 0); }); } catch(e) { Console.error('Inbox.replyMessage', e); } finally { return false; } }; /** * Loads the inbox messages * @public * @return {undefined} */ self.load = function() { try { // Read the local database var db_regex = new RegExp(('^' + Connection.desktop_hash + '_') + 'inbox' + ('_(.+)')); 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 message if(current.match(db_regex)) { // Get the current value var value = $(Common.XMLFromString(DataStore.storageDB.getItem(current))); // Display the current message self.displayMessage( value.find('from').text().revertHtmlEnc(), value.find('subject').text().revertHtmlEnc(), value.find('content').text().revertHtmlEnc(), value.find('status').text().revertHtmlEnc(), value.find('id').text().revertHtmlEnc(), value.find('date').text().revertHtmlEnc() ); } } // Check new messages self.checkMessages(); } catch(e) { Console.error('Inbox.load', e); } }; /** * Wait event for file attaching * @public * @return {undefined} */ self.waitAttach = function() { try { $('#inbox .wait').show(); } catch(e) { Console.error('Inbox.waitAttach', e); } }; /** * Success event for file attaching * @public * @param {string} responseXML * @return {undefined} */ self.handleAttach = function(responseXML) { try { // Data selector var dData = $(responseXML).find('jappix'); // Process the returned data if(dData.find('error').size()) { Board.openThisError(4); Console.error('Error while attaching the file', dData.find('error').text()); } else { // Get the file values var fName = dData.find('title').text(); var fType = dData.find('type').text(); var fURL = dData.find('href').text(); // Hide the attach link, show the unattach one $('#inbox .inbox-new-file input').hide(); $('#inbox .inbox-new-file').append('' + fName.htmlEnc() + '' + Common._e("Remove") + ''); // Set values to the file link $('#inbox .inbox-new-file a.file').attr('data-attachedtitle', fName) .attr('data-attachedhref', fURL); // Click events $('#inbox .inbox-new-file a.remove').click(function() { $('#inbox .inbox-new-file a').remove(); $('#inbox .inbox-new-file input').show(); return false; }); Console.info('File attached.'); } // Reset the attach bubble $('#inbox .inbox-new-file input[type="file"]').val(''); $('#inbox .wait').hide(); } catch(e) { Console.error('Inbox.handleAttach', e); } }; /** * Plugin launcher * @public * @return {undefined} */ self.instance = function() { try { // Define the pats var inbox = '#inbox .'; // Define the buddy search vars var destination = inbox + 'inbox-new-to'; var dHovered = destination + ' ul li.hovered:first'; // Send the message when enter pressend $(inbox + 'inbox-new input').keyup(function(e) { if(e.keyCode == 13) { if(Common.exists(dHovered)) Search.addBuddy(destination, $(dHovered).attr('data-xid')); else self.checkMessage(); } }); // Buddy search $(inbox + 'inbox-new-to-input').keyup(function(e) { if(e.keyCode != 13) { // 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 .blur(function() { if(!$(destination + ' ul').attr('mouse-hover')) { Search.resetBuddy(destination); } }) // Buddy search got focus .focus(function() { var value = $(this).val(); // Add a comma at the end if(value && !value.match(/^(.+)((,)(\s)?)$/)) { $(this).val(value + ', '); } }); // Click events $(inbox + 'a-delete-messages').click(self.purge); $(inbox + 'a-new-message').click(self.newMessage); $(inbox + 'a-show-messages').click(self.showMessage); $(inbox + 'inbox-new-send a').click(self.checkMessage); $(inbox + 'bottom .finish').click(function() { return self.close(); }); // File upload var attach_options = { dataType: 'xml', beforeSubmit: self.waitAttach, success: self.handleAttach }; // Upload form submit event $('#inbox .inbox-new-file').submit(function() { if($('#inbox .wait').is(':hidden') && $('#inbox .inbox-new-file input[type="file"]').val()) { $(this).ajaxSubmit(attach_options); } return false; }); // Upload input change event $('#inbox .inbox-new-file input[type="file"]').change(function() { if($('#inbox .wait').is(':hidden') && $(this).val()) { $('#inbox .inbox-new-file').ajaxSubmit(attach_options); } return false; }); } catch(e) { Console.error('Inbox.instance', e); } }; /** * Return class scope */ return self; })();