Browse Source

Merge branch 'master' into gh-pages

JC Brand 12 năm trước cách đây
mục cha
commit
0d9fa4a9ff
8 tập tin đã thay đổi với 413 bổ sung279 xóa
  1. 4 4
      README.rst
  2. 47 36
      converse.css
  3. 211 168
      converse.js
  4. 57 0
      docs/NOTES.rst
  5. 10 10
      index.html
  6. 7 1
      main.js
  7. 71 60
      spec/MainSpec.js
  8. 6 0
      tests.html

+ 4 - 4
README.rst

@@ -2,12 +2,12 @@
 converse.js
 ===========
 
-Converse.js_ implements an XMPP_ based instant messaging client in the browser.
+Converse.js_ is a web based `XMPP/Jabber`_ instant messaging client.
 
 It is used by collective.xmpp.chat_, which is a Plone_ instant messaging add-on.
 
-The ultimate goal is to enable anyone to add chat functionality to their websites, regardless of the backend.
-This is currently possible, except for adding new contacts, which still makes an XHR call to the (Plone) backend to fetch user info.
+The ultimate goal is to enable anyone to add chat functionality to their websites, independent of any backend.
+You will however need an XMPP server to connect to, either your own, or a public one.
 
 --------
 Features
@@ -54,7 +54,7 @@ Licence
 .. _require.js: http:/requirejs.org
 .. _collective.xmpp.chat: http://github.com/collective/collective.xmpp.chat
 .. _Plone: http://plone.org
-.. _XMPP: http://xmpp.org
+.. _`XMPP/Jabber`: http://xmpp.org
 .. _MIT: http://opensource.org/licenses/mit-license.php
 .. _GPL: http://opensource.org/licenses/gpl-license.php
 .. _here: http://opkode.com/media/blog/instant-messaging-for-plone-with-javascript-and-xmpp

+ 47 - 36
converse.css

@@ -182,6 +182,10 @@ div.delayed .chat-message-me {
     color: #7EABBB;
 }
 
+input.error {
+    border: 1px solid red;
+}
+
 .chat-message-error {
     color:#76797C;
     font-size:90%;
@@ -234,9 +238,8 @@ a.subscribe-to-user {
     font-weight: bold;
 }
 
-dl.add-xmpp-contact {
+dl.add-converse-contact {
     margin: 0 0 0 0.5em;
-    padding-top: 3px;
     z-index: 21;
     background: url('images/add_icon.png') no-repeat 3px;
 }
@@ -245,8 +248,13 @@ dt#xmpp-contact-search {
     padding-top: 3px;
 }
 
+.fancy-dropdown {
+    border:1px solid #ddd;
+    height: 22px;
+}
+
 .fancy-dropdown a.choose-xmpp-status,
-.fancy-dropdown a.add-xmpp-contact {
+.fancy-dropdown a.toggle-xmpp-contact-form {
     text-shadow: 0 1px 0 rgba(250, 250, 250, 1);
     padding-left: 1.5em;
     width: 140px;
@@ -272,7 +280,7 @@ dt#xmpp-contact-search {
 
 ul#found-users {
     padding: 10px 0 5px 5px;
-    border: 0; 
+    border: 0;
 }
 
 form.search-xmpp-contact {
@@ -283,7 +291,7 @@ form.search-xmpp-contact {
 }
 
 form.search-xmpp-contact input {
-    width: 9em;
+    width: 8em;
 }
 
 .oc-chat-head {
@@ -340,42 +348,42 @@ form.search-xmpp-contact input {
     padding-top: 0.5em;
 }
 
-#xmppchat-roster dd.odd {
+#converse-roster dd.odd {
     background-color: #DCEAC5; /* Make this difference */
 }
 
-#xmppchat-roster dd.current-xmpp-contact {
+#converse-roster dd.current-xmpp-contact {
     clear: both;
 }
 
-#xmppchat-roster dd.current-xmpp-contact,
-#xmppchat-roster dd.current-xmpp-contact:hover {
+#converse-roster dd.current-xmpp-contact,
+#converse-roster dd.current-xmpp-contact:hover {
     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 {
+#converse-roster dd.current-xmpp-contact.offline:hover,
+#converse-roster dd.current-xmpp-contact.unavailable:hover,
+#converse-roster dd.current-xmpp-contact.offline,
+#converse-roster dd.current-xmpp-contact.unavailable {
     background: url(images/user_offline_panel.png) no-repeat 5px 2px;
 }
 
-#xmppchat-roster dd.current-xmpp-contact.dnd,
-#xmppchat-roster dd.current-xmpp-contact.dnd:hover {
+#converse-roster dd.current-xmpp-contact.dnd,
+#converse-roster dd.current-xmpp-contact.dnd:hover {
     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 {
+#converse-roster dd.current-xmpp-contact.away,
+#converse-roster dd.current-xmpp-contact.away:hover {
     background: url(images/user_away_panel.png) no-repeat 5px 2px;
 }
 
-#xmppchat-roster dd.requesting-xmpp-contact button{
+#converse-roster dd.requesting-xmpp-contact button{
     margin-left: 0.5em;
 }
 
-#xmppchat-roster dd a,
-#xmppchat-roster dd span {
+#converse-roster dd a,
+#converse-roster dd span {
     text-shadow: 0 1px 0 rgba(250, 250, 250, 1);
     display: inline-block;
     overflow: hidden;
@@ -383,12 +391,12 @@ form.search-xmpp-contact input {
     text-overflow: ellipsis;
 }
 
-#xmppchat-roster dd a {
+#converse-roster dd a {
     margin-left: 1.5em;
     width: 113px;
 }
 
-#xmppchat-roster dd span {
+#converse-roster dd span {
     width: 125px;
 }
 
@@ -396,7 +404,7 @@ form.search-xmpp-contact input {
     border: none;
 }
 
-#xmppchat-roster {
+#converse-roster {
     height: 200px;
     overflow-y: scroll;
     width: 100%;
@@ -408,7 +416,7 @@ form.search-xmpp-contact input {
 }
 
 #available-chatrooms dt,
-#xmppchat-roster dt {
+#converse-roster dt {
     font-weight: normal;
     display: none;
     font-size: 13px;
@@ -428,7 +436,7 @@ form.search-xmpp-contact input {
 
 
 dd.available-chatroom,
-#xmppchat-roster dd {
+#converse-roster dd {
     font-weight: bold;
     border: none;
     display: block;
@@ -437,7 +445,7 @@ dd.available-chatroom,
     text-shadow: 0 1px 0 rgba(250, 250, 250, 1);
 }
 
-#xmppchat-roster dd a.remove-xmpp-contact {
+#converse-roster dd a.remove-xmpp-contact {
     background: url('images/delete_icon.png') no-repeat right top;
     padding: 0 1em 1em 0;
     float: right;
@@ -494,12 +502,12 @@ div#controlbox-panes {
     width: 199px;
 }
 
-form#xmppchat-login {
+form#converse-login {
     background: white;
     padding: 2em 0 0.3em 0.5em;
 }
 
-form#xmppchat-login input {
+form#converse-login input {
     display: block;
 }
 
@@ -599,17 +607,12 @@ form.sendXMPPMessage {
 form#set-custom-xmpp-status {
     float: left;
     padding: 0;
-    background: none;
 }
 
 #set-custom-xmpp-status button {
     padding: 1px 2px 1px 1px;
 }
 
