JQuery – Star Comment Rating

Here is a nice little rating effect. This does not include the PHP, it is only the JavaScript, HTML, CSS, and Images. If you like this, I do have the PHP script that I created, but will not support, and I threw together quite quickly.  But, what the heck, back to this post now.

Look below and you can see what will be created by the time we are done with this project.

Skip to full source code || Download Source in .zip

What we start with is one HTML file, JQUERY library, star_rating.js (contains all the effects), and the image folder with some images.

First let’s take a look at the file structure.

star-rating file structure

Right now I contain all the CSS in the html file, out of shear laziness, and so you don’t have an extra file with a small amount of CSS in it.

So let’s talk about the html.

Everything except the hidden form field that contains the final rating selected is contained within the rating_cont div.

Inside the main rating_cont div is three more divs.

  1. rating_btns div.
  2. rating_on div.
  3. rated div.
<div id="rating_cont">
<div id="rating_btns"></div>
<div id="rating_on" >&nbsp;</div>
<div id="rated"></div>
</div>
<input type="hidden" id="rating_output" name="rating_output" value="not rated" />

Now that we have the main divs setup, let’s add some of the style so we can see what we are working with.

We will add the following CSS to the rating_cont, our main div.

#rating_cont { background: #1E1D1C url(images/rating_background.jpg) top left no-repeat; border: 1px solid #F9BA0D; width: 140px; height: 23px; text-align: left; margin-left: 6px;}

This puts the background image of the stars ‘off’ and creates our height, width, border, and background for our main container.

Next, let’s create the CSS and html for the rating_btns div.

The rating_btns div will have an unordered list with the actual ratings in it.

Look below.

<ul>
<li>0.5</li>
<li>1.0</li>
<li>1.5</li>
<li>2.0</li>
<li>2.5</li>
<li>3.0</li>
<li>3.5</li>
<li>4.0</li>
<li>4.5</li>
<li>5.0</li>
</ul>

If you’re doing the code step by step, I’m sure you noticed that this looks pretty ugly right now.  Let’s add the CSS to the rating_btns div and the ul we have.

The rating_btns div needs to be above the rating_on div that we will create next, so we will give it a relative positioning and a z-index of 100. We also add the height and width to define the container of our <li> links.

Inside the rating_btns div is our <ul> and it’s <li>. We do not want our <ul> or our <li> to have any margin or padding.  The <li> needs to be 14px wide. Guess why.  14 x 100 = 140! Yup, you got it. That is the width of our container, amazing, I know. We are going to float them left, give them a block display so they don’t go over each other, and last but not least, change the font display. We will change the font to 1px, and the same color as the background. I’m sure you’re asking; why not just have them empty and not have any text in there at all? Well, we will use this text to tell our JQuery script what you hovered over.

Here is the CSS for this.

#rating_btns { position: relative; z-index: 100; width: 140px; height: 21px;}
#rating_btns ul, #rating_btns li  { padding: 0; margin: 0; }
#rating_btns li { float: left; width: 14px; height: 21px; display: block; font-size: 1px; cursor: pointer; color: #1E1D1C; }

Next, look at our rating_on div. Just as it says, it is our div that contains our stars that are “ON”.  We use a quite unique way of doing this. We give it a background image of the “on” stars, but change it’s width based upon what we hover over. That’s the reason we had to give the rating_btns a relative positioning with a z-index, and this div we will also give a relative positioning, but a z-index of 50. We will also set the width to 0px initially, so it doesn’t show before we hover over it.

Here is the HTML for this:

#rating_on { background: url(images/rating_onbackground.jpg) top left no-repeat; width: 0px; height: 21px; position: relative; z-index: 50; top: -21px; }
<div id="rating_on" >&nbsp;</div>

On to our last div, our rating div, this contains three smaller divs that act as cells, one containing the selected rating, another containing the image of the stars, and the last one containing our edit link.

I still haven’t gotten to the JQuery yet, so I will just show you the CSS, and HTML for this.

