Example #1
0
 def __init__(
     self,
     label=None,
     help_text=None,
     errors=None,
     inputelement_attrs=None,
     boundfield=None,
     **attributes,
 ):
     inputelement_attrs = inputelement_attrs or {}
     super().__init__(
         label,
         hg.DIV(
             self.get_input_element(inputelement_attrs, errors),
             hg.DIV(
                 hg.BUTTON(
                     Icon("caret--up", size=16),
                     _class="bx--number__control-btn up-icon",
                     type="button",
                 ),
                 hg.BUTTON(
                     Icon("caret--down", size=16),
                     _class="bx--number__control-btn down-icon",
                     type="button",
                 ),
                 _class="bx--number__controls",
             ),
             _class="bx--number__input-wrapper",
         ),
         errors,
         help_text,
         data_numberinput=True,
         data_invalid=hg.If(errors.condition, True),
         **hg.merge_html_attrs(attributes, {"_class": "bx--number"}),
     )
Example #2
0
    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,
        )
Example #3
0
    def __init__(self, *labels, selected=0, **wrapperkwargs):
        """
        labels: tuples in the form (label, button-attributes)
                button-attributes will be applied to the generated button for a context label
                data_target can be a CSS-selector of a panel for the according context
        """

        wrapperkwargs["_class"] = (wrapperkwargs.get("_class", "") +
                                   " bx--content-switcher")
        super().__init__(
            *[
                hg.BUTTON(
                    hg.SPAN(label, _class="bx--content-switcher__label"),
                    _class="bx--content-switcher-btn" +
                    (" bx--content-switcher--selected"
                     if i == selected else ""),
                    role="tab",
                    type="button",
                    **kwargs,
                ) for i, (label, kwargs) in enumerate(labels)
            ],
            data_content_switcher=True,
            role="tablist",
            **wrapperkwargs,
        )
Example #4
0
    def __init__(
        self,
        title,
        subtitle,
        kind="info",
        lowcontrast=False,
        hideclosebutton=False,
        hidetimestamp=False,
        **attributes,
    ):
        """
        kind: can be one of "error" "info", "info-square", "success", "warning", "warning-alt"
        """
        assert (
            kind in KIND_ICON_MAPPING
        ), f"kind '{kind}' does not exists, must be one of {KIND_ICON_MAPPING.keys()}"
        self.hidetimestamp = hidetimestamp

        attributes["data-notification"] = True
        attributes["_class"] = (
            attributes.get("_class", "")
            + f" bx--toast-notification bx--toast-notification--{kind}"
        )
        if lowcontrast:
            attributes["_class"] += "  bx--toast-notification--low-contrast"
        attributes["role"] = "alert"

        timestampelem = (
            [
                htmlgenerator.P(
                    _("Time stamp "), _class="bx--toast-notification__caption"
                )
            ]
            if not hidetimestamp
            else []
        )
        children = [
            Icon(
                KIND_ICON_MAPPING[kind],
                size=20,
                _class="bx--toast-notification__icon",
            ),
            htmlgenerator.DIV(
                htmlgenerator.H3(title, _class="bx--toast-notification__title"),
                htmlgenerator.P(subtitle, _class="bx--toast-notification__subtitle"),
                *timestampelem,
                _class="bx--toast-notification__details",
            ),
        ]
        if not hideclosebutton:
            children.append(
                htmlgenerator.BUTTON(
                    Icon("close", size=20, _class="bx--toast-notification__close-icon"),
                    data_notification_btn=True,
                    _class="bx--toast-notification__close-button",
                    aria_label="close",
                )
            )
        super().__init__(*children, **attributes)
    def __init__(
        self,
        links,
        menuiconname="overflow-menu--vertical",
        menuname=None,
        direction="bottom",
        flip=False,
        item_attributes={},
        **attributes,
    ):
        attributes["data-overflow-menu"] = True
        attributes["_class"] = attributes.get("_class",
                                              "") + " bx--overflow-menu"
        item_attributes["_class"] = (item_attributes.get("_class", "") +
                                     " bx--overflow-menu-options__option")

        menuid = hg.F(lambda c: OverflowMenu.MENUID_TEMPLATE % hg.html_id(
            c.get("row", self)))
        triggerid = hg.F(lambda c: (OverflowMenu.MENUID_TEMPLATE % hg.html_id(
            c.get("row", self))) + "-trigger")

        super().__init__(
            hg.BUTTON(
                Icon(menuiconname, size=16),
                _class="bx--overflow-menu__trigger" +
                (" bx--tooltip__trigger bx--tooltip--a11y bx--tooltip--right bx--tooltip--align-start"
                 if menuname is not None else ""),
                aria_haspopup="true",
                aria_expanded="false",
                aria_controls=menuid,
                type="button",
                id=triggerid,
            ),
            hg.DIV(
                hg.UL(
                    hg.Iterator(
                        links,
                        "link",
                        hg.LI(
                            hg.F(asoverflowbutton),
                            **item_attributes,
                        ),
                    ),
                    _class="bx--overflow-menu-options__content",
                ),
                _class="bx--overflow-menu-options" +
                (" bx--overflow-menu--flip" if flip else ""),
                tabindex="-1",
                role="menu",
                aria_labelledby=triggerid,
                data_floating_menu_direction=direction,
                id=menuid,
            ),
            **attributes,
        )
        if menuname is not None:
            self[0].insert(0, hg.SPAN(menuname, _class="bx--assistive-text"))
