Procházet zdrojové kódy

Merge branch 'master' into plugins-refactor

JC Brand před 10 roky
rodič
revize
334f095774

+ 8 - 1
.gitignore

@@ -15,7 +15,6 @@ analytics.js
 .sass-cache
 .sass-cache
 ruby
 ruby
 bourbon
 bourbon
-Gemfile.lock
 
 
 Backbone.Overview
 Backbone.Overview
 tags
 tags
@@ -41,3 +40,11 @@ develop-eggs
 
 
 # OSX
 # OSX
 .DS_Store
 .DS_Store
+
+# Builds
+converse-no-locales-no-otr.js
+converse-no-locales-no-otr.min.js
+converse-no-otr.js
+converse-no-otr.min.js
+converse.nojquery.js
+converse.nojquery.min.js

+ 15 - 0
Gemfile.lock

@@ -0,0 +1,15 @@
+GEM
+  remote: https://rubygems.org/
+  specs:
+    bourbon (4.2.1)
+      sass (~> 3.4)
+      thor
+    sass (3.4.13)
+    thor (0.19.1)
+
+PLATFORMS
+  ruby
+
+DEPENDENCIES
+  bourbon
+  sass (~> 3.3)

+ 3 - 3
Makefile

@@ -16,7 +16,7 @@ ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) ./d
 # the i18n builder cannot share the environment and doctrees with the others
 # the i18n builder cannot share the environment and doctrees with the others
 I18NSPHINXOPTS  = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) ./docs/source
 I18NSPHINXOPTS  = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) ./docs/source
 
 
-.PHONY: all help clean html epub changes linkcheck gettext po pot po2json merge release css minjs build dev-ruby
+.PHONY: all help clean html epub changes linkcheck gettext po pot po2json merge release css minjs build
 
 
 help:
 help:
 	@echo "Please use \`make <target>' where <target> is one of the following:"
 	@echo "Please use \`make <target>' where <target> is one of the following:"
@@ -103,10 +103,10 @@ dev: stamp-bower stamp-bundler
 ########################################################################
 ########################################################################
 ## Builds
 ## Builds
 
 
-css:: dev-ruby
+css:: stamp-bundler
 	$(SASS) -I .bundle/bin sass/converse.scss css/converse.css
 	$(SASS) -I .bundle/bin sass/converse.scss css/converse.css
 
 
-watch:: dev-ruby
+watch:: stamp-bundler
 	$(SASS) --watch -I .bundle/bin sass/converse.scss:css/converse.css
 	$(SASS) --watch -I .bundle/bin sass/converse.scss:css/converse.css
 
 
 jsmin:
 jsmin:

+ 5 - 4
README.rst

@@ -26,15 +26,16 @@ It has the following features:
 * In-band registration `XEP 77 <http://xmpp.org/extensions/xep-0077.html>`_
 * In-band registration `XEP 77 <http://xmpp.org/extensions/xep-0077.html>`_
 * Contact rosters and groups
 * Contact rosters and groups
 * Contact subscriptions
 * Contact subscriptions
-* Accept or decline contact requests
 * Roster item exchange `XEP 144 <http://xmpp.org/extensions/tmp/xep-0144-1.1.html>`_
 * Roster item exchange `XEP 144 <http://xmpp.org/extensions/tmp/xep-0144-1.1.html>`_
 * Chat statuses (online, busy, away, offline)
 * Chat statuses (online, busy, away, offline)
 * Custom status messages
 * Custom status messages
+* Typing and state notifications `XEP 85 <http://xmpp.org/extensions/xep-0085.html>`_
 * Messages appear in all connnected chat clients `XEP 280 <http://xmpp.org/extensions/xep-0280.html>`_
 * Messages appear in all connnected chat clients `XEP 280 <http://xmpp.org/extensions/xep-0280.html>`_
-* Typing and chat state notifications `XEP 85 <http://xmpp.org/extensions/xep-0085.html>`_
-* Third person messages (/me )
-* Translated into 16 languages
+* Third person "/me" messages `XEP 245 <http://xmpp.org/extensions/xep-0245.html>`_
+* XMPP Ping `XEP 199 <http://xmpp.org/extensions/xep-0199.html>`_
+* Client state indication `XEP 352 <http://xmpp.org/extensions/xep-0352.html>`_
 * Off-the-record encryption
 * Off-the-record encryption
+* Translated into 16 languages
 
 
 -----------
 -----------
 Screencasts
 Screencasts

+ 1 - 1
bower.json

@@ -2,7 +2,7 @@
   "name": "converse.js",
   "name": "converse.js",
   "description": "Web-based XMPP/Jabber chat client written in javascript",
   "description": "Web-based XMPP/Jabber chat client written in javascript",
   "version": "0.9.3",
   "version": "0.9.3",
-  "license": "MPL",
+  "license": "MPL-2.0",
   "devDependencies": {
   "devDependencies": {
     "jasmine": "https://github.com/jcbrand/jasmine.git#1_3_x",
     "jasmine": "https://github.com/jcbrand/jasmine.git#1_3_x",
     "otr": "0.2.12",
     "otr": "0.2.12",

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 0 - 14555
builds/converse-no-locales-no-otr.js


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 0 - 203
builds/converse-no-locales-no-otr.min.js


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 0 - 14555
builds/converse-no-otr.js


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 0 - 203
builds/converse-no-otr.min.js


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 0 - 4221
builds/converse.nojquery.js


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 0 - 203
builds/converse.nojquery.min.js


+ 191 - 28
converse.js

@@ -156,6 +156,7 @@
         Strophe.addNamespace('REGISTER', 'jabber:iq:register');
         Strophe.addNamespace('REGISTER', 'jabber:iq:register');
         Strophe.addNamespace('ROSTERX', 'http://jabber.org/protocol/rosterx');
         Strophe.addNamespace('ROSTERX', 'http://jabber.org/protocol/rosterx');
         Strophe.addNamespace('XFORM', 'jabber:x:data');
         Strophe.addNamespace('XFORM', 'jabber:x:data');
+        Strophe.addNamespace('CSI', 'urn:xmpp:csi:0');
 
 
         // Add Strophe Statuses
         // Add Strophe Statuses
         var i = 0;
         var i = 0;
@@ -215,7 +216,36 @@
 
 
         // Translation machinery
         // Translation machinery
         // ---------------------
         // ---------------------
-        this.i18n = settings.i18n ? settings.i18n : locales.en;
+        this.isAvailableLocale = function (locale) {
+            ret = null;
+            if (locales[locale]) {
+                ret = locales[locale];
+            } else{
+                sublocale=locale.split("-")[0];
+                if (sublocale!=locale && locales[sublocale]) {
+                    ret=locales[sublocale];
+                }
+            }
+            return ret;
+        };
+		
+        this.detectLocale = function () {
+            ret = null;
+            if (window.navigator.userLanguage) {
+                ret = this.isAvailableLocale(window.navigator.userLanguage);
+            } else if (window.navigator.languages && !ret) {
+                for (var i = 0; i < window.navigator.languages.length && !ret; i++) {
+                    ret = this.isAvailableLocale(window.navigator.languages[i]);
+                }
+            }
+            else if (window.navigator.browserLanguage && !ret) ret = this.isAvailableLocale(window.navigator.browserLanguage);
+            else if (window.navigator.language && !ret) ret = this.isAvailableLocale(window.navigator.language);
+            else if (window.navigator.systemLanguage && !ret) ret = this.isAvailableLocale(window.navigator.systemLanguage);
+            else { ret = locales.en; }
+            return ret;
+        };
+        this.i18n = settings.i18n ? settings.i18n : this.detectLocale();
+
         var __ = $.proxy(utils.__, this);
         var __ = $.proxy(utils.__, this);
         var ___ = utils.___;
         var ___ = utils.___;
 
 
@@ -228,6 +258,8 @@
             allow_logout: true,
             allow_logout: true,
             allow_muc: true,
             allow_muc: true,
             allow_otr: true,
             allow_otr: true,
+            auto_away: 0, //in seconds
+            auto_xa: 0, //in seconds
             allow_registration: true,
             allow_registration: true,
             animate: true,
             animate: true,
             auto_list_rooms: false,
             auto_list_rooms: false,
@@ -247,6 +279,7 @@
             keepalive: false,
             keepalive: false,
             message_carbons: false,
             message_carbons: false,
             no_trimming: false, // Set to true for phantomjs tests (where browser apparently has no width)
             no_trimming: false, // Set to true for phantomjs tests (where browser apparently has no width)
+            ping_interval: 180, //in seconds
             play_sounds: false,
             play_sounds: false,
             sounds_path: '/sounds/',
             sounds_path: '/sounds/',
             password: undefined,
             password: undefined,
@@ -351,9 +384,60 @@
 
 
         // Module-level functions
         // Module-level functions
         // ----------------------
         // ----------------------
+
+        this.sendCSI = function (stat) {
+            if (converse.features[Strophe.NS.CSI]) {
+                converse.connection.send($build(stat, {xmlns: Strophe.NS.CSI}));
+            }
+        };
+        this.autoAwayReset = function () {
+            if (converse._idleCounter > 0) {
+                converse._idleCounter = 0;
+                if (converse._autoAway > 0) {
+                    converse._autoAway = 0;
+                    converse.sendCSI(ACTIVE);
+                    converse.xmppstatus.setStatus('online');
+                }
+            }
+        };
+        this.registerAutoAwayHandler = function () {
+            // TODO: we should probably come up with a way to decouple CSI and auto-away
+            if (this.auto_away > 0 || this.auto_xa > 0) {
+                if (this.auto_xa > 0 && this.auto_xa < this.auto_away) {
+                    this.auto_xa = this.auto_away;
+                }
+                this._idleCounter = 0;
+                this._autoAway = 0;
+                $(window).on('click' , function () { converse.autoAwayReset(); });
+                $(window).on('mousemove' , function () { converse.autoAwayReset(); });
+                $(window).on('keypress' , function () { converse.autoAwayReset(); });
+                $(window).on('focus' , function () { converse.autoAwayReset(); });
+                $(window).on('beforeunload' , function () { converse.autoAwayReset(); });
+
+                window.setInterval(function () {
+                    if ((this._idleCounter <= this.auto_away || (this.auto_xa > 0 && this._idleCounter <= this.auto_xa)) &&
+                        (this.xmppstatus.get('status') == 'online' && this._autoAway === 0) || (this.xmppstatus.get('status') == 'away' && this._autoAway == 1) ){
+                        this._idleCounter++;
+                    }
+                    if (this.auto_away > 0 && this._autoAway != 1 && this._idleCounter > this.auto_away && this._idleCounter <= this.auto_xa){
+                        this.sendCSI(INACTIVE);
+                        this._autoAway = 1;
+                        this.xmppstatus.setStatus('away');
+                    }
+                    else if (this.auto_xa > 0 && this._autoAway != 2 && this._idleCounter > this.auto_xa){
+                        this.sendCSI(INACTIVE);
+                        this._autoAway = 2;
+                        this.xmppstatus.setStatus('xa');
+                    }
+                }.bind(this), 1000); //every seconds
+                return true;
+            }
+        };
+
+		
         this.playNotification = function () {
         this.playNotification = function () {
             var audio;
             var audio;
-            if (converse.play_sounds && typeof Audio !== "undefined"){
+            if (converse.play_sounds && typeof Audio !== "undefined") {
                 audio = new Audio(converse.sounds_path+"msg_received.ogg");
                 audio = new Audio(converse.sounds_path+"msg_received.ogg");
                 if (audio.canPlayType('/audio/ogg')) {
                 if (audio.canPlayType('/audio/ogg')) {
                     audio.play();
                     audio.play();
@@ -634,14 +718,69 @@
             },this), 200));
             },this), 200));
         };
         };
 
 
+        this.ping = function (jid, success, error, timeout) {
+            // XXX: We could first check here if the server advertised that it supports PING.
+            // However, some servers don't advertise while still keeping the
+            // connection option due to pings.
+            //
+            // var feature = converse.features.findWhere({'var': Strophe.NS.PING});
+            converse.lastStanzaDate = new Date();
+            if (typeof jid === 'undefined' || jid === null) {
+                jid = Strophe.getDomainFromJid(converse.bare_jid);
+            }
+            if (typeof timeout === 'undefined' ) { timeout = null; }
+            if (typeof success === 'undefined' ) { success = null; }
+            if (typeof error === 'undefined' ) { error = null; }
+            if (converse.connection) {
+                converse.connection.ping.ping(jid, success, error, timeout);
+                return true;
+            }
+            return false;
+        };
+		
+        this.pong = function (ping) {
+            converse.lastStanzaDate = new Date();
+            converse.connection.ping.pong(ping);
+            return true;
+        };
+
+        this.registerPongHandler = function () {
+            converse.connection.disco.addFeature(Strophe.NS.PING);
+            converse.connection.ping.addPingHandler(this.pong);
+        };
+
+        this.registerPingHandler = function () {
+            this.registerPongHandler();
+            if (this.ping_interval > 0) {
+                this.connection.addHandler(function () {
+                    /* Handler on each stanza, saves the received date
+                     * in order to ping only when needed.
+                     */
+                    this.lastStanzaDate = new Date();
+                    return true;
+                }.bind(converse));
+                this.connection.addTimedHandler(1000, function () {
+                    now = new Date();
+                    if (!this.lastStanzaDate) {
+                        this.lastStanzaDate = now;
+                    }
+                    if ((now - this.lastStanzaDate)/1000 > this.ping_interval) {
+                        return this.ping();
+                    }
+                    return true;
+                });
+            }
+        };
+
         this.onReconnected = function () {
         this.onReconnected = function () {
             // We need to re-register all the event handlers on the newly
             // We need to re-register all the event handlers on the newly
             // created connection.
             // created connection.
             this.initStatus($.proxy(function () {
             this.initStatus($.proxy(function () {
-                this.registerRosterXHandler();
-                this.registerPresenceHandler();
+                this.registerPingHandler();
+                this.rosterview.registerRosterXHandler();
+                this.rosterview.registerPresenceHandler();
                 this.chatboxes.registerMessageHandler();
                 this.chatboxes.registerMessageHandler();
-                converse.xmppstatus.sendPresence();
+                this.xmppstatus.sendPresence();
                 this.giveFeedback(__('Contacts'));
                 this.giveFeedback(__('Contacts'));
             }, this));
             }, this));
         };
         };
@@ -683,7 +822,8 @@
             this.features = new this.Features();
             this.features = new this.Features();
             this.enableCarbons();
             this.enableCarbons();
             this.initStatus($.proxy(function () {
             this.initStatus($.proxy(function () {
-
+                this.registerPingHandler();
+                this.registerAutoAwayHandler();				
                 this.chatboxes.onConnected();
                 this.chatboxes.onConnected();
                 this.giveFeedback(__('Contacts'));
                 this.giveFeedback(__('Contacts'));
                 if (this.callback) {
                 if (this.callback) {
@@ -1004,7 +1144,7 @@
                 'mousedown .dragresize-tm': 'onDragResizeStart'
                 'mousedown .dragresize-tm': 'onDragResizeStart'
             },
             },
 
 
-            initialize: function (){
+            initialize: function () {
                 this.model.messages.on('add', this.onMessageAdded, this);
                 this.model.messages.on('add', this.onMessageAdded, this);
                 this.model.on('show', this.show, this);
                 this.model.on('show', this.show, this);
                 this.model.on('destroy', this.hide, this);
                 this.model.on('destroy', this.hide, this);
@@ -1486,8 +1626,13 @@
             },
             },
 
 
             maximize: function () {
             maximize: function () {
+                var chatboxviews = converse.chatboxviews;
                 // Restores a minimized chat box
                 // Restores a minimized chat box
-                this.$el.insertAfter(converse.chatboxviews.get("controlbox").$el).show('fast', $.proxy(function () {
+                this.$el.insertAfter(chatboxviews.get("controlbox").$el).show('fast', $.proxy(function () {
+                    /* Now that the chat box is visible, we can call trimChats
+                     * to make space available if need be.
+                     */
+                    chatboxviews.trimChats(this);
                     converse.refreshWebkit();
                     converse.refreshWebkit();
                     this.setChatState(ACTIVE).focus();
                     this.setChatState(ACTIVE).focus();
                     converse.emit('chatBoxMaximized', this);
                     converse.emit('chatBoxMaximized', this);
@@ -1530,11 +1675,11 @@
                 var msgs = [];
                 var msgs = [];
                 if (data.otr_status == UNENCRYPTED) {
                 if (data.otr_status == UNENCRYPTED) {
                     msgs.push(__("Your messages are not encrypted anymore"));
                     msgs.push(__("Your messages are not encrypted anymore"));
-                } else if (data.otr_status == UNVERIFIED){
+                } else if (data.otr_status == UNVERIFIED) {
                     msgs.push(__("Your messages are now encrypted but your contact's identity has not been verified."));
                     msgs.push(__("Your messages are now encrypted but your contact's identity has not been verified."));
-                } else if (data.otr_status == VERIFIED){
+                } else if (data.otr_status == VERIFIED) {
                     msgs.push(__("Your contact's identify has been verified."));
                     msgs.push(__("Your contact's identify has been verified."));
-                } else if (data.otr_status == FINISHED){
+                } else if (data.otr_status == FINISHED) {
                     msgs.push(__("Your contact has ended encryption on their end, you should do the same."));
                     msgs.push(__("Your contact has ended encryption on their end, you should do the same."));
                 }
                 }
                 return this.showHelpMessages(msgs, 'info', false);
                 return this.showHelpMessages(msgs, 'info', false);
@@ -1545,11 +1690,11 @@
                     var data = this.model.toJSON();
                     var data = this.model.toJSON();
                     if (data.otr_status == UNENCRYPTED) {
                     if (data.otr_status == UNENCRYPTED) {
                         data.otr_tooltip = __('Your messages are not encrypted. Click here to enable OTR encryption.');
                         data.otr_tooltip = __('Your messages are not encrypted. Click here to enable OTR encryption.');
-                    } else if (data.otr_status == UNVERIFIED){
+                    } else if (data.otr_status == UNVERIFIED) {
                         data.otr_tooltip = __('Your messages are encrypted, but your contact has not been verified.');
                         data.otr_tooltip = __('Your messages are encrypted, but your contact has not been verified.');
-                    } else if (data.otr_status == VERIFIED){
+                    } else if (data.otr_status == VERIFIED) {
                         data.otr_tooltip = __('Your messages are encrypted and your contact verified.');
                         data.otr_tooltip = __('Your messages are encrypted and your contact verified.');
-                    } else if (data.otr_status == FINISHED){
+                    } else if (data.otr_status == FINISHED) {
                         data.otr_tooltip = __('Your contact has closed their end of the private session, you should do the same');
                         data.otr_tooltip = __('Your contact has closed their end of the private session, you should do the same');
                     }
                     }
                     this.$el.find('.chat-toolbar').html(
                     this.$el.find('.chat-toolbar').html(
@@ -2329,6 +2474,7 @@
                 'click .toggle-smiley': 'toggleEmoticonMenu',
                 'click .toggle-smiley': 'toggleEmoticonMenu',
                 'click .toggle-smiley ul li': 'insertEmoticon',
                 'click .toggle-smiley ul li': 'insertEmoticon',
                 'click .toggle-clear': 'clearChatRoomMessages',
                 'click .toggle-clear': 'clearChatRoomMessages',
+                'click .toggle-call': 'toggleCall',
                 'click .toggle-participants a': 'toggleOccupants',
                 'click .toggle-participants a': 'toggleOccupants',
                 'keypress textarea.chat-textarea': 'keyPressed',
                 'keypress textarea.chat-textarea': 'keyPressed',
                 'mousedown .dragresize-tm': 'onDragResizeStart'
                 'mousedown .dragresize-tm': 'onDragResizeStart'
@@ -2398,7 +2544,7 @@
                 this.toggleOccupants();
                 this.toggleOccupants();
                 return this;
                 return this;
             },
             },
-
+			
             toggleOccupants: function (ev) {
             toggleOccupants: function (ev) {
                 if (ev) {
                 if (ev) {
                     ev.preventDefault();
                     ev.preventDefault();
@@ -3018,6 +3164,11 @@
                 this.fetch({
                 this.fetch({
                     add: true,
                     add: true,
                     success: $.proxy(function (collection, resp) {
                     success: $.proxy(function (collection, resp) {
+                        collection.each(function (chatbox) {
+                            if (chatbox.get('id') !== 'controlbox' && !chatbox.get('minimized')) {
+                                chatbox.trigger('show');
+                            }
+                        });
                         if (!_.include(_.pluck(resp, 'id'), 'controlbox')) {
                         if (!_.include(_.pluck(resp, 'id'), 'controlbox')) {
                             this.add({
                             this.add({
                                 id: 'controlbox',
                                 id: 'controlbox',
@@ -3171,10 +3322,13 @@
             initialize: function () {
             initialize: function () {
                 this.model.on("add", this.onChatBoxAdded, this);
                 this.model.on("add", this.onChatBoxAdded, this);
                 this.model.on("change:minimized", function (item) {
                 this.model.on("change:minimized", function (item) {
-                    if (item.get('minimized') === false) {
-                         this.trimChats(this.get(item.get('id')));
+                    if (item.get('minimized') === true) {
+                        /* When a chat is minimized in trimChats, trimChats needs to be
+                        * called again (in case the minimized chats toggle is newly shown).
+                        */
+                        this.trimChats();
                     } else {
                     } else {
-                         this.trimChats();
+                        this.trimChats(this.get(item.get('id')));
                     }
                     }
                 }, this);
                 }, this);
             },
             },
@@ -3247,7 +3401,7 @@
                     }
                     }
                 });
                 });
 
 
-                if ((minimized_width + boxes_width + controlbox_width) > this.$el.outerWidth(true)) {
+                if ((minimized_width + boxes_width + controlbox_width) > $('body').outerWidth(true)) {
                     oldest_chat = this.getOldestMaximizedChat();
                     oldest_chat = this.getOldestMaximizedChat();
                     if (oldest_chat && oldest_chat.get('id') !== new_id) {
                     if (oldest_chat && oldest_chat.get('id') !== new_id) {
                         oldest_chat.minimize();
                         oldest_chat.minimize();
@@ -3270,17 +3424,19 @@
             },
             },
 
 
             closeAllChatBoxes: function (include_controlbox) {
             closeAllChatBoxes: function (include_controlbox) {
-                var i, chatbox;
                 // TODO: once Backbone.Overview has been refactored, we should
                 // TODO: once Backbone.Overview has been refactored, we should
                 // be able to call .each on the views themselves.
                 // be able to call .each on the views themselves.
-                this.model.each($.proxy(function (model) {
+                var ids = [];
+                this.model.each(function (model) {
                     var id = model.get('id');
                     var id = model.get('id');
                     if (include_controlbox || id !== 'controlbox') {
                     if (include_controlbox || id !== 'controlbox') {
-                        if (this.get(id)) { // Should always resolve, but shit happens
-                            this.get(id).close();
-                        }
+                        ids.push(id);
                     }
                     }
-                }, this));
+                });
+                ids.forEach(function(id) {
+                    var chatbox = this.get(id);
+                    if (chatbox) { chatbox.close(); }
+                }, this);
                 return this;
                 return this;
             },
             },
 
 
@@ -4687,7 +4843,7 @@
                 this.save({'status': value});
                 this.save({'status': value});
             },
             },
 
 
-            getStatus: function() {
+            getStatus: function () {
                 return this.get('status') || 'online';
                 return this.get('status') || 'online';
             },
             },
 
 
@@ -4741,7 +4897,7 @@
                             'desc_change_status': __('Click to change your chat status')
                             'desc_change_status': __('Click to change your chat status')
                             }));
                             }));
                 // iterate through all the <option> elements and add option values
                 // iterate through all the <option> elements and add option values
-                options.each(function (){
+                options.each(function () {
                     options_list.push(converse.templates.status_option({
                     options_list.push(converse.templates.status_option({
                         'value': $(this).val(),
                         'value': $(this).val(),
                         'text': this.text
                         'text': this.text
@@ -4798,6 +4954,8 @@
                     pretty_status = __('away for long');
                     pretty_status = __('away for long');
                 } else if (stat === 'away') {
                 } else if (stat === 'away') {
                     pretty_status = __('away');
                     pretty_status = __('away');
+                } else if (stat === 'offline') {
+                    pretty_status = __('offline');
                 } else {
                 } else {
                     pretty_status = __(stat) || __('online');
                     pretty_status = __(stat) || __('online');
                 }
                 }
@@ -4888,8 +5046,10 @@
                     return;
                     return;
                 }
                 }
                 $stanza.find('feature').each($.proxy(function (idx, feature) {
                 $stanza.find('feature').each($.proxy(function (idx, feature) {
+                    var namespace = $(feature).attr('var');
+                    this[namespace] = true;
                     this.create({
                     this.create({
-                        'var': $(feature).attr('var'),
+                        'var': namespace,
                         'from': $stanza.attr('from')
                         'from': $stanza.attr('from')
                     });
                     });
                 }, this));
                 }, this));
@@ -5853,6 +6013,9 @@
         'send': function (stanza) {
         'send': function (stanza) {
             converse.connection.send(stanza);
             converse.connection.send(stanza);
         },
         },
+        'ping': function (jid) {
+            converse.ping(jid);
+        },
         'plugins': {
         'plugins': {
             'add': function (name, plugin) {
             'add': function (name, plugin) {
                 converse.plugins[name] = plugin;
                 converse.plugins[name] = plugin;

+ 8 - 5
css/converse.css

@@ -32,11 +32,12 @@
   bottom: 0;
   bottom: 0;
   direction: ltr;
   direction: ltr;
   height: 35px;
   height: 35px;
-  left: 0;
+  left: auto;
   position: fixed;
   position: fixed;
-  right: 0;
+  right: 15px;
   z-index: 30;
   z-index: 30;
   display: block;
   display: block;
+  width: auto;
   -webkit-box-sizing: border-box;
   -webkit-box-sizing: border-box;
   -moz-box-sizing: border-box;
   -moz-box-sizing: border-box;
   box-sizing: border-box;
   box-sizing: border-box;
@@ -286,7 +287,8 @@
     content: "\2369"; }
     content: "\2369"; }
   #conversejs .icon-wrench:before {
   #conversejs .icon-wrench:before {
     content: "\e024"; }
     content: "\e024"; }
-  #conversejs .icon-xa:before,
+  #conversejs .icon-xa:before {
+    content: "\e602"; }
   #conversejs .icon-unavailable:before,
   #conversejs .icon-unavailable:before,
   #conversejs .icon-offline:before {
   #conversejs .icon-offline:before {
     content: "\e002"; }
     content: "\e002"; }
@@ -762,7 +764,8 @@
     display: block;
     display: block;
     margin-left: 5px; }
     margin-left: 5px; }
   #conversejs div.room-info {
   #conversejs div.room-info {
-    clear: left; }
+    clear: left;
+    width: 100%; }
   #conversejs p.room-info {
   #conversejs p.room-info {
     margin: 0;
     margin: 0;
     padding: 0;
     padding: 0;
@@ -793,7 +796,7 @@
     #conversejs dd.available-chatroom:hover {
     #conversejs dd.available-chatroom:hover {
       background-color: #E3C9C1; }
       background-color: #E3C9C1; }
       #conversejs dd.available-chatroom:hover .room-info {
       #conversejs dd.available-chatroom:hover .room-info {
-        display: inline-block;
+        display: block;
         font-size: 14px; }
         font-size: 14px; }
   #conversejs #converse-roster dd {
   #conversejs #converse-roster dd {
     border: none;
     border: none;

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 0 - 0
css/converse.css.map


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 0 - 0
css/converse.min.css


+ 0 - 1
dev.html

@@ -53,7 +53,6 @@
     require(['converse'], function (converse) {
     require(['converse'], function (converse) {
         converse.initialize({
         converse.initialize({
             bosh_service_url: 'https://conversejs.org/http-bind/', // Please use this connection manager only for testing purposes
             bosh_service_url: 'https://conversejs.org/http-bind/', // Please use this connection manager only for testing purposes
-            i18n: locales['en'], // Refer to ./locale/locales.js to see which locales are supported
             keepalive: true,
             keepalive: true,
             message_carbons: true,
             message_carbons: true,
             play_sounds: true,
             play_sounds: true,

+ 12 - 3
docs/CHANGES.rst

@@ -4,12 +4,21 @@ Changelog
 0.9.4 (Unreleased)
 0.9.4 (Unreleased)
 ------------------
 ------------------
 
 
-* Refactored in order to remove the strophe.roster.js dependency. [jcbrand]
+* #144 Add Ping funcionnality and Pong Handler [thierrytiti]
+* #389 Allow login panel placeholders and roster item 'Name' translations. [gbonvehi]
+* #415 closeAllChatBoxes is giving ReferenceError when 2 chats are open [nevcos, jcbrand]
+* Add automatic Away mode and XEP-0352 support [thierrytiti]
+* Add icon for XA status [thierrytiti]
+* Allow offline pretty status and placeholder for "Insert a smiley" to be translated [thierrytiti]
 * Bugfix. Manual login doesn't work when only websocket_url is set and not bosh_service_url. [jcbrand]
 * Bugfix. Manual login doesn't work when only websocket_url is set and not bosh_service_url. [jcbrand]
 * Bugfix. clearSessions during unload event would throw an error when not logged in. [gbonvehi]
 * Bugfix. clearSessions during unload event would throw an error when not logged in. [gbonvehi]
 * Bugfix. wrong callback argument mapping in XmppStatus initialize: fullname is null [thierrytiti]
 * Bugfix. wrong callback argument mapping in XmppStatus initialize: fullname is null [thierrytiti]
-* #389 Allow login panel placeholders and roster item 'Name' translations. [gbonvehi]
-* Add placeholder for "Insert a smiley" translation [thierrytiti]
+* CSS fix: position and width of the div #conversejs [thierrytiti]
+* CSS fix: room-info bug on hover after room description loaded [thierrytiti]
+* CSS: Fonts Path: editabable $font-path via sass/variables.scss [thierrytiti]
+* I18N: Autodetection of User Locale if no i18n setting is set. [thierrytiti]
+* MUC: missing toggle call handler and updated documentation about call. [thierrytiti]
+* Refactored in order to remove the strophe.roster.js dependency. [jcbrand]
 * Updated French translation [thierrytiti]
 * Updated French translation [thierrytiti]
 
 
 0.9.3 (2015-05-01)
 0.9.3 (2015-05-01)

+ 36 - 1
docs/source/configuration.rst

@@ -175,6 +175,27 @@ It should be used either with ``authentication`` set to ``anonymous`` or to
 If ``authentication`` is set to ``login``, then you will also need to provide a
 If ``authentication`` is set to ``login``, then you will also need to provide a
 valid ``jid`` and ``password`` values.
 valid ``jid`` and ``password`` values.
 
 
+auto_away
+---------
+
+* Default:  ``0``
+
+This option can be used to let converse.js automatically change user presence
+
+This set the number a seconds before user presence become ``away``
+If the value if negative or ``0``, the function is disabled.
+
+auto_xa
+-------
+
+* Default:  ``0``
+
+This option can be used to let converse.js automatically change user presence
+
+This set the number a seconds before user presence become ``xa`` (eXtended Away)
+The value must be greater than ``auto_away``
+If the value if negative or ``0``, the function is disabled.
+
 auto_reconnect
 auto_reconnect
 --------------
 --------------
 
 
@@ -360,11 +381,25 @@ If set to ``true``, then don't show offline users.
 i18n
 i18n
 ----
 ----
 
 
+* Default:  Auto-detection of the User/Browser language
+
+If no locale is matching available locales, the default is ``en``.
 Specify the locale/language. The language must be in the ``locales`` object. Refer to
 Specify the locale/language. The language must be in the ``locales`` object. Refer to
 ``./locale/locales.js`` to see which locales are supported.
 ``./locale/locales.js`` to see which locales are supported.
 
 
 .. _`play-sounds`:
 .. _`play-sounds`:
 
 
+ping_interval
+-------------
+
+* Default:  ``300``
+
+Make ping to server in order to keep connection with server killing sessions after idle timeout.
+The ping are sent only if no messages are sent in the last ``ping_interval`` seconds
+You need to set the value to any positive value to enable this functionality.
+
+If you set this value to ``0`` or any negative value, il will disable this functionality.
+
 play_sounds
 play_sounds
 -----------
 -----------
 
 
@@ -525,7 +560,7 @@ Allows you to show or hide buttons on the chat boxes' toolbars.
     Provides a button with a picture of a telephone on it.
     Provides a button with a picture of a telephone on it.
     When the call button is pressed, it will emit an event that can be used by a third-party library to initiate a call.::
     When the call button is pressed, it will emit an event that can be used by a third-party library to initiate a call.::
 
 
-        converse.on('callButtonClicked', function(event, data) {
+        converse.listen.on('callButtonClicked', function(event, data) {
             console.log('Strophe connection is', data.connection);
             console.log('Strophe connection is', data.connection);
             console.log('Bare buddy JID is', data.model.get('jid'));
             console.log('Bare buddy JID is', data.model.get('jid'));
             // ... Third-party library code ...
             // ... Third-party library code ...

+ 1 - 3
fonticons/demo-files/demo.css

@@ -108,9 +108,6 @@ p {
 .pvs, .pts {
 .pvs, .pts {
 	padding-top: .25em;
 	padding-top: .25em;
 }
 }
-.clearfix {
-	zoom: 1;
-}
 .unit {
 .unit {
 	float: left;
 	float: left;
 }
 }
@@ -141,6 +138,7 @@ p {
 	height: 1.5em;
 	height: 1.5em;
 }
 }
 #testDrive {
 #testDrive {
+	display: block;
 	padding-top: 24px;
 	padding-top: 24px;
 	line-height: 1.5;
 	line-height: 1.5;
 }
 }

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 475 - 187
fonticons/demo.html


binární
fonticons/fonts/icomoon.eot


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 0 - 0
fonticons/fonts/icomoon.svg


binární
fonticons/fonts/icomoon.ttf


binární
fonticons/fonts/icomoon.woff


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 3 - 0
fonticons/selection.json


+ 99 - 96
fonticons/style.css

@@ -1,10 +1,10 @@
 @font-face {
 @font-face {
 	font-family: 'icomoon';
 	font-family: 'icomoon';
-	src:url('fonts/icomoon.eot?-mnoxh0');
-	src:url('fonts/icomoon.eot?#iefix-mnoxh0') format('embedded-opentype'),
-		url('fonts/icomoon.woff?-mnoxh0') format('woff'),
-		url('fonts/icomoon.ttf?-mnoxh0') format('truetype'),
-		url('fonts/icomoon.svg?-mnoxh0#icomoon') format('svg');
+	src:url('fonts/icomoon.eot?dvaucx');
+	src:url('fonts/icomoon.eot?#iefixdvaucx') format('embedded-opentype'),
+		url('fonts/icomoon.ttf?dvaucx') format('truetype'),
+		url('fonts/icomoon.woff?dvaucx') format('woff'),
+		url('fonts/icomoon.svg?dvaucx#icomoon') format('svg');
 	font-weight: normal;
 	font-weight: normal;
 	font-style: normal;
 	font-style: normal;
 }
 }
@@ -23,276 +23,279 @@
 	-moz-osx-font-smoothing: grayscale;
 	-moz-osx-font-smoothing: grayscale;
 }
 }
 
 
-#conversejs .icon-conversejs:before {
+.icon-xa:before {
+	content: "\e602";
+}
+.icon-conversejs:before {
 	content: "\e600";
 	content: "\e600";
 }
 }
-#conversejs .icon-closed:before {
+.icon-closed:before {
 	content: "\25ba";
 	content: "\25ba";
 }
 }
-#conversejs .icon-opened:before {
+.icon-opened:before {
 	content: "\25bc";
 	content: "\25bc";
 }
 }
-#conversejs .icon-checkmark:before {
+.icon-checkmark:before {
 	content: "\2713";
 	content: "\2713";
 }
 }
-#conversejs .icon-home:before {
+.icon-home:before {
 	content: "\e000";
 	content: "\e000";
 }
 }
-#conversejs .icon-pencil:before {
+.icon-pencil:before {
 	content: "\270e";
 	content: "\270e";
 }
 }
-#conversejs .icon-camera:before {
+.icon-camera:before {
 	content: "\e003";
 	content: "\e003";
 }
 }
-#conversejs .icon-camera-2:before {
+.icon-camera-2:before {
 	content: "\2616";
 	content: "\2616";
 }
 }
-#conversejs .icon-play:before {
+.icon-play:before {
 	content: "\25d9";
 	content: "\25d9";
 }
 }
-#conversejs .icon-music:before {
+.icon-music:before {
 	content: "\266b";
 	content: "\266b";
 }
 }
-#conversejs .icon-headphones:before {
+.icon-headphones:before {
 	content: "\266c";
 	content: "\266c";
 }
 }
-#conversejs .icon-phone:before {
+.icon-phone:before {
 	content: "\260f";
 	content: "\260f";
 }
 }
-#conversejs .icon-phone-hang-up:before {
+.icon-phone-hang-up:before {
 	content: "\260e";
 	content: "\260e";
 }
 }
-#conversejs .icon-address-book:before {
+.icon-address-book:before {
 	content: "\270f";
 	content: "\270f";
 }
 }
-#conversejs .icon-notebook:before {
+.icon-notebook:before {
 	content: "\2710";
 	content: "\2710";
 }
 }
-#conversejs .icon-envelop:before {
+.icon-envelop:before {
 	content: "\2709";
 	content: "\2709";
 }
 }
-#conversejs .icon-pushpin:before {
+.icon-pushpin:before {
 	content: "\e012";
 	content: "\e012";
 }
 }
-#conversejs .icon-online:before {
+.icon-online:before {
 	content: "\25fc";
 	content: "\25fc";
 }
 }
-#conversejs .icon-away:before {
+.icon-away:before {
 	content: "\25fb";
 	content: "\25fb";
 }
 }
-#conversejs .icon-bubbles:before {
+.icon-bubbles:before {
 	content: "\e015";
 	content: "\e015";
 }
 }
-#conversejs .icon-bubbles2:before {
+.icon-bubbles2:before {
 	content: "\e016";
 	content: "\e016";
 }
 }
-#conversejs .icon-bubbles3:before {
+.icon-bubbles3:before {
 	content: "\e017";
 	content: "\e017";
 }
 }
-#conversejs .icon-user:before {
+.icon-user:before {
 	content: "\e01a";
 	content: "\e01a";
 }
 }
-#conversejs .icon-hide-users:before {
+.icon-hide-users:before {
 	content: "\e01c";
 	content: "\e01c";
 }
 }
-#conversejs .icon-show-users:before {
+.icon-show-users:before {
 	content: "\e01e";
 	content: "\e01e";
 }
 }
