class DOMTokenList(MutableSequence[str]):
class Attr:
class DraggableAttr(Attr):
class NamedNodeMap(UserDict):
class ElementParser(FragmentParser):
class HTMLElementParser(ElementParser):
class ElementMeta(type):
class Element(Node, EventTarget, ParentNode, NonDocumentTypeChildNode,
              ChildNode, metaclass=ElementMeta):
class HTMLElement(Element):
class FormControlMixin(AbstractNode):
class HTMLAnchorElement(HTMLElement):  # noqa: D204
class HTMLButtonElement(HTMLElement):  # noqa: D204
class HTMLFormElement(HTMLElement):  # noqa: D204
class HTMLIFrameElement(HTMLElement):  # noqa: D204
class HTMLInputElement(HTMLElement, FormControlMixin):
class HTMLLabelElement(HTMLElement, FormControlMixin):
class HTMLOptGroupElement(HTMLElement, FormControlMixin):  # noqa: D204
class HTMLOptionElement(HTMLElement, FormControlMixin):  # noqa: D204
class HTMLScriptElement(HTMLElement):  # noqa: D204
class HTMLSelectElement(HTMLElement, FormControlMixin):
class HTMLStyleElement(HTMLElement):  # noqa: D204
class HTMLTextAreaElement(HTMLElement, FormControlMixin):  # noqa: D204
    def __init__(self, owner: Union[Node, Type['HTMLElement']],
                 *args: Union[str, 'DOMTokenList']) -> None:
    def __len__(self) -> int:
    def __contains__(self, item: object) -> bool:
    def __iter__(self) -> Iterator[str]:
    def _validate_token(self, token: str) -> None:
    def _append(self, token: Union[Iterable, str]) -> None:
    def __getitem__(self, index: Union[int, slice]  # type: ignore
                    ) -> Optional[str]:
    def __setitem__(self, s, item) -> None:  # type: ignore
    def __delitem__(self, index: int) -> None:  # type: ignore
    def length(self) -> int:
    def add(self, *tokens: str) -> None:
    def remove(self, *tokens: str) -> None:
    def toggle(self, token: str) -> None:
    def item(self, index: int) -> Optional[str]:
    def insert(self, index: int, item: str) -> None:
    def contains(self, token: str) -> bool:
    def toString(self) -> str:
    def __init__(self, name: str,
                 value: _AttrValueType = None,
                 owner: Node = None) -> None:
    def html(self) -> str:
    def name(self) -> str:
    def value(self) -> _AttrValueType:
    def value(self, val: str) -> None:
    def isId(self) -> bool:
    def html(self) -> str:
    def __init__(self, owner: Node) -> None:
    def __len__(self) -> int:
    def __contains__(self, item: object) -> bool:
    def __getitem__(self, index: Union[int, str]) -> Optional[Attr]:
    def __setitem__(self, attr: str, item: Attr) -> None:
    def __delitem__(self, attr: str) -> None:
    def __iter__(self) -> Iterator[str]:
    def length(self) -> int:
    def getNamedItem(self, name: str) -> Optional[Attr]:
    def setNamedItem(self, item: Attr) -> None:
    def removeNamedItem(self, item: Attr) -> Optional[Attr]:
    def item(self, index: int) -> Optional[Attr]:
    def toString(self) -> str:
    def __init__(self, *args: Any, **kwargs: Any) -> None:
    def __init__(self, *args: Any, **kwargs: Any) -> None:
def _string_properties(attr: str) -> property:
    def getter(self: Node) -> str:
    def setter(self: Node, value: str) -> None:
    def deleter(self: Node) -> None:
def _boolean_properties(attr: str) -> property:
    def getter(self: Node) -> bool:
    def setter(self: Node, value: bool) -> None:
    def deleter(self: Node) -> None:
    def __new__(cls: type, name: str, bases: Tuple[type],
                namespace: Dict[str, Any], **kwargs: Any) -> type:
def getElementsBy(start_node: ParentNode,
                  cond: Callable[['Element'], bool]) -> NodeList:
def getElementsByTagName(start_node: ParentNode, tag: str) -> NodeList:
def getElementsByClassName(start_node: ParentNode, class_name: str
                           ) -> NodeList:
