Move javascript for forms into separate JS file
authorMagnus Hagander <magnus@hagander.net>
Thu, 20 Dec 2018 14:31:25 +0000 (15:31 +0100)
committerMagnus Hagander <magnus@hagander.net>
Thu, 20 Dec 2018 16:18:11 +0000 (17:18 +0100)
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.

media/js/forms.js [new file with mode: 0644]
pgweb/core/templatetags/pgfilters.py
pgweb/news/forms.py
pgweb/util/helpers.py
templates/base/form.html

diff --git a/media/js/forms.js b/media/js/forms.js
new file mode 100644 (file)
index 0000000..eba6cca
--- /dev/null
@@ -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();
+       }
+    });
+}
index 5d60628552d74fe6a0e2317780a961fb152d9973..8670535e89af3e29f646a543e7bf2c4a6877fb1f 100644 (file)
@@ -1,5 +1,8 @@
 from django.template.defaultfilters import stringfilter
 from django import template
+import json
+
+
 register = template.Library()
 
 @register.filter(name='class_name')
@@ -8,7 +11,11 @@ def class_name(ob):
 
 @register.filter(is_safe=True)
 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')
 @stringfilter
@@ -44,3 +51,11 @@ def planet_title(obj):
        # takes a ImportedRSSItem object from a Planet feed and extracts the info
        # specific to the title of the Planet entry
        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)
index 565a0aa17f9c6569f445c1d31b6e4f4dc3edbc12..a779db01777ed9212c9b3de3e9a890aae860f374 100644 (file)
@@ -18,7 +18,7 @@ class NewsArticleForm(forms.ModelForm):
        @property
        def described_checkboxes(self):
                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:
index 5377a113b37f375253b2557762286668d4663fff..6b3f08de7fdf9122d8214f9c189f43af2d5cb523 100644 (file)
@@ -52,24 +52,22 @@ def simple_form(instancetype, itemid, request, formclass, formtemplate='base/for
        if hasattr(form, 'filter_by_user'):
                form.filter_by_user(request.user)
 
-       if hasattr(instancetype, 'markdown_fields'):
-               markdownfields = instancetype.markdown_fields
-       else:
-               markdownfields = None
+       for fn in form.fields:
+               if fn in getattr(instancetype, 'markdown_fields', []):
+                       form.fields[fn].widget.attrs.update({'class': 'markdown-content'})
 
-       if hasattr(form, 'described_checkboxes'):
-               described_checkboxes = form.described_checkboxes
-       else:
-               described_checkboxes = None
+       for togg in getattr(form, 'toggle_fields', []):
+               form.fields[togg['name']].widget.attrs.update({
+                       'data-toggles': ','.join(togg['fields']),
+                       'data-toggle-invert': togg['invert'] and 'true' or 'false',
+                       'class': 'toggle-checkbox',
+               })
 
        return render_pgweb(request, navsection, formtemplate, {
                'form': form,
                'formitemtype': instance._meta.verbose_name,
-               'markdownfields': markdownfields,
-               'described_checkboxes': described_checkboxes,
                'form_intro': hasattr(form, 'form_intro') and form.form_intro or None,
-               'toggle_fields': hasattr(form, 'toggle_fields') and form.toggle_fields or None,
-               'jquery': hasattr(form, 'jquery') and form.jquery or None,
+               'described_checkboxes': getattr(form, 'described_checkboxes', {}),
                'savebutton': (itemid == "new") and "Submit New" or "Save",
                'operation': (itemid == "new") and "New" or "Edit",
        })
index db839f2ceee53f5dfc3d4cf4ad130645b0bcb3a4..0576a78337d19e6e1ddbba3fc60a5fbffbafbe34 100644 (file)
@@ -36,7 +36,7 @@
           </div>
         </div>
       {% 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%}">
             {% if not field|ismultiplecheckboxes %}
               <div class="form-check">
 
 {% block extrahead %}
 {{ 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" />
+{%endblock%}
+
+{%block extrascript%}
 <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">
-   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 #}
-
+<script type="text/javascript" src="/media/js/forms.js"></script>
 {%if recaptcha%}
 <script type="text/javascript" src="https://www.google.com/recaptcha/api.js?hl=en" async defer></script>
 {%endif%}