Example #6
0
    def __init__(
        self,
        item_iterator,
        iteratorclass=htmlgenerator.Iterator,
        menuname=None,
        direction="bottom",
        flip=False,
        item_attributes={},
        **attributes,
    ):
        # making the class inline seems better, I think we can enforce scoping the type to this instance of OverflowMenu
        class MenuItemValueProvider(htmlgenerator.ValueProvider):
            attributename = "item"

        """item_iterator: an iterable which contains bread.menu.Action objects where the onclick value is what will be passed to the onclick attribute of the menu-item (and therefore should be javascript, e.g. "window.location.href='/home'"). All three item_iterator in the tuple can be lazy objects
        iteratorclass: If the Iterator needs additional values in order to generate item_iterator it can be customized and passed here"""
        attributes["data-overflow-menu"] = True
        attributes["_class"] = attributes.get("_class",
                                              "") + " bx--overflow-menu"
        menuid = f"overflow-menu-{hash(id(self))}"
        super().__init__(
            htmlgenerator.BUTTON(
                Icon("overflow-menu--vertical", size=16),
                _class="bx--overflow-menu__trigger" +
                (" bx--tooltip__trigger bx--tooltip--a11y bx--tooltip--right bx--tooltip--align-start"
                 if menuname is not None else ""),
                aria_haspopup="true",
                aria_expanded="false",
                aria_controls=menuid,
                _id=f"{menuid}-trigger",
            ),
            htmlgenerator.DIV(
                htmlgenerator.UL(
                    iteratorclass(
                        item_iterator,
                        MenuItemValueProvider.Binding(OverflowMenuItem)(
                            MenuItemValueProvider, **item_attributes),
                        MenuItemValueProvider,
                    ),
                    _class="bx--overflow-menu-options__content",
                ),
                _class="bx--overflow-menu-options" +
                (" bx--overflow-menu--flip" if flip else ""),
                tabindex="-1",
                role="menu",
                aria_labelledby=f"{menuid}-trigger",
                data_floating_menu_direction=direction,
                id=menuid,
            ),
            **attributes,
        )
        if menuname is not None:
            self[0].insert(
                0, htmlgenerator.SPAN(menuname, _class="bx--assistive-text"))
 def __init__(self, platform, company, searchbar, actions=(), *args, **kwargs):
     super().__init__(
         hg.If(
             HasBreadCookieValue("sidenav-hidden", "true"),
             variable_size_header_part(hg.BaseElement(), company, searchbar, "5rem"),
             variable_size_header_part(
                 hg.SPAN(platform, _class="bx--header__name--prefix"),
                 company,
                 searchbar,
                 "18rem",
             ),
         ),
         hg.DIV(
             hg.If(
                 hg.F(lambda c: c["request"].user.is_authenticated),
                 hg.A(
                     hg.SPAN(
                         hg.C("request.user.get_username"),
                         _class="bx--header__name--prefix",
                     ),
                     _class="bx--header__name",
                     href=reverse("userprofile"),
                     title=hg.C("request.user.get_username"),
                     style="padding: 0; margin-right: 1rem",
                 ),
             ),
             hg.If(
                 hg.F(lambda c: c["request"].user.is_authenticated),
                 hg.BUTTON(
                     Icon(
                         "logout",
                         size=20,
                         _class="bx--navigation-menu-panel-expand-icon",
                         aria_hidden="true",
                     ),
                     Icon(
                         "logout",
                         size=20,
                         _class="bx--navigation-menu-panel-collapse-icon",
                         aria_hidden="true",
                     ),
                     _class="bx--header__menu-trigger bx--header__action",
                     title=_("Logout"),
                     data_navigation_menu_panel_label_expand=_("Logout"),
                     data_navigation_menu_panel_label_collapse=_("Close"),
                     onclick=f"document.location = '{reverse('logout')}'",
                 ),
             ),
             _class="bx--header__global",
         ),
         _class="bx--header",
         data_header=True,
     )