#rated { display: none; width: 138px; padding: 3px 0px 3px 2px; height: 23px; background-color: #1E1D1C; height: 17px;font-size: 11px;color: #FFC910;}
#rated div { display: block; float: left; }
#rating { font-size: 11px; font-family: Arial, Helvetica, sans-serif; color: #FFC910; padding-left: 3px; width: 22px; }
#small_stars { height: 11px; width: 69px; background-image: url(images/stars_small_sprite.jpg); background-position: 0px -11px; font-size:1px; line-height: 11px; margin-top:3px; }
#rate_edit { line-height: 17px; font-size: 11px; font-family: Arial, Helvetica, sans-serif; color: #FFF; padding-left: 9px; cursor: pointer; }
#rate_edit:hover { text-decoration: underline; }
<div id="rated">
<div id="rating" style="height: 17px; line-height: 17px;">not rated</div>
<div> &#8211; &nbsp;</div>
<div id="small_stars">&nbsp;</div>
<div id="rate_edit">edit</div>
</div>

Since this will be used to send a rating from a form, we will add a hidden form field to be sent. This will be updated from JQuery.

<input type="hidden" id="rating_output" name="rating_output" value="not rated" />

Ok, on to the fun stuff, the JQuery.

This will have a total of six functions, NOT including the document.ready function.

  1. rateWidth function
  2. starSprite function
  3. hover function *JQuery
  4. mouseout function *JQuery
  5. click function *JQuery
  6. edit function *JQuery

With JQuery we need to surround it’s functions with $(document).ready(function()).

In saying that, keep that in mind when you look at the source code. If you don’t know what I am talking about, check out the full source code at the end of this post, or the downloadable source code.

1. rateWidth function
This function accepts the rating variable from our JQuery functions, converts it to an Integer, uses a switch statement to determine the width value, then returns the width to make our rating_on div show the stars. (shows the stars).

function rateWidth($rating){
$rating = parseFloat($rating);
switch ($rating){
case 0.5: $width = "14px"; break;
case 1.0: $width = "28px"; break;
case 1.5: $width = "42px"; break;
case 2.0: $width = "56px"; break;
case 2.5: $width = "70px"; break;
case 3.0: $width = "84px"; break;
case 3.5: $width = "98px"; break;
case 4.0: $width = "112px"; break;
case 4.5: $width = "126px"; break;
case 5.0: $width = "140px"; break;
default:  $width =  "84px";
}
return $width;
}

2. starSprite function
I used two different methods for creating the stars. One uses less HTML, and one uses more. For the small stars that show up when you make a rating, I wanted to use less HTML and used the sprite method to show the rating.  But it does the same thing as the rateWidth but determines the background positioning based on the rating provided.

function starSprite($rating){
$rating = parseFloat($rating);
switch ($rating){
case 0.5: $pos = "-11px"; break;
case 1.0: $pos = "-22px"; break;
case 1.5: $pos = "-33px"; break;
case 2.0: $pos = "-44px"; break;
case 2.5: $pos = "-55px"; break;
case 3.0: $pos = "-66px"; break;
case 3.5: $pos = "-77px"; break;
case 4.0: $pos = "-88px"; break;
case 4.5: $pos = "-99px"; break;
case 5.0: $pos = "-110px"; break;
default:  $pos =  "-77px";
}
return $pos;
}

3. hover function *JQuery
The hover function will detect the cursor hovering over our <li>’s and the value of it and then send the value to the rateWidth function to get our width. It then assigns the width to the #rating_on div.

$('#rating_btns li').hover(function(){
$rating = $(this).text();
$('#rating_on').css('width', rateWidth($rating));
});

4. mouseout function
The mouseout function does just that, tells what stars should be showing on mouseout. But we do not want the stars to be reset every time we go off the stars, especially if we already selected a rating.  So we grab the value of our #rating div and if it is “not rated” we set our width to 0px but if it doesn’t equal “not rated” we set the width of it’s set value.  This way if you have selected a rating it defaults back to it when you mouseout.

$('#rating_btns li').mouseout(function(){
$rating = $('#rating').text();
if($rating == "not rated"){
$('#rating_on').css('width', "0px");
}
else{
$('#rating_on').css('width', rateWidth($rating));
}
});

5.  click function
This function has a little bit more going on than the other ones. When you click the <li> it first grabs the value of the clicked <li> assigns it to the #rating div, uses starSprite function to assign the background position for the #small_stars div, then hides the #rating_btns div, and the #rating_on div. Once hidden, it nicely fades in the #rated div.

