Explorar el Código

Merge branch 'master' of github.com:jcbrand/converse.js

Conflicts:
	converse.js
JC Brand hace 12 años
padre
commit
ffbacad969
Se han modificado 3 ficheros con 214 adiciones y 201 borrados
  1. 3 3
      Libraries/jarnxmpp.core.handlers.js
  2. 132 123
      converse.css
  3. 79 75
      converse.js

+ 3 - 3
Libraries/jarnxmpp.core.handlers.js

@@ -2,7 +2,7 @@
 $msg:false, Strophe:false, setTimeout:false, navigator:false, jarn:false, google:false, jarnxmpp:false, jQuery:false, sessionStorage:false, $iq:false, $pres:false, Image:false, */
 
 (function (jarnxmpp, $, portal_url) {
-    
+
     portal_url = portal_url || '';
 
     jarnxmpp.Storage = {
@@ -230,9 +230,9 @@ $msg:false, Strophe:false, setTimeout:false, navigator:false, jarn:false, google
             data = {};
         }
         $.ajax({
-            'url':portal_url + '/@@xmpp-loader', 
+            'url':portal_url + '/@@xmpp-loader',
             'dataType': 'json',
-            'data': data, 
+            'data': data,
             'success': function (data) {
                 if (!(('rid' in data) && ('sid' in data) && ('BOSH_SERVICE' in data))) {
                     return;

+ 132 - 123
converse.css

@@ -3,44 +3,53 @@
 }
 
 #chatpanel {
-	z-index: 4; /*--Keeps the panel on top of all other elements--*/
-	position: fixed;
-	bottom: 0; right: 0;
+    z-index: 4; /*--Keeps the panel on top of all other elements--*/
+    position: fixed;
+    bottom: 0; right: 0;
     height: 332px;
     width: auto;
 }
 
 #toggle-controlbox {
-	position: fixed;
+    position: fixed;
     font-size: 80%;
-	bottom: 0; 
+    bottom: 0;
     right: 0;
     border-top-right-radius: 4px;
     border-top-left-radius: 4px;
-	background: #e3e2e2;
-	border: 1px solid #c3c3c3;
-	border-bottom: none;
+    background: #e3e2e2;
+    border: 1px solid #c3c3c3;
+    border-bottom: none;
     padding: 0.25em 0.5em;
     margin-right: 1em;
     height: 1.1em;
 }
 
+#toggle-online-users {
+    display: none;
+}
+
+#connecting-to-chat {
+    background: url('/spinner.gif') no-repeat;
+    padding-left: 1.4em;
+}
+
 .chat-head {
-	color: #ffffff;
+    color: #ffffff;
     margin: 0;
-	font-size: 100%;
+    font-size: 100%;
     border-top-right-radius: 4px;
     border-top-left-radius: 4px;
-	padding: 3px 0 3px 7px;
+    padding: 3px 0 3px 7px;
 }
 
 .chat-head-chatbox {
-	background-color: rgb(89, 106, 114);
-	background-color: rgba(89, 106, 114, 1);
+    background-color: rgb(89, 106, 114);
+    background-color: rgba(89, 106, 114, 1);
 }
 
 .chat-head-chatroom {
-	background-color: #2D617A;
+    background-color: #2D617A;
 }
 
 .chatroom .chat-area {
@@ -60,15 +69,15 @@
     height: 272px;
     background-color: white;
     overflow: auto;
-	border-right: 1px solid #999;
-	border-bottom: 1px solid #999;
+    border-right: 1px solid #999;
+    border-bottom: 1px solid #999;
     border-bottom-right-radius: 4px;
 }
 
 .participants ul.participant-list li {
-	overflow: hidden;
-	text-overflow: ellipsis;
-	white-space: nowrap;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
     display: block;
     font-size: 12px;
     padding: 0.5em 0 0 0.5em;
@@ -89,58 +98,58 @@ input.new-chatroom-name {
 }
 
 .chat-blink {
-	background-color: #176689;
-	border-right:1px solid #176689;
-	border-left:1px solid #176689;
+    background-color: #176689;
+    border-right:1px solid #176689;
+    border-left:1px solid #176689;
 }
 
 .chat-content {
     padding: 0.3em;
-	font-size: 13px;
-	color: #333333;
-	height:193px;
-	overflow-y:auto;
-	border:1px solid #999;
+    font-size: 13px;
+    color: #333333;
+    height:193px;
+    overflow-y:auto;
+    border:1px solid #999;
     border-bottom: 0;
     border-top: 0;
-	background-color: #ffffff;
-	line-height: 1.3em;
+    background-color: #ffffff;
+    line-height: 1.3em;
 }
 
 .chat-textarea {
-	border: 0;
+    border: 0;
     height: 50px;
     width: 100%;
 }
 
 .chat-textarea-chatbox-selected {
-	border: 1px solid #578308;
-	margin:0;
+    border: 1px solid #578308;
+    margin:0;
 }
 
 .chat-textarea-chatroom-selected {
-	border: 2px solid #2D617A;
-	margin:0;
+    border: 2px solid #2D617A;
+    margin:0;
 }
 
 .chat-info {
-	color:#666666;
+    color:#666666;
 
 }
 
 .chat-message-me {
-	font-weight: bold;
+    font-weight: bold;
     color: #436976;
 }
 
 .chat-message-room {
-	font-weight: bold;
+    font-weight: bold;
     color: #4B7003;
     white-space: nowrap;
 }
 
 .chat-message-them {
-	font-weight: bold;
+    font-weight: bold;
     color: #F62817;
     white-space: nowrap;
 }
@@ -149,7 +158,7 @@ input.new-chatroom-name {
     color: #808080;
 }
 
-div#settings, 
+div#settings,
 div#chatrooms {
     height: 279px;
 }
@@ -160,11 +169,11 @@ p.not-implemented {
     color: #808080;
 }
 
-div.delayed .chat-message-them { 
+div.delayed .chat-message-them {
     color: #FB5D50;
 }
 
-div.delayed .chat-message-me { 
+div.delayed .chat-message-me {
     color: #7EABBB;
 }
 
@@ -175,30 +184,30 @@ div.delayed .chat-message-me {
 }
 
 .chat-head .avatar {
-	height: 35px;
-	float: left;
-	margin-right: 6px;
+    height: 35px;
+    float: left;
+    margin-right: 6px;
 }
 
 div.chat-title {
     height: 1.1em;
     color: white;
-	font-weight: bold;
-	line-height: 15px;
-	display: block;
+    font-weight: bold;
+    line-height: 15px;
+    display: block;
     margin-top: 2px;
-	margin-right: 20px;
-	overflow: hidden;
-	text-overflow: ellipsis;
-	white-space: nowrap;
-	text-shadow: rgba(0,0,0,0.51) 0 -1px 0;
+    margin-right: 20px;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+    text-shadow: rgba(0,0,0,0.51) 0 -1px 0;
 }
 
 .chat-head-chatbox,
 .chat-head-chatroom {
     background: linear-gradient(top, rgba(206,220,231,1) 0%,rgba(89,106,114,1) 100%);
-	height: 33px;
-	position: relative;
+    height: 33px;
+    position: relative;
 }
 
 p.user-custom-message,
@@ -207,9 +216,9 @@ p.chatroom-topic {
     font-style: italic;
     height: 1.3em;
     clear: right;
-	overflow: hidden;
-	text-overflow: ellipsis;
-	white-space: nowrap;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
 }
 
 .activated{
@@ -224,7 +233,7 @@ a.subscribe-to-user {
 
 div.add-xmpp-contact {
     display: block;
-    border:1px solid #ddd; 
+    border:1px solid #ddd;
     padding: 3px 3px 3px 3px;
     margin: 0 0.5em;
     clear: both;
@@ -233,12 +242,12 @@ div.add-xmpp-contact {
 }
 
 div.add-xmpp-contact a.add-xmpp-contact {
-	text-shadow: 0 1px 0 rgba(250, 250, 250, 1);
+    text-shadow: 0 1px 0 rgba(250, 250, 250, 1);
     padding-left: 1.5em;
 }
 
 #fancy-xmpp-status-select a.change-xmpp-status-message {
-	text-shadow: 0 1px 0 rgba(250, 250, 250, 1);
+    text-shadow: 0 1px 0 rgba(250, 250, 250, 1);
     background: url('/pencil_icon.png') no-repeat right top;
     float: right;
     clear: right;
@@ -247,13 +256,13 @@ div.add-xmpp-contact a.add-xmpp-contact {
 }
 
 #fancy-xmpp-status-select a.choose-xmpp-status {
-	text-shadow: 0 1px 0 rgba(250, 250, 250, 1);
+    text-shadow: 0 1px 0 rgba(250, 250, 250, 1);
     padding-left: 1.5em;
     width: 140px;
     display: block;
-	overflow: hidden;
-	text-overflow: ellipsis;
-	white-space: nowrap;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
     float: left;
 }
 
@@ -272,13 +281,13 @@ form.search-xmpp-contact input {
 
 .oc-chat-head {
     margin: 0;
-	color: #FFF;
+    color: #FFF;
     border-top-right-radius: 4px;
     border-top-left-radius: 4px;
     height: 35px;
     clear: right;
     background-color: #5390C8;
-	padding: 3px 0 0 0;
+    padding: 3px 0 0 0;
 }
 
 .close-chatbox-button {
@@ -334,24 +343,24 @@ form.search-xmpp-contact input {
 
 #xmppchat-roster dd.current-xmpp-contact,
 #xmppchat-roster dd.current-xmpp-contact:hover {
-	background: url(images/user_online_panel.png) no-repeat 5px 2px;
+    background: url(images/user_online_panel.png) no-repeat 5px 2px;
 }
 
 #xmppchat-roster dd.current-xmpp-contact.offline:hover,
 #xmppchat-roster dd.current-xmpp-contact.unavailable:hover,
 #xmppchat-roster dd.current-xmpp-contact.offline,
 #xmppchat-roster dd.current-xmpp-contact.unavailable {
-	background: url(images/user_offline_panel.png) no-repeat 5px 2px;
+    background: url(images/user_offline_panel.png) no-repeat 5px 2px;
 }
 
 #xmppchat-roster dd.current-xmpp-contact.busy,
 #xmppchat-roster dd.current-xmpp-contact.busy:hover {
-	background: url(images/user_busy_panel.png) no-repeat 5px 2px;
+    background: url(images/user_busy_panel.png) no-repeat 5px 2px;
 }
 
 #xmppchat-roster dd.current-xmpp-contact.away,
 #xmppchat-roster dd.current-xmpp-contact.away:hover {
-	background: url(images/user_away_panel.png) no-repeat 5px 2px;
+    background: url(images/user_away_panel.png) no-repeat 5px 2px;
 }
 
 #xmppchat-roster dd.requesting-xmpp-contact button{
@@ -360,7 +369,7 @@ form.search-xmpp-contact input {
 
 #xmppchat-roster dd a {
     margin-left: 2em;
-	text-shadow: 0 1px 0 rgba(250, 250, 250, 1);
+    text-shadow: 0 1px 0 rgba(250, 250, 250, 1);
 }
 
 .remove-xmpp-contact-dialog .ui-dialog-buttonpane {
@@ -386,7 +395,7 @@ form.search-xmpp-contact input {
     color: #666;
     border: none;
     padding: 0.3em 0.5em 0.3em 0.5em;
-	text-shadow: 0 1px 0 rgba(250, 250, 250, 1);
+    text-shadow: 0 1px 0 rgba(250, 250, 250, 1);
 }
 
 #available-chatrooms dt {
@@ -404,8 +413,8 @@ dd.available-chatroom,
     border: none;
     display: block;
     padding: 0 0.5em 0 0.5em;
-	color: #3f3f3f;
-	text-shadow: 0 1px 0 rgba(250, 250, 250, 1);
+    color: #3f3f3f;
+    text-shadow: 0 1px 0 rgba(250, 250, 250, 1);
 }
 
 #xmppchat-roster dd a.remove-xmpp-contact {
@@ -417,8 +426,8 @@ dd.available-chatroom,
 
 .chatbox,
 .chatroom {
-	box-shadow: 1px 1px 5px 1px rgba(0,0,0,0.4);
-	display:none;
+    box-shadow: 1px 1px 5px 1px rgba(0,0,0,0.4);
+    display:none;
     float: right;
     margin-right: 15px;
     z-index: 3; /* So that it's higher than the content actions */
@@ -426,16 +435,16 @@ dd.available-chatroom,
 }
 
 .chatbox {
-	width: 200px;
+    width: 200px;
 }
 
 .chatroom {
-	width: 300px;
+    width: 300px;
     height: 311px;
 }
 
 .oc-chat-content {
-	height:272px; 
+    height:272px;
     width: 199px;
     padding: 0;
 }
@@ -456,12 +465,12 @@ dd.available-chatroom,
 }
 
 div#controlbox-panes {
-	background: -moz-linear-gradient(top, rgba(255,255,255,1) 0%, rgba(240,240,240,1) 100%); /* FF3.6+ */
-	background: -ms-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(240,240,240,1) 100%); /* IE10+ */
-	background: -o-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(240,240,240,1) 100%); /* Opera 11.10+ */
-	background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,1)), color-stop(100%,rgba(240,240,240,1))); /* Chrome,Safari4+ */
-	background: -webkit-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(240,240,240,1) 100%); /* Chrome10+,Safari5.1+ */
-	background: linear-gradient(top, rgba(255,255,255,1) 0%,rgba(240,240,240,1) 100%); /* W3C */
+    background: -moz-linear-gradient(top, rgba(255,255,255,1) 0%, rgba(240,240,240,1) 100%); /* FF3.6+ */
+    background: -ms-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(240,240,240,1) 100%); /* IE10+ */
+    background: -o-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(240,240,240,1) 100%); /* Opera 11.10+ */
+    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,1)), color-stop(100%,rgba(240,240,240,1))); /* Chrome,Safari4+ */
+    background: -webkit-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(240,240,240,1) 100%); /* Chrome10+,Safari5.1+ */
+    background: linear-gradient(top, rgba(255,255,255,1) 0%,rgba(240,240,240,1) 100%); /* W3C */
     background-color: white;
     border-bottom-left-radius: 4px;
     border-bottom-right-radius: 4px;
@@ -482,18 +491,18 @@ select#select-xmpp-status {
 /* @group Tabs */
 
 .chat-head #controlbox-tabs {
-	text-align: center;
-	display: inline;
-	overflow: hidden;
-	font-size: 12px;
-	list-style-type: none;
+    text-align: center;
+    display: inline;
+    overflow: hidden;
+    font-size: 12px;
+    list-style-type: none;
 }
 
 /* single tab */
 .chat-head #controlbox-tabs li {
-	width: 40%;
+    width: 40%;
     float:left;
-	text-shadow: white 0 1px 0;
+    text-shadow: white 0 1px 0;
 }
 
 ul#controlbox-tabs li a {
@@ -509,27 +518,27 @@ ul#controlbox-tabs li a {
     border-top-left-radius: 4px;
     color:#666;
     background-color:#EEE;
-	background: -moz-linear-gradient(top, rgba(245,245,245,1) 0%, rgba(255,255,255,1) 100%); /* FF3.6+ */
-	background: -ms-linear-gradient(top, rgba(245,245,245,1) 0%, rgba(255,255,255,1) 100%); /* IE10+ */
-	background: -o-linear-gradient(top, rgba(245,245,245,1) 0%, rgba(255,255,255,1) 100%); /* Opera 11.10+ */
-	background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,1)), color-stop(100%,rgba(245,245,245,1))); /* Chrome,Safari4+ */
-	background: -webkit-linear-gradient(top, rgba(245,245,245,1) 0%, rgba(255,255,255,1) 100%); /* Chrome10+,Safari5.1+ */
-	background: linear-gradient(top, rgba(245,245,245,1) 0%, rgba(255,255,255,1) 100%); /* W3C */
-	text-shadow: 0 1px 0 rgba(250, 250, 250, 1);
+    background: -moz-linear-gradient(top, rgba(245,245,245,1) 0%, rgba(255,255,255,1) 100%); /* FF3.6+ */
+    background: -ms-linear-gradient(top, rgba(245,245,245,1) 0%, rgba(255,255,255,1) 100%); /* IE10+ */
+    background: -o-linear-gradient(top, rgba(245,245,245,1) 0%, rgba(255,255,255,1) 100%); /* Opera 11.10+ */
+    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,1)), color-stop(100%,rgba(245,245,245,1))); /* Chrome,Safari4+ */
+    background: -webkit-linear-gradient(top, rgba(245,245,245,1) 0%, rgba(255,255,255,1) 100%); /* Chrome10+,Safari5.1+ */
+    background: linear-gradient(top, rgba(245,245,245,1) 0%, rgba(255,255,255,1) 100%); /* W3C */
+    text-shadow: 0 1px 0 rgba(250, 250, 250, 1);
 }
 
 .chat-head #controlbox-tabs li a:hover {
