@pyscript/core 0.4.55 → 0.5.0-rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{codemirror-uEsvwGeX.js → codemirror-ZWX__zRS.js} +2 -2
- package/dist/{codemirror-uEsvwGeX.js.map → codemirror-ZWX__zRS.js.map} +1 -1
- package/dist/{codemirror_commands-BjErX5JV.js → codemirror_commands-BvofQ4B2.js} +2 -2
- package/dist/{codemirror_commands-BjErX5JV.js.map → codemirror_commands-BvofQ4B2.js.map} +1 -1
- package/dist/{codemirror_lang-python-rjOo-iGF.js → codemirror_lang-python-CAjFAwEr.js} +2 -2
- package/dist/{codemirror_lang-python-rjOo-iGF.js.map → codemirror_lang-python-CAjFAwEr.js.map} +1 -1
- package/dist/{codemirror_language-oTnz5LmX.js → codemirror_language-BzugrQDC.js} +2 -2
- package/dist/{codemirror_language-oTnz5LmX.js.map → codemirror_language-BzugrQDC.js.map} +1 -1
- package/dist/codemirror_view-DrrFKRyn.js +2 -0
- package/dist/codemirror_view-DrrFKRyn.js.map +1 -0
- package/dist/core-jHCq6GXZ.js +2 -0
- package/dist/core-jHCq6GXZ.js.map +1 -0
- package/dist/core.js +1 -1
- package/dist/{deprecations-manager-BsD6IG0e.js → deprecations-manager-JLWNpJ-L.js} +2 -2
- package/dist/{deprecations-manager-BsD6IG0e.js.map → deprecations-manager-JLWNpJ-L.js.map} +1 -1
- package/dist/{error-BwsFl_vB.js → error-BZdmXuMQ.js} +2 -2
- package/dist/{error-BwsFl_vB.js.map → error-BZdmXuMQ.js.map} +1 -1
- package/dist/{index-DvH26nkT.js → index-YJCpGJSa.js} +2 -2
- package/dist/{index-DvH26nkT.js.map → index-YJCpGJSa.js.map} +1 -1
- package/dist/{mpy-Cq6_SATz.js → mpy-CA-8GLzg.js} +2 -2
- package/dist/mpy-CA-8GLzg.js.map +1 -0
- package/dist/{py-editor-CO1XYgQ3.js → py-editor-BFwOcA7b.js} +2 -2
- package/dist/{py-editor-CO1XYgQ3.js.map → py-editor-BFwOcA7b.js.map} +1 -1
- package/dist/{py-terminal-7BWBB6VM.js → py-terminal-GLATgrHP.js} +2 -2
- package/dist/{py-terminal-7BWBB6VM.js.map → py-terminal-GLATgrHP.js.map} +1 -1
- package/dist/{py-Dpy4_-ky.js → py-tfDQPNNm.js} +2 -2
- package/dist/{py-Dpy4_-ky.js.map → py-tfDQPNNm.js.map} +1 -1
- package/dist/{zip-BxogYCy6.js → zip-CGWtiqjJ.js} +2 -2
- package/dist/zip-CGWtiqjJ.js.map +1 -0
- package/package.json +8 -8
- package/src/plugins/py-terminal/mpy.js +6 -5
- package/src/stdlib/pyscript/event_handling.py +13 -12
- package/src/stdlib/pyscript/magic_js.py +4 -12
- package/src/stdlib/pyscript/web/__init__.py +21 -4
- package/src/stdlib/pyscript/web/elements.py +919 -724
- package/src/stdlib/pyscript.js +4 -15
- package/types/core.d.ts +1 -1
- package/types/stdlib/pyscript.d.ts +0 -11
- package/dist/codemirror_view-CH_aW-qU.js +0 -2
- package/dist/codemirror_view-CH_aW-qU.js.map +0 -1
- package/dist/core-Di0g8mUD.js +0 -3
- package/dist/core-Di0g8mUD.js.map +0 -1
- package/dist/mpy-Cq6_SATz.js.map +0 -1
- package/dist/zip-BxogYCy6.js.map +0 -1
- package/dist.zip +0 -0
- package/src/stdlib/pyscript/web/dom.py +0 -21
- package/src/stdlib/pyscript/web/media.py +0 -95
- package/src/stdlib/pyweb/__init__.py +0 -2
- package/src/stdlib/pyweb/media.py +0 -95
- package/src/stdlib/pyweb/pydom.py +0 -569
- package/src/stdlib/pyweb/ui/__init__.py +0 -1
- package/src/stdlib/pyweb/ui/elements.py +0 -947
@@ -1,3 +1,4 @@
|
|
1
|
+
# noinspection PyPep8Naming
|
1
2
|
import inspect
|
2
3
|
import sys
|
3
4
|
|
@@ -18,23 +19,7 @@ except ImportError:
|
|
18
19
|
print("WARNING: ", *args, **kwargs)
|
19
20
|
|
20
21
|
|
21
|
-
|
22
|
-
from functools import cached_property
|
23
|
-
except ImportError:
|
24
|
-
# TODO: same comment about micropython as above
|
25
|
-
cached_property = property
|
26
|
-
|
27
|
-
try:
|
28
|
-
from pyodide.ffi import JsProxy
|
29
|
-
except ImportError:
|
30
|
-
# TODO: same comment about micropython as above
|
31
|
-
def JsProxy(obj):
|
32
|
-
return obj
|
33
|
-
|
34
|
-
|
35
|
-
from pyscript import document, window
|
36
|
-
|
37
|
-
# from pyscript.web import dom as pydom
|
22
|
+
from pyscript import document
|
38
23
|
|
39
24
|
#: A flag to show if MicroPython is the current Python interpreter.
|
40
25
|
is_micropython = "MicroPython" in sys.version
|
@@ -49,330 +34,331 @@ def getmembers_static(cls):
|
|
49
34
|
return inspect.getmembers_static(cls)
|
50
35
|
|
51
36
|
|
52
|
-
class
|
53
|
-
"""
|
54
|
-
|
37
|
+
class DOMProperty:
|
38
|
+
"""A descriptor representing a DOM property on an `Element` instance.
|
39
|
+
|
40
|
+
This maps a property on an `Element` instance, to the property with the specified
|
41
|
+
name on the element's underlying DOM element.
|
42
|
+
"""
|
55
43
|
|
56
44
|
def __init__(self, name: str, allow_nones: bool = False):
|
57
45
|
self.name = name
|
58
46
|
self.allow_nones = allow_nones
|
59
47
|
|
60
48
|
def __get__(self, obj, objtype=None):
|
61
|
-
return getattr(obj.
|
49
|
+
return getattr(obj._dom_element, self.name)
|
62
50
|
|
63
51
|
def __set__(self, obj, value):
|
64
52
|
if not self.allow_nones and value is None:
|
65
53
|
return
|
66
|
-
setattr(obj.
|
54
|
+
setattr(obj._dom_element, self.name, value)
|
67
55
|
|
68
56
|
|
69
|
-
|
57
|
+
class Element:
|
58
|
+
tag = "div"
|
70
59
|
|
60
|
+
# These are attribute that all elements have (this list is a subset of the official
|
61
|
+
# one - we are just trying to capture the most used ones).
|
62
|
+
accesskey = DOMProperty("accesskey")
|
63
|
+
autofocus = DOMProperty("autofocus")
|
64
|
+
autocapitalize = DOMProperty("autocapitalize")
|
65
|
+
className = DOMProperty("className")
|
66
|
+
contenteditable = DOMProperty("contenteditable")
|
67
|
+
draggable = DOMProperty("draggable")
|
68
|
+
enterkeyhint = DOMProperty("enterkeyhint")
|
69
|
+
hidden = DOMProperty("hidden")
|
70
|
+
innerHTML = DOMProperty("innerHTML")
|
71
|
+
id = DOMProperty("id")
|
72
|
+
lang = DOMProperty("lang")
|
73
|
+
nonce = DOMProperty("nonce")
|
74
|
+
part = DOMProperty("part")
|
75
|
+
popover = DOMProperty("popover")
|
76
|
+
slot = DOMProperty("slot")
|
77
|
+
spellcheck = DOMProperty("spellcheck")
|
78
|
+
tabindex = DOMProperty("tabindex")
|
79
|
+
tagName = DOMProperty("tagName")
|
80
|
+
textContent = DOMProperty("textContent")
|
81
|
+
title = DOMProperty("title")
|
82
|
+
translate = DOMProperty("translate")
|
83
|
+
virtualkeyboardpolicy = DOMProperty("virtualkeyboardpolicy")
|
84
|
+
|
85
|
+
@classmethod
|
86
|
+
def from_dom_element(cls, dom_element):
|
87
|
+
"""Create an instance of the appropriate subclass of `Element` for a DOM
|
88
|
+
element.
|
89
|
+
|
90
|
+
If the DOM element was created via an `Element` (i.e. by us) it will have a data
|
91
|
+
attribute named `data-pyscript-type` that contains the name of the subclass
|
92
|
+
that created it. Hence, if the `data-pyscript-type` attribute *is* present we
|
93
|
+
look up the subclass by name and create an instance of that. Otherwise, we make
|
94
|
+
a 'best-guess' and look up the `Element` subclass by the DOM element's tag name
|
95
|
+
(this is NOT fool-proof as many subclasses might use a `<div>`, but close enough
|
96
|
+
for jazz).
|
97
|
+
"""
|
71
98
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
99
|
+
# We use "getAttribute" here instead of `js_element.dataset.pyscriptType` as the
|
100
|
+
# latter throws an `AttributeError` if the value isn't set. This way we just get
|
101
|
+
# `None` which seems cleaner.
|
102
|
+
cls_name = dom_element.getAttribute("data-pyscript-type")
|
103
|
+
if cls_name:
|
104
|
+
element_cls = ELEMENT_CLASSES_BY_NAME.get(cls_name.lower())
|
78
105
|
|
79
|
-
|
80
|
-
|
81
|
-
the underlying JS element"""
|
82
|
-
return isinstance(obj, BaseElement) and obj._js == self._js
|
106
|
+
else:
|
107
|
+
element_cls = ELEMENT_CLASSES_BY_TAG.get(dom_element.tagName.lower())
|
83
108
|
|
84
|
-
|
85
|
-
|
86
|
-
if
|
87
|
-
|
109
|
+
# For any unknown elements (custom tags etc.) create an instance of this
|
110
|
+
# class ('Element').
|
111
|
+
if not element_cls:
|
112
|
+
element_cls = cls
|
88
113
|
|
89
|
-
|
90
|
-
# TODO: This should actually return the correct class (== to tagName)
|
91
|
-
self._parent = Element(self._js.parentElement)
|
114
|
+
return element_cls(dom_element=dom_element)
|
92
115
|
|
93
|
-
|
116
|
+
def __init__(self, dom_element=None, classes=None, style=None, **kwargs):
|
117
|
+
"""Create a new, or wrap an existing DOM element.
|
94
118
|
|
95
|
-
|
96
|
-
|
97
|
-
|
119
|
+
If `dom_element` is None we are being called to *create* a new element.
|
120
|
+
Otherwise, we are being called to *wrap* an existing DOM element.
|
121
|
+
"""
|
122
|
+
self._dom_element = dom_element or document.createElement(self.tag)
|
98
123
|
|
99
|
-
|
100
|
-
|
101
|
-
|
124
|
+
# Tag the DOM element with our class name.
|
125
|
+
#
|
126
|
+
# Using the `dataset` attribute is how you programmatically add `data-xxx`
|
127
|
+
# attributes to a DOM element. In this case it will set an attribute that
|
128
|
+
# appears in the DOM as `data-pyscript-type`.
|
129
|
+
self._dom_element.dataset.pyscriptType = type(self).__name__
|
102
130
|
|
103
|
-
|
104
|
-
|
105
|
-
|
131
|
+
self._parent = None
|
132
|
+
self._classes = Classes(self)
|
133
|
+
self._style = Style(self)
|
106
134
|
|
107
|
-
|
108
|
-
|
135
|
+
# Set any specified classes, styles, and DOM properties.
|
136
|
+
self.update(classes=classes, style=style, **kwargs)
|
109
137
|
|
110
|
-
|
111
|
-
|
138
|
+
def update(self, classes=None, style=None, **kwargs):
|
139
|
+
"""Update the element with the specified classes, styles, and DOM properties."""
|
112
140
|
|
113
|
-
if
|
114
|
-
self.
|
141
|
+
if classes:
|
142
|
+
self.classes.add(classes)
|
115
143
|
|
116
|
-
|
144
|
+
if isinstance(style, dict):
|
145
|
+
self.style.set(**style)
|
117
146
|
|
118
|
-
|
119
|
-
|
120
|
-
|
147
|
+
elif style is not None:
|
148
|
+
raise ValueError(
|
149
|
+
f"Style should be a dictionary, received {style} "
|
150
|
+
f"(type {type(style)}) instead."
|
151
|
+
)
|
121
152
|
|
122
|
-
|
123
|
-
selector (str): A string containing a selector expression
|
153
|
+
self._set_dom_properties(**kwargs)
|
124
154
|
|
125
|
-
|
126
|
-
|
155
|
+
def _set_dom_properties(self, **kwargs):
|
156
|
+
"""Set the specified DOM properties.
|
157
|
+
|
158
|
+
Args:
|
159
|
+
**kwargs: The properties to set
|
127
160
|
"""
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
161
|
+
# Harvest all DOM properties from the instance's class.
|
162
|
+
dom_properties = {
|
163
|
+
attribute_name: attribute_value
|
164
|
+
for attribute_name, attribute_value in getmembers_static(self.__class__)
|
165
|
+
if isinstance(attribute_value, DOMProperty)
|
166
|
+
}
|
167
|
+
|
168
|
+
for name, value in kwargs.items():
|
169
|
+
if name not in dom_properties:
|
170
|
+
raise ValueError(f"'{name}' is not a DOM property.")
|
171
|
+
|
172
|
+
try:
|
173
|
+
setattr(self, name, value)
|
174
|
+
except Exception as e:
|
175
|
+
print(f"Error setting {name} to {value}: {e}")
|
176
|
+
raise
|
132
177
|
|
178
|
+
def __eq__(self, obj):
|
179
|
+
"""Check for equality by comparing the underlying DOM element."""
|
180
|
+
return isinstance(obj, Element) and obj._dom_element == self._dom_element
|
133
181
|
|
134
|
-
class Element(BaseElement):
|
135
182
|
@property
|
136
183
|
def children(self):
|
137
|
-
return
|
184
|
+
return ElementCollection(
|
185
|
+
[Element.from_dom_element(el) for el in self._dom_element.children]
|
186
|
+
)
|
138
187
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
# higher level Python element
|
143
|
-
if inspect.isclass(JsProxy) and isinstance(child, JsProxy):
|
144
|
-
return self.append(Element(child))
|
145
|
-
|
146
|
-
elif isinstance(child, Element):
|
147
|
-
self._js.appendChild(child._js)
|
148
|
-
|
149
|
-
return child
|
150
|
-
|
151
|
-
elif isinstance(child, ElementCollection):
|
152
|
-
for el in child:
|
153
|
-
self.append(el)
|
188
|
+
@property
|
189
|
+
def classes(self):
|
190
|
+
return self._classes
|
154
191
|
|
155
|
-
# -------- Pythonic Interface to Element -------- #
|
156
192
|
@property
|
157
|
-
def
|
158
|
-
|
193
|
+
def parent(self):
|
194
|
+
if self._parent:
|
195
|
+
return self._parent
|
196
|
+
|
197
|
+
if self._dom_element.parentElement:
|
198
|
+
self._parent = Element.from_dom_element(self._dom_element.parentElement)
|
159
199
|
|
160
|
-
|
161
|
-
def html(self, value):
|
162
|
-
self._js.innerHTML = value
|
200
|
+
return self._parent
|
163
201
|
|
164
202
|
@property
|
165
|
-
def
|
166
|
-
return self.
|
203
|
+
def style(self):
|
204
|
+
return self._style
|
167
205
|
|
168
|
-
|
169
|
-
|
170
|
-
|
206
|
+
def append(self, child):
|
207
|
+
if isinstance(child, Element):
|
208
|
+
self._dom_element.appendChild(child._dom_element)
|
171
209
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
# handle this specifica use case. Just not support for now?
|
176
|
-
if self._js.tagName == "TEMPLATE":
|
177
|
-
warnings.warn(
|
178
|
-
"Content attribute not supported for template elements.", stacklevel=2
|
179
|
-
)
|
180
|
-
return None
|
181
|
-
return self._js.innerHTML
|
182
|
-
|
183
|
-
@content.setter
|
184
|
-
def content(self, value):
|
185
|
-
# TODO: (same comment as above)
|
186
|
-
if self._js.tagName == "TEMPLATE":
|
187
|
-
warnings.warn(
|
188
|
-
"Content attribute not supported for template elements.", stacklevel=2
|
189
|
-
)
|
190
|
-
return
|
210
|
+
elif isinstance(child, ElementCollection):
|
211
|
+
for el in child:
|
212
|
+
self._dom_element.appendChild(el._dom_element)
|
191
213
|
|
192
|
-
|
214
|
+
else:
|
215
|
+
# In this case we know it's not an Element or an ElementCollection, so we
|
216
|
+
# guess that it's either a DOM element or NodeList returned via the ffi.
|
217
|
+
try:
|
218
|
+
# First, we try to see if it's an element by accessing the 'tagName'
|
219
|
+
# attribute.
|
220
|
+
child.tagName
|
221
|
+
self._dom_element.appendChild(child)
|
222
|
+
|
223
|
+
except AttributeError:
|
224
|
+
try:
|
225
|
+
# Ok, it's not an element, so let's see if it's a NodeList by
|
226
|
+
# accessing the 'length' attribute.
|
227
|
+
child.length
|
228
|
+
for element_ in child:
|
229
|
+
self._dom_element.appendChild(element_)
|
230
|
+
|
231
|
+
except AttributeError:
|
232
|
+
# Nope! This is not an element or a NodeList.
|
233
|
+
raise TypeError(
|
234
|
+
f'Element "{child}" is a proxy object, "'
|
235
|
+
f"but not a valid element or a NodeList."
|
236
|
+
)
|
237
|
+
|
238
|
+
def clone(self, clone_id=None):
|
239
|
+
"""Make a clone of the element (clones the underlying DOM object too)."""
|
240
|
+
clone = Element.from_dom_element(self._dom_element.cloneNode(True))
|
241
|
+
clone.id = clone_id
|
242
|
+
return clone
|
193
243
|
|
194
|
-
|
195
|
-
|
196
|
-
|
244
|
+
def find(self, selector):
|
245
|
+
"""Return an ElementCollection representing all the child elements that
|
246
|
+
match the specified selector.
|
197
247
|
|
198
|
-
|
199
|
-
|
200
|
-
self._js.id = value
|
248
|
+
Args:
|
249
|
+
selector (str): A string containing a selector expression
|
201
250
|
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
251
|
+
Returns:
|
252
|
+
ElementCollection: A collection of elements matching the selector
|
253
|
+
"""
|
254
|
+
return ElementCollection(
|
255
|
+
[
|
256
|
+
Element.from_dom_element(dom_element)
|
257
|
+
for dom_element in self._dom_element.querySelectorAll(selector)
|
258
|
+
]
|
259
|
+
)
|
206
260
|
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
)
|
211
|
-
self._proxies["options"] = OptionsProxy(self)
|
212
|
-
return self._proxies["options"]
|
261
|
+
def show_me(self):
|
262
|
+
"""Scroll the element into view."""
|
263
|
+
self._dom_element.scrollIntoView()
|
213
264
|
|
214
|
-
@property
|
215
|
-
def value(self):
|
216
|
-
return self._js.value
|
217
|
-
|
218
|
-
@value.setter
|
219
|
-
def value(self, value):
|
220
|
-
# in order to avoid confusion to the user, we don't allow setting the
|
221
|
-
# value of elements that don't have a value attribute
|
222
|
-
if not hasattr(self._js, "value"):
|
223
|
-
raise AttributeError(
|
224
|
-
f"Element {self._js.tagName} has no value attribute. If you want to "
|
225
|
-
"force a value attribute, set it directly using the `_js.value = <value>` "
|
226
|
-
"javascript API attribute instead."
|
227
|
-
)
|
228
|
-
self._js.value = value
|
229
265
|
|
230
|
-
|
231
|
-
|
232
|
-
return self._js.selected
|
233
|
-
|
234
|
-
@selected.setter
|
235
|
-
def selected(self, value):
|
236
|
-
# in order to avoid confusion to the user, we don't allow setting the
|
237
|
-
# value of elements that don't have a value attribute
|
238
|
-
if not hasattr(self._js, "selected"):
|
239
|
-
raise AttributeError(
|
240
|
-
f"Element {self._js.tagName} has no value attribute. If you want to "
|
241
|
-
"force a value attribute, set it directly using the `_js.value = <value>` "
|
242
|
-
"javascript API attribute instead."
|
243
|
-
)
|
244
|
-
self._js.selected = value
|
266
|
+
class Classes:
|
267
|
+
"""A set-like interface to an element's `classList`."""
|
245
268
|
|
246
|
-
def
|
247
|
-
|
248
|
-
|
269
|
+
def __init__(self, element: Element):
|
270
|
+
self._element = element
|
271
|
+
self._class_list = self._element._dom_element.classList
|
249
272
|
|
250
|
-
|
273
|
+
def __contains__(self, item):
|
274
|
+
return item in self._class_list
|
251
275
|
|
252
|
-
def
|
253
|
-
|
254
|
-
if isinstance(
|
255
|
-
|
256
|
-
else:
|
257
|
-
classList.remove(classname)
|
258
|
-
return self
|
276
|
+
def __eq__(self, other):
|
277
|
+
# We allow comparison with either another `Classes` instance...
|
278
|
+
if isinstance(other, Classes):
|
279
|
+
compare_with = list(other._class_list)
|
259
280
|
|
260
|
-
|
261
|
-
classList = self._js.classList
|
262
|
-
if isinstance(classname, list):
|
263
|
-
classList.add(*classname)
|
281
|
+
# ...or iterables of strings.
|
264
282
|
else:
|
265
|
-
|
266
|
-
|
283
|
+
# TODO: Check MP for existence of better iterable test.
|
284
|
+
try:
|
285
|
+
compare_with = iter(other)
|
267
286
|
|
268
|
-
|
269
|
-
|
270
|
-
classes = self._js.classList.values()
|
271
|
-
return [x for x in classes]
|
287
|
+
except TypeError:
|
288
|
+
return False
|
272
289
|
|
273
|
-
|
274
|
-
self._js.scrollIntoView()
|
290
|
+
return set(self._class_list) == set(compare_with)
|
275
291
|
|
276
|
-
def
|
277
|
-
self
|
278
|
-
to: BaseElement | str = None,
|
279
|
-
width: int | None = None,
|
280
|
-
height: int | None = None,
|
281
|
-
):
|
282
|
-
"""
|
283
|
-
Captures a snapshot of a video element. (Only available for video elements)
|
292
|
+
def __iter__(self):
|
293
|
+
return iter(self._class_list)
|
284
294
|
|
285
|
-
|
295
|
+
def __len__(self):
|
296
|
+
return self._class_list.length
|
286
297
|
|
287
|
-
|
288
|
-
|
289
|
-
* height: height of the image
|
298
|
+
def __repr__(self):
|
299
|
+
return f"Classes({', '.join(self._class_list)})"
|
290
300
|
|
291
|
-
|
292
|
-
|
293
|
-
"""
|
294
|
-
if self._js.tagName != "VIDEO":
|
295
|
-
raise AttributeError("Snap method is only available for video Elements")
|
301
|
+
def __str__(self):
|
302
|
+
return " ".join(self._class_list)
|
296
303
|
|
297
|
-
|
298
|
-
|
299
|
-
if
|
300
|
-
|
301
|
-
|
302
|
-
height = self._js.height
|
303
|
-
canvas._js.width = width
|
304
|
-
canvas._js.height = height
|
304
|
+
def add(self, *class_names):
|
305
|
+
for class_name in class_names:
|
306
|
+
if isinstance(class_name, list):
|
307
|
+
for item in class_name:
|
308
|
+
self.add(item)
|
305
309
|
|
306
|
-
|
307
|
-
|
308
|
-
raise TypeError("Element to snap to must a canvas.")
|
309
|
-
canvas = to
|
310
|
-
elif getattr(to, "tagName", "") == "CANVAS":
|
311
|
-
canvas = Element(to)
|
312
|
-
elif isinstance(to, str):
|
313
|
-
# TODO (fpliger): This needs a better fix but doing a local import here for a quick fix
|
314
|
-
from pyscript.web import dom
|
310
|
+
else:
|
311
|
+
self._class_list.add(class_name)
|
315
312
|
|
316
|
-
|
317
|
-
|
318
|
-
raise TypeError("Element to snap to must a be canvas.")
|
313
|
+
def contains(self, class_name):
|
314
|
+
return class_name in self
|
319
315
|
|
320
|
-
|
316
|
+
def remove(self, *class_names):
|
317
|
+
for class_name in class_names:
|
318
|
+
if isinstance(class_name, list):
|
319
|
+
for item in class_name:
|
320
|
+
self.remove(item)
|
321
321
|
|
322
|
-
|
322
|
+
else:
|
323
|
+
self._class_list.remove(class_name)
|
323
324
|
|
324
|
-
def
|
325
|
-
|
326
|
-
|
325
|
+
def replace(self, old_class, new_class):
|
326
|
+
self.remove(old_class)
|
327
|
+
self.add(new_class)
|
327
328
|
|
328
|
-
|
329
|
-
|
329
|
+
def toggle(self, *class_names):
|
330
|
+
for class_name in class_names:
|
331
|
+
if class_name in self:
|
332
|
+
self.remove(class_name)
|
330
333
|
|
331
|
-
|
332
|
-
|
333
|
-
"""
|
334
|
-
if self._js.tagName != "CANVAS":
|
335
|
-
raise AttributeError(
|
336
|
-
"The download method is only available for canvas Elements"
|
337
|
-
)
|
334
|
+
else:
|
335
|
+
self.add(class_name)
|
338
336
|
|
339
|
-
link = self.create("a")
|
340
|
-
link._js.download = filename
|
341
|
-
link._js.href = self._js.toDataURL()
|
342
|
-
link._js.click()
|
343
337
|
|
344
|
-
|
345
|
-
|
338
|
+
class HasOptions:
|
339
|
+
"""Mix-in for elements that have an options attribute.
|
346
340
|
|
347
|
-
|
341
|
+
The elements that support options are: <datalist>, <optgroup>, and <select>.
|
342
|
+
"""
|
348
343
|
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
if self._js.tagName != "CANVAS":
|
354
|
-
raise AttributeError(
|
355
|
-
"The draw method is only available for canvas Elements"
|
356
|
-
)
|
344
|
+
@property
|
345
|
+
def options(self):
|
346
|
+
if not hasattr(self, "_options"):
|
347
|
+
self._options = Options(self)
|
357
348
|
|
358
|
-
|
359
|
-
what = what._js
|
349
|
+
return self._options
|
360
350
|
|
361
|
-
# https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage
|
362
|
-
self._js.getContext("2d").drawImage(what, 0, 0, width, height)
|
363
351
|
|
352
|
+
class Options:
|
353
|
+
"""This class represents the <option>s of a <datalist>, <optgroup> or <select>
|
354
|
+
element.
|
364
355
|
|
365
|
-
|
366
|
-
|
367
|
-
allows to access to add and remove options by using the `add` and `remove` methods.
|
356
|
+
It allows to access to add and remove <option>s by using the `add` and `remove`
|
357
|
+
methods.
|
368
358
|
"""
|
369
359
|
|
370
360
|
def __init__(self, element: Element) -> None:
|
371
361
|
self._element = element
|
372
|
-
if self._element._js.tagName.lower() != "select":
|
373
|
-
raise AttributeError(
|
374
|
-
f"Element {self._element._js.tagName} has no options attribute."
|
375
|
-
)
|
376
362
|
|
377
363
|
def add(
|
378
364
|
self,
|
@@ -383,7 +369,7 @@ class OptionsProxy:
|
|
383
369
|
**kws,
|
384
370
|
) -> None:
|
385
371
|
"""Add a new option to the select element"""
|
386
|
-
|
372
|
+
|
387
373
|
option = document.createElement("option")
|
388
374
|
if value is not None:
|
389
375
|
kws["value"] = value
|
@@ -397,13 +383,13 @@ class OptionsProxy:
|
|
397
383
|
|
398
384
|
if before:
|
399
385
|
if isinstance(before, Element):
|
400
|
-
before = before.
|
386
|
+
before = before._dom_element
|
401
387
|
|
402
|
-
self._element.
|
388
|
+
self._element._dom_element.add(option, before)
|
403
389
|
|
404
390
|
def remove(self, item: int) -> None:
|
405
391
|
"""Remove the option at the specified index"""
|
406
|
-
self._element.
|
392
|
+
self._element._dom_element.remove(item)
|
407
393
|
|
408
394
|
def clear(self) -> None:
|
409
395
|
"""Remove all the options"""
|
@@ -413,12 +399,14 @@ class OptionsProxy:
|
|
413
399
|
@property
|
414
400
|
def options(self):
|
415
401
|
"""Return the list of options"""
|
416
|
-
return [
|
402
|
+
return [
|
403
|
+
Element.from_dom_element(opt) for opt in self._element._dom_element.options
|
404
|
+
]
|
417
405
|
|
418
406
|
@property
|
419
407
|
def selected(self):
|
420
408
|
"""Return the selected option"""
|
421
|
-
return self.options[self._element.
|
409
|
+
return self.options[self._element._dom_element.selectedIndex]
|
422
410
|
|
423
411
|
def __iter__(self):
|
424
412
|
yield from self.options
|
@@ -433,13 +421,12 @@ class OptionsProxy:
|
|
433
421
|
return self.options[key]
|
434
422
|
|
435
423
|
|
436
|
-
class
|
424
|
+
class Style:
|
425
|
+
"""A dict-like interface to an element's css style."""
|
426
|
+
|
437
427
|
def __init__(self, element: Element) -> None:
|
438
428
|
self._element = element
|
439
|
-
|
440
|
-
@cached_property
|
441
|
-
def _style(self):
|
442
|
-
return self._element._js.style
|
429
|
+
self._style = self._element._dom_element.style
|
443
430
|
|
444
431
|
def __getitem__(self, key):
|
445
432
|
return self._style.getPropertyValue(key)
|
@@ -450,944 +437,1039 @@ class StyleProxy: # (dict):
|
|
450
437
|
def remove(self, key):
|
451
438
|
self._style.removeProperty(key)
|
452
439
|
|
453
|
-
def set(self, **
|
454
|
-
for
|
455
|
-
self._element.
|
440
|
+
def set(self, **kwargs):
|
441
|
+
for key, value in kwargs.items():
|
442
|
+
self._element._dom_element.style.setProperty(key, value)
|
456
443
|
|
457
444
|
# CSS Properties
|
458
445
|
# Reference: https://github.com/microsoft/TypeScript/blob/main/src/lib/dom.generated.d.ts#L3799C1-L5005C2
|
459
|
-
# Following
|
446
|
+
# Following properties automatically generated from the above reference using
|
460
447
|
# tools/codegen_css_proxy.py
|
461
448
|
@property
|
462
449
|
def visible(self):
|
463
|
-
return self._element.
|
450
|
+
return self._element._dom_element.style.visibility
|
464
451
|
|
465
452
|
@visible.setter
|
466
453
|
def visible(self, value):
|
467
|
-
self._element.
|
454
|
+
self._element._dom_element.style.visibility = value
|
468
455
|
|
469
456
|
|
470
|
-
|
457
|
+
class ContainerElement(Element):
|
458
|
+
"""Base class for elements that can contain other elements."""
|
471
459
|
|
460
|
+
def __init__(
|
461
|
+
self, *args, children=None, dom_element=None, style=None, classes=None, **kwargs
|
462
|
+
):
|
463
|
+
super().__init__(
|
464
|
+
dom_element=dom_element, style=style, classes=classes, **kwargs
|
465
|
+
)
|
472
466
|
|
473
|
-
|
474
|
-
|
467
|
+
for child in list(args) + (children or []):
|
468
|
+
if isinstance(child, Element) or isinstance(child, ElementCollection):
|
469
|
+
self.append(child)
|
475
470
|
|
476
|
-
|
477
|
-
|
478
|
-
# We are trying to capture the most used ones
|
479
|
-
accesskey = JSProperty("accesskey")
|
480
|
-
autofocus = JSProperty("autofocus")
|
481
|
-
autocapitalize = JSProperty("autocapitalize")
|
482
|
-
className = JSProperty("className")
|
483
|
-
contenteditable = JSProperty("contenteditable")
|
484
|
-
draggable = JSProperty("draggable")
|
485
|
-
enterkeyhint = JSProperty("enterkeyhint")
|
486
|
-
hidden = JSProperty("hidden")
|
487
|
-
id = JSProperty("id")
|
488
|
-
lang = JSProperty("lang")
|
489
|
-
nonce = JSProperty("nonce")
|
490
|
-
part = JSProperty("part")
|
491
|
-
popover = JSProperty("popover")
|
492
|
-
slot = JSProperty("slot")
|
493
|
-
spellcheck = JSProperty("spellcheck")
|
494
|
-
tabindex = JSProperty("tabindex")
|
495
|
-
title = JSProperty("title")
|
496
|
-
translate = JSProperty("translate")
|
497
|
-
virtualkeyboardpolicy = JSProperty("virtualkeyboardpolicy")
|
498
|
-
|
499
|
-
def __init__(self, style=None, **kwargs):
|
500
|
-
super().__init__(document.createElement(self.tag))
|
501
|
-
|
502
|
-
# set all the style properties provided in input
|
503
|
-
if isinstance(style, dict):
|
504
|
-
for key, value in style.items():
|
505
|
-
self.style[key] = value
|
506
|
-
elif style is None:
|
507
|
-
pass
|
508
|
-
else:
|
509
|
-
raise ValueError(
|
510
|
-
f"Style should be a dictionary, received {style} (type {type(style)}) instead."
|
511
|
-
)
|
512
|
-
|
513
|
-
# IMPORTANT!!! This is used to auto-harvest all input arguments and set them as properties
|
514
|
-
self._init_properties(**kwargs)
|
471
|
+
else:
|
472
|
+
self.innerHTML += child
|
515
473
|
|
516
|
-
def _init_properties(self, **kwargs):
|
517
|
-
"""Set all the properties (of type JSProperties) provided in input as properties
|
518
|
-
of the class instance.
|
519
474
|
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
for attr_name, attr in getmembers_static(self.__class__):
|
525
|
-
# For each one, actually check if it is a property of the class and set it
|
526
|
-
if isinstance(attr, JSProperty) and attr_name in kwargs:
|
527
|
-
try:
|
528
|
-
setattr(self, attr_name, kwargs[attr_name])
|
529
|
-
except Exception as e:
|
530
|
-
print(f"Error setting {attr_name} to {kwargs[attr_name]}: {e}")
|
531
|
-
raise
|
532
|
-
|
533
|
-
|
534
|
-
class TextElementBase(ElementBase):
|
535
|
-
def __init__(self, content=None, style=None, **kwargs):
|
536
|
-
super().__init__(style=style, **kwargs)
|
537
|
-
|
538
|
-
# If it's an element, append the element
|
539
|
-
if isinstance(content, Element):
|
540
|
-
self.append(content)
|
541
|
-
# If it's a list of elements
|
542
|
-
elif isinstance(content, list):
|
543
|
-
for item in content:
|
544
|
-
self.append(item)
|
545
|
-
# If the content wasn't set just ignore
|
546
|
-
elif content is None:
|
547
|
-
pass
|
548
|
-
else:
|
549
|
-
# Otherwise, set content as the html of the element
|
550
|
-
self.html = content
|
551
|
-
|
552
|
-
|
553
|
-
# IMPORTANT: For all HTML components defined below, we are not mapping all
|
554
|
-
# available attributes, just the global and the most common ones.
|
555
|
-
# If you need to access a specific attribute, you can always use the `_js.<attribute>`
|
556
|
-
class a(TextElementBase):
|
475
|
+
# IMPORTANT: For all HTML components defined below, we are not mapping all possible
|
476
|
+
# attributes, just the global and the most common ones. If you need to access a
|
477
|
+
# specific attribute, you can always use the `_dom_element.<attribute>`
|
478
|
+
class a(ContainerElement):
|
557
479
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a"""
|
558
480
|
|
559
481
|
tag = "a"
|
560
482
|
|
561
|
-
download =
|
562
|
-
href =
|
563
|
-
referrerpolicy =
|
564
|
-
rel =
|
565
|
-
target =
|
566
|
-
type =
|
483
|
+
download = DOMProperty("download")
|
484
|
+
href = DOMProperty("href")
|
485
|
+
referrerpolicy = DOMProperty("referrerpolicy")
|
486
|
+
rel = DOMProperty("rel")
|
487
|
+
target = DOMProperty("target")
|
488
|
+
type = DOMProperty("type")
|
567
489
|
|
568
490
|
|
569
|
-
class abbr(
|
491
|
+
class abbr(ContainerElement):
|
570
492
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/abbr"""
|
571
493
|
|
572
494
|
tag = "abbr"
|
573
495
|
|
574
496
|
|
575
|
-
class address(
|
497
|
+
class address(ContainerElement):
|
576
498
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/address"""
|
577
499
|
|
578
500
|
tag = "address"
|
579
501
|
|
580
502
|
|
581
|
-
class area(
|
503
|
+
class area(Element):
|
582
504
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/area"""
|
583
505
|
|
584
506
|
tag = "area"
|
585
507
|
|
586
|
-
alt =
|
587
|
-
coords =
|
588
|
-
download =
|
589
|
-
href =
|
590
|
-
ping =
|
591
|
-
referrerpolicy =
|
592
|
-
rel =
|
593
|
-
shape =
|
594
|
-
target =
|
508
|
+
alt = DOMProperty("alt")
|
509
|
+
coords = DOMProperty("coords")
|
510
|
+
download = DOMProperty("download")
|
511
|
+
href = DOMProperty("href")
|
512
|
+
ping = DOMProperty("ping")
|
513
|
+
referrerpolicy = DOMProperty("referrerpolicy")
|
514
|
+
rel = DOMProperty("rel")
|
515
|
+
shape = DOMProperty("shape")
|
516
|
+
target = DOMProperty("target")
|
595
517
|
|
596
518
|
|
597
|
-
class article(
|
519
|
+
class article(ContainerElement):
|
598
520
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/article"""
|
599
521
|
|
600
522
|
tag = "article"
|
601
523
|
|
602
524
|
|
603
|
-
class aside(
|
525
|
+
class aside(ContainerElement):
|
604
526
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/aside"""
|
605
527
|
|
606
528
|
tag = "aside"
|
607
529
|
|
608
530
|
|
609
|
-
class audio(
|
531
|
+
class audio(ContainerElement):
|
610
532
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/audio"""
|
611
533
|
|
612
534
|
tag = "audio"
|
613
535
|
|
614
|
-
autoplay =
|
615
|
-
controls =
|
616
|
-
controlslist =
|
617
|
-
crossorigin =
|
618
|
-
disableremoteplayback =
|
619
|
-
loop =
|
620
|
-
muted =
|
621
|
-
preload =
|
622
|
-
src =
|
536
|
+
autoplay = DOMProperty("autoplay")
|
537
|
+
controls = DOMProperty("controls")
|
538
|
+
controlslist = DOMProperty("controlslist")
|
539
|
+
crossorigin = DOMProperty("crossorigin")
|
540
|
+
disableremoteplayback = DOMProperty("disableremoteplayback")
|
541
|
+
loop = DOMProperty("loop")
|
542
|
+
muted = DOMProperty("muted")
|
543
|
+
preload = DOMProperty("preload")
|
544
|
+
src = DOMProperty("src")
|
623
545
|
|
624
546
|
|
625
|
-
class b(
|
547
|
+
class b(ContainerElement):
|
626
548
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/b"""
|
627
549
|
|
628
550
|
tag = "b"
|
629
551
|
|
630
552
|
|
631
|
-
class
|
553
|
+
class base(Element):
|
554
|
+
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base"""
|
555
|
+
|
556
|
+
tag = "base"
|
557
|
+
|
558
|
+
href = DOMProperty("href")
|
559
|
+
target = DOMProperty("target")
|
560
|
+
|
561
|
+
|
562
|
+
class blockquote(ContainerElement):
|
632
563
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/blockquote"""
|
633
564
|
|
634
565
|
tag = "blockquote"
|
635
566
|
|
636
|
-
cite =
|
567
|
+
cite = DOMProperty("cite")
|
568
|
+
|
569
|
+
|
570
|
+
class body(ContainerElement):
|
571
|
+
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/body"""
|
637
572
|
|
573
|
+
tag = "body"
|
638
574
|
|
639
|
-
|
575
|
+
|
576
|
+
class br(Element):
|
640
577
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/br"""
|
641
578
|
|
642
579
|
tag = "br"
|
643
580
|
|
644
581
|
|
645
|
-
class button(
|
582
|
+
class button(ContainerElement):
|
646
583
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button"""
|
647
584
|
|
648
585
|
tag = "button"
|
649
586
|
|
650
|
-
autofocus =
|
651
|
-
disabled =
|
652
|
-
form =
|
653
|
-
formaction =
|
654
|
-
formenctype =
|
655
|
-
formmethod =
|
656
|
-
formnovalidate =
|
657
|
-
formtarget =
|
658
|
-
name =
|
659
|
-
type =
|
660
|
-
value =
|
587
|
+
autofocus = DOMProperty("autofocus")
|
588
|
+
disabled = DOMProperty("disabled")
|
589
|
+
form = DOMProperty("form")
|
590
|
+
formaction = DOMProperty("formaction")
|
591
|
+
formenctype = DOMProperty("formenctype")
|
592
|
+
formmethod = DOMProperty("formmethod")
|
593
|
+
formnovalidate = DOMProperty("formnovalidate")
|
594
|
+
formtarget = DOMProperty("formtarget")
|
595
|
+
name = DOMProperty("name")
|
596
|
+
type = DOMProperty("type")
|
597
|
+
value = DOMProperty("value")
|
661
598
|
|
662
599
|
|
663
|
-
class canvas(
|
600
|
+
class canvas(ContainerElement):
|
664
601
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas"""
|
665
602
|
|
666
603
|
tag = "canvas"
|
667
604
|
|
668
|
-
height =
|
669
|
-
width =
|
605
|
+
height = DOMProperty("height")
|
606
|
+
width = DOMProperty("width")
|
607
|
+
|
608
|
+
def download(self, filename: str = "snapped.png") -> None:
|
609
|
+
"""Download the current element with the filename provided in input.
|
610
|
+
|
611
|
+
Inputs:
|
612
|
+
* filename (str): name of the file being downloaded
|
613
|
+
|
614
|
+
Output:
|
615
|
+
None
|
616
|
+
"""
|
617
|
+
download_link = a(download=filename, href=self._dom_element.toDataURL())
|
618
|
+
|
619
|
+
# Adding the link to the DOM is recommended for browser compatibility to make
|
620
|
+
# sure that the click works.
|
621
|
+
self.append(download_link)
|
670
622
|
|
623
|
+
download_link._dom_element.click()
|
671
624
|
|
672
|
-
|
625
|
+
def draw(self, what, width=None, height=None):
|
626
|
+
"""Draw `what` on the current element
|
627
|
+
|
628
|
+
Inputs:
|
629
|
+
|
630
|
+
* what (canvas image source): An element to draw into the context. The
|
631
|
+
specification permits any canvas image source, specifically, an
|
632
|
+
HTMLImageElement, an SVGImageElement, an HTMLVideoElement,
|
633
|
+
an HTMLCanvasElement, an ImageBitmap, an OffscreenCanvas, or a
|
634
|
+
VideoFrame.
|
635
|
+
"""
|
636
|
+
if isinstance(what, Element):
|
637
|
+
what = what._dom_element
|
638
|
+
|
639
|
+
# https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage
|
640
|
+
ctx = self._dom_element.getContext("2d")
|
641
|
+
if width or height:
|
642
|
+
ctx.drawImage(what, 0, 0, width, height)
|
643
|
+
|
644
|
+
else:
|
645
|
+
ctx.drawImage(what, 0, 0)
|
646
|
+
|
647
|
+
|
648
|
+
class caption(ContainerElement):
|
673
649
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/caption"""
|
674
650
|
|
675
651
|
tag = "caption"
|
676
652
|
|
677
653
|
|
678
|
-
class cite(
|
654
|
+
class cite(ContainerElement):
|
679
655
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/cite"""
|
680
656
|
|
681
657
|
tag = "cite"
|
682
658
|
|
683
659
|
|
684
|
-
class code(
|
660
|
+
class code(ContainerElement):
|
685
661
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/code"""
|
686
662
|
|
687
663
|
tag = "code"
|
688
664
|
|
689
665
|
|
690
|
-
class
|
666
|
+
class col(Element):
|
667
|
+
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/col"""
|
668
|
+
|
669
|
+
tag = "col"
|
670
|
+
|
671
|
+
span = DOMProperty("span")
|
672
|
+
|
673
|
+
|
674
|
+
class colgroup(ContainerElement):
|
675
|
+
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/colgroup"""
|
676
|
+
|
677
|
+
tag = "colgroup"
|
678
|
+
|
679
|
+
|
680
|
+
class data(ContainerElement):
|
691
681
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/data"""
|
692
682
|
|
693
683
|
tag = "data"
|
694
684
|
|
695
|
-
value =
|
685
|
+
value = DOMProperty("value")
|
696
686
|
|
697
687
|
|
698
|
-
class datalist(
|
688
|
+
class datalist(ContainerElement, HasOptions):
|
699
689
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/datalist"""
|
700
690
|
|
701
691
|
tag = "datalist"
|
702
692
|
|
703
693
|
|
704
|
-
class dd(
|
694
|
+
class dd(ContainerElement):
|
705
695
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dd"""
|
706
696
|
|
707
697
|
tag = "dd"
|
708
698
|
|
709
699
|
|
710
|
-
class del_(
|
700
|
+
class del_(ContainerElement):
|
711
701
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/del"""
|
712
702
|
|
713
703
|
tag = "del"
|
714
704
|
|
715
|
-
cite =
|
716
|
-
datetime =
|
705
|
+
cite = DOMProperty("cite")
|
706
|
+
datetime = DOMProperty("datetime")
|
717
707
|
|
718
708
|
|
719
|
-
class details(
|
709
|
+
class details(ContainerElement):
|
720
710
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details"""
|
721
711
|
|
722
712
|
tag = "details"
|
723
713
|
|
724
|
-
open =
|
714
|
+
open = DOMProperty("open")
|
725
715
|
|
726
716
|
|
727
|
-
class dialog(
|
717
|
+
class dialog(ContainerElement):
|
728
718
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog"""
|
729
719
|
|
730
720
|
tag = "dialog"
|
731
721
|
|
732
|
-
open =
|
722
|
+
open = DOMProperty("open")
|
733
723
|
|
734
724
|
|
735
|
-
class div(
|
725
|
+
class div(ContainerElement):
|
736
726
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/div"""
|
737
727
|
|
738
728
|
tag = "div"
|
739
729
|
|
740
730
|
|
741
|
-
class dl(
|
731
|
+
class dl(ContainerElement):
|
742
732
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dl"""
|
743
733
|
|
744
734
|
tag = "dl"
|
745
735
|
|
746
|
-
value =
|
736
|
+
value = DOMProperty("value")
|
747
737
|
|
748
738
|
|
749
|
-
class dt(
|
739
|
+
class dt(ContainerElement):
|
750
740
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dt"""
|
751
741
|
|
752
742
|
tag = "dt"
|
753
743
|
|
754
744
|
|
755
|
-
class em(
|
745
|
+
class em(ContainerElement):
|
756
746
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/em"""
|
757
747
|
|
758
748
|
tag = "em"
|
759
749
|
|
760
750
|
|
761
|
-
class embed(
|
751
|
+
class embed(Element):
|
762
752
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/embed"""
|
763
753
|
|
764
754
|
tag = "embed"
|
765
755
|
|
766
|
-
height =
|
767
|
-
src =
|
768
|
-
type =
|
769
|
-
width =
|
756
|
+
height = DOMProperty("height")
|
757
|
+
src = DOMProperty("src")
|
758
|
+
type = DOMProperty("type")
|
759
|
+
width = DOMProperty("width")
|
770
760
|
|
771
761
|
|
772
|
-
class fieldset(
|
762
|
+
class fieldset(ContainerElement):
|
773
763
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/fieldset"""
|
774
764
|
|
775
765
|
tag = "fieldset"
|
776
766
|
|
777
|
-
disabled =
|
778
|
-
form =
|
779
|
-
name =
|
767
|
+
disabled = DOMProperty("disabled")
|
768
|
+
form = DOMProperty("form")
|
769
|
+
name = DOMProperty("name")
|
780
770
|
|
781
771
|
|
782
|
-
class figcaption(
|
772
|
+
class figcaption(ContainerElement):
|
783
773
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/figcaption"""
|
784
774
|
|
785
775
|
tag = "figcaption"
|
786
776
|
|
787
777
|
|
788
|
-
class figure(
|
778
|
+
class figure(ContainerElement):
|
789
779
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/figure"""
|
790
780
|
|
791
781
|
tag = "figure"
|
792
782
|
|
793
783
|
|
794
|
-
class footer(
|
784
|
+
class footer(ContainerElement):
|
795
785
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/footer"""
|
796
786
|
|
797
787
|
tag = "footer"
|
798
788
|
|
799
789
|
|
800
|
-
class form(
|
790
|
+
class form(ContainerElement):
|
801
791
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form"""
|
802
792
|
|
803
793
|
tag = "form"
|
804
794
|
|
805
|
-
accept_charset =
|
806
|
-
action =
|
807
|
-
autocapitalize =
|
808
|
-
autocomplete =
|
809
|
-
enctype =
|
810
|
-
name =
|
811
|
-
method =
|
812
|
-
nonvalidate =
|
813
|
-
rel =
|
814
|
-
target =
|
795
|
+
accept_charset = DOMProperty("accept-charset")
|
796
|
+
action = DOMProperty("action")
|
797
|
+
autocapitalize = DOMProperty("autocapitalize")
|
798
|
+
autocomplete = DOMProperty("autocomplete")
|
799
|
+
enctype = DOMProperty("enctype")
|
800
|
+
name = DOMProperty("name")
|
801
|
+
method = DOMProperty("method")
|
802
|
+
nonvalidate = DOMProperty("nonvalidate")
|
803
|
+
rel = DOMProperty("rel")
|
804
|
+
target = DOMProperty("target")
|
815
805
|
|
816
806
|
|
817
|
-
class h1(
|
807
|
+
class h1(ContainerElement):
|
818
808
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h1"""
|
819
809
|
|
820
810
|
tag = "h1"
|
821
811
|
|
822
812
|
|
823
|
-
class h2(
|
813
|
+
class h2(ContainerElement):
|
824
814
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h2"""
|
825
815
|
|
826
816
|
tag = "h2"
|
827
817
|
|
828
818
|
|
829
|
-
class h3(
|
819
|
+
class h3(ContainerElement):
|
830
820
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h3"""
|
831
821
|
|
832
822
|
tag = "h3"
|
833
823
|
|
834
824
|
|
835
|
-
class h4(
|
825
|
+
class h4(ContainerElement):
|
836
826
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h4"""
|
837
827
|
|
838
828
|
tag = "h4"
|
839
829
|
|
840
830
|
|
841
|
-
class h5(
|
831
|
+
class h5(ContainerElement):
|
842
832
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h5"""
|
843
833
|
|
844
834
|
tag = "h5"
|
845
835
|
|
846
836
|
|
847
|
-
class h6(
|
837
|
+
class h6(ContainerElement):
|
848
838
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h6"""
|
849
839
|
|
850
840
|
tag = "h6"
|
851
841
|
|
852
842
|
|
853
|
-
class
|
843
|
+
class head(ContainerElement):
|
844
|
+
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/head"""
|
845
|
+
|
846
|
+
tag = "head"
|
847
|
+
|
848
|
+
|
849
|
+
class header(ContainerElement):
|
854
850
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/header"""
|
855
851
|
|
856
852
|
tag = "header"
|
857
853
|
|
858
854
|
|
859
|
-
class hgroup(
|
855
|
+
class hgroup(ContainerElement):
|
860
856
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/hgroup"""
|
861
857
|
|
862
858
|
tag = "hgroup"
|
863
859
|
|
864
860
|
|
865
|
-
class hr(
|
861
|
+
class hr(Element):
|
866
862
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/hr"""
|
867
863
|
|
868
864
|
tag = "hr"
|
869
865
|
|
866
|
+
align = DOMProperty("align")
|
867
|
+
color = DOMProperty("color")
|
868
|
+
noshade = DOMProperty("noshade")
|
869
|
+
size = DOMProperty("size")
|
870
|
+
width = DOMProperty("width")
|
870
871
|
|
871
|
-
|
872
|
+
|
873
|
+
class html(ContainerElement):
|
874
|
+
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/html"""
|
875
|
+
|
876
|
+
tag = "html"
|
877
|
+
|
878
|
+
|
879
|
+
class i(ContainerElement):
|
872
880
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/i"""
|
873
881
|
|
874
882
|
tag = "i"
|
875
883
|
|
876
884
|
|
877
|
-
class iframe(
|
885
|
+
class iframe(ContainerElement):
|
878
886
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe"""
|
879
887
|
|
880
888
|
tag = "iframe"
|
881
889
|
|
882
|
-
allow =
|
883
|
-
allowfullscreen =
|
884
|
-
height =
|
885
|
-
loading =
|
886
|
-
name =
|
887
|
-
referrerpolicy =
|
888
|
-
sandbox =
|
889
|
-
src =
|
890
|
-
srcdoc =
|
891
|
-
width =
|
890
|
+
allow = DOMProperty("allow")
|
891
|
+
allowfullscreen = DOMProperty("allowfullscreen")
|
892
|
+
height = DOMProperty("height")
|
893
|
+
loading = DOMProperty("loading")
|
894
|
+
name = DOMProperty("name")
|
895
|
+
referrerpolicy = DOMProperty("referrerpolicy")
|
896
|
+
sandbox = DOMProperty("sandbox")
|
897
|
+
src = DOMProperty("src")
|
898
|
+
srcdoc = DOMProperty("srcdoc")
|
899
|
+
width = DOMProperty("width")
|
892
900
|
|
893
901
|
|
894
|
-
class img(
|
902
|
+
class img(Element):
|
895
903
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img"""
|
896
904
|
|
897
905
|
tag = "img"
|
898
906
|
|
899
|
-
alt =
|
900
|
-
crossorigin =
|
901
|
-
decoding =
|
902
|
-
fetchpriority =
|
903
|
-
height =
|
904
|
-
ismap =
|
905
|
-
loading =
|
906
|
-
referrerpolicy =
|
907
|
-
sizes =
|
908
|
-
src =
|
909
|
-
width =
|
907
|
+
alt = DOMProperty("alt")
|
908
|
+
crossorigin = DOMProperty("crossorigin")
|
909
|
+
decoding = DOMProperty("decoding")
|
910
|
+
fetchpriority = DOMProperty("fetchpriority")
|
911
|
+
height = DOMProperty("height")
|
912
|
+
ismap = DOMProperty("ismap")
|
913
|
+
loading = DOMProperty("loading")
|
914
|
+
referrerpolicy = DOMProperty("referrerpolicy")
|
915
|
+
sizes = DOMProperty("sizes")
|
916
|
+
src = DOMProperty("src")
|
917
|
+
width = DOMProperty("width")
|
910
918
|
|
911
919
|
|
912
920
|
# NOTE: Input is a reserved keyword in Python, so we use input_ instead
|
913
|
-
class input_(
|
921
|
+
class input_(Element):
|
914
922
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input"""
|
915
923
|
|
916
924
|
tag = "input"
|
917
925
|
|
918
|
-
accept =
|
919
|
-
alt =
|
920
|
-
autofocus =
|
921
|
-
capture =
|
922
|
-
checked =
|
923
|
-
dirname =
|
924
|
-
disabled =
|
925
|
-
form =
|
926
|
-
formaction =
|
927
|
-
formenctype =
|
928
|
-
formmethod =
|
929
|
-
formnovalidate =
|
930
|
-
formtarget =
|
931
|
-
height =
|
932
|
-
list =
|
933
|
-
max =
|
934
|
-
maxlength =
|
935
|
-
min =
|
936
|
-
minlength =
|
937
|
-
multiple =
|
938
|
-
name =
|
939
|
-
pattern =
|
940
|
-
placeholder =
|
941
|
-
popovertarget =
|
942
|
-
popovertargetaction =
|
943
|
-
readonly =
|
944
|
-
required =
|
945
|
-
size =
|
946
|
-
src =
|
947
|
-
step =
|
948
|
-
type =
|
949
|
-
value =
|
950
|
-
width =
|
951
|
-
|
952
|
-
|
953
|
-
class ins(
|
926
|
+
accept = DOMProperty("accept")
|
927
|
+
alt = DOMProperty("alt")
|
928
|
+
autofocus = DOMProperty("autofocus")
|
929
|
+
capture = DOMProperty("capture")
|
930
|
+
checked = DOMProperty("checked")
|
931
|
+
dirname = DOMProperty("dirname")
|
932
|
+
disabled = DOMProperty("disabled")
|
933
|
+
form = DOMProperty("form")
|
934
|
+
formaction = DOMProperty("formaction")
|
935
|
+
formenctype = DOMProperty("formenctype")
|
936
|
+
formmethod = DOMProperty("formmethod")
|
937
|
+
formnovalidate = DOMProperty("formnovalidate")
|
938
|
+
formtarget = DOMProperty("formtarget")
|
939
|
+
height = DOMProperty("height")
|
940
|
+
list = DOMProperty("list")
|
941
|
+
max = DOMProperty("max")
|
942
|
+
maxlength = DOMProperty("maxlength")
|
943
|
+
min = DOMProperty("min")
|
944
|
+
minlength = DOMProperty("minlength")
|
945
|
+
multiple = DOMProperty("multiple")
|
946
|
+
name = DOMProperty("name")
|
947
|
+
pattern = DOMProperty("pattern")
|
948
|
+
placeholder = DOMProperty("placeholder")
|
949
|
+
popovertarget = DOMProperty("popovertarget")
|
950
|
+
popovertargetaction = DOMProperty("popovertargetaction")
|
951
|
+
readonly = DOMProperty("readonly")
|
952
|
+
required = DOMProperty("required")
|
953
|
+
size = DOMProperty("size")
|
954
|
+
src = DOMProperty("src")
|
955
|
+
step = DOMProperty("step")
|
956
|
+
type = DOMProperty("type")
|
957
|
+
value = DOMProperty("value")
|
958
|
+
width = DOMProperty("width")
|
959
|
+
|
960
|
+
|
961
|
+
class ins(ContainerElement):
|
954
962
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ins"""
|
955
963
|
|
956
964
|
tag = "ins"
|
957
965
|
|
958
|
-
cite =
|
959
|
-
datetime =
|
966
|
+
cite = DOMProperty("cite")
|
967
|
+
datetime = DOMProperty("datetime")
|
960
968
|
|
961
969
|
|
962
|
-
class kbd(
|
970
|
+
class kbd(ContainerElement):
|
963
971
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/kbd"""
|
964
972
|
|
965
973
|
tag = "kbd"
|
966
974
|
|
967
975
|
|
968
|
-
class label(
|
976
|
+
class label(ContainerElement):
|
969
977
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label"""
|
970
978
|
|
971
979
|
tag = "label"
|
972
980
|
|
973
|
-
for_ =
|
981
|
+
for_ = DOMProperty("for")
|
974
982
|
|
975
983
|
|
976
|
-
class legend(
|
984
|
+
class legend(ContainerElement):
|
977
985
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/legend"""
|
978
986
|
|
979
987
|
tag = "legend"
|
980
988
|
|
981
989
|
|
982
|
-
class li(
|
990
|
+
class li(ContainerElement):
|
983
991
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/li"""
|
984
992
|
|
985
993
|
tag = "li"
|
986
994
|
|
987
|
-
value =
|
995
|
+
value = DOMProperty("value")
|
988
996
|
|
989
997
|
|
990
|
-
class link(
|
998
|
+
class link(Element):
|
991
999
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link"""
|
992
1000
|
|
993
1001
|
tag = "link"
|
994
1002
|
|
995
|
-
as_ =
|
996
|
-
crossorigin =
|
997
|
-
disabled =
|
998
|
-
fetchpriority =
|
999
|
-
href =
|
1000
|
-
imagesizes =
|
1001
|
-
imagesrcset =
|
1002
|
-
integrity =
|
1003
|
-
media =
|
1004
|
-
rel =
|
1005
|
-
referrerpolicy =
|
1006
|
-
sizes =
|
1007
|
-
title =
|
1008
|
-
type =
|
1009
|
-
|
1010
|
-
|
1011
|
-
class main(
|
1003
|
+
as_ = DOMProperty("as")
|
1004
|
+
crossorigin = DOMProperty("crossorigin")
|
1005
|
+
disabled = DOMProperty("disabled")
|
1006
|
+
fetchpriority = DOMProperty("fetchpriority")
|
1007
|
+
href = DOMProperty("href")
|
1008
|
+
imagesizes = DOMProperty("imagesizes")
|
1009
|
+
imagesrcset = DOMProperty("imagesrcset")
|
1010
|
+
integrity = DOMProperty("integrity")
|
1011
|
+
media = DOMProperty("media")
|
1012
|
+
rel = DOMProperty("rel")
|
1013
|
+
referrerpolicy = DOMProperty("referrerpolicy")
|
1014
|
+
sizes = DOMProperty("sizes")
|
1015
|
+
title = DOMProperty("title")
|
1016
|
+
type = DOMProperty("type")
|
1017
|
+
|
1018
|
+
|
1019
|
+
class main(ContainerElement):
|
1012
1020
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/main"""
|
1013
1021
|
|
1014
1022
|
tag = "main"
|
1015
1023
|
|
1016
1024
|
|
1017
|
-
class map_(
|
1025
|
+
class map_(ContainerElement):
|
1018
1026
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/map"""
|
1019
1027
|
|
1020
1028
|
tag = "map"
|
1021
1029
|
|
1022
|
-
name =
|
1030
|
+
name = DOMProperty("name")
|
1023
1031
|
|
1024
1032
|
|
1025
|
-
class mark(
|
1033
|
+
class mark(ContainerElement):
|
1026
1034
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/mark"""
|
1027
1035
|
|
1028
1036
|
tag = "mark"
|
1029
1037
|
|
1030
1038
|
|
1031
|
-
class menu(
|
1039
|
+
class menu(ContainerElement):
|
1032
1040
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/menu"""
|
1033
1041
|
|
1034
1042
|
tag = "menu"
|
1035
1043
|
|
1036
1044
|
|
1037
|
-
class
|
1045
|
+
class meta(ContainerElement):
|
1046
|
+
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta"""
|
1047
|
+
|
1048
|
+
tag = "meta"
|
1049
|
+
|
1050
|
+
charset = DOMProperty("charset")
|
1051
|
+
content = DOMProperty("content")
|
1052
|
+
http_equiv = DOMProperty("http-equiv")
|
1053
|
+
name = DOMProperty("name")
|
1054
|
+
|
1055
|
+
|
1056
|
+
class meter(ContainerElement):
|
1038
1057
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meter"""
|
1039
1058
|
|
1040
1059
|
tag = "meter"
|
1041
1060
|
|
1042
|
-
form =
|
1043
|
-
high =
|
1044
|
-
low =
|
1045
|
-
max =
|
1046
|
-
min =
|
1047
|
-
optimum =
|
1048
|
-
value =
|
1061
|
+
form = DOMProperty("form")
|
1062
|
+
high = DOMProperty("high")
|
1063
|
+
low = DOMProperty("low")
|
1064
|
+
max = DOMProperty("max")
|
1065
|
+
min = DOMProperty("min")
|
1066
|
+
optimum = DOMProperty("optimum")
|
1067
|
+
value = DOMProperty("value")
|
1049
1068
|
|
1050
1069
|
|
1051
|
-
class nav(
|
1070
|
+
class nav(ContainerElement):
|
1052
1071
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/nav"""
|
1053
1072
|
|
1054
1073
|
tag = "nav"
|
1055
1074
|
|
1056
1075
|
|
1057
|
-
class object_(
|
1076
|
+
class object_(ContainerElement):
|
1058
1077
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/object"""
|
1059
1078
|
|
1060
1079
|
tag = "object"
|
1061
1080
|
|
1062
|
-
data =
|
1063
|
-
form =
|
1064
|
-
height =
|
1065
|
-
name =
|
1066
|
-
type =
|
1067
|
-
usemap =
|
1068
|
-
width =
|
1081
|
+
data = DOMProperty("data")
|
1082
|
+
form = DOMProperty("form")
|
1083
|
+
height = DOMProperty("height")
|
1084
|
+
name = DOMProperty("name")
|
1085
|
+
type = DOMProperty("type")
|
1086
|
+
usemap = DOMProperty("usemap")
|
1087
|
+
width = DOMProperty("width")
|
1069
1088
|
|
1070
1089
|
|
1071
|
-
class ol(
|
1090
|
+
class ol(ContainerElement):
|
1072
1091
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ol"""
|
1073
1092
|
|
1074
1093
|
tag = "ol"
|
1075
1094
|
|
1076
|
-
reversed =
|
1077
|
-
start =
|
1078
|
-
type =
|
1095
|
+
reversed = DOMProperty("reversed")
|
1096
|
+
start = DOMProperty("start")
|
1097
|
+
type = DOMProperty("type")
|
1079
1098
|
|
1080
1099
|
|
1081
|
-
class optgroup(
|
1100
|
+
class optgroup(ContainerElement, HasOptions):
|
1082
1101
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/optgroup"""
|
1083
1102
|
|
1084
1103
|
tag = "optgroup"
|
1085
1104
|
|
1086
|
-
disabled =
|
1087
|
-
label =
|
1105
|
+
disabled = DOMProperty("disabled")
|
1106
|
+
label = DOMProperty("label")
|
1088
1107
|
|
1089
1108
|
|
1090
|
-
class option(
|
1109
|
+
class option(ContainerElement):
|
1091
1110
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option"""
|
1092
1111
|
|
1093
1112
|
tag = "option"
|
1094
1113
|
|
1095
|
-
disabled =
|
1096
|
-
label =
|
1097
|
-
selected =
|
1098
|
-
value =
|
1114
|
+
disabled = DOMProperty("value")
|
1115
|
+
label = DOMProperty("label")
|
1116
|
+
selected = DOMProperty("selected")
|
1117
|
+
value = DOMProperty("value")
|
1099
1118
|
|
1100
1119
|
|
1101
|
-
class output(
|
1120
|
+
class output(ContainerElement):
|
1102
1121
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/output"""
|
1103
1122
|
|
1104
1123
|
tag = "output"
|
1105
1124
|
|
1106
|
-
for_ =
|
1107
|
-
form =
|
1108
|
-
name =
|
1125
|
+
for_ = DOMProperty("for")
|
1126
|
+
form = DOMProperty("form")
|
1127
|
+
name = DOMProperty("name")
|
1109
1128
|
|
1110
1129
|
|
1111
|
-
class p(
|
1130
|
+
class p(ContainerElement):
|
1112
1131
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/p"""
|
1113
1132
|
|
1114
1133
|
tag = "p"
|
1115
1134
|
|
1116
1135
|
|
1117
|
-
class
|
1136
|
+
class param(ContainerElement):
|
1137
|
+
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/p"""
|
1138
|
+
|
1139
|
+
tag = "p"
|
1140
|
+
|
1141
|
+
|
1142
|
+
class picture(ContainerElement):
|
1118
1143
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/picture"""
|
1119
1144
|
|
1120
1145
|
tag = "picture"
|
1121
1146
|
|
1122
1147
|
|
1123
|
-
class pre(
|
1148
|
+
class pre(ContainerElement):
|
1124
1149
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/pre"""
|
1125
1150
|
|
1126
1151
|
tag = "pre"
|
1127
1152
|
|
1128
1153
|
|
1129
|
-
class progress(
|
1154
|
+
class progress(ContainerElement):
|
1130
1155
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/progress"""
|
1131
1156
|
|
1132
1157
|
tag = "progress"
|
1133
1158
|
|
1134
|
-
max =
|
1135
|
-
value =
|
1159
|
+
max = DOMProperty("max")
|
1160
|
+
value = DOMProperty("value")
|
1136
1161
|
|
1137
1162
|
|
1138
|
-
class q(
|
1163
|
+
class q(ContainerElement):
|
1139
1164
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/q"""
|
1140
1165
|
|
1141
1166
|
tag = "q"
|
1142
1167
|
|
1143
|
-
cite =
|
1168
|
+
cite = DOMProperty("cite")
|
1144
1169
|
|
1145
1170
|
|
1146
|
-
class s(
|
1171
|
+
class s(ContainerElement):
|
1147
1172
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/s"""
|
1148
1173
|
|
1149
1174
|
tag = "s"
|
1150
1175
|
|
1151
1176
|
|
1152
|
-
class script(
|
1177
|
+
class script(ContainerElement):
|
1153
1178
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script"""
|
1154
1179
|
|
1155
1180
|
tag = "script"
|
1156
1181
|
|
1157
1182
|
# Let's add async manually since it's a reserved keyword in Python
|
1158
|
-
async_ =
|
1159
|
-
blocking =
|
1160
|
-
crossorigin =
|
1161
|
-
defer =
|
1162
|
-
fetchpriority =
|
1163
|
-
integrity =
|
1164
|
-
nomodule =
|
1165
|
-
nonce =
|
1166
|
-
referrerpolicy =
|
1167
|
-
src =
|
1168
|
-
type =
|
1169
|
-
|
1170
|
-
|
1171
|
-
class section(
|
1183
|
+
async_ = DOMProperty("async")
|
1184
|
+
blocking = DOMProperty("blocking")
|
1185
|
+
crossorigin = DOMProperty("crossorigin")
|
1186
|
+
defer = DOMProperty("defer")
|
1187
|
+
fetchpriority = DOMProperty("fetchpriority")
|
1188
|
+
integrity = DOMProperty("integrity")
|
1189
|
+
nomodule = DOMProperty("nomodule")
|
1190
|
+
nonce = DOMProperty("nonce")
|
1191
|
+
referrerpolicy = DOMProperty("referrerpolicy")
|
1192
|
+
src = DOMProperty("src")
|
1193
|
+
type = DOMProperty("type")
|
1194
|
+
|
1195
|
+
|
1196
|
+
class section(ContainerElement):
|
1172
1197
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/section"""
|
1173
1198
|
|
1174
1199
|
tag = "section"
|
1175
1200
|
|
1176
1201
|
|
1177
|
-
class select(
|
1202
|
+
class select(ContainerElement, HasOptions):
|
1178
1203
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select"""
|
1179
1204
|
|
1180
1205
|
tag = "select"
|
1181
1206
|
|
1207
|
+
value = DOMProperty("value")
|
1182
1208
|
|
1183
|
-
|
1209
|
+
|
1210
|
+
class small(ContainerElement):
|
1184
1211
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/small"""
|
1185
1212
|
|
1186
1213
|
tag = "small"
|
1187
1214
|
|
1188
1215
|
|
1189
|
-
class source(
|
1216
|
+
class source(Element):
|
1190
1217
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/source"""
|
1191
1218
|
|
1192
1219
|
tag = "source"
|
1193
1220
|
|
1194
|
-
media =
|
1195
|
-
sizes =
|
1196
|
-
src =
|
1197
|
-
srcset =
|
1198
|
-
type =
|
1221
|
+
media = DOMProperty("media")
|
1222
|
+
sizes = DOMProperty("sizes")
|
1223
|
+
src = DOMProperty("src")
|
1224
|
+
srcset = DOMProperty("srcset")
|
1225
|
+
type = DOMProperty("type")
|
1199
1226
|
|
1200
1227
|
|
1201
|
-
class span(
|
1228
|
+
class span(ContainerElement):
|
1202
1229
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/span"""
|
1203
1230
|
|
1204
1231
|
tag = "span"
|
1205
1232
|
|
1206
1233
|
|
1207
|
-
class strong(
|
1234
|
+
class strong(ContainerElement):
|
1208
1235
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/strong"""
|
1209
1236
|
|
1210
1237
|
tag = "strong"
|
1211
1238
|
|
1212
1239
|
|
1213
|
-
class style(
|
1240
|
+
class style(ContainerElement):
|
1214
1241
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/style"""
|
1215
1242
|
|
1216
1243
|
tag = "style"
|
1217
1244
|
|
1218
|
-
blocking =
|
1219
|
-
media =
|
1220
|
-
nonce =
|
1221
|
-
title =
|
1245
|
+
blocking = DOMProperty("blocking")
|
1246
|
+
media = DOMProperty("media")
|
1247
|
+
nonce = DOMProperty("nonce")
|
1248
|
+
title = DOMProperty("title")
|
1222
1249
|
|
1223
1250
|
|
1224
|
-
class sub(
|
1251
|
+
class sub(ContainerElement):
|
1225
1252
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sub"""
|
1226
1253
|
|
1227
1254
|
tag = "sub"
|
1228
1255
|
|
1229
1256
|
|
1230
|
-
class summary(
|
1257
|
+
class summary(ContainerElement):
|
1231
1258
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/summary"""
|
1232
1259
|
|
1233
1260
|
tag = "summary"
|
1234
1261
|
|
1235
1262
|
|
1236
|
-
class sup(
|
1263
|
+
class sup(ContainerElement):
|
1237
1264
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sup"""
|
1238
1265
|
|
1239
1266
|
tag = "sup"
|
1240
1267
|
|
1241
1268
|
|
1242
|
-
class table(
|
1269
|
+
class table(ContainerElement):
|
1243
1270
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table"""
|
1244
1271
|
|
1245
1272
|
tag = "table"
|
1246
1273
|
|
1247
1274
|
|
1248
|
-
class tbody(
|
1275
|
+
class tbody(ContainerElement):
|
1249
1276
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tbody"""
|
1250
1277
|
|
1251
1278
|
tag = "tbody"
|
1252
1279
|
|
1253
1280
|
|
1254
|
-
class td(
|
1281
|
+
class td(ContainerElement):
|
1255
1282
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/td"""
|
1256
1283
|
|
1257
1284
|
tag = "td"
|
1258
1285
|
|
1259
|
-
colspan =
|
1260
|
-
headers =
|
1261
|
-
rowspan =
|
1286
|
+
colspan = DOMProperty("colspan")
|
1287
|
+
headers = DOMProperty("headers")
|
1288
|
+
rowspan = DOMProperty("rowspan")
|
1262
1289
|
|
1263
1290
|
|
1264
|
-
class template(
|
1291
|
+
class template(ContainerElement):
|
1265
1292
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template"""
|
1266
1293
|
|
1267
1294
|
tag = "template"
|
1268
1295
|
|
1269
|
-
shadowrootmode =
|
1296
|
+
shadowrootmode = DOMProperty("shadowrootmode")
|
1270
1297
|
|
1271
1298
|
|
1272
|
-
class textarea(
|
1299
|
+
class textarea(ContainerElement):
|
1273
1300
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea"""
|
1274
1301
|
|
1275
1302
|
tag = "textarea"
|
1276
1303
|
|
1277
|
-
autocapitalize =
|
1278
|
-
autocomplete =
|
1279
|
-
autofocus =
|
1280
|
-
cols =
|
1281
|
-
dirname =
|
1282
|
-
disabled =
|
1283
|
-
form =
|
1284
|
-
maxlength =
|
1285
|
-
minlength =
|
1286
|
-
name =
|
1287
|
-
placeholder =
|
1288
|
-
readonly =
|
1289
|
-
required =
|
1290
|
-
rows =
|
1291
|
-
spellcheck =
|
1292
|
-
|
1293
|
-
|
1294
|
-
|
1295
|
-
|
1304
|
+
autocapitalize = DOMProperty("autocapitalize")
|
1305
|
+
autocomplete = DOMProperty("autocomplete")
|
1306
|
+
autofocus = DOMProperty("autofocus")
|
1307
|
+
cols = DOMProperty("cols")
|
1308
|
+
dirname = DOMProperty("dirname")
|
1309
|
+
disabled = DOMProperty("disabled")
|
1310
|
+
form = DOMProperty("form")
|
1311
|
+
maxlength = DOMProperty("maxlength")
|
1312
|
+
minlength = DOMProperty("minlength")
|
1313
|
+
name = DOMProperty("name")
|
1314
|
+
placeholder = DOMProperty("placeholder")
|
1315
|
+
readonly = DOMProperty("readonly")
|
1316
|
+
required = DOMProperty("required")
|
1317
|
+
rows = DOMProperty("rows")
|
1318
|
+
spellcheck = DOMProperty("spellcheck")
|
1319
|
+
value = DOMProperty("value")
|
1320
|
+
wrap = DOMProperty("wrap")
|
1321
|
+
|
1322
|
+
|
1323
|
+
class tfoot(ContainerElement):
|
1296
1324
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tfoot"""
|
1297
1325
|
|
1298
1326
|
tag = "tfoot"
|
1299
1327
|
|
1300
1328
|
|
1301
|
-
class th(
|
1329
|
+
class th(ContainerElement):
|
1302
1330
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/th"""
|
1303
1331
|
|
1304
1332
|
tag = "th"
|
1305
1333
|
|
1306
1334
|
|
1307
|
-
class thead(
|
1335
|
+
class thead(ContainerElement):
|
1308
1336
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/thead"""
|
1309
1337
|
|
1310
1338
|
tag = "thead"
|
1311
1339
|
|
1312
1340
|
|
1313
|
-
class time(
|
1341
|
+
class time(ContainerElement):
|
1314
1342
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/time"""
|
1315
1343
|
|
1316
1344
|
tag = "time"
|
1317
1345
|
|
1318
|
-
datetime =
|
1346
|
+
datetime = DOMProperty("datetime")
|
1319
1347
|
|
1320
1348
|
|
1321
|
-
class title(
|
1349
|
+
class title(ContainerElement):
|
1322
1350
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/title"""
|
1323
1351
|
|
1324
1352
|
tag = "title"
|
1325
1353
|
|
1326
1354
|
|
1327
|
-
class tr(
|
1355
|
+
class tr(ContainerElement):
|
1328
1356
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tr"""
|
1329
1357
|
|
1330
1358
|
tag = "tr"
|
1331
1359
|
|
1332
|
-
abbr =
|
1333
|
-
colspan =
|
1334
|
-
headers =
|
1335
|
-
rowspan =
|
1336
|
-
scope =
|
1360
|
+
abbr = DOMProperty("abbr")
|
1361
|
+
colspan = DOMProperty("colspan")
|
1362
|
+
headers = DOMProperty("headers")
|
1363
|
+
rowspan = DOMProperty("rowspan")
|
1364
|
+
scope = DOMProperty("scope")
|
1337
1365
|
|
1338
1366
|
|
1339
|
-
class track(
|
1367
|
+
class track(Element):
|
1340
1368
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/track"""
|
1341
1369
|
|
1342
1370
|
tag = "track"
|
1343
1371
|
|
1344
|
-
default =
|
1345
|
-
kind =
|
1346
|
-
label =
|
1347
|
-
src =
|
1348
|
-
srclang =
|
1372
|
+
default = DOMProperty("default")
|
1373
|
+
kind = DOMProperty("kind")
|
1374
|
+
label = DOMProperty("label")
|
1375
|
+
src = DOMProperty("src")
|
1376
|
+
srclang = DOMProperty("srclang")
|
1349
1377
|
|
1350
1378
|
|
1351
|
-
class u(
|
1379
|
+
class u(ContainerElement):
|
1352
1380
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/u"""
|
1353
1381
|
|
1354
1382
|
tag = "u"
|
1355
1383
|
|
1356
1384
|
|
1357
|
-
class ul(
|
1385
|
+
class ul(ContainerElement):
|
1358
1386
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ul"""
|
1359
1387
|
|
1360
1388
|
tag = "ul"
|
1361
1389
|
|
1362
1390
|
|
1363
|
-
class var(
|
1391
|
+
class var(ContainerElement):
|
1364
1392
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/var"""
|
1365
1393
|
|
1366
1394
|
tag = "var"
|
1367
1395
|
|
1368
1396
|
|
1369
|
-
class video(
|
1397
|
+
class video(ContainerElement):
|
1370
1398
|
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video"""
|
1371
1399
|
|
1372
1400
|
tag = "video"
|
1373
1401
|
|
1374
|
-
autoplay =
|
1375
|
-
controls =
|
1376
|
-
crossorigin =
|
1377
|
-
disablepictureinpicture =
|
1378
|
-
disableremoteplayback =
|
1379
|
-
height =
|
1380
|
-
loop =
|
1381
|
-
muted =
|
1382
|
-
playsinline =
|
1383
|
-
poster =
|
1384
|
-
preload =
|
1385
|
-
src =
|
1386
|
-
width =
|
1402
|
+
autoplay = DOMProperty("autoplay")
|
1403
|
+
controls = DOMProperty("controls")
|
1404
|
+
crossorigin = DOMProperty("crossorigin")
|
1405
|
+
disablepictureinpicture = DOMProperty("disablepictureinpicture")
|
1406
|
+
disableremoteplayback = DOMProperty("disableremoteplayback")
|
1407
|
+
height = DOMProperty("height")
|
1408
|
+
loop = DOMProperty("loop")
|
1409
|
+
muted = DOMProperty("muted")
|
1410
|
+
playsinline = DOMProperty("playsinline")
|
1411
|
+
poster = DOMProperty("poster")
|
1412
|
+
preload = DOMProperty("preload")
|
1413
|
+
src = DOMProperty("src")
|
1414
|
+
width = DOMProperty("width")
|
1415
|
+
videoHeight = DOMProperty("videoHeight")
|
1416
|
+
videoWidth = DOMProperty("videoWidth")
|
1417
|
+
|
1418
|
+
def snap(
|
1419
|
+
self,
|
1420
|
+
to: Element | str = None,
|
1421
|
+
width: int | None = None,
|
1422
|
+
height: int | None = None,
|
1423
|
+
):
|
1424
|
+
"""
|
1425
|
+
Capture a snapshot (i.e. a single frame) of a video to a canvas.
|
1426
|
+
|
1427
|
+
Inputs:
|
1428
|
+
|
1429
|
+
* to: the canvas to save the video frame to (if None, one is created).
|
1430
|
+
* width: width of the snapshot (defaults to the video width).
|
1431
|
+
* height: height of the snapshot (defaults to the video height).
|
1432
|
+
|
1433
|
+
Output:
|
1434
|
+
(Element) canvas element where the video frame snapshot was drawn into
|
1435
|
+
"""
|
1436
|
+
width = width if width is not None else self.videoWidth
|
1437
|
+
height = height if height is not None else self.videoHeight
|
1438
|
+
|
1439
|
+
if to is None:
|
1440
|
+
to = canvas(width=width, height=height)
|
1441
|
+
|
1442
|
+
elif isinstance(to, Element):
|
1443
|
+
if to.tag != "canvas":
|
1444
|
+
raise TypeError("Element to snap to must be a canvas.")
|
1445
|
+
|
1446
|
+
elif getattr(to, "tagName", "") == "CANVAS":
|
1447
|
+
to = canvas(dom_element=to)
|
1448
|
+
|
1449
|
+
# If 'to' is a string, then assume it is a query selector.
|
1450
|
+
elif isinstance(to, str):
|
1451
|
+
nodelist = document.querySelectorAll(to) # NOQA
|
1452
|
+
if nodelist.length == 0:
|
1453
|
+
raise TypeError("No element with selector {to} to snap to.")
|
1454
|
+
|
1455
|
+
if nodelist[0].tagName != "CANVAS":
|
1456
|
+
raise TypeError("Element to snap to must be a canvas.")
|
1457
|
+
|
1458
|
+
to = canvas(dom_element=nodelist[0])
|
1459
|
+
|
1460
|
+
to.draw(self, width, height)
|
1461
|
+
|
1462
|
+
return to
|
1463
|
+
|
1464
|
+
|
1465
|
+
class wbr(Element):
|
1466
|
+
"""Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/wbr"""
|
1467
|
+
|
1468
|
+
tag = "wbr"
|
1387
1469
|
|
1388
1470
|
|
1389
1471
|
# Custom Elements
|
1390
|
-
class grid(
|
1472
|
+
class grid(ContainerElement):
|
1391
1473
|
tag = "div"
|
1392
1474
|
|
1393
1475
|
def __init__(self, layout, content=None, gap=None, **kwargs):
|
@@ -1396,10 +1478,68 @@ class grid(TextElementBase):
|
|
1396
1478
|
self.style["grid-template-columns"] = layout
|
1397
1479
|
|
1398
1480
|
# TODO: This should be a property
|
1399
|
-
if
|
1481
|
+
if gap is not None:
|
1400
1482
|
self.style["gap"] = gap
|
1401
1483
|
|
1402
1484
|
|
1485
|
+
class ClassesCollection:
|
1486
|
+
def __init__(self, collection: "ElementCollection") -> None:
|
1487
|
+
self._collection = collection
|
1488
|
+
|
1489
|
+
def __contains__(self, class_name):
|
1490
|
+
for element in self._collection:
|
1491
|
+
if class_name in element.classes:
|
1492
|
+
return True
|
1493
|
+
|
1494
|
+
return False
|
1495
|
+
|
1496
|
+
def __eq__(self, other):
|
1497
|
+
return (
|
1498
|
+
isinstance(other, ClassesCollection)
|
1499
|
+
and self._collection == other._collection
|
1500
|
+
)
|
1501
|
+
|
1502
|
+
def __iter__(self):
|
1503
|
+
for class_name in self._all_class_names():
|
1504
|
+
yield class_name
|
1505
|
+
|
1506
|
+
def __len__(self):
|
1507
|
+
return len(self._all_class_names())
|
1508
|
+
|
1509
|
+
def __repr__(self):
|
1510
|
+
return f"ClassesCollection({repr(self._collection)})"
|
1511
|
+
|
1512
|
+
def __str__(self):
|
1513
|
+
return " ".join(self._all_class_names())
|
1514
|
+
|
1515
|
+
def add(self, *class_names):
|
1516
|
+
for element in self._collection:
|
1517
|
+
element.classes.add(*class_names)
|
1518
|
+
|
1519
|
+
def contains(self, class_name):
|
1520
|
+
return class_name in self
|
1521
|
+
|
1522
|
+
def remove(self, *class_names):
|
1523
|
+
for element in self._collection:
|
1524
|
+
element.classes.remove(*class_names)
|
1525
|
+
|
1526
|
+
def replace(self, old_class, new_class):
|
1527
|
+
for element in self._collection:
|
1528
|
+
element.classes.replace(old_class, new_class)
|
1529
|
+
|
1530
|
+
def toggle(self, *class_names):
|
1531
|
+
for element in self._collection:
|
1532
|
+
element.classes.toggle(*class_names)
|
1533
|
+
|
1534
|
+
def _all_class_names(self):
|
1535
|
+
all_class_names = set()
|
1536
|
+
for element in self._collection:
|
1537
|
+
for class_name in element.classes:
|
1538
|
+
all_class_names.add(class_name)
|
1539
|
+
|
1540
|
+
return all_class_names
|
1541
|
+
|
1542
|
+
|
1403
1543
|
class StyleCollection:
|
1404
1544
|
def __init__(self, collection: "ElementCollection") -> None:
|
1405
1545
|
self._collection = collection
|
@@ -1414,6 +1554,9 @@ class StyleCollection:
|
|
1414
1554
|
for element in self._collection._elements:
|
1415
1555
|
element.style[key] = value
|
1416
1556
|
|
1557
|
+
def __repr__(self):
|
1558
|
+
return f"StyleCollection({repr(self._collection)})"
|
1559
|
+
|
1417
1560
|
def remove(self, key):
|
1418
1561
|
for element in self._collection._elements:
|
1419
1562
|
element.style.remove(key)
|
@@ -1422,29 +1565,70 @@ class StyleCollection:
|
|
1422
1565
|
class ElementCollection:
|
1423
1566
|
def __init__(self, elements: [Element]) -> None:
|
1424
1567
|
self._elements = elements
|
1425
|
-
self.
|
1568
|
+
self._classes = ClassesCollection(self)
|
1569
|
+
self._style = StyleCollection(self)
|
1570
|
+
|
1571
|
+
def __eq__(self, obj):
|
1572
|
+
"""Check for equality by comparing the underlying DOM elements."""
|
1573
|
+
return isinstance(obj, ElementCollection) and obj._elements == self._elements
|
1426
1574
|
|
1427
1575
|
def __getitem__(self, key):
|
1428
1576
|
# If it's an integer we use it to access the elements in the collection
|
1429
1577
|
if isinstance(key, int):
|
1430
1578
|
return self._elements[key]
|
1579
|
+
|
1431
1580
|
# If it's a slice we use it to support slice operations over the elements
|
1432
1581
|
# in the collection
|
1433
1582
|
elif isinstance(key, slice):
|
1434
1583
|
return ElementCollection(self._elements[key])
|
1435
1584
|
|
1436
|
-
# If it's anything else (basically a string) we use it as a selector
|
1437
|
-
|
1438
|
-
|
1439
|
-
|
1585
|
+
# If it's anything else (basically a string) we use it as a query selector.
|
1586
|
+
return self.find(key)
|
1587
|
+
|
1588
|
+
def __iter__(self):
|
1589
|
+
yield from self._elements
|
1440
1590
|
|
1441
1591
|
def __len__(self):
|
1442
1592
|
return len(self._elements)
|
1443
1593
|
|
1444
|
-
def
|
1445
|
-
|
1446
|
-
|
1447
|
-
|
1594
|
+
def __repr__(self):
|
1595
|
+
return (
|
1596
|
+
f"{self.__class__.__name__} (length: {len(self._elements)}) "
|
1597
|
+
f"{self._elements}"
|
1598
|
+
)
|
1599
|
+
|
1600
|
+
def __getattr__(self, item):
|
1601
|
+
return self._get_attribute(item)
|
1602
|
+
|
1603
|
+
def __setattr__(self, key, value):
|
1604
|
+
# This class overrides `__setattr__` to delegate "public" attributes to the
|
1605
|
+
# elements in the collection, but we don't use the usual Python pattern where we
|
1606
|
+
# set attributes on the collection itself via `self.__dict__` as it is not yet
|
1607
|
+
# supported in our build of MicroPython. Instead, we handle it here.
|
1608
|
+
if key.startswith("_"):
|
1609
|
+
super().__setattr__(key, value)
|
1610
|
+
|
1611
|
+
else:
|
1612
|
+
self._set_attribute(key, value)
|
1613
|
+
|
1614
|
+
@property
|
1615
|
+
def children(self):
|
1616
|
+
return self._elements
|
1617
|
+
|
1618
|
+
@property
|
1619
|
+
def classes(self):
|
1620
|
+
return self._classes
|
1621
|
+
|
1622
|
+
@property
|
1623
|
+
def style(self):
|
1624
|
+
return self._style
|
1625
|
+
|
1626
|
+
def find(self, selector):
|
1627
|
+
elements = []
|
1628
|
+
for element in self._elements:
|
1629
|
+
elements.extend(element.find(selector))
|
1630
|
+
|
1631
|
+
return ElementCollection(elements)
|
1448
1632
|
|
1449
1633
|
def _get_attribute(self, attr, index=None):
|
1450
1634
|
if index is None:
|
@@ -1457,28 +1641,39 @@ class ElementCollection:
|
|
1457
1641
|
for el in self._elements:
|
1458
1642
|
setattr(el, attr, value)
|
1459
1643
|
|
1460
|
-
@property
|
1461
|
-
def html(self):
|
1462
|
-
return self._get_attribute("html")
|
1463
|
-
|
1464
|
-
@html.setter
|
1465
|
-
def html(self, value):
|
1466
|
-
self._set_attribute("html", value)
|
1467
|
-
|
1468
|
-
@property
|
1469
|
-
def value(self):
|
1470
|
-
return self._get_attribute("value")
|
1471
|
-
|
1472
|
-
@value.setter
|
1473
|
-
def value(self, value):
|
1474
|
-
self._set_attribute("value", value)
|
1475
1644
|
|
1476
|
-
|
1477
|
-
|
1478
|
-
|
1479
|
-
|
1480
|
-
|
1481
|
-
|
1482
|
-
|
1483
|
-
|
1484
|
-
|
1645
|
+
# fmt: off
|
1646
|
+
ELEMENT_CLASSES = [
|
1647
|
+
# We put grid first because it is really just a <div> but we want the div class to
|
1648
|
+
# be used if wrapping existing js elements that we have not tagged with a
|
1649
|
+
# `data-pyscript-type` attribute (last one is the winner when it comes to this
|
1650
|
+
# list).
|
1651
|
+
grid,
|
1652
|
+
# The rest in alphabetical order.
|
1653
|
+
a, abbr, address, area, article, aside, audio,
|
1654
|
+
b, base, blockquote, body, br, button,
|
1655
|
+
canvas, caption, cite, code, col, colgroup,
|
1656
|
+
data, datalist, dd, del_, details, dialog, div, dl, dt,
|
1657
|
+
em, embed,
|
1658
|
+
fieldset, figcaption, figure, footer, form,
|
1659
|
+
h1, h2, h3, h4, h5, h6, head, header, hgroup, hr, html,
|
1660
|
+
i, iframe, img, input_, ins,
|
1661
|
+
kbd,
|
1662
|
+
label, legend, li, link,
|
1663
|
+
main, map_, mark, menu, meta, meter,
|
1664
|
+
nav,
|
1665
|
+
object_, ol, optgroup, option, output,
|
1666
|
+
p, param, picture, pre, progress,
|
1667
|
+
q,
|
1668
|
+
s, script, section, select, small, source, span, strong, style, sub, summary, sup,
|
1669
|
+
table, tbody, td, template, textarea, tfoot, th, thead, time, title, tr, track,
|
1670
|
+
u, ul,
|
1671
|
+
var, video,
|
1672
|
+
wbr,
|
1673
|
+
]
|
1674
|
+
# fmt: on
|
1675
|
+
|
1676
|
+
|
1677
|
+
# Lookup tables to get an element class by its name or tag.
|
1678
|
+
ELEMENT_CLASSES_BY_NAME = {cls.__name__: cls for cls in ELEMENT_CLASSES}
|
1679
|
+
ELEMENT_CLASSES_BY_TAG = {cls.tag: cls for cls in ELEMENT_CLASSES}
|