Example #8
0
def _close_button(resultcontainerid, widgetattributes):
    kwargs = {
        "_class": hg.BaseElement(
            "bx--search-close",
            hg.If(widgetattributes.get("value"), None, " bx--search-close--hidden"),
        ),
        "title": _("Clear search input"),
        "aria_label": _("Clear search input"),
        "type": "button",
    }
    if resultcontainerid is not None:
        kwargs["onclick"] = hg.format(
            "document.getElementById('{}').innerHTML = '';", resultcontainerid
        )
    return hg.BUTTON(Icon("close", size=20, _class="bx--search-clear"), **kwargs)
Example #9
0
 def __init__(self, itemvalueproviderclass, **attributes):
     attributes["_class"] = (attributes.get("_class", "") +
                             " bx--overflow-menu-options__option")
     super().__init__(
         htmlgenerator.BUTTON(
             itemvalueproviderclass.Binding(htmlgenerator.DIV)(
                 htmlgenerator.F(lambda e, c: htmlgenerator.BaseElement(
                     Icon(e.item.icon, size=16), e.item.label)
                                 if e.item.icon else e.item.label),
                 _class="bx--overflow-menu-options__option-content",
             ),
             _class="bx--overflow-menu-options__btn",
             role="menuitem",
         ),
         **attributes,
     )
Example #10
0
 def as_header_cell(self, orderingurlparameter="ordering"):
     headcontent = hg.DIV(self.header, _class="bx--table-header-label")
     if self.sortingname:
         headcontent = hg.BUTTON(
             headcontent,
             Icon("arrow--down", _class="bx--table-sort__icon", size=16),
             Icon(
                 "arrows--vertical",
                 _class="bx--table-sort__icon-unsorted",
                 size=16,
             ),
             _class=hg.BaseElement(
                 "bx--table-sort ",
                 sortingclass_for_column(orderingurlparameter,
                                         self.sortingname),
             ),
             data_event="sort",
             **sortinglink_for_column(orderingurlparameter,
                                      self.sortingname),
         )
     return hg.TH(headcontent, lazy_attributes=self.th_attributes)
Example #11
0
    def __init__(self, header: Any, content: Any, **attributes):
        """
        Parameters
        ----------
        header : Any
            the header of the tile that is not hidden under the fold
        content : Any
            the hidden content that only visible when user click to unfold the tile
        **attributes : optional
            keyword arguments representing the specific HTML attributes for the tile
        """

        super().__init__(
            hg.BUTTON(Icon("chevron--down", size="16"),
                      _class="bx--tile__chevron"),
            hg.DIV(
                hg.SPAN(
                    header,
                    data_tile_atf=True,
                    _class="bx--tile-content__above-the-fold",
                ),
                hg.SPAN(
                    content,
                    _class="bx--tile-content__below-the-fold",
                    onclick="event.stopPropagation();",
                    style="cursor: initial",
                ),
                _class="bx--tile-content",
            ),
            **hg.merge_html_attrs(
                attributes,
                {
                    "_class": "bx--tile bx--tile--expandable",
                    "data_tile": "expandable",
                    "tabindex": "0",
                },
            ))