-#conversejs .icon-users:before {
+.icon-users:before {
 	content: "\e01b";
 	content: "\e01b";
 }
 }
-#conversejs .icon-quotes-left:before {
+.icon-quotes-left:before {
 	content: "\e01d";
 	content: "\e01d";
 }
 }
-#conversejs .icon-spinner:before {
+.icon-spinner:before {
 	content: "\231b";
 	content: "\231b";
 }
 }
-#conversejs .icon-search:before {
+.icon-search:before {
 	content: "\e021";
 	content: "\e021";
 }
 }
-#conversejs .icon-cogs:before {
+.icon-cogs:before {
 	content: "\e022";
 	content: "\e022";
 }
 }
-#conversejs .icon-wrench:before {
+.icon-wrench:before {
 	content: "\e024";
 	content: "\e024";
 }
 }
-#conversejs .icon-unlocked:before {
+.icon-unlocked:before {
 	content: "\e025";
 	content: "\e025";
 }
 }
-#conversejs .icon-lock:before {
+.icon-lock:before {
 	content: "\e026";
 	content: "\e026";
 }
 }
-#conversejs .icon-lock-2:before {
+.icon-lock-2:before {
 	content: "\e027";
 	content: "\e027";
 }
 }
-#conversejs .icon-key:before {
+.icon-key:before {
 	content: "\e028";
 	content: "\e028";
 }
 }
-#conversejs .icon-key-2:before {
+.icon-key-2:before {
 	content: "\e029";
 	content: "\e029";
 }
 }
-#conversejs .icon-zoomout:before {
+.icon-zoomout:before {
 	content: "\e02a";
 	content: "\e02a";
 }
 }
-#conversejs .icon-zoomin:before {
+.icon-zoomin:before {
 	content: "\e02b";
 	content: "\e02b";
 }
 }
-#conversejs .icon-cog:before {
+.icon-cog:before {
 	content: "\e02f";
 	content: "\e02f";
 }
 }
-#conversejs .icon-remove:before {
+.icon-remove:before {
 	content: "\e02d";
 	content: "\e02d";
 }
 }
