Hide navigation sidebar
Hide table of contents sidebar
Skip to content
Back to top
Toggle table of contents sidebar

# Source code for crispy_forms_foundation.layout.buttons

    """

    References
        * `Foundation 6 Button <https://get.foundation/sites/docs/button.html>`_;
        * `Foundation 6 Button Group <https://get.foundation/sites/docs/button-group.html>`_;

    """  # noqa: E501
    from django.template.loader import render_to_string

    from crispy_forms.utils import render_field, TEMPLATE_PACK
    from crispy_forms import layout as crispy_forms_layout

    __all__ = [
        'ButtonHolder', 'ButtonHolderCallout', 'ButtonGroup',
        'Button', 'Submit', 'Reset',
        'InputButton', 'InputSubmit', 'InputReset',
        'ButtonElement', 'ButtonSubmit', 'ButtonReset',
    ]

    class ButtonHolder(crispy_forms_layout.ButtonHolder):
        """
        It wraps fields in an element ``<div class="button-holder">``.

        This is where you should put Layout objects that render to form buttons
        like Submit. It should only hold ``HTML`` and ``BaseInput`` inherited
        objects.

        Example:

        .. code-block:: python

            ButtonHolder(
                HTML(<span style="display: hidden;">Information Saved</span>),
                Submit('Save', 'Save')
            )
        """
        template = "%s/layout/buttonholder.html"

    class ButtonHolderCallout(ButtonHolder):
        """
        Act like ``ButtonHolder`` but add a ``callout`` class name on the main
        ``div``.
        """
        def __init__(self, field, *args, **kwargs):
            kwargs['css_class'] = kwargs.get('css_class', '')+' callout'
            super().__init__(field, *args, **kwargs)

    class ButtonGroup(crispy_forms_layout.LayoutObject):
        """
        It wraps fields in an element ``<div class="button-group">``.

        This is where you should put Layout objects that render to form buttons
        like Submit. It should only hold `HTML` and `BaseInput` inherited objects.

        Example:

        .. code-block:: python

            ButtonGroup(
                Submit('Save', 'Save'),
                Button('Cancel', 'Cancel'),
            )
        """
        template = "%s/layout/buttongroup.html"

        def __init__(self, *fields, **kwargs):
            self.fields = list(fields)
            self.css_class = kwargs.get('css_class', None)
            self.css_id = kwargs.get('css_id', None)
            self.template = kwargs.get('template', self.template)

        def render(self, form, context, template_pack=TEMPLATE_PACK):
            field_list = []
            template = self.get_template_name(template_pack)

            for field in self.fields:
                field_list.append(
                    render_field(field, form, context,
                                 template_pack=template_pack)
                )

            buttons = render_to_string(template, {
                'buttongroup': self,
                'field_list': field_list,
            })

            return buttons

    class InputButton(crispy_forms_layout.BaseInput):
        """
        Used to create a Submit input descriptor for the {% crispy %} template tag:

        .. code-block:: python

            button = InputButton('Button 1', 'Press Me!')

        .. note:: The first argument is also slugified and turned into the id for
                  the button.
        """
        input_type = 'button'
        field_classes = 'button'

    class Button(InputButton):
        """
        This is the old Button object that inherit from ``InputButton`` for
        backward compatibility.

        If you want to stand for an input button, you are invited to use
        ``InputButton`` instead to avoid problem when ``ButtonElement`` will
        become the new ``Button`` object.
        """
        pass

    class InputSubmit(crispy_forms_layout.BaseInput):
        """
        Used to create a Submit button descriptor for the {% crispy %} template
        tag:

        .. code-block:: python

            submit = Submit('Search the Site', 'search this site')
        """
        input_type = 'submit'
        field_classes = 'submit button'

    class Submit(InputSubmit):
        """
        This is the old Button object that inherit from ``InputSubmit`` for
        backward compatibility.

        If you want to stand for an input button, you are invited to use
        ``InputSubmit`` instead to avoid problem when ``ButtonSubmit`` will
        become the new ``Submit`` object.
        """
        pass

    class InputReset(crispy_forms_layout.BaseInput):
        """
        Used to create a Reset button input descriptor for the ``{% crispy %}``
        template tag:

        .. code-block:: python

            reset = Reset('Reset This Form', 'Revert Me!')
        """
        input_type = 'reset'
        field_classes = 'reset button'

    class Reset(InputReset):
        """
        This is the old Button object that inherit from ``InputReset`` for
        backward compatibility.

        If you want to stand for an input button, you are invited to use
        ``InputReset`` instead to avoid problem when ``ButtonReset`` will
        become the new ``Reset`` object.
        """
        pass

    class ButtonElement(crispy_forms_layout.BaseInput):
        """
        Contrary to ``Button``, ButtonElement purpose use a ``<button>`` element
        to create a clickable form button and accept an argument to add free
        content inside element.

        Advantage of ``<button>`` is to accept almost any HTML content inside
        element.

        .. code-block:: python

            button = ButtonElement('name', 'value',
                                   content="<span>Press Me!</span>")

        .. note::
                * First argument is for ``name`` attribute and also turned into
                  the id for the button;
                * Second argument is for ``value`` attribute and also for element
                  content if not given;
                * Third argument is an optional named argument ``content``, if
                  given it will be appended inside element instead of ``value``.
                  Content string is marked as safe so you can put anything you
                  want;
        """
        template = "%s/layout/basebutton.html"
        input_type = 'button'
        field_classes = 'button'

        def __init__(self, field, *args, **kwargs):
            self.content = kwargs.pop('content', None)
            super(ButtonElement, self).__init__(field, *args, **kwargs)

        def render(self, form, context, template_pack=TEMPLATE_PACK):
            context['button_content'] = self.content
            return super(ButtonElement, self).render(form, context,
                                                     template_pack)

    class ButtonSubmit(ButtonElement):
        """
        Create a submit button following the ``ButtonElement`` behaviors:

        .. code-block:: python

            button = ButtonSubmit('search', 'go-search',
                                  content="<span>Search this site!</span>")

        """
        input_type = 'submit'
        field_classes = 'submit button'

    class ButtonReset(ButtonElement):
        """
        Create a reset button following the ``ButtonElement`` behaviors:

        .. code-block:: python

            button = ButtonReset('reset', 'revert'
                                 content="<span>Revert Me!</span>")

        """
        input_type = 'reset'
        field_classes = 'reset button'