Browse Source

Add JID validation and error messages to the `add contact` form

JC Brand 8 years ago
parent
commit
6fea88fcc3

+ 29 - 33
css/converse.css

@@ -1769,9 +1769,6 @@
             #converse-embedded-chat .chatbox form.sendXMPPMessage .chat-toolbar li .toolbar-menu ul.emoji-toolbar .picked,
             #conversejs .chatbox form.sendXMPPMessage .chat-toolbar li .toolbar-menu ul.emoji-toolbar .picked {
               background-color: #DCF9F6; }
-            #converse-embedded-chat .chatbox form.sendXMPPMessage .chat-toolbar li .toolbar-menu ul.emoji-toolbar .emoji-category-picker,
-            #conversejs .chatbox form.sendXMPPMessage .chat-toolbar li .toolbar-menu ul.emoji-toolbar .emoji-category-picker {
-              margin-right: 5em; }
             #converse-embedded-chat .chatbox form.sendXMPPMessage .chat-toolbar li .toolbar-menu ul.emoji-toolbar li,
             #conversejs .chatbox form.sendXMPPMessage .chat-toolbar li .toolbar-menu ul.emoji-toolbar li {
               height: 30px;
@@ -2028,37 +2025,37 @@
           padding: 0.3em 0;
           clear: left;
           width: 100%; }
-  #conversejs #controlbox .dropdown {
-    /* Custom addition for CSP */ }
-    #conversejs #controlbox .dropdown a {
-      width: 143px;
-      display: inline-block; }
-    #conversejs #controlbox .dropdown li {
-      list-style: none;
-      padding-left: 0; }
-    #conversejs #controlbox .dropdown dd ul {
-      padding: 0;
-      list-style: none;
+  #conversejs #controlbox .dropdown a {
+    width: 143px;
+    display: inline-block; }
+  #conversejs #controlbox .dropdown li {
+    list-style: none;
+    padding-left: 0; }
+  #conversejs #controlbox .dropdown dd ul {
+    padding: 0;
+    list-style: none;
+    position: absolute;
+    left: 0;
+    top: 0;
+    width: 100%;
+    z-index: 21;
+    background-color: #FCFDFD; }
+    #conversejs #controlbox .dropdown dd ul li:hover {
+      background-color: #DCF9F6; }
+  #conversejs #controlbox .dropdown dd.search-xmpp {
+    height: 0; }
+    #conversejs #controlbox .dropdown dd.search-xmpp .contact-form-container {
       position: absolute;
-      left: 0;
-      top: 0;
-      border: 1px solid #B1BFC4;
-      width: 100%;
-      z-index: 21;
+      z-index: 22; }
+      #conversejs #controlbox .dropdown dd.search-xmpp .contact-form-container form {
+        box-shadow: 1px 4px 10px 1px rgba(0, 0, 0, 0.4);
+        background-color: white; }
+    #conversejs #controlbox .dropdown dd.search-xmpp li:hover {
       background-color: #FCFDFD; }
-      #conversejs #controlbox .dropdown dd ul li:hover {
-        background-color: #DCF9F6; }
-    #conversejs #controlbox .dropdown dd.search-xmpp {
-      display: none;
-      width: 100%; }
-    #conversejs #controlbox .dropdown dd.search-xmpp ul {
-      box-shadow: 1px 4px 10px 1px rgba(0, 0, 0, 0.4); }
-      #conversejs #controlbox .dropdown dd.search-xmpp ul li:hover {
-        background-color: #FCFDFD; }
-    #conversejs #controlbox .dropdown dt a span {
-      cursor: pointer;
-      display: block;
-      padding: 4px 7px 0 5px; }
+  #conversejs #controlbox .dropdown dt a span {
+    cursor: pointer;
+    display: block;
+    padding: 4px 7px 0 5px; }
   #conversejs #controlbox #select-xmpp-status {
     display: none;
     float: right;
@@ -2175,7 +2172,6 @@
   #conversejs #controlbox #users {
     overflow-y: hidden; }
   #conversejs #controlbox .add-xmpp-contact {
-    background: none;
     padding: 1em 0.5em; }
     #conversejs #controlbox .add-xmpp-contact input {
       margin: 0 0 1rem;

+ 31 - 33
css/inverse.css

@@ -1815,9 +1815,6 @@ body {
             #converse-embedded-chat .chatbox form.sendXMPPMessage .chat-toolbar li .toolbar-menu ul.emoji-toolbar .picked,
             #conversejs .chatbox form.sendXMPPMessage .chat-toolbar li .toolbar-menu ul.emoji-toolbar .picked {
               background-color: #DCF9F6; }
-            #converse-embedded-chat .chatbox form.sendXMPPMessage .chat-toolbar li .toolbar-menu ul.emoji-toolbar .emoji-category-picker,
-            #conversejs .chatbox form.sendXMPPMessage .chat-toolbar li .toolbar-menu ul.emoji-toolbar .emoji-category-picker {
-              margin-right: 5em; }
             #converse-embedded-chat .chatbox form.sendXMPPMessage .chat-toolbar li .toolbar-menu ul.emoji-toolbar li,
             #conversejs .chatbox form.sendXMPPMessage .chat-toolbar li .toolbar-menu ul.emoji-toolbar li {
               height: 32px;
@@ -1939,6 +1936,8 @@ body {
     width: 100%; }
   #conversejs .chatbox form.sendXMPPMessage .toggle-smiley {
     padding-left: 0.5em; }
+    #conversejs .chatbox form.sendXMPPMessage .toggle-smiley ul.emoji-toolbar .emoji-category-picker {
+      margin-right: 5em; }
     #conversejs .chatbox form.sendXMPPMessage .toggle-smiley ul.emoji-toolbar .emoji-category {
       padding-left: 10px;
       padding-right: 10px; }
@@ -2106,37 +2105,37 @@ body {
           padding: 0.3em 0;
           clear: left;
           width: 100%; }
-  #conversejs #controlbox .dropdown {
-    /* Custom addition for CSP */ }
-    #conversejs #controlbox .dropdown a {
-      width: 143px;
-      display: inline-block; }
-    #conversejs #controlbox .dropdown li {
-      list-style: none;
-      padding-left: 0; }
-    #conversejs #controlbox .dropdown dd ul {
-      padding: 0;
-      list-style: none;
+  #conversejs #controlbox .dropdown a {
+    width: 143px;
+    display: inline-block; }
+  #conversejs #controlbox .dropdown li {
+    list-style: none;
+    padding-left: 0; }
+  #conversejs #controlbox .dropdown dd ul {
+    padding: 0;
+    list-style: none;
+    position: absolute;
+    left: 0;
+    top: 0;
+    width: 100%;
+    z-index: 21;
+    background-color: #FCFDFD; }
+    #conversejs #controlbox .dropdown dd ul li:hover {
+      background-color: #DCF9F6; }
+  #conversejs #controlbox .dropdown dd.search-xmpp {
+    height: 0; }
+    #conversejs #controlbox .dropdown dd.search-xmpp .contact-form-container {
       position: absolute;
-      left: 0;
-      top: 0;
-      border: 1px solid #B1BFC4;
-      width: 100%;
-      z-index: 21;
+      z-index: 22; }
+      #conversejs #controlbox .dropdown dd.search-xmpp .contact-form-container form {
+        box-shadow: 1px 4px 10px 1px rgba(0, 0, 0, 0.4);
+        background-color: white; }
+    #conversejs #controlbox .dropdown dd.search-xmpp li:hover {
       background-color: #FCFDFD; }
-      #conversejs #controlbox .dropdown dd ul li:hover {
-        background-color: #DCF9F6; }
-    #conversejs #controlbox .dropdown dd.search-xmpp {
-      display: none;
-      width: 100%; }
-    #conversejs #controlbox .dropdown dd.search-xmpp ul {
-      box-shadow: 1px 4px 10px 1px rgba(0, 0, 0, 0.4); }
-      #conversejs #controlbox .dropdown dd.search-xmpp ul li:hover {
-        background-color: #FCFDFD; }
-    #conversejs #controlbox .dropdown dt a span {
-      cursor: pointer;
-      display: block;
-      padding: 4px 7px 0 5px; }
+  #conversejs #controlbox .dropdown dt a span {
+    cursor: pointer;
+    display: block;
+    padding: 4px 7px 0 5px; }
   #conversejs #controlbox #select-xmpp-status {
     display: none;
     float: right;
