Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Reworked the widget form, including the JavaScript

- Turned the JavaScript code in to a jQuery plugin, removed most of the
  initialization code from the individual widget templates to a external
  JavaScript file, and added a {% phileo_js %} tag to load this plugin.
- Each like button gets a unique ID, so multiple like buttons can appear
  on a single page
- Made the widget a plain old form. This way, it works without
  JavaScript. Additionally, the CSRF stuff is included in the form by
  default, so the ajax_csrf.js script is obsolete
  • Loading branch information...
commit 45b5c4147a077635d8ebefa82686a9d6540888cb 1 parent eb56d27
Tim Heap authored November 28, 2011
9  docs/changelog.rst
Source Rendered
@@ -3,6 +3,15 @@
3 3
 ChangeLog
4 4
 =========
5 5
 
  6
+0.3
  7
+---
  8
+- Turned the JavaScript code in to a jQuery plugin, removed most of the initialization
  9
+  code from the individual widget templates to a external JavaScript file, and added a
  10
+  {% phileo_js %} tag to load this plugin.
  11
+- Each like button gets a unique ID, so multiple like buttons can appear on a single
  12
+  page
  13
+- The like form works without JavaScript.
  14
+
6 15
 0.2
7 16
 ---
8 17
 
26  docs/templatetags.rst
Source Rendered
@@ -23,6 +23,15 @@ This renders some css style sheets that will style the widget.::
23 23
 
24 24
 It renders "phileo/_css.html" and can be overridden as desired.
25 25
 
  26
+phileo_js
  27
+---------
  28
+
  29
+This renders some script tags that are needed to make the widget work.::
  30
+
  31
+    {% phileo_js %}
  32
+
  33
+It renders "phileo/_js.html" and can be overridden as desired.
  34
+
26 35
 
27 36
 likes_widget
28 37
 ------------
@@ -31,26 +40,11 @@ This renders a fragement of html that will be what the user will click
31 40
 on to unlike or like objects. It only has two required parameters, which
32 41
 are the user and the object.::
33 42
 
34  
-    {% likes_widget user object [like_link_id="likes" like_span_total_class="phileo-count" toggle_class="phileo-liked"] %}
  43
+    {% likes_widget user object [widget_id="unique_id" like_type="likes" toggle_class="phileo-liked"] %}
35 44
 
36 45
 
37 46
 It renders "phileo/_widget.html" and can be overridden as desired.
38 47
 
39  
-
40  
-likes_js
41  
---------
42  
-
43  
-This is a simple inclusion template tag that will render a bit
44  
-of javascript for doing the ajax toggling of a user's like for
45  
-a given object. The only two required parameters are the first
46  
-two which are the user doing the liking and the object that is
47  
-the subject of the liking.::
48  
-
49  
-    {% likes_js user object [like_link="#likes" like_span_total="phileo-count" toggle_class="phileo-liked"] %}
50  
-
51  
-It renders "phileo/_script.html" and can be overriden as desired.
52  
-
53  
-
54 48
 liked
55 49
 -----
56 50
 
10  docs/usage.rst
Source Rendered
@@ -17,14 +17,14 @@ Then in the <head> section of your template load the css::
17 17
     {% likes_css %}
18 18
 
19 19
 
20  
-In the body where you want the liking widget to go, add::
  20
+Load the required JavaScript file, wherever you load your JavaScript libraries::
21 21
 
22  
-    {% likes_widget request.user post %}
  22
+    {% phileo_js %}
23 23
 
24 24
 
25  
-Then at the bottom of your page where include your javascript::
  25
+In the body where you want the liking widget to go, add::
26 26
 
27  
-    {% likes_js request.user post %}
  27
+    {% likes_widget request.user post %}
28 28
 
29 29
 
30  
-That's all you need to do to get the basics working.
  30
