Move javascript for forms into separate JS file

In passing also clean up a few things that can be passed directly in the
template instead, and simplify things now that we have jquery all the
time.
This commit is contained in:
Magnus Hagander
2018-12-20 15:31:25 +01:00
parent a33bc4630b
commit c622ecd02a
5 changed files with 68 additions and 66 deletions

36
media/js/forms.js Normal file
View File

@ -0,0 +1,36 @@
$(document).ready(function(){
$('textarea.markdown-content').each(function(idx, e) {
attach_showdown_preview(e.id, 0);
});
$('input.toggle-checkbox').each(function(idx, e) {
$(this).change(function(e) {
update_form_toggles($(this));
});
update_form_toggles($(e));
});
$('div.form-group[data-cbtitles]').each(function(idx, e) {
var d = $(e).data('cbtitles');
$.each(d, function(k,v) {
$(e).find('input[type=checkbox][value=' + k + ']').parent('div').prop('title', v);
});
});
});
function update_form_toggles(e) {
var toggles = e.data('toggles').split(',');
var invert = e.data('toggle-invert');
var show = e.is(':checked');
if (invert) {
show = !show;
}
$.each(toggles, function(i, name) {
var e = $('#id_' + name);
if (show) {
$(e).parents('div.form-group').show();
} else {
$(e).parents('div.form-group').hide();
}
});
}

View File

@ -1,5 +1,8 @@
from django.template.defaultfilters import stringfilter from django.template.defaultfilters import stringfilter
from django import template from django import template
import json
register = template.Library() register = template.Library()
@register.filter(name='class_name') @register.filter(name='class_name')
@ -8,7 +11,11 @@ def class_name(ob):
@register.filter(is_safe=True) @register.filter(is_safe=True)
def field_class(value, arg): def field_class(value, arg):
return value.as_widget(attrs={"class": arg}) if 'class' in value.field.widget.attrs:
c = arg + ' ' + value.field.widget.attrs['class']
else:
c = arg
return value.as_widget(attrs={"class": c})
@register.filter(name='hidemail') @register.filter(name='hidemail')
@stringfilter @stringfilter
@ -44,3 +51,11 @@ def planet_title(obj):
# takes a ImportedRSSItem object from a Planet feed and extracts the info # takes a ImportedRSSItem object from a Planet feed and extracts the info
# specific to the title of the Planet entry # specific to the title of the Planet entry
return ":".join(obj.title.split(':')[1:]) return ":".join(obj.title.split(':')[1:])
@register.filter(name='dictlookup')
def dictlookup(value, key):
return value.get(key, None)
@register.filter(name='json')
def tojson(value):
return json.dumps(value)

View File

@ -18,7 +18,7 @@ class NewsArticleForm(forms.ModelForm):
@property @property
def described_checkboxes(self): def described_checkboxes(self):
return { return {
'tags': [(t.id, t.description) for t in NewsTag.objects.all()] 'tags': {t.id: t.description for t in NewsTag.objects.all()}
} }
class Meta: class Meta:

View File

