0
# DOM Manipulation
1
2
Core DOM tree manipulation with element creation, attribute management, content addition/removal, searching, and rendering with customizable formatting. Includes context manager support and decorator functionality.
3
4
## Capabilities
5
6
### Base DOM Tag Class
7
8
Foundation class providing core DOM manipulation functionality for all elements.
9
10
```python { .api }
11
class dom_tag:
12
def __init__(self, *args, **kwargs):
13
"""
14
Create a new DOM element.
15
16
Parameters:
17
- *args: Child elements, text content, or iterables
18
- **kwargs: Element attributes and special rendering options
19
20
Special kwargs:
21
- __inline (bool): Render children inline
22
- __pretty (bool): Enable pretty printing
23
"""
24
25
# Class attributes
26
is_single: bool = False # Self-closing tag (e.g., <br/>, <img/>)
27
is_pretty: bool = True # Pretty print content by default
28
is_inline: bool = False # Inline rendering
29
30
# Instance attributes
31
attributes: dict # Element attributes
32
children: list # Child elements and text
33
parent: dom_tag | None # Parent element
34
```
35
36
### Element Creation and Content Management
37
38
Add, remove, and manipulate element content and children.
39
40
```python { .api }
41
def add(self, *args):
42
"""
43
Add child elements or content to this element.
44
45
Parameters:
46
- *args: Elements, text, numbers, dicts (attributes), or iterables
47
48
Returns:
49
- Single element if one arg, tuple of elements if multiple args
50
"""
51
52
def remove(self, obj):
53
"""
54
Remove a child element.
55
56
Parameters:
57
- obj: Child element to remove
58
"""
59
60
def clear(self):
61
"""
62
Remove all child elements and reset parent references.
63
"""
64
65
def add_raw_string(self, s):
66
"""
67
Add raw string content without escaping.
68
69
Parameters:
70
- s (str): Raw string to add
71
"""
72
```
73
74
#### Usage Examples
75
76
```python
77
from dominate.tags import div, p, a, ul, li
78
from dominate.util import text
79
80
# Basic content addition
81
container = div()
82
container.add(p('First paragraph'))
83
container.add(p('Second paragraph'))
84
85
# Multiple elements at once
86
heading, content = container.add(h1('Title'), div(cls='content'))
87
88
# Different content types
89
element = div()
90
element.add('Plain text') # String
91
element.add(42) # Number (converted to string)
92
element.add(p('Paragraph')) # Element
93
element.add({'class': 'my-class'}) # Attributes dict
94
element.add([li('Item 1'), li('Item 2')]) # Iterable
95
96
# Using += operator
97
nav = ul()
98
nav += li(a('Home', href='/'))
99
nav += li(a('About', href='/about'))
100
101
# Clear content
102
container.clear() # Removes all children
103
104
# Raw string (no escaping)
105
div_element = div()
106
div_element.add_raw_string('<em>This will not be escaped</em>')
107
```
108
109
### Attribute Management
110
111
Set, get, and delete element attributes with dictionary-like interface.
112
113
```python { .api }
114
def set_attribute(self, key, value):
115
"""
116
Set an element attribute.
117
118
Parameters:
119
- key (str|int): Attribute name or child index
120
- value: Attribute value or child element
121
"""
122
123
def delete_attribute(self, key):
124
"""
125
Delete an attribute or child element.
126
127
Parameters:
128
- key (str|int): Attribute name or child index
129
"""
130
131
def __getitem__(self, key):
132
"""
133
Get attribute value or child element.
134
135
Parameters:
136
- key (str|int): Attribute name or child index
137
138
Returns:
139
- Attribute value or child element
140
"""
141
142
def __setitem__(self, key, value):
143
"""Dictionary-style attribute/child setting."""
144
145
def __delitem__(self, key):
146
"""Dictionary-style attribute/child deletion."""
147
```
148
149
#### Usage Examples
150
151
```python
152
# Attribute management
153
element = div()
154
155
# Set attributes
156
element.set_attribute('class', 'container')
157
element['id'] = 'main-div'
158
element.data_value = '123' # Using attribute access
159
160
# Get attributes
161
class_name = element['class']
162
element_id = element.id
163
164
# Delete attributes
165
del element['class']
166
element.delete_attribute('id')
167
168
# Child element access
169
list_element = ul(li('Item 1'), li('Item 2'))
170
first_item = list_element[0] # Get first child
171
list_element[1] = li('New Item 2') # Replace second child
172
del list_element[0] # Remove first child
173
```
174
175
### Element Search and Navigation
176
177
Find elements within the DOM tree using various criteria.
178
179
```python { .api }
180
def get(self, tag=None, **kwargs):
181
"""
182
Recursively search for child elements.
183
184
Parameters:
185
- tag (str|class|None): Tag type to search for
186
- **kwargs: Attribute filters
187
188
Returns:
189
- list: Matching elements
190
"""
191
192
@property
193
def parent(self):
194
"""Get the parent element."""
195
196
def __contains__(self, item):
197
"""
198
Check if element contains a specific tag type.
199
200
Parameters:
201
- item (str|class): Tag type to check for
202
203
Returns:
204
- bool: True if found in children tree
205
"""
206
```
207
208
#### Usage Examples
209
210
```python
211
# Search examples
212
document = div(
213
div(p('Content 1'), id='section1', cls='content'),
214
div(p('Content 2'), id='section2', cls='content'),
215
p('Footer text', cls='footer')
216
)
217
218
# Find by tag type
219
paragraphs = document.get('p') # All <p> elements
220
divs = document.get(div) # All div elements
221
222
# Find by attributes
223
content_divs = document.get(cls='content') # class="content"
224
section1 = document.get(id='section1') # id="section1"
225
footer_p = document.get('p', cls='footer') # <p> with class="footer"
226
227
# Check containment
228
has_paragraphs = 'p' in document # True
229
has_tables = 'table' in document # False
230
231
# Navigation
232
first_div = document[0] # First child
233
parent_element = first_div.parent # Back to document
234
```
235
236
### Context Manager Support
237
238
Use elements as context managers with Python's `with` statement for clean, hierarchical markup creation.
239
240
```python { .api }
241
def __enter__(self):
242
"""
243
Enter context manager mode.
244
245
Returns:
246
- self: The element instance
247
"""
248
249
def __exit__(self, type, value, traceback):
250
"""
251
Exit context manager, adding any unassigned elements to this element.
252
253
Parameters:
254
- type, value, traceback: Exception information (if any)
255
"""
256
```
257
258
#### Usage Examples
259
260
```python
261
# Context manager usage
262
container = div(cls='main-container')
263
264
with container:
265
h1('Page Title')
266
p('This paragraph will be added to the container.')
267
268
with ul(cls='nav-menu'):
269
li(a('Home', href='/'))
270
li(a('About', href='/about'))
271
li(a('Contact', href='/contact'))
272
273
# Nested contexts
274
page = div()
275
with page:
276
with header():
277
h1('Site Title')
278
nav(
279
a('Link 1', href='/1'),
280
a('Link 2', href='/2')
281
)
282
283
with main():
284
article(
285
h2('Article Title'),
286
p('Article content here.')
287
)
288
289
footer('© 2023 Site Name')
290
```
291
292
### Decorator Support
293
294
Use elements as decorators for functions to create reusable widgets and components.
295
296
```python { .api }
297
def __new__(cls, *args, **kwargs):
298
"""
299
Handle decorator usage when element class is used with single callable argument.
300
301
Returns:
302
- Decorated function or new element instance
303
"""
304
305
def __call__(self, func):
306
"""
307
Use element instance as decorator.
308
309
Parameters:
310
- func: Function to decorate
311
312
Returns:
313
- Decorated function that returns element with function result
314
"""
315
```
316
317
#### Usage Examples
318
319
```python
320
# Class decorator (creates new instance each call)
321
@div
322
def create_card(title, content):
323
h3(title)
324
p(content)
325
326
card1 = create_card('Card 1', 'Content for card 1')
327
card2 = create_card('Card 2', 'Content for card 2')
328
329
# Instance decorator (copies instance each call)
330
@div(cls='alert alert-info')
331
def info_message(text):
332
p(text)
333
334
message1 = info_message('This is an info message')
335
message2 = info_message('Another info message')
336
337
# More complex widget
338
@div(cls='product-card')
339
def product_card(name, price, description):
340
with div(cls='card-header'):
341
h4(name)
342
span(f'${price}', cls='price')
343
344
with div(cls='card-body'):
345
p(description)
346
button('Add to Cart', cls='btn btn-primary')
347
348
product = product_card('Widget', 19.99, 'A useful widget for your needs.')
349
```
350
351
### Rendering and Output
352
353
Control how elements are rendered to HTML with various formatting options.
354
355
```python { .api }
356
def render(self, indent=' ', pretty=True, xhtml=False):
357
"""
358
Render element to HTML string.
359
360
Parameters:
361
- indent (str): Indentation string for pretty printing
362
- pretty (bool): Enable pretty printing with indentation
363
- xhtml (bool): Use XHTML-style self-closing tags
364
365
Returns:
366
- str: Rendered HTML
367
"""
368
369
def _render(self, sb, indent_level, indent_str, pretty, xhtml):
370
"""
371
Internal rendering method.
372
373
Parameters:
374
- sb (list): String buffer for output
375
- indent_level (int): Current indentation level
376
- indent_str (str): Indentation string
377
- pretty (bool): Pretty printing enabled
378
- xhtml (bool): XHTML mode
379
380
Returns:
381
- list: Updated string buffer
382
"""
383
384
def __str__(self):
385
"""String representation using render()."""
386
387
def __unicode__(self):
388
"""Unicode representation using render()."""
389
```
390
391
#### Usage Examples
392
393
```python
394
# Rendering options
395
element = div(
396
h1('Title'),
397
p('Content here')
398
)
399
400
# Default pretty printing
401
html = element.render()
402
# <div>
403
# <h1>Title</h1>
404
# <p>Content here</p>
405
# </div>
406
407
# Compact rendering
408
compact = element.render(pretty=False)
409
# <div><h1>Title</h1><p>Content here</p></div>
410
411
# Custom indentation
412
tabbed = element.render(indent='\t')
413
# <div>
414
# <h1>Title</h1>
415
# <p>Content here</p>
416
# </div>
417
418
# XHTML mode
419
xhtml = element.render(xhtml=True)
420
# Self-closing tags get /> instead of >
421
422
# String conversion
423
html_string = str(element) # Same as element.render()
424
```
425
426
### Collection Interfaces
427
428
Elements support standard Python collection operations.
429
430
```python { .api }
431
def __len__(self):
432
"""
433
Get number of child elements.
434
435
Returns:
436
- int: Number of children
437
"""
438
439
def __iter__(self):
440
"""
441
Iterate over child elements.
442
443
Returns:
444
- iterator: Child element iterator
445
"""
446
447
def __bool__(self):
448
"""
449
Boolean evaluation (always True for elements).
450
451
Returns:
452
- bool: Always True
453
"""
454
```
455
456
#### Usage Examples
457
458
```python
459
# Collection operations
460
menu = ul(
461
li('Item 1'),
462
li('Item 2'),
463
li('Item 3')
464
)
465
466
# Length
467
num_items = len(menu) # 3
468
469
# Iteration
470
for item in menu:
471
print(item) # Prints each <li> element
472
473
# Boolean evaluation
474
if menu: # Always True for elements
475
print('Menu exists')
476
477
# List-like operations
478
first_item = menu[0]
479
last_item = menu[-1]
480
menu.append(li('Item 4')) # Error: use add() instead
481
```
482
483
### Attribute Name Conversion
484
485
Automatic conversion of Python attribute names to HTML-compatible names.
486
487
```python { .api }
488
@staticmethod
489
def clean_attribute(attribute):
490
"""
491
Convert Python attribute names to HTML attribute names.
492
493
Parameters:
494
- attribute (str): Python attribute name
495
496
Returns:
497
- str: HTML-compatible attribute name
498
"""
499
500
@classmethod
501
def clean_pair(cls, attribute, value):
502
"""
503
Clean attribute name and handle boolean values.
504
505
Parameters:
506
- attribute (str): Attribute name
507
- value: Attribute value
508
509
Returns:
510
- tuple: (cleaned_attribute, processed_value)
511
"""
512
```
513
514
#### Usage Examples
515
516
```python
517
# Attribute name conversions
518
element = div(
519
cls='my-class', # 'cls' -> 'class'
520
class_name='other', # 'class_name' -> 'class'
521
fr='input-id', # 'fr' -> 'for'
522
html_for='input-id', # 'html_for' -> 'for'
523
data_value='123', # 'data_value' -> 'data-value'
524
aria_label='Description', # 'aria_label' -> 'aria-label'
525
_private='hidden', # '_private' -> 'private'
526
http_equiv='refresh' # 'http_equiv' -> 'http-equiv'
527
)
528
529
# Boolean attribute handling
530
checkbox = input_(
531
type='checkbox',
532
checked=True, # becomes checked="checked"
533
disabled=False # omitted from output
534
)
535
```
536
537
## DOM Level 1 Core API
538
539
W3C DOM Level 1 Core specification compliance for standard DOM operations.
540
541
```python { .api }
542
@property
543
def parentNode(self):
544
"""
545
DOM API: Get the parent element.
546
547
Returns:
548
- dom_tag|None: Parent element or None if root
549
"""
550
551
def getElementById(self, id):
552
"""
553
DOM API: Get element with specified ID.
554
555
Parameters:
556
- id (str): Element ID to search for
557
558
Returns:
559
- dom_tag|None: Element with matching ID or None
560
561
Raises:
562
- ValueError: If multiple elements have the same ID
563
"""
564
565
def getElementsByTagName(self, name):
566
"""
567
DOM API: Get all elements with specified tag name.
568
569
Parameters:
570
- name (str): Tag name to search for
571
572
Returns:
573
- list: All matching elements
574
"""
575
576
def appendChild(self, obj):
577
"""
578
DOM API: Add child element to the end of children list.
579
580
Parameters:
581
- obj: Element to add as child
582
583
Returns:
584
- self: The parent element (for chaining)
585
"""
586
```
587
588
#### Usage Examples
589
590
```python
591
# DOM Level 1 Core API usage
592
document = div(
593
div(p('Section 1'), id='section1'),
594
div(p('Section 2'), id='section2'),
595
p('Footer', id='footer')
596
)
597
598
# Get element by ID
599
section1 = document.getElementById('section1')
600
print(section1) # <div id="section1">...</div>
601
602
# Handle multiple/missing IDs
603
try:
604
missing = document.getElementById('nonexistent') # Returns None
605
print(missing)
606
except ValueError as e:
607
print(f'Error: {e}') # If multiple elements have same ID
608
609
# Get elements by tag name
610
all_paragraphs = document.getElementsByTagName('p')
611
print(len(all_paragraphs)) # 2
612
613
all_divs = document.getElementsByTagName('div')
614
print(len(all_divs)) # 2
615
616
# Append child (DOM-style)
617
new_section = div(p('New section'), id='section3')
618
document.appendChild(new_section)
619
620
# Parent navigation
621
child = document.getElementById('section1')
622
parent = child.parentNode # Returns the document div
623
```
624
625
## Context Management Functions
626
627
Global functions for working with context managers and current element state.
628
629
```python { .api }
630
def get_current(default=None):
631
"""
632
Get the current element in context manager scope.
633
634
Parameters:
635
- default: Value to return if no current context
636
637
Returns:
638
- dom_tag|default: Current context element or default
639
640
Raises:
641
- ValueError: If no current context and no default provided
642
"""
643
644
def attr(*args, **kwargs):
645
"""
646
Set attributes on the current context element.
647
648
Parameters:
649
- *args: Dictionaries of attributes
650
- **kwargs: Attribute key-value pairs
651
"""
652
```
653
654
#### Usage Examples
655
656
```python
657
# Context functions
658
with div() as container:
659
p('Content here')
660
661
# Get current context
662
current = get_current() # Returns the div
663
664
# Set attributes on current context
665
attr(id='main-container', cls='wrapper')
666
attr({'data-value': '123'})
667
668
# Outside context
669
try:
670
current = get_current()
671
except ValueError:
672
print('No current context')
673
674
# With default
675
current = get_current(default=None) # Returns None if no context
676
```