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.