@@ -2253,7 +2252,6 @@ body {
   #conversejs #controlbox #users {
     overflow-y: hidden; }
   #conversejs #controlbox .add-xmpp-contact {
-    background: none;
     padding: 1em 0.5em; }
     #conversejs #controlbox .add-xmpp-contact input {
       margin: 0 0 1rem;

+ 0 - 3
sass/_chatbox.scss

@@ -337,9 +337,6 @@
                                 .picked {
                                     background-color: $highlight-color;
                                 }
-                                .emoji-category-picker {
-                                    margin-right: 5em;
-                                }
                                 li {
                                     height: $emoji_height + 2*5px;
                                     padding: 4px;

+ 9 - 9
sass/_controlbox.scss

@@ -236,7 +236,6 @@
                     position: absolute;
                     left: 0;
                     top: 0;
-                    border: 1px solid $light-background-border-color;
                     width: 100%;
                     z-index: 21;
                     background-color: $light-background-color;
@@ -246,14 +245,16 @@
                 }
             }
 
-            /* Custom addition for CSP */
             dd.search-xmpp {
-                display: none;
-                width: 100%;
-            }
-
-            dd.search-xmpp ul {
-                box-shadow: 1px 4px 10px 1px rgba(0, 0, 0, 0.4);
+                height: 0;
+                .contact-form-container {
+                    position: absolute;
+                    z-index: 22;
+                    form {
+                        box-shadow: 1px 4px 10px 1px rgba(0, 0, 0, 0.4);
+                        background-color: white;
+                    }
+                }
                 li:hover {
                     background-color: $light-background-color;
                 }
@@ -420,7 +421,6 @@
         }
 
         .add-xmpp-contact {
-            background: none;
             padding: 1em 0.5em;
             input {
                 margin: 0 0 1rem;

+ 3 - 0
sass/inverse/_chatbox.scss

@@ -74,6 +74,9 @@
                 padding-left: 0.5em;
                 ul {
                     &.emoji-toolbar {
+                        .emoji-category-picker {
+                            margin-right: 5em;
+                        }
                         .emoji-category {
                             padding-left: 10px;
                             padding-right: 10px;

+ 21 - 15
src/converse-controlbox.js

@@ -635,31 +635,32 @@
                     this.parent_el.appendChild(this.render().el);
                     this.tabs = this.parent_el.parentNode.querySelector('#controlbox-tabs');
                     this.tabs.appendChild(this.tab_el);
-                    this.$('.search-xmpp ul').append(
-                        this.generateAddContactHTML()
-                    );
                     return this;
                 },
 
-                generateAddContactHTML () {
+                generateAddContactHTML (settings={}) {
                     if (_converse.xhr_user_search) {
                         return tpl_search_contact({
                             label_contact_name: __('Contact name'),
                             label_search: __('Search')
                         });
                     } else {
-                        return tpl_add_contact_form({
+                        return tpl_add_contact_form(_.assign({
+                            error_message: null,
                             label_contact_username: __('e.g. user@example.org'),
-                            label_add: __('Add')
-                        });
+                            label_add: __('Add'),
+                            value: ''
+                        }, settings));
                     }
                 },
 
                 toggleContactForm (ev) {
                     ev.preventDefault();
-                    this.$el.find('.search-xmpp').toggle('fast', function () {
-                        if ($(this).is(':visible')) {
-                            $(this).find('input.username').focus();
+                    this.el.querySelector('.search-xmpp div').innerHTML = this.generateAddContactHTML();
+                    var dropdown = this.el.querySelector('.contact-form-container');
+                    utils.slideToggleElement(dropdown).then(() => {
+                        if ($(dropdown).is(':visible')) {
+                            $(dropdown).find('input.username').focus();
                         }
                     });
                 },
@@ -690,13 +691,18 @@
                     ev.preventDefault();
                     const $input = $(ev.target).find('input');
                     const jid = $input.val();
-                    if (! jid) {
-                        // this is not a valid JID
-                        $input.addClass('error');
+                    if (!jid || _.filter(jid.split('@')).length < 2) {
+                        this.el.querySelector('.search-xmpp div').innerHTML =
+                            this.generateAddContactHTML({
+                                error_message: __('Please enter a valid XMPP username'),
+                                label_contact_username: __('e.g. user@example.org'),
+                                label_add: __('Add'),
+                                value: jid
+                            });
                         return;
                     }
                     _converse.roster.addAndSubscribe(jid);
-                    $('.search-xmpp').hide();
+                    utils.slideIn(this.el.querySelector('.contact-form-container'));
                 },
 
                 addContactFromList (ev) {
@@ -706,7 +712,7 @@
                         name = $target.text();
                     _converse.roster.addAndSubscribe(jid, name);
                     $target.parent().remove();
-                    $('.search-xmpp').hide();
+                    utils.slideIn(this.el.querySelector('.contact-form-container'));
                 }
             });
 

+ 0 - 3
src/converse-core.js

@@ -1417,15 +1417,12 @@
             }
         });
 
-
         this.Messages = Backbone.Collection.extend({
             model: _converse.Message,
             comparator: 'time'
         });
 
-
         this.ChatBox = Backbone.Model.extend({
-
             defaults: {
                 'type': 'chatbox',
                 'bookmarked': false,

+ 4 - 1
src/templates/add_contact_dropdown.html

@@ -2,5 +2,8 @@
     <dt id="xmpp-contact-search" class="fancy-dropdown">
         <a class="toggle-xmpp-contact-form icon-plus" href="#" title="{{{label_click_to_chat}}}"> {{{label_add_contact}}}</a>
     </dt>
-    <dd class="search-xmpp"><ul></ul></dd>
+    <dd class="search-xmpp">
+        <div class="contact-form-container collapsed"></div>
+        <ul></ul>
+    </dd>
 </dl>

+ 11 - 9
src/templates/add_contact_form.html

@@ -1,9 +1,11 @@
-<li>
-    <form class="pure-form add-xmpp-contact">
-        <input type="text"
-            name="identifier"
-            class="username"
-            placeholder="{{{label_contact_username}}}"/>
-        <button class="pure-button button-primary" type="submit">{{{label_add}}}</button>
-    </form>
-</li>
+<form class="pure-form add-xmpp-contact">
+    {[ if (error_message) { ]}
+        <span class="pure-form-message error">{{{error_message}}}</span>
+    {[ } ]}
+    <input type="text"
+        name="identifier"
+        value="{{{value}}}"
+        class="username {[ if (error_message) { ]} error {[ } ]}"
+        placeholder="{{{label_contact_username}}}"/>
+    <button class="pure-button button-primary" type="submit">{{{label_add}}}</button>
+</form>

+ 9 - 4
src/utils.js

@@ -214,6 +214,13 @@
             );
         }
 
+        function wrapup (el) {
+            el.removeAttribute('data-slider-marker');
+            el.classList.remove('collapsed');
+            el.style.overflow = "";
+            el.style.height = "";
+        }
+
         return new Promise((resolve, reject) => {
             if (_.isNil(el)) {
                 const err = "Undefined or null element passed into slideOut"
@@ -229,6 +236,7 @@
             const end_height = calculateEndHeight(el);
             if ($.fx.off) { // Effects are disabled (for tests)
                 el.style.height = end_height + 'px';
+                wrapup(el);
                 resolve();
                 return;
             }
@@ -247,10 +255,7 @@
                     // offsetHeight beforehand.
                     el.style.height = calculateEndHeight(el) + 'px';
                     window.clearInterval(interval_marker);
-                    el.removeAttribute('data-slider-marker');
-                    el.classList.remove('collapsed');
-                    el.style.overflow = "";
-                    el.style.height = "";
+                    wrapup(el);
                     resolve();
                 }
             }, interval);