JGeer
JGeer

Reputation: 1852

Change star rating on hover

I use this code to display stars:

<ul class="rating">
<li>
<span class="ratingSelector">
<input type="radio" name="ratings[1]" id="Degelijkheid-1-5" value="1" class="radio">
<label class="full" for="Degelijkheid-1-5"></label>
<input type="radio" name="ratings[1]" id="Degelijkheid-2-5" value="2" class="radio">
<label class="full" for="Degelijkheid-2-5"></label>
<input type="radio" name="ratings[1]" id="Degelijkheid-3-5" value="3" class="radio">
<label class="full" for="Degelijkheid-3-5"></label>
<input type="radio" name="ratings[1]" id="Degelijkheid-4-5" value="4" class="radio">
<label class="full" for="Degelijkheid-4-5"></label>
<input type="radio" name="ratings[1]" id="Degelijkheid-5-5" value="5" class="radio">
<label class="full" for="Degelijkheid-5-5"></label>
</span>
</li>
</ul>

Dynamic code:

         <ul class="rating">
            <?php foreach ($this->getRatings() as $_rating): ?>
                <li>
                    <span class="rowlabel"><?php echo $this->escapeHtml($_rating->getRatingCode()) ?></span>
                    <span class="ratingSelector">
                <?php foreach ($_rating->getOptions() as $_option): ?>
                    <input type="radio" name="ratings[<?php echo $_rating->getId() ?>]" id="<?php echo $this->escapeHtml($_rating->getRatingCode()) ?>-<?php echo $_option->getValue() ?>-5" value="<?php echo $_option->getId() ?>" class="radio" /><label class="full" for="<?php echo $this->escapeHtml($_rating->getRatingCode()) ?>-<?php echo $_option->getValue() ?>-5"></label>
                <?php endforeach; ?>
                </span>
                </li>
            <?php endforeach; ?>
        </ul>

But hovering and selecting currently works from right to left, but I want to change this from left to right.

Code is loaded dynamically, so I can not change the sort and put value 5 first. This dynamic code is loaded 5 times, for 5 different ratings.

How can I change this? Or what code of JQuery do I need?

JSFiddle: https://jsfiddle.net/9nn14beq/

Upvotes: 14

Views: 5936

Answers (4)

Jamie Barker
Jamie Barker

Reputation: 8256

This can almost work with pure CSS. It does need one line of JavaScript to set the initial value though:

document.getElementById('Degelijkheid-1-5').checked = true;
.rating input {
    display: none;
}
.rating label:before {
    margin: 5px;
    font-size: 1.25em;
    font-family: FontAwesome;
    display: inline-block;
    content:"\f005";
}
li {
    list-style:none;
}

.ratingSelector input + label {
    color: #FFD700;
}
.ratingSelector input:checked ~ input:not(:checked) ~ label {
    color: #ddd;
}
.ratingSelector input:checked ~ input:not(:checked) + label:hover ~ label {
    color: #ddd;
}
.ratingSelector:hover input + label,
.ratingSelector:hover input:checked + label {
    color: #FFED85;
}
.ratingSelector:hover input:checked ~ input:not(:checked) ~ label:hover,
.ratingSelector:hover input:checked ~ input:not(:checked) + label {
    color: #FFD700;
}
.ratingSelector:hover input:checked ~ input:not(:checked) ~ label:hover ~ label {
    color: #ddd !important;
}
.ratingSelector input + label:hover ~ label {
    color: #ddd !important;
}
<ul class="rating">
    <li> <span class="ratingSelector">
    <input type="radio" name="ratings[1]" id="Degelijkheid-1-5" value="1" class="radio"/>
<label class="full" for="Degelijkheid-1-5"></label>
    <input type="radio" name="ratings[1]" id="Degelijkheid-2-5" value="2" class="radio"/>
<label class="full" for="Degelijkheid-2-5"></label>
    <input type="radio" name="ratings[1]" id="Degelijkheid-3-5" value="3" class="radio"/>
<label class="full" for="Degelijkheid-3-5"></label>
    <input type="radio" name="ratings[1]" id="Degelijkheid-4-5" value="4" class="radio"/>