-#conversejs .icon-eye:before {
+.icon-eye:before {
 	content: "\e030";
 	content: "\e030";
 }
 }
-#conversejs .icon-eye-blocked:before {
+.icon-eye-blocked:before {
 	content: "\e031";
 	content: "\e031";
 }
 }
-#conversejs .icon-attachment:before {
+.icon-attachment:before {
 	content: "\e032";
 	content: "\e032";
 }
 }
-#conversejs .icon-globe:before {
+.icon-globe:before {
 	content: "\e033";
 	content: "\e033";
 }
 }
-#conversejs .icon-heart:before {
+.icon-heart:before {
 	content: "\2764";
 	content: "\2764";
 }
 }
-#conversejs .icon-happy:before {
+.icon-happy:before {
 	content: "\263b";
 	content: "\263b";
 }
 }
-#conversejs .icon-thumbs-up:before {
+.icon-thumbs-up:before {
 	content: "\261d";
 	content: "\261d";
 }
 }
-#conversejs .icon-smiley:before {
+.icon-smiley:before {
 	content: "\263a";
 	content: "\263a";
 }
 }
-#conversejs .icon-tongue:before {
+.icon-tongue:before {
 	content: "\e038";
 	content: "\e038";
 }
 }
-#conversejs .icon-sad:before {
+.icon-sad:before {
 	content: "\2639";
 	content: "\2639";
 }
 }
-#conversejs .icon-wink:before {
+.icon-wink:before {
 	content: "\e03a";
 	content: "\e03a";
 }
 }
-#conversejs .icon-wondering:before {
+.icon-wondering:before {
 	content: "\2369";
 	content: "\2369";
 }
 }
-#conversejs .icon-confused:before {
+.icon-confused:before {
 	content: "\2368";
 	content: "\2368";
 }
 }
-#conversejs .icon-shocked:before {
+.icon-shocked:before {
 	content: "\2364";
 	content: "\2364";
 }
 }
-#conversejs .icon-evil:before {
+.icon-evil:before {
 	content: "\261f";
 	content: "\261f";
 }
 }
-#conversejs .icon-angry:before {
+.icon-angry:before {
 	content: "\e03f";
 	content: "\e03f";
 }
 }
-#conversejs .icon-cool:before {
+.icon-cool:before {
 	content: "\e040";
 	content: "\e040";
 }
 }
-#conversejs .icon-grin:before {
+.icon-grin:before {
 	content: "\e041";
 	content: "\e041";
 }
 }
-#conversejs .icon-info:before {
+.icon-info:before {
 	content: "\2360";
 	content: "\2360";
 }
 }
-#conversejs .icon-notification:before {
+.icon-notification:before {
 	content: "\e01f";
 	content: "\e01f";
 }
 }
-#conversejs .icon-warning:before {
+.icon-warning:before {
 	content: "\26a0";
 	content: "\26a0";
 }
 }
-#conversejs .icon-spell-check:before {
+.icon-spell-check:before {
 	content: "\e045";
 	content: "\e045";
 }
 }
-#conversejs .icon-volume-high:before {
+.icon-volume-high:before {
 	content: "\e046";
 	content: "\e046";
 }
 }
-#conversejs .icon-volume-medium:before {
+.icon-volume-medium:before {
 	content: "\e047";
 	content: "\e047";
 }
 }
-#conversejs .icon-volume-low:before {
+.icon-volume-low:before {
 	content: "\e048";
 	content: "\e048";
 }
 }
-#conversejs .icon-volume-mute:before {
+.icon-volume-mute:before {
 	content: "\e049";
 	content: "\e049";
 }
 }
-#conversejs .icon-volume-mute2:before {
+.icon-volume-mute2:before {
 	content: "\e04a";
 	content: "\e04a";
 }
 }
-#conversejs .icon-volume-decrease:before {
+.icon-volume-decrease:before {
 	content: "\e04b";
 	content: "\e04b";
 }
 }
-#conversejs .icon-volume-increase:before {
+.icon-volume-increase:before {
 	content: "\e04c";
 	content: "\e04c";
 }
 }
-#conversejs .icon-bold:before {
+.icon-bold:before {
 	content: "\e04d";
 	content: "\e04d";
 }
 }
-#conversejs .icon-underline:before {
+.icon-underline:before {
 	content: "\e04e";
 	content: "\e04e";
 }
 }
-#conversejs .icon-italic:before {
+.icon-italic:before {
 	content: "\e04f";
 	content: "\e04f";
 }
 }
-#conversejs .icon-strikethrough:before {
+.icon-strikethrough:before {
 	content: "\e050";
 	content: "\e050";
 }
 }
-#conversejs .icon-newtab:before {
+.icon-newtab:before {
 	content: "\e053";
 	content: "\e053";
 }
 }
-#conversejs .icon-youtube:before {
+.icon-youtube:before {
 	content: "\e055";
 	content: "\e055";
 }
 }
-#conversejs .icon-close:before {
+.icon-close:before {
 	content: "\2715";
 	content: "\2715";
 }
 }
-#conversejs .icon-blocked:before {
+.icon-blocked:before {
 	content: "\2718";
 	content: "\2718";
 }
 }
-#conversejs .icon-cancel-circle:before {
+.icon-cancel-circle:before {
 	content: "\e058";
 	content: "\e058";
 }
 }
-#conversejs .icon-minus:before {
+.icon-minus:before {
 	content: "\e05a";
 	content: "\e05a";
 }
 }
-#conversejs .icon-plus:before {
+.icon-plus:before {
 	content: "\271a";
 	content: "\271a";
 }
 }
-#conversejs .icon-checkbox-checked:before {
+.icon-checkbox-checked:before {
 	content: "\2611";
 	content: "\2611";
 }
 }
-#conversejs .icon-checkbox-unchecked:before {
+.icon-checkbox-unchecked:before {
 	content: "\2b27";
 	content: "\2b27";
 }
 }
-#conversejs .icon-checkbox-partial:before {
+.icon-checkbox-partial:before {
 	content: "\2b28";
 	content: "\2b28";
 }
 }
-#conversejs .icon-radio-checked:before {
+.icon-radio-checked:before {
 	content: "\2b26";
 	content: "\2b26";
 }
 }
-#conversejs .icon-radio-unchecked:before {
+.icon-radio-unchecked:before {
 	content: "\2b25";
 	content: "\2b25";
 }
 }
-#conversejs .icon-room-info:before {
+.icon-room-info:before {
 	content: "\e059";
 	content: "\e059";
 }
 }
-#conversejs .icon-newspaper:before {
+.icon-newspaper:before {
 	content: "\e001";
 	content: "\e001";
 }
 }
-#conversejs .icon-image:before {
+.icon-image:before {
 	content: "\2b14";
 	content: "\2b14";
 }
 }
-#conversejs .icon-offline:before {
+.icon-offline:before {
 	content: "\e002";
 	content: "\e002";
 }
 }
-#conversejs .icon-busy:before {
+.icon-busy:before {
 	content: "\e004";
 	content: "\e004";
 }
 }
-#conversejs .icon-exit:before {
+.icon-exit:before {
 	content: "\e601";
 	content: "\e601";
 }
 }

+ 8 - 5
index.html

@@ -144,18 +144,22 @@
                         <ul class="features">
                         <ul class="features">
                             <li>Single-user chat</li>
                             <li>Single-user chat</li>
                             <li>Multi-user chatrooms (<a href="http://xmpp.org/extensions/xep-0045.html" target="_blank">XEP 45</a>)</li>
                             <li>Multi-user chatrooms (<a href="http://xmpp.org/extensions/xep-0045.html" target="_blank">XEP 45</a>)</li>
+                            <li>Direct invitations to chat rooms (<a href="http://xmpp.org/extensions/xep-0249.html" target="_blank">XEP 249</a>)</li>
                             <li>vCard support (<a href="http://xmpp.org/extensions/xep-0054.html" target="_blank">XEP 54</a>)</li>
                             <li>vCard support (<a href="http://xmpp.org/extensions/xep-0054.html" target="_blank">XEP 54</a>)</li>
                             <li>Service discovery (<a href="http://xmpp.org/extensions/xep-0030.html" target="_blank">XEP 30</a>)</li>
                             <li>Service discovery (<a href="http://xmpp.org/extensions/xep-0030.html" target="_blank">XEP 30</a>)</li>
+                            <li>In-band registration (<a href="http://xmpp.org/extensions/xep-0077.html" target="_blank">XEP 77</a>)</li>
                             <li>Contact rosters and groups</li>
                             <li>Contact rosters and groups</li>
                             <li>Contact subscriptions</li>
                             <li>Contact subscriptions</li>
-                            <li>Accept or decline contact requests</li>
                             <li>Roster item exchange (<a href="http://xmpp.org/extensions/tmp/xep-0144-1.1.html" target="_blank">XEP 144</a>)</li>
                             <li>Roster item exchange (<a href="http://xmpp.org/extensions/tmp/xep-0144-1.1.html" target="_blank">XEP 144</a>)</li>
                             <li>Chat statuses (online, busy, away, offline)</li>
                             <li>Chat statuses (online, busy, away, offline)</li>
                             <li>Custom status messages</li>
                             <li>Custom status messages</li>
-                            <li>Typing notifications</li>
-                            <li>Third person messages (/me )</li>
+                            <li>Typing and state notifications (<a href="http://xmpp.org/extensions/xep-0085.html" target="_blank">XEP 85</a>)</li>
+                            <li>Messages appear in all connected chat clients (<a href="http://xmpp.org/extensions/xep-0280.html" target="_blank">XEP 280</a>)</li>
+                            <li>Third person "/me" messages (<a href="http://xmpp.org/extensions/xep-0245.html" target="_blank">XEP 245</a>)</li>
+                            <li>XMPP Ping (<a href="http://xmpp.org/extensions/xep-0199.html" target="_blank">XEP 199</a>)</li>
+                            <li>Client state indication (<a href="http://xmpp.org/extensions/xep-0352.html" target="_blank">XEP 352</a>)</li>A
+                            <li>Off-the-record encryption</li>
                             <li>Translated into 16 languages</li>
                             <li>Translated into 16 languages</li>
-                            <li>Off-the-record encryption
                         </ul>
                         </ul>
                 </div>
                 </div>
                 <div class="col-lg-4">
                 <div class="col-lg-4">