Example #12
0
    def __init__(
        self,
        title,
        subtitle,
        action=None,
        kind="info",
        lowcontrast=False,
        hideclosebutton=False,
        **attributes,
    ):
        """
        action: typle with (action_name, javascript_onclick), e.g. ("Open Google", "windows.location='https://google.com'")
        kind: can be one of "error" "info", "info-square", "success", "warning", "warning-alt"
        """
        assert (
            kind in KIND_ICON_MAPPING
        ), f"kind '{kind}' does not exists, must be one of {KIND_ICON_MAPPING.keys()}"
        assert action is None or (
            len(action) == 2
        ), "action must be a tuple with: (action_name, javascript_onclick)"

        attributes["data-notification"] = True
        attributes["_class"] = (
            attributes.get("_class", "")
            + f" bx--inline-notification bx--inline-notification--{kind}"
        )
        if lowcontrast:
            attributes["_class"] += "  bx--inline-notification--low-contrast"
        attributes["role"] = "alert"

        children = [
            htmlgenerator.DIV(
                Icon(
                    KIND_ICON_MAPPING[kind],
                    size=20,
                    _class="bx--inline-notification__icon",
                ),
                htmlgenerator.DIV(
                    htmlgenerator.P(title, _class="bx--inline-notification__title"),
                    htmlgenerator.P(
                        subtitle, _class="bx--inline-notification__subtitle"
                    ),
                    _class="bx--inline-notification__text-wrapper",
                ),
                _class="bx--inline-notification__details",
            ),
        ]
        if action is not None:
            children.append(
                Button(
                    action[0],
                    onclick=action[1],
                    type="ghost",
                    small=True,
                    _class="bx--inline-notification__action-button",
                )
            )
        if not hideclosebutton:
            children.append(
                htmlgenerator.BUTTON(
                    Icon(
                        "close", size=20, _class="bx--inline-notification__close-icon"
                    ),
                    data_notification_btn=True,
                    _class="bx--inline-notification__close-button",
                    aria_label="close",
                )
            )
        super().__init__(*children, **attributes)