$('#rating_btns li').click(function(){
$rating = $(this).text();
$('#rating').text($rating);
$('#rating_output').val($rating);
$pos = starSprite($rating);
$('#small_stars').css('background-position', "0px " + $pos );
$('#rating_btns').hide();
$('#rating_on').hide();
$('#rated').fadeIn();
});

6. edit function
This function just hides the #rated div and fades in the two divs we just hid. The #rating_div and the #rating_btns div.

$('#rate_edit').click(function(){
$('#rated').hide();
$('#rating_btns').fadeIn();
$('#rating_on').fadeIn();
});

Bam… we’re done.

FULL SOURCE CODE

Here is the completed code for your viewing pleasure.

HTML (star_rating.html) -

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>JQuery-Star Comment Rating</title>
<script type="text/javascript" src="js/jquery/jquery-1.3.2.min.js"></script>
<script type="text/javascript" src="js/star_rating.js"></script>
<style type="text/css">
#rating_cont { background: #1E1D1C url(images/rating_background.jpg) top left no-repeat; border: 1px solid #F9BA0D; width: 140px; height: 23px; text-align: left; margin-left: 6px;}
#rating_on { background: url(images/rating_onbackground.jpg) top left no-repeat; width: 0px; height: 21px; position: relative; z-index: 50; top: -21px; }
#rated { display: none; width: 138px; padding: 3px 0px 3px 2px; height: 23px; background-color: #1E1D1C; height: 17px;font-size: 11px;color: #FFC910;}
#rated div { display: block; float: left; }
#rating { font-size: 11px; font-family: Arial, Helvetica, sans-serif; color: #FFC910; padding-left: 3px; width: 22px; }
#small_stars { height: 11px; width: 69px; background-image: url(images/stars_small_sprite.jpg); background-position: 0px -11px; font-size:1px; line-height: 11px; margin-top:3px; }
#rate_edit { line-height: 17px; font-size: 11px; font-family: Arial, Helvetica, sans-serif; color: #FFF; padding-left: 9px; cursor: pointer; }
#rate_edit:hover { text-decoration: underline; }
#rating_btns { position: relative; z-index: 100; width: 140px; height: 21px;}
#rating_btns ul, #rating_btns li  { padding: 0; margin: 0; }
#rating_btns li { float: left; width: 14px; height: 21px; display: block; font-size: 1px; cursor: pointer; color: #1E1D1C;
}
</style>
</head>
<body>
<div id="rating_cont">
<div id="rating_btns">
<ul>
<li>0.5</li>
<li>1.0</li>
<li>1.5</li>
<li>2.0</li>
<li>2.5</li>
<li>3.0</li>
<li>3.5</li>
<li>4.0</li>
<li>4.5</li>
<li>5.0</li>
</ul>
</div>
<div id="rating_on" >&nbsp;</div>
<div id="rated">
<div id="rating" style="height: 17px; line-height: 17px;">not rated</div>
<div> &#8211; &nbsp;</div>
<div id="small_stars">&nbsp;</div>
<div id="rate_edit">edit</div>
</div>
</div>
<input type="hidden" id="rating_output" name="rating_output" />
</body>
</html>

JQuery/JavaScript (star_rating.js) -

/*
* Written by eligeske
* downloaded from eligeske.com
* have fun. nerd.
*/
$(document).ready(function(){
// hover
$('#rating_btns li').hover(function(){
$rating = $(this).text();
$('#rating_on').css('width', rateWidth($rating));
});
// mouseout
$('#rating_btns li').mouseout(function(){
$rating = $('#rating').text();
if($rating == "not rated"){
$('#rating_on').css('width', "0px");
}
else{
$('#rating_on').css('width', rateWidth($rating));
}
});
//click
$('#rating_btns li').click(function(){
$rating = $(this).text();
$('#rating').text($rating);
$('#rating_output').val($rating);
$pos = starSprite($rating);
$('#small_stars').css('background-position', "0px " + $pos );
$('#rating_btns').hide();
$('#rating_on').hide();
$('#rated').fadeIn();
});
//edit
$('#rate_edit').click(function(){
$('#rated').hide();
$('#rating_btns').fadeIn();
$('#rating_on').fadeIn();
});
function rateWidth($rating){
$rating = parseFloat($rating);
switch ($rating){
case 0.5: $width = "14px"; break;
case 1.0: $width = "28px"; break;
case 1.5: $width = "42px"; break;
case 2.0: $width = "56px"; break;
case 2.5: $width = "70px"; break;
case 3.0: $width = "84px"; break;
case 3.5: $width = "98px"; break;
case 4.0: $width = "112px"; break;
case 4.5: $width = "126px"; break;
case 5.0: $width = "140px"; break;
default:  $width =  "84px";
}
return $width;
}
function starSprite($rating){
$rating = parseFloat($rating);
switch ($rating){
case 0.5: $pos = "-11px"; break;
case 1.0: $pos = "-22px"; break;
case 1.5: $pos = "-33px"; break;
case 2.0: $pos = "-44px"; break;
case 2.5: $pos = "-55px"; break;
case 3.0: $pos = "-66px"; break;
case 3.5: $pos = "-77px"; break;
case 4.0: $pos = "-88px"; break;
case 4.5: $pos = "-99px"; break;
case 5.0: $pos = "-110px"; break;
default:  $pos =  "-77px";
}
return $pos;
}
});