+That's all you need to do to get the basics working.
25  phileo/static/phileo/js/ajax_csrf.js
... ...
@@ -1,25 +0,0 @@
1  
-(function($) {
2  
-     // from http://docs.djangoproject.com/en/1.3/ref/contrib/csrf/#ajax
3  
-     $('html').ajaxSend(
4  
-         function(event, xhr, settings) {
5  
-             function getCookie(name) {
6  
-                 var cookieValue = null;
7  
-                 if (document.cookie && document.cookie != '') {
8  
-                     var cookies = document.cookie.split(';');
9  
-                     for (var i = 0; i < cookies.length; i++) {
10  
-                         var cookie = $.trim(cookies[i]);
11  
-                         // Does this cookie string begin with the name we want?
12  
-                         if (cookie.substring(0, name.length + 1) == (name + '=')) {
13  
-                             cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
14  
-                             break;
15  
-                         }
16  
-                     }
17  
-                 }
18  
-                 return cookieValue;
19  
-             }
20  
-             if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
21  
-                 // Only send the token to relative URLs i.e. locally.
22  
-                 xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
23  
-             }
24  
-         });
25  
- })(jQuery);
39  phileo/static/phileo/js/jquery.phileo.js
... ...
@@ -0,0 +1,39 @@
  1
+jQuery(function($) {
  2
+
  3
+    var PhileoLikes = function(form, options) {
  4
+        this.options = $.extend({}, $.fn.phileo.defaults, options);
  5
+        this.$form = $(form);
  6
+
  7
+        this.$count = $(this.options.count);
  8
+
  9
+        var self = this;
  10
+        this.$form.submit(function(event) {
  11
+            event.preventDefault();
  12
+
  13
+            $.ajax({
  14
+                url: self.$form.attr('action'),
  15
+                type: "POST",
  16
+                data: self.$form.serialize(),
  17
+                statusCode: {
  18
+                    200: function(data, textStatus, jqXHR) {
  19
+                        self.$count.text(data.likes_count);
  20
+                        self.$form[data.liked ? 'addClass' : 'removeClass'](self.options.toggle_class);
  21
+                    }
  22
+                }
  23
+            });
  24
+        });
  25
+    };
  26
+
  27
+    $.fn.phileo = function(options) {
  28
+        $(this).each(function(i, el) {
  29
+            var phileo = new PhileoLikes(el, options);
  30
+            $(el).data('Phileo', {instance: phileo});
  31
+        });
  32
+        return this;
  33
+    };
  34
+
  35
+    $.fn.phileo.defaults = {
  36
+        toggle_class: 'phileo-liked',
  37
+        count: false
  38
+    };
  39
+});
1  phileo/templates/phileo/_js.html
... ...
@@ -0,0 +1 @@
  1
+<script src="{{ STATIC_URL }}phileo/js/jquery.phileo.js"></script>
23  phileo/templates/phileo/_script.html
... ...
@@ -1,23 +0,0 @@
1  
-<script type="text/javascript" src="{{ STATIC_URL }}phileo/js/ajax_csrf.js"></script>
2  
-<script type="text/javascript">
3  
-    $(function () {
4  
-        $("{{ like_link }}")
5  
-            .addClass("iconic")
6  
-            .addClass("check")
7  
-            .addClass("phileo")
8  
-            .addClass("{{ is_liked }}");
9  
-        $("{{ like_link }}").click(function() {
10  
-            $.ajax({
11  
-                url: "{{ like_url }}",
12  
-                type: "POST",
13  
-                data: {},
14  
-                statusCode: {
15  
-                    200: function(data, textStatus, jqXHR) {
16  
-                        $("{{ like_span_total }}").text(data.likes_count);
17  
-                        $("{{ like_link }}").toggleClass("{{ toggle_class }}");
18  
-                    }
19  
-                }
20  
-            });
21  
-        });
22  
-    });
23  
-</script>
27  phileo/templates/phileo/_widget.html
... ...
@@ -1,4 +1,23 @@
1  
-<div class="phileo">
2  
-    <a class="{{ toggle_class }}" id="{{ like_link }}"></a>
3  
-    <span class="{{ like_span_total }}">{{ likes_count }}</span>
4  
-</div>
  1
+{% block phileo_widget_form %}
  2
+	<form class="phileo {{ is_liked }} {{ like_type }}" action="{{ like_url }}" method="POST" id="{{ widget_id }}">{% csrf_token %}
  3
+		{% block phileo_widget_button %}
  4
+			<input type="submit" class="phileo-toggle" value="Like" />
  5
+		{% endblock phileo_widget_button %}
  6
+		{% block phileo_widget_count %}
  7
+            <span class="phileo-count">
  8
+                <span id="{{ like_count_id }}">{{ like_count }}</span>
  9
+                {{ like_type }}{{ like_count|pluralize }}
  10
+            </span>
  11
+		{% endblock phileo_widget_count %}
  12
+	</form>
  13