-input.custom-xmpp-status {
-    width: 138px;
-}
-
 /* status dropdown styles */
 dl.dropdown {
     margin-right: 0.5em;
@@ -622,9 +625,17 @@ div.xmpp-status {
     padding: 3px;
 }
 
-.fancy-dropdown {
-    border:1px solid #ddd;
-    height: 22px;
+input.custom-xmpp-status {
+    width: 138px;
+}
+
+form.add-xmpp-contact {
+    background: white;
+    padding: 5px;
+}
+
+form.add-xmpp-contact input {
+    width: 125px;
 }
 
 .dropdown dt a span {

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 211 - 168
converse.js


+ 57 - 0
docs/NOTES.rst

@@ -0,0 +1,57 @@
+=========================
+Converse.js Documentation
+=========================
+
+------------------------------------
+Converse.js configuration variables:
+------------------------------------
+
+Prebind
+========
+
+Use this option if you don't want to render the login form on the chat control
+box.
+
+When set to true, the onConnected method needs to be called manually, together
+with a Strophe connection object.
+
+The most likely usecase is if you want to already authenticate on the backend
+and merely attach to that connection in the browser.
+
+Besides requiring the back-end to authenticate you, you'll also 
+have to write a Javascript snippet to attach to the set up connection::
+
+    $.JSON({
+        'url': 'mysite.com/xmpp-authenticate',
+        'success': function (data) {
+            connection = new Strophe.Connection(data.BOSH_SERVICE_URL);
+            connection.attach(data.jid, data.sid, data.rid, converse.onConnected);
+        }
+
+fullname
+========
+
+If you are using prebinding, you need to specify the fullname of the currently
+logged in user.
+
+xhr_user_search
+===============
+
+There are two ways to add users. 
+
+* The user inputs a valid JID (Jabber ID), and the user is added as a pending
+contact.
+* The user inputs some text (for example part of a firstname or lastname), an XHR will be made to a backend, and a list of matches are returned. The user can then choose one of the matches to add as a contact.
+
+This setting enables the second mechanism, otherwise by default the first will
+be used.
+
+auto_subscribe
+==============
+
+If true, the user will automatically subscribe back to any contact requests.
+
+animate
+=======
+
+Show animations, for example when opening and closing chat boxes.

+ 10 - 10
index.html

@@ -29,16 +29,16 @@
     <!-- MAIN CONTENT -->
     <div id="main_content_wrap" class="outer">
     <section id="main_content" class="inner">
-    <p><strong>Converse.js</strong> implements an <a href="http://xmpp.org" target="_blank">XMPP</a> based instant messaging client in the browser.</p>
+    <p><strong>Converse.js</strong> is a web based <a href="http://xmpp.org" target="_blank">XMPP/Jabber</a> instant messaging client.</p>
     <p>It is used by <a href="http://github.com/collective/collective.xmpp.chat" target="_blank">collective.xmpp.chat</a>, which is a <a href="http://plone.org" target="_blank">Plone</a> instant messaging add-on.</p>
-    <p>The ultimate goal is to enable anyone to add chat functionality to their websites, regardless of the backend.</p>
-    <p>This is currently possible, except for adding new contacts, which still makes an XHR call to the (Plone) backend to fetch user info.</p>
+    <p>The ultimate goal is to enable anyone to add chat functionality to their websites, independent of any backend.
+       You will however need an XMPP server to connect to, either your own, or a public one.</p>
 
     <h2>Features</h2>
     <ul>
         <li>Manually or automically subscribe to other users.</li>
         <li>Accept or decline contact requests</li>
-        <li>Chat status (online, busy, away, offline)</li>
+        <li>Chat statuses (online, busy, away, offline)</li>
         <li>Custom status messages</li>
         <li>Typing notifications</li>
         <li>Third person messages (/me )</li>
@@ -131,10 +131,10 @@
     </div>
 </div>
 
-    <script type="text/javascript">
-        var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-        document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-    </script>
-    <script type="text/javascript">try { var pageTracker = _gat._getTracker("UA-2128260-8"); pageTracker._trackPageview(); } catch(err) {}</script>
-  </body>
+<script type="text/javascript">
+    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
+    document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
+</script>
+<script type="text/javascript">try { var pageTracker = _gat._getTracker("UA-2128260-8"); pageTracker._trackPageview(); } catch(err) {}</script>
+</body>
 </html>

+ 7 - 1
main.js

@@ -1 +1,7 @@
-require(["jquery", "converse"], function($) {});
+require(["jquery", "converse"], function($, converse) {
+    converse.initialize({
+        prebind: false,
+        xhr_user_search: false,
+        auto_subscribe: false 
+    });
+});

+ 71 - 60
spec/MainSpec.js

@@ -1,11 +1,11 @@
 (function (root, factory) {
     define([
         "converse"
-        ], function (xmppchat) {
-            return factory(xmppchat);
+        ], function (converse) {
+            return factory(converse);
         }
     );
-} (this, function (xmppchat) {
+} (this, function (converse) {
 
     return describe("Converse.js", $.proxy(function() {
         // Names from http://www.fakenamegenerator.com/
@@ -21,13 +21,12 @@
             'Lena Grunewald', 'Laura Grunewald', 'Mandy Seiler', 'Sven Bosch', 'Nuriye Cuypers'
         ];
         var num_contacts = req_names.length + pend_names.length + cur_names.length;
-        this.bare_jid = 'dummy@localhost';
         mock_connection  = {
             'muc': {
                 'listRooms': function () {},
                 'join': function () {}
             },
-            'jid': this.bare_jid,
+            'jid': 'dummy@localhost',
             'addHandler': function (handler, ns, name, type, id, from, options) { 
                 return function () {};
             },
@@ -54,9 +53,13 @@
 
         // Clear localStorage
         window.localStorage.clear();
-        this.prebind = true;
+        this.initialize({
+            prebind: false,
+            xhr_user_search: false,
+            auto_subscribe: false,
+            animate: false
+        });
         this.onConnected(mock_connection);
-        this.animate = false; // don't use animations
 
         // Variable declarations for specs
         var open_controlbox;
@@ -64,7 +67,7 @@
         describe("The Control Box", $.proxy(function () {
             it("is not shown by default", $.proxy(function () {
                 expect(this.rosterview.$el.is(':visible')).toEqual(false);
-            }, xmppchat));
+            }, converse));
 
             open_controlbox = $.proxy(function () {
                 // This spec will only pass if the controlbox is not currently
@@ -74,7 +77,7 @@
                 $('.toggle-online-users').click();
                 expect(this.toggleControlBox).toHaveBeenCalled();
                 expect($("div#controlbox").is(':visible')).toBe(true);
-            }, xmppchat);
+            }, converse);
             it("can be opened by clicking a DOM element with class 'toggle-online-users'", open_controlbox);
             
             describe("The Status Widget", $.proxy(function () {
@@ -100,8 +103,8 @@
                         expect(view.updateStatusUI).toHaveBeenCalled();
                         expect(view.$el.find('a.choose-xmpp-status').hasClass('online')).toBe(true);
                         expect(view.$el.find('a.choose-xmpp-status span.value').text()).toBe('I am online');
-                    }, xmppchat));
-                }, xmppchat));
+                    }, converse));
+                }, converse));
 
                 it("can be used to set a custom status message", $.proxy(function () {
                     var view = this.xmppstatusview;
@@ -123,17 +126,17 @@
                         expect(view.$el.find('a.choose-xmpp-status').hasClass('online')).toBe(true);
                         expect(view.$el.find('a.choose-xmpp-status span.value').text()).toBe(msg);
                     });
-                }, xmppchat));
-            }, xmppchat));
+                }, converse));
+            }, converse));
 