@@ -251,7 +255,6 @@
         })();
         })();
         converse.initialize({
         converse.initialize({
             bosh_service_url: 'https://conversejs.org/http-bind/', // Please use this connection manager only for testing purposes
             bosh_service_url: 'https://conversejs.org/http-bind/', // Please use this connection manager only for testing purposes
-            i18n: locales['en'], // Refer to ./locale/locales.js to see which locales are supported
             keepalive: true,
             keepalive: true,
             message_carbons: true,
             message_carbons: true,
             play_sounds: true,
             play_sounds: true,

+ 106 - 50
locale/de/LC_MESSAGES/converse.json

@@ -17,11 +17,11 @@
          ],
          ],
          "unverified": [
          "unverified": [
             null,
             null,
-            "unbestätigt"
+            "nicht verifiziert"
          ],
          ],
          "verified": [
          "verified": [
             null,
             null,
-            "bestätigt"
+            "verifiziert"
          ],
          ],
          "finished": [
          "finished": [
             null,
             null,
@@ -29,7 +29,7 @@
          ],
          ],
          "This contact is busy": [
          "This contact is busy": [
             null,
             null,
-            "Dieser Kontakt ist beschäfticht"
+            "Dieser Kontakt ist beschäftigt"
          ],
          ],
          "This contact is online": [
          "This contact is online": [
             null,
             null,
@@ -45,7 +45,7 @@
          ],
          ],
          "This contact is away for an extended period": [
          "This contact is away for an extended period": [
             null,
             null,
-            "Dieser Kontakt is für längere Zeit abwesend"
+            "Dieser Kontakt ist für längere Zeit abwesend"
          ],
          ],
          "This contact is away": [
          "This contact is away": [
             null,
             null,
@@ -53,7 +53,7 @@
          ],
          ],
          "Click to hide these contacts": [
          "Click to hide these contacts": [
             null,
             null,
-            "Hier klicken um diesen Kontakte zu verstecken"
+            "Hier klicken um diesen Kontakt zu verstecken"
          ],
          ],
          "My contacts": [
          "My contacts": [
             null,
             null,
@@ -69,7 +69,7 @@
          ],
          ],
          "Ungrouped": [
          "Ungrouped": [
             null,
             null,
-            ""
+            "Ungruppiert"
          ],
          ],
          "Contacts": [
          "Contacts": [
             null,
             null,
@@ -77,7 +77,11 @@
          ],
          ],
          "Groups": [
          "Groups": [
             null,
             null,
-            ""
+            "Gruppen"
+         ],
+         "Reconnecting": [
+            null,
+            "Verbindung wiederherstellen …"
          ],
          ],
          "Error": [
          "Error": [
             null,
             null,
@@ -97,36 +101,52 @@
          ],
          ],
          "Re-establishing encrypted session": [
          "Re-establishing encrypted session": [
             null,
             null,
-            ""
+            "Verschlüsselte Sitzung wiederherstellen"
          ],
          ],
          "Generating private key.": [
          "Generating private key.": [
             null,
             null,
-            ""
+            "Generiere privaten Schlüssel."
          ],
          ],
          "Your browser might become unresponsive.": [
          "Your browser might become unresponsive.": [
             null,
             null,
-            ""
+            "Ihr Browser könnte langsam reagieren."
          ],
          ],
          "Authentication request from %1$s\n\nYour chat contact is attempting to verify your identity, by asking you the question below.\n\n%2$s": [
          "Authentication request from %1$s\n\nYour chat contact is attempting to verify your identity, by asking you the question below.\n\n%2$s": [
             null,
             null,
-            ""
+            "Authentifizierungsanfrage von %1$s\n\nIhr Kontakt möchte durch die folgende Frage Ihre Identität verifizieren.\n\n%2$s"
          ],
          ],
          "Could not verify this user's identify.": [
          "Could not verify this user's identify.": [
             null,
             null,
-            ""
+            "Die Identität des Benutzers konnte nicht verifiziert werden."
          ],
          ],
          "Exchanging private key with contact.": [
          "Exchanging private key with contact.": [
             null,
             null,
-            ""
+            "Tausche private Schlüssel mit Kontakt aus."
          ],
          ],
          "Personal message": [
          "Personal message": [
             null,
             null,
             "Persönliche Nachricht"
             "Persönliche Nachricht"
          ],
          ],
+         "Are you sure you want to clear the messages from this room?": [
+            null,
+            "Sind Sie sicher, dass Sie alle Nachrichten in diesem Raum löschen möchten?"
+         ],
          "me": [
          "me": [
             null,
             null,
             "Ich"
             "Ich"
          ],
          ],
+         "is typing": [
+            null,
+            "%1$s tippt"
+         ],
+         "has stopped typing": [
+            null,
+            "%1$s tippt nicht mehr"
+         ],
+         "has gone away": [
+            null,
+            "ist jetzt abwesend"
+         ],
          "Show this menu": [
          "Show this menu": [
             null,
             null,
             "Dieses Menü anzeigen"
             "Dieses Menü anzeigen"
@@ -141,19 +161,19 @@
          ],
          ],
          "Are you sure you want to clear the messages from this chat box?": [
          "Are you sure you want to clear the messages from this chat box?": [
             null,
             null,
-            ""
+            "Sind Sie sicher, dass Sie alle Nachrichten dieses Chats löschen möchten?"
          ],
          ],
          "Your message could not be sent": [
          "Your message could not be sent": [
             null,
             null,
-            ""
+            "Ihre Nachricht konnte nicht gesendet werden"
          ],
          ],
          "We received an unencrypted message": [
          "We received an unencrypted message": [
             null,
             null,
-            ""
+            "Wir haben eine unverschlüsselte Nachricht empfangen"
          ],
          ],
          "We received an unreadable encrypted message": [
          "We received an unreadable encrypted message": [
             null,
             null,
-            ""
+            "Wir haben eine unlesbare Nachricht empfangen"
          ],
          ],
          "Here are the fingerprints, please confirm them with %1$s, outside of this chat.\n\nFingerprint for you, %2$s: %3$s\n\nFingerprint for %1$s: %4$s\n\nIf you have confirmed that the fingerprints match, click OK, otherwise click Cancel.": [
          "Here are the fingerprints, please confirm them with %1$s, outside of this chat.\n\nFingerprint for you, %2$s: %3$s\n\nFingerprint for %1$s: %4$s\n\nIf you have confirmed that the fingerprints match, click OK, otherwise click Cancel.": [
             null,
             null,
@@ -213,7 +233,7 @@
          ],
          ],
          "Hide the list of participants": [
          "Hide the list of participants": [
             null,
             null,
-            ""
+            "Teilnehmerliste ausblenden"
          ],
          ],
          "Refresh encrypted conversation": [
          "Refresh encrypted conversation": [
             null,
             null,
@@ -237,7 +257,7 @@
          ],
          ],
          "What's this?": [
          "What's this?": [
             null,
             null,
-            ""
+            "Was ist das?"
          ],
          ],
          "Online": [
          "Online": [
             null,
             null,
@@ -245,7 +265,7 @@
          ],
          ],
          "Busy": [
          "Busy": [
             null,
             null,
-            "Beschäfticht"
+            "Beschäftigt"
          ],
          ],
          "Away": [
          "Away": [
             null,
             null,
@@ -273,11 +293,11 @@
          ],
          ],
          "Click to add new chat contacts": [
          "Click to add new chat contacts": [
             null,
             null,
-            "Klicken Sie, um einen neuen Kontakt hinzuzufügen"
+            "Hier klicken um neuen Kontakt hinzuzufügen"
          ],
          ],
          "Add a contact": [
          "Add a contact": [
             null,
             null,
-            "Kontakte hinzufügen"
+            "Kontakt hinzufügen"
          ],
          ],
          "No users found": [
          "No users found": [
             null,
             null,
@@ -393,7 +413,7 @@
          ],
          ],
          "Invite...": [
          "Invite...": [
             null,
             null,
-            ""
+            "Einladen..."
          ],
          ],
          "Occupants": [
          "Occupants": [
             null,
             null,
@@ -413,7 +433,7 @@
          ],
          ],
          "Error: could not execute the command": [
          "Error: could not execute the command": [
             null,
             null,
-            ""
+            "Fehler: konnte den Befehl nicht ausführen"
          ],
          ],
          "Change user's affiliation to admin": [
          "Change user's affiliation to admin": [
             null,
             null,
@@ -425,7 +445,7 @@
          ],
          ],
          "Change user role to participant": [
          "Change user role to participant": [
             null,
             null,
-            ""
+            "Benutzerrolle zu Teilnehmer ändern"
          ],
          ],
          "Kick user from room": [
          "Kick user from room": [
             null,
             null,
@@ -445,12 +465,16 @@
          ],
          ],
          "Change your nickname": [
          "Change your nickname": [
             null,
             null,
-            ""
+            "Spitznamen ändern"
          ],
          ],
          "Grant moderator role to user": [
          "Grant moderator role to user": [
             null,
             null,
             ""
             ""
          ],
          ],
+         "Grant ownership of this room": [
+            null,
+            "Besitzrechte an diesem Raum vergeben"
+         ],
          "Revoke user's membership": [
          "Revoke user's membership": [
             null,
             null,
             ""
             ""
@@ -473,11 +497,11 @@
          ],
          ],
          "An error occurred while trying to save the form.": [
          "An error occurred while trying to save the form.": [
             null,
             null,
-            "Beim Speichern der Formular is ein Fehler aufgetreten."
+            "Beim Speichern des Formulars ist ein Fehler aufgetreten."
          ],
          ],
          "This chatroom requires a password": [
          "This chatroom requires a password": [
             null,
             null,
-            "Passwort wird für die Anmeldung benötigt."
+            "Dieser Raum erfordert ein Passwort"
          ],
          ],
          "Password: ": [
          "Password: ": [
             null,
             null,
@@ -485,7 +509,7 @@
          ],
          ],
          "Submit": [
          "Submit": [
             null,
             null,
-            "Einreichen"
+            "Abschicken"
          ],
          ],
          "This room is not anonymous": [
          "This room is not anonymous": [
             null,
             null,
@@ -493,23 +517,23 @@
          ],
          ],
          "This room now shows unavailable members": [
          "This room now shows unavailable members": [
             null,
             null,
-            "Dieser Raum zeigt jetzt unferfügbare Mitglieder"
+            "Dieser Raum zeigt jetzt nicht verfügbare Mitglieder an"
          ],
          ],
          "This room does not show unavailable members": [
          "This room does not show unavailable members": [
             null,
             null,
-            "Dieser Raum zeigt nicht unverfügbare Mitglieder"
+            "Dieser Raum zeigt jetzt nicht verfügbare Mitglieder nicht an"
          ],
          ],
          "Non-privacy-related room configuration has changed": [
          "Non-privacy-related room configuration has changed": [
             null,
             null,
-            "Die Konfiguration, die nicht auf die Privatsphäre bezogen ist, hat sich geändert"
+            "Raumkonfiguration, nicht Privatsphäre relevant, hat sich geändert"
          ],
          ],
          "Room logging is now enabled": [
          "Room logging is now enabled": [
             null,
             null,
-            "Zukünftige Nachrichten dieses Raums werden protokolliert."
+            "Nachrichten in diesem Raums werden ab jetzt protokolliert."
          ],
          ],
          "Room logging is now disabled": [
          "Room logging is now disabled": [
             null,
             null,
-            "Zukünftige Nachrichten dieses Raums werden nicht protokolliert."
+            "Nachrichten in diesem Raums werden nicht mehr protokolliert."
          ],
          ],
          "This room is now non-anonymous": [
          "This room is now non-anonymous": [
             null,
             null,
@@ -525,7 +549,7 @@
          ],
          ],
          "A new room has been created": [
          "A new room has been created": [
             null,
             null,
-            "Einen neuen Raum ist erstellen"
+            "Einen neuer Raum wurde erstellt"
          ],
          ],
          "You have been banned from this room": [
          "You have been banned from this room": [
             null,
             null,
@@ -541,19 +565,23 @@
          ],
          ],
          "You have been removed from this room because the room has changed to members-only and you're not a member": [
          "You have been removed from this room because the room has changed to members-only and you're not a member": [
             null,
             null,
-            "Sie wurden aus diesem Raum entfernt da Sie kein Mitglied sind."
+            "Sie wurden aus diesem Raum entfernt, da Sie kein Mitglied sind."
          ],
          ],
          "You have been removed from this room because the MUC (Multi-user chat) service is being shut down.": [
          "You have been removed from this room because the MUC (Multi-user chat) service is being shut down.": [
             null,
             null,
-            "Sie werden aus diesem Raum entfernt da der MUC (Muli-user chat) Dienst gerade abgeschalten wird."
+            "Sie wurden aus diesem Raum entfernt, da der MUC (Multi-User Chat) Dienst gerade heruntergefahren wird."
          ],
          ],
          "<strong>%1$s</strong> has been banned": [
          "<strong>%1$s</strong> has been banned": [
             null,
             null,
-            "<strong>%1$s</strong> ist verbannt"
+            "<strong>%1$s</strong> ist verbannt worden"
+         ],
+         "<strong>%1$s</strong>'s nickname has changed": [
+            null,
+            "<strong>%1$s</strong> hat den Spitznamen geändert"
          ],
          ],
          "<strong>%1$s</strong> has been kicked out": [
          "<strong>%1$s</strong> has been kicked out": [
             null,
             null,
-            "<strong>%1$s</strong> ist hinausgeworfen"
+            "<strong>%1$s</strong> wurde hinausgeworfen"
          ],
          ],
          "<strong>%1$s</strong> has been removed because of an affiliation change": [
          "<strong>%1$s</strong> has been removed because of an affiliation change": [
             null,
             null,
@@ -563,9 +591,13 @@
             null,
             null,
             "<strong>%1$s</strong> ist kein Mitglied und wurde daher entfernt"
             "<strong>%1$s</strong> ist kein Mitglied und wurde daher entfernt"
          ],
          ],
+         "Your nickname has been automatically changed to: <strong>%1$s</strong>": [
+            null,
+            "Ihr Spitzname wurde automatisiert geändert zu: <strong>%1$s</strong>"
+         ],
          "The reason given is: \"": [
          "The reason given is: \"": [
             null,
             null,
-            ""
+            "Die angegebene Begründung lautet: \""
          ],
          ],
          "You are not on the member list of this room": [
          "You are not on the member list of this room": [
             null,
             null,
@@ -577,7 +609,7 @@
          ],
          ],
          "You are not allowed to create new rooms": [
          "You are not allowed to create new rooms": [
             null,
             null,
-            "Es ist Ihnen nicht erlaubt, neue Räume anzulegen"
+            "Es ist Ihnen nicht erlaubt neue Räume anzulegen"
          ],
          ],
          "Your nickname doesn't conform to this room's policies": [
          "Your nickname doesn't conform to this room's policies": [
             null,
             null,
@@ -597,31 +629,51 @@
          ],
          ],
          "Topic set by %1$s to: %2$s": [
          "Topic set by %1$s to: %2$s": [
             null,
             null,
-            "%1$s hat das Thema zu \"%2$s\" abgeändert"
+            "%1$s hat das Thema zu \"%2$s\" geändert"
          ],
          ],
          "%1$s has invited you to join a chat room: %2$s": [
          "%1$s has invited you to join a chat room: %2$s": [
             null,
             null,
-            ""
+            "%1$s hat Sie in den Raum \"%2$s\" eingeladen"
          ],
          ],
          "%1$s has invited you to join a chat room: %2$s, and left the following reason: \"%3$s\"": [
          "%1$s has invited you to join a chat room: %2$s, and left the following reason: \"%3$s\"": [
             null,
             null,
-            ""
+            "%1$s hat Sie in den Raum \"%2$s\" eingeladen. Begründung: \"%3$s\""
+         ],
+         "Click to restore this chat": [
+            null,
+            "Hier klicken um diesen Chat wiederherzustellen"
          ],
          ],
          "Minimized": [
          "Minimized": [
             null,
             null,
-            ""
+            "Minimiert"
          ],
          ],
          "Click to remove this contact": [
          "Click to remove this contact": [
             null,
             null,
             "Hier klicken um diesen Kontakt zu entfernen"
             "Hier klicken um diesen Kontakt zu entfernen"
          ],
          ],
+         "Click to accept this contact request": [
+            null,
+            "Hier klicken um diesen Kontaktanfrage zu akzeptieren"
+         ],
+         "Click to decline this contact request": [
+            null,
+            "Hier klicken um diesen Kontaktanfrage zu abzulehnen"
+         ],
          "Click to chat with this contact": [
          "Click to chat with this contact": [
             null,
             null,
             "Hier klicken um mit diesem Kontakt zu chatten"
             "Hier klicken um mit diesem Kontakt zu chatten"
          ],
          ],
+         "Are you sure you want to remove this contact?": [
+            null,
+            "Wollen Sie diesen Kontakt wirklich entfernen?"
+         ],
+         "Are you sure you want to decline this contact request?": [
+            null,
+            "Wollen Sie diese Kontaktanfrage wirklich ablehnen?"
+         ],
          "Type to filter": [
          "Type to filter": [
             null,
             null,
-            ""
+            "Tippen um zu filtern"
          ],
          ],
          "I am %1$s": [
          "I am %1$s": [
             null,
             null,
@@ -629,11 +681,11 @@
          ],
          ],
          "Click here to write a custom status message": [
          "Click here to write a custom status message": [
             null,
             null,
-            "Klicken Sie hier, um ihrer Status-Nachricht to ändern"
+            "Hier klicken um Status-Nachricht zu ändern"
          ],
          ],
          "Click to change your chat status": [
          "Click to change your chat status": [
             null,
             null,
-            "Klicken Sie, um ihrer Status to ändern"
+            "Hier klicken um Status zu ändern"
          ],
          ],
          "Custom status": [
          "Custom status": [
             null,
             null,
@@ -645,7 +697,7 @@
          ],
          ],
          "busy": [
          "busy": [
             null,
             null,
-            "beschäfticht"
+            "beschäftigt"
          ],
          ],
          "away for long": [
          "away for long": [
             null,
             null,
@@ -711,6 +763,10 @@
             null,
             null,
             "Passwort:"
             "Passwort:"
          ],
          ],
+         "Click here to log in anonymously": [
+            null,
+            "Hier klicken um anonym anzumelden"
+         ],
          "Log In": [
          "Log In": [
             null,
             null,
             "Anmelden"
             "Anmelden"
@@ -721,7 +777,7 @@
          ],
          ],
          "Toggle chat": [
          "Toggle chat": [
             null,
             null,
-            ""
+            "Chat ein-/ausblenden"
          ]
          ]
       }
       }
    }
    }

+ 76 - 115
locale/de/LC_MESSAGES/converse.po

@@ -8,7 +8,7 @@ msgstr ""
 "Project-Id-Version: Converse.js 0.4\n"
 "Project-Id-Version: Converse.js 0.4\n"
 "Report-Msgid-Bugs-To: \n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2015-05-01 12:26+0200\n"
 "POT-Creation-Date: 2015-05-01 12:26+0200\n"
-"PO-Revision-Date: 2015-05-01 12:25+0200\n"
+"PO-Revision-Date: 2015-06-04 10:11+0200\n"
 "Last-Translator: JC Brand <jc@opkode.com>\n"
 "Last-Translator: JC Brand <jc@opkode.com>\n"
 "Language-Team: German\n"
 "Language-Team: German\n"
 "Language: de\n"
 "Language: de\n"
@@ -30,11 +30,11 @@ msgstr "unverschlüsselt"
 
 
 #: converse.js:332
 #: converse.js:332
 msgid "unverified"
 msgid "unverified"
-msgstr "unbestätigt"
+msgstr "nicht verifiziert"
 
 
 #: converse.js:333
 #: converse.js:333
 msgid "verified"
 msgid "verified"
-msgstr "bestätigt"
+msgstr "verifiziert"
 
 
 #: converse.js:334
 #: converse.js:334
 msgid "finished"
 msgid "finished"
@@ -42,7 +42,7 @@ msgstr "erledigt"
 
 
 #: converse.js:337
 #: converse.js:337
 msgid "This contact is busy"
 msgid "This contact is busy"
-msgstr "Dieser Kontakt ist beschäfticht"
+msgstr "Dieser Kontakt ist beschäftigt"
 
 
 #: converse.js:338
 #: converse.js:338
 msgid "This contact is online"
 msgid "This contact is online"
@@ -58,7 +58,7 @@ msgstr "Dieser Kontakt ist nicht verfügbar"
 
 
 #: converse.js:341
 #: converse.js:341
 msgid "This contact is away for an extended period"
 msgid "This contact is away for an extended period"
-msgstr "Dieser Kontakt is für längere Zeit abwesend"
+msgstr "Dieser Kontakt ist für längere Zeit abwesend"
 
 
 #: converse.js:342
 #: converse.js:342
 msgid "This contact is away"
 msgid "This contact is away"
@@ -82,7 +82,7 @@ msgstr "Kontaktanfragen"
 
 
 #: converse.js:349
 #: converse.js:349
 msgid "Ungrouped"
 msgid "Ungrouped"
-msgstr ""
+msgstr "Ungruppiert"
 
 
 #: converse.js:351 converse.js:648 converse.js:691
 #: converse.js:351 converse.js:648 converse.js:691
 msgid "Contacts"
 msgid "Contacts"
@@ -90,12 +90,11 @@ msgstr "Kontakte"
 
 
 #: converse.js:352
 #: converse.js:352
 msgid "Groups"
 msgid "Groups"
-msgstr ""
+msgstr "Gruppen"
 
 
 #: converse.js:452
 #: converse.js:452
-#, fuzzy
 msgid "Reconnecting"
 msgid "Reconnecting"
-msgstr "Verbindungsaufbau …"
+msgstr "Verbindung wiederherstellen …"
 
 
 #: converse.js:495
 #: converse.js:495
 msgid "Error"
 msgid "Error"
@@ -115,15 +114,15 @@ msgstr "Authentifizierung gescheitert"
 
 
 #: converse.js:807
 #: converse.js:807
 msgid "Re-establishing encrypted session"
 msgid "Re-establishing encrypted session"
-msgstr ""
+msgstr "Verschlüsselte Sitzung wiederherstellen"
 
 
 #: converse.js:819
 #: converse.js:819
 msgid "Generating private key."
 msgid "Generating private key."
-msgstr ""
+msgstr "Generiere privaten Schlüssel."
 
 
 #: converse.js:820
 #: converse.js:820
 msgid "Your browser might become unresponsive."
 msgid "Your browser might become unresponsive."
-msgstr ""
+msgstr "Ihr Browser könnte langsam reagieren."
 
 
 #: converse.js:855
 #: converse.js:855
 msgid ""
 msgid ""
@@ -134,42 +133,44 @@ msgid ""
 "\n"
 "\n"
 "%2$s"
 "%2$s"
 msgstr ""
 msgstr ""
+"Authentifizierungsanfrage von %1$s\n"
+"\n"
+"Ihr Kontakt möchte durch die folgende Frage "
+"Ihre Identität verifizieren.\n"
+"\n"
+"%2$s"
 
 
 #: converse.js:864
 #: converse.js:864
 msgid "Could not verify this user's identify."
 msgid "Could not verify this user's identify."
-msgstr ""
+msgstr "Die Identität des Benutzers konnte nicht verifiziert werden."
 
 
 #: converse.js:903
 #: converse.js:903
 msgid "Exchanging private key with contact."
 msgid "Exchanging private key with contact."
-msgstr ""
+msgstr "Tausche private Schlüssel mit Kontakt aus."
 
 
 #: converse.js:1049
 #: converse.js:1049
 msgid "Personal message"
 msgid "Personal message"
 msgstr "Persönliche Nachricht"
 msgstr "Persönliche Nachricht"
 
 
 #: converse.js:1081
 #: converse.js:1081
-#, fuzzy
 msgid "Are you sure you want to clear the messages from this room?"
 msgid "Are you sure you want to clear the messages from this room?"
-msgstr "Sie sind nicht auf der Mitgliederliste dieses Raums"
+msgstr "Sind Sie sicher, dass Sie alle Nachrichten in diesem Raum löschen möchten?"
 
 
 #: converse.js:1103
 #: converse.js:1103
 msgid "me"
 msgid "me"
 msgstr "Ich"
 msgstr "Ich"
 
 
 #: converse.js:1158
 #: converse.js:1158
-#, fuzzy
 msgid "is typing"
 msgid "is typing"
 msgstr "%1$s tippt"
 msgstr "%1$s tippt"
 
 
 #: converse.js:1161
 #: converse.js:1161
-#, fuzzy
 msgid "has stopped typing"
 msgid "has stopped typing"
-msgstr "%1$s tippt"
+msgstr "%1$s tippt nicht mehr"
 
 
 #: converse.js:1167 converse.js:1447
 #: converse.js:1167 converse.js:1447
-#, fuzzy
 msgid "has gone away"
 msgid "has gone away"
-msgstr "Dieser Kontakt ist abwesend"
+msgstr "ist jetzt abwesend"
 
 
 #: converse.js:1212 converse.js:2531
 #: converse.js:1212 converse.js:2531
 msgid "Show this menu"
 msgid "Show this menu"
@@ -185,19 +186,19 @@ msgstr "Nachrichten entfernen"
 
 
 #: converse.js:1340
 #: converse.js:1340
 msgid "Are you sure you want to clear the messages from this chat box?"
 msgid "Are you sure you want to clear the messages from this chat box?"
-msgstr ""
+msgstr "Sind Sie sicher, dass Sie alle Nachrichten dieses Chats löschen möchten?"
 
 
 #: converse.js:1375
 #: converse.js:1375
 msgid "Your message could not be sent"
 msgid "Your message could not be sent"
-msgstr ""
+msgstr "Ihre Nachricht konnte nicht gesendet werden"
 
 
 #: converse.js:1378
 #: converse.js:1378
 msgid "We received an unencrypted message"
 msgid "We received an unencrypted message"
-msgstr ""
+msgstr "Wir haben eine unverschlüsselte Nachricht empfangen"
 
 
 #: converse.js:1381
 #: converse.js:1381
 msgid "We received an unreadable encrypted message"
 msgid "We received an unreadable encrypted message"
-msgstr ""
+msgstr "Wir haben eine unlesbare Nachricht empfangen"
 
 
 #: converse.js:1407
 #: converse.js:1407
 msgid ""
 msgid ""
@@ -239,9 +240,8 @@ msgid "has gone offline"
 msgstr "Dieser Kontakt ist offline"
 msgstr "Dieser Kontakt ist offline"
 
 
 #: converse.js:1449
 #: converse.js:1449
-#, fuzzy
 msgid "is busy"
 msgid "is busy"
-msgstr "beschäfticht"
+msgstr "ist beschäftigt"
 
 
 #: converse.js:1537
 #: converse.js:1537
 msgid "Your messages are not encrypted anymore"
 msgid "Your messages are not encrypted anymore"
@@ -280,9 +280,8 @@ msgid ""
 msgstr ""
 msgstr ""
 
 
 #: converse.js:1568
 #: converse.js:1568
-#, fuzzy
 msgid "Clear all messages"
 msgid "Clear all messages"
-msgstr "Persönliche Nachricht"
+msgstr "Alle Nachrichten löschen"
 
 
 #: converse.js:1569
 #: converse.js:1569
 msgid "End encrypted conversation"
 msgid "End encrypted conversation"
@@ -290,7 +289,7 @@ msgstr ""
 
 
 #: converse.js:1570
 #: converse.js:1570
 msgid "Hide the list of participants"
 msgid "Hide the list of participants"
-msgstr ""
+msgstr "Teilnehmerliste ausblenden"
 
 
 #: converse.js:1571
 #: converse.js:1571
 msgid "Refresh encrypted conversation"
 msgid "Refresh encrypted conversation"
@@ -314,7 +313,7 @@ msgstr ""
 
 
 #: converse.js:1576
 #: converse.js:1576
 msgid "What's this?"
 msgid "What's this?"
-msgstr ""
+msgstr "Was ist das?"
 
 
 #: converse.js:1668
 #: converse.js:1668
 msgid "Online"
 msgid "Online"
@@ -322,7 +321,7 @@ msgstr "Online"
 
 
 #: converse.js:1669
 #: converse.js:1669
 msgid "Busy"
 msgid "Busy"
-msgstr "Beschäfticht"
+msgstr "Beschäftigt"
 
 
 #: converse.js:1670
 #: converse.js:1670
 msgid "Away"
 msgid "Away"
@@ -333,9 +332,8 @@ msgid "Offline"
 msgstr "Abgemeldet"
 msgstr "Abgemeldet"
 
 
 #: converse.js:1672
 #: converse.js:1672
-#, fuzzy
 msgid "Log out"
 msgid "Log out"
-msgstr "Anmelden"
+msgstr "Abmelden"
 
 
 #: converse.js:1678
 #: converse.js:1678
 msgid "Contact name"
 msgid "Contact name"
@@ -355,11 +353,11 @@ msgstr "Hinzufügen"
 
 
 #: converse.js:1689
 #: converse.js:1689
 msgid "Click to add new chat contacts"
 msgid "Click to add new chat contacts"
-msgstr "Klicken Sie, um einen neuen Kontakt hinzuzufügen"
+msgstr "Hier klicken um neuen Kontakt hinzuzufügen"
 
 
 #: converse.js:1690
 #: converse.js:1690
 msgid "Add a contact"
 msgid "Add a contact"
-msgstr "Kontakte hinzufügen"
+msgstr "Kontakt hinzufügen"
 
 
 #: converse.js:1714
 #: converse.js:1714
 msgid "No users found"
 msgid "No users found"
@@ -382,9 +380,8 @@ msgid "Server"
 msgstr "Server"
 msgstr "Server"
 
 
 #: converse.js:1787
 #: converse.js:1787
-#, fuzzy
 msgid "Join Room"
 msgid "Join Room"
-msgstr "Beitreten"
+msgstr "Raum betreten"
 
 
 #: converse.js:1788
 #: converse.js:1788
 msgid "Show rooms"
 msgid "Show rooms"
@@ -483,7 +480,7 @@ msgstr "Dieser Benutzer kann keine Nachrichten in diesem Raum verschicken"
 
 
 #: converse.js:2221
 #: converse.js:2221
 msgid "Invite..."
 msgid "Invite..."
-msgstr ""
+msgstr "Einladen..."
 
 
 #: converse.js:2222
 #: converse.js:2222
 msgid "Occupants"
 msgid "Occupants"
@@ -505,7 +502,7 @@ msgstr "Nachricht"
 
 
 #: converse.js:2452
 #: converse.js:2452
 msgid "Error: could not execute the command"
 msgid "Error: could not execute the command"
