mirror of
https://github.com/wassname/baukit.git
synced 2026-06-27 17:14:53 +08:00
Fix datalist and menu and choice widgets.
This commit is contained in:
+22
-18
@@ -747,13 +747,13 @@ class Choice(Widget):
|
||||
A set of radio button choices.
|
||||
"""
|
||||
|
||||
def __init__(self, choices=None, selection=None,
|
||||
def __init__(self, choices=None, value=None,
|
||||
**kwargs):
|
||||
super().__init__(**kwargs)
|
||||
if choices is None:
|
||||
choices = []
|
||||
self.choices = Property(choices)
|
||||
self.selection = Property(selection)
|
||||
self.value = Property(value)
|
||||
|
||||
def widget_js(self):
|
||||
# Note that the 'input' event would enable during-drag feedback,
|
||||
@@ -771,13 +771,13 @@ class Choice(Widget):
|
||||
element.innerHTML = lines.join();
|
||||
}
|
||||
model.on('choices horizontal', render);
|
||||
model.on('selection', (ev) => {
|
||||
model.on('value', (ev) => {
|
||||
[...element.querySelectorAll('input')].forEach((e) => {
|
||||
e.checked = (e.value == ev.value);
|
||||
})
|
||||
});
|
||||
element.addEventListener('change', (e) => {
|
||||
model.set('selection', element.choice.value);
|
||||
model.set('value', element.choice.value);
|
||||
});
|
||||
''')
|
||||
|
||||
@@ -786,9 +786,11 @@ class Choice(Widget):
|
||||
with show.enter('form', self.std_attrs(), out=out):
|
||||
for value in self.choices:
|
||||
with show.enter('label', out=out):
|
||||
show.emit('input',
|
||||
(show.attrs(checked=None) if value == self.selection else None),
|
||||
name='choice', type='radio', value=value, out=out)
|
||||
show.emit(show.PLAIN('input',
|
||||
(show.attr(checked=None) if value == self.value else None),
|
||||
name='choice', type='radio', value=value), out=out)
|
||||
with show.enter('div', out=out):
|
||||
out.append(html.escape(str(value)))
|
||||
return ''.join(out)
|
||||
|
||||
class Menu(Widget):
|
||||
@@ -796,12 +798,12 @@ class Menu(Widget):
|
||||
A dropdown choice.
|
||||
"""
|
||||
|
||||
def __init__(self, choices=None, selection=None, **kwargs):
|
||||
def __init__(self, choices=None, value=None, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
if choices is None:
|
||||
choices = []
|
||||
self.choices = Property(choices)
|
||||
self.selection = Property(selection)
|
||||
self.value = Property(value)
|
||||
|
||||
def widget_js(self):
|
||||
return minify('''
|
||||
@@ -810,21 +812,21 @@ class Menu(Widget):
|
||||
.replace(/>/g, ">").replace(/"/g, """);
|
||||
}
|
||||
function render() {
|
||||
var selection = model.get('selection');
|
||||
var value = model.get('value');
|
||||
var lines = model.get('choices').map((c) => {
|
||||
return '<option value="' + esc(''+c) + '"' +
|
||||
(c == selection ? ' selected' : '') +
|
||||
(c == value ? ' selected' : '') +
|
||||
'>' + esc(''+c) + '</option>';
|
||||
});
|
||||
element.menu.innerHTML = lines.join('\\n');
|
||||
}
|
||||
model.on('selection', (ev) => {
|
||||
model.on('value', (ev) => {
|
||||
[...element.querySelectorAll('option')].forEach((e) => {
|
||||
e.selected = (e.value == ev.value);
|
||||
})
|
||||
});
|
||||
element.addEventListener('change', (e) => {
|
||||
model.set('selection', element.menu.value);
|
||||
model.set('value', element.menu.value);
|
||||
});
|
||||
''')
|
||||
|
||||
@@ -834,7 +836,7 @@ class Menu(Widget):
|
||||
with show.enter(show.Tag('select', name='menu'), out=out):
|
||||
for value in self.choices:
|
||||
with show.enter(show.Tag('option',
|
||||
(show.attr(selected=None) if value == self.selection else None),
|
||||
(show.attr(selected=None) if value == self.value else None),
|
||||
value=value), out=out):
|
||||
out.append(html.escape(str(value)))
|
||||
return ''.join(out)
|
||||
@@ -900,11 +902,13 @@ class Datalist(Widget):
|
||||
out = []
|
||||
with show.enter('form', self.std_attrs(),
|
||||
onsubmit='return false;', out=out):
|
||||
show.emit('input', name='inp', list=self.datalist_id(),
|
||||
autocomplete='off', out=out)
|
||||
with show.enter(show.Tag('datalist'), id=self.datalist_id()):
|
||||
show.emit(show.PLAIN('input', name='inp', list=self.datalist_id(),
|
||||
value=self.value, autocomplete='off'), out=out)
|
||||
with show.enter(show.PLAIN('datalist', show.style(display='none')),
|
||||
id=self.datalist_id(), out=out):
|
||||
for value in self.choices:
|
||||
show.emit('option', value=str(value))
|
||||
show.emit('option', value=str(value), out=out)
|
||||
return ''.join(out)
|
||||
|
||||
|
||||
class Div(Widget):
|
||||
|
||||
+2
-1
@@ -237,7 +237,8 @@ TR = Tag('tr', ChildTag(TD))
|
||||
TABLE = Tag('table', ChildTag(TR))
|
||||
|
||||
# Remove defaults
|
||||
PLAIN = Tag()
|
||||
PLAIN = Tag(style(display=None, flex=None, flexFlow=None, gap=None),
|
||||
ChildTag(None))
|
||||
|
||||
# The TIGHT style allows the content to provide the size, instead of
|
||||
# expanding to fill the available space.
|
||||
|
||||
@@ -191,9 +191,9 @@
|
||||
"id": "b78f64fa",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Tight columns and Wrapped rows\n",
|
||||
"## Tight columns and wrapped rows\n",
|
||||
"\n",
|
||||
"A few useful `show.style` instances are predefined as constants. For example, `show.style(display='inline-flex')` is also called `show.TIGHT`, because it provides a tight layout of rows that are sized to fit the content instead of making the flexbox expand to fill its container. Similaly `show.WRAP` makes a row that packs the data to the left and wraps it (like the way text flows), instad of as spaced-out columns."
|
||||
"A few useful `show.style` instances are predefined as constants. For example, `show.style(display='inline-flex')` is also called `show.TIGHT`, because it provides a tight layout of rows that are sized to fit the content instead of making the flexbox expand to fill its container. Similaly `show.WRAP` makes a row that packs the data to the left and wraps it (like the way text flows), instead of as spaced-out columns."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -213,7 +213,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"show(show.TIGHT,\n",
|
||||
"show(show.TIGHT, show.style(gap=0),\n",
|
||||
" [[[show.style(font='italic 24px serif'), 'lots of data',\n",
|
||||
" show.style(background='gainsboro'),\n",
|
||||
" show.WRAP, [f'({a},{b})' for a in range(i) for b in range(j)]]\n",
|
||||
@@ -361,6 +361,80 @@
|
||||
"show([[div, show.style(flex=7), ra3]])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "21ecb0c0",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Menus, Choices, and Datalists\n",
|
||||
"\n",
|
||||
"You can make dropdown menus using `Menu`; radio button choices using `Choice`; and editable dropdowns (combobox) using `Datalist`."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "8f3032e1",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from baukit import Menu\n",
|
||||
"\n",
|
||||
"menu = Menu(choices=list(range(0,101,10)))\n",
|
||||
"ra4 = Range(step=10)\n",
|
||||
"menu.value = ra4.prop('value')\n",
|
||||
"\n",
|
||||
"show([[menu, show.style(flex=7), ra4]])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "20d1070c",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Radio button choice arrays can be arranged horizontally or vertically based on the level of nesting."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "8df5514a",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from baukit import Choice\n",
|
||||
"\n",
|
||||
"choice = Choice(choices=list(range(0,101,50)))\n",
|
||||
"ra6 = Range(step=50)\n",
|
||||
"choice.value = ra6.prop('value')\n",
|
||||
"\n",
|
||||
"show([[choice, show.style(flex=6), ra6]])\n",
|
||||
"show([[[choice], show.style(flex=6), ra6]])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "8d85174a",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"A Datalist allows free-form input while also providing a dropdown menu for choices."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "07a2ed9e",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from baukit import Datalist\n",
|
||||
"dl = Datalist(choices=list(range(0,101,20)))\n",
|
||||
"ra5 = Range(step=1)\n",
|
||||
"dl.value = ra5.prop('value')\n",
|
||||
"\n",
|
||||
"show([[dl, show.style(flex=7), ra5]])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "8b8a23a9",
|
||||
|
||||
Reference in New Issue
Block a user