Basic DOM Features¶
First Example¶
Program to show "Hello, WDOM"
on browser is:
from wdom.document import get_document
from wdom.server import start
if __name__ == '__main__':
document = get_document()
h1 = document.createElement('h1')
h1.textContent = 'Hello, WDOM'
document.body.appendChild(h1)
start()
Save and execute code and access http://localhost:8888
by browser.
Then, web page with "Hello, WDOM"
will be shown.
The four lines beginning from document = get_document()
are very similar to
JavaScript.
document
returned by get_document()
is a Document Node, equivalent to
document
object in JavaScript on browsers.
document.createElement('{tag-name}')
generates new element with the given
tag-name.
appendChild
method inserts the child node at the last of its child nodes.
Not used in the sample code, by using removeChild
method, one can remove the
child node.
Model of WDOM Elements¶
GUI elements of the WDOM are composed of HTML tags (elements or nodes) on a
browser.
Usually they have one-by-one relationships:
thus document.createElement('h1')
returns one WDOM element, and it is
rendered as an <h1>
tag on a browser.
All WDOM elements have their own HTML representations, which can be obtained by
their html
property.
Elements created by WDOM are all based on DOM Living Standard and related standards (HTML Living Standard, CSS Object Model, DOM Parsing, and Custom Elements in WebComponents).
As elements are modeled by DOM, you can add/remove/replace them as same as the way in JavaScript on browsers. Currently, not all of DOM features have been implemented in WDOM, but lots of frequently-used methods/properties are available. Implemented features are listed in wiki pages at gihub.
Create New Element¶
To make elements, WDOM provides two methods.
One is document.createElement
mentioned above, and the other is to
instantiate classes defined in wdom.tag
module. For details about the
wdom.tag
module, see Python Classes and Extensions of WDOM section.
Note
Every element does not appear on browser until inserted to the DOM
tree which roots on the document node returned by get_document()
.
Append/Insert Node¶
To insert nodes on the DOM tree, use appendChild
or insertBefore
method.
A.appendChild(B)
append the node B at last of child nodes of the parent node A.
A.insertBefore(B, C)
inserts new element B just before the reference node C.
The reference node C must be a child node of the parent node A.
These method names are quite long, so some methods specified in DOM
specification are also available on WDOM: prepend
, append
, before
,
after
, and replaceWith
. Details about these methods are described in
Newest DOM Features section.
Remove Node¶
It is also able to remove child node from the DOM tree.
A.removeChild(B)
removes the child node B from the parent node A. If B is
not a child node of A, it will raise Error.
More simple method B.remove()
is also available, see Newest DOM Features
section.
Access Child/Parent/Sibling Nodes¶
childNodes
property returns list-like live-object which contains its direct
child nodes. firstChild
and lastChild
property returns its first/last
child node.
On the other way, parentNode
property returns its parent node.
These properties are same as JavaScript’s DOM.
nextSibling
and previousSibling
returns its next/previous
sibling node.
If there is no corresponding node, all these properties return None
.
Attributes¶
To get element’s attributes like class="..."
in HTML tag, use
getAttribute('attribute-name')
method.
If called getAttribute
to the attribute which does not exists, it will return
None
.
To set or change attribute’s value, use setAttribute('attribute-name', value)
method. And to remove an attribute, use removeAttribute
method.
To obtain all attributes set for the element, access attributes
property.
This property returns dictionary-like abject NamedNodeMap
. This object has
attributes and its value as {'attribute-name': value, ...}
.
Special Attributes¶
Some attributes are accessible via special properties, for exmaple, A.id
returns its ID attribute. Available properties will be found in
wiki page at gihub.
With getAttribute
returns string or None, but attributes accessed via its
properties return different types depending on its property.
For example, element.id
return always string even if it is not set (in case
id is not set, element.id
returns empty string, not None).
Similarly, element.hidden
returns boolean (True
or False
) and
element.style
returns CSSStyleDeclaration
.
- References
Style Attribute (CSSStyleDeclaration)¶
CSSStyleDeclaration
obtained by element.style
provides property access
to its css properties. For example, element.style.color = 'red'
makes
element’s color red.
Some css properties including hyphen (-
) will be converted to CamelCase name.
For example, background-color
will become element.style.backgroundColor
.
For more examples, please see CSS Properties
Reference
Using HTML¶
Making large applications with appendChild
and insertBefore
are quite
difficult.
So writing HTML and parse it to WDOM elements is sometimes useful.
It can be done by innerHTML
method, as same as JavaScript.
An example to make large list is below:
from wdom.tag import Ul
ul = Ul()
ul.innerHTML = '''\
<li>item1</li>
<li>item2</li>
<li>item3</li>
<li>item4</li>
'''
print(ul.html_noid) # <ul><li>...
# Accessing child nodes
# for child in ul.childNodes:
# print(child.html)
# or, first/lastChild
print(ul.firstChild.html)
print(ul.lastChild.html)
# excluding Text nodes
for child in ul.children:
print(child.html)
# first/lastElementChild
print(ul.firstElementChild.html)
print(ul.lastElementChild.html)
Note
Assignment to innerHTML
removes all child nodes and insert parsed
elements.
Each child nodes can be accessed via childNodes
property, which returns
list-like live-object, but not able to modify its values.
insertAdjacentHTML({position}, {html})
also parses HTML and insert new
elements to the position
. This method is also same as JavaScript’s one, so
for details please see MDN Element.insertAdjacentHTML()
or DOM specification.
outerHTML
is not implemented in WDOM.
Event Handling¶
Reverse Text on Click¶
WDOM’s event handling is also same as JavaScript:
from wdom.server import start
from wdom.document import get_document
if __name__ == '__main__':
document = get_document()
h1 = document.createElement('h1')
h1.textContent = 'Hello, WDOM'
def rev_text(event):
h1.textContent = h1.textContent[::-1]
h1.addEventListener('click', rev_text)
document.body.appendChild(h1)
start()
Run this code and click "Hello, WDOM"
.
Then it will be reversed.
When clicked again, it will be reversed again and back to "Hello, WDOM"
.
addEventListener('{event-type}', {handler})
method registers handler
to the
given event-type
. In the sample code, rev_text
function is registered to
click
event. Values available for event type are same as JavaScript’s DOM, as
listed in Event reference |
MDN.
When the h1
element is clicked, registered function rev_text
is called with
a single argument, event, which is an Event object, though it is not used in the
above example.
User Input Event¶
The below sample shows how to use event object:
from wdom.document import get_document
from wdom.server import start
if __name__ == '__main__':
document = get_document()
h1 = document.createElement('h1')
h1.textContent = 'Hello, WDOM'
input = document.createElement('textarea')
def update(event):
h1.textContent = event.target.value
input.addEventListener('input', update)
document.body.appendChild(input)
document.body.appendChild(h1)
start()
In this sample, textarea
element is added.
When user inputs some text on the textarea
, it will be shown as h1
element.
In the update
function, event.target
has a reference to the element
which emitted the event, in this case it is a textarea
element.
And, as same as JavaScript, a textarea
element (and input
element) contains
its current value at value
attribute.
At the moment update
function is called, textarea.value
is already
updated to the latest value. So the above code you can use textarea.value
instead of event.target.value
.
In the sample code, setting its value to h1
element’s textContent
.