Ability to change modal form backdrop element behavior
By default modal form is closed after clicking outside of it on a dark backdrop (data-backdrop="true"). For the forms with a lot of fields this could lead to a loss of data the user had entered before he has unintentionally clicked outside of the form. So more preferable option for such forms (and workflows/client-side modals) would be data-backdrop="static". DocImpact Change-Id: I56fca9131a4e4d3991d53184ee1332e84138cdc2 Partially-Implements: blueprint form-template-to-view Related-Bug: #1062065
This commit is contained in:
parent
277fc76fb2
commit
a6c364448a
@ -168,6 +168,20 @@ A dictionary containing classes of exceptions which Horizon's centralized
|
||||
exception handling should be aware of. Based on these exception categories,
|
||||
Horizon will handle the exception and display a message to the user.
|
||||
|
||||
``modal_backdrop``
|
||||
------------------
|
||||
|
||||
.. versionadded:: 2014.2(Kilo)
|
||||
|
||||
Default: ``"static"``
|
||||
|
||||
Controls how bootstrap backdrop element outside of modals looks and feels.
|
||||
Valid values are ``"true"`` (show backdrop element outside the modal, close
|
||||
the modal after clicking on backdrop), ``"false"`` (do not show backdrop
|
||||
element, do not close the modal after clicking outside of it) and ``"static"``
|
||||
(show backdrop element outside the modal, do not close the modal after
|
||||
clicking on backdrop).
|
||||
|
||||
``password_validator``
|
||||
----------------------
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
import json
|
||||
import os
|
||||
|
||||
from django.conf import settings
|
||||
from django import http
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.views import generic
|
||||
@ -25,6 +26,35 @@ from horizon import exceptions
|
||||
ADD_TO_FIELD_HEADER = "HTTP_X_HORIZON_ADD_TO_FIELD"
|
||||
|
||||
|
||||
class ModalBackdropMixin(object):
|
||||
"""This mixin class is to be used for together with ModalFormView and
|
||||
WorkflowView classes to augment them with modal_backdrop context data.
|
||||
|
||||
.. attribute: modal_backdrop (optional)
|
||||
|
||||
The appearance and behavior of backdrop under the modal element.
|
||||
Possible options are:
|
||||
* 'true' - show backdrop element outside the modal, close the modal
|
||||
after clicking on backdrop (the default one);
|
||||
* 'false' - do not show backdrop element, do not close the modal after
|
||||
clicking outside of it;
|
||||
* 'static' - show backdrop element outside the modal, do not close
|
||||
the modal after clicking on backdrop.
|
||||
"""
|
||||
modal_backdrop = 'static'
|
||||
|
||||
def __init__(self):
|
||||
super(ModalBackdropMixin, self).__init__()
|
||||
config = getattr(settings, 'HORIZON_CONFIG', {})
|
||||
if 'modal_backdrop' in config:
|
||||
self.modal_backdrop = config['modal_backdrop']
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(ModalBackdropMixin, self).get_context_data(**kwargs)
|
||||
context['modal_backdrop'] = self.modal_backdrop
|
||||
return context
|
||||
|
||||
|
||||
class ModalFormMixin(object):
|
||||
def get_template_names(self):
|
||||
if self.request.is_ajax():
|
||||
@ -47,7 +77,7 @@ class ModalFormMixin(object):
|
||||
return context
|
||||
|
||||
|
||||
class ModalFormView(ModalFormMixin, generic.FormView):
|
||||
class ModalFormView(ModalBackdropMixin, ModalFormMixin, generic.FormView):
|
||||
"""The main view class from which all views which handle forms in Horizon
|
||||
should inherit. It takes care of all details with processing
|
||||
:class:`~horizon.forms.base.SelfHandlingForm` classes, and modal concerns
|
||||
|
@ -33,9 +33,11 @@ horizon.modals.create = function (title, body, confirm, cancel) {
|
||||
cancel = gettext("Cancel");
|
||||
}
|
||||
var template = horizon.templates.compiled_templates["#modal_template"],
|
||||
params = {title: title, body: body, confirm: confirm, cancel: cancel},
|
||||
modal = $(template.render(params)).appendTo("#modal_wrapper");
|
||||
return modal;
|
||||
params = {
|
||||
title: title, body: body, confirm: confirm, cancel: cancel,
|
||||
modal_backdrop: horizon.modals.MODAL_BACKDROP
|
||||
};
|
||||
return $(template.render(params)).appendTo("#modal_wrapper");
|
||||
};
|
||||
|
||||
horizon.modals.success = function (data, textStatus, jqXHR) {
|
||||
|
@ -6,10 +6,10 @@
|
||||
|
||||
{% comment %} Django's JavaScript i18n Implementation {% endcomment %}
|
||||
<script type="text/javascript" src="{% url 'horizon:jsi18n' 'horizon' %}"></script>
|
||||
<script type="text/javascript">var STATIC_URL = "{{ STATIC_URL }}";</script>
|
||||
|
||||
{% comment %} Compress jQuery, Angular, Plugins, Bootstrap, Hogan.js and Horizon-specific JS. {% endcomment %}
|
||||
{% compress js %}
|
||||
<script type="text/javascript">var STATIC_URL = "{{ STATIC_URL }}";</script>
|
||||
{% for file in HORIZON_CONFIG.js_files %}
|
||||
<script src='{{ STATIC_URL }}{{ file }}' type='text/javascript' charset='utf-8'></script>
|
||||
{% endfor %}
|
||||
@ -42,6 +42,9 @@
|
||||
<script src='{{ STATIC_URL }}horizon/js/horizon.instances.js' type='text/javascript' charset='utf-8'></script>
|
||||
<script src='{{ STATIC_URL }}horizon/js/horizon.messages.js' type='text/javascript' charset='utf-8'></script>
|
||||
<script src='{{ STATIC_URL }}horizon/js/horizon.modals.js' type='text/javascript' charset='utf-8'></script>
|
||||
<script type="text/javascript">
|
||||
horizon.modals.MODAL_BACKDROP = "{% firstof HORIZON_CONFIG.modal_backdrop 'static' %}";
|
||||
</script>
|
||||
<script src='{{ STATIC_URL }}horizon/js/horizon.quota.js' type='text/javascript' charset='utf-8'></script>
|
||||
<script src='{{ STATIC_URL }}horizon/js/horizon.tables.js' type='text/javascript' charset='utf-8'></script>
|
||||
<script src='{{ STATIC_URL }}horizon/js/horizon.tables_inline_edit.js' type='text/javascript' charset='utf-8'></script>
|
||||
|
@ -4,7 +4,7 @@
|
||||
{% block id %}modal_template{% endblock %}
|
||||
|
||||
{% block template %}{% spaceless %}{% jstemplate %}
|
||||
<div class="modal">
|
||||
<div class="modal" data-backdrop="[[modal_backdrop]]">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class='modal-header'>
|
||||
|
@ -1,4 +1,5 @@
|
||||
<div id="{% block modal_id %}{{ modal_id }}{% endblock %}"
|
||||
data-backdrop="{{ modal_backdrop }}"
|
||||
class="{% block modal_class %}{% if hide %}modal{% else %}static_page{% endif %}{% endblock %}">
|
||||
<div class="{% if hide %}modal-dialog{% endif %}">
|
||||
<div class="{% if hide %}modal-content{% endif %}">
|
||||
|
@ -1,6 +1,6 @@
|
||||
{% load i18n %}
|
||||
{% with workflow.get_entry_point as entry_point %}
|
||||
<div class="workflow {{ layout|join:' ' }}">
|
||||
<div class="workflow {{ layout|join:' ' }}" data-backdrop="{{ modal_backdrop }}">
|
||||
<form {{ workflow.attr_string|safe }} action="{{ workflow.get_absolute_url }}" {% if add_to_field %}data-add-to-field="{{ add_to_field }}"{% endif %} method="POST"{% if workflow.multipart %} enctype="multipart/form-data"{% endif %}>{% csrf_token %}
|
||||
{% if REDIRECT_URL %}<input type="hidden" name="{{ workflow.redirect_param_name }}" value="{{ REDIRECT_URL }}"/>{% endif %}
|
||||
<div class="modal-dialog">
|
||||
|
@ -23,11 +23,12 @@ from django.views import generic
|
||||
import six
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon.forms import views as hz_views
|
||||
from horizon.forms.views import ADD_TO_FIELD_HEADER # noqa
|
||||
from horizon import messages
|
||||
|
||||
|
||||
class WorkflowView(generic.TemplateView):
|
||||
class WorkflowView(hz_views.ModalBackdropMixin, generic.TemplateView):
|
||||
"""A generic class-based view which handles the intricacies of workflow
|
||||
processing with minimal user configuration.
|
||||
|
||||
@ -60,6 +61,7 @@ class WorkflowView(generic.TemplateView):
|
||||
step_errors = {}
|
||||
|
||||
def __init__(self):
|
||||
super(WorkflowView, self).__init__()
|
||||
if not self.workflow_class:
|
||||
raise AttributeError("You must set the workflow_class attribute "
|
||||
"on %s." % self.__class__.__name__)
|
||||
|
@ -63,6 +63,7 @@ HORIZON_CONFIG = {
|
||||
'exceptions': {'recoverable': exceptions.RECOVERABLE,
|
||||
'not_found': exceptions.NOT_FOUND,
|
||||
'unauthorized': exceptions.UNAUTHORIZED},
|
||||
'modal_backdrop': 'static',
|
||||
'angular_modules': [],
|
||||
'js_files': [],
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user