-        }, xmppchat));
+        }, converse));
 
         describe("The Contacts Roster", $.proxy(function () {
 
             describe("Pending Contacts", $.proxy(function () {
                 it("do not have a heading if there aren't any", $.proxy(function () {
                     expect(this.rosterview.$el.find('dt#pending-xmpp-contacts').css('display')).toEqual('none');
-                }, xmppchat));
+                }, converse));
 
                 it("can be added to the roster and they will be sorted alphabetically", $.proxy(function () {
                     var i, t, is_last;
@@ -159,17 +162,17 @@
                         t = this.rosterview.$el.find('dt#pending-xmpp-contacts').siblings('dd.pending-xmpp-contact').text();
                         expect(t).toEqual(pend_names.slice(0,i+1).sort().join(''));
                     }
-                }, xmppchat));
+                }, converse));
 
                 it("will have their own heading once they have been added", $.proxy(function () {
                     expect(this.rosterview.$el.find('dt#pending-xmpp-contacts').css('display')).toEqual('block');
-                }, xmppchat));
-            }, xmppchat));
+                }, converse));
+            }, converse));
 
             describe("Existing Contacts", $.proxy(function () {
                 it("do not have a heading if there aren't any", $.proxy(function () {
                     expect(this.rosterview.$el.find('dt#xmpp-contacts').css('display')).toEqual('none');
-                }, xmppchat));
+                }, converse));
 
                 it("can be added to the roster and they will be sorted alphabetically", $.proxy(function () {
                     var i, t;
@@ -187,11 +190,11 @@
                         t = this.rosterview.$el.find('dt#xmpp-contacts').siblings('dd.current-xmpp-contact.offline').find('a.open-chat').text();
                         expect(t).toEqual(cur_names.slice(0,i+1).sort().join(''));
                     }
-                }, xmppchat));
+                }, converse));
 
                 it("will have their own heading once they have been added", $.proxy(function () {
                     expect(this.rosterview.$el.find('dt#xmpp-contacts').css('display')).toEqual('block');
-                }, xmppchat));
+                }, converse));
 
                 it("can change their status to online and be sorted alphabetically", $.proxy(function () {
                     var item, view, jid, t;
@@ -209,7 +212,7 @@
                         t = this.rosterview.$el.find('dt#xmpp-contacts').siblings('dd.current-xmpp-contact.online').find('a.open-chat').text();
                         expect(t).toEqual(cur_names.slice(0,i+1).sort().join(''));
                     }
-                }, xmppchat));
+                }, converse));
 
                 it("can change their status to busy and be sorted alphabetically", $.proxy(function () {
                     var item, view, jid, t;
@@ -226,7 +229,7 @@
                         t = this.rosterview.$el.find('dt#xmpp-contacts').siblings('dd.current-xmpp-contact.dnd').find('a.open-chat').text();
                         expect(t).toEqual(cur_names.slice(3,i+1).sort().join(''));
                     }
-                }, xmppchat));
+                }, converse));
 
                 it("can change their status to away and be sorted alphabetically", $.proxy(function () {
                     var item, view, jid, t;
@@ -244,7 +247,7 @@
                         t = this.rosterview.$el.find('dt#xmpp-contacts').siblings('dd.current-xmpp-contact.away').find('a.open-chat').text();
                         expect(t).toEqual(cur_names.slice(6,i+1).sort().join(''));
                     }
-                }, xmppchat));
+                }, converse));
 
                 it("can change their status to unavailable and be sorted alphabetically", $.proxy(function () {
                     var item, view, jid, t;
@@ -262,7 +265,7 @@
                         t = this.rosterview.$el.find('dt#xmpp-contacts').siblings('dd.current-xmpp-contact.unavailable').find('a.open-chat').text();
                         expect(t).toEqual(cur_names.slice(9, i+1).sort().join(''));
                     }
-                }, xmppchat));
+                }, converse));
 
                 it("are ordered according to status: online, busy, away, unavailable, offline", $.proxy(function () {
                     var contacts = this.rosterview.$el.find('dd.current-xmpp-contact');
@@ -287,17 +290,17 @@
                     for (i=12; i<cur_names.length; i++) {
                         expect($(contacts[i]).attr('class').split(' ',1)[0]).toEqual('offline');
                     }
-                }, xmppchat));
+                }, converse));
 
 
-            }, xmppchat));
+            }, converse));
 
             describe("Requesting Contacts", $.proxy(function () {
                 // by default the dts are hidden from css class and only later they will be hidden
                 // by jQuery therefore for the first check we will see if visible instead of none
                 it("do not have a heading if there aren't any", $.proxy(function () {
                     expect(this.rosterview.$el.find('dt#xmpp-contact-requests').is(':visible')).toEqual(false);
-                }, xmppchat));
+                }, converse));
 
                 it("can be added to the roster and they will be sorted alphabetically", $.proxy(function () {
                     var i, t;
@@ -319,11 +322,11 @@
                         // be opened.
                         expect(this.showControlBox).toHaveBeenCalled();
                     }
-                }, xmppchat));
+                }, converse));
 
                 it("will have their own heading once they have been added", $.proxy(function () {
                     expect(this.rosterview.$el.find('dt#xmpp-contact-requests').css('display')).toEqual('block');
-                }, xmppchat));
+                }, converse));
 
                 it("can have their requests accepted by the user", $.proxy(function () {
                     // TODO: Testing can be more thorough here, the user is
@@ -338,7 +341,7 @@
                     accept_button.click();
                     expect(view.acceptRequest).toHaveBeenCalled();
                     expect(this.connection.roster.authorize).toHaveBeenCalled();
-                }, xmppchat));
+                }, converse));
 
                 it("can have their requests denied by the user", $.proxy(function () {
                     var jid = req_names.sort()[1].replace(' ','.').toLowerCase() + '@localhost';
@@ -354,8 +357,8 @@
                     expect(this.connection.roster.unauthorize).toHaveBeenCalled();
                     // There should now be one less contact
                     expect(this.roster.length).toEqual(num_contacts-1); 
-                }, xmppchat));
-            }, xmppchat));
+                }, converse));
+            }, converse));
 
             describe("All Contacts", $.proxy(function () {
 
@@ -384,7 +387,7 @@
                         expect(_.isEqual(new_attrs.sort(), old_attrs.sort())).toEqual(true);
                     }
                     this.rosterview.render();
-                }, xmppchat));
+                }, converse));
 
                 afterEach($.proxy(function () {
                     // Contacts retrieved from localStorage have chat_status of
@@ -396,12 +399,24 @@
                         view = this.rosterview.rosteritemviews[jid];
                         view.model.set('chat_status', 'online');
                     }
-                }, xmppchat));
-            }, xmppchat));
-        }, xmppchat));
+                }, converse));
+            }, converse));
+        }, converse));
+
+        describe("The 'Add Contact' widget", $.proxy(function () {
+            it("opens up an add form when you click on it", $.proxy(function () {
+                var panel = this.chatboxesview.views.controlbox.contactspanel;
+                spyOn(panel, 'toggleContactForm').andCallThrough();
+                panel.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
+                panel.$el.find('a.toggle-xmpp-contact-form').click();
+                expect(panel.toggleContactForm).toHaveBeenCalled();
+                // XXX: Awaiting more tests, close it again for now...
+                panel.$el.find('a.toggle-xmpp-contact-form').click();
+            }, converse));
+
+        }, converse));
 
         describe("A Chatbox", $.proxy(function () {
-
             it("is created when you click on a roster item", $.proxy(function () {
                 var i, $el, click, jid, view;
                 // showControlBox was called earlier, so the controlbox is
@@ -419,7 +434,7 @@
                     expect(view.openChat).toHaveBeenCalled();
                     expect(this.chatboxes.length).toEqual(i+2);
                 }
-            }, xmppchat));
+            }, converse));
 
             it("can be saved to, and retrieved from, localStorage", $.proxy(function () {
                 // We instantiate a new ChatBoxes collection, which by default
@@ -439,7 +454,7 @@
                     expect(_.isEqual(new_attrs, old_attrs)).toEqual(true);
                 }
                 this.rosterview.render();
-            }, xmppchat));
+            }, converse));
 
             it("can be closed again by clicking a DOM element with class 'close-chatbox-button'", $.proxy(function () {
                 var chatbox, view, $el,
@@ -452,7 +467,7 @@
                     view.$el.find('.close-chatbox-button').click();
                     expect(view.closeChat).toHaveBeenCalled();
                 }
-            }, xmppchat));
+            }, converse));
 
             it("will be removed from localStorage when closed", $.proxy(function () {
                 var newchatboxes = new this.ChatBoxes();
@@ -465,7 +480,7 @@
 
                 // Lets open the controlbox again, purely for visual feedback
                 open_controlbox(); 
-            }, xmppchat));
+            }, converse));
 
             describe("A Chat Message", $.proxy(function () {
                 it("can be received which will open a chatbox and be displayed inside it", $.proxy(function () {
@@ -473,7 +488,7 @@
                     var sender_jid = cur_names[0].replace(' ','.').toLowerCase() + '@localhost';
                         msg = $msg({
                             from: sender_jid,
-                            to: this.bare_jid, 
+                            to: this.connection.jid, 
                             type: 'chat', 
                             id: (new Date()).getTime()
                         }).c('body').t(message).up()
@@ -488,7 +503,7 @@
                         // messageReceived is a handler for received XMPP
                         // messages
                         this.chatboxes.messageReceived(msg);
-                    }, xmppchat));
+                    }, converse));
                     waits(500);
                     runs($.proxy(function () {
                         // Since we didn't already have an open chatbox, one
@@ -514,8 +529,8 @@
                         // chatbox in the DOM
                         var txt = chatboxview.$el.find('.chat-content').find('.chat-message').find('.chat-message-content').text();
                         expect(txt).toEqual(message);
-                    }, xmppchat));
-                }, xmppchat));
+                    }, converse));
+                }, converse));
 
                 it("can be sent from a chatbox, and will appear inside it", $.proxy(function () {
                     var contact_jid = cur_names[0].replace(' ','.').toLowerCase() + '@localhost';
@@ -528,9 +543,9 @@
                     expect(view.model.messages.length, 2);
                     var txt = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-message-content').text();
                     expect(txt).toEqual(message);
-                }, xmppchat));
-            }, xmppchat));
-        }, xmppchat));
+                }, converse));
+            }, converse));
+        }, converse));
 
         describe("The Controlbox Tabs", $.proxy(function () {
             it("consist of two tabs, 'Contacts' and 'ChatRooms', of which 'Contacts' is by default visible", $.proxy(function () {
@@ -541,7 +556,7 @@
                 expect($panels.children().first().is(':visible')).toBe(true);
                 expect($panels.children().last().attr('id')).toBe('chatrooms');
                 expect($panels.children().last().is(':visible')).toBe(false);
-            }, xmppchat));
+            }, converse));
 
             describe("The Chatrooms Panel", $.proxy(function () {
 
@@ -562,7 +577,7 @@
                         expect($chatrooms.is(':visible')).toBe(true);
                         expect(cbview.switchTab).toHaveBeenCalled();
                     });
-                }, xmppchat));
+                }, converse));
 
                 it("contains a form through which a new chatroom can be created", $.proxy(function () {
                     var roomspanel = this.chatboxesview.views.controlbox.roomspanel;
@@ -582,13 +597,9 @@
                     waits('250');
                     runs($.proxy(function () {
                         expect($('.chatroom').length).toBe(1); // There should now be an open chatroom
-                    }, xmppchat));
-                }, xmppchat));
-
-
-            }, xmppchat));
-        }, xmppchat));
-
-
-    }, xmppchat));
+                    }, converse));
+                }, converse));
+            }, converse));
+        }, converse));
+    }, converse));
 }));

+ 6 - 0
tests.html

@@ -29,5 +29,11 @@
             </a>
         </div>
     </div>
+
+    <script type="text/javascript">
+        var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
+        document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
+    </script>
+    <script type="text/javascript">try { var pageTracker = _gat._getTracker("UA-2128260-8"); pageTracker._trackPageview(); } catch(err) {}</script>
 </body>
 </html>

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác