[Kimchi-devel] [PATCH V7] Add nfs server and target UI in create storage pool

Yu Xin Huo huoyuxin at linux.vnet.ibm.com
Thu Jan 16 02:44:33 UTC 2014


Reviewed by Yu Xin Huo <huoyuxin at linux.vnet.ibm.com>

On 1/16/2014 10:03 AM, zhoumeina wrote:
> v6-v7 Fix """ in storagepool-add.html.tmpl
> v5-v6 Fix bug in IE10.
>        Fix bug in Firefox 17.
> v4-v5 Change some html nits.
> V3-V4 add value in jquery widget.
>        move all storage all page style to css files.
>
> v2-v3 Make nfs server inputbox to combobox
>        Edit jquery widgets to fix some small nits in it.
>        change some parameter according to the changes from
>        back end.
> v1-v2 Fix some bug in this patch, make it working and retest
> This patch is working adding a select box in create nfs pool,
> when user don't want to input the server ip or name, he can
> simply select "used the server I have used before" and choose
> a server in a select box, this is more convinent.
>
> In order to show server target I did a select box in UI, but sometimes
> maybe the export path number is large. So I made a filter-select
> widget to make user easier to choose the export path he want.
> This is the first jquery widget. And let us make all common widget to
> jquery widget from now on.
>
> Signed-off-by: zhoumeina <zhoumein at linux.vnet.ibm.com>
> ---
>   ui/css/theme-default/button.css          |   28 ++++--
>   ui/css/theme-default/form.css            |    6 ++
>   ui/css/theme-default/popover.css         |    1 +
>   ui/css/theme-default/storage.css         |   29 ++++++-
>   ui/js/Makefile.am                        |    4 +-
>   ui/js/src/kimchi.api.js                  |   27 ++++++-
>   ui/js/src/kimchi.popable.js              |    2 +-
>   ui/js/src/kimchi.storagepool_add_main.js |   65 +++++++++++---
>   ui/js/src/kimchi.utils.js                |   11 +++
>   ui/js/widgets/combobox.js                |  130 ++++++++++++++++++++++++++++
>   ui/js/widgets/filter-select.js           |  139 ++++++++++++++++++++++++++++++
>   ui/js/widgets/select-menu.js             |   86 ++++++++++++++++++
>   ui/pages/i18n.html.tmpl                  |    6 +-
>   ui/pages/storagepool-add.html.tmpl       |   59 +++++++------
>   14 files changed, 538 insertions(+), 55 deletions(-)
>   create mode 100644 ui/js/widgets/combobox.js
>   create mode 100644 ui/js/widgets/filter-select.js
>   create mode 100644 ui/js/widgets/select-menu.js
>
> diff --git a/ui/css/theme-default/button.css b/ui/css/theme-default/button.css
> index c7ed3f6..4d1a808 100644
> --- a/ui/css/theme-default/button.css
> +++ b/ui/css/theme-default/button.css
> @@ -247,30 +247,38 @@
>   .btn-select {
>       display: inline-block;
>       position: relative;
> -    height: 38px;
> +    height: 30px;
>       padding-right: 20px;
> -    margin: 5px;
>       vertical-align: top;
>       -webkit-border-radius: 5px;
>       -moz-border-radius: 5px;
> -    border-radius: 5px;
> -    background: #eee;
> -    box-shadow: -1px -1px 1px #666, 1px 1px 1px #fff, 2px 2px 2px rgba(0, 0, 0, .15) inset;
> +    background: #fff;
> +    box-shadow: -1px -1px 1px #666, 1px 1px 1px #fff, 1px 1px 1px rgba(0, 0, 0, .15) inset;
>       font-size: 13px;
> -    line-height: 38px;
> +    line-height: 30px;
>       text-align: left;
>       cursor: pointer;
>   }
>
> -.btn-select .text {
> -    padding: 0 10px;
> +.btn-select .input {
> +    border: 0 solid #CCCCCC;
> +    margin-right: 10px;
> +    font-size: 16px;
> +    height: 30px;
> +    line-height: 30px;
> +    width: 100%;
> +    position: absolute;
> +    padding: 0 5px;
>   }
>
> +.btn-select input.invalid-field {
> +    border: 1px solid #FF4444;
> +}
>   .btn-select .arrow {
>       position: absolute;
>       width: 15px;
> -    height: 38px;
> -    line-height: 38px;
> +    height: 30px;
> +    line-height: 30px;
>       top: 0;
>       right: 5px;
>       background: url(../images/theme-default/arrow-down-black.png) no-repeat center center;
> diff --git a/ui/css/theme-default/form.css b/ui/css/theme-default/form.css
> index 28e30a5..d1a3885 100644
> --- a/ui/css/theme-default/form.css
> +++ b/ui/css/theme-default/form.css
> @@ -49,4 +49,10 @@
>
>   .form-section input.invalid-field[type="text"] {
>       border-color: #FF4444;
> +}
> +
> +.text-help {
> +    font-size: 12px;
> +    color: #333;
> +    margin: 0 0 5px 5px;
>   }
> \ No newline at end of file
> diff --git a/ui/css/theme-default/popover.css b/ui/css/theme-default/popover.css
> index 95eb183..e91ccc0 100644
> --- a/ui/css/theme-default/popover.css
> +++ b/ui/css/theme-default/popover.css
> @@ -31,6 +31,7 @@
>       left: 0;
>       display: none;
>       cursor: default;
> +    width: 100%;
>   }
>
>   .popover:BEFORE {
> diff --git a/ui/css/theme-default/storage.css b/ui/css/theme-default/storage.css
> index d81dc75..62e1540 100644
> --- a/ui/css/theme-default/storage.css
> +++ b/ui/css/theme-default/storage.css
> @@ -529,7 +529,7 @@
>       width: 300px;
>       display: inline-block;
>       vertical-align: top;
> -    padding: 5px 5px 5px 20px;
> +    padding: 5px 5px 5px 22px;
>   }
>
>   .storage-type-wrapper-controls input[type="text"] {
> @@ -548,11 +548,36 @@
>
>   .storage-type-wrapper-controls > .dropdown {
>       margin: 5px 0 0 1px;
> -    width: 250px;
> +    width: 150px;
>   }
>
>   .storage-type-wrapper-controls input[type="text"][disabled] {
>       color: #bbb;
>       background-color: #fafafa;
>       cursor: not-allowed;
> +}
> +
> +.storage-add-input-width {
> +    width: 285px;
> +}
> +
> +.form-section .storage-field {
> +    overflow: visible;
> +}
> +
> +.storage-base-input-width {
> +    width: 300px;
> +}
> +
> +.storage-window {
> +    width: 600px;
> +    height: 700px;
> +}
> +
> +.storage-port-width {
> +    width:40px;
> +}
> +
> +.storage-auth-width {
> +    width: 150px;
>   }
> \ No newline at end of file
> diff --git a/ui/js/Makefile.am b/ui/js/Makefile.am
> index 6808226..65254da 100644
> --- a/ui/js/Makefile.am
> +++ b/ui/js/Makefile.am
> @@ -20,7 +20,7 @@
>
>   SUBDIRS = novnc
>
> -EXTRA_DIST = src
> +EXTRA_DIST = src widgets
>
>   jsdir = $(datadir)/kimchi/ui/js
>
> @@ -31,7 +31,7 @@ dist_js_DATA = \
>   	modernizr.custom.2.6.2.min.js \
>   	$(NULL)
>
> -kimchi.min.js: src/*.js
> +kimchi.min.js: widgets/*.js src/*.js
>   	cat $(sort $^) > $@
>
>   CLEANFILES = kimchi.min.js
> diff --git a/ui/js/src/kimchi.api.js b/ui/js/src/kimchi.api.js
> index a4608ff..8d006d2 100644
> --- a/ui/js/src/kimchi.api.js
> +++ b/ui/js/src/kimchi.api.js
> @@ -683,5 +683,30 @@ var kimchi = {
>               success : suc,
>               error : err
>           });
> +    },
> +
> +    getStorageServers: function(type, suc, err) {
> +        var url = kimchi.url + 'storageservers?target_type=' + type;
> +        kimchi.requestJSON({
> +            url : url,
> +            type : 'GET',
> +            contentType : 'application/json',
> +            dataType : 'json',
> +            success : suc,
> +            error : err
> +        });
> +    },
> +
> +    getStorageTargets: function(server,type, suc, err) {
> +        var url = kimchi.url + 'storageservers/' + server + '/storagetargets?target_type=' + type;
> +        kimchi.requestJSON({
> +            url : url,
> +            type : 'GET',
> +            contentType : 'application/json',
> +            timeout: 2000,
> +            dataType : 'json',
> +            success : suc,
> +            error : err
> +        });
>       }
> -};
> +};
> \ No newline at end of file
> diff --git a/ui/js/src/kimchi.popable.js b/ui/js/src/kimchi.popable.js
> index 153d32c..2a843be 100644
> --- a/ui/js/src/kimchi.popable.js
> +++ b/ui/js/src/kimchi.popable.js
> @@ -25,7 +25,7 @@ kimchi.popable = function() {
>       $(document).on("click", ".popable", function(e) {
>           var isOpen = $(this).hasClass('open');
>           $(".popable").removeClass('open');
> -        if (!isOpen) {
> +        if (!isOpen && $(this).find('ul').html() !== '') {
>               $(this).addClass('open');
>           }
>
> diff --git a/ui/js/src/kimchi.storagepool_add_main.js b/ui/js/src/kimchi.storagepool_add_main.js
> index 24de979..a4d4648 100644
> --- a/ui/js/src/kimchi.storagepool_add_main.js
> +++ b/ui/js/src/kimchi.storagepool_add_main.js
> @@ -23,12 +23,13 @@
>   kimchi.storagepool_add_main = function() {
>       kimchi.initStorageAddPage();
>       $('#form-pool-add').on('submit', kimchi.addPool);
> -    $('#form-nfs-pool-add').on('submit', kimchi.addnfsPool);
>       $('#pool-doAdd').on('click', kimchi.addPool);
> -    $('#pool-nfs-doAdd').on('click', kimchi.addnfsPool);
>   };
>
>   kimchi.initStorageAddPage = function() {
> +    $('#poolTypeId').selectMenu();
> +    $('#serverComboboxId').combobox();
> +    $('#targetFilterSelectId').filterselect();
>       var options = [ {
>           label : "DIR",
>           value : "dir"
> @@ -54,8 +55,53 @@ kimchi.initStorageAddPage = function() {
>               });
>               $('.host-partition').html(listHtml);
>           }
> -        kimchi.select('storagePool-list', options);
> -        $('#poolType').change(function() {
> +        $('#poolTypeId').selectMenu("setData", options);
> +        kimchi.getStorageServers('netfs', function(data) {
> +            var serverContent = [];
> +            if (data.length > 0) {
> +                $.each(data, function(index, value) {
> +                    serverContent.push({
> +                        label : value.addr,
> +                        value : value.addr
> +                    });
> +                });
> +            }
> +            $('#serverComboboxId').combobox("setData", serverContent);
> +            $('input[name=nfsServerType]').change(function() {
> +                if ($(this).val() === 'input') {
> +                    $('#nfsServerInputDiv').removeClass('tmpl-html');
> +                    $('#nfsServerChooseDiv').addClass('tmpl-html');
> +                } else {
> +                    $('#nfsServerInputDiv').addClass('tmpl-html');
> +                    $('#nfsServerChooseDiv').removeClass('tmpl-html');
> +                }
> +            });
> +            $('#nfsserverId').on("change",function() {
> +                if ($(this).val() !== '' && kimchi.isServer($(this).val())) {
> +                    $('#nfspathId').prop('disabled',false);
> +                    $(this).removeClass("invalid-field");
> +                } else {
> +                    $(this).addClass("invalid-field");
> +                    $('#nfspathId').prop( "disabled",true);
> +                }
> +                $('#targetFilterSelectId').filterselect('clear');
> +            });
> +            $('#nfspathId').focus(function() {
> +                var targetContent = [];
> +                kimchi.getStorageTargets($('#nfsserverId').val(), 'netfs', function(data) {
> +                    if (data.length > 0) {
> +                        $.each(data, function(index, value) {
> +                            targetContent.push({
> +                                label : value.target,
> +                                value : value.target
> +                            });
> +                        });
> +                    }
> +                    $('#targetFilterSelectId').filterselect("setData", targetContent);
> +                });
> +            });
> +        });
> +        $('#poolTypeInputId').change(function() {
>               if ($(this).val() === 'dir') {
>                   $('.path-section').removeClass('tmpl-html');
>                   $('.logical-section').addClass('tmpl-html');
> @@ -93,7 +139,7 @@ kimchi.initStorageAddPage = function() {
>
>   kimchi.validateForm = function() {
>       var name = $('#poolId').val();
> -    var poolType = $("#poolType").val();
> +    var poolType = $("#poolTypeInputId").val();
>       if ('' === name) {
>           kimchi.message.error(i18n['msg.pool.edit.name.blank']);
>           return false;
> @@ -111,7 +157,6 @@ kimchi.validateForm = function() {
>       } else {
>           return kimchi.validateLogicalForm();
>       }
> -
>   };
>
>   kimchi.validateDirForm = function () {
> @@ -162,11 +207,7 @@ kimchi.validateServer = function(serverField) {
>           kimchi.message.error(i18n['msg.pool.edit.server.blank']);
>           return false;
>       }
> -    var domain = "([0-9a-z_!~*'()-]+\.)*([0-9a-z][0-9a-z-]{0,61})?[0-9a-z]\.[a-z]{2,6}"
> -    var ip = "(\\d{1,3}\.){3}\\d{1,3}"
> -    regex = new RegExp('^' + domain + '|' + ip + '$')
> -
> -    if (!regex.test(serverField)) {
> +    if(!kimchi.isServer(serverField)) {
>           kimchi.message.error(i18n['msg.validate.pool.edit.server']);
>           return false;
>       }
> @@ -186,7 +227,7 @@ kimchi.addPool = function(event) {
>       if (kimchi.validateForm()) {
>           var formData = $('#form-pool-add').serializeObject();
>           delete formData.authname;
> -        var poolType = $("#poolType").val();
> +        var poolType = $('#poolTypeId').selectMenu('value');
>           if (poolType === 'dir') {
>               formData.path = $('#pathId').val();
>           } else if (poolType === 'logical') {
> diff --git a/ui/js/src/kimchi.utils.js b/ui/js/src/kimchi.utils.js
> index a23bf51..3cf36b9 100644
> --- a/ui/js/src/kimchi.utils.js
> +++ b/ui/js/src/kimchi.utils.js
> @@ -168,3 +168,14 @@ kimchi.isUnsignedNumeric = function(number) {
>       var reg = /^d+(.d+)?$/
>       return reg.test(number);
>   }
> +
> +kimchi.isServer = function(server) {
> +    var domain = "([0-9a-z_!~*'()-]+\.)*([0-9a-z][0-9a-z-]{0,61})?[0-9a-z]\.[a-z]{2,6}";
> +    var ip = "(\\d{1,3}\.){3}\\d{1,3}";
> +    regex = new RegExp('^' + domain + '|' + ip + '$');
> +    if (!regex.test(server)) {
> +        return false;
> +    } else {
> +        return true;
> +    }
> +};
> diff --git a/ui/js/widgets/combobox.js b/ui/js/widgets/combobox.js
> new file mode 100644
> index 0000000..2782f62
> --- /dev/null
> +++ b/ui/js/widgets/combobox.js
> @@ -0,0 +1,130 @@
> +/*
> + * Project Kimchi
> + *
> + * Copyright IBM, Corp. 2013
> + *
> + * Authors:
> + *  zhoumeina <zhoumein at linux.vnet.ibm.com>
> + *
> + * Licensed under the Apache License, Version 2.0 (the 'License');
> + * you may not use this file except in compliance with the License.
> + * You may obtain a copy of the License at
> + *
> + *     http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an 'AS IS' BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> + * See the License for the specific language governing permissions and
> + * limitations under the License.
> + */
> +(function($) {
> +    $.widget('kimchi.combobox', {
> +        _create : function() {
> +            this.selectDiv = this.element;
> +            this.listControl = this.selectDiv.find('ul').first();
> +            this.listControl.html('');
> +            this.target = this.selectDiv.find('input').first();
> +            this.selectDiv.addClass('btn-select dropdown popable');
> +            this.target.addClass('input');
> +            this.target.width(this.selectDiv.width()+10);
> +            this.listControl.addClass('select-list');
> +            this.listControl.parent().addClass('popover');
> +        },
> +
> +        setData : function(options) {
> +            var that = this;
> +            var value = this.target.val();
> +            var selectedClass = 'active';
> +            var itemTag = 'li';
> +            if (options.length > 0) {
> +                that.target.after($('<span class="arrow"></span>'));
> +                that.listControl.on('click', itemTag, function(e) {
> +                    that.listControl.children().removeClass(selectedClass);
> +                    $(this).addClass(selectedClass);
> +                    var oldValue = that.target.val();
> +                    var newValue = $(this).data('value');
> +                    that.target.val(newValue);
> +                    if (oldValue !== newValue) {
> +                        that.target.change();
> +                    }
> +                });
> +
> +                that.selectDiv.click(function(e) {
> +                    that.listControl.html('');
> +                    var items = that._dataList(options);
> +                    $.each(items, function(index, item) {
> +                        that.listControl.append(item);
> +                    })
> +                });
> +
> +                that.target.keyup(function(event) {
> +                    that.listControl.html('');
> +                    var items = that._dataList(options);
> +                    var temp = 0;
> +                    $.each(items, function(index, item) {
> +                        if (item.text().indexOf(that.target.val()) == 0) {
> +                            that.listControl.append(item);
> +                            temp++;
> +                        }
> +                    });
> +                    if (temp > 0 && that.listControl.html() !== '') {
> +                        that._open();
> +                    } else {
> +                        that._close();
> +                    }
> +                });
> +            }
> +        },
> +
> +        value : function(value) {
> +            if (value === undefined) {
> +                return this.target.val();
> +            }
> +            this.target.val(value);
> +        },
> +
> +        _dataList : function(options) {
> +            var item;
> +            var itemTag = 'li';
> +            var selectedClass = 'active';
> +            var items = [];
> +            var that = this;
> +            $.each(options, function(index, option) {
> +                item = $('<' + itemTag + '>' + option.label +'</' + itemTag + '>');
> +                item.data('value', option.value);
> +                if (option.value === that.target.val()) {
> +                    item.addClass(selectedClass);
> +                }
> +                items.push(item);
> +            });
> +            return items;
> +        },
> +
> +        clear : function() {
> +            this.target.val("");
> +        },
> +
> +        _open : function() {
> +            var isOpen = this.selectDiv.hasClass('open');
> +            if (!isOpen) {
> +                this.selectDiv.addClass('open');
> +            }
> +        },
> +
> +        _close : function() {
> +            var isOpen = this.selectDiv.hasClass('open');
> +            if (isOpen) {
> +                this.selectDiv.removeClass('open');
> +            }
> +        },
> +
> +        destroy : function() {
> +            this.selectDiv.removeClass('btn-select dropdown popable');
> +            this.target.removeClass('input');
> +            this.listControl.removeClass('select-list');
> +            this.listControl.parent().removeClass('popover');
> +            $.Widget.prototype.destroy.call(this);
> +        }
> +    });
> +}(jQuery));
> \ No newline at end of file
> diff --git a/ui/js/widgets/filter-select.js b/ui/js/widgets/filter-select.js
> new file mode 100644
> index 0000000..44030a1
> --- /dev/null
> +++ b/ui/js/widgets/filter-select.js
> @@ -0,0 +1,139 @@
> +/*
> + * Project Kimchi
> + *
> + * Copyright IBM, Corp. 2013
> + *
> + * Authors:
> + *  zhoumeina <zhoumein at linux.vnet.ibm.com>
> + *
> + * Licensed under the Apache License, Version 2.0 (the 'License');
> + * you may not use this file except in compliance with the License.
> + * You may obtain a copy of the License at
> + *
> + *     http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an 'AS IS' BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> + * See the License for the specific language governing permissions and
> + * limitations under the License.
> + */
> +(function($) {
> +    $.widget('kimchi.filterselect', {
> +        _create : function() {
> +            this.selectDiv = this.element;
> +            this.listControl = this.selectDiv.find('ul').first();
> +            this.listControl.html('');
> +            this.target = this.selectDiv.find('input').first();
> +            this.selectDiv.addClass('btn-select dropdown popable');
> +            this.target.addClass('input');
> +            this.target.width(this.selectDiv.width()+10);
> +            this.listControl.addClass('select-list');
> +            this.listControl.parent().addClass('popover');
> +        },
> +
> +        setData : function(options) {
> +            var that = this;
> +            var value = this.target.val();
> +            var selectedClass = 'active';
> +            var itemTag = 'li';
> +            if (options.length > 0) {
> +                that.target.after($('<span class="arrow"></span>'));
> +                that.listControl.on('click', itemTag, function(e) {
> +                    that.listControl.children().removeClass(selectedClass);
> +                    $(this).addClass(selectedClass);
> +                    var oldValue = that.target.val();
> +                    var newValue = $(this).data('value');
> +                    that.target.val(newValue);
> +                    if (oldValue !== newValue) {
> +                        that.target.change();
> +                        that.target.removeClass("invalid-field");
> +                    }
> +                });
> +
> +                that.selectDiv.click(function(e) {
> +                    that.listControl.html('');
> +                    var items = that._dataList(options);
> +                    if (items.length === 0) {
> +                        that.listControl.html(i18n['msg.no.mapping.result']);
> +                    } else {
> +                        $.each(items, function(index, item) {
> +                            that.listControl.append(item);
> +                        });
> +                    }
> +                });
> +
> +                that.target.keyup(function(event) {
> +                    that.listControl.html('');
> +                    var items = that._dataList(options);
> +                    var temp = 0;
> +                    $.each(items, function(index, item) {
> +                        if (item.text().indexOf(that.target.val()) == 0) {
> +                            that.listControl.append(item);
> +                            temp++;
> +                        }
> +                    });
> +                    if (that.listControl.html() === '') {
> +                        that.target.addClass("invalid-field");
> +                        that.listControl.html(i18n['msg.no.mapping.result']);
> +                    } else {
> +                        that.target.removeClass("invalid-field");
> +                    }
> +                    if (temp > 0) {
> +                        that._open();
> +                    }
> +                });
> +            }
> +        },
> +
> +        value : function(value) {
> +            if (value === undefined) {
> +                return this.target.val();
> +            }
> +            this.target.val(value);
> +        },
> +
> +        _dataList : function(options) {
> +            var item;
> +            var itemTag = 'li';
> +            var selectedClass = 'active';
> +            var items = [];
> +            var that = this;
> +            $.each(options, function(index, option) {
> +                item = $('<' + itemTag + '>' + option.label +'</' + itemTag + '>');
> +                item.data('value', option.value);
> +                if (option.value === that.target.val()) {
> +                    item.addClass(selectedClass);
> +                }
> +                items.push(item);
> +            });
> +            return items;
> +        },
> +
> +        clear : function() {
> +            this.target.val("");
> +        },
> +
> +        _open : function() {
> +            var isOpen = this.selectDiv.hasClass('open');
> +            if (!isOpen) {
> +                this.selectDiv.addClass('open');
> +            }
> +        },
> +
> +        _close : function() {
> +            var isOpen = this.selectDiv.hasClass('open');
> +            if (isOpen) {
> +                this.selectDiv.removeClass('open');
> +            }
> +        },
> +
> +        destroy : function() {
> +            this.selectDiv.removeClass('btn-select dropdown popable');
> +            this.target.removeClass('input');
> +            this.listControl.removeClass('select-list');
> +            this.listControl.parent().removeClass('popover')
> +            $.Widget.prototype.destroy.call(this);
> +        }
> +    });
> +}(jQuery));
> \ No newline at end of file
> diff --git a/ui/js/widgets/select-menu.js b/ui/js/widgets/select-menu.js
> new file mode 100644
> index 0000000..c9a1b87
> --- /dev/null
> +++ b/ui/js/widgets/select-menu.js
> @@ -0,0 +1,86 @@
> +/*
> + * Project Kimchi
> + *
> + * Copyright IBM, Corp. 2013
> + *
> + * Authors:
> + *  zhoumeina <zhoumein at linux.vnet.ibm.com>
> + *
> + * Licensed under the Apache License, Version 2.0 (the 'License');
> + * you may not use this file except in compliance with the License.
> + * You may obtain a copy of the License at
> + *
> + *     http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an 'AS IS' BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> + * See the License for the specific language governing permissions and
> + * limitations under the License.
> + */
> +(function($) {
> +    $.widget('kimchi.selectMenu', {
> +
> +        _create : function() {
> +            this.selectDiv = this.element;
> +            this.listControl = this.selectDiv.find('ul').first();
> +            this.listControl.html('');
> +            this.target = this.selectDiv.find('input').first();
> +            this.label = this.selectDiv.find('span').first();
> +            this.selectDiv.addClass('btn-select dropdown popable');
> +            this.target.addClass('input');
> +            this.label.addClass('input');
> +            this.listControl.addClass('select-list');
> +            this.listControl.parent().addClass('popover');
> +        },
> +
> +        setData : function (options) {
> +            var that = this;
> +            var value = this.target.val();
> +            var selectedClass = 'active';
> +            var itemTag = 'li';
> +            var item;
> +            if (options.length > 0) {
> +                $.each(options, function(index, option) {
> +                    item = $('<' + itemTag + '>' + option.label +'</' + itemTag + '>');
> +                    item.data('value', option.value);
> +                    if(option.value === value) {
> +                        item.addClass(selectedClass);
> +                        that.label.text(option.label);
> +                    }
> +                    that.listControl.append(item);
> +                });
> +                that.listControl.on('click', itemTag, function() {
> +                    that.listControl.children().removeClass(selectedClass);
> +                    $(this).addClass(selectedClass);
> +                    that.label.text($(this).text());
> +                    var oldValue = that.target.val();
> +                    var newValue = $(this).data('value');
> +                    that.target.val(newValue);
> +                    if(oldValue !== newValue) {
> +                        that.target.change();
> +                    }
> +                });
> +            } else {
> +                kimchi.message.error(i18n['selectmenu.data.error']);
> +            }
> +        },
> +
> +        value : function(data) {
> +            if (data === undefined) {
> +                return this.target.val();
> +            }
> +            this.target.val(data.value);
> +            this.label.val(data.label);
> +        },
> +
> +        destroy : function() {
> +            this.selectDiv.removeClass('btn-select dropdown popable');
> +            this.target.removeClass('input');
> +            this.label.removeClass('input');
> +            this.listControl.removeClass('select-list');
> +            this.listControl.parent().removeClass('popover');
> +            $.Widget.prototype.destroy.call(this);
> +        }
> +    });
> +}(jQuery));
> \ No newline at end of file
> diff --git a/ui/pages/i18n.html.tmpl b/ui/pages/i18n.html.tmpl
> index 603f8d7..37b4114 100644
> --- a/ui/pages/i18n.html.tmpl
> +++ b/ui/pages/i18n.html.tmpl
> @@ -122,7 +122,11 @@ var i18n = {
>                                         " there, are you sure to continue? ")",
>       'msg.pool.edit.iscsitarget.blank': "$_("The iSCSI target can not be blank.")",
>       'msg.pool.edit.server.blank':"$_("Server name can not be blank.")",
> -    'msg.validate.pool.edit.server':"$_("This is not a valid Server Name or IP. please, modify it.")"
> +    'msg.validate.pool.edit.server':"$_("This is not a valid Server Name or IP. please, modify it.")",
> +    'select_default': "$_("Please choose")",
> +    'msg.no.mapping.result': "$_("No such data exsit.")",
> +    'msg.no.result' : "$_("No valid result")",
> +    'selectmenu.data.error' : "$_("options needed.")"
>   };
>   </script>
>   </body>
> diff --git a/ui/pages/storagepool-add.html.tmpl b/ui/pages/storagepool-add.html.tmpl
> index e8dac43..363d097 100644
> --- a/ui/pages/storagepool-add.html.tmpl
> +++ b/ui/pages/storagepool-add.html.tmpl
> @@ -27,7 +27,7 @@
>   <!DOCTYPE html>
>   <html>
>   <body>
> -    <div class="window" style="width: 600px; height: 700px;">
> +    <div class="window storage-window">
>           <header>
>               <h1 class="title">$_("Define a New Storage Pool")</h1>
>               <div class="close">X</div>
> @@ -40,18 +40,17 @@
>                           <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" style="width: 300px"
> -                            name="name">
> +                        <input id="poolId" required="required" type="text" class="text storage-base-input-width" name="name">
>                       </div>
>                   </section>
>                   <section class="form-section">
>                       <h2>2. $_("Storage Pool Type")</h2>
>                       <div class="storage-type-wrapper-controls">
> -                        <div class="btn dropdown popable">
> -                            <input id="poolType" name="type" type="hidden" value="dir"/>
> -                            <span class="text" id="pool-type-label"></span><span class="arrow"></span>
> -                            <div class="popover" style="width: 100%">
> -                                <ul class="select-list" id="storagePool-list" data-target="poolType" data-label="pool-type-label">
> +                        <div id="poolTypeId">
> +                            <input id="poolTypeInputId" name="type" type="hidden" value="dir"/>
> +                            <span id="pool-type-label"></span><span class="arrow"></span>
> +                            <div>
> +                                <ul id="storagePool-list">
>                                   </ul>
>                               </div>
>                           </div>
> @@ -65,30 +64,38 @@
>                                   $_("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" required="required" style="width: 300px">
> +                            <input id="pathId" type="text" class="text storage-base-input-width">
>                           </div>
>                           <div class="clear"></div>
>                       </section>
>                   </div>
>                   <div class="nfs-section tmpl-html">
>                       <section class="form-section">
> -                        <h2>3. $_("NFS server IP")</h2>
> -                        <div class="field">
> +                        <h2>3. $_("NFS Server IP")</h2>
> +                        <div class="field storage-field">
>                               <p class="text-help">
> -                                $_("NFS server IP or hostname. It should not be empty.")</p>
> -                            <input id="nfsserverId" required="required" type="text" class="text"
> -                                style="width: 300px">
> +                                $_("NFS server IP or hostname. It can be input or chosen from history.")</p>
> +                            <div id="serverComboboxId" class="storage-add-input-width">
> +                                <input id="nfsserverId"/>
> +                                <div>
> +                                    <ul id="nfs-server-used">
> +                                    </ul>
> +                                </div>
> +                            </div>
>                           </div>
>                       </section>
>                       <section class="form-section">
>                           <h2>4. $_("NFS Path")</h2>
> -                        <div class="field">
> -                            <p class="text-help">$_("The nfs exported path on nfs server")</p>
> -                            <input id="nfspathId" required="required" type="text" class="text"
> -                                style="width: 300px">
> -                            <input type="hidden" id="localpathId" class="text" value="none">
> -                        </div>
> -                        <div class="clear"></div>
> +                        <div class="field storage-field">
> +                            <p class="text-help">$_("The nfs exported path on nfs server.")</p>
> +                            <div id="targetFilterSelectId" class="storage-add-input-width">
> +	                            <input id="nfspathId" class="input" disabled/>
> +		                        <div>
> +		                            <ul id="nfs-server-target">
> +		                            </ul>
> +		                        </div>
> +		                    </div>
> +	                    </div>
>                       </section>
>                   </div>
>                   <div class="logical-section tmpl-html">
> @@ -103,15 +110,15 @@
>                           <div class="field">
>                               <p class="text-help">
>                                   $_("iSCSI server IP or hostname. It should not be empty.")</p>
> -                            <input id="iscsiserverId" placeholder="$_("Server")" type="text" class="text" style="width: 300px">
> -                            <input id="iscsiportId" placeholder="$_("Port")" type="text" class="text" style="width:40px" maxlength='4'>
> +                            <input id="iscsiserverId" placeholder="$_("Server")" type="text" class="text storage-base-input-width">
> +                            <input id="iscsiportId" placeholder="$_("Port")" type="text" class="text storage-port-width" maxlength="4">
>                           </div>
>                       </section>
>                       <section class="form-section">
>                           <h2>4. $_("Target")</h2>
>                           <div class="field">
>                               <p class="text-help">$_("The iSCSI target on iSCSI server")</p>
> -                            <input id="iscsiTargetId" type="text" class="text" style="width: 300px">
> +                            <input id="iscsiTargetId" type="text" class="text storage-base-input-width">
>                           </div>
>                       </section>
>                       <section class="form-section">
> @@ -123,8 +130,8 @@
>                       <section class="authenticationfield form-section tmpl-html">
>                           <h2>5. $_("iSCSI Authentication")</h2>
>                           <div class="field">
> -                            <input id="usernameId" placeholder="$_("User Name")" type="text" class="text" style="width: 150px">
> -                            <input id="passwordId" placeholder="$_("Password")" type="text" class="text" style="width: 150px">
> +                            <input id="usernameId" placeholder="$_("User Name")" type="text" class="text storage-auth-width">
> +                            <input id="passwordId" placeholder="$_("Password")" type="text" class="text storage-auth-width">
>                           </div>
>                       </section>
>                   </div>




More information about the Kimchi-devel mailing list