Skip to content

Commit

Permalink
feat: add slider() input
Browse files Browse the repository at this point in the history
  • Loading branch information
wang0618 committed May 29, 2021
1 parent 3df460a commit aa629e3
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 4 deletions.
7 changes: 7 additions & 0 deletions docs/spec.rst
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,13 @@ Unique attributes of different input types:
* max_size: The maximum size of a single file, in bytes.
* max_total_size: The maximum size of all files, in bytes.

* slider

* min_value: The minimum permitted value.
* max_value: The maximum permitted value.
* step: The stepping interval.
* float: If need return a float value

update_input
^^^^^^^^^^^^^^^

Expand Down
27 changes: 26 additions & 1 deletion pywebio/input.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@
* - `radio <pywebio.input.radio>`
- Radio
* - `slider <pywebio.input.slider>`
- Slider
* - `actions <pywebio.input.actions>`
- Actions selection
Expand Down Expand Up @@ -87,7 +90,7 @@
TEXTAREA = 'textarea'

__all__ = ['TEXT', 'NUMBER', 'FLOAT', 'PASSWORD', 'URL', 'DATE', 'TIME', 'input', 'textarea', 'select',
'checkbox', 'radio', 'actions', 'file_upload', 'input_group', 'input_update']
'checkbox', 'radio', 'actions', 'file_upload', 'slider', 'input_group', 'input_update']


def _parse_args(kwargs, excludes=()):
Expand Down Expand Up @@ -577,6 +580,28 @@ def read_file(data):
return single_input(item_spec, valid_func, read_file, onchange_func)


def slider(label='', *, name=None, value=0, min_value=0, max_value=100, step=1, validate=None, onchange=None,
required=None, help_text=None, **other_html_attrs):
r"""Range input.
:param int/float value: The initial value of the slider.
:param int/float min_value: The minimum permitted value.
:param int/float max_value: The maximum permitted value.
:param int step: The stepping interval.
Only available when ```value``, ``min_value`` and ``max_value`` are all integer.
:param - label, name, validate, onchange, required, help_text, other_html_attrs: Those arguments have the same meaning as for `input()`
:return int/float: If one of ``value``, ``min_value`` and ``max_value`` is float,
the return value is a float, otherwise an int is returned.
"""
item_spec, valid_func, onchange_func = _parse_args(locals())
item_spec['type'] = 'slider'
item_spec['float'] = any(isinstance(i, float) for i in (value, min_value, max_value))
if item_spec['float']:
item_spec['step'] = 'any'

return single_input(item_spec, valid_func, lambda d: d, onchange_func)


def input_group(label='', inputs=None, validate=None, cancelable=False):
r"""Input group. Request a set of inputs from the user at once.
Expand Down
13 changes: 11 additions & 2 deletions pywebio/pin.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
.. autofunction:: put_select
.. autofunction:: put_checkbox
.. autofunction:: put_radio
.. autofunction:: put_slider
Pin utils
------------------
Expand Down Expand Up @@ -125,7 +126,7 @@

_html_value_chars = set(string.ascii_letters + string.digits + '_')

__all__ = ['put_input', 'put_textarea', 'put_select', 'put_checkbox', 'put_radio', 'pin', 'pin_update',
__all__ = ['put_input', 'put_textarea', 'put_select', 'put_checkbox', 'put_radio', 'put_slider', 'pin', 'pin_update',
'pin_wait_change']


Expand Down Expand Up @@ -186,6 +187,15 @@ def put_radio(name, options=None, *, label='', inline=None, value=None, help_tex
return _pin_output(single_input_return, scope, position)


def put_slider(name, *, label='', value=0, min_value=0, max_value=100, step=1, required=None, help_text=None,
scope=Scope.Current, position=OutputPosition.BOTTOM) -> Output:
"""Output a slide widget. Refer to: `pywebio.input.slide()`"""
check_name(name)
single_input_return = slider(name=name, label=label, value=value, min_value=min_value, max_value=max_value,
step=step, required=required, help_text=help_text)
return _pin_output(single_input_return, scope, position)


@chose_impl
def get_client_val():
res = yield next_client_event()
Expand Down Expand Up @@ -250,7 +260,6 @@ def pin_update(name, **spec):
:param str name: The ``name`` of the target input widget.
:param spec: The pin widget parameters need to be updated.
Note that those parameters can not be updated: ``type``, ``name``, ``code``, ``multiple``
"""
check_name(name)
attributes = parse_input_update_spec(spec)
Expand Down
3 changes: 2 additions & 1 deletion webiojs/src/models/input/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import {CheckboxRadio} from "./checkbox_radio"
import {Textarea} from "./textarea"
import {File} from "./file"
import {Select} from "./select"
import {Slider} from "./slider"
import {InputItem} from "./base";


export const all_input_items = [Input, Actions, CheckboxRadio, Textarea, File, Select];
export const all_input_items = [Input, Actions, CheckboxRadio, Textarea, File, Select, Slider];

export function get_input_item_from_type(type: string) {
return type2item[type];
Expand Down
70 changes: 70 additions & 0 deletions webiojs/src/models/input/slider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import {InputItem} from "./base";
import {deep_copy, make_set} from "../../utils";

const slider_input_tpl = `
<div class="form-group">
{{#label}}<label for="{{id_name}}">{{label}}</label>{{/label}}
<input type="range" class="form-control-range" name="{{name}}" min="{{min_value}}" max="{{max_value}}" value="{{value}}" id="{{id_name}}">
<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>`;

export class Slider extends InputItem {
static accept_input_types: string[] = ["slider"];

files: Blob[] = []; // Files to be uploaded
valid = true;

constructor(spec: any, task_id: string, on_input_event: (event_name: string, input_item: InputItem) => void) {
super(spec, task_id, on_input_event);
}

create_element(): JQuery {
let spec = deep_copy(this.spec);
spec['id_name'] = spec.name + '-' + Math.floor(Math.random() * Math.floor(9999));

const html = Mustache.render(slider_input_tpl, spec);
this.element = $(html);
let input_elem = this.element.find('input[type="range"]');

const ignore_keys = make_set(['value', 'type', 'label', 'invalid_feedback', 'valid_feedback',
'help_text', 'min_value', 'max_value', 'id_name', 'name', 'float']);
for (let key in this.spec) {
if (key in ignore_keys) continue;
input_elem.attr(key, this.spec[key]);
}

if (spec.onblur) {
// blur事件时,发送当前值到服务器
input_elem.on("blur", (e) => {
this.on_input_event("blur", this);
});
}
if (spec.onchange) {
input_elem.on("change", (e) => {
this.on_input_event("change", this);
});
}

return this.element;
}

update_input(spec: any): any {
let attributes = spec.attributes;
this.update_input_helper(-1, attributes);
}

get_value(): any {
let val = this.element.find('input[type="range"]').val();
if (this.spec['float'])
val = parseFloat(val as string);
else
val = parseInt(val as string);
return val;
}

}



0 comments on commit aa629e3

Please sign in to comment.