Step 1. Building the HTML
We’re going to create a simple page that lists two movies, and allows you to rate them. This means we need the stars to show the current rating, and to allow voting. We also want an area to show the total votes cast, and the current rating down to one decimal place.- <div class='movie_choice'>
- Rate: Raiders of the Lost Ark
- <div id="r1" class="rate_widget">
- <div class="star_1 ratings_stars"></div>
- <div class="star_2 ratings_stars"></div>
- <div class="star_3 ratings_stars"></div>
- <div class="star_4 ratings_stars"></div>
- <div class="star_5 ratings_stars"></div>
- <div class="total_votes">vote data</div>
- </div>
- </div>
- <div class='movie_choice'>
- Rate: The Hunt for Red October
- <div id="r2" class="rate_widget">
- <div class="star_1 ratings_stars"></div>
- <div class="star_2 ratings_stars"></div>
- <div class="star_3 ratings_stars"></div>
- <div class="star_4 ratings_stars"></div>
- <div class="star_5 ratings_stars"></div>
- <div class="total_votes">vote data</div>
- </div>
- </div>
- .rate_widget {
- border: 1px solid #CCC;
- overflow: visible;
- padding: 10px;
- position: relative;
- width: 180px;
- height: 32px;
- }
- .ratings_stars {
- background: url('star_empty.png') no-repeat;
- float: left;
- height: 28px;
- padding: 2px;
- width: 32px;
- }
- .ratings_vote {
- background: url('star_full.png') no-repeat;
- }
- .ratings_over {
- background: url('star_highlight.png') no-repeat;
- }
- Gives the default ‘empty’ start to each star location
- Sets up classes for filled in stars, and highlighted stars
- Defines and styles the stars’ container.
Next we add a little more CSS to position the total votes box, and center the widgets so the page matches the graphic at the start of this section.
- .total_votes {
- background: #eaeaea;
- top: 58px;
- left: 0;
- padding: 5px;
- position: absolute;
- }
- .movie_choice {
- font: 10px verdana, sans-serif;
- margin: 0 auto 40px auto;
- width: 180px;
- }
Step 2. Adding the UI Interactivity
At this point, we have a very plain looking bunch of empty stars, but they don’t do a whole lot at this point. This is where jQuery comes to the rescue.- $('.ratings_stars').hover(
- // Handles the mouseover
- function() {
- $(this).prevAll().andSelf().addClass('ratings_over');
- $(this).nextAll().removeClass('ratings_vote');
- },
- // Handles the mouseout
- function() {
- $(this).prevAll().andSelf().removeClass('ratings_over');
- set_votes($(this).parent());
- }
- );
The code above then adds and removes the classes to make the stars under the mouse and before ‘highlighted’, and the stars after ‘not highlighted’.
What about set_votes() ?
This is a function that checks which stars should be in the ‘full’ state, and ties in closely with the next step, where we grab remote data from the server.Step 3. Retrieving Data from the Server
Our stars highlight when you move the mouse over them, and that’s a great start. But what about the red stars showing the current vote? To reach this step, we need to both get the information from the server, and write some JavaScript to handle that data.- $('.rate_widget').each(function(i) {
- var widget = this;
- var out_data = {
- widget_id : $(widget).attr('id'),
- fetch: 1
- };
- $.post(
- 'ratings.php',
- out_data,
- function(INFO) {
- $(widget).data( 'fsr', INFO );
- set_votes(widget);
- },
- 'json'
- );
- });
First we set up an object, out_data, to contain the information we’re sending to the server. Our PHP script expects to see ‘fetch’ when just grabbing data, so we include it here. We also include the ID of the widget, which lets the server-side script know what data we’re after. When the call back function fires, it contains a JavaScript object that looks like this:
- {
- "widget_id" : "r1",
- "number_votes" : 129,
- "total_points" : 344,
- "dec_avg" : 2.7,
- "whole_avg" : 3
- }
The .data() method is a bit of jQuery magic that allows you to associate arbitrary data with a DOMIf you look closely at the code, you’ll see we’re taking that object (stored in the variable INFO) and
object.
doing something with it via the .data() method.
The .data() method is a bit of jQuery magic that allows you to associate arbitrary data with a DOM
object. In this case, we’re storing the data in the widget div. It can be accessed later like this:
- $('#one_of_your_widgets).data('fsr').widget_id;
set_votes(), Finally.
After the data has been returned from the server, its handed off indirectly to set_votes().- function set_votes(widget) {
- var avg = $(widget).data('fsr').whole_avg;
- var votes = $(widget).data('fsr').number_votes;
- var exact = $(widget).data('fsr').dec_avg;
- $(widget).find('.star_' + avg).prevAll().andSelf().addClass('ratings_vote');
- $(widget).find('.star_' + avg).nextAll().removeClass('ratings_vote');
- $(widget).find('.total_votes').text( votes + ' votes recorded (' + exact + ' rating)' );
- }
Line 7: ‘avg’ is a whole number, representing the rounded vote average of this widget. Because it’s
a number 1-5, we can use it to find the proper star in the widget, and turn it, and the
preceding ones to our ‘filled’ graphic. Notice the use of .andSelf() to include the star that
we’ve selected.
Line 8: This is quite similar to line seven, but we’re removing the filled graphic from later stars. This
is necessary in case the average for this widget has gone down since the last vote.
Line 9: Here we’re updating the grey box underneath the widget, which shows a more precise rating,
and lets a visitor know how many votes have been cast.