Skip to content

Commit 918d817

Browse files
committed
Vscroll* and Sortable should be ok + tests
1 parent bd45cea commit 918d817

File tree

5 files changed

+95
-42
lines changed

5 files changed

+95
-42
lines changed

README.md

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ Force the navigator to download a file named 'name', with the content bytes 'con
283283

284284
## Object HSplit & VSplit
285285

286-
A Tag object to use "SplitJS" (currently only in horizontal form)
286+
A Tag object to use "SplitJS"
287287

288288
```python
289289
import htagui as ui
@@ -296,6 +296,46 @@ split.setSizes( [50,50] )
296296
split.onchange = lambda object: print( object.sizes ) # event
297297

298298

299+
## Object Sortable
300+
301+
A component to let the user reorder items using drag'n'drop.
302+
303+
```python
304+
ll=[Tag.div(f"Item {i} (drag me)",value=i) for i in range(10)]
305+
306+
def onchange(o:ui.Sortable):
307+
print( str([i.value for i in o.values]) )
308+
309+
self <= ui.Sortable(ll,onchange=onchange)
310+
```
311+
312+
## Object VScroll
313+
314+
A component to help you to create an infinite scroller.
315+
316+
```python
317+
def feed():
318+
yield [Tag.div(i) for i in range(20) ]
319+
320+
self <= Tag.div(_style="height:200px; border:1px solid red;" ) <= ui.VScroll( feed )
321+
```
322+
323+
This component should be embbeded in an element which have a constraint on its height. The given callback should yield Tag(s) (or `None` to finnish the endless scroll)
324+
325+
## Object VScrollPager
326+
327+
A component (which inherit from VScroll) to present a finnished list of items in an "on-demand" way (create items on-demand), can contain a big amount of data.
328+
329+
```python
330+
331+
ll=[lambda i=i: MyObject(i) for i in range(1,200_000_000)]
332+
self <= Tag.div(_style="height:200px; border:1px solid red;" ) <= ui.VScrollPager(ll,preload=50,moreload=10,endzone=50)
333+
334+
```
335+
This component should be embbeded in an element which have a constraint on its height. `preload` is the number of items which will be created (it should overflow on height). `moreload` is the number of items which will be loaded when scrolling is in the `endzone` pixels at the end.
336+
337+
Note that the list is a list of lambda (`List[Callable[[], Tag]]`) to create the rendering on-demand.
338+
299339
## utilities methods
300340

301341
### hflex & vflex

htagui/all.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
from .splitters import HSplit, VSplit
1717
from .ifields import IText,ITextarea,IRange,IBool,ISelect,IRadios
1818
from .fileupload import FileUpload
19-
from .containers import VScroll,VScrollPager # NEW TODO:doc
20-
from .sortables import Sortable # NEW TODO:doc
19+
from .containers import VScroll,VScrollPager
20+
from .sortables import Sortable
2121
class App(Tag.body):
2222
_ui=None
2323

@@ -31,4 +31,4 @@ def ui(self):
3131
from .flex import hflex,vflex # utilities (Htag contructor methods)
3232

3333

34-
ALL=[App,Form,Tabs,Dialog,HSplit,VSplit,IText,ITextarea,IRange,IBool,ISelect,IRadios,FileUpload]
34+
ALL=[App,Form,Tabs,Dialog,HSplit,VSplit,IText,ITextarea,IRange,IBool,ISelect,IRadios,FileUpload,Sortable,VScroll,VScrollPager]

htagui/containers.py

Lines changed: 3 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@
1111

1212
from typing import Callable, List
1313

14-
creators= List[Callable[[], Tag]]
15-
14+
TagCreators = List[Callable[[], Tag]]
1615

1716
class VScroll(Tag.div):
1817
def init(self,cbloader:Callable[[], Tag],endzone:int=50,**a):
@@ -49,7 +48,7 @@ def _loadmore(self):
4948

5049

5150
class VScrollPager(VScroll):
52-
def __init__(self,all:creators,preload:int=50,moreload:int=10,endzone:int=50,**a):
51+
def __init__(self,all:TagCreators,preload:int=50,moreload:int=10,endzone:int=50,**a):
5352
"""
5453
the CONTAINER/PARENT should have a "height" !
5554
@@ -63,7 +62,7 @@ def __init__(self,all:creators,preload:int=50,moreload:int=10,endzone:int=50,**a
6362
self.all=all
6463
self.preload=preload
6564
self.moreload=moreload
66-
VScroll.__init__(self,self._more)
65+
VScroll.__init__(self,self._more,endzone=endzone)
6766

6867

6968
def _more(self):
@@ -76,28 +75,3 @@ def _more(self):
7675
self.first=False
7776

7877

79-
class O(Tag.div):
80-
def init(self,x):
81-
self <= x
82-
self["style"]="display:inline-block;width:100px;height:100px;border:1px solid black"
83-
84-
85-
class App(Tag.div):
86-
imports=[]
87-
statics=""" html,body {height:100%;overflow:hidden} """ # NEEDED !
88-
89-
def init(self):
90-
with Tag.div(_style="display:flex;flow-flow: row nowrap;height:100%") as d:
91-
def feed():
92-
yield [O(i) for i in range(50) ]
93-
94-
# unlimited scrolling
95-
d <= VScroll( feed,_style="flex: 0 0 50%" )
96-
97-
# scrolling on demand in a defined list (of lambda())
98-
d <= Tag.div( Tag.button("hello") + VScrollPager([lambda i=i: O(i) for i in range(1000,1200)]) ,_style="height:100%")
99-
self += d
100-
101-
if __name__=="__main__":
102-
from htag import Runner
103-
Runner(App,interface=(800,600)).run()

htagui/sortables.py

Lines changed: 7 additions & 9 deletions
Large diffs are not rendered by default.

manual_tests.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,45 @@ def doit(name:str,content:bytes):
225225
self <= Tag.div("Simple:") <= ui.FileUpload( doit )
226226
self <= Tag.div("Multiple:") <= ui.FileUpload( doit, _multiple=True )
227227

228+
229+
class TestSortable(Tag.div):
230+
def init(self,root):
231+
self.output=root.output
232+
233+
ll=[Tag.div(f"Item {i} (drag me)",value=i) for i in range(10)]
234+
235+
def onchange(o:ui.Sortable):
236+
self.output( str([i.value for i in o.values]) )
237+
238+
self <= ui.Sortable(ll,onchange=onchange)
239+
240+
241+
class TestVscroll(Tag.div):
242+
def init(self,root):
243+
self.output=root.output
244+
245+
#=====================================================================
246+
def feed():
247+
yield [Tag.div(i) for i in range(20) ]
248+
249+
self <= Tag.h3("Unlimited scrolling")
250+
self <= Tag.div(_style="height:200px; border:1px solid red;" ) <= ui.VScroll( feed )
251+
#=====================================================================
252+
253+
254+
255+
#=====================================================================
256+
class O(Tag.div):
257+
def init(self,x):
258+
self <= x
259+
self["style"]="display:inline-block;width:100px;height:100px;border:1px solid black"
260+
261+
# scrolling on demand in a defined list (of lambda())
262+
self <= Tag.h3("On-demand vertical scroll")
263+
self <= Tag.div(_style="height:200px; border:1px solid red;" ) <= ui.VScrollPager([lambda i=i: O(i) for i in range(1,200)])
264+
265+
266+
228267
class App(ui.App):
229268
statics="""
230269
my {cursor:pointer;padding:4px;margin:4px;display:inline-block;text-decoration:underline}
@@ -258,6 +297,8 @@ def setter(o,testobject):
258297
menu <= Tag.my("Inputs statics",_onclick=lambda ev: setter(ev.target,TestInputs(self)) )
259298
menu <= Tag.my("I-fields dynamics",_onclick=lambda ev: setter(ev.target,TestInputs(self,True)) )
260299
menu <= Tag.my("others",_onclick=lambda ev: setter(ev.target,TestOthers(self)) )
300+
menu <= Tag.my("Sortable",_onclick=lambda ev: setter(ev.target,TestSortable(self)) )
301+
menu <= Tag.my("VScroll",_onclick=lambda ev: setter(ev.target,TestVscroll(self)) )
261302
self <= menu
262303
self <= Tag.hr()
263304
self <= self.omain

0 commit comments

Comments
 (0)