فهرست منبع

`put_buttons()` support disabled button, button value can be any type

wangweimin 3 سال پیش
والد
کامیت
5b9ec842f1
3فایلهای تغییر یافته به همراه37 افزوده شده و 18 حذف شده
  1. 1 1
      docs/spec.rst
  2. 35 15
      pywebio/output.py
  3. 1 2
      webiojs/src/models/output.ts

+ 1 - 1
docs/spec.rst

@@ -228,7 +228,7 @@ Unique attributes of different types:
 * type: buttons
 * type: buttons
 
 
   * callback_id:
   * callback_id:
-  * buttons:[ {value:, label:, [color:]},...]
+  * buttons:[ {value:, label:, [color:], [disabled:]},...]
   * small: bool, Whether to enable small button
   * small: bool, Whether to enable small button
   * group: bool, Whether to group the buttons together
   * group: bool, Whether to group the buttons together
   * link: bool, Whether to make button seem as link.
   * link: bool, Whether to make button seem as link.

+ 35 - 15
pywebio/output.py

@@ -660,17 +660,18 @@ def put_table(tdata, header=None, scope=None, position=OutputPosition.BOTTOM) ->
 
 
 def _format_button(buttons):
 def _format_button(buttons):
     """
     """
-    Format `buttons` parameter in `put_buttons()`
+    Format `buttons` parameter in `put_buttons()`, replace its value with its idx
     :param buttons:
     :param buttons:
         {label:, value:, }
         {label:, value:, }
         (label, value, )
         (label, value, )
         single value, label=value
         single value, label=value
 
 
-    :return: [{value:, label:, }, ...]
+    :return: [{value:, label:, }, ...], values
     """
     """
 
 
     btns = []
     btns = []
-    for btn in buttons:
+    values = []
+    for idx, btn in enumerate(buttons):
         btn = copy.deepcopy(btn)
         btn = copy.deepcopy(btn)
         if isinstance(btn, Mapping):
         if isinstance(btn, Mapping):
             assert 'value' in btn and 'label' in btn, 'actions item must have value and label key'
             assert 'value' in btn and 'label' in btn, 'actions item must have value and label key'
@@ -679,8 +680,10 @@ def _format_button(buttons):
             btn = dict(zip(('label', 'value'), btn))
             btn = dict(zip(('label', 'value'), btn))
         else:
         else:
             btn = dict(value=btn, label=btn)
             btn = dict(value=btn, label=btn)
+        values.append(btn['value'])
+        btn['value'] = idx
         btns.append(btn)
         btns.append(btn)
