Submitted by BillB on 9/25/2009

Simple Star Rating with CSS, JQuery & Ajax

Try It, Click a Star

Not yet rated.

How it Works

I'd almost finished integrating the Fyneworks JQuery Star Rating Plugin into an MVC project when I started to get a bad feeling about the size of it, though it worked fine and seemed to perform quickly. After adding plugin after plugin I just started to balk at more code and I didn't need all the functionality of the fyneworks plugin anyway. So I set out to code my own lighter weight solution. My UI requires that a user clicks a star to indicate a rating, instead of first selecting a rating and then clicking a separate submit button. In the end this might not be a good design. Maybe users will click too soon or not understand that the stars are clickable. Still, I could add a visual clue or two to mitigate these concerns. I could send back a ratingID after the first post and allow the user to edit the rating. (BTW, billb.name doesn't capture rating info. The server side code running for this demo simply spits your rating back at you.)

These Classic ASP files are going to look odd to you but I find myself developing browser side code using a text editor and Classic ASP pages; interpreted languages and stripped down environments are pleasingly snappy. (I used to use TCL to prototype C code.) When the code is working I copy it into my ASP.NET MVC project.

So, this demo consists of two .asp files:

  1. Rating.asp - contains the html, css and javascript.
  2. RatingProcess.asp - processes the form post from Rating.asp
There's nothing fancy about this solution except maybe the star image, which is the basis for the CSS based rollover technique called CSS Sprites. I discovered it at a tutorial on Elated.


The trick is one image that contains both the selected and un-selected stars; one star is 20px square so the image is 20px wide and 40px high. (I used a pitifully old Paint Shop Pro 9 to make it.) You put the image in the background of your element and set the width and height to match the size of one image; in my case that's 20 x 20. Then set the background-position to correspond to the image you want to see. It's like I've made a little window and beneath it I'm moving a sheet of images around so one image appears through the window at a time. So, in my example, on a hover event, I set the image position down 20px so the lower image shows through the window.

But my code shows that I drop it down 21px!!?? Well, being a lame graphics person, my stars.png file was 1 pixel off; the lower star should have been 1px lower. Instead of fixing the image file, I just used code. If the image is off a hair, you can play with the CSS positioning in the code to get them lined up perfectly. Actually, that's probably how people do it - create the image and then figure out all the coordinates of all the various individual images that are in the big image file.

If you're using a CSS-only, no-javascript design, CSS-Sprites is a way to deal with the fact that you can't pre-load images without Javascript. Web designers will often put many images into one file; I looked at Yahoo's home page and found an image that actually contained about 20 images within. (There are other techniques to load images with just css, like hiding them behind other images or off the screen.)

UPDATE!!! There are now tools out there that will take your images and put them all in a single sprites file and even write all the css to make it all work. Find out more by Googling "ASPNET Sprite" to find a bunch of stuff for the Microsoft web world and I'm sure there are tools for other worlds too; just replace "ASPNET" in your search with the environment of your choice.


Since I'm using javascript anyway, to loop through the 5 stars, I used mouse events instead of CSS hover but I still used the Sprites idea of multiple images in one file just for fun. I could have used separate images and done a pre-load and replaced the image in the mouse events instead of the css background-position trick.

All the code appears below. You can copy and paste it and experiment with it a bit. Maybe instead of buttons you'd use div's or span's. Maybe change the cursor to a hand during a mouseover. Maybe find another solution for dealing with multiple submit buttons on one form. You'd also probably add a little more code to disable the stars somehow once a rating has been posted, hide them maybe, unless you wanted to allow the user to edit their previously posted rating. Anyway, here's the code; it's light and it works. Hope the comments will clarify things.

Client side code - Rating.asp

<html>
<head>
<script type="text/javascript">
    $(document).ready(function(){        
        $('#ratingForm').submit(function() {             
            $.post($(this).attr('action'),
                $(this).serialize(),
                    function(response) {
                    $("#ratingDisplay").html("Your rating was " 
                                        + response + " stars.");
                },                
                "text"
            );  
            return false;
        }); 
          
        $('.star').click(function() {
            $('#rating').val(this.id);
        });
        
        $('.star').mouseover(function() {
            var id = $(this).attr('id');            
            for (i=1;i<=id;i++)
            {    
                $('#' + i).css('background-position', '0px -21px');
            }
        });        
            
        $('.star').mouseout(function() {
            var id = $(this).attr('id');
            for (i=1;i<=id;i++)
            {    
                $('#' + i).css('background-position', '0px 0px');
            }
            $(this).blur();  //remove dotted outline 
        });
          
    });    /*End Ready*/
</script>
</head>

<body>
    <h2>Try It, Click a Star</h2>    
        <form id="ratingForm" action='RatingProcess.asp' method="POST">
            <!-- No carriage returns between the buttons for best looking result-->
            <input type="hidden" id="rating" name="rating" value='0' />    
            <button type='submit' class="star" id="1" ></button>
            <button type='submit' class="star" id="2" ></button>
            <button type='submit' class="star" id="3" ></button>
            <button type='submit' class="star" id="4" ></button>
            <button type='submit' class="star" id="5" ></button>
        </form>
        <p>
            <div id="ratingDisplay">Not yet rated.</div>
        </p>
</body>
</html>

Server side code - RatingProcess.asp

RatingProcess.asp is just for testing; make sure my post is working right. All it does is grab the value from the request and spit it back into the response.
<%@ LANGUAGE="VBSCRIPT" %>
<% response.write(request.form("rating")) %>

Click a star

Comments

Add your comment: