[Kimchi-devel] [PATCH] Enable buttons only when all required data is entered

Crístian Viana vianac at linux.vnet.ibm.com
Tue May 13 20:44:39 UTC 2014


Most forms contain fields that must be filled before they are submitted.
Some of them submit the missing data and display an error message when
something goes wrong, and some of them do not allow the user to submit
them if some data is missing.

Make the forms behavior consistent by enabling their buttons only
when the required data is entered.
Internally, the page tags all required fields with the class "required"
and whenever any of their values change, they are checke. If any
required field is empty, the submit button becomses disabled; otherwise,
it becomes enabled.

Fix GitHub issue #317 ("Inconsistent button status when adding or
creating new resources").

Signed-off-by: Crístian Viana <vianac at linux.vnet.ibm.com>
---
 ui/css/theme-default/login-window.css    |  4 --
 ui/js/src/kimchi.guest_edit_main.js      | 15 +++++++
 ui/js/src/kimchi.login_window.js         | 36 +++++++--------
 ui/js/src/kimchi.storagepool_add_main.js | 75 +++++++++++++++++++++++---------
 ui/js/src/kimchi.template_edit_main.js   | 20 +++++++++
 ui/pages/guest-edit.html.tmpl            |  6 +--
 ui/pages/i18n.html.tmpl                  |  6 ---
 ui/pages/login-window.html.tmpl          |  8 ++--
 ui/pages/storagepool-add.html.tmpl       |  6 +--
 ui/pages/template-edit.html.tmpl         |  8 ++--
 10 files changed, 117 insertions(+), 67 deletions(-)

diff --git a/ui/css/theme-default/login-window.css b/ui/css/theme-default/login-window.css
index 8a21090..d021be6 100644
--- a/ui/css/theme-default/login-window.css
+++ b/ui/css/theme-default/login-window.css
@@ -62,10 +62,6 @@
     width: 290px;
 }
 
-#login-window .login-panel .msg-required {
-    color: red;
-}
-
 #login-window .login-panel button {
     font-size: 18px;
     height: 40px;