+{% endblock phileo_widget_form %}
  14
+{% block phileo_widget_js %}
  15
+	<script type="text/javascript">
  16
+	jQuery(function ($) {
  17
+		$("#{{ widget_id }}").phileo({
  18
+			count: "#{{ like_count_id }}",
  19
+			toggle_class: "{{ toggle_class }}"
  20
+		});
  21
+	});
  22
+	</script>
  23
+{% endblock phileo_widget_js %}
49  phileo/templatetags/phileo_tags.py
@@ -7,7 +7,6 @@
7 7
 
8 8
 from phileo.models import Like
9 9
 
10  
-
11 10
 register = template.Library()
12 11
 
13 12
 
@@ -65,52 +64,42 @@ def likes_count(obj):
65 64
 def likes_css():
66 65
     return {"STATIC_URL": settings.STATIC_URL}
67 66
 
  67
+@register.inclusion_tag("phileo/_js.html")
  68
+def phileo_js():
  69
+    return {"STATIC_URL": settings.STATIC_URL}
  70
+
68 71
 
69 72
 @register.inclusion_tag("phileo/_widget.html")
70  
-def likes_widget(user, obj, like_link_id="likes", like_span_total_class="phileo-count", toggle_class="phileo-liked"):
  73
+def likes_widget(user, obj, widget_id=None, like_type="like", toggle_class="phileo-liked"):
71 74
     ct = ContentType.objects.get_for_model(obj)
72  
-    likes_count = Like.objects.filter(
  75
+
  76
+    like_count = Like.objects.filter(
73 77
        receiver_content_type = ct,
74 78
        receiver_object_id = obj.pk
75 79
     ).count()
  80
+
76 81
     liked = user.liking.filter(
77 82
         receiver_content_type = ct,
78 83
         receiver_object_id = obj.pk
79 84
     ).exists()
80  
-    return {
81  
-        "like_link": like_link_id,
82  
-        "like_span_total": like_span_total_class,
83  
-        "likes_count": likes_count,
84  
-        "toggle_class": toggle_class if liked else ""
85  
-    }
86 85
 
87  
-
88  
-@register.inclusion_tag("phileo/_script.html")
89  
-def likes_js(user, obj, like_link="#likes", like_span_total=".phileo-count", toggle_class="phileo-liked"):
90  
-    ct = ContentType.objects.get_for_model(obj)
91  
-    url = reverse("phileo_like_toggle", kwargs={
92  
-        "content_type_id": ct.id,
  86
+    like_count_id = "%s_count" % widget_id
  87
+    
  88
+    like_url = reverse("phileo_like_toggle", kwargs={
  89
+        "content_type_id": ct.pk,
93 90
         "object_id": obj.pk
94 91
     })
95  
-    liked = Like.objects.filter(
96  
-       sender = user,
97  
-       receiver_content_type = ContentType.objects.get_for_model(obj),
98  
-       receiver_object_id = obj.pk
99  
-    ).exists()
100  
-    if liked:
101  
-        is_liked = toggle_class
102  
-    else:
103  
-        is_liked = ""
  92
+
104 93
     return {
105  
-        "STATIC_URL": settings.STATIC_URL,
106  
-        "like_url": url,
107  
-        "like_link": like_link,
108  
-        "like_span_total": like_span_total,
  94
+        "like_url": like_url,
  95
+        "widget_id": widget_id,
  96
+        "like_type": like_type,
  97
+        "like_count": like_count,
  98
+        "like_count_id": like_count_id,
109 99
         "toggle_class": toggle_class,
110  
-        "is_liked": is_liked
  100
+        "is_liked": toggle_class if liked else ""
111 101
     }
112 102
 
113  
-
114 103
 class LikedObjectsNode(template.Node):
115 104
     
116 105
     def __init__(self, objects, user, varname):
4  phileo/views.py
@@ -37,7 +37,9 @@ def like_toggle(request, content_type_id, object_id):
37 37
             "likes_count": Like.objects.filter(
38 38
                 receiver_content_type = content_type,
39 39
                 receiver_object_id = object_id
40  
-            ).count()
  40
+            ).count(),
  41
+            "liked": created,
  42
+
41 43
         }), mimetype="application/json")
42 44
     
43 45
     return redirect(request.META["HTTP_REFERER"])

0 notes on commit 45b5c41

Please sign in to comment.
Something went wrong with that request. Please try again.