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

Hongliang Wang hlwang at linux.vnet.ibm.com
Thu May 15 06:51:02 UTC 2014


On 05/14/2014 04:44 AM, Crístian Viana wrote:
> 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);
> +
There's some problem with this new function. And there is no need to 
replace the current validateNonEmpty() function.
   In the current validateNonEmpty() function, several checks are processed:

   1)
   If user name field is empty, then
     put cursor in user name box
   Else if password field is empty, then
     put cursor in password box
   Else
     put cursor on log in button

   2)
   If some field is empty, a message will show to tell user the field is 
required.
>       $('#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);
> +    };
> +
Adam is working on the global form validation item, so you can leave 
this function alone and work on other feature currently.
>       $('#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>
Suggest not change this as mentioned above.
>         </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>




More information about the Kimchi-devel mailing list