diff --git a/ui/js/src/kimchi.guest_edit_main.js b/ui/js/src/kimchi.guest_edit_main.js
index 0236e2d..bb4ee51 100644
--- a/ui/js/src/kimchi.guest_edit_main.js
+++ b/ui/js/src/kimchi.guest_edit_main.js
@@ -202,6 +202,21 @@ kimchi.guest_edit_main = function() {
 
     kimchi.retrieveVM(kimchi.selectedGuest, initContent);
 
+    var updateSubmitButtonStatus = function() {
+        var valid = true;
+        guestEditForm.find('input.required').each(function(index, field) {
+            if (field.value === '') {
+                valid = false;
+                return;
+            }
+        });
+
+        saveButton.prop('disabled', !valid);
+    };
+
+    guestEditForm.find('input.required').on('input propertychange',
+                                            updateSubmitButtonStatus);
+
     var submitForm = function(event) {
         $(saveButton).prop('disabled', true);
         var data=$('#form-guest-edit-general').serializeObject();
diff --git a/ui/js/src/kimchi.login_window.js b/ui/js/src/kimchi.login_window.js
index 9c06a50..52394a5 100644
--- a/ui/js/src/kimchi.login_window.js
+++ b/ui/js/src/kimchi.login_window.js
@@ -30,26 +30,25 @@ kimchi.login_main = function() {
         $(opt).prop('selected', selectedLanguage === k);
     }
 
+    var updateSubmitButtonStatus = function() {
+        var valid = true;
+        $('#form-login').find('input.required').each(function(index, field) {
+            if (field.value === '') {
+                valid = false;
+                return;
+            }
+        });
+
+        $('#btn-login').prop('disabled', !valid);
+    }
+
+    $('#form-login').find('input.required').on('input propertychange',
+                                               updateSubmitButtonStatus);
+
     $('#language').on('change', function() {
         kimchi.topic('languageChanged').publish($(this).val());
     });
 
-    var validateNonEmpty = function(idsArray) {
-        for(var i = 0; i < idsArray.length; i++) {
-            var id = idsArray[i];
-            if (!$('#' + id).val()) {
-                $('#' + id + '-msg').text(i18n['KCHAUTH6002E']);
-                placeCursor(id);
-                return false;
-            }
-            else {
-                $('#' + id + '-msg').empty();
-            }
-        }
-
-        return true;
-    };
-
     var placeCursor = function(id) {
         if (id && $('#' + id).size() > 0) {
             $('#' + id).focus();
@@ -66,11 +65,6 @@ kimchi.login_main = function() {
     };
 
     var login = function(event) {
-
-        if (!validateNonEmpty(['username', 'password'])) {
-            return false;
-        }
-
         $('#btn-login').text(i18n['KCHAUTH6002M']).prop('disabled', true);
 
         var userName = $('#username').val();
diff --git a/ui/js/src/kimchi.storagepool_add_main.js b/ui/js/src/kimchi.storagepool_add_main.js
index 86dbe7f..5356985 100644
--- a/ui/js/src/kimchi.storagepool_add_main.js
+++ b/ui/js/src/kimchi.storagepool_add_main.js
@@ -122,6 +122,18 @@ kimchi.initStorageAddPage = function() {
         });
     });
 
+    var updateSubmitButtonStatus = function() {
+        var valid = true;
+        $('#form-pool-add').find('input.required').each(function(index, field) {
+            if (field.value === '') {
+                valid = false;
+                return;
+            }
+        });
+
+        $('#pool-doAdd').prop('disabled', !valid);
+    };
+
     $('#poolTypeInputId').change(function() {
         var poolObject = {'dir': ".path-section", 'netfs': '.nfs-section',
                           'iscsi': '.iscsi-section', 'scsi': '.scsi-section',
@@ -134,7 +146,49 @@ kimchi.initStorageAddPage = function() {
                 $(value).addClass('tmpl-html');
             }
         });
+
+        switch (selectType) {
+            case 'dir':
+                $('#pathId').addClass('required');
+
+                $('#nfsserverId').removeClass('required');
+                $('#nfspathId').removeClass('required');
+                $('#iscsiserverId').removeClass('required');
+                break;
+            case 'netfs':
+                $('#nfsserverId').addClass('required');
+                $('#nfspathId').addClass('required');
+
+                $('#pathId').removeClass('required');
+                $('#iscsiserverId').removeClass('required');
+                break;
+            case 'iscsi':
+                $('#iscsiserverId').addClass('required');
+
+                $('#pathId').removeClass('required');
+                $('#nfsserverId').removeClass('required');
+                $('#nfspathId').removeClass('required');
+                break;
+            case 'scsi':
+                $('#pathId').removeClass('required');
+                $('#nfsserverId').removeClass('required');
+                $('#nfspathId').removeClass('required');
+                $('#iscsiserverId').removeClass('required');
+                break;
+            case 'logical':
+                $('#pathId').removeClass('required');
+                $('#nfsserverId').removeClass('required');
+                $('#nfspathId').removeClass('required');
+                $('#iscsiserverId').removeClass('required');
+                break;
+        }
+
+        updateSubmitButtonStatus();
     });
+
+    $('#form-pool-add').find('input').on('input propertychange',
+                                         updateSubmitButtonStatus);
+
     $('#authId').click(function() {
         if ($(this).prop("checked")) {
             $('.authenticationfield').removeClass('tmpl-html');
@@ -150,10 +204,6 @@ kimchi.initStorageAddPage = function() {
 kimchi.validateForm = function() {
     var name = $('#poolId').val();
     var poolType = $("#poolTypeInputId").val();
-    if ('' === name) {
-        kimchi.message.error.code('KCHPOOL6001E');
-        return false;
-    }
     if (name.indexOf("/")!=-1) {
         kimchi.message.error.code('KCHPOOL6004E');
         return false;
@@ -173,10 +223,6 @@ kimchi.validateForm = function() {
 
 kimchi.validateDirForm = function () {
     var path = $('#pathId').val();
-    if ('' === path) {
-        kimchi.message.error.code('KCHPOOL6002E');
-        return false;
-    }
     if (!/(^\/.*)$/.test(path)) {
         kimchi.message.error.code('KCHAPI6003E');
         return false;
@@ -190,10 +236,6 @@ kimchi.validateNfsForm = function () {
     if (!kimchi.validateServer(nfsserver)) {
         return false;
     }
-    if ('' === nfspath) {
-        kimchi.message.error.code('KCHPOOL6003E');
-        return false;
-    }
     if (!/((\/([0-9a-zA-Z-_\.]+)))$/.test(nfspath)) {
         kimchi.message.error.code('KCHPOOL6005E');
         return false;
@@ -203,22 +245,13 @@ kimchi.validateNfsForm = function () {
 
 kimchi.validateIscsiForm = function() {
     var iscsiServer = $('#iscsiserverId').val();
-    var iscsiTarget = $('#iscsiTargetId').val();
     if (!kimchi.validateServer(iscsiServer)) {
         return false;
     }
-    if ('' === iscsiTarget) {
-        kimchi.message.error.code('KCHPOOL6007E');
-        return false;
-    }
     return true;
 };
 
 kimchi.validateServer = function(serverField) {
-    if ('' === serverField) {
-        kimchi.message.error.code('KCHPOOL6008E');
-        return false;
-    }
     if(!kimchi.isServer(serverField)) {
         kimchi.message.error.code('KCHPOOL6009E');
         return false;
diff --git a/ui/js/src/kimchi.template_edit_main.js b/ui/js/src/kimchi.template_edit_main.js
index f0f4718..e552bf9 100644
--- a/ui/js/src/kimchi.template_edit_main.js
+++ b/ui/js/src/kimchi.template_edit_main.js
@@ -104,6 +104,26 @@ kimchi.template_edit_main = function() {
         });
     });
 
+    var updateSubmitButtonStatus = function() {
+        var valid = true;
+        templateEditForm.find('input.required').each(function(index, field) {
+            if (field.value === '') {
+                valid = false;
+                return;
+            }
+        });
+
+        if (valid) {
+            $('#tmpl-edit-button-save').removeAttr('disabled');
+        }
+        else {
+            $('#tmpl-edit-button-save').attr('disabled', 'disabled');
+        }
+    };
+
+    templateEditForm.find('input.required').on('input propertychange',
+                                                updateSubmitButtonStatus);
+
     $('#tmpl-edit-button-cancel').on('click', function() {
         kimchi.window.close();
     });
diff --git a/ui/pages/guest-edit.html.tmpl b/ui/pages/guest-edit.html.tmpl
index 96d907e..d35ad7a 100644
--- a/ui/pages/guest-edit.html.tmpl
+++ b/ui/pages/guest-edit.html.tmpl
@@ -49,7 +49,7 @@
                         </div>
                         <div class="guest-edit-wrapper-controls">
                             <input id="guest-edit-id-textbox"
-                                name="name" type="text" />
+                                name="name" type="text" class="required" />
                         </div>
                     </div>
                     <div>
@@ -62,7 +62,7 @@
                             <input
                                 id="guest-edit-cores-textbox"
                                 name="cpus"
-                                type="text" />
+                                type="text" class="required" />
                         </div>
                     </div>
                     <div>
@@ -74,7 +74,7 @@
                         <div class="guest-edit-wrapper-controls">
                             <input id="guest-edit-memory-textbox"
                                 name="memory"
-                                type="text" />
+                                type="text" class="required" />
                         </div>
                     </div>
                     <div>
diff --git a/ui/pages/i18n.html.tmpl b/ui/pages/i18n.html.tmpl
index 98da828..814825f 100644
--- a/ui/pages/i18n.html.tmpl
+++ b/ui/pages/i18n.html.tmpl
@@ -33,7 +33,6 @@
 <script>
 var i18n = {
     'KCHAUTH6001E': "$_("The username or password you entered is incorrect. Please try again.")",
-    'KCHAUTH6002E': "$_("This field is required.")",
 
     'KCHAUTH6001M': "$_("Log in")",
     'KCHAUTH6002M': "$_("Logging in...")",
@@ -158,14 +157,9 @@ var i18n = {
     'KCHPOOL6004M': "$_("SCSI Fibre Channel")",
     'KCHPOOL6005M': "$_("No SCSI adapters found.")",
 
-    'KCHPOOL6001E': "$_("The storage pool name can not be blank.")",
-    'KCHPOOL6002E': "$_("The storage pool path can not be blank.")",
-    'KCHPOOL6003E': "$_("NFS server mount path can not be blank.")",
     'KCHPOOL6004E': "$_("Invalid storage pool name. It should not contain '/'.")",
     'KCHPOOL6005E': "$_("Invalid NFS mount path.")",
     'KCHPOOL6006E': "$_("No logical device selected.")",
-    'KCHPOOL6007E': "$_("The iSCSI target can not be blank.")",
-    'KCHPOOL6008E': "$_("Server name can not be blank.")",
     'KCHPOOL6009E': "$_("This is not a valid Server Name or IP. please, modify it.")",
     'KCHPOOL6010M': "$_("Looking for available partitions ...")",
     'KCHPOOL6011M': "$_("No available partitions found.")",
diff --git a/ui/pages/login-window.html.tmpl b/ui/pages/login-window.html.tmpl
index 3e451c4..1cd9e83 100644
--- a/ui/pages/login-window.html.tmpl
+++ b/ui/pages/login-window.html.tmpl
@@ -34,15 +34,13 @@
   <div class="content login-panel">
     <form id="form-login" action="/login" method="POST">
       <div class="row">
-        <input type="text" id="username" name="username" required="required" placeholder="$_("User Name")" />
-        <div id="username-msg" class="msg-required"></div>
+        <input type="text" id="username" name="username" class="required" placeholder="$_("User Name")" />
       </div>
       <div class="row">
-        <input type="password" id="password" name="password" required="required" placeholder="$_("Password")" />
-        <div id="password-msg" class="msg-required"></div>
+        <input type="password" id="password" name="password" class="required" placeholder="$_("Password")" />
       </div>
       <div class="row">
-        <button id="btn-login" class="btn-normal">$_("Log in")</button>
+        <button id="btn-login" class="btn-normal" disabled="true">$_("Log in")</button>
       </div>
     </form>
   </div>
diff --git a/ui/pages/storagepool-add.html.tmpl b/ui/pages/storagepool-add.html.tmpl
index 977db66..6ce1343 100644
--- a/ui/pages/storagepool-add.html.tmpl
+++ b/ui/pages/storagepool-add.html.tmpl
@@ -36,7 +36,7 @@
                         <p class="text-help">
                             $_("The name used to identify the storage pools, and it should not be empty.")
                         </p>
-                        <input id="poolId" required="required" type="text" class="text storage-base-input-width" name="name">
+                        <input id="poolId" type="text" class="text storage-base-input-width required" name="name">
                     </div>
                 </section>
                 <section class="form-section">
@@ -60,7 +60,7 @@
                                 $_("The path of the Storage Pool. Each Storage Pool must have a unique path.")</p>
                             <p class="text-help">
                                 $_("Kimchi will try to create the directory when it does not already exist in your system.")</p>
-                            <input id="pathId" type="text" class="text storage-base-input-width">
+                            <input id="pathId" type="text" class="text storage-base-input-width required">
                         </div>
                         <div class="clear"></div>
                     </section>
@@ -152,7 +152,7 @@
         </div>
         <footer>
             <div class="btn-group">
-                <button id="pool-doAdd" class="btn-normal">
+                <button id="pool-doAdd" class="btn-normal" disabled="disabled">
                     <span class="text">$_("Create")</span>
                 </button>
             </div>
diff --git a/ui/pages/template-edit.html.tmpl b/ui/pages/template-edit.html.tmpl
index 434d938..46b7058 100644
--- a/ui/pages/template-edit.html.tmpl
+++ b/ui/pages/template-edit.html.tmpl
@@ -36,7 +36,7 @@
                         <label for="template-edit-id-textbox">$_("Name")</label>
                     </div>
                     <div class="template-edit-wrapper-controls">
-                        <input id="template-edit-id-textbox" name="name" type="text" />
+                        <input id="template-edit-id-textbox" name="name" type="text" class="required" />
                     </div>
                 </div>
                 <div>
@@ -60,7 +60,7 @@
                         <label for="template-edit-cpu-textbox">$_("CPU Number")</label>
                     </div>
                     <div class="template-edit-wrapper-controls">
-                        <input id="template-edit-cpu-textbox" name="cpus" type="text" />
+                        <input id="template-edit-cpu-textbox" name="cpus" type="text" class="required" />
                     </div>
                 </div>
                 <div>
@@ -68,7 +68,7 @@
                         <label for="template-edit-memory-textbox">$_("Memory")</label>
                     </div>
                     <div class="template-edit-wrapper-controls">
-                        <input id="template-edit-memory-textbox" name="memory" type="text" />
+                        <input id="template-edit-memory-textbox" name="memory" type="text" class="required" />
                     </div>
                 </div>
                 <div>
@@ -76,7 +76,7 @@
                         <label for="template-edit-disk-textbox">$_("Disk (GB)")</label>
                     </div>
                     <div class="template-edit-wrapper-controls">
-                        <input id="template-edit-disk-textbox" name="disks" type="text" />
+                        <input id="template-edit-disk-textbox" name="disks" type="text" class="required" />
                     </div>
                 </div>
             </fieldset>
-- 
1.9.0




More information about the Kimchi-devel mailing list