Prechádzať zdrojové kódy

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

wangweimin 5 rokov pred
rodič
commit
6b88127e42
4 zmenil súbory, kde vykonal 79 pridanie a 12 odobranie
  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:
     value:
     placeholder: placeholder 属性是提示用户内容的输入格式。某些情况下 placeholder 属性对用户不可见, 所以当没有它时也需要保证form能被理解。
     placeholder: placeholder 属性是提示用户内容的输入格式。某些情况下 placeholder 属性对用户不可见, 所以当没有它时也需要保证form能被理解。
     ^inline  // type==checkbox,radio
     ^inline  // type==checkbox,radio
-    ^options // type==checkbox,radio , 字典列表 {*value:, *label:, checked,disabled }
+    ^options // type==checkbox,radio , 字典列表 {*value:, *label:, selected,disabled }
 
 
 
 
 
 
 type=<select>
 type=<select>
 ref https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/select
 ref https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/select
+    multiple
 
 
 type=<textarea>
 type=<textarea>
 ref https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/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():
 def say_hello():
     # 向用户输出文字
     # 向用户输出文字
     text_print("Welcome!!!")
     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')
     res = yield from input('This is single input')
     text_print('Your input:%s' % res)
     text_print('Your input:%s' % res)
 
 

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

@@ -342,7 +342,7 @@
         this.create_element();
         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=
     * type=
@@ -354,12 +354,28 @@
     <div class="invalid-feedback">{{invalid_feedback}}</div>  <!-- input 添加 is-invalid 类 -->
     <div class="invalid-feedback">{{invalid_feedback}}</div>  <!-- input 添加 is-invalid 类 -->
     <div class="valid-feedback">{{valid_feedback}}</div> <!-- input 添加 is-valid 类 -->
     <div class="valid-feedback">{{valid_feedback}}</div> <!-- input 添加 is-valid 类 -->
     <small id="{{id_name}}_help" class="form-text text-muted">{{help_text}}</small>
     <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>`;
 </div>`;
     CommonInputController.prototype.create_element = function () {
     CommonInputController.prototype.create_element = function () {
         var spec = deep_copy(this.spec);
         var spec = deep_copy(this.spec);
         const id_name = spec.name + '-' + Math.floor(Math.random() * Math.floor(9999));
         const id_name = spec.name + '-' + Math.floor(Math.random() * Math.floor(9999));
         spec['id_name'] = id_name;
         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);
         this.element = $(html);
         var input_elem = this.element.find('#' + id_name);
         var input_elem = this.element.find('#' + id_name);
@@ -368,7 +384,7 @@
         input_elem.on('blur', this.send_value_listener);
         input_elem.on('blur', this.send_value_listener);
 
 
         // 将额外的html参数加到input标签上
         // 将额外的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) {
         for (var key in this.spec) {
             if (key in ignore_keys) continue;
             if (key in ignore_keys) continue;
             input_elem.attr(key, this.spec[key]);
             input_elem.attr(key, this.spec[key]);
@@ -382,7 +398,7 @@
     };
     };
 
 
     CommonInputController.prototype.get_value = function () {
     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) {
     function CheckboxRadioController(ws_client, coro_id, spec) {
@@ -398,7 +414,7 @@
     <label>{{label}}</label> {{#inline}}<br>{{/inline}}
     <label>{{label}}</label> {{#inline}}<br>{{/inline}}
     {{#options}}
     {{#options}}
     <div class="form-check {{#inline}}form-check-inline{{/inline}}">
     <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 class="form-check-label" for="{{id_name_prefix}}-{{idx}}">
             {{label}}
             {{label}}
         </label>
         </label>
@@ -420,7 +436,7 @@
         var elem = $(html);
         var elem = $(html);
         this.element = elem;
         this.element = elem;
 
 
-        const ignore_keys = {'value': '', 'label': ''};
+        const ignore_keys = {'value': '', 'label': '', 'selected': ''};
         for (idx = 0; idx < this.spec.options.length; idx++) {
         for (idx = 0; idx < this.spec.options.length; idx++) {
             var input_elem = elem.find('#' + id_name_prefix + '-' + idx);
             var input_elem = elem.find('#' + id_name_prefix + '-' + idx);
             // blur事件时,发送当前值到服务器
             // 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 'options' in input_item, 'Input type not allowed.'
         assert isinstance(input_item['options'], Iterable), 'options must be list type'
         assert isinstance(input_item['options'], Iterable), 'options must be list type'
         # option 可用形式:
         # option 可用形式:
-        # {value:, label:, [checked:,] [disabled:]}
-        # (value, label, [checked,] [disabled])
+        # {value:, label:, [selected:,] [disabled:]}
+        # (value, label, [selected,] [disabled])
         # value 单值,label等于value
         # value 单值,label等于value
         opts = input_item['options']
         opts = input_item['options']
         opts_res = []
         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'
                 assert 'value' in opt and 'label' in opt, 'options item must have value and label key'
             elif isinstance(opt, list):
             elif isinstance(opt, list):
                 assert len(opt) > 1 and len(opt) <= 4, 'options item format error'
                 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:
             else:
                 opt = dict(value=opt, label=opt)
                 opt = dict(value=opt, label=opt)
             opts_res.append(opt)
             opts_res.append(opt)
@@ -155,8 +155,30 @@ def input(label, type=TEXT, *, valid_func=None, name='data', value='', placehold
     return data[name]
     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 = dict(locals())
     input_kwargs['label'] = ''
     input_kwargs['label'] = ''
     input_kwargs['__name__'] = select.__name__
     input_kwargs['__name__'] = select.__name__