diff --git a/source/CHANGELOG.md b/source/CHANGELOG.md index bd0d64f..bbe9a13 100644 --- a/source/CHANGELOG.md +++ b/source/CHANGELOG.md @@ -4,8 +4,22 @@ Jappix Changelog Here's the log of what has changed over the Jappix releases. -Primo, v1.1.0 (Jun 2014) ------------------------- +Primo, v1.1.2 (October 2014) +---------------------------- + + * XEP-0353: Jingle Message Initiation @valeriansaliou + * Fixes Jingle calls in Chrome 38+ @valeriansaliou + + +Primo, v1.1.1 (September 2014) +------------------------------ + + * Ignore empty XHTML-IM messages @eijebong, @valeriansaliou + * Fix a bug with message markers @valeriansaliou + + +Primo, v1.1.0 (June 2014) +------------------------- * XEP-0272: Multiparty Jingle (Muji) @valeriansaliou * Prevent client crash on huge messages @valeriansaliou diff --git a/source/PROTOCOL.md b/source/PROTOCOL.md index 7ac144f..846dfb1 100644 --- a/source/PROTOCOL.md +++ b/source/PROTOCOL.md @@ -67,14 +67,15 @@ Here are listed the XMPP Protocol Extensions that Jappix supports, as well as th * XEP-0334: Message Processing Hints *v0.1* * XEP-0338: Jingle Grouping Framework *v0.1* * XEP-0339: Source-Specific Media Attributes in Jingle *v0.1* + * XEP-0353: Jingle Message Initiation *v0.1* # XMPP Extensions (Updated) * XEP-0272: Multiparty Jingle (Muji) *v0.2* - * Alternate URL: https://demo.frenchtouch.pro/valerian.saliou/xmpp/extensions/xep-0272.html + * Alternate URL: https://demo.hakuma.holdings/valerian.saliou/xmpp/extensions/xep-0272.html * XEP-0313: Message Archive Management *v0.3* - * Alternate URL: https://demo.frenchtouch.pro/valerian.saliou/xmpp/extensions/xep-0313.html + * Alternate URL: https://demo.hakuma.holdings/valerian.saliou/xmpp/extensions/xep-0313.html # XMPP Extensions (Proposed) diff --git a/source/README.md b/source/README.md index bd8e047..8413ee0 100644 --- a/source/README.md +++ b/source/README.md @@ -6,7 +6,7 @@ Jappix is a fresh new open social platform which enables you to create your own You can build your own Jappix installation for your own requirements: if you want to use it as a personal social client, you can download it and put it on your webserver. It's easy, fast and free. -[![build status](https://ci.frenchtouch.pro/projects/7/status.png?ref=master)](https://ci.frenchtouch.pro/projects/7?ref=master) +[![build status](https://ci.hakuma.holdings/projects/7/status.png?ref=master)](https://ci.hakuma.holdings/projects/7?ref=master) License @@ -45,7 +45,7 @@ Mirrors In case a master service is down (GitHub for Git access or Jappix.org for project download), here is a list of available mirrors: * Project website mirror: https://project.jappix.com/ -* Development repository mirror: https://code.frenchtouch.pro/jappix/jappix +* Development repository mirror: https://code.hakuma.holdings/jappix/jappix MUC Links diff --git a/source/VERSION b/source/VERSION index b01a2fc..3793834 100644 --- a/source/VERSION +++ b/source/VERSION @@ -1 +1 @@ -Primo [1.1.0] \ No newline at end of file +Primo [1.1.2] diff --git a/source/app/javascripts/adhoc.js b/source/app/javascripts/adhoc.js index b1cc518..e4e898b 100644 --- a/source/app/javascripts/adhoc.js +++ b/source/app/javascripts/adhoc.js @@ -29,24 +29,24 @@ var AdHoc = (function () { try { // Popup HTML content - var html = - '
' + Common._e("Commands") + '
' + - - '
' + - '
' + - - '
' + - '
' + - - '
' + - '
' + - - '' + Common._e("Close") + '' + + var html = + '
' + Common._e("Commands") + '
' + + + '
' + + '
' + + + '
' + + '
' + + + '
' + + '
' + + + '' + Common._e("Close") + '' + '
'; - + // Create the popup Popup.create('adhoc', html); - + // Associate the events self.launch(); } catch(e) { @@ -88,16 +88,16 @@ var AdHoc = (function () { try { // Open the popup self.open(); - + // Add a XID marker $('#adhoc .adhoc-head').html('' + Name.getBuddy(xid).htmlEnc() + ' (' + xid.htmlEnc() + ')'); - + // Get the highest entity resource var highest = Presence.highestPriority(xid); - + if(highest) xid = highest; - + // Start a new adhoc command DataForm.go(xid, 'command', '', '', 'adhoc'); } catch(e) { @@ -120,10 +120,10 @@ var AdHoc = (function () { try { // Open the popup self.open(); - + // Add a XID marker $('#adhoc .adhoc-head').html('' + server.htmlEnc() + ''); - + // Start a new adhoc command DataForm.go(server, 'command', '', '', 'adhoc'); } catch(e) { diff --git a/source/app/javascripts/anonymous.js b/source/app/javascripts/anonymous.js index d472b80..f38f819 100644 --- a/source/app/javascripts/anonymous.js +++ b/source/app/javascripts/anonymous.js @@ -51,40 +51,40 @@ var Anonymous = (function () { try { Console.info('Jappix (anonymous) is now connected.'); - + // Connected marker Connection.connected = true; Connection.current_session = true; Connection.reconnect_try = 0; Connection.reconnect_timer = 0; - + // Not resumed? if(!Connection.resume) { // Create the app Talk.create(); - + // Send our first presence Presence.sendFirst(''); - + // Set last activity stamp DateUtils.last_activity = DateUtils.getTimeStamp(); - + // Create the new groupchat Chat.checkCreate(Common.generateXID(ANONYMOUS_ROOM, 'groupchat'), 'groupchat'); - + // Remove some nasty elements for the anonymous mode $('.tools-mucadmin, .tools-add').remove(); } - + // Resumed else { // Send again our presence Presence.sendActions(); - + // Change the title Interface.updateTitle(); } - + // Remove the waiting icon Interface.removeGeneralWait(); } catch(e) { @@ -129,16 +129,16 @@ var Anonymous = (function () { // Check BOSH origin BOSH_SAME_ORIGIN = Origin.isSame(httpbase); - + // We create the new http-binding connection con = new JSJaCHttpBindingConnection({ httpbase: httpbase }); } - + // And we handle everything that happen self._registerHandlers(con); - + // We set the anonymous connection parameters oArgs = {}; oArgs.domain = server; @@ -146,10 +146,10 @@ var Anonymous = (function () { oArgs.resource = JAPPIX_RESOURCE + ' Anonymous (' + (new Date()).getTime() + ')'; oArgs.secure = true; oArgs.xmllang = XML_LANG; - + // We connect ! con.connect(oArgs); - + // Change the page title Interface.title('wait'); } catch(e) { @@ -157,7 +157,7 @@ var Anonymous = (function () { // Reset Jappix self.disconnected(); - + // Open an unknown error Board.openThisError(2); } finally { @@ -177,19 +177,19 @@ var Anonymous = (function () { try { $(document).ready(function() { Console.info('Anonymous mode detected, connecting...'); - + // We add the login wait div Interface.showGeneralWait(); - + // Get the vars if(XMPPLinks.links_var.r) { ANONYMOUS_ROOM = XMPPLinks.links_var.r; } - + if(XMPPLinks.links_var.n) { ANONYMOUS_NICK = XMPPLinks.links_var.n; } - + // Fire the login action self.login(HOST_ANONYMOUS); }); diff --git a/source/app/javascripts/audio.js b/source/app/javascripts/audio.js index fa7abc4..62652ea 100644 --- a/source/app/javascripts/audio.js +++ b/source/app/javascripts/audio.js @@ -57,36 +57,36 @@ var Audio = (function () { // If the audio elements aren't yet in the DOM if(!Common.exists('#audio')) { $('body').append( - '
' + - '' + - - '' + - - '' + + '
' + + '' + - '' + - - '' + - - '' + + '' + + + '' + + + '' + + + '' + + + '' + '
' ); } @@ -112,11 +112,11 @@ var Audio = (function () { if(!self._isSupported()) { return false; } - + // If the sounds are enabled if(DataStore.getDB(Connection.desktop_hash, 'options', 'sounds') === '1') { self._appendDOM(); - + // We play the target sound var audio_raw_sel = $('#audio audio').filter('#' + name); var audio_sel = audio_raw_sel[0]; @@ -133,7 +133,7 @@ var Audio = (function () { var duration = parseInt((audio_raw_sel.attr('data-duration') || 0), 10); self._timeout_stop = false; - + audio_raw_sel.oneTime((duration + 's'), function() { if(!self._timeout_stop) { self.play(name, repeat); @@ -170,7 +170,7 @@ var Audio = (function () { if(!self._isSupported()) { return false; } - + self._timeout_stop = true; // Check the audio container exists before doing anything... @@ -180,7 +180,7 @@ var Audio = (function () { if(audio_parent_sel.size()) { audio_raw_sel.stopTime(); - + if(audio_sel) { if(!audio_sel.paused) { audio_sel.pause(); diff --git a/source/app/javascripts/autocompletion.js b/source/app/javascripts/autocompletion.js index 0fa63fc..78f48b5 100644 --- a/source/app/javascripts/autocompletion.js +++ b/source/app/javascripts/autocompletion.js @@ -34,7 +34,7 @@ var Autocompletion = (function () { // Put the two strings into lower case var sort_a = a[0].toLowerCase(); var sort_b = b[0].toLowerCase(); - + // Process the sort if(sort_a > sort_b) { return 1; @@ -192,7 +192,7 @@ var Autocompletion = (function () { } var query = message_area_sel.attr('data-autocompletion-query'); - + if(query === undefined) { // The autocompletion has not been yet launched query = self.getSubQueries(value); @@ -201,11 +201,11 @@ var Autocompletion = (function () { // The autocompletion has already stored a query query = JSON.parse(query); } - + // Get the pointer var pointer = message_area_sel.attr('data-autocompletion-pointer'); var i = pointer ? parseInt(pointer, 10) : 0; - + // We get the nickname var nick_result = self.process(query[0], hash)[i]; var nick; @@ -213,12 +213,12 @@ var Autocompletion = (function () { if(nick_result !== undefined) { nick = nick_result[0]; } - + // Shit, this is my nick! if((nick !== undefined) && (nick.toLowerCase() == Name.getMUCNick(hash).toLowerCase())) { // Increment i++; - + // Get the next nick nick_result = self.process(query[0], hash)[i]; @@ -226,7 +226,7 @@ var Autocompletion = (function () { nick = nick_result[0]; } } - + // We quote the nick if((nick_result !== undefined) && (nick !== undefined)) { // Increment @@ -237,7 +237,7 @@ var Autocompletion = (function () { nick, query[1][nick_result[1]] ); - + // Put a pointer message_area_sel.attr('data-autocompletion-pointer', i); } diff --git a/source/app/javascripts/avatar.js b/source/app/javascripts/avatar.js index 4bbd6c1..4aae5a5 100644 --- a/source/app/javascripts/avatar.js +++ b/source/app/javascripts/avatar.js @@ -42,29 +42,29 @@ var Avatar = (function () { if(Utils.existArrayValue(self.pending, xid)) { return false; } - + // Initialize: XML data is in one SQL entry, because some browser are sloooow with SQL requests var xml = Common.XMLFromString( DataStore.getPersistent('global', 'avatar', xid) ); var forced = false; - + // Retrieving forced? if($(xml).find('forced').text() == 'true') { forced = true; } - + // No avatar in presence if(!photo && !forced && enabled == 'true') { // Pending marker self.pending.push(xid); - + // Reset the avatar self.reset(xid, hex_md5(xid)); - + Console.warn('No avatar for: ' + xid); } - + // Try to catch the avatar else { // Define some stuffs @@ -82,31 +82,31 @@ var Avatar = (function () { if(mode == 'cache' && type && binval && checksum && updated) { // Pending marker self.pending.push(xid); - + // Display the cache avatar self.display(xid, hex_md5(xid), type, binval); - + Console.info('Read avatar from cache: ' + xid); } - + // Else if the request has not yet been fired, we get it else if((!updated || mode == 'force' || photo == 'forget') && enabled != 'false') { // Pending marker self.pending.push(xid); - + // Get the latest avatar var iq = new JSJaCIQ(); iq.setType('get'); iq.setTo(xid); - + iq.appendNode('vCard', {'xmlns': NS_VCARD}); - + con.send(iq, self.handle); - + Console.info('Get avatar from server: ' + xid); } } - + return true; } catch(e) { Console.error('Avatar.get', e); @@ -127,28 +127,28 @@ var Avatar = (function () { // Extract the XML values var handleXML = iq.getNode(); var handleFrom = Common.fullXID(Common.getStanzaFrom(iq)); - + // Is this me? Remove the resource! if(Common.bareXID(handleFrom) == Common.getXID()) { handleFrom = Common.bareXID(handleFrom); } - + // Get some other values var hash = hex_md5(handleFrom); var find = $(handleXML).find('vCard'); var aChecksum = 'none'; var oChecksum = null; - + // Read our own checksum if(handleFrom == Common.getXID()) { oChecksum = DataStore.getDB(Connection.desktop_hash, 'checksum', 1); - + // Avoid the "null" value if(!oChecksum) { oChecksum = ''; } } - + // vCard not empty? if(find.size()) { // We get our profile details @@ -156,23 +156,23 @@ var Avatar = (function () { // Get the names var names = Name.generateBuddy(iq); var phone_number = find.find('TEL:has(NUMBER):first NUMBER:first').text(); - + // Write the values to the database DataStore.setDB(Connection.desktop_hash, 'profile', 'name', names[0]); DataStore.setDB(Connection.desktop_hash, 'profile', 'nick', names[1]); DataStore.setDB(Connection.desktop_hash, 'profile', 'phone', phone_number); } - + // We get the avatar var aType = find.find('TYPE:first').text(); var aBinval = find.find('BINVAL:first').text(); - + // No binval? if(!aBinval) { aType = 'none'; aBinval = 'none'; } - + // Enough data else { // No type? @@ -182,33 +182,33 @@ var Avatar = (function () { aChecksum = hex_sha1(Base64.decode(aBinval)); } } - + // We display the user avatar self.display(handleFrom, hash, aType, aBinval); - + // Store the avatar DataStore.setPersistent('global', 'avatar', handleFrom, '' + aType + '' + aBinval + '' + aChecksum + 'false'); - + Console.info('Avatar retrieved from server: ' + handleFrom); } - + // vCard is empty else { self.reset(handleFrom); } - + // We got a new checksum for us? if(((oChecksum !== null) && (oChecksum != aChecksum)) || !Presence.first_sent) { // Define a proper checksum var pChecksum = aChecksum; - + if(pChecksum == 'none') { pChecksum = ''; } - + // Update our temp. checksum DataStore.setDB(Connection.desktop_hash, 'checksum', 1, pChecksum); - + // Send the stanza if(!Presence.first_sent) { Storage.get(NS_OPTIONS); @@ -235,7 +235,7 @@ var Avatar = (function () { try { // Store the empty avatar DataStore.setPersistent('global', 'avatar', xid, 'nonenonenonefalse'); - + // Display the empty avatar self.display(xid, hash, 'none', 'none'); } catch(e) { @@ -260,19 +260,19 @@ var Avatar = (function () { // Initialize the vars var container = hash + ' .avatar-container'; var code = ''; - + // Replace with the new avatar (in the roster and in the chat) $('.' + container).html(code); - + // We can remove the pending marker Utils.removeArrayValue(self.pending, xid); } catch(e) { diff --git a/source/app/javascripts/base64.js b/source/app/javascripts/base64.js index 6e5366e..1ef3528 100644 --- a/source/app/javascripts/base64.js +++ b/source/app/javascripts/base64.js @@ -17,12 +17,12 @@ var Base64 = (function () { var chr1, chr2, chr3; var enc1, enc2, enc3, enc4; var i = 0; - + do { chr1 = input.charCodeAt(i++); chr2 = input.charCodeAt(i++); chr3 = input.charCodeAt(i++); - + enc1 = chr1 >> 2; enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); @@ -33,14 +33,14 @@ var Base64 = (function () { } else if (isNaN(chr3)) { enc4 = 64; } - + output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) + keyStr.charAt(enc3) + keyStr.charAt(enc4); } while (i < input.length); - + return output; }, - + /** * Decodes a base64 string. * @param {String} input The string to decode. @@ -50,22 +50,22 @@ var Base64 = (function () { var chr1, chr2, chr3; var enc1, enc2, enc3, enc4; var i = 0; - + // remove all characters that are not A-Z, a-z, 0-9, +, /, or = input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); - + do { enc1 = keyStr.indexOf(input.charAt(i++)); enc2 = keyStr.indexOf(input.charAt(i++)); enc3 = keyStr.indexOf(input.charAt(i++)); enc4 = keyStr.indexOf(input.charAt(i++)); - + chr1 = (enc1 << 2) | (enc2 >> 4); chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); chr3 = ((enc3 & 3) << 6) | enc4; - + output = output + String.fromCharCode(chr1); - + if (enc3 != 64) { output = output + String.fromCharCode(chr2); } @@ -73,7 +73,7 @@ var Base64 = (function () { output = output + String.fromCharCode(chr3); } } while (i < input.length); - + return output; } }; diff --git a/source/app/javascripts/board.js b/source/app/javascripts/board.js index 25b02d4..fd73bd4 100644 --- a/source/app/javascripts/board.js +++ b/source/app/javascripts/board.js @@ -39,37 +39,37 @@ var Board = (function () { // Password change case 1: text = Common._e("Your password has been changed, now you can connect to your account with your new login data."); - + break; - + // Account deletion case 2: text = Common._e("Your XMPP account has been removed, bye!"); - + break; - + // Account logout case 3: text = Common._e("You have been logged out of your XMPP account, have a nice day!"); - + break; - + // Groupchat join case 4: text = Common._e("The room you tried to join doesn't seem to exist."); - + break; - + // Groupchat removal case 5: text = Common._e("The groupchat has been removed."); - + break; - + // Non-existant groupchat user case 6: text = Common._e("The user that you want to reach is not present in the room."); - + break; } } catch(e) { @@ -96,25 +96,25 @@ var Board = (function () { // Custom error case 1: text = '' + Common._e("Error") + ' » '; - + break; - + // Network error case 2: text = Common._e("Jappix has been interrupted by a network issue, a bug or bad login (check that you entered the right credentials), sorry for the inconvenience."); - + break; - + // List retrieving error case 3: text = Common._e("The element list on this server could not be obtained!"); - + break; - + // Attaching error case 4: text = Common.printf(Common._e("An error occured while uploading your file: maybe it is too big (%s maximum) or forbidden!"), JAPPIX_MAX_UPLOAD); - + break; } } catch(e) { @@ -138,11 +138,11 @@ var Board = (function () { board_sel.click(function() { self.closeThis(this); }); - + board_sel.oneTime('5s', function() { self.closeThis(this); }); - + board_sel.slideDown(); } catch(e) { Console.error('Board._attachEvents', e); @@ -163,29 +163,29 @@ var Board = (function () { try { // Text var var text = ''; - + // Info if(type == 'info') { text = self._generateBoardInfo(id); } else { text = self._generateBoardError(id); } - + // No text? if(!text) { return false; } - + // Append the content $('#board').append( '
' + text + '
' ); - + // Events (click and auto-hide) self._attachEvents( $('#board .one-board.' + type + '[data-id="' + id + '"]') ); - + return true; } catch(e) { Console.error('Board.create', e); @@ -221,7 +221,7 @@ var Board = (function () { try { // In a first, we destroy other boards self.destroy(); - + // Then we display the board self.create(type, id); } catch(e) { @@ -301,11 +301,11 @@ var Board = (function () { if(Common.isFocused() || !content || !self.NOTIFICATION) { return; } - + // Default icon? if(!icon) { icon = './images/others/default-avatar.png'; - + // Avatar icon? if(xid) { var avatar_xml = Common.XMLFromString( @@ -314,13 +314,13 @@ var Board = (function () { var avatar_type = $(avatar_xml).find('type').text() || 'image/png'; var avatar_binval = $(avatar_xml).find('binval').text(); - + if(avatar_binval && avatar_type) { icon = 'data:' + avatar_type + ';base64,' + avatar_binval; } } } - + // Default title? if(!title) { title = Common._e("New event!"); @@ -342,18 +342,18 @@ var Board = (function () { case 'chat': Interface.switchChan(hex_md5(xid)); break; - + case 'groupchat': Interface.switchChan(hex_md5(Common.bareXID(xid))); break; - + default: break; } - + // Focus on msg-me window.focus(); - + // Remove notification this.close(); }; diff --git a/source/app/javascripts/browser-detect.js b/source/app/javascripts/browser-detect.js index 9f83444..cef3c4a 100644 --- a/source/app/javascripts/browser-detect.js +++ b/source/app/javascripts/browser-detect.js @@ -6,12 +6,12 @@ var BrowserDetect = { init: function () { this.browser = this.searchString(this.dataBrowser) || "An unknown browser"; - this.version = this.searchVersion(navigator.userAgent) - || this.searchVersion(navigator.appVersion) - || "an unknown version"; + this.version = this.searchVersion(navigator.userAgent) || + this.searchVersion(navigator.appVersion) || + "an unknown version"; this.OS = this.searchString(this.dataOS) || "an unknown OS"; }, - + searchString: function (data) { for (var i=0;i' + - '
' + - '
' + - '' + - '
' + + '
' + + '
' + + '
' + + '' + + '
' + - '' + - '
' + + '' + + '
' + - '
' + - '' + fullname + '' + - '' + map[type].text + '' + + '
' + + '' + fullname + '' + + '' + map[type].text + '' + - '
' + buttons_html + '
' + - '
' + + '
' + buttons_html + '
' + + '
' + '
' ); @@ -532,11 +655,11 @@ var Call = (function() { call_tools_all_sel.find('a.reply-button[data-action="' + button + '"]').click(function() { try { // Remove notification - self._unnotify(xid); + self._unnotify(); // Execute callback, if any if(typeof attrs.cb === 'function') { - attrs.cb(xid, mode); + attrs.cb(xid, mode, options_arr); } Console.info('Closed call notification drawer'); @@ -750,7 +873,7 @@ var Call = (function() { self.stop_counter(); self._start_stamp = DateUtils.getTimeStamp(); self._fire_clock(); - + // Fire it every second $('#top-content .tools.call .counter').everyTime('1s', self._fire_clock); @@ -778,7 +901,7 @@ var Call = (function() { // Reset counter var counter_sel = $('#top-content .tools.call .counter'); var default_count = counter_sel.attr('data-default'); - + counter_sel.stopTime(); $('#top-content .tools.call .counter').text(default_count); @@ -807,13 +930,13 @@ var Call = (function() { DateUtils.getTimeStamp(), self._start_stamp ); - + if(count.getHours()) { count = count.toString('H:mm:ss'); } else { count = count.toString('mm:ss'); } - + // Display updated counter $('#top-content .tools.call .counter').text(count); $('#jingle, #muji').find('.elapsed').text(count); @@ -969,4 +1092,4 @@ var Call = (function() { */ return self; -})(); \ No newline at end of file +})(); diff --git a/source/app/javascripts/caps.js b/source/app/javascripts/caps.js index e267ed2..0538f43 100644 --- a/source/app/javascripts/caps.js +++ b/source/app/javascripts/caps.js @@ -106,7 +106,7 @@ var Caps = (function () { cur_type = $(this).attr('type') || ''; cur_lang = $(this).attr('xml:lang') || ''; cur_name = $(this).attr('name') || ''; - + identities.push(cur_category + '/' + cur_type + '/' + cur_lang + '/' + cur_name); }); } catch(e) { @@ -133,7 +133,7 @@ var Caps = (function () { $(query).find('feature').each(function() { cur_var = $(this).attr('var'); - + // Add the current value to the array if(cur_var) { features.push(cur_var); @@ -166,57 +166,57 @@ var Caps = (function () { // Initialize some stuffs cur_string = ''; cur_sort_var = []; - + // Add the form type field $(this).find('field[var="FORM_TYPE"] value').each(function() { cur_text = $(this).text(); - + if(cur_text) { cur_string += cur_text + '<'; } }); - + // Add the var attributes into an array $(this).find('field:not([var="FORM_TYPE"])').each(function() { cur_var = $(this).attr('var'); - + if(cur_var) { cur_sort_var.push(cur_var); } }); - + // Sort the var attributes cur_sort_var = cur_sort_var.sort(); - + // Loop this sorted var attributes $.each(cur_sort_var, function(i) { // Initialize the value sorting cur_sort_val = []; - + // Append it to the string cur_string += cur_sort_var[i] + '<'; - + // Add each value to the array $(this).find('field[var=' + cur_sort_var[i] + '] value').each(function() { cur_sort_val.push($(this).text()); }); - + // Sort the values cur_sort_val = cur_sort_val.sort(); - + // Append the values to the string for(var j in cur_sort_val) { cur_string += cur_sort_val[j] + '<'; } }); - + // Any string? if(cur_string) { // Remove the undesired double '<' from the string if(cur_string.match(/(.+)(<)+$/)) { cur_string = cur_string.substring(0, cur_string.length - 1); } - + // Add the current string to the array data_forms.push(cur_string); } @@ -249,7 +249,7 @@ var Caps = (function () { // Remove the tooltip elements style_sel.hide(); style_sel.find('.bubble-style').remove(); - + // Reset the markers message_area_sel.removeAttr('style') .removeAttr('data-font') @@ -341,7 +341,7 @@ var Caps = (function () { if(iq_oob_xid || NS_XOOB in features) { file_sel.show(); - + // Set a marker file_sel.attr( 'data-oob', @@ -351,7 +351,7 @@ var Caps = (function () { // Remove the tooltip elements file_sel.hide(); file_sel.find('.bubble-style').remove(); - + // Reset the marker file_sel.removeAttr('data-oob'); } @@ -489,7 +489,7 @@ var Caps = (function () { var disco_jingle = JSJaCJingle.disco(); var disco_all = disco_base.concat(disco_jingle); - + return Utils.uniqueArrayValues(disco_all); } catch(e) { Console.error('Caps.myDiscoInfos', e); @@ -511,35 +511,35 @@ var Caps = (function () { // No CAPS if(!caps) { Console.warn('No CAPS: ' + to); - + self.displayDiscoInfos(to, ''); - + return false; } - + // Get the stored disco infos var xml = self.read(caps); - + // Yet stored if(xml) { Console.info('CAPS from cache: ' + to); - + self.displayDiscoInfos(to, xml); - + return true; } - + Console.info('CAPS from the network: ' + to); - + // Not stored: get the disco#infos var iq = new JSJaCIQ(); - + iq.setTo(to); iq.setType('get'); iq.setQuery(NS_DISCO_INFO); - + con.send(iq, self.handleDiscoInfos); - + return true; } catch(e) { Console.error('Caps.getDiscoInfos', e); @@ -560,34 +560,34 @@ var Caps = (function () { if(!iq || (iq.getType() == 'error')) { return; } - + var from = Common.fullXID(Common.getStanzaFrom(iq)); var query = iq.getQuery(); - + // Parse values var identities = self._parseDiscoIdentities(query); var features = self._parseDiscoFeatures(query); var data_forms = self._parseDiscoDataForms(query); - + // Process the CAPS var caps = self.process(identities, features, data_forms); - + // Get the XML string var xml = Common.xmlToString(query); - + // Store the disco infos DataStore.setPersistent('global', 'caps', caps, xml); - + // This is our server if(from == Utils.getServer()) { // Handle the features Features.handle(xml); - + Console.info('Got our server CAPS'); } else { // Display the disco infos self.displayDiscoInfos(from, xml); - + Console.info('Got CAPS: ' + from); } } catch(e) { @@ -609,12 +609,12 @@ var Caps = (function () { try { // Generate the chat path var xid = Common.bareXID(from); - + // This comes from a private groupchat chat? if(Utils.isPrivate(xid)) { xid = from; } - + hash = hex_md5(xid); // Display the supported features @@ -627,14 +627,14 @@ var Caps = (function () { features[current] = 1; } }); - + // Paths var path_sel = $('#' + hash); var roster_sel = $('#roster .buddy.' + hash); var message_area_sel = path_sel.find('.message-area'); var style_sel = path_sel.find('.chat-tools-style'); var file_sel = path_sel.find('.chat-tools-file'); - + // Apply Features self._applyDiscoXHTMLIM(xid, features, style_sel, message_area_sel); self._applyDiscoJingle(xid, path_sel, roster_sel); @@ -663,30 +663,30 @@ var Caps = (function () { try { // Initialize var caps_str = ''; - + // Sort the arrays identities = identities.sort(); features = features.sort(); dataforms = dataforms.sort(); - + // Process the sorted identity string for(var a in identities) { caps_str += identities[a] + '<'; } - + // Process the sorted feature string for(var b in features) { caps_str += features[b] + '<'; } - + // Process the sorted data-form string for(var c in dataforms) { caps_str += dataforms[c] + '<'; } - + // Process the SHA-1 hash var cHash = b64_sha1(caps_str); - + return cHash; } catch(e) { Console.error('Caps.process', e); @@ -705,8 +705,8 @@ var Caps = (function () { try { return self.process( [ - self.disco_infos.identity.category + '/' + - self.disco_infos.identity.type + '//' + + self.disco_infos.identity.category + '/' + + self.disco_infos.identity.type + '//' + self.disco_infos.identity.name ], diff --git a/source/app/javascripts/carbons.js b/source/app/javascripts/carbons.js index 96e64f4..4635b94 100644 --- a/source/app/javascripts/carbons.js +++ b/source/app/javascripts/carbons.js @@ -35,9 +35,9 @@ var Carbons = (function () { var iq = new JSJaCIQ(); iq.setType('set'); - + iq.appendNode(type, {'xmlns': NS_URN_CARBONS}); - + con.send(iq, function(iq) { self._handleConfigure(iq, type); }); diff --git a/source/app/javascripts/chat.js b/source/app/javascripts/chat.js index 31882a1..a9f0bd6 100644 --- a/source/app/javascripts/chat.js +++ b/source/app/javascripts/chat.js @@ -45,7 +45,7 @@ var Chat = (function () { $(path + 'tools-jingle-video').click(function() { Jingle.start(xid, 'video'); }); - + // Click event: user-infos $(path + 'tools-infos').click(function() { UserInfos.open(xid); @@ -91,11 +91,11 @@ var Chat = (function () { 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) { @@ -144,7 +144,7 @@ var Chat = (function () { // 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) @@ -234,9 +234,10 @@ var Chat = (function () { * @private * @param {string} type * @param {string} id + * @param {string} xid * @return {object} */ - self._generateChatCode = function(type, id) { + self._generateChatCode = function(type, id, xid) { var code_args = {}; @@ -246,14 +247,14 @@ var Chat = (function () { 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") + '

' + + 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 = ''; @@ -266,31 +267,31 @@ var Chat = (function () { code_args.avatar = '
'; code_args.name = '

'; code_args.code = '
' + code_args.mam + '
'; - code_args.link = '' + - '' + + 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 = '
' + - '' + + code_args.style_picker = '
' + + '' + '
'; - + if((BrowserDetect.browser == 'Explorer') && (BrowserDetect.version < 9)) { code_args.style_picker = ''; } @@ -320,11 +321,11 @@ var Chat = (function () { 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; @@ -333,18 +334,18 @@ var Chat = (function () { 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 @@ -358,7 +359,7 @@ var Chat = (function () { 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; @@ -367,11 +368,11 @@ var Chat = (function () { if(!title && fName) name = fName; } - + Groupchat.create(hash, xid, name, nickname, password); } } - + // Switch to the newly-created chat Interface.switchChan(hash); } catch(e) { @@ -398,52 +399,52 @@ var Chat = (function () { // Generate some stuffs var path = '#' + id + ' .'; var escaped_xid = escape(xid); - + // Special code - var chat_args = self._generateChatCode(type, id); + var chat_args = self._generateChatCode(type, id, xid); // Append the chat HTML code $('#page-engine').append( - '
' + - '
' + - chat_args.avatar + - - '
' + - '

' + nick.htmlEnc() + '

' + - chat_args.name + - '
' + - '
' + - - chat_args.code + - - '
' + - '' + - - '
' + - '' + - '
' + - '
' + + '
' + + '
' + + chat_args.avatar + + + '
' + + '

' + nick.htmlEnc() + '

' + + chat_args.name + + '
' + + '
' + + + chat_args.code + + + '
' + + '' + + + '
' + + '' + + '
' + + '
' + '
' ); - + self._generateEvents(path, id, xid); } catch(e) { Console.error('Chat.generate', e); @@ -466,38 +467,38 @@ var Chat = (function () { 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 = '
' + - '
' + - + var html = '
' + + '
' + + '
' + nick.htmlEnc() + '
'; - + // Show the close button if not MUC and not anonymous if(show_close) { - html += '
' + - 'x' + + html += '
' + + 'x' + '
'; } - + // Close the HTML html += '
'; - + // Append the HTML code $(chat_switch + 'chans, ' + chat_switch + 'more-content').append(html); } catch(e) { @@ -518,10 +519,10 @@ var Chat = (function () { 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(); @@ -569,13 +570,13 @@ var Chat = (function () { 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! @@ -589,22 +590,22 @@ var Chat = (function () { } 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()) @@ -613,18 +614,18 @@ var Chat = (function () { 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'); } @@ -636,23 +637,23 @@ var Chat = (function () { $('#' + 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'); @@ -668,4 +669,4 @@ var Chat = (function () { */ return self; -})(); \ No newline at end of file +})(); diff --git a/source/app/javascripts/chatstate.js b/source/app/javascripts/chatstate.js index 6459103..d0353fb 100644 --- a/source/app/javascripts/chatstate.js +++ b/source/app/javascripts/chatstate.js @@ -32,27 +32,27 @@ var ChatState = (function () { try { var user_type = $('#' + hash).attr('data-type'); - + // If the friend client supports chatstates and is online if((user_type == 'groupchat') || ((user_type == 'chat') && $('#' + hash + ' .message-area').attr('data-chatstates') && !Common.exists('#page-switch .' + hash + ' .unavailable'))) { // Already sent? if(DataStore.getDB(Connection.desktop_hash, 'currentchatstate', xid) == state) { return; } - + // Write the state DataStore.setDB(Connection.desktop_hash, 'currentchatstate', xid, state); - + // New message stanza var aMsg = new JSJaCMessage(); aMsg.setTo(xid); aMsg.setType(user_type); - + // Append the chatstate node aMsg.appendNode(state, { 'xmlns': NS_CHATSTATES }); - + // Send this! con.send(aMsg); } @@ -77,57 +77,57 @@ var ChatState = (function () { // Groupchat? if(type == 'groupchat') { self.reset(hash, type); - + // "gone" state not allowed if(state != 'gone') { $('#page-engine .page-engine-chan .user.' + hash).addClass(state); } } - + // Chat else { // We change the buddy name color in the page-switch self.reset(hash, type); $('#page-switch .' + hash + ' .name').addClass(state); - + // We generate the chatstate text var text = ''; - + switch(state) { // Active case 'active': text = Common._e("Your friend is paying attention to the conversation."); - + break; - + // Composing case 'composing': text = Common._e("Your friend is writing a message..."); - + break; - + // Paused case 'paused': text = Common._e("Your friend stopped writing a message."); - + break; - + // Inactive case 'inactive': text = Common._e("Your friend is doing something else."); - + break; - + // Gone case 'gone': text = Common._e("Your friend closed the chat."); - + break; } - + // We reset the previous state $('#' + hash + ' .chatstate').remove(); - + // We create the chatstate $('#' + hash + ' .content').after( '
' + text + '
' @@ -152,13 +152,13 @@ var ChatState = (function () { try { // Define the selector var selector; - + if(type == 'groupchat') { selector = $('#page-engine .page-engine-chan .user.' + hash); } else { selector = $('#page-switch .' + hash + ' .name'); } - + // Reset! selector.removeClass('active composing paused inactive gone'); } catch(e) { @@ -186,33 +186,33 @@ var ChatState = (function () { if($(this).val() && (DataStore.getDB(Connection.desktop_hash, 'chatstate', xid) != 'on')) { // We change the state detect input DataStore.setDB(Connection.desktop_hash, 'chatstate', xid, 'on'); - + // We send the friend a "composing" chatstate self.send('composing', xid, hash); } - + // Flushed the message which was being composed else if(!$(this).val() && (DataStore.getDB(Connection.desktop_hash, 'chatstate', xid) == 'on')) { // We change the state detect input DataStore.setDB(Connection.desktop_hash, 'chatstate', xid, 'off'); - + // We send the friend an "active" chatstate self.send('active', xid, hash); } } }); - + target.change(function() { // Reset the composing database entry DataStore.setDB(Connection.desktop_hash, 'chatstate', xid, 'off'); }); - + target.focus(function() { // Not needed if(target.is(':disabled')) { return; } - + // Something was written, user started writing again if($(this).val()) { self.send('composing', xid, hash); @@ -223,7 +223,7 @@ var ChatState = (function () { self.send('active', xid, hash); } }); - + target.blur(function() { // Not needed if(target.is(':disabled')) { diff --git a/source/app/javascripts/common.js b/source/app/javascripts/common.js index 2b340a5..5874604 100644 --- a/source/app/javascripts/common.js +++ b/source/app/javascripts/common.js @@ -154,16 +154,16 @@ var Common = (function () { if(type == 'groupchat') { return xid + '@' + HOST_MUC; } - + // Gateway XID if(self.isDomain(xid) === true) { return xid; } - + // User XID return xid + '@' + HOST_MAIN; } - + // Nothing special (yet bare XID) return xid; } catch(e) { @@ -221,14 +221,14 @@ var Common = (function () { if(!given_char || !str) { return ''; } - + var char_index = str.lastIndexOf(given_char); var str_return = str; - + if(char_index >= 0) { str_return = str.substr(char_index + 1); } - + return str_return; } catch(e) { Console.error('Common.strAfterLast', e); @@ -250,7 +250,7 @@ var Common = (function () { try { // Get the index of our char to explode var index = toStr.indexOf(toEx); - + // We split if necessary the string if(index !== -1) { if(i === 0) { @@ -259,7 +259,7 @@ var Common = (function () { toStr = toStr.substr(index + 1); } } - + // We return the value return toStr; } catch(e) { @@ -424,12 +424,12 @@ var Common = (function () { try { // Cut the resource xid = self.cutResource(xid); - + // Launch nodeprep if(xid.indexOf('@') !== -1) { xid = self.nodeprep(self.getXIDNick(xid, true)) + '@' + self.getXIDHost(xid); } - + return xid; } catch(e) { Console.error('Common.bareXID', e); @@ -450,12 +450,12 @@ var Common = (function () { // Normalizes the XID var full = self.bareXID(xid); var resource = self.thisResource(xid); - + // Any resource? if(resource) { full += '/' + resource; } - + return full; } catch(e) { Console.error('Common.fullXID', e); @@ -480,7 +480,7 @@ var Common = (function () { return self.explodeThis('\\40', aXID, 0); } } - + return self.explodeThis('@', aXID, 0); } catch(e) { Console.error('Common.getXIDNick', e); @@ -555,7 +555,7 @@ var Common = (function () { /** - * Gets the full XID of the user + * Gets the bare XID of the user * @public * @return {string} */ @@ -566,7 +566,7 @@ var Common = (function () { if(con.username && con.domain) { return con.username + '@' + con.domain; } - + return ''; } catch(e) { Console.error('Common.getXID', e); @@ -575,6 +575,29 @@ var Common = (function () { }; + /** + * Gets the full XID of the user + * @public + * @return {string} + */ + self.getFullXID = function() { + + try { + var xid = self.getXID(); + + // Return the full XID of the user + if(xid) { + return xid + '/' + con.resource; + } + + return ''; + } catch(e) { + Console.error('Common.getFullXID', e); + } + + }; + + /** * Generates the colors for a given user XID * @public @@ -592,15 +615,15 @@ var Common = (function () { '00236b', '4e005c' ); - + var number = 0; - + for(var i = 0; i < xid.length; i++) { number += xid.charCodeAt(i); } - + var color = '#' + colors[number % (colors.length)]; - + return color; } catch(e) { Console.error('Common.generateColor', e); @@ -642,12 +665,12 @@ var Common = (function () { try { var from = stanza.getFrom(); - + // No from, we assume this is our XID if(!from) { from = self.getXID(); } - + return from; } catch(e) { Console.error('Common.getStanzaFrom', e); @@ -692,12 +715,12 @@ var Common = (function () { if(i > -10 && i < 0) { return '-0' + (i * -1); } - + // Positive number (without first 0) if(i < 10 && i >= 0) { return '0' + i; } - + // All is okay return i; } catch(e) { @@ -798,7 +821,7 @@ var Common = (function () { if(window.XMLSerializer) { xml_str = (new XMLSerializer()).serializeToString(xmlData); } - + // For Internet Explorer if(window.ActiveXObject) { xml_str = xmlData.xml; @@ -825,21 +848,21 @@ var Common = (function () { if(!sXML) { return ''; } - + // Add the XML tag if(!sXML.match(/^<\?xml/i)) { sXML = '' + sXML; } - + // Parse it! if(window.DOMParser) { return (new DOMParser()).parseFromString(sXML, 'text/xml'); } - + if(window.ActiveXObject) { var oXML = new ActiveXObject('Microsoft.XMLDOM'); oXML.loadXML(sXML); - + return oXML; } } catch(e) { @@ -861,7 +884,7 @@ var Common = (function () { try { var timer = 0; - + return function(callback, ms) { clearTimeout(timer); timer = setTimeout(callback, ms); @@ -880,4 +903,4 @@ var Common = (function () { })(); -var JappixCommon = Common; \ No newline at end of file +var JappixCommon = Common; diff --git a/source/app/javascripts/connection.js b/source/app/javascripts/connection.js index 9a5f6d9..6f1dadb 100644 --- a/source/app/javascripts/connection.js +++ b/source/app/javascripts/connection.js @@ -45,20 +45,20 @@ var Connection = (function () { try { // Show the waiting image Interface.showGeneralWait(); - + // Change the page title Interface.title('wait'); - + // Send request $.post('./server/register.php', {username: username, domain: domain, password: pass, captcha: captcha}, function(data) { // Error registering Interface.removeGeneralWait(); Interface.title('home'); - + // In all case, update CAPTCHA $('#home img.captcha_img').attr('src', './server/captcha.php?id=' + genID()); $('#home input.captcha').val(''); - + // Registration okay if($(data).find('query status').text() == '1') { is_success = true; @@ -66,28 +66,28 @@ var Connection = (function () { } else { // Show error message var error_message = ''; - + switch($(data).find('query message').text()) { case 'CAPTCHA Not Matching': error_message = Common._e("The security code you entered is invalid. Please retry with another one."); - + $('#home input.captcha').focus(); - + break; - + case 'Username Unavailable': error_message = Common._e("The username you picked is not available. Please try another one."); - + $('#home input.nick').focus(); - + break; - + default: error_message = Common._e("There was an error registering your account. Please retry."); - + break; } - + if(error_message) { Errors.show('', error_message, ''); } @@ -125,17 +125,17 @@ var Connection = (function () { // Check BOSH origin BOSH_SAME_ORIGIN = Origin.isSame(httpbase); - + // We create the new http-binding connection con = new JSJaCHttpBindingConnection({ httpbase: httpbase }); } - + // We setup the connection ! con.registerHandler('onconnect', self.handleRegistered); con.registerHandler('onerror', Errors.handle); - + con.connect({ 'domain': $.trim(domain), 'username': $.trim(username), @@ -145,10 +145,10 @@ var Connection = (function () { 'secure': true, 'xmllang': XML_LANG }); - + // Show the waiting image Interface.showGeneralWait(); - + // Change the page title Interface.title('wait'); } catch(e) { @@ -176,7 +176,7 @@ var Connection = (function () { return self.cancelReconnect(); }); } - + $('#reconnect a.finish.reconnect').click(function() { return self.acceptReconnect(mode); }); @@ -202,22 +202,22 @@ var Connection = (function () { } else { self.reconnect_timer = 120; } - + // Change the try number self.reconnect_try++; - + // Fire the event! $('#reconnect a.finish.reconnect').everyTime('1s', function() { // We can reconnect! if(self.reconnect_timer === 0) { return self.acceptReconnect(mode); } - + // Button text if(self.reconnect_timer <= 10) { $(this).text(Common._e("Reconnect") + ' (' + self.reconnect_timer + ')'); } - + // Remove 1 second self.reconnect_timer--; }); @@ -248,10 +248,10 @@ var Connection = (function () { // We remove the not completed class to avoid problems $('#home .loginer input').removeClass('please-complete'); - + // We add the login wait div Interface.showGeneralWait(); - + if(Common.hasWebSocket()) { // WebSocket supported & configured con = new JSJaCWebSocketConnection({ @@ -262,19 +262,19 @@ var Connection = (function () { // Check BOSH origin BOSH_SAME_ORIGIN = Origin.isSame(httpbase); - + // We create the new http-binding connection con = new JSJaCHttpBindingConnection({ httpbase: httpbase }); } - + // And we handle everything that happen self.setupCon(con, extend_obj); - + // Generate a resource var random_resource = DataStore.getDB(self.desktop_hash, 'session', 'resource'); - + if(!random_resource) { random_resource = lResource + ' (' + (new Date()).getTime() + ')'; } @@ -289,29 +289,29 @@ var Connection = (function () { }; self.desktop_hash = 'jd.' + hex_md5(con_args.username + '@' + con_args.domain); - + // Store the resource (for reconnection) DataStore.setDB(self.desktop_hash, 'session', 'resource', random_resource); - + // Store session XML in temporary database self.storeSession(lNick, lServer, lPass, lResource, lPriority, lRemember); - + // We store the infos of the user into the data-base DataStore.setDB(self.desktop_hash, 'priority', 1, lPriority); - + // We connect ! con.connect(con_args); - + // Change the page title Interface.title('wait'); - + Console.info('Jappix is connecting...'); } catch(e) { Console.error('Connection.doLogin', e); // Reset Jappix Talk.destroy(); - + // Open an unknown error Board.openThisError(2); } finally { @@ -330,16 +330,16 @@ var Connection = (function () { try { Console.info('A new account has been registered.'); - + // We remove the waiting image Interface.removeGeneralWait(); - + // Reset the title Interface.title('home'); - + // We show the success information $('#home .registerer .success').fadeIn('fast'); - + // We quit the session if(Common.isConnected()) { self.logout(); @@ -364,21 +364,21 @@ var Connection = (function () { try { Console.info('Trying to register an account...'); - + // We change the registered information text $('#home .homediv.registerer').append( - '
' + - Common._e("You have been registered, here is your XMPP address:") + - ' ' + username.htmlEnc() + '@' + domain.htmlEnc() + ' - ' + - '' + Common._e("Login") + '' + + '
' + + Common._e("You have been registered, here is your XMPP address:") + + ' ' + username.htmlEnc() + '@' + domain.htmlEnc() + ' - ' + + '' + Common._e("Login") + '' + '
' ); - + // Login link $('#home .homediv.registerer .success a').click(function() { return self.doLogin(username, domain, pass, '', '10', false); }); - + if((REGISTER_API == 'on') && (domain == HOST_MAIN) && captcha) { self._doRegisterAPI(username, domain, pass, captcha); } else { @@ -402,28 +402,28 @@ var Connection = (function () { try { Console.info('Trying to login anonymously...'); - + var path_sel = $('#home .anonymouser'); var room = path_sel.find('.room').val(); var nick = path_sel.find('.nick').val(); - + // Form correctly completed? if(room && nick) { // We remove the not completed class to avoid problems $('#home .anonymouser input').removeClass('please-complete'); - + // Redirect the user to the anonymous room window.location.href = JAPPIX_LOCATION + '?r=' + room + '&n=' + nick; } else { path_sel.find('input[type="text"]').each(function() { var this_sel = $(this); - + if(!this_sel.val()) { $(document).oneTime(10, function() { this_sel.addClass('please-complete').focus(); }); } else { - this_sel.removeClass('please-complete'); + this_sel.removeClass('please-complete'); } }); } @@ -445,22 +445,22 @@ var Connection = (function () { try { Console.info('Jappix is now connected.'); - + // Connection markers self.connected = true; self.reconnect_try = 0; self.reconnect_timer = 0; - + // We hide the home page $('#home').hide(); - + // Any suggest to do before triggering connected event? Groupchat.suggestCheck(); - + // Remove the waiting item Interface.removeGeneralWait(); - // Init Jingle + // Init call Call.init(); } catch(e) { Console.error('Connection.handleConnected', e); @@ -483,25 +483,25 @@ var Connection = (function () { if(DataStore.getDB(self.desktop_hash, 'remember', 'session')) { DataStore.setPersistent('global', 'session', 1, self.current_session); } - + // We show the chatting app. Talk.create(); - + // We reset the homepage Home.change('default'); - + // We get all the other things self.getEverything(); - + // Set last activity stamp DateUtils.last_activity = DateUtils.getTimeStamp(); } - + // Resumed else { // Send our presence Presence.sendActions(); - + // Change the title Interface.updateTitle(); } @@ -521,7 +521,10 @@ var Connection = (function () { try { Console.info('Jappix is now disconnected.'); - + + // Abort ongoing call (if any) + Call.stop(true); + // Normal disconnection if(!self.current_session && !self.connected) { Talk.destroy(); @@ -562,7 +565,7 @@ var Connection = (function () { // Extended handlers extend_obj = extend_obj || {}; - + jQuery.each(extend_obj, function(keywd,funct) { con.registerHandler(keywd, funct); }); @@ -611,13 +614,13 @@ var Connection = (function () { if(Common.isConnected()) { // Clear temporary session storage self.resetConMarkers(); - + // Show the waiting item (useful if BOSH is sloooow) Interface.showGeneralWait(); - + // Change the page title Interface.title('wait'); - + // Disconnect from the XMPP server self.logout(); } @@ -640,13 +643,13 @@ var Connection = (function () { if(!Common.isConnected()) { return; } - + // We show the waiting image Interface.showGeneralWait(); - + // Change the page title Interface.title('wait'); - + // We disconnect from the XMPP server self.logout(); } catch(e) { @@ -666,34 +669,34 @@ var Connection = (function () { try { Console.error('This is not a normal disconnection, show the reconnect pane...'); - + // Reconnect pane not yet displayed? if(!Common.exists('#reconnect')) { // Blur the focused input/textarea/select $('input, select, textarea').blur(); - + // Create the HTML code - var html = '
' + - '
' + + var html = '
' + + '
' + Common._e("Due to a network issue, you were disconnected. What do you want to do now?"); - + // Can we cancel reconnection? if(mode == 'normal') { html += '' + Common._e("Cancel") + ''; } - - html += '' + Common._e("Reconnect") + '' + + + html += '' + Common._e("Reconnect") + '' + '
'; - + // Append the code $('body').append(html); - + // Attach events self._eventsReconnect(mode); - + // Schedule next reconnect self._scheduleReconnect(mode); - + // Page title Interface.updateTitle(); } @@ -714,13 +717,13 @@ var Connection = (function () { try { Console.info('Trying to reconnect the user...'); - + // Resume marker self.resume = true; - + // Show waiting item Interface.showGeneralWait(); - + // Reset some various stuffs var groupchats = '#page-engine .page-engine-chan[data-type="groupchat"]'; var groupchats_sel = $(groupchats); @@ -728,13 +731,13 @@ var Connection = (function () { groupchats_sel.find('.list .role').hide(); groupchats_sel.find('.one-group, ' + groupchats + ' .list .user').remove(); groupchats_sel.attr('data-initial', 'false'); - + // Stop the timer $('#reconnect a.finish.reconnect').stopTime(); - + // Remove the reconnect pane $('#reconnect').remove(); - + // Try to login again if(mode == 'normal') { self.loginFromSession(Common.XMLFromString(self.current_session)); @@ -759,16 +762,16 @@ var Connection = (function () { try { Console.info('User has canceled automatic reconnection...'); - + // Stop the timer $('#reconnect a.finish.reconnect').stopTime(); - + // Remove the reconnect pane $('#reconnect').remove(); - + // Destroy the talk page Talk.destroy(); - + // Renitialize the previous session parameters self.resetConMarkers(); } catch(e) { @@ -790,7 +793,7 @@ var Connection = (function () { try { // Clear temporary storage self.resetConMarkers(); - + // Clear persistent storage if($(Common.XMLFromString(DataStore.getPersistent('global', 'session', 1))).find('stored').text() == 'true') { DataStore.removePersistent('global', 'session', 1); @@ -833,7 +836,7 @@ var Connection = (function () { try { // Select the data var session = $(data); - + // Fire the login event self.doLogin( session.find('username').text(), @@ -860,10 +863,10 @@ var Connection = (function () { try { // Reset our database self.clearLastSession(); - + // We quit the current session self.quit(); - + // We show an info Board.openThisInfo(3); } catch(e) { @@ -909,23 +912,23 @@ var Connection = (function () { try { // Generate a session XML to be stored - session_xml = '' + - 'true' + - '' + lServer.htmlEnc() + '' + - '' + lNick.htmlEnc() + '' + - '' + lResource.htmlEnc() + '' + - '' + lPass.htmlEnc() + '' + - '' + lPriority.htmlEnc() + '' + + session_xml = '' + + 'true' + + '' + lServer.htmlEnc() + '' + + '' + lNick.htmlEnc() + '' + + '' + lResource.htmlEnc() + '' + + '' + lPass.htmlEnc() + '' + + '' + lPriority.htmlEnc() + '' + ''; - + // Save the session parameters (for reconnect if network issue) self.current_session = session_xml; - + // Remember me? if(lRemember) { DataStore.setDB(self.desktop_hash, 'remember', 'session', 1); } - + return session_xml; } catch(e) { Console.error('Connection.storeSession', e); @@ -945,12 +948,12 @@ var Connection = (function () { $(document).ready(function() { // Logouts when Jappix is closed $(window).bind('beforeunload', Connection.terminate); - + // Nothing to do when anonymous! if(Utils.isAnonymous()) { return; } - + // Connection params submitted in URL? if(XMPPLinks.links_var.u && XMPPLinks.links_var.q) { // Generate login data @@ -961,7 +964,7 @@ var Connection = (function () { var login_resource = JAPPIX_RESOURCE + ' (' + (new Date()).getTime() + ')'; var login_priority = '10'; var login_remember = 1; - + // Must store session? if(XMPPLinks.links_var.h && (XMPPLinks.links_var.h === '1')) { // Store session @@ -975,42 +978,42 @@ var Connection = (function () { ); DataStore.setPersistent('global', 'session', 1, session_xml); - + // Redirect to a clean URL document.location.href = './'; } else { // Hide the homepage $('#home').hide(); - + // Show the waiting icon Interface.showGeneralWait(); - + // Proceed login self.doLogin(login_nick, login_server, login_pwd, login_resource, login_priority, login_remember); } - + return; } - + // Try to resume a stored session, if not anonymous var session = Common.XMLFromString( DataStore.getPersistent('global', 'session', 1) ); - + if($(session).find('stored').text() == 'true') { // Hide the homepage $('#home').hide(); - + // Show the waiting icon Interface.showGeneralWait(); - + // Login! self.loginFromSession(session); - + Console.info('Saved session found, resuming it...'); } else if((parent.location.hash != '#OK') && XMPPLinks.links_var.x) { Home.change('loginer'); - + Console.info('A XMPP link is set, switch to login page.'); } }); diff --git a/source/app/javascripts/constants.js b/source/app/javascripts/constants.js index be9241e..69b71d1 100644 --- a/source/app/javascripts/constants.js +++ b/source/app/javascripts/constants.js @@ -187,7 +187,7 @@ function STANZA_ERROR(code, type, cond) { if(window == this) { return new STANZA_ERROR(code, type, cond); } - + this.code = code; this.type = type; this.cond = cond; diff --git a/source/app/javascripts/correction.js b/source/app/javascripts/correction.js index 1bfa930..deea70c 100644 --- a/source/app/javascripts/correction.js +++ b/source/app/javascripts/correction.js @@ -134,9 +134,9 @@ var Correction = (function () { text_sel.addClass('correction-active'); text_sel.prepend( - '
' + - '' + Common._e("Editing") + '' + - '' + Common._e("Cancel") + '' + + '
' + + '' + Common._e("Editing") + '' + + '' + Common._e("Cancel") + '' + '
' ); @@ -146,8 +146,8 @@ var Correction = (function () { message_sel.find('.correction-edit').hide(); message_sel.append( - '' + - Common._e("Being edited") + + '' + + Common._e("Being edited") + '' ); @@ -224,14 +224,14 @@ var Correction = (function () { // Generates the correct message depending of the choosen style var generate_message = Message.generate(message, message_body, hash); args.xhtml = (generate_message === 'XHTML'); - + // Receipt request var receipt_request = Receipts.request(hash); - + if(receipt_request) { message.appendNode('request', {'xmlns': NS_URN_RECEIPTS}); } - + // Chatstate message.appendNode('active', {'xmlns': NS_CHATSTATES}); diff --git a/source/app/javascripts/dataform.js b/source/app/javascripts/dataform.js index 62304a0..b409768 100644 --- a/source/app/javascripts/dataform.js +++ b/source/app/javascripts/dataform.js @@ -19,7 +19,7 @@ var DataForm = (function () { */ var self = {}; - + /** * Gets the defined dataform elements * @public @@ -35,79 +35,79 @@ var DataForm = (function () { try { // Clean the current session self.clean(target); - + // We tell the user that a search has been launched $('#' + target + ' .wait').show(); - + // If we have enough data if(host && type) { // Generate a session ID var sessionID = Math.round(100000.5 + (((900000.49999) - (100000.5)) * Math.random())); var id = target + '-' + sessionID + '-' + genID(); $('.' + target + '-results').attr('data-session', target + '-' + sessionID); - + // We request the service item var iq = new JSJaCIQ(); iq.setID(id); iq.setTo(host); iq.setType('get'); - + // MUC admin query if(type == 'muc') { iq.setQuery(NS_MUC_OWNER); con.send(iq, self.handleMUC); } - + // Browse query else if(type == 'browse') { var iqQuery = iq.setQuery(NS_DISCO_ITEMS); - + if(node) { iqQuery.setAttribute('node', node); } - + con.send(iq, self.handleBrowse); } - + // Command else if(type == 'command') { var items; - + if(node) { items = iq.appendNode('command', {'node': node, 'xmlns': NS_COMMANDS}); } - + else { items = iq.setQuery(NS_DISCO_ITEMS); items.setAttribute('node', NS_COMMANDS); } - + if(action && node) { iq.setType('set'); items.setAttribute('action', action); } - + con.send(iq, self.handleCommand); } - + // Search query else if(type == 'search') { iq.setQuery(NS_SEARCH); con.send(iq, self.handleSearch); } - + // Subscribe query else if(type == 'subscribe') { iq.setQuery(NS_REGISTER); con.send(iq, self.handleSubscribe); } - + // Join else if(type == 'join') { if(target == 'discovery') { Discovery.close(); } - + Chat.checkCreate(host, 'groupchat'); } } @@ -138,15 +138,15 @@ var DataForm = (function () { try { // Path var pathID = '#' + target + ' .results[data-session="' + id + '"]'; - + // New IQ var iq = new JSJaCIQ(); iq.setTo(xid); iq.setType('set'); - + // Set the correct query var query; - + if(type == 'subscribe') { iqQuery = iq.setQuery(NS_REGISTER); } else if(type == 'search') { @@ -156,7 +156,7 @@ var DataForm = (function () { } else if(type == 'x') { iqQuery = iq.setQuery(NS_MUC_OWNER); } - + // Build the XML document if(action != 'cancel') { // No X node @@ -164,25 +164,25 @@ var DataForm = (function () { $('input.register-special').each(function() { var iName = $(this).attr('name'); var iValue = $(this).val(); - + iqQuery.appendChild(iq.buildNode(iName, {'xmlns': NS_REGISTER}, iValue)); }); } - + // Can create the X node else { var iqX = iqQuery.appendChild(iq.buildNode('x', {'xmlns': NS_XDATA, 'type': x_type})); - + // Each input $(pathID + ' .oneresult input, ' + pathID + ' .oneresult textarea, ' + pathID + ' .oneresult select').each(function() { // Get the current input value var iVar = $(this).attr('name'); var iType = $(this).attr('data-type'); var iValue = $(this).val(); - + // Build a new field node var field = iqX.appendChild(iq.buildNode('field', {'var': iVar, 'type': iType, 'xmlns': NS_XDATA})); - + // Boolean input? if(iType == 'boolean') { if($(this).filter(':checked').size()) { @@ -191,28 +191,28 @@ var DataForm = (function () { iValue = '0'; } } - + // JID-multi input? if(iType == 'jid-multi') { // Values array var xid_arr = [iValue]; var xid_check = []; - + // Try to split it if(iValue.indexOf(',') != -1) { xid_arr = iValue.split(','); } - + // Append each value to the XML document for(var i in xid_arr) { // Get the current value xid_current = $.trim(xid_arr[i]); - + // No current value? if(!xid_current) { continue; } - + // Add the current value if(!Utils.existArrayValue(xid_check, xid_current)) { xid_check.push(xid_current); @@ -220,7 +220,7 @@ var DataForm = (function () { } } } - + // List-multi selector? else if(iType == 'list-multi') { // Any value? @@ -230,7 +230,7 @@ var DataForm = (function () { } } } - + // Other inputs? else { field.appendChild(iq.buildNode('value', {'xmlns': NS_XDATA}, iValue)); @@ -238,18 +238,18 @@ var DataForm = (function () { }); } } - + // Clean the current session self.clean(target); - + // Show the waiting item $('#' + target + ' .wait').show(); - + // Change the ID of the current discovered item var iqID = target + '-' + genID(); $('#' + target + ' .' + target + '-results').attr('data-session', iqID); iq.setID(iqID); - + // Send the IQ if(type == 'subscribe') { con.send(iq, self.handleSubscribe); @@ -289,7 +289,7 @@ var DataForm = (function () { if(type == 'muc') { return; } - + // Override the "undefined" output if(!id) id = ''; @@ -299,57 +299,57 @@ var DataForm = (function () { node = ''; if(!sessionid) sessionid = ''; - + // We generate the buttons code var buttonsCode = '
'; - + if(action == 'submit') { if((target == 'adhoc') && (type == 'command')) { buttonsCode += '' + Common._e("Submit") + ''; - + // When keyup on one text input $(pathID + ' input').keyup(function(e) { if(e.keyCode == 13) { self.send(type, 'execute', 'submit', id, xid, node, sessionid, target); - + return false; } }); } else { buttonsCode += '' + Common._e("Submit") + ''; - + // When keyup on one text input $(pathID + ' input').keyup(function(e) { if(e.keyCode == 13) { self.send(type, 'submit', 'submit', id, xid, node, sessionid, target); - + return false; } }); } } - + if((action == 'submit') && (type != 'subscribe') && (type != 'search')) { buttonsCode += '' + Common._e("Cancel") + ''; } - + if(((action == 'back') || (type == 'subscribe') || (type == 'search')) && (target == 'discovery')) { buttonsCode += '' + Common._e("Close") + ''; } - + if((action == 'back') && ((target == 'welcome') || (target == 'directory'))) { buttonsCode += '' + Common._e("Previous") + ''; } - + if((action == 'back') && (target == 'adhoc')) { buttonsCode += '' + Common._e("Previous") + ''; } - + buttonsCode += '
'; - + // We display the buttons code $(pathID).append(buttonsCode); - + // If no submit link, lock the form if(!Common.exists(pathID + ' a.submit')) { $(pathID + ' input, ' + pathID + ' textarea').attr('readonly', true); @@ -395,7 +395,7 @@ var DataForm = (function () { } }; - + /** * Handles the command dataform @@ -463,40 +463,40 @@ var DataForm = (function () { try { // Get the ID var sID = iq.getID(); - + // Get the target var splitted = sID.split('-'); var target = splitted[0]; var sessionID = target + '-' + splitted[1]; var from = Common.fullXID(Common.getStanzaFrom(iq)); var pathID = '#' + target + ' .results[data-session="' + sessionID + '"]'; - + // If an error occured if(!iq || (iq.getType() != 'result')) { self.noResult(pathID); } - + // If we got something okay else { var handleXML = iq.getNode(); - + if(type == 'browse') { if($(handleXML).find('item').attr('jid')) { // Get the query node var queryNode = $(handleXML).find('query').attr('node'); - + $(handleXML).find('item').each(function() { // We parse the received xml var itemHost = $(this).attr('jid'); var itemNode = $(this).attr('node'); var itemName = $(this).attr('name'); var itemHash = hex_md5(itemHost); - + // Node if(itemNode) { $(pathID).append( - '
' + - '
' + itemNode.htmlEnc() + '
' + + '
' + + '
' + itemNode.htmlEnc() + '
' + '
' ); } @@ -504,8 +504,8 @@ var DataForm = (function () { // Item else if(queryNode && itemName) { $(pathID).append( - '
' + - '
' + itemName.htmlEnc() + '
' + + '
' + + '
' + itemName.htmlEnc() + '
' + '
' ); } @@ -514,27 +514,27 @@ var DataForm = (function () { else { // We display the waiting element $(pathID + ' .disco-wait .disco-category-title').after( - '
' + - '
' + - '
' + itemHost + '
' + - '
' + Common._e("Requesting this service...") + '
' + + '
' + + '
' + + '
' + itemHost + '
' + + '
' + Common._e("Requesting this service...") + '
' + '
' ); - + // We display the category $('#' + target + ' .disco-wait').show(); - + // We ask the server what's the service type self.getType(itemHost, itemNode, sessionID); } }); } - + // Else, there are no items for this query else self.noResult(pathID); } - + else if((type == 'muc') || (type == 'search') || (type == 'subscribe') || ((type == 'command') && $(handleXML).find('command').attr('xmlns'))) { // Get some values var xCommand = $(handleXML).find('command'); @@ -543,11 +543,11 @@ var DataForm = (function () { var bStatus = xCommand.attr('status'); var xRegister = $(handleXML).find('query[xmlns="' + NS_REGISTER + '"]').text(); var xElement = $(handleXML).find('x'); - + // Search done if((xElement.attr('type') == 'result') && (type == 'search')) { var bPath = pathID; - + // Display the result $(handleXML).find('item').each(function() { // Have some "flexibility" for what regards field names, it would be better to return the whole original DF @@ -560,7 +560,7 @@ var DataForm = (function () { var bCountry; var doneName, doneCountry; - $.each($(this).find('field'), function(i, item) { + $.each($(this).find('field'), function(i, item) { var $item = $(item); if($(item).attr('var').match(/^(fn|name|[^n][^i][^c][^k]name)$/gi) && doneName !== true) { @@ -574,7 +574,7 @@ var DataForm = (function () { var bXID = $(this).find('field[var="jid"] value:first').text(); var dName = bName; - + // Override "undefined" value if(!bXID) bXID = ''; @@ -582,84 +582,84 @@ var DataForm = (function () { bName = Common._e("Unknown name"); if(!bCountry) bCountry = Common._e("Unknown country"); - + // User hash var bHash = hex_md5(bXID); - + // HTML code - var bHTML = '
' + - '
' + - '' + - '
' + - '
' + bName + '
' + - '
' + bCountry + '
' + - '
' + bXID + '
' + + var bHTML = '
' + + '
' + + '' + + '
' + + '
' + bName + '
' + + '
' + bCountry + '
' + + '
' + bXID + '
' + '
'; - + // The buddy is not in our buddy list? if(!Common.exists('#roster .buddy[data-xid="' + escape(bXID) + '"]')) { bHTML += '' + Common._e("Add") + ''; } - + // Chat button, if not in welcome/directory mode if(target == 'discovery') { bHTML += '' + Common._e("Chat") + ''; } - + // Profile button, if not in discovery mode else { bHTML += '' + Common._e("Profile") + ''; } - + // Close the HTML element bHTML += '
'; - + $(bPath).append(bHTML); - + // Click events $(bPath + ' .' + bHash + ' a').click(function() { // Buddy add if($(this).is('.one-add')) { $(this).hide(); - + Roster.addThisContact(bXID, dName); } - + // Buddy chat if($(this).is('.one-chat')) { if(target == 'discovery') Discovery.close(); - + Chat.checkCreate(bXID, 'chat', '', '', dName); } - + // Buddy profile if($(this).is('.one-profile')) { UserInfos.open(bXID); } - + return false; }); - + // Get the user's avatar if(bXID) { Avatar.get(bXID, 'cache', 'true', 'forget'); } }); - + // No result? if(!$(handleXML).find('item').size()) self.noResult(pathID); - + // Previous button self.buttons(type, 'back', sessionID, from, bNode, bSession, target, pathID); } - + // Command to complete else if(xElement.attr('xmlns') || ((type == 'subscribe') && xRegister)) { // We display the elements self.fill(handleXML, sessionID); - + // We display the buttons if(bStatus != 'completed') { self.buttons(type, 'submit', sessionID, from, bNode, bSession, target, pathID); @@ -667,12 +667,12 @@ var DataForm = (function () { self.buttons(type, 'back', sessionID, from, bNode, bSession, target, pathID); } } - + // Command completed or subscription done else if(((bStatus == 'completed') && (type == 'command')) || (!xRegister && (type == 'subscribe'))) { // Display the good text var cNote = $(xCommand).find('note'); - + // Any note? if(cNote.size()) { cNote.each(function() { @@ -681,21 +681,21 @@ var DataForm = (function () { ); }); } - + // Default text else { $(pathID).append('
' + Common._e("Your form has been sent.") + '
'); } - + // Display the back button self.buttons(type, 'back', sessionID, from, '', '', target, pathID); - + // Add the gateway to our roster if subscribed if(type == 'subscribe') { Roster.addThisContact(from); } } - + // Command canceled else if((bStatus == 'canceled') && (type == 'command')) { if(target == 'discovery') { @@ -704,12 +704,12 @@ var DataForm = (function () { dataForm(from, 'command', '', '', 'adhoc'); } } - + // No items for this query else self.noResult(pathID); } - + else if(type == 'command') { if($(handleXML).find('item').attr('jid')) { // We display the elements @@ -719,29 +719,29 @@ var DataForm = (function () { var itemNode = $(this).attr('node'); var itemName = $(this).attr('name'); var itemHash = hex_md5(itemHost); - + // We display the waiting element $(pathID).prepend( - '
' + - '
' + itemName + '
' + - '
»
' + + '
' + + '
' + itemName + '
' + + '
»
' + '
' ); }); } - + // Else, there are no items for this query else { self.noResult(pathID); } } } - + // Focus on the first input $(document).oneTime(10, function() { $(pathID + ' input:visible:first').focus(); }); - + // Hide the wait icon $('#' + target + ' .wait').hide(); } catch(e) { @@ -767,56 +767,56 @@ var DataForm = (function () { var target = id.split('-')[0]; var pathID = '#' + target + ' .results[data-session="' + id + '"]'; var selector, is_dataform; - + // Is it a dataform? if($(xml).find('x[xmlns="' + NS_XDATA + '"]').size()) { is_dataform = true; } else { is_dataform = false; } - + // Determines the good selector to use if(is_dataform) { selector = $(xml).find('x[xmlns="' + NS_XDATA + '"]'); } else { selector = $(xml); } - + // Form title selector.find('title').each(function() { $(pathID).append( '
' + $(this).text().htmlEnc() + '
' ); }); - + // Form instructions selector.find('instructions').each(function() { $(pathID).append( '
' + $(this).text().htmlEnc() + '
' ); }); - + // Register? if(!is_dataform) { // Items to detect var reg_names = [Common._e("Nickname"), Common._e("Name"), Common._e("Password"), Common._e("E-mail")]; var reg_ids = ['username', 'name', 'password', 'email']; - + // Append these inputs $.each(reg_names, function(a) { selector.find(reg_ids[a]).each(function() { $(pathID).append( - '
' + - '' + - '' + + '
' + + '' + + '' + '
' ); }); }); - + return false; } - + // Dataform? selector.find('field').each(function() { // We parse the received xml @@ -825,30 +825,30 @@ var DataForm = (function () { var field = $(this).attr('var'); var value = $(this).find('value:first').text(); var required = ''; - + // No value? if(!field) { return; } - + // Required input? if($(this).find('required').size()) { required = ' required=""'; } - + // Compatibility fix if(!label) { label = field; } - + if(!type) { type = ''; } - + // Generate some values var input; var hideThis = ''; - + // Fixed field if(type == 'fixed') { $(pathID).append('
' + value.htmlEnc() + '
'); @@ -862,113 +862,113 @@ var DataForm = (function () { // Boolean field else if(type == 'boolean') { var checked; - + if(value == '1') checked = 'checked'; else checked = ''; - + input = ''; } - + // List-single/list-multi field else if((type == 'list-single') || (type == 'list-multi')) { var multiple = ''; - + // Multiple options? if(type == 'list-multi') { multiple = ' multiple=""'; } - + // Append the select field input = ''; } - + // Text-multi field else if(type == 'text-multi') { input = ''; } - + // JID-multi field else if(type == 'jid-multi') { // Put the XID into an array var xid_arr = []; - + $(this).find('value').each(function() { var cValue = $(this).text(); - + if(!Utils.existArrayValue(xid_arr, cValue)) { xid_arr.push(cValue); } }); - + // Sort the array xid_arr.sort(); - + // Create the input var xid_value = ''; - + if(xid_arr.length) { for(var i in xid_arr) { // Any pre-value if(xid_value) { xid_value += ', '; } - + // Add the current XID xid_value += xid_arr[i]; } } - + input = ''; } - + // Other stuffs that are similar else { // Text-single field var iType = 'text'; - + // Text-private field if(type == 'text-private') { iType = 'password'; } - + // JID-single field else if(type == 'jid-single') { iType = 'email'; } - + input = ''; } - + // Append the HTML markup for this field $(pathID).append( - '
' + - '' + - input + + '
' + + '' + + input + '
' ); } @@ -997,13 +997,13 @@ var DataForm = (function () { iq.setID(id + '-' + genID()); iq.setTo(host); iq.setType('get'); - + var iqQuery = iq.setQuery(NS_DISCO_INFO); - + if(node) { iqQuery.setAttribute('node', node); } - + con.send(iq, self.handleThisBrowse); } catch(e) { Console.error('DataForm.getType', e); @@ -1031,68 +1031,68 @@ var DataForm = (function () { var hash = hex_md5(from); var handleXML = iq.getQuery(); var pathID = '#' + target + ' .results[data-session="' + sessionID + '"]'; - + // We first remove the waiting element $(pathID + ' .disco-wait .' + hash).remove(); - + if($(handleXML).find('identity').attr('type')) { var category = $(handleXML).find('identity').attr('category'); var type = $(handleXML).find('identity').attr('type'); var named = $(handleXML).find('identity').attr('name'); - + if(named) { gName = named; } else { gName = ''; } - + var one, two, three, four, five; - + // Get the features that this entity supports var findFeature = $(handleXML).find('feature'); - + for(var i in findFeature) { var current = findFeature.eq(i).attr('var'); - + switch(current) { case NS_SEARCH: one = 1; break; - + case NS_MUC: two = 1; break; - + case NS_REGISTER: three = 1; break; - + case NS_COMMANDS: four = 1; break; - + case NS_DISCO_ITEMS: five = 1; break; - + default: break; } } - + var buttons = Array(one, two, three, four, five); - + // We define the toolbox links depending on the supported features var tools = ''; var aTools = Array('search', 'join', 'subscribe', 'command', 'browse'); var bTools = Array(Common._e("Search"), Common._e("Join"), Common._e("Subscribe"), Common._e("Command"), Common._e("Browse")); - + for(var b in buttons) { if(buttons[b]) { tools += ''; } } - + // As defined in the ref, we detect the type of each category to put an icon switch(category) { case 'account': @@ -1111,38 +1111,38 @@ var DataForm = (function () { case 'server': case 'store': break; - + default: category = 'others'; } - + // We display the item we found $(pathID + ' .disco-' + category + ' .disco-category-title').after( - '
' + - '
' + - '
' + from + '
' + - '
' + gName + '
' + - '
' + tools + '
' + + '
' + + '
' + + '
' + from + '
' + + '
' + gName + '
' + + '
' + tools + '
' + '
' ); - + // We display the category $(pathID + ' .disco-' + category).show(); } - + else { $(pathID + ' .disco-others .disco-category-title').after( - '
' + - '
' + - '
' + from + '
' + - '
' + Common._e("Service offline or broken") + '
' + + '
' + + '
' + + '
' + from + '
' + + '
' + Common._e("Service offline or broken") + '
' + '
' ); - + // We display the category $(pathID + ' .disco-others').show(); } - + // We hide the waiting stuffs if there's no remaining loading items if(!$(pathID + ' .disco-wait .' + target + '-oneresult').size()) { $(pathID + ' .disco-wait, #' + target + ' .wait').hide(); diff --git a/source/app/javascripts/datastore.js b/source/app/javascripts/datastore.js index c933d8b..1f4b64f 100644 --- a/source/app/javascripts/datastore.js +++ b/source/app/javascripts/datastore.js @@ -165,7 +165,7 @@ var DataStore = (function () { try { return self.storageDB.getItem(dbID + '_' + type + '_' + id); } - + catch(e) { Console.error('Error while getting a temporary database entry (' + dbID + ' -> ' + type + ' -> ' + id + ')', e); } @@ -195,7 +195,7 @@ var DataStore = (function () { return true; } - + catch(e) { Console.error('Error while writing a temporary database entry (' + dbID + ' -> ' + type + ' -> ' + id + ')', e); } @@ -221,10 +221,10 @@ var DataStore = (function () { try { try { self.storageDB.removeItem(dbID + '_' + type + '_' + id); - + return true; } - + catch(e) { Console.error('Error while removing a temporary database entry (' + dbID + ' -> ' + type + ' -> ' + id + ')', e); } @@ -266,15 +266,15 @@ var DataStore = (function () { try { try { self.storageDB.clear(); - + Console.info('Temporary database cleared.'); - + return true; } - + catch(e) { Console.error('Error while clearing temporary database', e); - + return false; } } catch(e) { @@ -297,7 +297,7 @@ var DataStore = (function () { // Try to write something self.storagePersistent.setItem('haspersistent_check', 'ok'); self.storagePersistent.removeItem('haspersistent_check'); - + has_persistent = true; } catch(e) { Console.error('DataStore.hasPersistent', e); @@ -322,10 +322,10 @@ var DataStore = (function () { try { return self.storagePersistent.getItem(dbID + '_' + type + '_' + id); } - + catch(e) { Console.error('Error while getting a persistent database entry (' + dbID + ' -> ' + type + ' -> ' + id + ')', e); - + return null; } } catch(e) { @@ -349,24 +349,24 @@ var DataStore = (function () { try { try { self.storagePersistent.setItem(dbID + '_' + type + '_' + id, value); - + return true; } - + // Database might be full catch(e) { Console.warn('Retrying: could not write a persistent database entry (' + dbID + ' -> ' + type + ' -> ' + id + ')', e); - + // Flush it! self.flushPersistent(); - + // Set the item again try { self.storagePersistent.setItem(dbID + ' -> ' + type + '_' + id, value); - + return true; } - + // New error! catch(_e) { Console.error('Aborted: error while writing a persistent database entry (' + dbID + ' -> ' + type + ' -> ' + id + ')', _e); @@ -397,7 +397,7 @@ var DataStore = (function () { return true; } - + catch(e) { Console.error('Error while removing a persistent database entry (' + dbID + ' -> ' + type + ' -> ' + id + ')', e); } @@ -442,10 +442,10 @@ var DataStore = (function () { self.storagePersistent.clear(); Console.info('Persistent database cleared.'); - + return true; } - + catch(e) { Console.error('Error while clearing persistent database', e); } @@ -470,20 +470,20 @@ var DataStore = (function () { try { // Get the stored session entry var session = self.getPersistent('global', 'session', 1); - + // Reset the persistent database self.resetPersistent(); - + // Restaure the stored session entry if(session) { self.setPersistent('global', 'session', 1, session); } - + Console.info('Persistent database flushed.'); - + return true; } - + catch(e) { Console.error('Error while flushing persistent database', e); } diff --git a/source/app/javascripts/date.js b/source/app/javascripts/date.js index 71b63c7..977b677 100644 --- a/source/app/javascripts/date.js +++ b/source/app/javascripts/date.js @@ -87,7 +87,7 @@ var DateUtils = (function () { if(self.last_activity === 0) { return 0; } - + return self.getTimeStamp() - self.last_activity; } catch(e) { Console.error('DateUtils.getLastActivity', e); @@ -129,7 +129,7 @@ var DateUtils = (function () { if(self.presence_last_activity === 0) { return 0; } - + return self.getTimeStamp() - self.presence_last_activity; } catch(e) { Console.error('DateUtils.getPresenceLast', e); @@ -170,7 +170,7 @@ var DateUtils = (function () { minutes = date.getMinutes(); seconds = date.getSeconds(); } - + // Generates the date string date_string = year + '-'; date_string += Common.padZero(month + 1) + '-'; @@ -178,7 +178,7 @@ var DateUtils = (function () { date_string += Common.padZero(hours) + ':'; date_string += Common.padZero(minutes) + ':'; date_string += Common.padZero(seconds) + 'Z'; - + // Returns the date string return date_string; } catch(e) { @@ -221,7 +221,7 @@ var DateUtils = (function () { var time = Common.padZero(init.getHours()) + ':'; time += Common.padZero(init.getMinutes()) + ':'; time += Common.padZero(init.getSeconds()); - + return time; } catch(e) { Console.error('DateUtils.getCompleteTime', e); @@ -241,26 +241,26 @@ var DateUtils = (function () { // Get the date var date = new Date(); var offset = date.getTimezoneOffset(); - + // Default vars var sign = ''; var hours = 0; var minutes = 0; - + // Process a neutral offset if(offset < 0) { offset = offset * -1; sign = '+'; } - + // Get the values var n_date = new Date(offset * 60 * 1000); hours = n_date.getHours() - 1; minutes = n_date.getMinutes(); - + // Process the TZO tzo = sign + Common.padZero(hours) + ':' + Common.padZero(minutes); - + // Return the processed value return tzo; } catch(e) { @@ -301,7 +301,7 @@ var DateUtils = (function () { try { var date = Date.jab2date(to_parse); var parsed = date.toLocaleDateString() + ' (' + date.toLocaleTimeString() + ')'; - + return parsed; } catch(e) { Console.error('DateUtils.parse', e); @@ -321,7 +321,7 @@ var DateUtils = (function () { try { var date = Date.jab2date(to_parse); var parsed = date.toLocaleDateString(); - + return parsed; } catch(e) { Console.error('DateUtils.parseDay', e); @@ -341,7 +341,7 @@ var DateUtils = (function () { try { var date = Date.jab2date(to_parse); var parsed = date.toLocaleTimeString(); - + return parsed; } catch(e) { Console.error('DateUtils.parseTime', e); @@ -363,36 +363,36 @@ var DateUtils = (function () { var current_date = Date.jab2date(self.getXMPPTime('utc')); var current_day = current_date.getDate(); var current_stamp = current_date.getTime(); - + // Parse the given date var old_date = Date.jab2date(to_parse); var old_day = old_date.getDate(); var old_stamp = old_date.getTime(); var old_time = old_date.toLocaleTimeString(); - + // Get the day number between the two dates var days = Math.round((current_stamp - old_stamp) / 86400000); - + // Invalid date? if(isNaN(old_stamp) || isNaN(days)) { return self.getCompleteTime(); } - + // Is it today? if(current_day == old_day) { return old_time; } - + // It is yesterday? if(days <= 1) { return Common._e("Yesterday") + ' - ' + old_time; } - + // Is it less than a week ago? if(days <= 7) { return Common.printf(Common._e("%s days ago"), days) + ' - ' + old_time; } - + // Another longer period return old_date.toLocaleDateString() + ' - ' + old_time; } catch(e) { @@ -406,17 +406,18 @@ var DateUtils = (function () { * Reads a message delay * @public * @param {string} node - * @return {string} + * @param {boolean} return_date + * @return {string|Date} */ - self.readMessageDelay = function(node) { + self.readMessageDelay = function(node, return_date) { try { // Initialize var delay, d_delay; - + // Read the delay d_delay = jQuery(node).find('delay[xmlns="' + NS_URN_DELAY + '"]:first').attr('stamp'); - + // Get delay if(d_delay) { // New delay (valid XEP) @@ -424,11 +425,17 @@ var DateUtils = (function () { } else { // Old delay (obsolete XEP!) var x_delay = jQuery(node).find('x[xmlns="' + NS_DELAY + '"]:first').attr('stamp'); - - if(x_delay) + + if(x_delay) { delay = x_delay.replace(/^(\w{4})(\w{2})(\w{2})T(\w{2}):(\w{2}):(\w{2})Z?(\S+)?/, '$1-$2-$3T$4:$5:$6Z$7'); + } } - + + // Return a date object? + if(return_date === true && delay) { + return Date.jab2date(delay); + } + return delay; } catch(e) { Console.error('DateUtils.readMessageDelay', e); diff --git a/source/app/javascripts/directory.js b/source/app/javascripts/directory.js index 4ee6efa..67bd1c1 100644 --- a/source/app/javascripts/directory.js +++ b/source/app/javascripts/directory.js @@ -29,31 +29,31 @@ var Directory = (function () { try { // Popup HTML content - var html = - '
' + Common._e("User directory") + '
' + - - '
' + - '
' + - '
' + Common._e("Server to query") + '
' + - - '' + - '
' + - - '
' + - '
' + - - '
' + - '
' + - - '' + Common._e("Close") + '' + + var html = + '
' + Common._e("User directory") + '
' + + + '
' + + '
' + + '
' + Common._e("Server to query") + '
' + + + '' + + '
' + + + '
' + + '
' + + + '
' + + '
' + + + '' + Common._e("Close") + '' + '
'; - + // Create the popup Popup.create('directory', html); - + // Associate the events self.instance(); - + // Start a search! self.start(); } catch(e) { @@ -94,10 +94,10 @@ var Directory = (function () { try { // Get the server to query var server = $('#directory .directory-server-input').val(); - + // Launch the search! DataForm.go($('#directory .directory-server-input').val(), 'search', '', '', 'directory'); - + Console.log('Directory search launched: ' + server); } catch(e) { Console.error('Directory.start', e); @@ -118,7 +118,7 @@ var Directory = (function () { try { // Click event $('#directory .bottom .finish').click(self.close); - + // Keyboard event $('#directory .directory-server-input').keyup(function(e) { if(e.keyCode == 13) { @@ -126,10 +126,10 @@ var Directory = (function () { if(!$(this).val()) { $(this).val(HOST_VJUD); } - + // Start the directory search self.start(); - + return false; } }); diff --git a/source/app/javascripts/discovery.js b/source/app/javascripts/discovery.js index 4490fba..ef419ba 100644 --- a/source/app/javascripts/discovery.js +++ b/source/app/javascripts/discovery.js @@ -29,99 +29,99 @@ var Discovery = (function () { try { // Popup HTML content - var html = - '
' + Common._e("Service discovery") + '
' + - - '
' + - '
' + - '
' + Common._e("Server to query") + '
' + - - '' + - '
' + - - '
' + - '' + - - '
' + - '

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

' + - '
' + - - '
' + - '

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

' + - '
' + - - '
' + - '

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

' + - '
' + - - '
' + - '

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

' + - '
' + - - '
' + - '

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

' + - '
' + - - '
' + - '

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

' + - '
' + - - '
' + - '

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

' + - '
' + - - '
' + - '

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

' + - '
' + - - '
' + - '

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

' + - '
' + - - '
' + - '

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

' + - '
' + - - '
' + - '

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

' + - '
' + - - '
' + - '

' + Common._e("Publication/Subscription") + '

' + - '
' + - - '
' + - '

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

' + - '
' + - - '
' + - '

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

' + - '
' + - - '
' + - '

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

' + - '
' + - - '
' + - '

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

' + - '
' + - '
' + - '
' + - - '
' + - '
' + - - '' + Common._e("Close") + '' + + var html = + '
' + Common._e("Service discovery") + '
' + + + '
' + + '
' + + '
' + Common._e("Server to query") + '
' + + + '' + + '
' + + + '
' + + '' + + + '
' + + '

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

' + Common._e("Publication/Subscription") + '

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

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

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

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

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

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

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

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

' + + '
' + + '
' + + '
' + + + '
' + + '
' + + + '' + Common._e("Close") + '' + '
'; - + // Create the popup Popup.create('discovery', html); - + // Associate the events self.instance(); - + // We request a disco to the default server self.start(); } catch(e) { @@ -164,10 +164,10 @@ var Discovery = (function () { try { // We get the server to query var discoServer = $('#discovery .disco-server-input').val(); - + // We launch the items query DataForm.go(discoServer, 'browse', '', '', 'discovery'); - + Console.log('Service discovery launched: ' + discoServer); } catch(e) { Console.error('Discovery.start', e); @@ -188,10 +188,10 @@ var Discovery = (function () { try { // We remove the results $('#discovery .discovery-oneresult, #discovery .oneinstructions, #discovery .onetitle, #discovery .no-results').remove(); - + // We clean the user info $('#discovery .disco-server-info').text(''); - + // We hide the wait icon, the no result alert and the results $('#discovery .wait, #discovery .disco-category').hide(); } catch(e) { @@ -211,7 +211,7 @@ var Discovery = (function () { try { // Click event $('#discovery .bottom .finish').click(self.close); - + // Keyboard event $('#discovery .disco-server-input').keyup(function(e) { if(e.keyCode == 13) { @@ -219,10 +219,10 @@ var Discovery = (function () { if(!$(this).val()) { $(this).val(HOST_MAIN); } - + // Start the discovery self.start(); - + return false; } }); diff --git a/source/app/javascripts/errors.js b/source/app/javascripts/errors.js index b9f1832..f1a651c 100644 --- a/source/app/javascripts/errors.js +++ b/source/app/javascripts/errors.js @@ -35,33 +35,33 @@ var Errors = (function () { if(condition || reason) { // Initialize the error text var eText = ''; - + // Any error condition if(condition) { eText += condition; } - + // Any error type if(type && eText) { eText += ' (' + type + ')'; } - + // Any error reason if(reason) { if(eText) { eText += ' - '; } - + eText += reason; } - + // We reveal the error Board.openThisError(1); - + // Create the error text $('#board .one-board.error[data-id="1"] span').text(eText); } - + // Not enough data to output the error: output a generic board else { Board.openThisError(2); @@ -87,38 +87,38 @@ var Errors = (function () { // Initialize var type, code, reason, condition; var node = $(packet); - + // First level error (connection error) if(node.is('error')) { // Get the value code = node.attr('code'); - + // Specific error reason switch(code) { case '401': reason = Common._e("Authorization failed"); break; - + case '409': reason = Common._e("Registration failed, please choose a different username"); break; - + case '503': reason = Common._e("Service unavailable"); break; - + case '500': reason = Common._e("Internal server error, try later"); break; - + default: reason = node.find('text').text(); break; } - + // Remove the general wait item (security) Interface.removeGeneralWait(); - + // Show reconnect pane if(Connection.current_session && Connection.connected) { // Anonymous? @@ -128,35 +128,35 @@ var Errors = (function () { Connection.createReconnect('normal'); } } - + // Show the homepage (security) else if(!Connection.current_session || !Connection.connected) { $('#home').show(); Interface.title('home'); } - + // Still connected? (security) if(Common.isConnected()) { con.disconnect(); } - + Console.error('First level error received.'); } - + // Second level error (another error) else if(node.find('error').size()) { type = node.find('error').attr('type'); reason = node.find('error text').text(); condition = packet.getElementsByTagName('error').item(0).childNodes.item(0).nodeName.replace(/-/g, ' '); - + Console.error('Second level error received.'); } else { return false; } - + // Show the error board self.show(condition, reason, type); - + // Return there's an error return true; } catch(e) { diff --git a/source/app/javascripts/favorites.js b/source/app/javascripts/favorites.js index 5ba5112..ffbbe17 100644 --- a/source/app/javascripts/favorites.js +++ b/source/app/javascripts/favorites.js @@ -29,103 +29,103 @@ var Favorites = (function () { try { // Popup HTML content - var html = - '
' + Common._e("Manage favorite rooms") + '
' + - - '
' + - '
' + - '
' + - '
' + - - Common._e("Change favorites") + - '
' + - - '' + - '
' + - - '
' + - '
' + - '
' + - '
' + Common._e("Select a favorite") + '
' + - - '' + - '
' + - - '
' + - '
' + - '' + - - '' + - '
' + - - '
' + - '' + - - '' + - '
' + - - '
' + - '' + - - '' + - '
' + - - '
' + - '' + - - '' + - '
' + - - '
' + - '' + - - '' + - '
' + - - '
' + - '' + - - '' + - '
' + - - '' + - '
' + - '
' + - - '' + - '
' + - '
' + - - '
' + - '
' + - - '' + Common._e("Close") + '' + + var html = + '
' + Common._e("Manage favorite rooms") + '
' + + + '
' + + '
' + + '
' + + '
' + + + Common._e("Change favorites") + + '
' + + + '' + + '
' + + + '
' + + '
' + + '
' + + '
' + Common._e("Select a favorite") + '
' + + + '' + + '
' + + + '
' + + '
' + + '' + + + '' + + '
' + + + '
' + + '' + + + '' + + '
' + + + '
' + + '' + + + '' + + '
' + + + '
' + + '' + + + '' + + '
' + + + '
' + + '' + + + '' + + '
' + + + '
' + + '' + + + '' + + '
' + + + '' + + '
' + + '
' + + + '' + + '
' + + '
' + + + '
' + + '
' + + + '' + Common._e("Close") + '' + '
'; - + // Create the popup Popup.create('favorites', html); - + // Load the favorites self.load(); - + // Associate the events self.instance(); } catch(e) { @@ -144,7 +144,7 @@ var Favorites = (function () { try { var path_sel = $('#favorites'); - + path_sel.find('.wait'); path_sel.find('.fedit-terminate').hide(); path_sel.find('.fedit-add').show(); @@ -196,26 +196,26 @@ var Favorites = (function () { try { // Button path var button_sel = $('#favorites .fsearch-results div[data-xid="' + escape(room_xid) + '"] a.one-button'); - + // Add a remove button instead of the add one button_sel.filter('.add').replaceWith( '' + Common._e("Remove") + '' ); - + // Click event button_sel.filter('.remove').click(function() { return self.removeThis(room_xid, room_name); }); - + // Hide the add button in the (opened?) groupchat $('#' + hex_md5(room_xid) + ' .tools-add').hide(); - + // Add the database entry self.display( room_xid, Common.explodeThis(' (', room_name, 0), Name.getNick(), '0', '' ); - + // Publish the favorites self.publish(); } catch(e) { @@ -239,21 +239,21 @@ var Favorites = (function () { try { // Button path var button_sel = $('#favorites .fsearch-results div[data-xid="' + escape(room_xid) + '"] a.one-button'); - + // Add a remove button instead of the add one button_sel.filter('.remove').replaceWith('' + Common._e("Add") + ''); - + // Click event button_sel.filter('.add').click(function() { return self.addThis(room_xid, room_name); }); - + // Show the add button in the (opened?) groupchat $('#' + hex_md5(room_xid) + ' .tools-add').show(); - + // Remove the favorite self.remove(room_xid, true); - + // Publish the favorites self.publish(); } catch(e) { @@ -275,21 +275,21 @@ var Favorites = (function () { try { // Path to favorites var favorites_sel = $('#favorites'); - + // Reset the favorites self.reset(); - + // Show the edit/remove button, hide the others favorites_sel.find('.fedit-terminate').hide(); favorites_sel.find('.fedit-edit').show(); favorites_sel.find('.fedit-remove').show(); - + // We retrieve the values var xid = favorites_sel.find('.fedit-head-select').val(); var data_sel = $(Common.XMLFromString( DataStore.getDB(Connection.desktop_hash, 'favorites', xid) )); - + // If this is not the default room if(xid != 'none') { // We apply the values @@ -298,7 +298,7 @@ var Favorites = (function () { favorites_sel.find('.fedit-chan').val(Common.getXIDNick(xid)); favorites_sel.find('.fedit-server').val(Common.getXIDHost(xid)); favorites_sel.find('.fedit-password').val(data_sel.find('password').text()); - + if(data_sel.find('autojoin').text() == 'true') { favorites_sel.find('.fedit-autojoin').attr('checked', true); } @@ -321,10 +321,10 @@ var Favorites = (function () { try { // Path to favorites var favorites_sel = $('#favorites'); - + // We get the values of the current edited groupchat var old_xid = favorites_sel.find('.fedit-head-select').val(); - + var title = favorites_sel.find('.fedit-title').val(); var nick = favorites_sel.find('.fedit-nick').val(); var room = favorites_sel.find('.fedit-chan').val(); @@ -332,11 +332,11 @@ var Favorites = (function () { var xid = room + '@' + server; var password = favorites_sel.find('.fedit-password').val(); var autojoin = 'false'; - + if(favorites_sel.find('.fedit-autojoin').filter(':checked').size()) { autojoin = 'true'; } - + // We check the missing values and send this if okay if((type == 'add') || (type == 'edit')) { if(title && nick && room && server) { @@ -344,35 +344,35 @@ var Favorites = (function () { if(type == 'edit') { self.remove(old_xid, true); } - + // Display the favorites self.display(xid, title, nick, autojoin, password); - + // Reset the inputs self.reset(); } else { favorites_sel.find('input[required]').each(function() { var select = $(this); - + if(!select.val()) { $(document).oneTime(10, function() { select.addClass('please-complete').focus(); }); } else { - select.removeClass('please-complete'); + select.removeClass('please-complete'); } }); } } else if(type == 'remove') { self.remove(old_xid, true); - + // Reset the inputs self.reset(); } - + // Publish the new favorites self.publish(); - + Console.info('Action on this bookmark: ' + room + '@' + server + ' / ' + type); } catch(e) { Console.error('Favorites.terminateThis', e); @@ -396,7 +396,7 @@ var Favorites = (function () { // We remove the target favorite everywhere needed $('.buddy-conf-groupchat-select option[value="' + xid + '"]').remove(); $('.fedit-head-select option[value="' + xid + '"]').remove(); - + // Must remove it from database? if(database) { DataStore.removeDB(Connection.desktop_hash, 'favorites', xid); @@ -418,19 +418,19 @@ var Favorites = (function () { try { var iq = new JSJaCIQ(); iq.setType('set'); - + var query = iq.setQuery(NS_PRIVATE); var storage = query.appendChild(iq.buildNode('storage', { 'xmlns': NS_BOOKMARKS })); - + // We generate the XML var db_regex = new RegExp(('^' + Connection.desktop_hash + '_') + 'favorites_(.+)'); 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 favorite if(current.match(db_regex)) { var data_sel = $(Common.XMLFromString( @@ -442,7 +442,7 @@ var Favorites = (function () { var nick = data_sel.find('nick').text(); var password = data_sel.find('password').text(); var autojoin = data_sel.find('autojoin').text(); - + // We create the node for this groupchat var item = storage.appendChild( iq.buildNode('conference', { @@ -452,21 +452,21 @@ var Favorites = (function () { xmlns: NS_BOOKMARKS }) ); - + item.appendChild(iq.buildNode('nick', { xmlns: NS_BOOKMARKS }, nick)); - + if(password) { item.appendChild(iq.buildNode('password', { xmlns: NS_BOOKMARKS }, password)); } - + Console.info('Bookmark sent: ' + xid); } } - + con.send(iq); } catch(e) { Console.error('Favorites.publish', e); @@ -485,18 +485,18 @@ var Favorites = (function () { try { var path_sel = $('#favorites'); var groupchat_server = $('.fsearch-head-server').val(); - + // We reset some things path_sel.find('.fsearch-oneresult').remove(); path_sel.find('.fsearch-noresults').hide(); path_sel.find('.wait').show(); - + var iq = new JSJaCIQ(); iq.setType('get'); iq.setTo(groupchat_server); - + iq.setQuery(NS_DISCO_ITEMS); - + con.send(iq, self.handleGCList); } catch(e) { Console.error('Favorites.getGCList', e); @@ -516,69 +516,69 @@ var Favorites = (function () { try { var path_sel = $('#favorites'); var from = Common.fullXID(Common.getStanzaFrom(iq)); - + if(!iq || (iq.getType() != 'result')) { Board.openThisError(3); - + path_sel.find('.wait').hide(); - + Console.error('Error while retrieving the rooms: ' + from); } - + else { var handleXML = iq.getQuery(); - + if($(handleXML).find('item').size()) { // Initialize the HTML code var html = ''; - + $(handleXML).find('item').each(function() { var this_sel = $(this); var room_xid = this_sel.attr('jid'); var room_name = this_sel.attr('name'); - + if(room_xid && room_name) { // Escaped values var escaped_xid = Utils.encodeOnclick(room_xid); var escaped_name = Utils.encodeOnclick(room_name); - + // Initialize the room HTML - html += '
' + - '
' + room_name.htmlEnc() + '
' + + html += '
' + + '
' + room_name.htmlEnc() + '
' + '' + Common._e("Join") + ''; - + // This room is yet a favorite if(DataStore.existDB(Connection.desktop_hash, 'favorites', room_xid)) { - html += '' + - Common._e("Remove") + + html += '' + + Common._e("Remove") + ''; } else { - html += '' + - Common._e("Add") + + html += '' + + Common._e("Add") + ''; } - + // Close the room HTML html += '
'; } }); - + // Append this code to the popup path_sel.find('.fsearch-results').append(html); } else { path_sel.find('.fsearch-noresults').show(); } - + Console.info('Rooms retrieved: ' + from); } - + path_sel.find('.wait').hide(); } catch(e) { Console.error('Favorites.handleGCList', e); @@ -629,20 +629,20 @@ var Favorites = (function () { try { // Generate the HTML code var html = ''; - + // Remove the existing favorite self.remove(xid, false); - + // We complete the select forms $('#roster .gc-join-first-option, #favorites .fedit-head-select-first-option').after(html); - + // We store the informations - var value = '' + - '' + xid.htmlEnc() + '' + - '' + name.htmlEnc() + '' + - '' + nick.htmlEnc() + '' + - '' + autojoin.htmlEnc() + '' + - '' + password.htmlEnc() + '' + + var value = '' + + '' + xid.htmlEnc() + '' + + '' + name.htmlEnc() + '' + + '' + nick.htmlEnc() + '' + + '' + autojoin.htmlEnc() + '' + + '' + password.htmlEnc() + '' + ''; DataStore.setDB(Connection.desktop_hash, 'favorites', xid, value); @@ -663,34 +663,34 @@ var Favorites = (function () { try { // Initialize the HTML code var html = ''; - + // Read the database var db_regex = new RegExp(('^' + Connection.desktop_hash + '_') + 'favorites_(.+)'); 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 favorite if(current.match(db_regex)) { var data = Common.XMLFromString(DataStore.storageDB.getItem(current)); - + // Add the current favorite to the HTML code - html += ''; } } - + // Generate specific HTML code - var favorites_bubble = '' + html; - var favorites_popup = '' + html; - + // Append the HTML code $('#roster .buddy-conf-groupchat-select').html(favorites_bubble); $('#favorites .fedit-head-select').html(favorites_popup); @@ -710,22 +710,22 @@ var Favorites = (function () { try { var favorites_sel = $('#favorites'); - + // Keyboard events favorites_sel.find('.fsearch-head-server').keyup(function(e) { if(e.keyCode == 13) { var this_sel = $(this); - + // No value? if(!this_sel.val()) { this_sel.val(HOST_MUC); } - + // Get the list self.getGCList(); } }); - + favorites_sel.find('.fedit-line input').keyup(function(e) { if(e.keyCode == 13) { // Edit a favorite @@ -736,37 +736,37 @@ var Favorites = (function () { } } }); - + // Change events $('.fedit-head-select').change(self.edit); - + // Click events favorites_sel.find('.room-switcher').click(function() { favorites_sel.find('.favorites-content').hide(); self.reset(); }); - + favorites_sel.find('.room-list').click(function() { favorites_sel.find('.favorites-edit').show(); }); - + favorites_sel.find('.room-search').click(function() { favorites_sel.find('.favorites-search').show(); self.getGCList(); }); - + favorites_sel.find('.fedit-add').click(function() { return self.terminateThis('add'); }); - + favorites_sel.find('.fedit-edit').click(function() { return self.terminateThis('edit'); }); - + favorites_sel.find('.fedit-remove').click(function() { return self.terminateThis('remove'); }); - + favorites_sel.find('.bottom .finish').click(function() { return self.quit(); }); diff --git a/source/app/javascripts/features.js b/source/app/javascripts/features.js index fb0455b..2e7ba1e 100644 --- a/source/app/javascripts/features.js +++ b/source/app/javascripts/features.js @@ -50,29 +50,29 @@ var Features = (function () { var to = Utils.getServer(); var caps = con.server_caps; var xml = null; - + // Try to get the stored data if(caps) { xml = Common.XMLFromString( DataStore.getPersistent('global', 'caps', caps) ); } - + // Any stored data? if(xml) { self.handle(xml); - + Console.log('Read server CAPS from cache.'); } else { // Not stored (or no CAPS)! var iq = new JSJaCIQ(); - + iq.setTo(to); iq.setType('get'); iq.setQuery(NS_DISCO_INFO); - + con.send(iq, Caps.handleDiscoInfos); - + Console.log('Read server CAPS from network.'); } } catch(e) { @@ -93,7 +93,7 @@ var Features = (function () { try { // Selector var selector = $(xml); - + // Functions var check_feature_fn = function(namespace) { // This weird selector fixes an IE8 bug... @@ -137,21 +137,21 @@ var Features = (function () { // Get the PEP nodes to initiate Microblog.getInit(); PEP.getInitGeoloc(); - + // Get the notifications Notification.get(); - + // Geolocate the user PEP.geolocate(); - + // Enable microblogging send tools Microblog.wait('sync'); $('.postit.attach').css('display', 'block'); - + Console.info('XMPP server supports PEP.'); } else { Microblog.wait('unsync'); - + Console.warn('XMPP server does not support PEP.'); } @@ -159,10 +159,10 @@ var Features = (function () { if(features.pep === false && features[NS_URN_MAM] === false) { $('#options fieldset.privacy').hide(); } - + // Apply the features self.apply('talk'); - + // Process the roster height if(features.pep === true) { Roster.adapt(); @@ -192,12 +192,12 @@ var Features = (function () { try { // Path to the elements var path = '#' + id + ' .'; - + // PEP features if(self.enabledPEP()) { $(path + 'pep-hidable').show(); } - + // PubSub features if(self.enabledPubSub()) { $(path + 'pubsub-hidable').show(); @@ -207,7 +207,7 @@ var Features = (function () { if(self.enabledPubSubCN()) { $(path + 'pubsub-hidable-cn').show(); } - + // MAM features if(self.enabledMAM()) { $(path + 'mam-hidable').show(); @@ -223,12 +223,12 @@ var Features = (function () { if(self.enabledCorrection()) { $(path + 'correction-hidable').show(); } - + // Commands features if(self.enabledCommands()) { $(path + 'commands-hidable').show(); } - + // XMPP links (browser feature) if(navigator.registerProtocolHandler) { $(path + 'xmpplinks-hidable').show(); diff --git a/source/app/javascripts/filter.js b/source/app/javascripts/filter.js index a06e254..bda2f2e 100644 --- a/source/app/javascripts/filter.js +++ b/source/app/javascripts/filter.js @@ -285,7 +285,7 @@ var Filter = (function () { 'ul', 'var' ], - + 'attributes': [ 'accesskey', 'alt', @@ -345,17 +345,17 @@ var Filter = (function () { try { var filtered = message; - + // We encode the HTML special chars if(html_escape) { filtered = filtered.htmlEnc(); } - + // Security: don't filter huge messages (avoids crash attacks) if(filtered.length < 10000) { // /me command filtered = filtered.replace(self.message_regex.commands.me, nick + ' $7'); - + // We replace the smilies text into images var cur_emote; @@ -371,7 +371,7 @@ var Filter = (function () { ) ); } - + // Text formatting var cur_formatting; @@ -388,11 +388,11 @@ var Filter = (function () { if(html_escape) { filtered = Links.apply(filtered, 'desktop'); } - + // Filter integratebox links filtered = IntegrateBox.filter(filtered); } - + return filtered; } catch(e) { Console.error('Filter.message', e); @@ -401,6 +401,32 @@ var Filter = (function () { }; + /** + * Returns whether XHTML body exists or not + * @public + * @param {DOM} xhtml_sel + * @return {boolean} + */ + self.has_xhtml_body = function(xhtml_sel) { + + var has_xhtml_body = false; + + try { + xhtml_sel.find('*').each(function() { + if($(this).text()) { + has_xhtml_body = true; + return false; + } + }); + } catch(e) { + Console.error('Filter.has_xhtml_body', e); + } finally { + return has_xhtml_body; + } + + }; + + /** * Filters a xHTML message to be displayed in Jappix * @public @@ -411,12 +437,12 @@ var Filter = (function () { try { var code_sel = $(code); - + // Check if Filter for XHTML-IM images is enabled if(DataStore.getDB(Connection.desktop_hash, 'options', 'no-xhtml-images') != '1') { self.xhtml_allow.elements.push("img"); } - + // Remove forbidden elements code_sel.find('html body *').each(function() { // This element is not authorized @@ -424,31 +450,31 @@ var Filter = (function () { $(this).remove(); } }); - + // Remove forbidden attributes code_sel.find('html body *').each(function() { // Put a pointer on this element (jQuery way & normal way) var cSelector = $(this); var cElement = (this); - + // Loop the attributes of the current element $(cElement.attributes).each(function(index) { // Read the current attribute var cAttr = cElement.attributes[index]; var cName = cAttr.name; var cVal = cAttr.value; - + // This attribute is not authorized, or contains JS code - if(!Utils.existArrayValue(self.xhtml_allow.attributes, cName.toLowerCase()) || + if(!Utils.existArrayValue(self.xhtml_allow.attributes, cName.toLowerCase()) || ((cVal.toLowerCase()).match(/(^|"|')javascript:/))) { cSelector.removeAttr(cName); } }); }); - + // Filter some other elements code_sel.find('a').attr('target', '_blank'); - + return code_sel.find('html body').html(); } catch(e) { Console.error('Filter.xhtml', e); diff --git a/source/app/javascripts/groupchat.js b/source/app/javascripts/groupchat.js index ccf9a0e..21ed7da 100644 --- a/source/app/javascripts/groupchat.js +++ b/source/app/javascripts/groupchat.js @@ -21,7 +21,7 @@ var Groupchat = (function () { /* Variables */ - var JOIN_SUGGEST = []; + self.join_suggest = []; /** @@ -58,11 +58,11 @@ var Groupchat = (function () { 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! @@ -111,12 +111,12 @@ var Groupchat = (function () { } else { // Send the message Message.send(hash, 'groupchat'); - + // Reset the composing database entry DataStore.setDB(Connection.desktop_hash, 'chatstate', room, 'off'); } } - + return false; } @@ -127,14 +127,14 @@ var Groupchat = (function () { 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); @@ -175,17 +175,17 @@ var Groupchat = (function () { // 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); @@ -193,18 +193,20 @@ var Groupchat = (function () { 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')); + self.join_suggest.push( + $(this).attr('data-xid') + ); }); } - + // Switch to talk UI $('#suggest').remove(); Connection.triggerConnected(); - + return false; }); } catch(e) { @@ -230,17 +232,17 @@ var Groupchat = (function () { 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); @@ -265,11 +267,11 @@ var Groupchat = (function () { 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 @@ -278,22 +280,22 @@ var Groupchat = (function () { } 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); } @@ -322,50 +324,49 @@ var Groupchat = (function () { 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); @@ -392,34 +393,34 @@ var Groupchat = (function () { 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( - '
' + - '' + - '' + + '
' + + '' + + '' + '
' ); - + // When a key is pressed in the input $(path_to + ' input').keyup(function(e) { var value_input = $(this).val(); - + // Enter key pressed if(e.keyCode == 13) { // $.trim() fixes #304 @@ -427,14 +428,14 @@ var Groupchat = (function () { nickname = $.trim(value_input); return self.getMUC(room, nickname, password); } - + if(type == 'password' && value_input) { password = value_input; return self.getMUC(room, nickname, password); } } }); - + // Focus on the input $(document).oneTime(10, function() { $(path_to + ' input').focus(); @@ -462,37 +463,37 @@ var Groupchat = (function () { try { Console.info('New groupchat: ' + room); - + // Create the chat content Chat.generate('groupchat', hash, room, chan); - + // Create the chat switcher Chat.generateSwitch('groupchat', hash, room, chan); - + // The icons-hover functions Tooltip.icons(room, hash); - + // Click event on the add tool $('#' + hash + ' .tools-add').click(function() { // Hide the icon (to tell the user all is okay) $(this).hide(); - + // Add the groupchat to the user favorites Favorites.addThis(room, chan); }); - + // Must show the add button? if(!DataStore.existDB(Connection.desktop_hash, 'favorites', room)) { $('#' + hash + ' .tools-add').show(); } - + // The event handlers var input_sel = $('#' + hash + ' .message-area'); self._createEvents(input_sel, hash, room); - + // Chatstate events ChatState.events(input_sel, room, hash, 'groupchat'); - + // Get the current muc informations and content self.getMUC(room, nickname, password); } catch(e) { @@ -513,30 +514,30 @@ var Groupchat = (function () { // Values array var muc_arr = [GROUPCHATS_JOIN]; var new_arr = []; - + // Try to split it if(GROUPCHATS_JOIN.indexOf(',') != -1) { muc_arr = GROUPCHATS_JOIN.split(','); } - + for(var i in muc_arr) { // Get the current value var muc_current = $.trim(muc_arr[i]); - + // No current value? if(!muc_current) { continue; } - + // Filter the current value muc_current = Common.generateXID(muc_current, 'groupchat'); - + // Add the current value if(!Utils.existArrayValue(new_arr, muc_current)) { new_arr.push(muc_current); } } - + return new_arr; } catch(e) { Console.error('Groupchat.arrayJoin', e); @@ -554,14 +555,14 @@ var Groupchat = (function () { try { // Nothing to join? - if(!JOIN_SUGGEST) { + if(!self.join_suggest) { return; } - + // Join the chats - if(JOIN_SUGGEST.length) { - for(var g in JOIN_SUGGEST) { - Chat.checkCreate(JOIN_SUGGEST[g], 'groupchat'); + if(self.join_suggest.length) { + for(var g in self.join_suggest) { + Chat.checkCreate(self.join_suggest[g], 'groupchat'); } } } catch(e) { @@ -580,17 +581,17 @@ var Groupchat = (function () { try { var groupchat_arr = self.arrayJoin(); - + // Must suggest the user? if((GROUPCHATS_SUGGEST == 'on') && groupchat_arr.length) { if(Common.exists('#suggest')) { return; } - + // Create HTML code var html = '
'; html += '
' + Common._e("Suggested chatrooms") + '
'; - + html += '
'; for(var g in groupchat_arr) { html += ''; @@ -601,21 +602,21 @@ var Groupchat = (function () { html += ''; } html += '
'; - + html += '
'; html += ''; html += ''; html += '
'; html += '
'; - + // Append HTML code $('body').append(html); - + // Attach events self._suggestCheckEvents(); } else { - JOIN_SUGGEST = groupchat_arr; - + self.join_suggest = groupchat_arr; + Connection.triggerConnected(); } } catch(e) { @@ -646,20 +647,20 @@ var Groupchat = (function () { var iq = new JSJaCIQ(); iq.setTo(room_xid); iq.setType('set'); - + var iqQuery = iq.setQuery(NS_MUC_ADMIN); var item = iqQuery.appendChild(iq.buildNode('item', { 'affiliation': 'outcast', 'jid': ban_xid, 'xmlns': NS_MUC_ADMIN })); - + if(reason) { item.appendChild(iq.buildNode('reason', { 'xmlns': NS_MUC_ADMIN }, reason)); } - + con.send(iq, Errors.handleReply); Console.log('Banned user with XID: ' + ban_xid + ' from room: ' + room_xid); @@ -693,20 +694,20 @@ var Groupchat = (function () { var iq = new JSJaCIQ(); iq.setTo(room_xid); iq.setType('set'); - + var iqQuery = iq.setQuery(NS_MUC_ADMIN); var item = iqQuery.appendChild(iq.buildNode('item', { 'nick': nick, 'role': 'none', 'xmlns': NS_MUC_ADMIN })); - + if(reason) { item.appendChild(iq.buildNode('reason', { 'xmlns': NS_MUC_ADMIN }, reason)); } - + con.send(iq, Errors.handleReply); Console.info('Kicked user "' + nick + '" from room: ' + room_xid); @@ -810,7 +811,7 @@ var Groupchat = (function () { } }; - + /** * Sends initial configuration of the room * @private @@ -834,7 +835,7 @@ var Groupchat = (function () { 'xmlns': NS_XDATA, 'type': 'submit' })); - + // Build a new field node var iqField = iqX.appendChild(iq.buildNode('field', { 'var': 'FORM_TYPE', @@ -844,7 +845,7 @@ var Groupchat = (function () { iqField.appendChild(iq.buildNode('value', { 'xmlns': NS_XDATA - }, NS_MUC_CONFIG)); + }, NS_MUC_CONFIG)); con.send(iq); @@ -853,7 +854,7 @@ var Groupchat = (function () { Console.error('Groupchat._initialConfiguration', e); } }; - + /** diff --git a/source/app/javascripts/home.js b/source/app/javascripts/home.js index b66f29c..06f8672 100644 --- a/source/app/javascripts/home.js +++ b/source/app/javascripts/home.js @@ -37,26 +37,26 @@ var Home = (function () { current_sel.find('a.to-anonymous').click(function() { return self.change('anonymouser'); }); - + current_sel.find('a.advanced').click(self.showAdvanced); current_sel.find('form').submit(self.loginForm); - + break; - + // Anonymous login tool case 'anonymouser': current_sel.find('a.to-home').click(function() { return self.change('loginer'); }); - + current_sel.find('form').submit(Connection.doAnonymous); - + // Keyup event on anonymous join's room input current_sel.find('input.room').keyup(function() { var value = $(this).val(); var report_sel = current_sel.find('.report'); var span_sel = current_sel.find('span'); - + if(!value) { report_sel.hide(); span_sel.text(''); @@ -65,9 +65,9 @@ var Home = (function () { span_sel.text(JAPPIX_LOCATION + '?r=' + value); } }); - + break; - + // Register tool case 'registerer': // Server input change @@ -80,14 +80,14 @@ var Home = (function () { $('#home input.captcha').attr('disabled', true); } }); - + // Register input placeholder // FIXME: breaks IE compatibility //$('#home input[placeholder]').placeholder(); - + // Register form submit current_sel.find('form').submit(self.registerForm); - + break; } } catch(e) { @@ -109,22 +109,22 @@ var Home = (function () { try { // Add the code $(locale).after( - '
' + - '

' + Common._e("Your browser is out of date!") + '

' + - - '' + - '' + - '' + - '' + - '' + + '
' + + '

' + Common._e("Your browser is out of date!") + '

' + + + '' + + '' + + '' + + '' + + '' + '
' ); - + // Display it later $(home + '.obsolete').oneTime('1s', function() { $(this).slideDown(); }); - + Console.warn('Jappix does not support this browser!'); } catch(e) { Console.error('Home._obsolete', e); @@ -146,19 +146,19 @@ var Home = (function () { var home = '#home .'; var right = home + 'right '; var current = right + '.homediv.' + div; - + // We switch the div $(right + '.homediv, ' + right + '.top').hide(); $(right + '.' + div).show(); - + // We reset the homedivs $(home + 'homediv:not(.default), ' + home + 'top:not(.default)').remove(); - + // Get the HTML code to display var disable_form = ''; var lock_host = ''; var code = ''; - + // Apply the previous link switch(div) { case 'loginer': @@ -167,144 +167,144 @@ var Home = (function () { if(!Common.exists(right + '.top.sub')) { // Append the HTML code for previous link $(right + '.top.default').after('

«

'); - + // Click event on previous link $(home + 'top.sub a.previous').click(function() { return self.change('default'); }); } - + break; } - + // Apply the form switch(div) { // Login tool case 'loginer': lock_host = Utils.disableInput(LOCK_HOST, 'on'); - code = '

' + Common.printf(Common._e("Login to your existing XMPP account. You can also use the %s to join a groupchat."), '' + Common._e("anonymous mode") + '') + '

' + - - '
' + - '
' + - '' + Common._e("Required") + '' + - - '' + - '@' + - '' + - '' + - '' + - '' + - '
' + - - '' + Common._e("Advanced") + '' + - - '
' + - '' + Common._e("Advanced") + '' + - - '' + - '' + - '' + - '' + - '
' + - - '
' + - '' + + code = '

' + Common.printf(Common._e("Login to your existing XMPP account. You can also use the %s to join a groupchat."), '' + Common._e("anonymous mode") + '') + '

' + - '
' + - '
' + + '' + + '
' + + '' + Common._e("Required") + '' + + + '' + + '@' + + '' + + '' + + '' + + '' + + '
' + + + '' + Common._e("Advanced") + '' + + + '
' + + '' + Common._e("Advanced") + '' + + + '' + + '' + + '' + + '' + + '
' + + + '
' + + '' + + + '
' + + '
' + '
'; - + break; - + // Anonymous login tool case 'anonymouser': disable_form = Utils.disableInput(ANONYMOUS, 'off'); code = '

' + Common.printf(Common._e("Enter the groupchat you want to join and the nick you want to have. You can also go back to the %s."), '' + Common._e("login page") + '') + '

'; - + if(LEGAL) { code += '

' + Common.printf(Common._e("By using our service, you accept %s."), '' + Common._e("our terms of use") + '') + '

'; } - - code += '
' + - '
' + - '' + Common._e("Required") + '' + - - '' + - '' + - - '' + - '' + - '
' + - - '' + - '
' + - - '
' + - Common._e("Share this link with your friends:") + ' ' + + + code += '
' + + '
' + + '' + Common._e("Required") + '' + + + '' + + '' + + + '' + + '' + + '
' + + + '' + + '
' + + + '
' + + Common._e("Share this link with your friends:") + ' ' + '
'; - + break; - + // Register tool case 'registerer': disable_form = Utils.disableInput(REGISTRATION, 'off'); - + if(!disable_form) { lock_host = Utils.disableInput(LOCK_HOST, 'on'); } - + code = '

' + Common._e("Register a new XMPP account to join your friends on your own social cloud. That's simple!") + '

'; - + if(LEGAL) { code += '

' + Common.printf(Common._e("By using our service, you accept %s."), '' + Common._e("our terms of use") + '') + '

'; } - - code += '
' + - '
' + - '' + Common._e("Required") + '' + - - '' + - '@' + - '' + + + code += '' + + '
' + + '' + Common._e("Required") + '' + + + '' + + '@' + + '' + ''; - + if(REGISTER_API == 'on') { - code += '
' + - '' + + code += '
' + + '' + '
'; } - - code += '
' + - - '' + + + code += '
' + + + '' + '
'; - + break; } - + // Form disabled? if(disable_form) { - code += '
' + - Common._e("This tool has been disabled!") + + code += '
' + + Common._e("This tool has been disabled!") + '
'; } - + // Create this HTML code if(code && !Common.exists(current)) { $(right + '.homediv.default').after( '
' + code + '
' ); - + self._eventsChange( $(current), div ); } - + // We focus on the first input $(document).oneTime(10, function() { $(right + 'input:visible:first').focus(); @@ -328,7 +328,7 @@ var Home = (function () { try { // Hide the link $('#home a.advanced').hide(); - + // Show the fieldset $('#home fieldset.advanced').show(); } catch(e) { @@ -357,20 +357,20 @@ var Home = (function () { var lResource = path_sel.find('.resource').val(); var lPriority = path_sel.find('.priority').val(); var lRemember = path_sel.find('.remember').filter(':checked').size(); - + // Enough values? if(lServer && lNick && lPass && lResource && lPriority) { Connection.doLogin(lNick, lServer, lPass, lResource, lPriority, lRemember); } else { $(lPath + 'input[type="text"], ' + lPath + 'input[type="password"]').each(function() { var select = $(this); - + if(!select.val()) { $(document).oneTime(10, function() { select.addClass('please-complete').focus(); }); } else { - select.removeClass('please-complete'); + select.removeClass('please-complete'); } }); } @@ -393,37 +393,37 @@ var Home = (function () { try { var path = '#home .registerer'; var path_sel = $(path); - + // Remove the success info path_sel.find('.success').remove(); - + // Get the values var username = Common.nodeprep(path_sel.find('.nick').val()); var domain = path_sel.find('.server').val(); var pass = path_sel.find('.password').val(); var spass = path_sel.find('.spassword').val(); var captcha = path_sel.find('.captcha').val(); - + // Enough values? if(domain && username && pass && spass && (pass == spass) && !((REGISTER_API == 'on') && (domain == HOST_MAIN) && !captcha)) { // We remove the not completed class to avoid problems $('#home .registerer input').removeClass('please-complete'); - + // Fire the register event! Connection.doRegister(username, domain, pass, captcha); } - + // Something is missing? else { $(path + ' input[type="text"], ' + path + ' input[type="password"]').each(function() { var select = $(this); - + if(!select.val() || (select.is('#spassword') && pass && (pass != spass))) { $(document).oneTime(10, function() { select.addClass('please-complete').focus(); }); } else { - select.removeClass('please-complete'); + select.removeClass('please-complete'); } }); } @@ -452,61 +452,61 @@ var Home = (function () { var corp = home + '.corporation'; var aboutus = home + '.aboutus'; var locale = home + '.locale'; - + // Removes the