Turn a Number into Star Rating Display Using Jquery and Css

Turn a number into star rating display using jQuery and CSS

Here's a solution for you, using only one very tiny and simple image and one automatically generated span element:

CSS

span.stars, span.stars span {
display: block;
background: url(stars.png) 0 -16px repeat-x;
width: 80px;
height: 16px;
}

span.stars span {
background-position: 0 0;
}

Image

alt text

(source: ulmanen.fi)

Note: do NOT hotlink to the above image! Copy the file to your own server and use it from there.

jQuery

$.fn.stars = function() {
return $(this).each(function() {
// Get the value
var val = parseFloat($(this).html());
// Make sure that the value is in 0 - 5 range, multiply to get width
var size = Math.max(0, (Math.min(5, val))) * 16;
// Create stars holder
var $span = $('<span />').width(size);
// Replace the numerical value with stars
$(this).html($span);
});
}

If you want to restrict the stars to only half or quarter star sizes, add one of these rows before the var size row:

val = Math.round(val * 4) / 4; /* To round to nearest quarter */
val = Math.round(val * 2) / 2; /* To round to nearest half */

HTML

<span class="stars">4.8618164</span>
<span class="stars">2.6545344</span>
<span class="stars">0.5355</span>
<span class="stars">8</span>

Usage

$(function() {
$('span.stars').stars();
});

Output

Image from fugue icon set (www.pinvoke.com)

(source: ulmanen.fi)

Demo

http://www.ulmanen.fi/stuff/stars.php

This will probably suit your needs. With this method you don't have to calculate any three quarter or whatnot star widths, just give it a float and it'll give you your stars.


A small explanation on how the stars are presented might be in order.

The script creates two block level span elements. Both of the spans initally get a size of 80px * 16px and a background image stars.png. The spans are nested, so that the structure of the spans looks like this:

<span class="stars">
<span></span>
</span>

The outer span gets a background-position of 0 -16px. That makes the gray stars in the outer span visible. As the outer span has height of 16px and repeat-x, it will only show 5 gray stars.

The inner span on the other hand has a background-position of 0 0 which makes only the yellow stars visible.

This would of course work with two separate imagefiles, star_yellow.png and star_gray.png. But as the stars have a fixed height, we can easily combine them into one image. This utilizes the CSS sprite technique.

Now, as the spans are nested, they are automatically overlayed over each other. In the default case, when the width of both spans is 80px, the yellow stars completely obscure the grey stars.

But when we adjust the width of the inner span, the width of the yellow stars decreases, revealing the gray stars.

Accessibility-wise, it would have been wiser to leave the float number inside the inner span and hide it with text-indent: -9999px, so that people with CSS turned off would at least see the floating point number instead of the stars.

Hopefully that made some sense.


Updated 2010/10/22

Now even more compact and harder to understand! Can also be squeezed down to a one liner:

$.fn.stars = function() {
return $(this).each(function() {
$(this).html($('<span />').width(Math.max(0, (Math.min(5, parseFloat($(this).html())))) * 16));
});
}

How to turn number into star rating while Ajax success using JavaScript, jQuery in Spring Boot?

You can simply use for-loop with rating as counter end value then on each iteration append your icon in some variable using += and finally append this inside html which is already generated .

Demo Code :

var div = "",
des = "";
//just for demo
var list = [{
"customername": "abc",
"reviewmessage": "Good",
"reviewrating": 4.5
}, {
"customername": "xyz",
"reviewmessage": "Very good",
"reviewrating": 5
}, {
"customername": "xyz",
"reviewmessage": "Very good",
"reviewrating": 3.5
}] //data.response;
var listlength = list.length;
if (listlength > 0) {
for (var i = 0; i < listlength; i++) {
var rating = parseInt(list[i].reviewrating);
var stars = "";
//loop through rating...no
for (var j = 1; j <= rating; j++) {
stars += '<i class="fas fa-star" style="color:gold"></i>'; //append new star on each iteration..
}
//check if there is `.` in number..means .5
if (list[i].reviewrating.toString().indexOf('.') != -1) {
//half star
stars += '<i class="fas fa-star-half-alt" style="color:gold"></i>'
}
//pass them here
div = div + "<div class=\"row\"><div class=\"col-lg-7\"><div class=\"review-wrapper\"><div class=\"single-review\"><div class=\"review-img\">" +
"<img src=\"public/web/assets/images/1.png\" alt=\"\"/></div><div class=\"review-content\">" +
"<div class=\"review-top-wrap\"><div class=\"review-left\"><div class=\"review-name\">" +
"<h4>" + list[i].customername + "</h4></div><div class=\"rating-product\">" + stars +
"</div></div><div class=\"review-left\"><a href=\"#\">Reply</a></div>" +
"</div><div class=\"review-bottom\"><p>" + list[i].reviewmessage + "</p></div></div></div>" +
"<div class=\"single-review child-review\"><div class=\"review-img\">\<img src=\"public/web/assets/images/2.png\" alt=\"\"/>\</div>" +
"<div class=\"review-content\"><div class=\"review-top-wrap\"><div class=\"review-left\"><div class=\"review-name\">" +
"<h4>" + list[i].customername + "</h4></div><div class=\"rating-product\">" + stars +
"</div></div><div class=\"review-left\"><a href=\"#\">Reply</a></div>" +
"</div><div class=\"review-bottom\"><p>" + list[i].reviewmessage + "</p></div></div></div>" +
"</div></div></div>";
document.getElementById('des-details3').innerHTML = div;
}
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" integrity="sha512-iBBXm8fW90+nuLcSKlbmrPcLa0OT92xO1BIsZ+ywDWZCvqsWgccV3gFoRBv0z+8dLJgyAHIhR35VZc2oM/gI1w==" crossorigin="anonymous" referrerpolicy="no-referrer"
/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/fontawesome.min.css" integrity="sha512-OdEXQYCOldjqUEsuMKsZRj93Ht23QRlhIb8E/X0sbwZhme8eUw6g8q7AdxGJKakcBbv7+/PX0Gc2btf7Ru8cZA==" crossorigin="anonymous" referrerpolicy="no-referrer"
/>

<div id="des-details3"> </div>

how to show stars based on user rating?

Edit: I have edited the answer to be more specific. Also, I believe this to be ejs template just to be more clear.

Id in html is used for identifying individual element and Checking your code there are two places where ID is wrongly declared, that is you are declaring it multiple times.

  1. In the Creation section for row

    <h3><%= products.title %></h3>
    <b>Rating: <span id=stars></span><%= products.rating %>/5</b>
  2. In the script tag where you are accessing id

     <% savedexcit.forEach(function(products){ %>
    document.getElementById("stars").innerHTML = getStars(<%= products.rating %>);

To solve this issue you either need to add different ids, which you can do simply by adding a counter to it or you need to add a class on the star and use it to access the elements or just access it by using class. You can try to do the following changes and this should solve the issue hopefully

  1. Access the index for it by including a variable(index) in the callback function.

    <% savedexcit.forEach(function(products, index){ %>
    <div class="col-xs-12 col-md-4 p shop-item">
    <a class="pa" href="/products/<%= products.category %>/<%= products.slug %>">
    <img class="pimage" src="/product_images/<%= products.id %>/<%= products.image %>" alt="">
    </a>
    <h3><%= products.title %></h3>
    <b>Rating: <span id="stars<%= index %>">></span><%= products.rating %>/5</b>

  2. Then make the same change inside the script tag as below

     <% savedexcit.forEach(function(products,index){ %>
    document.getElementById("stars<%= index %>").innerHTML = getStars(<%= products.rating %>);

This should change target the specific element id.

Star Rating - Not able to reduce value of rating after selecting

Yes, this is a bug on the plugin. It works internally but not visually.

Comment below code and you will be fine :

if (stateClass === 'rated' && endIndex > -1) { // limit to painting only to rated stars, and specific case for half star if (index <= Math.ceil(endIndex) || (index < 1 && endIndex < 0)) { $polygonLeft.attr('style', 'fill:'+ratedColor); } if (index <= endIndex) { $polygonRight.attr('style', 'fill:'+ratedColor); } }

Ref bug link

Star Rating System (jQuery)

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
<script>
function setRating(number)
{
jQuery('#main').css('background','url(images/'+number+'-star.gif) no-repeat');
}

function saveRating(number)
{
jQuery('.rating').attr('onmouseout','setRating(\''+number+'\')');
alert(number);
}
</script>
<style>
.rating
{
width:8px;
height:16px;
float:left;
}
#main
{
width:80px;
height:16px;
}
</style>
<div id="main" style="background:url(images/1.0-star.gif) no-repeat;">
<div class="rating" onmouseover="setRating('0.5')" onclick="saveRating('0.5');" onmouseout="setRating('1.0')"></div>
<div class="rating" onmouseover="setRating('1.0')" onclick="saveRating('1.0');" onmouseout="setRating('1.0')"></div>
<div class="rating" onmouseover="setRating('1.5')" onclick="saveRating('1.5');" onmouseout="setRating('1.0')"></div>
<div class="rating" onmouseover="setRating('2.0')" onclick="saveRating('2.0');" onmouseout="setRating('1.0')"></div>
<div class="rating" onmouseover="setRating('2.5')" onclick="saveRating('2.5');" onmouseout="setRating('1.0')"></div>
<div class="rating" onmouseover="setRating('3.0')" onclick="saveRating('3.0');" onmouseout="setRating('1.0')"></div>
<div class="rating" onmouseover="setRating('3.5')" onclick="saveRating('3.5');" onmouseout="setRating('1.0')"></div>
<div class="rating" onmouseover="setRating('4.0')" onclick="saveRating('4.0');" onmouseout="setRating('1.0')"></div>
<div class="rating" onmouseover="setRating('4.5')" onclick="saveRating('4.5');" onmouseout="setRating('1.0')"></div>
<div class="rating" onmouseover="setRating('5.0')" onclick="saveRating('5.0');" onmouseout="setRating('1.0')"></div>
</div>

This is what I was looking for.

Using JQuery rating stars and submitting data to analytics

I found the answer to my problem. It appears the currValue was being parsed as a String, not an integer which is required by analytics to fire the script. I solved it by converting the value into an integer using the following code:

var myString = currValue;
var myConvertedInteger;
myConvertedInteger = parseInt(myString);
//Check string has been converted
alert(myConvertedInteger);
_gaq.push(['_trackEvent', 'UATRatingTest', 'UATRatingTest2', url, myConvertedInteger]);

Thanks for your input Rory.

How to calculate and display ratings for font-awesome using jQuery

You can achieve what you want like below,

var ratingValue = 3.489, rounded = (ratingValue | 0);
var decimal = ratingValue - rounded, $rating = $(".rating");

for (var j = 0; j < rounded ; j++) {
$rating.append('<i class="fa fa-star" aria-hidden="true"></i>');
}

if(decimal) {
$rating.append('<i class="fa fa-star-half" aria-hidden="true"></i>');
}

DEMO

Edit as per your new requirement,

There is no need for 2 different for loops (simple math is enough)

var ratingValue = 3.9, rounded = (ratingValue | 0);

for (var j = 0; j < 5 ; j++) {
$(".rating").append(
'<i class="fa '+ ((j < rounded)
? "fa-star"
: ((((ratingValue - j) > 0) && ((ratingValue - j) < 1))
? "fa-star-half-o"
: "fa-star-o"))
+'" aria-hidden="true"></i>');
}

DEMO

And to make the code more readable, we can do like this,

var ratingValue = 1.9,
rounded = (ratingValue | 0),
str;

for (var j = 0; j < 5; j++) {
str = '<i class="fa ';
if (j < rounded) {
str += "fa-star";
} else if ((ratingValue - j) > 0 && (ratingValue - j) < 1) {
str += "fa-star-half-o";
} else {
str += "fa-star-o";
}
str += '" aria-hidden="true"></i>';
$(".rating").append(str);
}

DEMO



Related Topics



Leave a reply



Submit