-    return btns
+    return btns, values
 
 
 
 
 def put_buttons(buttons, onclick, small=None, link_style=False, outline=False, group=False, scope=None,
 def put_buttons(buttons, onclick, small=None, link_style=False, outline=False, group=False, scope=None,
@@ -690,11 +693,19 @@ def put_buttons(buttons, onclick, small=None, link_style=False, outline=False, g
 
 
     :param list buttons: Button list. The available formats of list items are:
     :param list buttons: Button list. The available formats of list items are:
 
 
-        * dict: ``{label:(str)button label, value:(str)button value, color:(str, optional)button color}``
+        * dict::
+
+            {
+                "label":(str)button label,
+                "value":(str)button value,
+                "color":(str, optional)button color,
+                "disabled":(bool, optional) whether the button is disabled
+            }
+
         * tuple or list: ``(label, value)``
         * tuple or list: ``(label, value)``
         * single value: label and value of option use the same value
         * single value: label and value of option use the same value
 
 
-        The ``value`` of button can be any JSON serializable object.
+        The ``value`` of button can be any type.
         The ``color`` of button can be one of: `primary`, `secondary`, `success`, `danger`, `warning`, `info`, `light`, `dark`.
         The ``color`` of button can be one of: `primary`, `secondary`, `success`, `danger`, `warning`, `info`, `light`, `dark`.
 
 
         Example:
         Example:
@@ -760,19 +771,23 @@ def put_buttons(buttons, onclick, small=None, link_style=False, outline=False, g
             put_text("You click delete button")
             put_text("You click delete button")
 
 
         put_buttons(['edit', 'delete'], onclick=[edit, delete])
         put_buttons(['edit', 'delete'], onclick=[edit, delete])
+
+    .. versionchanged:: 1.5
+       Add ``disabled`` button support.
+       The ``value`` of button can be any object.
     """
     """
-    btns = _format_button(buttons)
+    btns, values = _format_button(buttons)
 
 
     if isinstance(onclick, Sequence):
     if isinstance(onclick, Sequence):
         assert len(btns) == len(onclick), "`onclick` and `buttons` must be same length."
         assert len(btns) == len(onclick), "`onclick` and `buttons` must be same length."
-        for idx, btn in enumerate(btns):
-            btn['value'] = idx
 
 
-    def click_callback(btn_val):
+    def click_callback(btn_idx):
         if isinstance(onclick, Sequence):
         if isinstance(onclick, Sequence):
-            return onclick[btn_val]()
+            onclick[btn_idx]()
         else:
         else:
-            return onclick(btn_val)
+            btn_val = values[btn_idx]
+            if not btns[btn_idx].get('disabled'):
+                onclick(btn_val)
 
 
     callback_id = output_register_callback(click_callback, **callback_options)
     callback_id = output_register_callback(click_callback, **callback_options)
     spec = _get_output_spec('buttons', callback_id=callback_id, buttons=btns, small=small,
     spec = _get_output_spec('buttons', callback_id=callback_id, buttons=btns, small=small,
@@ -781,7 +796,7 @@ def put_buttons(buttons, onclick, small=None, link_style=False, outline=False, g
     return Output(spec)
     return Output(spec)
 
 
 
 
-def put_button(label, onclick, color=None, small=None, link_style=False, outline=False, scope=None,
+def put_button(label, onclick, color=None, small=None, link_style=False, outline=False, disabled=False, scope=None,
                position=OutputPosition.BOTTOM) -> Output:
                position=OutputPosition.BOTTOM) -> Output:
     """Output a single button and bind click event to it.
     """Output a single button and bind click event to it.
 
 
@@ -789,6 +804,7 @@ def put_button(label, onclick, color=None, small=None, link_style=False, outline
     :param callable onclick: Callback which will be called when button is clicked.
     :param callable onclick: Callback which will be called when button is clicked.
     :param str color: The color of the button,
     :param str color: The color of the button,
         can be one of: `primary`, `secondary`, `success`, `danger`, `warning`, `info`, `light`, `dark`.
         can be one of: `primary`, `secondary`, `success`, `danger`, `warning`, `info`, `light`, `dark`.
+    :param bool disabled: Whether the button is disabled
     :param - small, link_style, outline, scope, position:  Those arguments have the same meaning as for `put_buttons()`
     :param - small, link_style, outline, scope, position:  Those arguments have the same meaning as for `put_buttons()`
 
 
     Example:
     Example:
@@ -800,9 +816,13 @@ def put_button(label, onclick, color=None, small=None, link_style=False, outline
         put_button("click me", onclick=lambda: toast("Clicked"), color='success', outline=True)
         put_button("click me", onclick=lambda: toast("Clicked"), color='success', outline=True)
 
 
     .. versionadded:: 1.4
     .. versionadded:: 1.4
+
+    .. versionchanged:: 1.5
+       add ``disabled`` parameter
     """
     """
-    return put_buttons([{'label': label, 'value': '', 'color': color or 'primary'}], onclick=[onclick],
-                       small=small, link_style=link_style, outline=outline, scope=scope, position=position)
+    return put_buttons([{'label': label, 'value': '', 'color': color or 'primary', 'disabled': disabled}],
+                       onclick=[onclick], small=small, link_style=link_style, outline=outline, scope=scope,
+                       position=position)
 
 
 
 
 def put_image(src, format=None, title='', width=None, height=None,
 def put_image(src, format=None, title='', width=None, height=None,

+ 1 - 2
webiojs/src/models/output.ts

@@ -85,7 +85,7 @@ let Buttons = {
     handle_type: 'buttons',
     handle_type: 'buttons',
     get_element: function (spec: any) {
     get_element: function (spec: any) {
         const btns_tpl = `<div{{#group}} class="btn-group" role="group"{{/group}}>{{#buttons}} 
         const btns_tpl = `<div{{#group}} class="btn-group" role="group"{{/group}}>{{#buttons}} 
-                                <button class="btn {{#color}}btn-{{#outline}}outline-{{/outline}}{{color}}{{/color}}{{#small}} btn-sm{{/small}}">{{label}}</button> 
+                                <button class="btn {{#color}}btn-{{#outline}}outline-{{/outline}}{{color}}{{/color}}{{#small}} btn-sm{{/small}}" {{#disabled}}disabled{{/disabled}}>{{label}}</button> 
                           {{/buttons}}</div>`;
                           {{/buttons}}</div>`;
         spec.color = "primary";  // fallback color
         spec.color = "primary";  // fallback color
         if (spec.link) {
         if (spec.link) {
@@ -226,7 +226,6 @@ let ScrollableWidget = {
             }).on('focusout mouseleave', function (e) {
             }).on('focusout mouseleave', function (e) {
                 stop = false
                 stop = false
             });
             });
-            console.log(container)
             new MutationObserver(function (mutations, observe) {
             new MutationObserver(function (mutations, observe) {
                 if (!stop) container.stop().animate({scrollTop: container.prop("scrollHeight")}, 200);
                 if (!stop) container.stop().animate({scrollTop: container.prop("scrollHeight")}, 200);
             }).observe(container[0], {childList: true, subtree: true});
             }).observe(container[0], {childList: true, subtree: true});