<label class="full" for="Degelijkheid-4-5"></label>
    <input type="radio" name="ratings[1]" id="Degelijkheid-5-5" value="5" class="radio"/>
<label class="full" for="Degelijkheid-5-5"></label>
    </span>
    </li>
</ul>

EDIT

To use JS (to re-order the items):

var objGroup = document.getElementsByClassName('ratingSelector');
for (var i = 0; i < objGroup.length; i++) {
  var objRadio = [].slice.call(objGroup[i].getElementsByClassName('full')); // Create an array of items
  for (var j = objRadio.length; j--;) { // Loop through the array backwards
    var checkbox = document.getElementById(objRadio[j].getAttribute('for'));
    objGroup[i].appendChild(checkbox);
    objGroup[i].appendChild(objRadio[j]);
  }
}
.rating {
  direction: rtl;
  text-align: left;
}
.rating input {
  display: none;
}
.rating label:before {
  margin: 5px;
  font-size: 1.25em;
  font-family: FontAwesome;
  display: inline-block;
  content: "\f005";
}
li {
  list-style: none;
}
.rating label {
  color: #ddd;
}
/***** CSS to Highlight Stars on Hover *****/

.ratingSelector input:checked ~ label,
/* show gold star when clicked */

.ratingSelector label:hover,
/* hover current star */

.ratingSelector label:hover ~ label {
  color: #FFD700;
}
/* hover previous stars in list */

.ratingSelector input:checked + label:hover,
/* hover current star when changing rating */

.ratingSelector input:checked ~ label:hover,
.ratingSelector label:hover ~ input:checked ~ label,
/* lighten current selection */

.ratingSelector input:checked ~ label:hover ~ label {
  color: #FFED85;
}
<ul class="rating">
  <li> <span class="ratingSelector">
    <input type="radio" name="ratings[1]" id="Degelijkheid-1-5" value="1" class="radio"/>
<label class="full" for="Degelijkheid-1-5"></label>
    <input type="radio" name="ratings[1]" id="Degelijkheid-2-5" value="2" class="radio"/>
<label class="full" for="Degelijkheid-2-5"></label>
    <input type="radio" name="ratings[1]" id="Degelijkheid-3-5" value="3" class="radio"/>
<label class="full" for="Degelijkheid-3-5"></label>
    <input type="radio" name="ratings[1]" id="Degelijkheid-4-5" value="4" class="radio"/>
<label class="full" for="Degelijkheid-4-5"></label>
    <input type="radio" name="ratings[1]" id="Degelijkheid-5-5" value="5" class="radio"/>
<label class="full" for="Degelijkheid-5-5"></label>
    </span>
  </li>
  <li> <span class="ratingSelector">
    <input type="radio" name="ratings[2]" id="Design-1-5" value="1" class="radio"/>
<label class="full" for="Design-1-5"></label>
    <input type="radio" name="ratings[2]" id="Design-2-5" value="2" class="radio"/>
<label class="full" for="Design-2-5"></label>
    <input type="radio" name="ratings[2]" id="Design-3-5" value="3" class="radio"/>
<label class="full" for="Design-3-5"></label>
    <input type="radio" name="ratings[2]" id="Design-4-5" value="4" class="radio"/>
<label class="full" for="Design-4-5"></label>
    <input type="radio" name="ratings[2]" id="Design-5-5" value="5" class="radio"/>
<label class="full" for="Design-5-5"></label>
    </span>
  </li>
  <li> <span class="ratingSelector">
    <input type="radio" name="ratings[3]" id="Gebruiksgemak-1-5" value="1" class="radio"/>
<label class="full" for="Gebruiksgemak-1-5"></label>
    <input type="radio" name="ratings[3]" id="Gebruiksgemak-2-5" value="2" class="radio"/>
<label class="full" for="Gebruiksgemak-2-5"></label>
    <input type="radio" name="ratings[3]" id="Gebruiksgemak-3-5" value="3" class="radio"/>
<label class="full" for="Gebruiksgemak-3-5"></label>
    <input type="radio" name="ratings[3]" id="Gebruiksgemak-4-5" value="4" class="radio"/>