def querySelector(start_node: ParentNode, selectors: str) -> AbstractNode:
def querySelectorAll(start_node: ParentNode, selectors: str) -> NodeList:
    def __init__(self, tag: str='', parent: Node = None,
                 _registered: bool = True, **kwargs: Any) -> None:
    def _clone_node(self) -> 'Element':
    def _get_attrs_by_string(self) -> str:
    def start_tag(self) -> str:
    def end_tag(self) -> str:
    def _parse_html(self, html: str) -> DocumentFragment:
    def _get_inner_html(self) -> str:
    def _set_inner_html(self, html: str) -> None:
    def innerHTML(self) -> str:
    def innerHTML(self, html: str) -> None:
    def html(self) -> str:
    def insertAdjacentHTML(self, position: str, html: str) -> None:
    def outerHTML(self) -> str:
    def nodeName(self) -> str:  # type: ignore
    def tagName(self) -> str:
    def localName(self) -> str:
    def className(self) -> str:
    def className(self, new_class: str) -> None:
    def getAttribute(self, attr: str) -> _AttrValueType:
    def getAttributeNode(self, attr: str) -> Optional[Attr]:
    def hasAttribute(self, attr: str) -> bool:
    def hasAttributes(self) -> bool:
    def _set_attribute_class(self, value: _AttrValueType) -> None:
    def _change_id(self, value: _AttrValueType) -> None:
    def _set_attribute(self, attr: str, value: _AttrValueType) -> None:
    def setAttribute(self, attr: str, value: _AttrValueType) -> None:
    def setAttributeNode(self, attr: Attr) -> None:
    def _remove_attribute(self, attr: str) -> None:
    def removeAttribute(self, attr: str) -> None:
    def removeAttributeNode(self, attr: Attr) -> Optional[Attr]:
    def getElementsBy(self, cond: Callable[['Element'], bool]) -> NodeList:
    def getElementsByTagName(self, tag: str) -> NodeList:
    def getElementsByClassName(self, class_name: str) -> NodeList:
    def querySelector(self, selectors: str) -> Node:
    def querySelectorAll(self, selectors: str) -> NodeList:
    def __init__(self, *args: Any, style: str=None, **kwargs: Any) -> None:
    def _get_attrs_by_string(self) -> str:
    def _clone_node(self) -> 'HTMLElement':
    def end_tag(self) -> str:
    def style(self) -> CSSStyleDeclaration:
    def style(self, style: _AttrValueType) -> None:
    def draggable(self) -> Union[bool, str]:
    def draggable(self, value: Union[bool, str]) -> None:
    def getAttribute(self, attr: str) -> _AttrValueType:  # noqa: D102
    def _set_attribute(self, attr: str, value: _AttrValueType) -> None:
    def _remove_attribute(self, attr: str) -> None:
    def __init__(self, *args: Any, form: Union[str, 'HTMLFormElement'] = None,
                 **kwargs: Any) -> None:
    def form(self) -> Optional['HTMLFormElement']:
    def on_event_pre(self, e: Event) -> None:
    def defaultChecked(self) -> bool:
    def defaultChecked(self, value: bool) -> None:
    def defaultValue(self) -> _AttrValueType:
    def defaultValue(self, value: str) -> None:
    def _is_same_group(self, node: Element) -> bool:
    def _find_root(self) -> Node:
    def _find_grouped_nodes(self) -> NodeList:
    def htmlFor(self) -> _AttrValueType:
    def htmlFor(self, value: str) -> None:
    def control(self) -> Optional[HTMLElement]:
    def __init__(self, *args: Any, **kwargs: Any) -> None:
    def on_event_pre(self, e: Event) -> None:
    def length(self) -> int:
    def options(self) -> NodeList:
    def selectedOptions(self) -> NodeList:
    def on_event_pre(self, e: Event) -> None: class HTMLAnchorElement(HTMLElement):  # noqa: D204
    """HTMLAnchorElement class (<a></a> tag)."""
    _special_attr_string = ['href', 'name', 'rel', 'src', 'target'] class HTMLButtonElement(HTMLElement):  # noqa: D204
    """HTMLButtonElement class (<button></button> tag)."""
    _special_attr_string = ['name', 'value']
    _special_attr_boolean = ['disabled'] class HTMLFormElement(HTMLElement):  # noqa: D204
    """HTMLFormElement class (<form></form> tag)."""
    _special_attr_string = ['name'] class HTMLIFrameElement(HTMLElement):  # noqa: D204
    """HTMLIFrameElement class (<iframe></iframe> tag)."""
    _special_attr_string = ['height', 'name', 'src', 'target', 'width'] class HTMLInputElement(HTMLElement, FormControlMixin):
    """HTMLInputElement class (<input></input> tag)."""

    _special_attr_string = ['height', 'name', 'src', 'value', 'width']
    _special_attr_boolean = ['checked', 'disabled', 'multiple', 'readonly',
                             'required']

    def on_event_pre(self, e: Event) -> None:
        """Set values set on browser before calling event listeners."""
        super().on_event_pre(e)
        ct_msg = e.init.get('currentTarget', dict())
        if e.type in ('input', 'change'):
            # Update user inputs
            if self.type.lower() == 'checkbox':
                self._set_attribute('checked', ct_msg.get('checked'))
            elif self.type.lower() == 'radio':
                self._set_attribute('checked', ct_msg.get('checked'))
                for other in self._find_grouped_nodes():
                    if other is not self:
                        other._remove_attribute('checked')
            else:
                self._set_attribute('value', ct_msg.get('value'))

    @property
    def defaultChecked(self) -> bool:
        """Property is this control checked by default."""
        return bool(self.getAttribute('defaultChecked'))

    @defaultChecked.setter
    def defaultChecked(self, value: bool) -> None:
        if value:
            self.setAttribute('defaultChecked', True)
            self.checked = True
        else:
            self.removeAttribute('defaultChecked')
            self.checked = False

    @property
    def defaultValue(self) -> _AttrValueType:
        """Defatul value of this node."""
        return self.getAttribute('defaultValue')

    @defaultValue.setter
    def defaultValue(self, value: str) -> None:
        self.setAttribute('defaultValue', value)
        self.value = value

    def _is_same_group(self, node: Element) -> bool:
        tag = self.tagName
        name = self.getAttribute('name')
        return (tag == node.tagName and
                node is not self and
                name == node.getAttribute('name'))

    def _find_root(self) -> Node:
        doc = self.ownerDocument
        if doc is not None:
            return doc
        p = self
        while p.parentNode is not None:
            p = p.parentNode
        return p

    def _find_grouped_nodes(self) -> NodeList:
        p = self._find_root()
        return p.getElementsBy(self._is_same_group) class HTMLLabelElement(HTMLElement, FormControlMixin):
    """HTMLLabelElement class (<label></label> tag)."""

    @property
    def htmlFor(self) -> _AttrValueType:
        """Retrun ``for`` attribute value."""
        return self.getAttribute('for')

    @htmlFor.setter
    def htmlFor(self, value: str) -> None:
        self.setAttribute('for', value)

    @property
    def control(self) -> Optional[HTMLElement]:
        """Return related HTMLElement object."""
        id = self.getAttribute('for')
        if id:
            if self.ownerDocument:
                return self.ownerDocument.getElementById(id)
            elif isinstance(id, str):
                from wdom.document import getElementById
                return getElementById(id)
            else:
                raise TypeError('"for" attribute must be string')
        return None class HTMLOptGroupElement(HTMLElement, FormControlMixin):  # noqa: D204
    """HTMLOptionElement class (<optgroup></optgroup> tag)."""
    _special_attr_string = ['label']
    _special_attr_boolean = ['disabled'] class HTMLOptionElement(HTMLElement, FormControlMixin):  # noqa: D204
    """HTMLOptionElement class (<option></option> tag)."""
    _special_attr_string = ['label', 'value']
    _special_attr_boolean = ['defaultSelected', 'disabled', 'selected'] class HTMLScriptElement(HTMLElement):  # noqa: D204
    """HTMLScriptElement class (<script></script> tag).

    In this tag, all inner contents are not escaped.
    """
    _special_attr_string = ['charset', 'src']
    _special_attr_boolean = ['async', 'defer']
    _should_escape_text = False class HTMLSelectElement(HTMLElement, FormControlMixin):
    """HTMLSelectElement class (<select></select> tag)."""

    _special_attr_string = ['name', 'size', 'value']
    _special_attr_boolean = ['disabled', 'multiple', 'required']

    def __init__(self, *args: Any, **kwargs: Any) -> None:
        self._selected_options = []  # type: List[str]
        super().__init__(*args, **kwargs)

    def on_event_pre(self, e: Event) -> None:
        """Set values set on browser before calling event listeners."""
        super().on_event_pre(e)
        ct_msg = e.init.get('currentTarget', dict())
        if e.type in ('input', 'change'):
            self._set_attribute('value', ct_msg.get('value'))
            _selected = ct_msg.get('selectedOptions', [])
            self._selected_options.clear()
            for opt in self.options:
                if opt.wdom_id in _selected:
                    self._selected_options.append(opt)
                    opt._set_attribute('selected', True)
                else:
                    opt._remove_attribute('selected')

    @property
    def length(self) -> int:
        """Return number of options in this node."""
        return len(self.options)

    @property
    def options(self) -> NodeList:
        """Return all option nodes in this node."""
        return self.getElementsByTagName('option')

    @property
    def selectedOptions(self) -> NodeList:
        """Return all selected option nodes."""
        return NodeList(list(opt for opt in self.options if opt.selected)) class HTMLStyleElement(HTMLElement):  # noqa: D204
    """HTMLStyleElement class (<style></style> tag).

    In this tag, all inner contents are not escaped.
    """
    _special_attr_boolean = ['disabled', 'scoped']
    _should_escape_text = False class HTMLTextAreaElement(HTMLElement, FormControlMixin):  # noqa: D204
    """HTMLTextAreaElement class (<textarea></textarea> tag)."""
    _special_attr_string = ['height', 'name', 'src', 'value', 'width']
    _special_attr_boolean = ['disabled']
    defaultValue = HTMLElement.textContent

    def on_event_pre(self, e: Event) -> None:
        """Set values set on browser before calling event listeners."""
        super().on_event_pre(e)
        ct_msg = e.init.get('currentTarget', dict())
        if e.type in ('input', 'change'):
            # Update user inputs
            self._set_text_content(ct_msg.get('value') or '') class Node(AbstractNode):
    """Base Class for Node interface."""

    @property
    def connected(self) -> bool:
        """When this instance has any connection, return True."""
        return False

    def __init__(self, parent: AbstractNode = None) -> None:
        """Initialize node object with parent node.

        :param Node parent: parent node.
        """
        super().__init__()  # Need to call init in multiple inheritce
        self.__children = list()  # type: List[Node]
        self.__parent = None
        if parent:
            parent.appendChild(self)

    def __bool__(self) -> bool:
        """Return always True."""
        return True

    def __len__(self) -> int:
        """Return number of child nodes."""
        return self.length

    def __contains__(self, other: AbstractNode) -> bool:
        return other in self.__children

    # DOM Level 1
    @property
    def length(self) -> int:
        """Return number of child nodes."""
        return len(self.childNodes)

    @property
    def parentNode(self) -> Optional[AbstractNode]:
        """Return parent node.

        If this node does not have a parent, return ``None``.
        """
        return self.__parent

    @property
    def childNodes(self) -> 'NodeList':
        """Return child nodes of this node.

        Returned object is an instance of NodeList, which is a list like object
        but not support any modification. NodeList is a **live object**, which
        means that changes on this node is reflected to the object.
        """
        return NodeList(self.__children)

    @property
    def firstChild(self) -> Optional[AbstractNode]:
        """Return the first child node.

        If this node does not have any child, return ``None``.
        """
        if self.hasChildNodes():
            return self.childNodes[0]
        return None

    @property
    def lastChild(self) -> Optional[AbstractNode]:
        """Return the last child node.

        If this node does not have any child, return ``None``.
        """
        if self.hasChildNodes():
            return self.childNodes[-1]
        return None

    @property
    def previousSibling(self) -> Optional[AbstractNode]:
        """Return the previous sibling of this node.

        If there is no previous sibling, return ``None``.
        """
        parent = self.parentNode
        if parent is None:
            return None
        return parent.childNodes.item(parent.childNodes.index(self) - 1)

    @property
    def nextSibling(self) -> Optional[AbstractNode]:
        """Return the next sibling of this node.

        If there is no next sibling, return ``None``.
        """
        parent = self.parentNode
        if parent is None:
            return None
        return parent.childNodes.item(parent.childNodes.index(self) + 1)

    # DOM Level 2
    @property
    def ownerDocument(self) -> Optional[AbstractNode]:
        """Return the owner document of this node.

        Owner document is an ancestor document node of this node. If this node
        (or node tree including this node) is not appended to any document
        node, this property returns ``None``.

        :rtype: Document or None
        """
        if self.nodeType == Node.DOCUMENT_NODE:
            return self
        elif self.parentNode:
            return self.parentNode.ownerDocument
        return None

    # Methods
    def _append_document_fragment(self, node: AbstractNode) -> AbstractNode:
        for c in tuple(node.childNodes):
            self._append_child(c)
        return node

    def _append_element(self, node: AbstractNode) -> AbstractNode:
        if node.parentNode:
            node.parentNode.removeChild(node)
        self.__children.append(node)
        node.__parent = self
        return node

    def _append_child(self, node: AbstractNode) -> AbstractNode:
        if not isinstance(node, Node):
            raise TypeError(
                'appndChild() only accepts a Node instance, but get {}. '
                'If you want to add string or mupltiple nodes once, '
                'use append() method instead.'.format(type(node)))
        if node.nodeType == Node.DOCUMENT_FRAGMENT_NODE:
            return self._append_document_fragment(node)
        return self._append_element(node)

    def appendChild(self, node: AbstractNode) -> AbstractNode:
        """Append the node at the last of this child nodes."""
        return self._append_child(node)

    def index(self, node: AbstractNode) -> int:
        """Return index of the node.

        If the node is not a child of this node, raise ``ValueError``.
        """
        if node in self.childNodes:
            return self.childNodes.index(node)
        elif isinstance(node, Text):
            for i, n in enumerate(self.childNodes):
                # should consider multiple match?
                if isinstance(n, Text) and n.data == node:
                    return i
        raise ValueError('node is not in this node')

    def _insert_document_fragment_before(self, node: AbstractNode,
                                         ref_node: AbstractNode
                                         ) -> AbstractNode:
        for c in tuple(node.childNodes):
            self._insert_before(c, ref_node)
        return node

    def _insert_element_before(self, node: AbstractNode,
                               ref_node: AbstractNode) -> AbstractNode:
        if node.parentNode:
            node.parentNode.removeChild(node)
        self.__children.insert(self.index(ref_node), node)
        node.__parent = self
        return node

    def _insert_before(self, node: AbstractNode, ref_node:
                       AbstractNode) -> AbstractNode:
        if not isinstance(node, Node):
            raise TypeError(
                'insertBefore() only accepts a Node instance, but get {}.'
                'If you want to insert string or mupltiple nodes, '
                'use ref_node.before() instead.'.format(type(node)))
        if node.nodeType == Node.DOCUMENT_FRAGMENT_NODE:
            return self._insert_document_fragment_before(node, ref_node)
        return self._insert_element_before(node, ref_node)

    def insertBefore(self, node: AbstractNode,
                     ref_node: AbstractNode) -> AbstractNode:
        """Insert a node just before the reference node."""
        return self._insert_before(node, ref_node)

    def hasChildNodes(self) -> bool:
        """Return True if this node has child nodes, otherwise return False."""
        return bool(self.childNodes)

    def _remove_child(self, node: AbstractNode) -> AbstractNode:
        if node not in self.__children:
            raise ValueError('node to be removed is not a child of this node.')
        self.__children.remove(node)
        node.__parent = None
        return node

    def removeChild(self, node: AbstractNode) -> AbstractNode:
        """Remove a node from this node.

        If node is not a child of this node, raise ``ValueError``.
        """
        return self._remove_child(node)

    def _replace_child(self, new_child: AbstractNode,
                       old_child: AbstractNode) -> AbstractNode:
        self._insert_before(new_child, old_child)
        return self._remove_child(old_child)

    def replaceChild(self, new_child: AbstractNode,
                     old_child: AbstractNode) -> AbstractNode:
        """Replace an old child with new child."""
        return self._replace_child(new_child, old_child)

    def hasAttributes(self) -> bool:
        """Return True if this node has attributes."""
        return hasattr(self, 'attributes') and bool(self.attributes)

    def _clone_node(self) -> 'Node':
        clone = type(self)()
        return clone

    def _clone_node_deep(self) -> 'Node':
        clone = self._clone_node()
        for child in self.childNodes:
            clone.appendChild(child._clone_node_deep())
        return clone

    def cloneNode(self, deep: bool=False) -> AbstractNode:
        """Return new copy of this node.

        If optional argument ``deep`` is specified and is True, new node has
        clones of child nodes of this node (if presents).
        """
        if deep:
            return self._clone_node_deep()
        return self._clone_node()

    __copy__ = _clone_node  # alias

    def __deepcopy__(self, memo: Any) -> 'Node':
        return self.cloneNode(True)

    def _empty(self) -> None:
        for child in tuple(self.__children):
            self._remove_child(child)

    def empty(self) -> None:
        """[Not Standard] Remove all child nodes from this node.

        This is equivalent to ``node.textContent = ''``.
        """
        self._empty()

    def _get_text_content(self) -> str:
        return ''.join(child.textContent for child in self.childNodes)

    def _set_text_content(self, value: str) -> None:
        self._empty()
        if value:
            self._append_child(Text(value))

    @property
    def textContent(self) -> str:
        """Return text contents of this node and all chid nodes.

        When any value is set to this property, all child nodes are removed and
        new value is set as a text node.
        """
        return self._get_text_content()

    @textContent.setter
    def textContent(self, value: str) -> None:
        """Remove all child nodes and set new text."""
        self._set_text_content(value) class NodeList(Sequence[Node]):
    """Collection of Node objects."""

    def __init__(self, nodes: Sequence[Node]) -> None:
        """Initialize NodeList by iterable `nodes`."""
        self.__nodes = nodes

    def __getitem__(self, index: int) -> Node:  # type: ignore
        """Get `index`-th node."""
        return self.__nodes[index]

    def __len__(self) -> int:
        return len(self.__nodes)

    def __contains__(self, other: object) -> bool:
        return other in self.__nodes

    def __iter__(self) -> Iterator[AbstractNode]:
        for n in self.__nodes:
            yield n

    @property
    def length(self) -> int:
        """Return number of nodes in this list."""
        return len(self)

    def item(self, index: int) -> Optional[Node]:
        """Return item with the index.

        If the index is negative number or out of the list, return None.
        """
        if not isinstance(index, int):
            raise TypeError(
                'Indeces must be integer, not {}'.format(type(index)))
        return self.__nodes[index] if 0 <= index < self.length else None

    def index(self, node: Node) -> int:  # type: ignore
        """Get index of the node."""
        return self.__nodes.index(node) class Comment(CharacterData):
    """Comment node class."""

    nodeType = Node.COMMENT_NODE
    nodeName = '#comment'

    @property
    def html(self) -> str:
        """Return html representation."""
        return ''.join(('<!--', self.data, '-->')) class RawHtml(Text):
    """Very similar to ``Text`` class, but contents are always not escaped.

    This node is [NOT DOM Standard].
    """

    @property
    def html(self) -> str:
        """Return html representation."""
        return self.data class Text(CharacterData):
    """Node class to wrap text contents."""

    nodeType = Node.TEXT_NODE
    nodeName = '#text'

    @property
    def html(self) -> str:
        """Return html-escaped string representation of this node."""
        if self.parentNode and self.parentNode._should_escape_text:
            return html.escape(self.data)
        return self.data class WdomElement(HTMLElement, WebEventTarget, metaclass=WdomElementMeta):
    """WdomElement class.

    This class provides main features to synchronously control browser DOM
    node.

    Additionally, this class provides shortcut properties to handle class
    attributes.
    """

    _elements_with_wdom_id = WeakValueDictionary(
    )  # type: WeakValueDictionary[_WdomIdType, WdomElement]
    _parser_class = WdomElementParser  # type: Type[ElementParser]

    #: str and list of strs are acceptale.
    class_ = ''
    #: Inherit classes defined in super class or not.
    #: By default, this variable is True.
    inherit_class = True

    @property
    def wdom_id(self) -> str:
        """Get wdom_id attribute.

        This attribute is used to relate python node and browser DOM node.
        """
        return self.__wdom_id

    @property
    def rimo_id(self) -> str:
        """[Deprecated] Alias to `wdom_id`.

        rimo_id is renamed to `wdom_id`.
        """
        warnings.warn('rimo_id is renamed to wdom_id.', DeprecationWarning)
        return self.wdom_id

    @property
    def connected(self) -> bool:
        """When this instance has any connection, return True."""
        return bool(server.is_connected() and self.ownerDocument)

    def __init__(self, *args: Any, parent: 'WdomElement' = None,
                 wdom_id: _WdomIdType = None, **kwargs: Any) -> None:
        if wdom_id is None:
            self.__wdom_id = str(id(self))
        else:
            self.__wdom_id = str(wdom_id)
        super().__init__(*args, **kwargs)
        # use super class to set wdom_id
        self._elements_with_wdom_id[self.wdom_id] = self
        self.addEventListener('mount', self._on_mount)
        if parent:
            parent.appendChild(self)

    def _clone_node(self) -> HTMLElement:
        clone = super()._clone_node()
        for c in self.classList:
            clone.addClass(c)
        return clone

    # Hanlde attributes
    def _get_attrs_by_string(self) -> str:
        res = 'wdom_id="{}"'.format(self.wdom_id)
        attrs = super()._get_attrs_by_string()
        if attrs:
            return ' '.join([res, attrs])
        return res

    def _set_attribute(self, attr: str, value: _AttrValueType) -> None:
        if attr == 'wdom_id':
            raise ValueError('Cannot change wdom_id')
        super()._set_attribute(attr, value)

    def __getitem__(self, attr: Union[str, int]
                    ) -> Union[Node, _AttrValueType]:
        """Get/Set/Remove access by subscription (node['attr'])."""
        if isinstance(attr, int):
            return self.childNodes[attr]
        return self.getAttribute(attr)

    def __setitem__(self, attr: str, val: _AttrValueType) -> None:
        self.setAttribute(attr, val)

    def __delitem__(self, attr: str) -> None:
        self.removeAttribute(attr)

    @classmethod
    def get_class_list(cls) -> DOMTokenList:
        """Get class-level class list, including all super class's."""
        cl = []
        cl.append(DOMTokenList(cls, cls.class_))
        if cls.inherit_class:
            for base_cls in cls.__bases__:
                if issubclass(base_cls, WdomElement):
                    cl.append(base_cls.get_class_list())
        # Reverse order so that parent's class comes to front  <- why?
        cl.reverse()
        return DOMTokenList(cls, *cl)

    def getAttribute(self, attr: str) -> _AttrValueType:  # noqa: D102
        if attr == 'class':
            cls = self.get_class_list()
            cls._append(self.classList)
            return cls.toString() if cls else None
        return super().getAttribute(attr)

    def addClass(self, *classes: str) -> None:
        """[Not Standard] Add classes to this node."""
        self.classList.add(*classes)

    def hasClass(self, class_: str) -> bool:  # noqa: D102
        """[Not Standard] Return if this node has ``class_`` class or not."""
        return class_ in self.classList

    def hasClasses(self) -> bool:  # noqa: D102
        """[Not Standard] Return if this node has any classes or not."""
        return len(self.classList) > 0

    def removeClass(self, *classes: str) -> None:
        """[Not Standard] Remove classes from this node."""
        _remove_cl = []
        for class_ in classes:
            if class_ not in self.classList:
                if class_ in self.get_class_list():
                    logger.warning(
                        'tried to remove class-level class: '
                        '{}'.format(class_)
                    )
                else:
                    logger.warning(
                        'tried to remove non-existing class: {}'.format(class_)
                    )
            else:
                _remove_cl.append(class_)
        self.classList.remove(*_remove_cl)

    # Handle child nodes
    def _remove_web(self) -> None:
        self.js_exec('remove')

    def remove(self) -> None:
        """Remove this node from parent's DOM tree."""
        if self.connected:
            self._remove_web()
        self._remove()

    def _empty_web(self) -> None:
        self.js_exec('empty')

    def empty(self) -> None:
        """Remove all child nodes from this node."""
        if self.connected:
            self._empty_web()
        self._empty()

    def _get_child_html(self, child: Node) -> str:
        if isinstance(child, CharacterData):
            # temparary become new parent
            # text node needs to know its parent to escape or not its content
            self._append_child(child)
            html = child.html
            self._remove_child(child)
        else:
            html = getattr(child, 'html', str(child))
        return html

    def _append_child_web(self, child: 'WdomElement') -> Node:
        html = self._get_child_html(child)
        self.js_exec('insertAdjacentHTML', 'beforeend', html)
        return child

    def appendChild(self, child: 'WdomElement') -> Node:
        """Append child node at the last of child nodes.

        If this instance is connected to the node on browser, the child node is
        also added to it.
        """
        if self.connected:
            self._append_child_web(child)
        return self._append_child(child)

    def _insert_before_web(self, child: Node, ref_node: Node) -> Node:
        html = self._get_child_html(child)
        if isinstance(ref_node, WdomElement):
            ref_node.js_exec('insertAdjacentHTML', 'beforebegin', html)
        else:
            index = self.index(ref_node)
            self.js_exec('insert', index, html)
        return child

    def insertBefore(self, child: Node, ref_node: Node) -> Node:
        """Insert new child node before the reference child node.

        If the reference node is not a child of this node, raise ValueError. If
        this instance is connected to the node on browser, the child node is
        also added to it.
        """
        if self.connected:
            self._insert_before_web(child, ref_node)
        return self._insert_before(child, ref_node)

    def _remove_child_web(self, child: Node) -> Node:
        if child in self.childNodes:
            if isinstance(child, WdomElement):
                self.js_exec('removeChildById', child.wdom_id)
            else:
                self.js_exec('removeChildByIndex', self.index(child))
        return child

    def removeChild(self, child: Node) -> Node:
        """Remove the child node from this node.

        If the node is not a child of this node, raise ValueError.
        """
        if self.connected:
            self._remove_child_web(child)
        return self._remove_child(child)

    def _replace_child_web(self, new_child: Node, old_child: Node) -> None:
        html = self._get_child_html(new_child)
        if isinstance(old_child, WdomElement):
            self.js_exec('replaceChildById', html, old_child.wdom_id)
        elif old_child.parentNode is not None:
            # old_child will be Text Node
            index = old_child.parentNode.index(old_child)
            # Remove old_child before insert new child
            self._remove_child_web(old_child)
            self.js_exec('insert', index, html)

    def replaceChild(self, new_child: 'WdomElement', old_child: 'WdomElement'
                     ) -> Node:
        """Replace child nodes."""
        if self.connected:
            self._replace_child_web(new_child, old_child)
        return self._replace_child(new_child, old_child)

    async def getBoundingClientRect(self) -> None:
        """Get size of this node on browser."""
        fut = await self.js_query('getBoundingClientRect')
        return fut

    def _set_text_content_web(self, text: str) -> None:
        self.js_exec('textContent', self.textContent)

    @HTMLElement.textContent.setter  # type: ignore
    def textContent(self, text: str) -> None:  # type: ignore
        """Set textContent both on this node and related browser node."""
        self._set_text_content(text)
        if self.connected:
            self._set_text_content_web(text)

    def _set_inner_html_web(self, html: str) -> None:
        self.js_exec('innerHTML', html)

    @HTMLElement.innerHTML.setter  # type: ignore
    def innerHTML(self, html: str) -> None:  # type: ignore
        """Set innerHTML both on this node and related browser node."""
        df = self._parse_html(html)
        if self.connected:
            self._set_inner_html_web(df.html)
        self._empty()
        self._append_child(df)

    @property
    def html_noid(self) -> str:
        """Get html representation of this node without wdom_id."""
        return remove_wdom_id(self.html)

    def click(self) -> None:
        """Send click event."""
        if self.connected:
            self.js_exec('click')
        else:
            # Web上に表示されてれば勝手にブラウザ側からクリックイベント発生する
            # のでローカルのクリックイベント不要
            msg = {'proto': '', 'type': 'click',
                   'currentTarget': {'id': self.wdom_id},
                   'target': {'id': self.wdom_id}}
            e = create_event(msg)
            self._dispatch_event(e)

    def exec(self, script: str) -> None:
        """Execute JavaScript on the related browser node."""
        self.js_exec('eval', script)

    # Window controll
    def scroll(self, x: int, y: int) -> None:  # noqa: D102
        self.js_exec('scroll', x, y)

    def scrollTo(self, x: int, y: int) -> None:  # noqa: D102
        self.js_exec('scrollTo', x, y)

    def scrollBy(self, x: int, y: int) -> None:  # noqa: D102
        self.js_exec('scrollBy', x, y)

    def scrollX(self) -> Awaitable:  # noqa: D102
        return self.js_query('scrollX')

    def scrollY(self) -> Awaitable:  # noqa: D102
        return self.js_query('scrollY')

    def show(self) -> None:
        """[Not Standard] Show this node on browser."""
        self.hidden = False

    def hide(self) -> None:
        """[Not Standard] Hide this node on browser."""
        self.hidden = True