-msgstr ""
+msgstr "Fehler: konnte den Befehl nicht ausführen"
 
 
 #: converse.js:2527
 #: converse.js:2527
 msgid "Change user's affiliation to admin"
 msgid "Change user's affiliation to admin"
@@ -517,7 +514,7 @@ msgstr "Verbanne einen Benutzer aus dem Raum."
 
 
 #: converse.js:2530
 #: converse.js:2530
 msgid "Change user role to participant"
 msgid "Change user role to participant"
-msgstr ""
+msgstr "Benutzerrolle zu Teilnehmer ändern"
 
 
 #: converse.js:2532
 #: converse.js:2532
 msgid "Kick user from room"
 msgid "Kick user from room"
@@ -537,16 +534,15 @@ msgstr ""
 
 
 #: converse.js:2536
 #: converse.js:2536
 msgid "Change your nickname"
 msgid "Change your nickname"
-msgstr ""
+msgstr "Spitznamen ändern"
 
 
 #: converse.js:2537
 #: converse.js:2537
 msgid "Grant moderator role to user"
 msgid "Grant moderator role to user"
 msgstr ""
 msgstr ""
 
 
 #: converse.js:2538
 #: converse.js:2538
-#, fuzzy
 msgid "Grant ownership of this room"
 msgid "Grant ownership of this room"
-msgstr "Sie sind nicht auf der Mitgliederliste dieses Raums"
+msgstr "Besitzrechte an diesem Raum vergeben"
 
 
 #: converse.js:2539
 #: converse.js:2539
 msgid "Revoke user's membership"
 msgid "Revoke user's membership"
@@ -570,11 +566,11 @@ msgstr "Abbrechen"
 
 
 #: converse.js:2730
 #: converse.js:2730
 msgid "An error occurred while trying to save the form."
 msgid "An error occurred while trying to save the form."
-msgstr "Beim Speichern der Formular is ein Fehler aufgetreten."
+msgstr "Beim Speichern des Formulars ist ein Fehler aufgetreten."
 
 
 #: converse.js:2777
 #: converse.js:2777
 msgid "This chatroom requires a password"
 msgid "This chatroom requires a password"
-msgstr "Passwort wird für die Anmeldung benötigt."
+msgstr "Dieser Raum erfordert ein Passwort"
 
 
 #: converse.js:2778
 #: converse.js:2778
 msgid "Password: "
 msgid "Password: "
@@ -582,7 +578,7 @@ msgstr "Passwort: "
 
 
 #: converse.js:2779
 #: converse.js:2779
 msgid "Submit"
 msgid "Submit"
-msgstr "Einreichen"
+msgstr "Abschicken"
 
 
 #: converse.js:2814
 #: converse.js:2814
 msgid "This room is not anonymous"
 msgid "This room is not anonymous"
@@ -590,25 +586,23 @@ msgstr "Dieser Raum ist nicht anonym"
 
 
 #: converse.js:2815
 #: converse.js:2815
 msgid "This room now shows unavailable members"
 msgid "This room now shows unavailable members"
-msgstr "Dieser Raum zeigt jetzt unferfügbare Mitglieder"
+msgstr "Dieser Raum zeigt jetzt nicht verfügbare Mitglieder an"
 
 
 #: converse.js:2816
 #: converse.js:2816
 msgid "This room does not show unavailable members"
 msgid "This room does not show unavailable members"
-msgstr "Dieser Raum zeigt nicht unverfügbare Mitglieder"
+msgstr "Dieser Raum zeigt jetzt nicht verfügbare Mitglieder nicht an"
 
 
 #: converse.js:2817
 #: converse.js:2817
 msgid "Non-privacy-related room configuration has changed"
 msgid "Non-privacy-related room configuration has changed"
-msgstr ""
-"Die Konfiguration, die nicht auf die Privatsphäre bezogen ist, hat sich "
-"geändert"
+msgstr "Raumkonfiguration, nicht Privatsphäre relevant, hat sich geändert"
 
 
 #: converse.js:2818
 #: converse.js:2818
 msgid "Room logging is now enabled"
 msgid "Room logging is now enabled"
-msgstr "Zukünftige Nachrichten dieses Raums werden protokolliert."
+msgstr "Nachrichten in diesem Raums werden ab jetzt protokolliert."
 
 
 #: converse.js:2819
 #: converse.js:2819
 msgid "Room logging is now disabled"
 msgid "Room logging is now disabled"
-msgstr "Zukünftige Nachrichten dieses Raums werden nicht protokolliert."
+msgstr "Nachrichten in diesem Raums werden nicht mehr protokolliert."
 
 
 #: converse.js:2820
 #: converse.js:2820
 msgid "This room is now non-anonymous"
 msgid "This room is now non-anonymous"
@@ -624,7 +618,7 @@ msgstr "Dieser Raum ist jetzt anonym"
 
 
 #: converse.js:2823
 #: converse.js:2823
 msgid "A new room has been created"
 msgid "A new room has been created"
-msgstr "Einen neuen Raum ist erstellen"
+msgstr "Einen neuer Raum wurde erstellt"
 
 
 #: converse.js:2827 converse.js:2926
 #: converse.js:2827 converse.js:2926
 msgid "You have been banned from this room"
 msgid "You have been banned from this room"
@@ -642,51 +636,47 @@ msgstr "Sie wurden wegen einer Zugehörigkeitsänderung entfernt"
 msgid ""
 msgid ""
 "You have been removed from this room because the room has changed to members-"
 "You have been removed from this room because the room has changed to members-"
 "only and you're not a member"
 "only and you're not a member"
-msgstr "Sie wurden aus diesem Raum entfernt da Sie kein Mitglied sind."
+msgstr "Sie wurden aus diesem Raum entfernt, da Sie kein Mitglied sind."
 
 
 #: converse.js:2831
 #: converse.js:2831
 msgid ""
 msgid ""
 "You have been removed from this room because the MUC (Multi-user chat) "
 "You have been removed from this room because the MUC (Multi-user chat) "
 "service is being shut down."
 "service is being shut down."
 msgstr ""
 msgstr ""
-"Sie werden aus diesem Raum entfernt da der MUC (Muli-user chat) Dienst "
-"gerade abgeschalten wird."
+"Sie wurden aus diesem Raum entfernt, da der MUC (Multi-User Chat) Dienst "
+"gerade heruntergefahren wird."
 
 
 #: converse.js:2845
 #: converse.js:2845
 msgid "<strong>%1$s</strong> has been banned"
 msgid "<strong>%1$s</strong> has been banned"
-msgstr "<strong>%1$s</strong> ist verbannt"
+msgstr "<strong>%1$s</strong> ist verbannt worden"
 
 
 #: converse.js:2846
 #: converse.js:2846
-#, fuzzy
 msgid "<strong>%1$s</strong>'s nickname has changed"
 msgid "<strong>%1$s</strong>'s nickname has changed"
-msgstr "<strong>%1$s</strong> ist verbannt"
+msgstr "<strong>%1$s</strong> hat den Spitznamen geändert"
 
 
 #: converse.js:2847
 #: converse.js:2847
 msgid "<strong>%1$s</strong> has been kicked out"
 msgid "<strong>%1$s</strong> has been kicked out"
-msgstr "<strong>%1$s</strong> ist hinausgeworfen"
+msgstr "<strong>%1$s</strong> wurde hinausgeworfen"
 
 
 #: converse.js:2848
 #: converse.js:2848
 msgid "<strong>%1$s</strong> has been removed because of an affiliation change"
 msgid "<strong>%1$s</strong> has been removed because of an affiliation change"
-msgstr ""
-"<strong>%1$s</strong> wurde wegen einer Zugehörigkeitsänderung entfernt"
+msgstr "<strong>%1$s</strong> wurde wegen einer Zugehörigkeitsänderung entfernt"
 
 
 #: converse.js:2849
 #: converse.js:2849
 msgid "<strong>%1$s</strong> has been removed for not being a member"
 msgid "<strong>%1$s</strong> has been removed for not being a member"
 msgstr "<strong>%1$s</strong> ist kein Mitglied und wurde daher entfernt"
 msgstr "<strong>%1$s</strong> ist kein Mitglied und wurde daher entfernt"
 
 
 #: converse.js:2853
 #: converse.js:2853
-#, fuzzy
 msgid "Your nickname has been automatically changed to: <strong>%1$s</strong>"
 msgid "Your nickname has been automatically changed to: <strong>%1$s</strong>"
-msgstr "Spitzname festgelegen"
+msgstr "Ihr Spitzname wurde automatisiert geändert zu: <strong>%1$s</strong>"
 
 
 #: converse.js:2854
 #: converse.js:2854
-#, fuzzy
 msgid "Your nickname has been changed to: <strong>%1$s</strong>"
 msgid "Your nickname has been changed to: <strong>%1$s</strong>"
-msgstr "Spitzname festgelegen"
+msgstr "Ihr Spitzname wurde geändert zu: <strong>%1$s</strong>"
 
 
 #: converse.js:2902 converse.js:2912
 #: converse.js:2902 converse.js:2912
 msgid "The reason given is: \""
 msgid "The reason given is: \""
-msgstr ""
+msgstr "Die angegebene Begründung lautet: \""
 
 
 #: converse.js:2924
 #: converse.js:2924
 msgid "You are not on the member list of this room"
 msgid "You are not on the member list of this room"
@@ -698,7 +688,7 @@ msgstr "Kein Spitzname festgelegt"
 
 
 #: converse.js:2934
 #: converse.js:2934
 msgid "You are not allowed to create new rooms"
 msgid "You are not allowed to create new rooms"
-msgstr "Es ist Ihnen nicht erlaubt, neue Räume anzulegen"
+msgstr "Es ist Ihnen nicht erlaubt neue Räume anzulegen"
 
 
 #: converse.js:2936
 #: converse.js:2936
 msgid "Your nickname doesn't conform to this room's policies"
 msgid "Your nickname doesn't conform to this room's policies"
@@ -718,58 +708,55 @@ msgstr "Dieser Raum hat die maximale Mitgliederanzahl erreicht"
 
 
 #: converse.js:2988
 #: converse.js:2988
 msgid "Topic set by %1$s to: %2$s"
 msgid "Topic set by %1$s to: %2$s"
-msgstr "%1$s hat das Thema zu \"%2$s\" abgeändert"
+msgstr "%1$s hat das Thema zu \"%2$s\" geändert"
 
 
 #: converse.js:3066
 #: converse.js:3066
 msgid "%1$s has invited you to join a chat room: %2$s"
 msgid "%1$s has invited you to join a chat room: %2$s"
-msgstr ""
+msgstr "%1$s hat Sie in den Raum \"%2$s\" eingeladen"
 
 
 #: converse.js:3070
 #: converse.js:3070
 msgid ""
 msgid ""
 "%1$s has invited you to join a chat room: %2$s, and left the following "
 "%1$s has invited you to join a chat room: %2$s, and left the following "
 "reason: \"%3$s\""
 "reason: \"%3$s\""
 msgstr ""
 msgstr ""
+"%1$s hat Sie in den Raum \"%2$s\" eingeladen. "
+"Begründung: \"%3$s\""
 
 
 #: converse.js:3339
 #: converse.js:3339
-#, fuzzy
 msgid "Click to restore this chat"
 msgid "Click to restore this chat"
-msgstr "Hier klicken um diesen Kontakt zu entfernen"
+msgstr "Hier klicken um diesen Chat wiederherzustellen"
 
 
 #: converse.js:3481
 #: converse.js:3481
 msgid "Minimized"
 msgid "Minimized"
-msgstr ""
+msgstr "Minimiert"
 
 
 #: converse.js:3582 converse.js:3600
 #: converse.js:3582 converse.js:3600
 msgid "Click to remove this contact"
 msgid "Click to remove this contact"
 msgstr "Hier klicken um diesen Kontakt zu entfernen"
 msgstr "Hier klicken um diesen Kontakt zu entfernen"
 
 
 #: converse.js:3589
 #: converse.js:3589
-#, fuzzy
 msgid "Click to accept this contact request"
 msgid "Click to accept this contact request"
-msgstr "Hier klicken um diesen Kontakt zu entfernen"
+msgstr "Hier klicken um diesen Kontaktanfrage zu akzeptieren"
 
 
 #: converse.js:3590
 #: converse.js:3590
-#, fuzzy
 msgid "Click to decline this contact request"
 msgid "Click to decline this contact request"
-msgstr "Hier klicken um diesen Kontakt zu entfernen"
+msgstr "Hier klicken um diesen Kontaktanfrage zu abzulehnen"
 
 
 #: converse.js:3599
 #: converse.js:3599
 msgid "Click to chat with this contact"
 msgid "Click to chat with this contact"
 msgstr "Hier klicken um mit diesem Kontakt zu chatten"
 msgstr "Hier klicken um mit diesem Kontakt zu chatten"
 
 
 #: converse.js:3616
 #: converse.js:3616
-#, fuzzy
 msgid "Are you sure you want to remove this contact?"
 msgid "Are you sure you want to remove this contact?"
-msgstr "Hier klicken um diesen Kontakt zu entfernen"
+msgstr "Wollen Sie diesen Kontakt wirklich entfernen?"
 
 
 #: converse.js:3639
 #: converse.js:3639
-#, fuzzy
 msgid "Are you sure you want to decline this contact request?"
 msgid "Are you sure you want to decline this contact request?"
-msgstr "Hier klicken um diesen Kontakt zu entfernen"
+msgstr "Wollen Sie diese Kontaktanfrage wirklich ablehnen?"
 
 
 #: converse.js:4166
 #: converse.js:4166
 msgid "Type to filter"
 msgid "Type to filter"
-msgstr ""
+msgstr "Tippen um zu filtern"
 
 
 #. For translators: the %1$s part gets replaced with the status
 #. For translators: the %1$s part gets replaced with the status
 #. Example, I am online
 #. Example, I am online