Example #13
0
 def __init__(self, menu: "bread.menu.Menu", **kwargs):
     kwargs["_class"] = hg.BaseElement(
         kwargs.get("_class", ""),
         " bx--side-nav bx--side-nav--rail",
         hg.If(
             HasBreadCookieValue("sidenav-hidden", "true"),
             "",
             " bx--side-nav--expanded",
         ),
     )
     kwargs["data_side_nav"] = True
     super().__init__(
         hg.NAV(
             hg.UL(
                 hg.Iterator(
                     hg.F(lambda c: (i for i in sorted(
                         hg.resolve_lazy(menu, c)._registry.values())
                                     if i.has_permission(c["request"]))),
                     "menugroup",
                     hg.LI(
                         hg.If(
                             hg.F(lambda c: len(c["menugroup"].items) > 1 or
                                  c["menugroup"].force_show),
                             hg.BaseElement(
                                 hg.BUTTON(
                                     hg.DIV(
                                         Icon(hg.C("menugroup.iconname"),
                                              size=16),
                                         _class="bx--side-nav__icon",
                                     ),
                                     hg.SPAN(
                                         hg.C("menugroup.label"),
                                         _class=
                                         "bx--side-nav__submenu-title",
                                     ),
                                     hg.DIV(
                                         Icon("chevron--down", size=16),
                                         _class=
                                         "bx--side-nav__icon bx--side-nav__submenu-chevron",
                                     ),
                                     _class="bx--side-nav__submenu",
                                     type="button",
                                     aria_haspopup="true",
                                     aria_expanded=hg.If(
                                         isactive("menugroup"), "true"),
                                 ),
                                 hg.UL(
                                     hg.Iterator(
                                         hg.F(lambda c: (i for i in sorted(
                                             c["menugroup"].items) if i.
                                                         has_permission(c[
                                                             "request"]))),
                                         "menuitem",
                                         hg.LI(
                                             hg.A(
                                                 hg.SPAN(
                                                     hg.
                                                     C("menuitem.link.label"
                                                       ),
                                                     _class=
                                                     "bx--side-nav__link-text",
                                                 ),
                                                 _class=hg.BaseElement(
                                                     "bx--side-nav__link",
                                                     hg.If(
                                                         isactive(
                                                             "menuitem"),
                                                         " bx--side-nav__link--current",
                                                     ),
                                                 ),
                                                 href=hg.C(
                                                     "menuitem.link.href"),
                                             ),
                                             _class=hg.BaseElement(
                                                 "bx--side-nav__menu-item",
                                                 hg.If(
                                                     isactive("menuitem"),
                                                     " bx--side-nav__menu-item--current",
                                                 ),
                                             ),
                                         ),
                                     ),
                                     _class="bx--side-nav__menu",
                                 ),
                             ),
                             hg.A(
                                 hg.DIV(
                                     Icon(
                                         hg.
                                         C("menugroup.items.0.link.iconname"
                                           ),
                                         size=16,
                                     ),
                                     _class="bx--side-nav__icon",
                                 ),
                                 hg.SPAN(
                                     hg.C("menugroup.items.0.link.label"),
                                     _class="bx--side-nav__link-text",
                                 ),
                                 _class=hg.BaseElement(
                                     "bx--side-nav__link",
                                     hg.If(
                                         isactive("menugroup"),
                                         " bx--side-nav__link--current",
                                     ),
                                 ),
                                 href=hg.C("menugroup.items.0.link.href"),
                             ),
                         ),
                         _class=hg.BaseElement(
                             "bx--side-nav__item",
                             hg.If(isactive("menugroup"),
                                   " bx--side-nav__item--active"),
                         ),
                     ),
                 ),
                 _class="bx--side-nav__items",
             ),
             hg.FOOTER(
                 hg.BUTTON(
                     hg.DIV(
                         Icon(
                             "close",
                             size=20,
                             _class=
                             "bx--side-nav__icon--collapse bx--side-nav-collapse-icon",
                             aria_hidden="true",
                         ),
                         Icon(
                             "chevron--right",
                             size=20,
                             _class=
                             "bx--side-nav__icon--expand bx--side-nav-expand-icon",
                             aria_hidden="true",
                         ),
                         _class="bx--side-nav__icon",
                     ),
                     hg.SPAN(
                         "Toggle the expansion state of the navigation",
                         _class="bx--assistive-text",
                     ),
                     _class="bx--side-nav__toggle",
                     onclick=
                     "setBreadCookie('sidenav-hidden', getBreadCookie('sidenav-hidden', 'false') != 'true');",
                 ),
                 _class="bx--side-nav__footer",
             ),
             _class="bx--side-nav__navigation",
         ),
         **kwargs,
     )
    def __init__(
        self,
        message,
        details,
        kind="info",
        lowcontrast=False,
        hideclosebutton=False,
        hidetimestamp=False,
        autoremove=4.0,
        **attributes,
    ):
        """
        kind: can be one of "error" "info", "info-square", "success", "warning", "warning-alt"
        autoremove: remove notification after ``autoremove`` seconds
        """
        self.hidetimestamp = hidetimestamp

        attributes["data-notification"] = True
        attributes["_class"] = hg.BaseElement(
            attributes.get("_class", ""),
            " bx--toast-notification bx--toast-notification--",
            kind,
            hg.If(lowcontrast, " bx--toast-notification--low-contrast"),
        )
        attributes["role"] = "alert"

        attributes["style"] = hg.BaseElement(
            attributes.get("style", ""),
            ";opacity: 0; animation: ",
            hg.F(lambda c: autoremove * (c["message_index"] + 1)),
            "s ease-in-out notification",
        )
        attributes["onload"] = hg.BaseElement(
            attributes.get("onload", ""),
            ";setTimeout(() => this.style.display = 'None', ",
            hg.F(lambda c: (autoremove * 1000 * (c["message_index"] + 1))),
            ")",
        )

        timestampelem = ([
            hg.P(
                _("Time stamp"), " ", _class="bx--toast-notification__caption")
        ] if not hidetimestamp else [])
        children = [
            Icon(
                hg.F(lambda c: KIND_ICON_MAPPING[hg.resolve_lazy(kind, c)]),
                size=20,
                _class="bx--toast-notification__icon",
            ),
            hg.DIV(
                hg.DIV(message, _class="bx--toast-notification__title"),
                hg.DIV(details, _class="bx--toast-notification__subtitle"),
                *timestampelem,
                _class="bx--toast-notification__details",
            ),
        ]
        children.append(
            hg.If(
                hideclosebutton,
                None,
                hg.BUTTON(
                    Icon("close",
                         size=20,
                         _class="bx--toast-notification__close-icon"),
                    data_notification_btn=True,
                    _class="bx--toast-notification__close-button",
                    aria_label="close",
                ),
            ))
        super().__init__(*children, **attributes)
    def __init__(
        self,
        message,
        details,
        action=None,
        kind="info",
        lowcontrast=False,
        hideclosebutton=False,
        **attributes,
    ):
        """
        action: typle with (action_name, javascript_onclick), e.g. ("Open Google", "windows.location='https://google.com'")
        kind: can be one of "error" "info", "info-square", "success", "warning", "warning-alt"
        """
        if action is not None and (len(action) != 2):
            raise ValueError(
                "action must be a tuple with: (action_name, javascript_onclick)"
            )

        attributes["data-notification"] = True
        attributes["_class"] = hg.BaseElement(
            attributes.get("_class", ""),
            " bx--inline-notification bx--inline-notification--",
            kind,
            hg.If(lowcontrast, " bx--inline-notification--low-contrast"),
        )
        attributes["role"] = "alert"

        children = [
            hg.DIV(
                Icon(
                    hg.F(
                        lambda c: KIND_ICON_MAPPING[hg.resolve_lazy(kind, c)]),
                    size=20,
                    _class="bx--inline-notification__icon",
                ),
                hg.DIV(
                    hg.P(message, _class="bx--inline-notification__title"),
                    hg.P(details, _class="bx--inline-notification__subtitle"),
                    _class="bx--inline-notification__text-wrapper",
                ),
                _class="bx--inline-notification__details",
            ),
        ]
        if action is not None:
            children.append(
                Button(
                    action[0],
                    onclick=action[1],
                    buttontype="ghost",
                    small=True,
                    _class="bx--inline-notification__action-button",
                ))
        children.append(
            hg.If(
                hideclosebutton,
                None,
                hg.BUTTON(
                    Icon("close",
                         size=20,
                         _class="bx--inline-notification__close-icon"),
                    data_notification_btn=True,
                    _class="bx--inline-notification__close-button",
                    aria_label="close",
                ),
            ))
        super().__init__(*children, **attributes)
