Python Classes and Extensions of WDOM¶
Generating new elements by document.createElement
every time is quite mess.
So WDOM’s wdom.tag
module provides simple tag classes usually used.
By using tag classes, the previous example can be written as:
from wdom.document import set_app
from wdom.server import start
from wdom.tag import Div, H1, Input
class MyElement(Div):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.h1 = H1()
self.h1.textContent = 'Hello, WDOM'
self.input = Input()
self.input.addEventListener('input', self.update)
self.appendChild(self.input)
self.appendChild(self.h1)
def update(self, event):
self.h1.textContent = event.target.value
if __name__ == '__main__':
set_app(MyElement())
server = start()
Instead of using document.createElement
, in the above example is using
H1
class and Input
class to generate h1 element and input element.
Furthermore, MyElement
class inherits Div
class. Its instance is
rendered as div
element, or <div>
tag on a browser. These instances are
same as instances generated by document.createElement
method.
Names of pre-defined classes on wdom.tag
module are same as related tag
names, starting with upper-case and followed by lower-case.
For example, <button>
tag is Button
class, <br>
tag is Br
class,
and <textarea>
tag is Textarea
.
Actual HTML strings can be obtained by html
property of each elements.
For example, print(MyElement().html)
shows
<div wdom_id="..."><input wdom_id="..."><h1 wdom_id="...">Hello, WDOM</h1></div>
wdom_id
is an attribute which is used internally.
If you want to omit it for tests, use html_noid
property instead
print(MyElement().html_noid)
# -> <div><input><h1>Hello, WDOM</h1></div>
Append to Parent Node¶
By using parent
argument of constructor, newly generated elements will be
automatically appended to the parent node.
Using this, the above example can be written as:
from wdom.server import start
from wdom.document import set_app
from wdom.tag import Div, H1, Input
class MyElement(Div):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.h1 = H1(parent=self)
self.h1.textContent = 'Hello, WDOM'
self.input = Input(parent=self)
self.input.addEventListener('input', self.update)
def update(self, event):
self.h1.textContent = event.target.value
if __name__ == '__main__':
set_app(MyElement())
start()
At the line self.h1 = H1(parent=self)
, new h1
element is automatically
appended to self
as its child node.
Append Child Nodes¶
In the other way, child nodes can be appended on generation.
from wdom.document import set_app
from wdom.server import start
from wdom.tag import Div, H1, Input
class MyElement(Div):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.h1 = H1('Hello, WDOM', parent=self)
self.input = Input(parent=self)
self.input.addEventListener('input', self.update)
def update(self, event):
self.h1.textContent = event.target.value
if __name__ == '__main__':
set_app(MyElement())
start()
At the self.h1 = H1('Hello, WDOM', parent=self)
, the first argument is
converted to Text Node and appended to the newly generated h1
element.
With multiple arguments, more than one child node can be appended, like
H1(H2(), P(), ...)
.
Initialization with Attributes¶
Attributes are also able to be defined with keyword arguments on the constructor.
from wdom.tag import Input
input = Input(type='checkbox')
print(input.html_noid) # <input type="checkbox">
# this is equivalent to:
input = Input()
input.setAttribute('type', 'checkbox')
# also same as:
input.type = 'checkbox'
class
is a python’s keyword, so use class_
(trailing underscore) instead.
from wdom.tag import H1
h1 = H1(class_='title')
print(h1.html_noid) # <h1 class="title"></h1>
# this is equivalent to:
h1 = H1()
h1.setAttribute('class', 'title')
# also same as:
h1.classList.add('title')
# classList.add accepts mutliple arguments
h1.classList.add('title', 'heading', '...', )
Default Class Attribute¶
User-defined class can have default class attributes.
from wdom.tag import Button
class MyButton(Button):
class_ = 'btn'
print(MyButton().html_noid)
# <button class="btn"></button>
# This is almost same as:
class MyButton2(Button):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.setAttribute('class', 'btn')
...
# class-level classes are not able to remove from instance
btn = MyButton()
btn.classList.remove('btn')
print(btn.html_noid) # <button class="btn"></button>
btn2 = MyButton2()
btn2.classList.remove('btn')
print(btn2.html_noid) # <button></button>
# Inherited class_ not overrides super-classes class_
class DefaultButton(MyButton):
class_ = 'btn-default'
db = DefaultButton()
print(db.html_noid) # <button class="btn btn-default"></button>
class_
class-variable is added to the instance. This attribute cannot be
removed at its instance and it is inherited to the subclasses. If you don’t want
to inherit parent’s class attributes, add inherit_class = False
as a class
variable.
Shortcut of Class Definition¶
Defining lots of similar classes by class
statement is quite mess.
WDOM provides wdom.tag.NewTagClass
function to make new user-defined
classes.
MyButton
class and DefaultButton
class defined in the above example can
be defined simply by using NewTagClass
function as below:
from wdom.tag import Button, NewTagClass
# Making new class easily
MyButton = NewTagClass('MyButton', 'button', Button, class_='btn')
DefaultButton = NewTagClass('DefaultButton', 'button', MyButton, class_='btn-default')
print(MyButton().html_noid)
print(DefaultButton().html_noid)
The first argument is a name of new class, the second is a tag name, the third is a base class, and the firth and other keyword arguments are class-variables of the new class. To inherit multiple classes, use tuple at the third argument.
These features are not DOM standard and specially defined for WDOM.
Execute JavaScript on Browser¶
(to be written)