Parcourir la source

添加select支持, option 参数checked变为selected

wangweimin il y a 5 ans
Parent
commit
6b88127e42
4 fichiers modifiés avec 79 ajouts et 12 suppressions
  1. 2 1
      doc/spec.md
  2. 28 0
      test.py
  3. 22 6
      wsrepl/html/js/form.js
  4. 27 5
      wsrepl/interact.py

+ 2 - 1
doc/spec.md

@@ -36,12 +36,13 @@
     value:
     placeholder: placeholder 属性是提示用户内容的输入格式。某些情况下 placeholder 属性对用户不可见, 所以当没有它时也需要保证form能被理解。
     ^inline  // type==checkbox,radio
-    ^options // type==checkbox,radio , 字典列表 {*value:, *label:, checked,disabled }
+    ^options // type==checkbox,radio , 字典列表 {*value:, *label:, selected,disabled }
 
 
 
 type=<select>
 ref https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/select
+    multiple
 
 type=<textarea>
 ref https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/textarea

+ 28 - 0
test.py

@@ -12,6 +12,34 @@ from tornado.gen import sleep
 def say_hello():
     # 向用户输出文字
     text_print("Welcome!!!")
+    res = yield from select('This is select input', [
+        {'value': 1, 'label': 'one', 'selected': False, 'disabled': False},
+        {'value': 2, 'label': 'two', 'selected': True, 'disabled': False},
+        {'value': 2, 'label': 'three disabled', 'selected': False, 'disabled': True},
+    ], type=SELECT, multiple=False)
+    text_print('Your input:%s' % res)
+
+    res = yield from select('This is multiple select input', [
+        {'value': 1, 'label': 'one', 'selected': True, 'disabled': False},
+        {'value': 2, 'label': 'two', 'selected': True, 'disabled': False},
+        {'value': 2, 'label': 'three disabled', 'selected': False, 'disabled': True},
+    ], type=SELECT, multiple=True)
+    text_print('Your input:%s' % res)
+
+    res = yield from select('This is RADIO input', [
+        {'value': 1, 'label': 'one', 'selected': False, 'disabled': False},
+        {'value': 2, 'label': 'two', 'selected': True, 'disabled': False},
+        {'value': 2, 'label': 'three disabled', 'selected': False, 'disabled': True},
+    ], type=RADIO, multiple=True)
+    text_print('Your input:%s' % res)
+
+    res = yield from select('This is CHECKBOX input', [
+        {'value': 1, 'label': 'one', 'selected': False, 'disabled': False},
+        {'value': 2, 'label': 'two', 'selected': True, 'disabled': False},
+        {'value': 2, 'label': 'three disabled', 'selected': False, 'disabled': True},
+    ], type=CHECKBOX, multiple=True)
+    text_print('Your input:%s' % res)
+
     res = yield from input('This is single input')
     text_print('Your input:%s' % res)
 

+ 22 - 6
wsrepl/html/js/form.js

@@ -342,7 +342,7 @@
         this.create_element();
     }
 