<label class="full" for="Gebruiksgemak-4-5"></label>
    <input type="radio" name="ratings[3]" id="Gebruiksgemak-5-5" value="5" class="radio"/>
<label class="full" for="Gebruiksgemak-5-5"></label>
    </span>
  </li>
</ul>

Upvotes: 8

Faisal Alvi
Faisal Alvi

Reputation: 532

Just add the below CSS code to make it from left to right:

.ratingSelector {
    max-width: 145px;
    display: inline-block;
}
.rating label {
    float: right;
}

Upvotes: 0

vals
vals

Reputation: 64254

As stated in previous answers, CSS selectors work only in the netural order of the DOM. (Even though this can change some time in the future).

So, if you can not change your DOM, you need to reverse your CSS logic:

Change all the elements on hover of the container. And then use the sibling selector to change the elements to the right of the hovered item

.rating input { display: none; } 
.rating label:before { 
  margin: 5px;
  font-size: 1.25em;
  font-family: FontAwesome;
  display: inline-block;
  content: "\f005";
}

li {list-style:none; }

/***** CSS to Highlight Stars on Hover *****/

.rating label {color: grey;}
label:hover { color: red;  }
.ratingSelector:hover .full {color: red; }
.full:hover ~ .full { color: grey !important;  } 
<ul class="rating">
<li>
<span class="ratingSelector">
<input type="radio" name="ratings[1]" id="Degelijkheid-1-5" value="1" class="radio">
<label class="full" for="Degelijkheid-1-5"></label>
<input type="radio" name="ratings[1]" id="Degelijkheid-2-5" value="2" class="radio">
<label class="full" for="Degelijkheid-2-5"></label>
<input type="radio" name="ratings[1]" id="Degelijkheid-3-5" value="3" class="radio">
<label class="full" for="Degelijkheid-3-5"></label>
<input type="radio" name="ratings[1]" id="Degelijkheid-4-5" value="4" class="radio">
<label class="full" for="Degelijkheid-4-5"></label>
<input type="radio" name="ratings[1]" id="Degelijkheid-5-5" value="5" class="radio">
<label class="full" for="Degelijkheid-5-5"></label>
</span>
</li>
</ul>

Upvotes: 0

ketan
ketan

Reputation: 19341

You expected thing is possible with only css. Because css rule is applied for next sibling not for previous. You should also use JQuery.

But you can do it using following trick using css:

.rating input { display: none; } 
.rating label:before { 
  margin: 5px;
  font-size: 1.25em;
  font-family: FontAwesome;
  display: inline-block;
  content: "\f005";
}

li {list-style:none;
direction:rtl;
text-align: left;}

.rating label { 
  color: #ddd;
}

/***** CSS to Highlight Stars on Hover *****/

.rating input:checked ~ label, /* show gold star when clicked */
.rating:not(:checked) label:hover, /* hover current star */
.rating:not(:checked) label:hover ~ label { color: #FFD700;  } /* hover previous stars in list */

.rating input:checked + label:hover, /* hover current star when changing rating */
.rating input:checked ~ label:hover,
.rating label:hover ~ input:checked ~ label, /* lighten current selection */
.rating input:checked ~ label:hover ~ label { color: #FFED85;  } 
<ul class="rating">
<li>
<span class="ratingSelector">
<input type="radio" name="ratings[1]" id="Degelijkheid-5-5" value="5" class="radio">
<label class="full" for="Degelijkheid-5-5"></label>
<input type="radio" name="ratings[1]" id="Degelijkheid-4-5" value="4" class="radio">
<label class="full" for="Degelijkheid-4-5"></label>
<input type="radio" name="ratings[1]" id="Degelijkheid-3-5" value="3" class="radio">
<label class="full" for="Degelijkheid-3-5"></label>
<input type="radio" name="ratings[1]" id="Degelijkheid-2-5" value="2" class="radio">
<label class="full" for="Degelijkheid-2-5"></label>
<input type="radio" name="ratings[1]" id="Degelijkheid-1-5" value="1" class="radio">
<label class="full" for="Degelijkheid-1-5"></label>
</span>
</li>
</ul>

Upvotes: 0

Related Questions