def __init__(self, size="xl", widgetattributes=None, **kwargs): kwargs["_class"] = kwargs.get("_class", "") + f" bx--search bx--search--{size}" kwargs["data-search"] = True kwargs["role"] = "search" attributes = { "id": "search__" + hg.html_id(self), "_class": "bx--search-input", "type": "text", "placeholder": _("Search"), **(widgetattributes or {}), } super().__init__( hg.LABEL(_("Search"), _class="bx--label", _for=attributes["id"]), hg.INPUT(**attributes), Icon("search", size=16, _class="bx--search-magnifier", aria_hidden="true"), hg.BUTTON( Icon("close", size=20, _class="bx--search-clear"), _class="bx--search-close bx--search-close--hidden", title=_("Clear search input"), aria_label=_("Clear search input"), type="button", ), **kwargs, )
def __init__( self, fieldname, light=False, widgetattributes={}, **attributes, ): self.fieldname = fieldname attributes["_class"] = (attributes.get("_class", "") + " bx--form-item bx--text-input-wrapper") widgetattributes["_class"] = ( widgetattributes.get("_class", "") + f" bx--text-input {'bx--text-input--light' if light else ''}") super().__init__( htmlgenerator.LABEL(_class="bx--label"), htmlgenerator.DIV( htmlgenerator.INPUT(**widgetattributes), _class="bx--text-input__field-wrapper", ), **attributes, ) # for easier reference in the render method: self.label = self[0] self.input = self[1][0]
def __init__( self, fieldname, placeholder="", rows=None, cols=None, light=False, widgetattributes={}, **attributes, ): self.fieldname = fieldname attributes["_class"] = attributes.get("_class", "") + " bx--form-item" widgetattributes["_class"] = ( widgetattributes.get("_class", "") + f" bx--text-area bx--text-area--v2 {'bx--text-area--light' if light else ''}", ) if rows: widgetattributes["rows"] = rows if cols: widgetattributes["cols"] = cols super().__init__( htmlgenerator.LABEL(_class="bx--label"), htmlgenerator.DIV( htmlgenerator.TEXTAREA(placeholder=placeholder, **widgetattributes), _class="bx--text-area__wrapper", ), **attributes, ) # for easier reference in the render method: self.label = self[0] self.input = self[1][0]
def __init__( self, label=None, help_text=None, errors=None, inputelement_attrs=None, boundfield=None, **attributes, ): inputelement_attrs = inputelement_attrs or {} attrs = {} if boundfield: attrs["checked"] = hg.F( lambda c: hg.resolve_lazy(boundfield, c).field.widget. check_test(hg.resolve_lazy(boundfield, c).value())) inputelement_attrs = _combine_lazy_dict(inputelement_attrs, attrs) label = None if label is None else label.label super().__init__( self.get_input_element(inputelement_attrs, errors), hg.LABEL( hg.SPAN(_class="bx--radio-button__appearance"), hg.SPAN(label, _class="bx--radio-button__label-text"), _class="bx--radio-button__label", _for=inputelement_attrs.get("id"), ), help_text, errors, **hg.merge_html_attrs(attributes, {"_class": "bx--radio-button-wrapper"}), )
def __init__( self, size="xl", placeholder=None, widgetattributes=None, backend=None, resultcontainerid=None, show_result_container=True, resultcontainer_onload_js=None, disabled=False, **kwargs, ): """ :param SearchBackendConfig backend: Where and how to get search results """ kwargs["_class"] = kwargs.get("_class", "") + f" bx--search bx--search--{size}" kwargs["data_search"] = True kwargs["role"] = "search" width = kwargs.get("width", None) if width: kwargs["style"] = kwargs.get("style", "") + f"width:{width};" widgetattributes = { "id": "search__" + hg.html_id(self), "_class": "bx--search-input", "type": "text", "placeholder": placeholder or _("Search"), "autocomplete": "off", **(widgetattributes or {}), } if backend: if resultcontainerid is None: resultcontainerid = f"search-result-{hg.html_id((self, backend.url))}" widgetattributes["hx_get"] = backend.url widgetattributes["hx_trigger"] = "changed, click, keyup changed delay:500ms" widgetattributes["hx_target"] = hg.format("#{}", resultcontainerid) widgetattributes["hx_indicator"] = hg.format( "#{}-indicator", resultcontainerid ) widgetattributes["name"] = backend.query_parameter self.close_button = _close_button(resultcontainerid, widgetattributes) super().__init__( hg.DIV( hg.LABEL(_("Search"), _class="bx--label", _for=widgetattributes["id"]), hg.INPUT(**widgetattributes), _search_icon(), self.close_button, hg.If(backend is not None, _loading_indicator(resultcontainerid)), **kwargs, ), hg.If( backend is not None and show_result_container, _result_container(resultcontainerid, resultcontainer_onload_js, width), ), style=hg.If(disabled, hg.BaseElement("display: none")), )
def __init__( self, fieldname, placeholder="", light=False, short=False, simple=False, widgetattributes={}, **attributes, ): self.fieldname = fieldname attributes["_class"] = attributes.get("_class", "") + " bx--form-item" picker_attribs = ( {} if simple else {"data-date-picker": True, "data-date-picker-type": "single"} ) widgetattributes["_class"] = ( widgetattributes.get("_class", "") + " bx--date-picker__input" ) input = htmlgenerator.INPUT( placeholder=placeholder, type="text", **widgetattributes, ) self.input = input if not simple: input.attributes["data-date-picker-input"] = True input = htmlgenerator.DIV( input, Icon( "calendar", size=16, _class="bx--date-picker__icon", data_date_picker_icon="true", ), _class="bx--date-picker-input__wrapper", ) super().__init__( htmlgenerator.DIV( htmlgenerator.DIV( htmlgenerator.LABEL(_class="bx--label"), input, _class="bx--date-picker-container", ), _class="bx--date-picker" + (" bx--date-picker--simple" if simple else "bx--date-picker--single") + (" bx--date-picker--short" if short else "") + (" bx--date-picker--light" if light else ""), **picker_attribs, ), **attributes, ) # for easier reference in the render method: self.label = self[0][0][0] self.simple = simple
def __init__( self, fieldname, widgetattributes={}, **attributes, ): self.fieldname = fieldname attributes["_class"] = (attributes.get("_class", "") + " bx--form-item bx--checkbox-wrapper") widgetattributes["_class"] = (widgetattributes.get("_class", "") + " bx--checkbox") widgetattributes["type"] = "checkbox" self.input = htmlgenerator.INPUT(**widgetattributes) self.label = htmlgenerator.LABEL(self.input, _class="bx--checkbox-label") super().__init__(self.label, **attributes)
def __init__( self, label=None, help_text=None, errors=None, inputelement_attrs=None, boundfield=None, **attributes, ): inputelement_attrs = inputelement_attrs or {} attrs = {} if boundfield: attrs["checked"] = hg.F( lambda c: hg.resolve_lazy(boundfield, c).field.widget. check_test(hg.resolve_lazy(boundfield, c).value())) attrs["value"] = None inputelement_attrs = _combine_lazy_dict(inputelement_attrs, attrs) # labels for checkboxes are treated a bit different, need to use plain value label = hg.F(lambda c, label=label: getattr(hg.resolve_lazy(label, c), "label", label)) required = hg.F( lambda c, label=label: hg.resolve_lazy(label, c) is not None) super().__init__( hg.LABEL( self.get_input_element(inputelement_attrs, errors), label, hg.If(inputelement_attrs.get("required"), hg.If(required, REQUIRED_LABEL)), _class=hg.BaseElement( "bx--checkbox-label", hg.If(inputelement_attrs.get("disabled"), " bx--label--disabled"), ), data_contained_checkbox_state=hg.If( inputelement_attrs.get("checked"), "true", "false", ), data_invalid=hg.If(getattr(errors, "condition", False), True), ), help_text, errors, **hg.merge_html_attrs(attributes, {"_class": "bx--checkbox-wrapper"}), )
def __init__( self, label, offlabel=_("Off"), onlabel=_("On"), help_text=None, errors=None, disabled=None, required=None, widgetattributes={}, **attributes, ): attributes["_class"] = attributes.get("_class", "") + " bx--form-item" widgetattributes["_class"] = (widgetattributes.get("_class", "") + " bx--toggle-input") widgetattributes["type"] = "checkbox" widgetattributes["id"] = widgetattributes.get("id", None) or hg.html_id(self) self.input = hg.INPUT(**widgetattributes) self.label = hg.LABEL( label, hg.If(required, REQUIRED_LABEL), hg.SPAN( hg.SPAN(offlabel, _class="bx--toggle__text--off", aria_hidden="true"), hg.SPAN(onlabel, _class="bx--toggle__text--on", aria_hidden="true"), _class="bx--toggle__switch", ), _class=hg.BaseElement( "bx--label bx--toggle-input__label", hg.If(disabled, " bx--label--disabled"), ), _for=widgetattributes["id"], ) super().__init__( self.input, self.label, HelpText(help_text), ErrorList(errors), **attributes, )
def __init__(self, label, _for=None, required=None, disabled=None, **kwargs): self.label = label super().__init__( label, hg.LABEL( label, hg.If(required, REQUIRED_LABEL), _for=_for, _class=hg.BaseElement( "bx--label", hg.If(disabled, " bx--label--disabled"), ), **kwargs, ), )
def with_toolbar( self, title: Any, helper_text: Any = None, primary_button: Optional[Button] = None, bulkactions: Iterable[Link] = (), pagination_config: Optional[PaginationConfig] = None, checkbox_for_bulkaction_name: str = "_selected", search_urlparameter: Optional[str] = None, settingspanel: Any = None, ): """ wrap this datatable with title and toolbar title: table title helper_text: sub title primary_button: bread.layout.button.Button instance bulkactions: List of bread.utils.links.Link instances. Will send a post or a get (depending on its "method" attribute) to the target url the sent data will be a form with the selected checkboxes as fields if the head-checkbox has been selected only that field will be selected. """ checkboxallid = f"datatable-check-{hg.html_id(self)}" header: List[hg.BaseElement] = [ hg.H4(title, _class="bx--data-table-header__title") ] if helper_text is not None: header.append( hg.P(helper_text, _class="bx--data-table-header__description")) bulkactionlist = [] for link in bulkactions: bulkactionlist.append( Button( link.label, icon=link.iconname, onclick=hg.BaseElement( "submitbulkaction(this.closest('[data-table]'), '", link.href, "', method='GET')", ), ), ) if bulkactions: self.head.insert( 0, hg.TH( hg.INPUT( data_event="select-all", id=checkboxallid, _class="bx--checkbox", type="checkbox", name=checkbox_for_bulkaction_name, value="all", ), hg.LABEL( _for=checkboxallid, _class="bx--checkbox-label", ), _class="bx--table-column-checkbox", ), ) self.iterator[0].insert( 0, hg.TD( hg.INPUT( data_event="select", id=hg.BaseElement( checkboxallid, "-", hg.C(self.iterator.loopvariable + "_index"), ), _class="bx--checkbox", type="checkbox", name=checkbox_for_bulkaction_name, value=hg.If( hg.F(lambda c: hasattr( c[self.iterator.loopvariable], "pk")), hg.C(f"{self.iterator.loopvariable}.pk"), hg.C(f"{self.iterator.loopvariable}_index"), ), ), hg.LABEL( _for=hg.BaseElement( checkboxallid, "-", hg.C(self.iterator.loopvariable + "_index"), ), _class="bx--checkbox-label", aria_label="Label name", ), _class="bx--table-column-checkbox", ), ) return hg.DIV( hg.DIV(*header, _class="bx--data-table-header"), hg.SECTION( hg.DIV( hg.DIV( *(bulkactionlist + [ Button( _("Cancel"), data_event="action-bar-cancel", _class="bx--batch-summary__cancel", ) ]), _class="bx--action-list", ), hg.DIV( hg.P( hg.SPAN(0, data_items_selected=True), _(" items selected"), _class="bx--batch-summary__para", ), _class="bx--batch-summary", ), _class="bx--batch-actions", aria_label=_("Table Action Bar"), ), hg.DIV( searchbar(search_urlparameter) if search_urlparameter else None, Button( icon="settings--adjust", buttontype="ghost", onclick=""" let settings = this.parentElement.parentElement.parentElement.querySelector('.settingscontainer'); settings.style.display = settings.style.display == 'block' ? 'none' : 'block'; event.stopPropagation()""", ) if settingspanel else None, primary_button or None, _class="bx--toolbar-content", ), _class="bx--table-toolbar", ), hg.DIV( hg.DIV( hg.DIV( settingspanel, _class="bx--tile raised", style="margin: 0; padding: 0", ), _class="settingscontainer", style= "position: absolute; z-index: 999; right: 0; display: none", onload= "document.addEventListener('click', (e) => {this.style.display = 'none'})", ), style="position: relative", onclick="event.stopPropagation()", ), self, Pagination.from_config(pagination_config) if pagination_config else None, _class="bx--data-table-container", data_table=True, )
def __init__( self, label=None, help_text=None, errors=None, inputelement_attrs=None, boundfield=None, **attributes, ): inputelement_attrs = inputelement_attrs or {} uploadbutton = hg.LABEL( hg.SPAN(_("Select file"), role="button"), tabindex=0, _class=hg.BaseElement( "bx--btn bx--btn--tertiary", hg.If(inputelement_attrs.get("disabled"), " bx--btn--disabled"), ), data_file_drop_container=True, disabled=inputelement_attrs.get("disabled"), data_invalid=hg.If(getattr(errors, "condition", False), True), _for=inputelement_attrs.get("id"), ) input = self.get_input_element( inputelement_attrs, errors, onload=""" that = this; document.addEventListener('change', (e) => { that.parentElement.querySelector('[data-file-container]').innerHTML = ''; var widget = new CarbonComponents.FileUploader(that.parentElement); widget._displayFilenames(); widget.setState('edit'); }); """, ) # we can only clear the field if it originates form a django field # otherwise it has no use clearbox = None if boundfield: checkbox_name = hg.F( lambda c: hg.resolve_lazy(boundfield, c).field.widget. clear_checkbox_name(hg.resolve_lazy(boundfield, c).html_name)) checkbox_id = hg.F( lambda c: hg.resolve_lazy(boundfield, c).field.widget. clear_checkbox_id(hg.resolve_lazy(checkbox_name, c))) clearbox = hg.If( self.clearable, hg.INPUT( type="checkbox", name=checkbox_name, id=checkbox_id, style="display: none", ), ) # clearbutton is always used, to allow clearing a just selected field in the browser clearbutton = hg.If( self.clearable, hg.SPAN( hg.BUTTON( Icon("close", size=16), _class="bx--file-close", type="button", aria_label="close", onclick=hg.If( clearbox, hg.format("$('#{}').checked = 'checked';", checkbox_id), ), ), data_for=inputelement_attrs.get("id"), _class="bx--file__state-container", ), ) super().__init__( label, hg.DIV( uploadbutton, input, clearbox, hg.DIV( hg.If( inputelement_attrs.get("value"), hg.SPAN( hg.P( hg.If( hg.F(lambda c: hasattr( hg.resolve_lazy(inputelement_attrs, c). get("value").file, "name", )), hg.A( hg.F(lambda c: os.path.basename( hg.resolve_lazy( inputelement_attrs, c).get( "value").name)), href=hg.F(lambda c: settings.MEDIA_URL + hg.resolve_lazy( inputelement_attrs, c ).get("value").name), ), hg.F(lambda c: os.path.basename( hg.resolve_lazy(inputelement_attrs, c). get("value").name)), ), _class="bx--file-filename", ), clearbutton, _class="bx--file__selected-file", ), ), data_file_container=True, _class="bx--file-container", ), help_text, errors, _class="bx--file", data_file=True, ), **attributes, )
def __init__( self, label=None, help_text=None, errors=None, inputelement_attrs=None, boundfield=None, # for django-form select elements use this choices=None, # for non-django-form select elements use this **attributes, # for non-django-form select elements use this ): inputelement_attrs = inputelement_attrs or {} optgroups = (_optgroups_from_choices( choices, name=inputelement_attrs.get("name"), value=inputelement_attrs.get("value"), ) if choices else _gen_optgroup(boundfield)) def countselected(context): options = [ o for og in hg.resolve_lazy(optgroups, context) for o in og[1] ] return len([o for o in options if o and o["selected"]]) searchfieldid = hg.html_id(self) super().__init__( label, hg.If( inputelement_attrs.get("disabled"), hg.DIV( hg.Iterator( optgroups, "optiongroup", hg.Iterator( hg.C("optiongroup.1"), "option", hg.If(hg.C("option.selected"), Tag(hg.C("option.label"))), ), )), hg.DIV( hg.DIV( hg.DIV( hg.F(countselected), Icon( "close", focusable="false", size=15, role="img", onclick= "clearMultiselect(this.parentElement.parentElement.parentElement)", ), role="button", _class= "bx--list-box__selection bx--list-box__selection--multi bx--tag--filter", tabindex="0", title="Clear all selected items", ), hg.INPUT( id=searchfieldid, _class="bx--text-input", placeholder="Filter...", onclick= "this.parentElement.nextElementSibling.style.display = 'block'", onkeyup= "filterOptions(this.parentElement.parentElement)", ), hg.DIV( Icon("chevron--down", size=16, role="img", focusable="false"), _class="bx--list-box__menu-icon", onclick= "this.parentElement.nextElementSibling.style.display = this.parentElement.nextElementSibling.style.display == 'none' ? 'block' : 'none';", ), role="button", _class="bx--list-box__field", tabindex="0", onload= "window.addEventListener('click', (e) => {this.nextElementSibling.style.display = 'none'})", ), hg.FIELDSET( hg.Iterator( optgroups, "optgroup", hg.Iterator( hg.C("optgroup.1"), "option", hg.DIV( hg.DIV( hg.DIV( hg.LABEL( hg.INPUT( type="checkbox", readonly=True, _class="bx--checkbox", value=hg.C("option.value"), lazy_attributes=hg.C( "option.attrs"), onchange= "updateMultiselect(this.closest('.bx--multi-select'))", checked=hg.C( "option.selected"), name=hg.C("option.name"), ), hg.SPAN( _class= "bx--checkbox-appearance"), hg.SPAN( hg.C("option.label"), _class= "bx--checkbox-label-text", ), title=hg.C("option.label"), _class="bx--checkbox-label", ), _class= "bx--form-item bx--checkbox-wrapper", ), _class= "bx--list-box__menu-item__option", ), _class="bx--list-box__menu-item", ), ), ), _class="bx--list-box__menu", role="listbox", style="display: none", ), _class=hg.BaseElement( "bx--multi-select bx--list-box bx--multi-select--selected bx--combo-box bx--multi-select--filterable", hg.If( inputelement_attrs.get("disabled"), " bx--list-box--disabled", ), ), data_invalid=hg.If(getattr(errors, "condition", None), True), ), ), help_text, errors, **hg.merge_html_attrs( attributes, { "onclick": "event.stopPropagation()", "_class": "bx--list-box__wrapper", }, ), )