class Input(VoidElement): """An HTML <input> element. >>> input_ = Input("text", "description") >>> input_.size = 20 >>> input_.placeholder = "Enter description..." For most input types, a specific sub-class is provided. """ def __init__(self, type_="text", name=""): """Create an HTML input element. The type_ argument sets the HTML type attribute. Possible values are 'text', 'email', 'password', 'submit', etc. For most of these types, a more specific sub-class is provided. The optional name argument sets this input element's name, used when submitting a form. """ super().__init__("input") self.type = type_ self.name = name name = html_attribute("name", default="") value = html_attribute("value", default="") readonly = boolean_html_attribute("readonly") disabled = boolean_html_attribute("disabled") type = html_attribute("type") autocomplete = html_attribute("autocomplete") placeholder = html_attribute("placeholder") size = int_html_attribute("size") focus = boolean_html_attribute("autofocus")
class HeadLink(VoidElement): """HTML meta data link (<link>) element.""" def __init__(self, relation, url): super(HeadLink, self).__init__("link") self.relation = relation self.url = url relation = html_attribute("rel") url = html_attribute("href") @classmethod def create_stylesheet(cls, stylesheet): return cls("stylesheet", stylesheet)
class TextArea(Element): """An HTML <textarea> element. >>> area = TextArea("element-name") >>> area.placeholder = "Placeholder text ..." >>> area.append("Initial text area content.") """ def __init__(self, name=""): super(TextArea, self).__init__("textarea") self.name = name name = html_attribute("name", default="") readonly = boolean_html_attribute("readonly") disabled = boolean_html_attribute("disabled") columns = int_html_attribute("cols") rows = int_html_attribute("rows") placeholder = html_attribute("placeholder")
class Label(Element): """An HTML label (<label>) element. >>> str(Label(Checkbox(), " My Label")) '<label><input type="checkbox"/> My Label</label>' """ def __init__(self, *children): super(Label, self).__init__("label") self.extend(children) for_ = html_attribute("for")
class Script(NonVoidElement): """HTML script (<script>) element. A script element can either point to an external script via the url attribute or it contains the script as element contents: >>> external_script = Script(url="http://www.example.com/script.js") >>> external_script.url 'http://www.example.com/script.js' >>> external_script.script >>> internal_script = Script(script="alert('Hello World!');") >>> internal_script.url >>> internal_script.script "alert('Hello World!');" The type attribute can be overridden: >>> json_script = Script() >>> json_script.type = "application/json" It defaults to Javascript: >>> Script().type 'text/javascript' """ def __init__(self, url=None, script=None): assert url is None or script is None super(Script, self).__init__("script") if url: self.url = url self.script = script type = html_attribute("type", default=MIME_JAVASCRIPT) url = html_attribute("src") def generate_children(self): if self.script: yield self.script
class Form(Element): """An HTML <form> element. >>> form = Form("POST", "/feedback") >>> form.append(Division("Name: ", TextInput("name"))) >>> form.append(Division(SubmitButton("Submit"))) If the form contains file input elements, set multipart to True: >>> form.multipart = True >>> form.encryption_type 'multipart/form-data' """ def __init__(self, method="GET", url=""): super().__init__("form") self.method = method self.url = url method = html_attribute("method", default="GET") url = html_attribute("action", default="") target = html_attribute("target", "_self") encryption_type = html_attribute("enctype", _ENC_TYPE_URL_ENCODED) autocomplete = html_attribute("autocomplete") def set_blank_target(self): self.target = "_blank" @property def multipart(self): return self.encryption_type == _ENC_TYPE_MULTI_PART @multipart.setter def multipart(self, multipart): if multipart: self.encryption_type = _ENC_TYPE_MULTI_PART else: self.encryption_type = _ENC_TYPE_URL_ENCODED
class OptionGroup(Element): """An HTML selection list option group (<optgroup>) element.""" def __init__(self, label): super(OptionGroup, self).__init__("optgroup") self.label = label label = html_attribute("label") disabled = boolean_html_attribute("disabled") def create_option(self, label, value=None): """Create and append an option.""" option = Option(label, value) self.append(option) return option
class Link(Element): """An HTML inline link (<a>) element. >>> link = Link("http://www.example.com/", "caption") >>> link.append(", more") >>> link.url 'http://www.example.com/' >>> str(link) '<a href="http://www.example.com/">caption, more</a>' By default links open in the same window. This can be influenced using the target property: >>> link = Link("/foo/bar") >>> link.target '_self' >>> link.set_blank_target() >>> link.target '_blank' >>> link.target = "my-window" >>> str(link) '<a href="/foo/bar" target="my-window"></a>' Please refer to the HeadLink class for <link> elements. """ def __init__(self, url, *content): super(Link, self).__init__("a") self.url = url self.extend(content) url = html_attribute("href") target = html_attribute("target", "_self") title = html_attribute("title") def set_blank_target(self): self.target = "_blank"
class Select(Element): """An HTML selection list (<select>) element. >>> select = Select("element-name") >>> option1 = select.create_option("Option 1", "v1") >>> option2 = select.create_option("Option 2", "v2", selected=True) >>> option2 is select.selected_option True >>> option2.value == select.selected_value True >>> select.selected_value = "v1" >>> option1 is select.selected_option True It is also possible to use option groups: >>> select = Select() >>> group = select.create_group("Group 1") >>> option1 = group.create_option("Option 1") >>> option2 = group.create_option("Option 2") At the moment, multiple selection lists are not supported. """ def __init__(self, name=""): super().__init__("select") self.name = name name = html_attribute("name", default="") disabled = boolean_html_attribute("disabled") autocomplete = html_attribute("autocomplete") def create_group(self, label): """Create and append an option group.""" group = OptionGroup(label) self.append(group) return group def create_option(self, label, value=None, selected=False): """Create and append an option.""" option = Option(label, value) self.append(option) if selected: self.selected_option = option return option @property def _options_iter(self): for child in self.children.children: if is_element(child, "option"): yield child elif is_element(child, "optgroup"): for sub_child in child.children.children: if is_element(sub_child, "option"): yield sub_child @property def selected_option(self): """Return the first selected option object. If no option is selected, return None. """ for child in self._options_iter: if child.selected: return child return None @selected_option.setter def selected_option(self, option): """Set the selected option object. All other selected options will be deselected. """ for child in self._options_iter: child.selected = False option.selected = True @property def selected_value(self): """Return the value of the first selected option. If no option is selected, return None. """ option = self.selected_option return option.value if option else None @selected_value.setter def selected_value(self, selected_value): """Set the selected option by its value. If no option has the supplied value, raise a ValueError. """ for option in self._options_iter: if option.value == selected_value: self.selected_option = option break else: raise ValueError( "no option with value '{}' found".format(selected_value))
class MyElement(Element): attr = html_attribute("data-attr", default="Bar")
class MyElement(Element): attr = html_attribute("data-attr")