-    CommonInputController.prototype.accept_input_types = ["text", "password", "number", "color", "date", "range", "time"];
+    CommonInputController.prototype.accept_input_types = ["text", "password", "number", "color", "date", "range", "time", "select"];
     /*
     *
     * type=
@@ -354,12 +354,28 @@
     <div class="invalid-feedback">{{invalid_feedback}}</div>  <!-- input 添加 is-invalid 类 -->
     <div class="valid-feedback">{{valid_feedback}}</div> <!-- input 添加 is-valid 类 -->
     <small id="{{id_name}}_help" class="form-text text-muted">{{help_text}}</small>
+</div>`;
+    const select_input_tpl = `
+<div class="form-group">
+    <label for="{{id_name}}">{{label}}</label>
+    <select id="{{id_name}}" aria-describedby="{{id_name}}_help" class="form-control">
+        {{#options}}
+        <option value="{{value}}" {{#selected}}selected{{/selected}} {{#disabled}}disabled{{/disabled}}>{{label}}</option>
+        {{/options}}
+    </select>
+    <div class="invalid-feedback">{{invalid_feedback}}</div>
+    <div class="valid-feedback">{{valid_feedback}}</div>
+    <small id="{{id_name}}_help" class="form-text text-muted">{{help_text}}</small>
 </div>`;
     CommonInputController.prototype.create_element = function () {
         var spec = deep_copy(this.spec);
         const id_name = spec.name + '-' + Math.floor(Math.random() * Math.floor(9999));
         spec['id_name'] = id_name;
-        const html = Mustache.render(common_input_tpl, spec);
+        var html;
+        if (spec.type === 'select')
+            html = Mustache.render(select_input_tpl, spec);
+        else
+            html = Mustache.render(common_input_tpl, spec);
 
         this.element = $(html);
         var input_elem = this.element.find('#' + id_name);
@@ -368,7 +384,7 @@
         input_elem.on('blur', this.send_value_listener);
 
         // 将额外的html参数加到input标签上
-        const ignore_keys = {'type': '', 'label': '', 'invalid_feedback': '', 'valid_feedback': '', 'help_text': ''};
+        const ignore_keys = {'type': '', 'label': '', 'invalid_feedback': '', 'valid_feedback': '', 'help_text': '', 'options':''};
         for (var key in this.spec) {
             if (key in ignore_keys) continue;
             input_elem.attr(key, this.spec[key]);
@@ -382,7 +398,7 @@
     };
 
     CommonInputController.prototype.get_value = function () {
-        return this.element.find('input').val();
+        return this.element.find('input,select').val();
     };
 
     function CheckboxRadioController(ws_client, coro_id, spec) {
@@ -398,7 +414,7 @@
     <label>{{label}}</label> {{#inline}}<br>{{/inline}}
     {{#options}}
     <div class="form-check {{#inline}}form-check-inline{{/inline}}">
-        <input type="{{type}}" id="{{id_name_prefix}}-{{idx}}" class="form-check-input" name="{{name}}" value="{{value}}">
+        <input type="{{type}}" id="{{id_name_prefix}}-{{idx}}" name="{{name}}" value="{{value}}" {{#selected}}checked{{/selected}} class="form-check-input">
         <label class="form-check-label" for="{{id_name_prefix}}-{{idx}}">
             {{label}}
         </label>
@@ -420,7 +436,7 @@
         var elem = $(html);
         this.element = elem;
 
-        const ignore_keys = {'value': '', 'label': ''};
+        const ignore_keys = {'value': '', 'label': '', 'selected': ''};
         for (idx = 0; idx < this.spec.options.length; idx++) {
             var input_elem = elem.find('#' + id_name_prefix + '-' + idx);
             // blur事件时,发送当前值到服务器

+ 27 - 5
wsrepl/interact.py

@@ -119,8 +119,8 @@ def _make_input_spec(label, type, name, valid_func=None, multiple=None, inline=N
         assert 'options' in input_item, 'Input type not allowed.'
         assert isinstance(input_item['options'], Iterable), 'options must be list type'
         # option 可用形式:
-        # {value:, label:, [checked:,] [disabled:]}
-        # (value, label, [checked,] [disabled])
+        # {value:, label:, [selected:,] [disabled:]}
+        # (value, label, [selected,] [disabled])
         # value 单值,label等于value
         opts = input_item['options']
         opts_res = []
@@ -129,7 +129,7 @@ def _make_input_spec(label, type, name, valid_func=None, multiple=None, inline=N
                 assert 'value' in opt and 'label' in opt, 'options item must have value and label key'
             elif isinstance(opt, list):
                 assert len(opt) > 1 and len(opt) <= 4, 'options item format error'
-                opt = dict(zip(('value', 'label', 'checked', 'disabled'), opt))
+                opt = dict(zip(('value', 'label', 'selected', 'disabled'), opt))
             else:
                 opt = dict(value=opt, label=opt)
             opts_res.append(opt)
@@ -155,8 +155,30 @@ def input(label, type=TEXT, *, valid_func=None, name='data', value='', placehold
     return data[name]
 
 
-def select(label, options, type=SELECT, *, multiple=False, valid_func=None, name='data', value='', placeholder='',
-           required=False, readonly=False, disabled=False, inline=False, **other_html_attrs):
+def select(label, options, type=SELECT, *, multiple=None, valid_func=None, name='data', value='', placeholder='',
+           required=False, readonly=False, disabled=False, inline=None, **other_html_attrs):
+    """
+    参数值为None表示不指定,使用默认值
+
+    :param label:
+    :param options: option 列表
+        option 可用形式:
+        {value:, label:, [selected:,] [disabled:]}
+        (value, label, [selected,] [disabled])
+        value 单值,label等于value
+    :param type:
+    :param multiple:
+    :param valid_func:
+    :param name:
+    :param value:
+    :param placeholder:
+    :param required:
+    :param readonly:
+    :param disabled:
+    :param inline:
+    :param other_html_attrs:
+    :return:
+    """
     input_kwargs = dict(locals())
     input_kwargs['label'] = ''
     input_kwargs['__name__'] = select.__name__