@ -52,24 +52,22 @@ def simple_form(instancetype, itemid, request, formclass, formtemplate='base/for
if hasattr(form, 'filter_by_user'): if hasattr(form, 'filter_by_user'):
form.filter_by_user(request.user) form.filter_by_user(request.user)
if hasattr(instancetype, 'markdown_fields'): for fn in form.fields:
markdownfields = instancetype.markdown_fields if fn in getattr(instancetype, 'markdown_fields', []):
else: form.fields[fn].widget.attrs.update({'class': 'markdown-content'})
markdownfields = None
if hasattr(form, 'described_checkboxes'): for togg in getattr(form, 'toggle_fields', []):
described_checkboxes = form.described_checkboxes form.fields[togg['name']].widget.attrs.update({
else: 'data-toggles': ','.join(togg['fields']),
described_checkboxes = None 'data-toggle-invert': togg['invert'] and 'true' or 'false',
'class': 'toggle-checkbox',
})
return render_pgweb(request, navsection, formtemplate, { return render_pgweb(request, navsection, formtemplate, {
'form': form, 'form': form,
'formitemtype': instance._meta.verbose_name, 'formitemtype': instance._meta.verbose_name,
'markdownfields': markdownfields,
'described_checkboxes': described_checkboxes,
'form_intro': hasattr(form, 'form_intro') and form.form_intro or None, 'form_intro': hasattr(form, 'form_intro') and form.form_intro or None,
'toggle_fields': hasattr(form, 'toggle_fields') and form.toggle_fields or None, 'described_checkboxes': getattr(form, 'described_checkboxes', {}),
'jquery': hasattr(form, 'jquery') and form.jquery or None,
'savebutton': (itemid == "new") and "Submit New" or "Save", 'savebutton': (itemid == "new") and "Submit New" or "Save",
'operation': (itemid == "new") and "New" or "Edit", 'operation': (itemid == "new") and "New" or "Edit",
}) })

View File

@ -36,7 +36,7 @@
</div> </div>
</div> </div>
{% else %}{# field|ischeckbox #} {% else %}{# field|ischeckbox #}
<div class="form-group"> <div class="form-group"{%if field|ismultiplecheckboxes%} data-cbtitles="{{described_checkboxes|dictlookup:field.name|json}}"{%endif%}>
<div class="col-lg-12 {%if field|isrequired_error%} alert alert-danger{%endif%}"> <div class="col-lg-12 {%if field|isrequired_error%} alert alert-danger{%endif%}">
{% if not field|ismultiplecheckboxes %} {% if not field|ismultiplecheckboxes %}
<div class="form-check"> <div class="form-check">
@ -74,60 +74,13 @@
{% block extrahead %} {% block extrahead %}
{{ block.super }} {{ block.super }}
{%if toggle_fields or described_checkboxes or jquery %}
<script type="text/javascript" src="/media/js/jquery.min.js"></script>
{%endif%}
{%if markdownfields%}
<link rel="stylesheet" type="text/css" href="/media/css/showdown_preview.css" /> <link rel="stylesheet" type="text/css" href="/media/css/showdown_preview.css" />
{%endblock%}
{%block extrascript%}
<script type="text/javascript" src="/media/showdown/showdown.js"></script> <script type="text/javascript" src="/media/showdown/showdown.js"></script>
<script type="text/javascript" src="/media/js/showdown_preview.js"></script> <script type="text/javascript" src="/media/js/showdown_preview.js"></script>
<script type="text/javascript"> <script type="text/javascript" src="/media/js/forms.js"></script>
window.onload = function() {
{%for mdf in markdownfields %}
attach_showdown_preview('id_{{mdf}}', 0);
{%endfor%}
{%for cbf, descs in described_checkboxes.items%}
{%comment%}more than a little ugly, but django uses a sequence and not the id for the labels{%endcomment%}
var descs={
{%for k,v in descs %}
'{{k}}': '{{v|escapejs}}',
{%endfor%}
};
$('ul#id_{{cbf}} li').each(function (i,e) {
var id = $(e).find('input[type=checkbox]')[0].value;
e.title=descs[id];
});
{%endfor%}
}
</script>
{%if toggle_fields %}
<script type="text/javascript">
{%for f in toggle_fields%}
function toggle_{{f.name}}() {
v = $('#id_{{f.name}}').prop('checked');
{%for c in f.fields%}
{%if f.invert%}
if (v) {
{%else%}
if (!v) {
{%endif%}
$('#id_{{c}}').attr('disabled', true).parents('.form-group').hide();
} else {
$('#id_{{c}}').removeAttr('disabled').parents('.form-group').show();
}
{%endfor%}
}
$(document).ready(function() {
$('#id_{{f.name}}').change(function() {
toggle_{{f.name}}();
});
toggle_{{f.name}}();
});
{%endfor%}
</script>
{%endif%}{# toggle_fields #}
{%endif%}{# markdownfields #}
{%if recaptcha%} {%if recaptcha%}
<script type="text/javascript" src="https://www.google.com/recaptcha/api.js?hl=en" async defer></script> <script type="text/javascript" src="https://www.google.com/recaptcha/api.js?hl=en" async defer></script>
{%endif%} {%endif%}