-	color: black;
+    color: black;
 }
 
 .chat-head #controlbox-tabs li a {
-	background-color: rgba(240,240,240,1);
-	box-shadow: inset 0 0 8px rgba(0,0,0,0.2);
+    background-color: rgba(240,240,240,1);
+    box-shadow: inset 0 0 8px rgba(0,0,0,0.2);
 }
 
 ul#controlbox-tabs a.current, ul#controlbox-tabs a.current:hover {
-	box-shadow: none; 
-    color: #000; 
+    box-shadow: none;
+    color: #000;
     border-bottom: 0;
     height: 35px;
 }
@@ -566,7 +575,7 @@ form.sendXMPPMessage {
     padding: 1px 2px 1px 1px;
 }
 
-/* status dropdown styles */       
+/* status dropdown styles */
 dl.dropdown {
     margin-right: 0.5em;
 }
@@ -582,7 +591,7 @@ input.custom-xmpp-status {
 }
 
 #fancy-xmpp-status-select {
-    border:1px solid #ddd; 
+    border:1px solid #ddd;
     height: 22px;
 }
 
@@ -590,43 +599,43 @@ input.custom-xmpp-status {
     cursor:pointer; display:block; padding:5px;
 }
 
-.dropdown dd ul { 
-    list-style:none; 
-    padding:5px 0; 
-    position:absolute; left:0; top:0; 
-    border:1px solid #ddd; 
+.dropdown dd ul {
+    list-style:none;
+    padding:5px 0;
+    position:absolute; left:0; top:0;
+    border:1px solid #ddd;
     border-top: 0;
     width: 99%;
     background-color: #FFF;
     z-index: 4;
 }
 
-.dropdown dd ul li a:hover { 
+.dropdown dd ul li a:hover {
     background-color: #bed6e5;
 }
 
-.dropdown span.value { 
+.dropdown span.value {
     display:none;
 }
 
-.dropdown dd ul li a { 
-    padding:5px 5px 5px 30px; 
+.dropdown dd ul li a {
+    padding:5px 5px 5px 30px;
     display:block;
 }
 
-.dropdown a.online { 
-	background: url(images/user_online_panel.png) no-repeat left;
+.dropdown a.online {
+    background: url(images/user_online_panel.png) no-repeat left;
 }
 
-.dropdown a.offline { 
-	background: url(images/user_offline_panel.png) no-repeat left;
+.dropdown a.offline {
+    background: url(images/user_offline_panel.png) no-repeat left;
 }
 
-.dropdown a.busy { 
-	background: url(images/user_busy_panel.png) no-repeat left;
+.dropdown a.busy {
+    background: url(images/user_busy_panel.png) no-repeat left;
 }
 
-.dropdown a.away { 
-	background: url(images/user_away_panel.png) no-repeat left;
+.dropdown a.away {
+    background: url(images/user_away_panel.png) no-repeat left;
 }
 

+ 79 - 75
converse.js

@@ -14,7 +14,7 @@
     if (console===undefined || console.log===undefined) {
         console = { log: function () {}, error: function () {} };
     }
-    if (typeof define === 'function' && define.amd) { 
+    if (typeof define === 'function' && define.amd) {
         require.config({
             // paths: {
             //     "patterns": "Libraries/Patterns"
@@ -25,7 +25,7 @@
                     //These script dependencies should be loaded before loading
                     //backbone.js
                     deps: [
-                        'Libraries/underscore', 
+                        'Libraries/underscore',
                         'jquery'],
                     //Once loaded, use the global 'Backbone' as the
                     //module value.
@@ -62,7 +62,7 @@
                 return factory(jQuery, store, _, console);
             }
         );
-    } else { 
+    } else {
         // Browser globals
         var store = new Burry.Store('collective.xmpp.chat');
         _.templateSettings = {
@@ -84,12 +84,12 @@
             pad = function (num) {
                 return (num < 10) ? '0' + num : '' + num;
             };
-            return date.getUTCFullYear() + '-' + 
-                pad(date.getUTCMonth() + 1) + '-' + 
-                pad(date.getUTCDate()) + 'T' + 
-                pad(date.getUTCHours()) + ':' + 
-                pad(date.getUTCMinutes()) + ':' + 
-                pad(date.getUTCSeconds()) + '.000Z'; 
+            return date.getUTCFullYear() + '-' +
+                pad(date.getUTCMonth() + 1) + '-' +
+                pad(date.getUTCDate()) + 'T' +
+                pad(date.getUTCHours()) + ':' +
+                pad(date.getUTCMinutes()) + ':' +
+                pad(date.getUTCSeconds()) + '.000Z';
         }
     };
 
@@ -132,7 +132,7 @@
     };
 
     xmppchat.collections = {
-        /* FIXME: XEP-0136 specifies 'urn:xmpp:archive' but the mod_archive_odbc 
+        /* FIXME: XEP-0136 specifies 'urn:xmpp:archive' but the mod_archive_odbc
         *  add-on for ejabberd wants the URL below. This might break for other
         *  Jabber servers.
         */
@@ -150,17 +150,17 @@
                     .c('max')
                     .t('1');
 
-        xmppchat.connection.sendIQ(iq, 
+        xmppchat.connection.sendIQ(iq,
                     callback,
-                    function () { 
-                        console.log('Error while retrieving collections'); 
+                    function () {
+                        console.log('Error while retrieving collections');
                     });
     };
 
     xmppchat.collections.getLastMessages = function (jid, callback) {
         var that = this;
         this.getLastCollection(jid, function (result) {
-            // Retrieve the last page of a collection (max 30 elements). 
+            // Retrieve the last page of a collection (max 30 elements).
             var $collection = $(result).find('chat'),
                 jid = $collection.attr('with'),
                 start = $collection.attr('start'),
@@ -208,7 +208,7 @@
             var msgs = store.get(hex_sha1(this.get('own_jid')+bare_jid)) || [];
             if (msgs.length) {
                 return sjcl.decrypt(hex_sha1(this.get('own_jid')), msgs[msgs.length-1]);
-            } 
+            }
         },
 
         clearMessages: function (jid) {
@@ -218,7 +218,7 @@
 
         getOpenChats: function () {
             var key = hex_sha1(this.get('own_jid')+'-open-chats'),
-                chats = store.get(key) || [], 
+                chats = store.get(key) || [],
                 decrypted_chats = [],
                 i;
 
@@ -255,7 +255,7 @@
             store.flush();
         }
     });
-    
+
     xmppchat.ChatBox = Backbone.Model.extend({
         initialize: function () {
             this.set({
@@ -279,15 +279,15 @@
         },
 
         message_template: _.template(
-                            '<div class="chat-message {{extra_classes}}">' + 
-                                '<span class="chat-message-{{sender}}">{{time}} {{username}}:&nbsp;</span>' + 
-                                '<span class="chat-message-content">{{message}}</span>' + 
+                            '<div class="chat-message {{extra_classes}}">' +
+                                '<span class="chat-message-{{sender}}">{{time}} {{username}}:&nbsp;</span>' +
+                                '<span class="chat-message-content">{{message}}</span>' +
                             '</div>'),
 
         action_template: _.template(
-                            '<div class="chat-message {{extra_classes}}">' + 
-                                '<span class="chat-message-{{sender}}">{{time}}:&nbsp;</span>' + 
-                                '<span class="chat-message-content">{{message}}</span>' + 
+                            '<div class="chat-message {{extra_classes}}">' +
+                                '<span class="chat-message-{{sender}}">{{time}}:&nbsp;</span>' +
+                                '<span class="chat-message-content">{{message}}</span>' +
                             '</div>'),
 
         autoLink: function (text) {
@@ -314,9 +314,9 @@
             if (minutes.length==1) {minutes = '0'+minutes;}
             $chat_content.find('div.chat-event').remove();
             $chat_content.append(this.message_template({
-                                'sender': 'me', 
-                                'time': time, 
-                                'message': message, 
+                                'sender': 'me',
+                                'time': time,
+                                'message': message,
                                 'username': 'me',
                                 'extra_classes': ''
                             }));
@@ -331,8 +331,8 @@
         },
 
         messageReceived: function (message) {
-            /* XXX: event.mtype should be 'xhtml' for XHTML-IM messages, 
-                but I only seem to get 'text'. 
+            /* XXX: event.mtype should be 'xhtml' for XHTML-IM messages,
+                but I only seem to get 'text'.
             */
             var body = this.autoLink($message.children('body').text()),
                 from = Strophe.getBareJidFromJid($message.attr('from')),
@@ -368,13 +368,13 @@
                     // XXX: Test properly (for really old messages we somehow need to show
                     // their date as well)
                     stamp = $message.find('delay').attr('stamp');
-                    time = (new Date(stamp)).toLocaleTimeString().substring(0,5); 
+                    time = (new Date(stamp)).toLocaleTimeString().substring(0,5);
                 } else {
-                    time = (new Date()).toLocaleTimeString().substring(0,5); 
+                    time = (new Date()).toLocaleTimeString().substring(0,5);
                 }
                 $chat_content.append(
                         this.message_template({
-                            'sender': sender, 
+                            'sender': sender,
                             'time': time,
                             'message': body,
                             'username': username,
@@ -391,11 +391,11 @@
 
         insertClientStoredMessages: function () {
             var msgs = xmppchat.storage.getMessages(this.model.get('jid')),
-                $content = this.$el.find('.chat-content'), 
-                prev_date, this_date, now, separator, i; 
+                $content = this.$el.find('.chat-content'),
+                prev_date, this_date, now, separator, i;
 
             for (i=0; i<_.size(msgs); i++) {
-                var msg = msgs[i], 
+                var msg = msgs[i],
                     msg_array = msg.split(' ', 2),
                     date = msg_array[0];
 
@@ -416,16 +416,16 @@
                 if (msg_array[1] == 'to') {
                     $content.append(
                         this.message_template({
-                            'sender': 'me', 
+                            'sender': 'me',
                             'time': this_date.toLocaleTimeString().substring(0,5),
-                            'message': msg, 
+                            'message': msg,
                             'username': 'me',
                             'extra_classes': 'delayed'
                     }));
                 } else {
                     $content.append(
                         this.message_template({
-                            'sender': 'them', 
+                            'sender': 'them',
                             'time': this_date.toLocaleTimeString().substring(0,5),
                             'message': msg,
                             'username': this.model.get('fullname').split(' ')[0],
@@ -563,7 +563,7 @@
 		                '</a>' +
                         '<p class="user-custom-message"><p/>' +
                     '</div>' +
-                    '<div class="chat-content"></div>' + 
+                    '<div class="chat-content"></div>' +
                     '<form class="sendXMPPMessage" action="" method="post">' +
                     '<textarea ' +
                         'type="text" ' +
@@ -650,7 +650,7 @@
             $.getJSON(portal_url + "/search-users?q=" + $(ev.target).find('input.username').val(), function (data) {
                 var $results_el = $('#found-users');
                 $(data).each(function (idx, obj) {
-                    if ($results_el.children().length > 0) {  
+                    if ($results_el.children().length > 0) {
                         $results_el.empty();
                     }
                     $results_el.append(
@@ -717,7 +717,7 @@
 
         updateRoomsList: function () {
             xmppchat.connection.muc.listRooms(xmppchat.connection.muc_domain, $.proxy(function (iq) {
-                var room, name, jid, i, 
+                var room, name, jid, i,
                     rooms = $(iq).find('query').find('item');
                 this.$el.find('#available-chatrooms').find('dd.available-chatroom').remove();
                 if (rooms.length) {
@@ -795,7 +795,7 @@
                 $tab_panel = $($tab.attr('href')),
                 $sibling_panel = $($sibling.attr('href'));
 
-            $sibling_panel.fadeOut('fast', function () { 
+            $sibling_panel.fadeOut('fast', function () {
                 $sibling.removeClass('current');
                 $tab.addClass('current');
                 $tab_panel.fadeIn('fast', function () {
@@ -842,8 +842,8 @@
         closeChatRoom: function () {
             this.closeChat();
             xmppchat.connection.muc.leave(
-                            this.model.get('jid'), 
-                            this.model.get('nick'), 
+                            this.model.get('jid'),
+                            this.model.get('nick'),
                             this.onLeave,
                             undefined);
             delete xmppchat.chatboxesview.views[this.model.get('jid')];
@@ -865,7 +865,7 @@
                 if (message !== '') {
                     this.sendChatRoomMessage(message);
                 }
-            } 
+            }
         },
 
         sendChatRoomMessage: function (body) {
@@ -988,16 +988,16 @@
                         body = body.replace(/^\/me/, '*'+sender);
                         $chat_content.append(
                                 this.action_template({
-                                    'sender': 'room', 
+                                    'sender': 'room',
                                     'time': (new Date()).toLocaleTimeString().substring(0,5),
-                                    'message': body, 
+                                    'message': body,
                                     'username': sender,
                                     'extra_classes': ($(message).find('delay').length > 0) && 'delayed' || ''
                                 }));
                     } else {
                         $chat_content.append(
                                 this.message_template({
-                                    'sender': 'room', 
+                                    'sender': 'room',
                                     'time': (new Date()).toLocaleTimeString().substring(0,5),
                                     'message': body,
                                     'username': sender,
@@ -1061,11 +1061,11 @@
                 }
             }, this));
         },
-        
+
         isChatRoom: function (jid) {
             return Strophe.getDomainFromJid(jid) === xmppchat.connection.muc_domain;
         },
-        
+
         createChatBox: function (jid, data) {
             var box, view;
             if (this.isChatRoom(jid)) {
@@ -1075,14 +1075,14 @@
                 });
             } else {
                 box = new xmppchat.ChatBox({
-                                        'id': jid, 
-                                        'jid': jid, 
-                                        'fullname': data.fullname, 
+                                        'id': jid,
+                                        'jid': jid,
+                                        'fullname': data.fullname,
                                         'portrait_url': data.portrait_url,
                                         'user_profile_url': data.user_profile_url
                                     });
                 view = new xmppchat.ChatBoxView({
-                    model: box 
+                    model: box
                 });
             }
             this.views[jid] = view.render();
@@ -1109,7 +1109,7 @@
                 $.getJSON(portal_url + "/xmpp-userinfo?user_id=" + Strophe.getNodeFromJid(jid), $.proxy(function (data) {
                     view = this.createChatBox(jid, data);
                 }, this));
-            } 
+            }
         },
 
         showChat: function (jid) {
@@ -1212,7 +1212,7 @@
                 'bare_jid': Strophe.getBareJidFromJid(jid),
                 'user_id': user_id,
                 'subscription': subscription,
-                'fullname': name, 
+                'fullname': name,
                 'resources': [],
                 'presence_type': 'offline',
                 'status': 'offline'
@@ -1291,7 +1291,6 @@
                 ask = item.get('ask'),
                 that = this,
                 subscription = item.get('subscription');
-
             this.$el.addClass(item.get('presence_type'));
             
             if (ask === 'subscribe') {
@@ -1317,7 +1316,7 @@
                     that.openChat();
                 });
             }
-            
+
             // Event handlers
             this.$el.delegate('a.remove-xmpp-contact','click', function (ev) {
                 ev.preventDefault();
@@ -1345,7 +1344,7 @@
             var presence_type = rosteritem.get('presence_type'),
                 rank = 4;
             switch(presence_type) {
-                case 'offline': 
+                case 'offline':
                     rank = 0;
                     break;
                 case 'unavailable':
@@ -1393,7 +1392,7 @@
             var model = new xmppchat.RosterItem(jid, subscription, ask, name);
             this.add(model);
         },
-            
+
         addResource: function (bare_jid, resource) {
             var item = this.getItem(bare_jid),
                 resources;
@@ -1475,13 +1474,13 @@
             if (this.isSelf(bare_jid)) {
                 if (xmppchat.connection.jid != jid) {
                     // Another resource has changed it's status, we'll update ours as well.
-                    // FIXME: We should ideally differentiate between converse.js using 
+                    // FIXME: We should ideally differentiate between converse.js using
                     // resources and other resources (i.e Pidgin etc.)
                     xmppchat.xmppstatus.set({'status': presence_type});
-                } 
+                }
                 return true;
             } else if (($(presence).find('x').attr('xmlns') || '').indexOf(Strophe.NS.MUC) === 0) {
-                return true; // Ignore MUC 
+                return true; // Ignore MUC
             }
 
             if ((status_message.length > 0) && (status_message.text() && (presence_type !== 'unavailable'))) {
@@ -1526,10 +1525,10 @@
                 }
 
             } else if (presence_type === 'unsubscribed') {
-                /* Upon receiving the presence stanza of type "unsubscribed", 
-                * the user SHOULD acknowledge receipt of that subscription state 
-                * notification by sending a presence stanza of type "unsubscribe" 
-                * this step lets the user's server know that it MUST no longer 
+                /* Upon receiving the presence stanza of type "unsubscribed",
+                * the user SHOULD acknowledge receipt of that subscription state
+                * notification by sending a presence stanza of type "unsubscribe"
+                * this step lets the user's server know that it MUST no longer
                 * send notification of the subscription state change to the user.
                 */
                 xmppchat.xmppstatus.sendPresence('unsubscribe');
@@ -1537,7 +1536,7 @@
                     xmppchat.chatboxesview.controlbox.roster.remove(bare_jid);
                     xmppchat.connection.roster.remove(bare_jid);
                 }
-            } else { 
+            } else {
                 if ((presence_type === undefined) && (show)) {
                     if (show.text() === 'chat') {
                         presence_type = 'online';
@@ -1628,7 +1627,7 @@
                     $my_contacts.after($my_contacts.siblings('dd.current-xmpp-contact.away').tsort('a', crit));
                     $my_contacts.after($my_contacts.siblings('dd.current-xmpp-contact.busy').tsort('a', crit));
                     $my_contacts.after($my_contacts.siblings('dd.current-xmpp-contact.online').tsort('a', crit));
-                } 
+                }
             }
             // Hide the headings if there are no contacts under them
             _.each([$my_contacts, $contact_requests, $pending_contacts], function (h) {
@@ -1781,12 +1780,12 @@
             this.$el.find('#fancy-xmpp-status-select')
                     .html(this.status_template({
                             'status_message': "I am " + presence_type,
-                            'presence_type': presence_type 
+                            'presence_type': presence_type
                             }));
             // iterate through all the <option> elements and create UL
             options.each(function(){
                 $(that.el).find("#target dd ul").append(that.option_template({
-                                                                'value': $(this).val(), 
+                                                                'value': $(this).val(),
                                                                 'text': $(this).text()
                                                             })).hide();
             });
@@ -1794,7 +1793,7 @@
 
             // Listen for status change on the model and initialize
             // ----------------------------------------------------
-            this.options.model.on("change", $.proxy(this.updateStatusUI, this)); 
+            this.options.model.on("change", $.proxy(this.updateStatusUI, this));
             this.model.initStatus();
         }
     });
@@ -1803,6 +1802,7 @@
     // --------------
     $(document).ready($.proxy(function () {
         var chatdata = $('div#collective-xmpp-chat-data'),
+            $connecting = $('span#connecting-to-chat'),
             $toggle = $('a#toggle-online-users');
         $toggle.unbind('click');
 
@@ -1815,6 +1815,8 @@
         }).render();
 
         $(document).bind('jarnxmpp.disconnected', $.proxy(function (ev, conn) {
+            $connecting.show();
+            $toggle.hide();
             console.log("Connection Failed :(");
         }, this));
 
@@ -1832,11 +1834,11 @@
             this.chatboxesview = new this.ChatBoxesView({'model': this.chatboxes});
 
             this.connection.addHandler(
-                    $.proxy(this.roster.subscribeToSuggestedItems, this.roster), 
+                    $.proxy(this.roster.subscribeToSuggestedItems, this.roster),
                     'http://jabber.org/protocol/rosterx', 'message', null);
 
             this.connection.roster.registerCallback(
-                    $.proxy(this.roster.rosterHandler, this.roster), 
+                    $.proxy(this.roster.rosterHandler, this.roster),
                     null, 'presence', null);
 
             this.connection.roster.get($.proxy(function () {
@@ -1847,12 +1849,12 @@
                             }, this.roster), null, 'presence', null);
 
                     this.connection.addHandler(
-                            $.proxy(function (message) { 
+                            $.proxy(function (message) {
                                 this.chatboxesview.messageReceived(message);
                                 return true;
                             }, this), null, 'message', 'chat');
 
-                    // XMPP Status 
+                    // XMPP Status
                     this.xmppstatus = new this.XMPPStatus();
                     this.xmppstatusview = new this.XMPPStatusView({
                         'model': this.xmppstatus
@@ -1861,6 +1863,8 @@
 
             // Controlbox toggler
             if ($toggle.length) {
+                $connecting.hide();
+                $toggle.show();
                 $toggle.bind('click', $.proxy(function (e) {
                     e.preventDefault();
                     if ($("div#controlbox").is(':visible')) {