@@ -779,11 +766,11 @@ msgstr "Ich bin %1$s"
 
 
 #: converse.js:4602 converse.js:4678
 #: converse.js:4602 converse.js:4678
 msgid "Click here to write a custom status message"
 msgid "Click here to write a custom status message"
-msgstr "Klicken Sie hier, um ihrer Status-Nachricht to ändern"
+msgstr "Hier klicken um Status-Nachricht zu ändern"
 
 
 #: converse.js:4603 converse.js:4679
 #: converse.js:4603 converse.js:4679
 msgid "Click to change your chat status"
 msgid "Click to change your chat status"
-msgstr "Klicken Sie, um ihrer Status to ändern"
+msgstr "Hier klicken um Status zu ändern"
 
 
 #: converse.js:4628
 #: converse.js:4628
 msgid "Custom status"
 msgid "Custom status"
@@ -795,7 +782,7 @@ msgstr "online"
 
 
 #: converse.js:4658
 #: converse.js:4658
 msgid "busy"
 msgid "busy"
-msgstr "beschäfticht"
+msgstr "beschäftigt"
 
 
 #: converse.js:4660
 #: converse.js:4660
 msgid "away for long"
 msgid "away for long"
@@ -866,9 +853,8 @@ msgid "Password:"
 msgstr "Passwort:"
 msgstr "Passwort:"
 
 
 #: converse.js:5202
 #: converse.js:5202
-#, fuzzy
 msgid "Click here to log in anonymously"
 msgid "Click here to log in anonymously"
-msgstr "Dieser Raum ist nicht anonym"
+msgstr "Hier klicken um anonym anzumelden"
 
 
 #: converse.js:5203
 #: converse.js:5203
 msgid "Log In"
 msgid "Log In"
@@ -880,29 +866,4 @@ msgstr "Anmelden"
 
 
 #: converse.js:5291
 #: converse.js:5291
 msgid "Toggle chat"
 msgid "Toggle chat"
-msgstr ""
-
-#~ msgid "Online Contacts"
-#~ msgstr "Online-Kontakte"
-
-#~ msgid "Disconnected"
-#~ msgstr "Verbindung unterbrochen."
-
-#~ msgid "Connection Failed"
-#~ msgstr "Entfernte Verbindung fehlgeschlagen"
-
-#~ msgid "Disconnecting"
-#~ msgstr "Trenne Verbindung"
-
-#, fuzzy
-#~ msgid "Decline"
-#~ msgstr "Online"
-
-#~ msgid "BOSH Service URL:"
-#~ msgstr "BOSH "
-
-#~ msgid "Connected"
-#~ msgstr "Verbunden"
-
-#~ msgid "Attached"
-#~ msgstr "Angehängt"
+msgstr "Chat ein-/ausblenden"

+ 3 - 1
main.js

@@ -38,6 +38,7 @@ require.config({
         "strophe.disco":            "components/strophejs-plugins/disco/strophe.disco",
         "strophe.disco":            "components/strophejs-plugins/disco/strophe.disco",
         "strophe.roster":           "src/strophe.roster",
         "strophe.roster":           "src/strophe.roster",
         "strophe.vcard":            "src/strophe.vcard",
         "strophe.vcard":            "src/strophe.vcard",
+        "strophe.ping":             "src/strophe.ping",
         "text":                     'components/requirejs-text/text',
         "text":                     'components/requirejs-text/text',
         "tpl":                      'components/requirejs-tpl-jcbrand/tpl',
         "tpl":                      'components/requirejs-tpl-jcbrand/tpl',
         "typeahead":                "components/typeahead.js/index",
         "typeahead":                "components/typeahead.js/index",
@@ -170,7 +171,8 @@ require.config({
         'strophe.disco':        { deps: ['strophe'] },
         'strophe.disco':        { deps: ['strophe'] },
         'strophe.register':     { deps: ['strophe'] },
         'strophe.register':     { deps: ['strophe'] },
         'strophe.roster':       { deps: ['strophe'] },
         'strophe.roster':       { deps: ['strophe'] },
-        'strophe.vcard':        { deps: ['strophe'] }
+        'strophe.vcard':        { deps: ['strophe'] },
+        'strophe.ping':         { deps: ['strophe'] }
     }
     }
 });
 });
 
 

+ 1 - 0
non_amd.html

@@ -35,6 +35,7 @@
     <script type="text/javascript" src="src/strophe.roster.js"></script>
     <script type="text/javascript" src="src/strophe.roster.js"></script>
     <script type="text/javascript" src="components/strophejs-plugins/vcard/strophe.vcard.js"></script>
     <script type="text/javascript" src="components/strophejs-plugins/vcard/strophe.vcard.js"></script>
     <script type="text/javascript" src="components/strophejs-plugins/disco/strophe.disco.js"></script>
     <script type="text/javascript" src="components/strophejs-plugins/disco/strophe.disco.js"></script>
+	<script type="text/javascript" src="src/strophe.ping.js"></script>
     <script type="text/javascript" src="components/underscore/underscore.js"></script>
     <script type="text/javascript" src="components/underscore/underscore.js"></script>
     <script type="text/javascript" src="components/backbone//backbone.js"></script>
     <script type="text/javascript" src="components/backbone//backbone.js"></script>
     <script type="text/javascript" src="components/backbone.browserStorage/backbone.browserStorage.js"></script>
     <script type="text/javascript" src="components/backbone.browserStorage/backbone.browserStorage.js"></script>

+ 10 - 6
sass/converse.scss

@@ -8,10 +8,12 @@
 
 
 @import "../ruby/1.9.1/gems/bourbon-4.2.1/app/assets/stylesheets/_bourbon";
 @import "../ruby/1.9.1/gems/bourbon-4.2.1/app/assets/stylesheets/_bourbon";
 
 
+@import "variables";
+
 @font-face {
 @font-face {
   font-family: 'Converse-js';
   font-family: 'Converse-js';
-  src: url('../fonticons/fonts/icomoon.eot?-mnoxh0');
-  src: url('../fonticons/fonts/icomoon.eot?#iefix-mnoxh0') format("embedded-opentype"), url('../fonticons/fonts/icomoon.woff?-mnoxh0') format("woff"), url('../fonticons/fonts/icomoon.ttf?-mnoxh0') format("truetype"), url('../fonticons/fonts/icomoon.svg?-mnoxh0#icomoon') format("svg");
+  src: url($font-path + 'icomoon.eot?-mnoxh0');
+  src: url($font-path + 'icomoon.eot?#iefix-mnoxh0') format("embedded-opentype"), url($font-path + 'icomoon.woff?-mnoxh0') format("woff"), url($font-path + 'icomoon.ttf?-mnoxh0') format("truetype"), url($font-path + 'icomoon.svg?-mnoxh0#icomoon') format("svg");
   font-weight: normal;
   font-weight: normal;
   font-style: normal;
   font-style: normal;
 }
 }
@@ -46,11 +48,12 @@
   bottom: 0;
   bottom: 0;
   direction: ltr;
   direction: ltr;
   height: $bottom-gutter-height;
   height: $bottom-gutter-height;
-  left: 0;
+  left: auto;
   position: fixed;
   position: fixed;
-  right: 0;
+  right: 15px;
   z-index: 30;
   z-index: 30;
   display: block;
   display: block;
+  width: auto;
 
 
   @include box-sizing(border-box);
   @include box-sizing(border-box);
   *, *:before, *:after {
   *, *:before, *:after {
@@ -227,7 +230,7 @@
   .icon-wink:before               { content: "\e03a"; }
   .icon-wink:before               { content: "\e03a"; }
   .icon-wondering:before          { content: "\2369"; }
   .icon-wondering:before          { content: "\2369"; }
   .icon-wrench:before             { content: "\e024"; }
   .icon-wrench:before             { content: "\e024"; }
-  .icon-xa:before,
+  .icon-xa:before                 { content: "\e602"; }
   .icon-unavailable:before,
   .icon-unavailable:before,
   .icon-offline:before            { content: "\e002"; }
   .icon-offline:before            { content: "\e002"; }
   .icon-youtube:before            { content: "\e055"; }
   .icon-youtube:before            { content: "\e055"; }
@@ -856,6 +859,7 @@
 
 
   div.room-info {
   div.room-info {
     clear: left;
     clear: left;
+	width: 100%;
   }
   }
 
 
   p.room-info {
   p.room-info {
@@ -896,7 +900,7 @@
     &:hover {
     &:hover {
       background-color: $highlight-color;
       background-color: $highlight-color;
       .room-info {
       .room-info {
-        display: inline-block;
+        display: block;
         font-size: 14px;
         font-size: 14px;
       }
       }
     }
     }

+ 1 - 0
sass/variables.scss

@@ -37,3 +37,4 @@
   $mobile-chat-width: 100%;
   $mobile-chat-width: 100%;
   $mobile-chat-height: 400px;
   $mobile-chat-height: 400px;
 
 
+  $font-path: "../fonticons/fonts/";

+ 1 - 0
src/deps-full.js

@@ -6,6 +6,7 @@ define("converse-dependencies", [
     "strophe",
     "strophe",
     "strophe.vcard",
     "strophe.vcard",
     "strophe.disco",
     "strophe.disco",
+    "strophe.ping",
     "backbone.browserStorage",
     "backbone.browserStorage",
     "backbone.overview",
     "backbone.overview",
     "jquery.browser",
     "jquery.browser",

+ 1 - 0
src/deps-no-otr.js

@@ -5,6 +5,7 @@ define("converse-dependencies", [
     "strophe",
     "strophe",
     "strophe.vcard",
     "strophe.vcard",
     "strophe.disco",
     "strophe.disco",
+    "strophe.ping",
     "backbone.browserStorage",
     "backbone.browserStorage",
     "backbone.overview",
     "backbone.overview",
     "jquery.browser",
     "jquery.browser",

+ 1 - 0
src/deps-website-no-otr.js

@@ -5,6 +5,7 @@ define("converse-dependencies", [
     "strophe",
     "strophe",
     "strophe.vcard",
     "strophe.vcard",
     "strophe.disco",
     "strophe.disco",
+    "strophe.ping",
     "bootstrapJS", // XXX: Can be removed, only for https://conversejs.org
     "bootstrapJS", // XXX: Can be removed, only for https://conversejs.org
     "backbone.browserStorage",
     "backbone.browserStorage",
     "backbone.overview",
     "backbone.overview",

+ 1 - 0
src/deps-website.js

@@ -7,6 +7,7 @@ define("converse-dependencies", [
     "strophe",
     "strophe",
     "strophe.vcard",
     "strophe.vcard",
     "strophe.disco",
     "strophe.disco",
+    "strophe.ping",
     "bootstrapJS", // XXX: Only for https://conversejs.org
     "bootstrapJS", // XXX: Only for https://conversejs.org
     "backbone.browserStorage",
     "backbone.browserStorage",
     "backbone.overview",
     "backbone.overview",

+ 100 - 0
src/strophe.ping.js

@@ -0,0 +1,100 @@
+/*
+* Based on Ping Strophejs plugins (https://github.com/metajack/strophejs-plugins/tree/master/ping)
+* This plugin is distributed under the terms of the MIT licence.
+* Please see the LICENCE file for details.
+*
+* Copyright (c) Markus Kohlhase, 2010
+* Refactored by Pavel Lang, 2011
+*/
+/**
+* File: strophe.ping.js
+* A Strophe plugin for XMPP Ping ( http://xmpp.org/extensions/xep-0199.html )
+*/
+/* 
+* AMD Support added by Thierry
+* 
+*/
+
+(function (root, factory) {
+    if (typeof define === 'function' && define.amd) {
+        // AMD. Register as an anonymous module.
+        define([
+            "strophe"
+        ], function (Strophe) {
+            factory(
+                Strophe.Strophe,
+                Strophe.$build,
+                Strophe.$iq ,
+                Strophe.$msg,
+                Strophe.$pres
+            );
+            return Strophe;
+        });
+    } else {
+        // Browser globals
+        factory(
+            root.Strophe,
+            root.$build,
+            root.$iq ,
+            root.$msg,
+            root.$pres
+        );
+    }
+}(this, function (Strophe, $build, $iq, $msg, $pres) {
+Strophe.addConnectionPlugin('ping', {
+        _c: null,
+
+        // called by the Strophe.Connection constructor
+        init: function(conn)
+        {
+                this._c = conn;
+                Strophe.addNamespace('PING', "urn:xmpp:ping");
+        },
+
+        /**
+         * Function: ping
+         *
+         * Parameters:
+         * (String) to - The JID you want to ping
+         * (Function) success - Callback function on success
+         * (Function) error - Callback function on error
+         * (Integer) timeout - Timeout in milliseconds
+         */
+        ping: function(jid, success, error, timeout)
+        {
+                var id = this._c.getUniqueId('ping');
+                var iq = $iq({type: 'get', to: jid, id: id}).c(
+                                'ping', {xmlns: Strophe.NS.PING});
+                this._c.sendIQ(iq, success, error, timeout);
+        },
+
+        /**
+         * Function: pong
+         *
+         * Parameters:
+         * (Object) ping - The ping stanza from the server.
+         */
+        pong: function(ping)
+        {
+                var from = ping.getAttribute('from');
+                var id = ping.getAttribute('id');
+                var iq = $iq({type: 'result', to: from,id: id});
+                this._c.sendIQ(iq);
+        },
+
+        /**
+         * Function: addPingHandler
+         *
+         * Parameters:
+         * (Function) handler - Ping handler
+         *
+         * Returns:
+         * A reference to the handler that can be used to remove it.
+         */
+        addPingHandler: function(handler)
+        {
+                return this._c.addHandler(handler, Strophe.NS.PING, "iq", "get");
+        }
+});
+
+}));

Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů