Mehraj Khan
Mehraj Khan

Reputation: 977

Rating Star Widgets – How to Check Stars Dynamically

I'm working on rating stars. My question is how to check stars dynamically for example if we pass a variable with value 4.2 then dynamically 4.2stars four an halfstar has to checked.

How I can achieve this using JQuery? This is my HTML:

Thanks.

$(document).ready(function(){

    var value = 3;
    $("input[name=rating][value=" + value + "]").attr('checked', 'checked');
});
.rating_widgets {
	display: flex;
  margin-top: 25px;
}
.rating { 
  border: none;
  float: left;
}
.rating > input { display: none; } 
.rating > label:before { 
  margin: 5px;
  font-size: 24px;
  font-family: FontAwesome;
  display: inline-block;
  content: "\f005";
}
.rating > .half:before { 
  content: "\f089";
  position: absolute;
}
.rating > label { 
  color: #ddd; 
 float: right; 
}
.rating > input:checked ~ label, 
.rating:not(:checked),
.rating:not(:checked){ color: #FFD700;  }

.rating > input:checked, 
.rating > input:checked,
.rating > input:checked ~ label, 
.rating > input:checked ~ label { 
	color: #FFED85;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://use.fontawesome.com/a2e210f715.js"></script>
<div class="rating_widgets">
	<fieldset class="rating">
		<input type="radio" id="star5" name="rating"/>
		<label class = "full" for="star5" title="Awesome - 5 stars"></label>
		<input type="radio" id="star4half" name="rating" value="4 and a half" />
		<label class="half" for="star4half" title="Pretty good - 4.5 stars"></label>
		<input type="radio" id="star4" name="rating" value="4" />
		<label class = "full" for="star4" title="Pretty good - 4 stars"></label>
		<input type="radio" id="star3half" name="rating" value="3 and a half" />
		<label class="half" for="star3half" title="Good - 3.5 stars"></label>
		<input type="radio" id="star3" name="rating" value="3" />
		<label class = "full" for="star3" title="Good - 3 stars"></label>
		<input type="radio" id="star2half" name="rating" value="2 and a half" />
		<label class="half" for="star2half" title="ok - 2.5 stars"></label>
		<input type="radio" id="star2" name="rating" value="2" />
		<label class = "full" for="star2" title="ok - 2 stars"></label>
		<input type="radio" id="star1half" name="rating" value="1 and a half" />
		<label class="half" for="star1half" title="Bad - 1.5 stars"></label>
		<input type="radio" id="star1" name="rating" value="1" />
		<label class = "full" for="star1" title="Very bad - 1 star"></label>
		<input type="radio" id="starhalf" name="rating" value="half" />
		<label class="half" for="starhalf" title="Very bad - 0.5 stars"></label>
 </fieldset>
  </div><!-- .rating_widget-->
  <p class="figcaption">4.2 Stars-Based on 1540 Users Reviews</p>

Upvotes: 1

Views: 1833

Answers (1)

Patrick Hund
Patrick Hund

Reputation: 20246

So the problem here is that the value of the input fields that you are selecting by the rating value (e.g. 4.4) are fairly irregular (e.g. “4 and a half”). If you really must use these values, I'd first create me an object that maps properly normalized input values to the values of the checkbox input fields, like so:

var starMap = {
    '0.5': 'half',
    '1': '1',
    '1.5': '1 and a half',
    '2': '2',
    '2.5': '2 and a half',
    '3': '3',
    '3.5': '3 and a half',
    '4': '4',
    '4.5': '4 and a half',
    '5': '5'
}

You can then get the value that corresponds to a number by using it as a key to the mapping object, which will give you the target value, like this:

var value = '4.5';
var fieldValue = starMap[value]; // result: '4 and a half'

Note that the number actually needs to be a string, so if your input is a number, like in your example, you have to convert it before using as a key:

var value = 4.5;
var stringValue = Number(value).toString(); // result: '4.5'
var fieldValue = starMap[stringValue]; // result: '4 and a half'

So what if your number is not represented in the mapping object, like 4.4, for example? Well, you'll have to round it first to the next half integer, so you'll wind up with this:

var value = 4.4;
var roundedValue = Math.round(value*2)/2; // result: 4.5
var stringValue = Number(value).toString(); // result: '4.5'
var fieldValue = starMap[stringValue]; // result: '4 and a half'

Putting it all together, a working solution to your problem could look like this:

var starMap = {
    '0.5': 'half',
    '1': '1',
    '1.5': '1 and a half',
    '2': '2',
    '2.5': '2 and a half',
    '3': '3',
    '3.5': '3 and a half',
    '4': '4',
    '4.5': '4 and a half',
    '5': '5'
}

function roundToHalf(value) {
    return Math.round(value * 2) / 2;
}

function convertToString(value) {
    return Number(value).toString();
}

function setStarRating(value) {
    var fieldValue = starMap[convertToString(roundToHalf(value))];
    $("input[name=rating][value='" + fieldValue + "']").attr('checked', 'checked');
}

$(document).ready(function() {
    var value = 4.4;
    setStarRating(value);
});
.rating_widgets {
    display: flex;
    margin-top: 25px;
}

.rating {
    border: none;
    float: left;
}

.rating > input {
    display: none;
}

.rating > label:before {
    margin: 5px;
    font-size: 24px;
    font-family: FontAwesome;
    display: inline-block;
    content: "\f005";
}

.rating > .half:before {
    content: "\f089";
    position: absolute;
}

.rating > label {
    color: #ddd;
    float: right;
}

.rating > input:checked ~ label,
.rating:not(:checked),
.rating:not(:checked) {
    color: #FFD700;
}

.rating > input:checked,
.rating > input:checked,
.rating > input:checked ~ label,
.rating > input:checked ~ label {
    color: #FFED85;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://use.fontawesome.com/a2e210f715.js"></script>
<div class="rating_widgets">
    <fieldset class="rating">
        <input type="radio" id="star5" name="rating" />
        <label class="full" for="star5" title="Awesome - 5 stars"></label>
        <input type="radio" id="star4half" name="rating" value="4 and a half" />
        <label class="half" for="star4half" title="Pretty good - 4.5 stars"></label>
        <input type="radio" id="star4" name="rating" value="4" />
        <label class="full" for="star4" title="Pretty good - 4 stars"></label>
        <input type="radio" id="star3half" name="rating" value="3 and a half" />
        <label class="half" for="star3half" title="Good - 3.5 stars"></label>
        <input type="radio" id="star3" name="rating" value="3" />
        <label class="full" for="star3" title="Good - 3 stars"></label>
        <input type="radio" id="star2half" name="rating" value="2 and a half" />
        <label class="half" for="star2half" title="ok - 2.5 stars"></label>
        <input type="radio" id="star2" name="rating" value="2" />
        <label class="full" for="star2" title="ok - 2 stars"></label>
        <input type="radio" id="star1half" name="rating" value="1 and a half" />
        <label class="half" for="star1half" title="Bad - 1.5 stars"></label>
        <input type="radio" id="star1" name="rating" value="1" />
        <label class="full" for="star1" title="Very bad - 1 star"></label>
        <input type="radio" id="starhalf" name="rating" value="half" />
        <label class="half" for="starhalf" title="Very bad - 0.5 stars"></label>
    </fieldset>
</div>
<!-- .rating_widget-->
<p class="figcaption">4.4 Stars-Based on 1540 Users Reviews</p>

Some notes:

  • I've used 4.4 instead of 4.2 like you did to demonstrate that it works for half stars (4.2 rounded would be 4 stars, which will work just as well)
  • I've refactored the rounding, converting to string, and marking the star each into extra functions to make the code tidier

You can also find this code in this fiddle: https://jsfiddle.net/pahund/0zrooko3/

Upvotes: 1

Related Questions