Example #16
0
    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,
        )
Example #17
0
    def __init__(
            self,
            heading,
            *content,
            label="",
            size="sm",
            buttons=(),
            id=None,
            with_form=False,
            **attributes,
    ):
        """
        heading: Modal title
        content: content elements of the modal, can be empty
        label: small informative label above heading
        size: one of ["xs", "sm", "md", "lg"]
        buttons: buttons displayed on bottom of modal, last button has default focus
                 the attribute "data_modal_close" can be set on an button in order to make it a cancel button

        In order to open the modal just pass self.openerattributes as kwargs to another html element, e.g. a button

            modal = modal.Modal("My Modal", "Hello world")
            button.Button("Model", **modal.openerattributes)

        """
        if size not in Modal.SIZES:
            raise ValueError(
                f"argument 'size' has value {size} but needs to be one of {Modal.SIZES}"
            )
        if buttons and "data_modal_primary_focus" not in buttons[-1].attributes:
            buttons[-1].attributes["data_modal_primary_focus"] = True
        attributes["_class"] = attributes.get("_class", "") + " bx--modal"
        self.id = hg.html_id(self, prefix="modal-") if id is None else id
        self.openerattributes = {
            "data_modal_target": hg.format("#{}", self.id)
        }
        self.contentcontainer = hg.DIV(
            *content,
            _class="bx--modal-content" +
            (" bx--modal-content--with-form" if with_form else ""),
            tabindex=0,
        )
        super().__init__(
            hg.DIV(
                hg.DIV(
                    hg.P(
                        label,
                        _class="bx--modal-header__label",
                    ),
                    hg.P(
                        heading,
                        _class="bx--modal-header__heading",
                    ),
                    hg.BUTTON(
                        Icon(
                            "close",
                            size=16,
                            _class="bx--modal-close__icon",
                            aria_hidden="true",
                        ),
                        _class="bx--modal-close",
                        type="button",
                        data_modal_close=True,
                    ),
                    _class="bx--modal-header",
                ),
                self.contentcontainer,
                hg.DIV(_class="bx--modal-content--overflow-indicator"),
                hg.DIV(
                    *buttons,
                    _class="bx--modal-footer",
                ) if buttons else "",
                _class=f"bx--modal-container  bx--modal-container--{size}",
            ),
            data_modal=True,
            id=self.id,
            role="dialog",
            aria_modal="true",
            tabindex="-1",
            **attributes,
        )