Newest DOM Features¶
Some newest DOM features, which have not been implemented yet on browsers are available on WDOM.
ParentNode and ChildNode Interfaces¶
appendChild method add only one child node, but append method can append
multiple nodes at once. Furthermore, strings are also available (strings are
automatically converted to a Text Node).
from wdom.tag import Ul, Li
ul = Ul()
li1 = Li('item1')
li2 = Li('item2')
...
ul.appendChild(li1)
ul.appendChild(li2)
...
print(ul.html_noid)
# by append
ul2 = Ul()
ul2.append(Li('item1'), Li('item2'))
print(ul2.html_noid)
Similarly, prepend, after, and before methods are available.
Additionally, remove, replaceWith, children, firstElementChild,
lastElementChild, previousElementSibling, and nextElementSibling
methods/properties are also available on WDOM.
Internally, these methods update view on the browser at once, so using these methods usually results in better performance.
Custom Elements¶
WDOM provides limited supports on custom elements (experimental).
User Defined Custom Tags¶
As an example, define MyElement as a custom tag <my-element>.
from wdom.tag import Div, H1, Input
from wdom.document import get_document
from wdom.server import start
class MyElement(Div):
tag = 'my-element' # custom tag name
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__':
document = get_document()
# Register MyElement
document.defaultView.customElements.define('my-element', MyElement)
# Make instance of MyElement from HTML
document.body.insertAdjacentHTML('beforeend', '<my-element></my-element>')
# Or, from createElement method
my_element = document.createElement('my-element')
document.body.appendChild(my_element)
start()
Difference is a class variable tag = 'my-element'.
To register MyElement class as a custom tag, use
document.defaultView.customElements.define() method.
Note
Formerly, document.registerElement method was used to define custom
tags, but in the latest specification uses
customElements.define method to reagister custom tags. WDOM supports
the same method as the latest specification.
document.defaultView property returns a reference to the window object,
which is same as the window object of JavaScript on browsers.
Now you can use the registered custom tag from
document.createElement('my-element') or innerHTML = '<my-element></my-element>'.
Both these methods make a new instance of MyElement
Extended Custom Tags¶
WDOM supports to extend existing tags with is attribute.
For example, to define MyButton or DefaultButton as a custom tag:
from wdom.document import get_document
from wdom.server import start
from wdom.tag import Button, Div
class MyButton(Button):
# tag = 'button' <- tag name is already defined in Button class
class_ = 'btn'
is_ = 'my-button' # set name at is_
class DefaultButton(MyButton):
class_ = 'btn-default'
is_ = 'default-button'
if __name__ == '__main__':
document = get_document()
# Register MyElement
document.defaultView.customElements.define('my-button', MyButton, {'extends': 'button'})
document.defaultView.customElements.define('default-button', DefaultButton, {'extends': 'button'})
# Load css and js file for bootstrap
document.add_cssfile('https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css')
document.add_jsfile('https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js')
document.add_jsfile('https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js')
div = Div(parent=document.body)
div.innerHTML = '''
<button is="my-button">MyButton</button>
<button is="default-button">DefaultButton</button>
'''.strip()
print(isinstance(div.firstChild, MyButton)) # True
print(isinstance(div.lastChild, DefaultButton)) # True
start()
On the class statements, add class variable is_ and specify the name of the
custom tag.
Class variable tag is a tag name to be extended, but in the above example,
it is already defined in Button class.
When registering the custom tag, pass the name (value of is_) at the first
argument to customElements.define and pass dictionary which contains
'extends' field to specify the tag name to be extended, at the third
argument.
After the new tag is registered, an HTML like <button is="my-button"> will be parsed
to an instance of MyElement, and <button is="default-button"> to
DefaultButton.
Caution
It’s highly recommended to register custom tags as early as possible.
If the instance was generated before registering it, it becomes different
class. When the customElements.define is called and registerd the custom
tag, WDOM will try to update the class of existing instances but
__init__ will not be not called.
Additionally, changing is attribute of the existing instances, e.g.
element.setAttribute('is', '...'), do not change its class currently.
In future, Lifecycle callback methods or silimar features will be implemented, but still it’s safer to register custom tags before instanciate it.