From bcaa32d9575a4f339c77fcd771c5975b38f0e5d7 Mon Sep 17 00:00:00 2001 From: Matt Claypotch Date: Thu, 5 Aug 2010 13:34:04 -0700 Subject: [PATCH] Bug 574286, new ratings widget --- apps/bandwagon/helpers.py | 19 ++--- apps/bandwagon/models.py | 16 ++++- .../templates/bandwagon/barometer.html | 27 ++++++- media/css/main-mozilla.css | 6 ++ media/css/zamboni/zamboni.css | 16 ++++- media/js/zamboni/collections.js | 70 +++++++++++++++++-- 6 files changed, 132 insertions(+), 22 deletions(-) diff --git a/apps/bandwagon/helpers.py b/apps/bandwagon/helpers.py index 18edcf4995..4199e15a5d 100644 --- a/apps/bandwagon/helpers.py +++ b/apps/bandwagon/helpers.py @@ -50,10 +50,8 @@ def barometer(context, collection): if request.user.is_authenticated(): # TODO: Use reverse when bandwagon is on Zamboni. - base_action = remora_url(u'collections/vote/%s' % collection.url_slug) - up_action = base_action + '/up' - down_action = base_action + '/down' - cancel = base_action + '/cancel' + up_action = collection.upvote_url() + down_action = collection.downvote_url() up_title = _('Add a positive vote for this collection') down_title = _('Add a negative vote for this collection') cancel_title = _('Remove my vote for this collection') @@ -63,12 +61,13 @@ def barometer(context, collection): user_vote = votes[0] else: - up_action = down_action = cancel_action = login_link(c) + up_action = down_action = login_link(c) login_title = _('Log in to vote for this collection') up_title = down_title = cancel_title = login_title up_class = 'upvotes' down_class = 'downvotes' + cancel_class = 'cancel_vote' total_votes = collection.upvotes + collection.downvotes @@ -81,9 +80,13 @@ def barometer(context, collection): down_width = max(down_ratio - 1, 0) if user_vote: - up_class += ' voted' - down_class += ' voted' - up_class + if user_vote.vote > 0: + up_class += ' voted' + else: + down_class += ' voted' + else: + cancel_class += ' hidden' + c.update(locals()) c.update({'c': collection}) return c diff --git a/apps/bandwagon/models.py b/apps/bandwagon/models.py index e43cebea08..9b3518d359 100644 --- a/apps/bandwagon/models.py +++ b/apps/bandwagon/models.py @@ -122,11 +122,23 @@ class Collection(amo.models.ModelBase): def get_url_path(self): if settings.NEW_COLLECTIONS: - nick = self.author.nickname if self.author else 'anonymous' - return reverse('collections.detail', args=[nick, self.slug]) + return reverse('collections.detail', + args=[self.author_nickname, self.slug]) else: return '/collection/%s' % self.url_slug + def upvote_url(self): + return reverse('collections.vote', + args=[self.author_nickname, self.slug, 'up']) + + def downvote_url(self): + return reverse('collections.vote', + args=[self.author_nickname, self.slug, 'down']) + + @property + def author_nickname(self): + return self.author.nickname if self.author else 'anonymous' + @classmethod def get_fallback(cls): return cls._meta.get_field('default_locale') diff --git a/apps/bandwagon/templates/bandwagon/barometer.html b/apps/bandwagon/templates/bandwagon/barometer.html index 2d45d698d4..88aec844cc 100644 --- a/apps/bandwagon/templates/bandwagon/barometer.html +++ b/apps/bandwagon/templates/bandwagon/barometer.html @@ -1,12 +1,33 @@
- -
+
-
+
+ {# L10n: Link to remove a collection vote #} + {{ _('Remove') }} + {% if user.is_anonymous() %} +
+ +
+ {% endif %}
diff --git a/media/css/main-mozilla.css b/media/css/main-mozilla.css index 7b3ff73b36..aa9f0123dd 100644 --- a/media/css/main-mozilla.css +++ b/media/css/main-mozilla.css @@ -2801,6 +2801,12 @@ html[xmlns] .clearfix { .barometer form { display: inline-block; + position: relative; +} + +.barometer .cancel_vote { + font-size: .9em; + margin: 0 0 0 .5em; } /* .upvotes and .downvotes are the numbers + thumb images, in inputs. */ diff --git a/media/css/zamboni/zamboni.css b/media/css/zamboni/zamboni.css index 0c7da07f40..951dc8b723 100644 --- a/media/css/zamboni/zamboni.css +++ b/media/css/zamboni/zamboni.css @@ -2380,14 +2380,26 @@ h6.author, .author a { left: -42px; } -.collection-add-dropdown { +.collection-add-dropdown, .collection-rate-dropdown { margin: 0; display: none; width: 200px; - left: -42px; padding: 1em; } +.collection-rate-dropdown { + margin-top:1em; +} + +.upvote .collection-rate-dropdown { + left: -56px; +} + +.downvote .collection-rate-dropdown { + left: inherit; + right: -76px; +} + .collection-add-dropdown a { color: #0055EE; } diff --git a/media/js/zamboni/collections.js b/media/js/zamboni/collections.js index fd1d1380d1..3f009cc6bd 100644 --- a/media/js/zamboni/collections.js +++ b/media/js/zamboni/collections.js @@ -269,18 +269,74 @@ $(document).ready(collections.recently_viewed); $(document).ready(function() { /* Hijack the voting forms to submit over xhr. * - * On success we get all this HTML back again, so it's replaced with a more - * up-to-date version of itself. + * On success we update the vote counts, + * and show/hide the 'Remove' link. */ var callback = function(e) { e.preventDefault(); - var the_form = this; - $.post(this.action, $(this).serialize(), function(content) { - $(the_form).closest('.barometer').parent().html(content) - .find('form').submit(callback); + var the_form = $(this); + $.post(this.action, $(this).serialize(), function(content, status, xhr) { + if (xhr.status == 200) { + var barometer = the_form.closest('.barometer'); + var oldvote = $('input.voted', barometer); + var newvote = $('input[type="submit"]', the_form); + var cancel = $('.cancel_vote', barometer); + + //If the vote cancels an existing vote, cancel said vote + if (oldvote.length) { + oldvote.get(0).value--; + oldvote.removeClass('voted'); + cancel.hide(); + } + + //Render new vote if it wasn't a double + if (oldvote.get(0) !== newvote.get(0)) { + newvote.get(0).value++; + newvote.addClass('voted'); + cancel.show(); + } + } }); }; - $('body[data-anonymous["false"]] .barometer form').submit(callback); + if (z.anonymous) { + $('.barometer form').submit(function(e) { + e.preventDefault(); + var the_form = this; + var dropdown = $('.collection-rate-dropdown', $(the_form).closest('.barometer')); + if ($(the_form).hasClass('downvote')) { + dropdown.addClass('left'); + } else { + dropdown.removeClass('left'); + } + dropdown.detach().appendTo(the_form).show(); + + // Clear popup when we click outside it. + setTimeout(function(){ + function cb(e) { + _root = dropdown.get(0); + // Bail if the click was somewhere on the popup. + if (e.type == 'click' && + _root == e.target || + _.indexOf($(e.target).parents(), _root) != -1) { + return; + } + dropdown.hide(); + $(document.body).unbind('click newPopup', cb); + } + + $(document.body).bind('click newPopup', cb); + }, 0); + + }); + } else { + $('.barometer form').submit(callback); + $('.barometer .cancel_vote').click(function (e) { + e.preventDefault(); + //Clicking 'Remove' re-submits the user's vote, canceling it. + $('input.voted', $(this).closest('.barometer')).closest('form').submit(); + }); + } + }) $(document).ready(function(){