import logging
from collections import Iterable
from typing import Any, Dict, Union, TYPE_CHECKING
from types import new_class
from wdom.element import _AttrValueType
from wdom.element import (
    HTMLAnchorElement,
    HTMLButtonElement,
    HTMLFormElement,
    HTMLIFrameElement,
    HTMLInputElement,
    HTMLLabelElement,
    HTMLOptGroupElement,
    HTMLOptionElement,
    HTMLScriptElement,
    HTMLSelectElement,
    HTMLStyleElement,
    HTMLTextAreaElement,
)
from wdom.node import Node, NodeList
from wdom.node import Comment, RawHtml, Text  # noqa: F401
from wdom.web_node import WdomElement
    from typing import List, Type  # noqa
        MyButton = NewTagClass('MyButton', 'button', (Button,),
                               class_='btn', is_='my-button')
        my_button = MyButton('Click!')
        print(my_button.html)

        >>> <button class="btn" id="111111111" is="my-button">Click!</button>
    """
    if tag is None:
        tag = class_name.lower()
    if not isinstance(type, tuple):
        if isinstance(bases, Iterable):
            bases = tuple(bases)
        elif isinstance(bases, type):
            bases = (bases, )
        else:
            TypeError('Invalid base class: {}'.format(str(bases)))
    kwargs['tag'] = tag
    # Here not use type() function, since it does not support
    # metaclasss (__prepare__) properly.
    cls = new_class(  # type: ignore
        class_name, bases, {}, lambda ns: ns.update(kwargs))
    return cls


class Input(Tag, HTMLInputElement):
    """Base class for ``<input>`` element."""

    tag = 'input'
    #: type attribute; text, button, checkbox, or radio... and so on.
    type_ = ''

    def __init__(self, *args: Any, **kwargs: Any) -> None:
        if self.type_ and 'type' not in kwargs:
            kwargs['type'] = self.type_
        super().__init__(*args, **kwargs)


class Textarea(Tag, HTMLTextAreaElement):  # noqa: D204
    """Base class for ``<textarea>`` element."""
    tag = 'textarea'

    @property
    def value(self) -> str:
        """Get input value of this node.

        This value is used as a default value of this element.
        """
        return self.textContent

    @value.setter
    def value(self, value: str) -> None:
        self.textContent = value


class Script(Tag, HTMLScriptElement):  # noqa: D204
    """Base class for <script> tag.

    Inner contents of this node is not escaped.
    """
    tag = 'script'

    def __init__(self, *args: Any, type: str = 'text/javascript',
                 **kwargs: Any) -> None:
        super().__init__(*args, type=type, **kwargs)


Html = NewTagClass('Html')
Body = NewTagClass('Body')
Meta = NewTagClass('Meta')
Head = NewTagClass('Head')
Link = NewTagClass('Link')
Title = NewTagClass('Title')
Style = NewTagClass('Style', 'style', (Tag, HTMLStyleElement))
Iframe = NewTagClass('Iframe', 'iframe', (Tag, HTMLIFrameElement))

Div = NewTagClass('Div')
Span = NewTagClass('Span')

# Typography
H1 = NewTagClass('H1')
H2 = NewTagClass('H2')
H3 = NewTagClass('H3')
H4 = NewTagClass('H4')
H5 = NewTagClass('H5')
H6 = NewTagClass('H6')

P = NewTagClass('P')
A = NewTagClass('A', 'a', (Tag, HTMLAnchorElement))
Strong = NewTagClass('Strong')
Em = NewTagClass('Em')
U = NewTagClass('U')
Br = NewTagClass('Br')
Hr = NewTagClass('Hr')

Cite = NewTagClass('Cite')
Code = NewTagClass('Code')
Pre = NewTagClass('Pre')

Img = NewTagClass('Img')

# table tags
Table = NewTagClass('Table')
Thead = NewTagClass('Thead')
Tbody = NewTagClass('Tbody')
Tfoot = NewTagClass('Tfoot')
Th = NewTagClass('Th')
Tr = NewTagClass('Tr')
Td = NewTagClass('Td')

# List tags
Ol = NewTagClass('Ol')
Ul = NewTagClass('Ul')
Li = NewTagClass('Li')

# Definition-list tags
Dl = NewTagClass('Dl')
Dt = NewTagClass('Dt')
Dd = NewTagClass('Dd')

# Form controls

Form = NewTagClass('Form', 'form', (Tag, HTMLFormElement))