I hope it works for you all. If you have any questions feel free to leave a comment.

This will have a total of six functions, NOT including the document.ready function.

  1. rateWidth function
  2. starSprite function
  3. hover function *JQuery
  4. mouseout function *JQuery
  5. click function *JQuery
  6. edit function *JQuery

With JQuery we need to surround it’s functions with $(document).ready(function()).

In saying that, keep that in mind when you look at the source code.

1. rateWidth function

This function accepts the rating variable from our JQuery functions, converts it to an Integer, uses a switch statement to determine the width value, then returns the width to make our rating_on div show the stars. (shows the stars).

ß jscript rateWidth à

2. starSprite function

I used two different methods for creating the stars. One uses less HTML, and one uses more. For the small stars that show up when you make a rating, I wanted to use less HTML and used the sprite method to show the rating. But it does the same thing as the rateWidth but determines the background positioning based on the rating provided.

ß jscript starSprite à

3. hover function *JQuery

The hover function will detect the cursor hovering over our <li>’s and the value of it and then send the value to the rateWidth function to get our width. It then assigns the width to the #rating_on div.

ß hover function à

4. mouseout function

The mouseout function does just that, tells what stars should be showing on mouseout. But we do not want the stars to be reset every time we go off the stars, especially if we already selected a rating. So we grab the value of our #rating div and if it is “not rated” we set our width to 0px but if it doesn’t equal “not rated” we set the width of it’s set value. This way if you have selected a rating it defaults back to it when you mouseout.

ß à

5. click function

This function has a little bit more going on than the other ones. When you click the <li> it first grabs the value of the clicked <li> assigns it to the #rating div, uses starSprite function to assign the background position for the #small_stars div, then hides the #rating_btns div, and the #rating_on div. Once hidden, it nicely fades in the #rated div.

6. edit function

This function just hides the #rated div and fades in the two divs we just hid. The #rating_div and the #rating_btns div.

Bam… we’re done.

Here is the completed code for your viewing pleasure.

ß html à

ß JQuery à

 

29 Responses to “JQuery – Star Comment Rating”

  1. tt says:

    too long

  2. DH says:

    well done! thanks for sharing!

  3. eligeske says:

    What makes it as lengthy as it appears is the rated box fade-in effect. If you need a shorter one you can take out the starSprite function, .click and the “edit”.click. Here is the edited Jquery that would only be the roll over effect:

    $(document).ready(function(){
    // hover
    $(’#rating_btns li’).hover(function(){
    $rating = $(this).text();
    $(’#rating_on’).css(’width’, rateWidth($rating));
    });
    // mouseout
    $(’#rating_btns li’).mouseout(function(){
    $rating = $(’#rating’).text();
    if ($rating == “not rated”) {
    $(’#rating_on’).css(’width’, “0px”);
    }
    else {
    $(’#rating_on’).css(’width’, rateWidth($rating));
    }
    });
    //click
    $(’#rating_btns li’).click(function(){
    $rating = $(this).text();
    $(’#rating’).text($rating);
    $(’#rating_output’).val($rating);
    });
    function rateWidth($rating){
    $rating = parseFloat($rating);
    switch ($rating) {
    case 0.5: $width = “14px”;break;
    case 1.0:$width = “28px”;break;
    case 1.5:$width = “42px”; break;
    case 2.0:$width = “56px”;break;
    case 2.5:$width = “70px”; break;
    case 3.0:$width = “84px”; break;
    case 3.5:$width = “98px”; break;
    case 4.0: $width = “112px”;break;
    case 4.5:$width = “126px”;break;
    case 5.0:$width = “140px”;break;
    default:$width = “84px”;
    }
    return $width;
    }
    });

  4. Strawberry says:

    Nice but when you reload the page it shows like you didn’t rate. So I do not see any purpose of this. :(

  5. eligeske says:

    Hey Strawberry,

    This was created only to make a rating. You would need to add some server side scripting to this in order to make the rating stay. When creating a rating system you need to get the average of all the ratings on a particular item or post. Usually this is done by allowing the user to select which rating they want, then send it to the database, and have the average reappear.

    Let me know a little bit about your skills so I can better assist you.

    Are you a web designer or a programmer?

  6. DJ says:

    Thanks for the write-up. It works on firefox, but I notice that your page doesn’t render on chrome.

  7. Rosie says:

    That’s a cool code!

    Love it!!!!

  8. jay says:

    You are great!!!!…i see it in every word……..keep going

  9. me says:

    Well its for every one ……… from the basic….i just installed it and was having trouble ..with file structure …you saved my day…thanks!!!!!

  10. eligeske says:

    Glad you found it helpful! Tis the season to be jolly! :P

  11. Altaf says:

    Thanks for sharing. This is really useful.

  12. Kakubei says:

    This looks great,just what I need. But how would I pass the voted value to php since the page doesn’t seem to send a form? Also, could I build the chosen rating based on stored values

  13. eligeske says:

    Kakubei,

    There are several different ways you could pass the vote into php. I’ll give you a couple examples.

    1. HTML form -

    <form method=”your.php” action=”post” >
    <input type=”hidden” id=”rating_output” name=”rating_output” value=”not rated” />
    <input type=”submit” />
    </form> .

    Note: The hidden input field that you created with the tutorial will have the value of the rating after they click it, so when they submit the form it will send the rating to your php file. Test it by changing the type=”hidden” to type=”text” and you can see how it works.

    2. AJAX (with JQuery of course) :) -

    $url = ‘your.php’;
    $rating = $(’#rating_output’).val();

    $.post($url, {
    rating: $rating
    }, function(data){
    $(’#rate_edit’).remove(); // hide the edit
    });

    Note: Put this right inside your $(’#rating_btns li’).click(function(){ //here });
    Also, notice inside the ajax function the .remove, this will remove the “edit” so they cannot send multiple ratings.

    – Let me know if this has helped you at all. As far as the build the rating on stored values, explain what you are trying to do a little more on that and I ‘ll see what I can do.

    Eli

  14. abdo says:

    thanks a lot !

  15. eligeske says:

    My Pleasure!

  16. gams says:

    very nice !!!!!!!

  17. ZO_h says:

    Note that in the Opera browser in element <li> is visible text value (0.5, 1, 1.5 … etc). To prevent this bug you have to set in css style – font-size: 0px; for element &#35rating_btns li.

  18. Hello webmaster I like your post :)

  19. enam says:

    thanks a lot…very helpful tutorial…..:)

  20. eligeske says:

    Thanks for the update on that ZO_h,

    I should have checked all browsers with it. For those of you who have problems checking out cross browser compatibility, I found an awesome way that some of you may know of. http://www.spoon.net/browsers

  21. ZO_h says:

    Null problem!
    I’m using part of your code in my site (crete.pl). I combine this with php, cookie, mysql and smarty template. Works very fine.

    Many thanks for your work! Great work!!

    very helpful tutorial :)

  22. Val10 says:

    THANK YOU!

  23. [...] JQuery – Star Comment Rating [...]

  24. [...] &#74Qu&#101ry – Star Comm&#101nt Rating [...]

  25. abdullah says:

    Hello!

    What if the client changes the html so that in the list item, he/she types <li>999<li> ? You should add delimiters in server-side scripting i think?

  26. eligeske says:

    Server side validation is always a must! Relying on the client side to do validation makes it pretty and fast for the user, but ultimately for your data’s safety you MUST ALWAYS do server side validation.

  27. [...] JQuer&#121 – Star &#67&#111mment &#82at&#105ng [...]

  28. ur-stars.com says:

    heah that’s so great
    thanks for explaining

Leave a Reply