Submit your widget

jQuery voting tools

Created 14 years ago   Views 18419   downloads 4005    Author aaronweyenberg
jQuery voting tools
View DemoDownload
681
Share |

Markup

Like anything, this can be done a number of ways. There’s not much semantic relevance here, so any sensible structure will do. The only real requirement is to have enough elements for styling and animation.

<div class="votecard">
<div><em><strong>293</strong><span>Flips</span></em></div>
</div>

<a class="voteaction">Flippit</a>

Background & CSS

I’ll just use one sprite for this tool. The top will serve as the background for the numeric value, the bottom area gives us backgrounds for the unclicked, hover and clicked states of the action button.

There’s nothing too tricky or innovative in the CSS below. However, the key technique here is the overflow:hidden rule on the “votecard” class’s child div (line 10). This will effectively serve as a mask which the animating objects will move across. More on that later.

.votecard {
 background: url(images/sprite.png) no-repeat 0 0;
 padding: 4px;
 width: 63px;
 height: 43px;
 text-align: center;
}
.votecard div {
 position: relative;
 overflow: hidden;
 width: 63px;
 height: 43px;
}
.votecard em {
 display: block;
 position: relative;
 width: 63px;
 height: 33px;
 padding: 6px 0 6px 0;
 font: normal 24px/24px "Helvetica Neue","Helvetica","Arial",Sans-serif;
 color: #45453f;
}
.votecard strong {
 font-weight: bold;
}
.votecard span {
 font-size: 10px;
 line-height: 10px;
 display: block;
 color: #9a9a94;
}
a.voteaction {
 margin: 0 0 0 3px;
 display: block;
 text-indent: -9999px;
 width: 71px;
 height: 21px;
 background: url(images/sprite.png) no-repeat -3px -75px;
}
a.voteaction:hover {
 outline: none;
 background-position: -3px -54px;
}
a.voted,
a.voted:hover {
 outline: none;
 background-position: -3px -96px;
 cursor: default;
}

jQuery

Now we’ll have some real fun and wire this up.

$(document).ready(function() {
 /* create a node for the flip-to number */
 $(".votecard em").clone().appendTo(".votecard div");
 /* increment that by 1 */
 var node = $(".votecard em:last strong")
 node.text(parseInt(node.text())+1);

 function flip(obj) {
  obj.prev().find("em").animate({
   top: '-=45'
  }, 200);
  obj.toggleClass("voted",true);
 }

 $('.voteaction').bind({
   click: function(event) {
     event.preventDefault()
   },
   mouseup: function() {
     flip($(this));
  $(this).unbind('mouseup');
   }
 });

});

Content duplication

You might have wondered why the next number (294) was not included in the original markup shown earlier. The answer is found in line 3 through 6. This code duplicates the <em> node containing the current vote value (293) then increments that value by one. This new <em> node is forced to flow beneath the original one, but is hidden from view as specified in the CSS above. Here’s what your browser sees after this code runs:

Button events

Two events will be bound to the “Flippit” button, and you’ll see why these events are kept separate shortly. The default browser response is disabled in the click event. The mouseup event handler will call the flip() function which will perform the animation. It is important to allow this function to be called once only. After the user has initiated a “flip”, this action should be immediately disabled.

Had we grouped the event.preventDefault() together with the flip() call in a single button event (on click for example), we’d reinstate the default browser response when we unbound that event from the button. This would likely result in a page refresh if the user clicked the button twice. Keeping these events separate lets us unbind just the flipping action while preserving event.preventDefault().

Flip tha script *

The flip() function’s task is to select both <em>s and then move them up a distance of 45 pixels. Note also that this function takes as an argument a jQuery object reference to the button which called it. From this, we can traverse to select the <em>s we want to animate. The top <em> will slide out of view, while the jQuery generated one slides into view. The process is completed by toggling the button’s class name to “voted”.

What’s this good for?

This adds a little tactility to these contraptions. It reinforces the notion that you just impacted a piece of content on the web, if only by one solitary unit. If it’s good enough for sports apps, it’s good enough for anything else.

This technique could be used for anything where a numeric value increases or decreases whether it results from user interaction or not (as in live scoreboards).