Files
pyscript/examples/py_list.py
Madhur Tandon b247864414 remove PyWidget and py-register-widget + refactor PyList as a Python Plugin (#1452)
* 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>
2023-05-10 20:17:07 +05:30

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()