mirror of
https://github.com/pyscript/pyscript.git
synced 2025-12-20 02:37:41 -05:00
* remove PyWidget and py-register-widget * refactor py-list as Plugin * add newline * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix eslint * handle case if src not supplied * move inside if * - Remove src attribute for py-list - Re-implement as a Python plugin - Remove pylist.py from examples directory - Remove PyListPlugin as one of the default ones * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * move PyItem and PyList classes to the plugin * clean up PyListTemplate and PyItemTemplate from pyscript module * fix linting * use PyList instead of PyListTemplate instead * fix example for todo-pylist * re-enable and improve test * move py-list plugin to examples * fix py-list plugin link --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
171 lines
4.4 KiB
Python
171 lines
4.4 KiB
Python
import time
|
|
from datetime import datetime as dt
|
|
from textwrap import dedent
|
|
|
|
import js
|
|
from pyscript import Element, Plugin, create
|
|
|
|
plugin = Plugin("PyList")
|
|
|
|
|
|
class PyItemTemplate(Element):
|
|
label_fields = None
|
|
|
|
def __init__(self, data, labels=None, state_key=None, parent=None):
|
|
self.data = data
|
|
|
|
self.register_parent(parent)
|
|
|
|
if not labels:
|
|
labels = list(self.data.keys())
|
|
self.labels = labels
|
|
|
|
self.state_key = state_key
|
|
|
|
super().__init__(self._id)
|
|
|
|
def register_parent(self, parent):
|
|
self._parent = parent
|
|
if parent:
|
|
self._id = f"{self._parent._id}-c-{len(self._parent._children)}"
|
|
self.data["id"] = self._id
|
|
else:
|
|
self._id = None
|
|
|
|
def create(self):
|
|
new_child = create("div", self._id, "py-li-element")
|
|
new_child._element.innerHTML = dedent(
|
|
f"""
|
|
<label id="{self._id}" for="flex items-center p-2 ">
|
|
<input class="mr-2" type="checkbox" class="task-check">
|
|
<p>{self.render_content()}</p>
|
|
</label>
|
|
"""
|
|
)
|
|
return new_child
|
|
|
|
def on_click(self, evt):
|
|
pass
|
|
|
|
def pre_append(self):
|
|
pass
|
|
|
|
def post_append(self):
|
|
self.element.click = self.on_click
|
|
self.element.onclick = self.on_click
|
|
self._post_append()
|
|
|
|
def _post_append(self):
|
|
pass
|
|
|
|
def strike(self, value, extra=None):
|
|
if value:
|
|
self.add_class("line-through")
|
|
else:
|
|
self.remove_class("line-through")
|
|
|
|
def render_content(self):
|
|
return " - ".join([self.data[f] for f in self.labels])
|
|
|
|
|
|
class PyListTemplate:
|
|
item_class = PyItemTemplate
|
|
|
|
def __init__(self, parent):
|
|
self.parent = parent
|
|
self._children = []
|
|
self._id = self.parent.id
|
|
self.main_style_classes = "py-li-element"
|
|
|
|
@property
|
|
def children(self):
|
|
return self._children
|
|
|
|
@property
|
|
def data(self):
|
|
return [c.data for c in self._children]
|
|
|
|
def render_children(self):
|
|
binds = {}
|
|
for i, c in enumerate(self._children):
|
|
txt = c.element.innerHTML
|
|
rnd = str(time.time()).replace(".", "")[-5:]
|
|
new_id = f"{c.element.id}-{i}-{rnd}"
|
|
binds[new_id] = c.element.id
|
|
txt = txt.replace(">", f" id='{new_id}'>")
|
|
print(txt)
|
|
|
|
def foo(evt):
|
|
evtEl = evt.srcElement
|
|
srcEl = Element(binds[evtEl.id])
|
|
srcEl.element.onclick()
|
|
evtEl.classList = srcEl.element.classList
|
|
|
|
for new_id in binds:
|
|
Element(new_id).element.onclick = foo
|
|
|
|
def connect(self):
|
|
self.md = main_div = js.document.createElement("div")
|
|
main_div.id = self._id + "-list-tasks-container"
|
|
|
|
if self.main_style_classes:
|
|
for klass in self.main_style_classes.split(" "):
|
|
main_div.classList.add(klass)
|
|
|
|
self.parent.appendChild(main_div)
|
|
|
|
def add(self, *args, **kws):
|
|
if not isinstance(args[0], self.item_class):
|
|
child = self.item_class(*args, **kws)
|
|
else:
|
|
child = args[0]
|
|
child.register_parent(self)
|
|
return self._add(child)
|
|
|
|
def _add(self, child_elem):
|
|
self.pre_child_append(child_elem)
|
|
child_elem.pre_append()
|
|
self._children.append(child_elem)
|
|
self.md.appendChild(child_elem.create().element)
|
|
child_elem.post_append()
|
|
self.child_appended(child_elem)
|
|
return child_elem
|
|
|
|
def pre_child_append(self, child):
|
|
pass
|
|
|
|
def child_appended(self, child):
|
|
"""Overwrite me to define logic"""
|
|
pass
|
|
|
|
|
|
class PyItem(PyItemTemplate):
|
|
def on_click(self, evt=None):
|
|
self.data["done"] = not self.data["done"]
|
|
self.strike(self.data["done"])
|
|
|
|
self.select("input").element.checked = self.data["done"]
|
|
|
|
|
|
class PyList(PyListTemplate):
|
|
item_class = PyItem
|
|
|
|
def add(self, item):
|
|
if isinstance(item, str):
|
|
item = {"content": item, "done": False, "created_at": dt.now()}
|
|
|
|
super().add(item, labels=["content"], state_key="done")
|
|
|
|
|
|
@plugin.register_custom_element("py-list")
|
|
class PyListPlugin:
|
|
def __init__(self, element):
|
|
self.element = element
|
|
self.py_list = PyList(self.element)
|
|
|
|
def add(self, item):
|
|
self.py_list.add(item)
|
|
|
|
def connect(self):
|
|
self.py_list.connect()
|