Skip to content

Commit 101191d

Browse files
committed
Update DOM with goodies
1 parent 081150b commit 101191d

1 file changed

Lines changed: 81 additions & 9 deletions

File tree

violetear/dom.py

Lines changed: 81 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -82,15 +82,6 @@ def remove(self, *classes: str) -> "DOMElement":
8282
self._el.classList.remove(cls)
8383
return self
8484

85-
def toggle(self, *classes: str) -> "DOMElement":
86-
if IS_BROWSER and self._el:
87-
for cls in classes:
88-
if cls in self._el.classList:
89-
self._el.classList.remove(cls)
90-
else:
91-
self._el.classList.add(cls)
92-
return self
93-
9485
def on(self, event: str, handler: Callable) -> "DOMElement":
9586
"""Attaches a Python event listener."""
9687
if IS_BROWSER and self._el:
@@ -113,6 +104,87 @@ def raw(self):
113104
"""Returns the underlying JS element."""
114105
return self._el
115106

107+
def attr(self, name: str, value: Any = None) -> Union[str, "DOMElement", None]:
108+
"""
109+
Get or Set an HTML attribute.
110+
- attr("src") -> returns value
111+
- attr("src", "img.jpg") -> sets value and returns self
112+
"""
113+
if IS_BROWSER and self._el:
114+
if value is None:
115+
return self._el.getAttribute(name)
116+
self._el.setAttribute(name, str(value))
117+
return self
118+
119+
# Mock return for server-side safety
120+
return self if value is not None else None
121+
122+
def prop(self, name: str, value: Any = None) -> Any:
123+
"""
124+
Get or Set a JavaScript property (e.g. checked, disabled, valueAsDate).
125+
Distinct from attributes (html).
126+
"""
127+
if IS_BROWSER and self._el:
128+
if value is None:
129+
return getattr(self._el, name, None)
130+
setattr(self._el, name, value)
131+
return self
132+
133+
return self if value is not None else None
134+
135+
def toggle(self, cls: str, force: Optional[bool] = None) -> "DOMElement":
136+
"""
137+
Toggles a class.
138+
If 'force' is True, adds it. If False, removes it.
139+
If None, inverts current state.
140+
"""
141+
if IS_BROWSER and self._el:
142+
if force is True:
143+
self._el.classList.add(cls)
144+
elif force is False:
145+
self._el.classList.remove(cls)
146+
else:
147+
# Standard toggle behavior
148+
if self._el.classList.contains(cls):
149+
self._el.classList.remove(cls)
150+
else:
151+
self._el.classList.add(cls)
152+
return self
153+
154+
def serialize(self) -> dict:
155+
"""
156+
Scrapes all named input, select, and textarea elements within this element
157+
and returns a dictionary of their values.
158+
Handles checkboxes and radio buttons correctly.
159+
"""
160+
data = {}
161+
if IS_BROWSER and self._el:
162+
inputs = self._el.querySelectorAll("input, select, textarea")
163+
164+
for i in range(inputs.length):
165+
el = inputs.item(i)
166+
name = el.name
167+
if not name:
168+
continue
169+
170+
# Handle Checkbox
171+
if el.type == "checkbox":
172+
if el.checked:
173+
data[name] = True
174+
# Optional: Handle unchecked state if needed,
175+
# but usually omitted in serialization
176+
177+
# Handle Radio
178+
elif el.type == "radio":
179+
if el.checked:
180+
data[name] = el.value
181+
182+
# Handle standard inputs
183+
else:
184+
data[name] = el.value
185+
186+
return data
187+
116188

117189
class DOM:
118190
"""

0 commit comments

Comments
 (0)