-1

I am working on a rating system where a user can rate by stars.

I made my rating stars as follows:

<div id="rating-submit">
    <ol class="rating-stars">
        <div class="rating"></div>
        <li rate="1"></li>
        <li rate="2"></li>
        <li rate="3"></li>
        <li rate="4"></li>
        <li rate="5"></li>
    </ol><!--End rating-stars-->
</div><!--End rating-submit-->

I placed <li> items (stars) over my "rating" <div>, and if you click on one of the items I style my "rating" <div> with a CSS background so it looks like you have clicked this star.

I style it by giving the "rating" <div> an extra class called rating-(1, 2, 3, 4, 5).

jQuery:

jQuery( document ).ready( function( $ ) {

    $( '#rating-submit .rating-stars li' ).click( function() {
        var rating = $( this ).attr( 'rate' );
        $( '#rating-submit .rating' ).addClass( 'rating-' + rating );

    });

});

My problem:

If I add for example "rate-3" as class and then click on the second star, the "rate-3" class stays there and it overrules the other class.

My question:

How can I remove the previously added classes if I click on a new star?

Here is my Jsfiddle

Robbert
  • 1,270
  • 6
  • 30
  • 62
  • 1
    does this help? http://api.jquery.com/removeclass/ – ewizard Jun 17 '14 at 12:50
  • 1
    Make each star it's own element, with its own generic class for on/off. Use `prevAll().addClass()` to add the class to all previous stars, and `removeClass()` to remove it. Much simpler than trying to maintain each star having it's own unique class. – Rory McCrossan Jun 17 '14 at 12:53
  • This plugin is simple and neat: http://wbotelhos.com/raty – urbz Jun 17 '14 at 12:57
  • Anyway, that's not valid HTML markup, DIV cannot be direct child of OL and BTW `rate` isn't valid HTML attribute – A. Wolff Jun 17 '14 at 12:59
  • I hope this post will help you http://stackoverflow.com/questions/8118266/integrating-css-star-rating-into-an-html-form – Srinivasa Reddy Jun 17 '14 at 13:15
  • Hi I hope this post will help you http://stackoverflow.com/questions/8118266/integrating-css-star-rating-into-an-html-form – Srinivasa Reddy Jun 17 '14 at 13:18

4 Answers4

3

Make each star it's own element, with its own generic class for on/off. Use prevAll().addClass() to add the class to all previous stars, and removeClass() to remove it. It's much simpler than trying to maintain each star having it's own unique class.

To do this, firstly make your HTML valid by removing the div within the ol and using data attributes::

<div id="rating-submit">
    <ol class="rating-stars">
        <li data-rate="1"></li>
        <li data-rate="2"></li>
        <li data-rate="3"></li>
        <li data-rate="4"></li>
        <li data-rate="5"></li>
    </ol>
</div>

You can then make your CSS generic based on a single class on each stars' li:

#rating-submit .rating-stars {
    position: static;
    width: 112px;
    height: 20px;
    margin: 0;
    padding: 0;
    background: url(http://s4.postimg.org/qukg9gyih/rating_stars.png) no-repeat;    
}

#rating-submit .rating-stars li {
    height: 20px;
    width: 19px;
    display: inline-block;
    margin: 0;
    list-style: none;
}

#rating-submit .rating-stars li.active {
    background: url(http://s4.postimg.org/qukg9gyih/rating_stars.png) 0 -38px no-repeat;    
}

Finally all your JS needs to do is set the active class on the chosen star, and those to the left of it using prevAll():

$('#rating-submit .rating-stars li').click(function () {
    var $chosenStar = $(this);
    $chosenStar
        .siblings('li').removeClass('active').end() // remove existing classes
        .prevAll().add(this).addClass('active');
    console.log($chosenStar.data('rate')); // the chosen rating value
});

Working fiddle

Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
  • Thanks for this great answer! Nice solution. I only have 2 questions left. Is it still possible to add the clicked 'rate' attr to a hidden field. And can I also use this for hover the elements. So if I hover star 3, the star 1 and 2 getting active class – Robbert Jun 17 '14 at 13:12
  • And what is the console.log doing? – Robbert Jun 17 '14 at 13:13
  • The console.log is showing you how to get the rating value which was clicked on. You can use that to set the `val()` of your hidden field as you need. – Rory McCrossan Jun 17 '14 at 13:15
  • You can also change this to work on hover quite easily. `mouseenter` will be the same logic as above, `mouseleave` will simply remove the classes, unless something has been selected. – Rory McCrossan Jun 17 '14 at 13:16
  • But it's a debugging thing right? http://stackoverflow.com/questions/4539253/what-is-console-log – Robbert Jun 17 '14 at 13:16
  • Yes, you need to change the `console.log` to select the field you want to put the value in. – Rory McCrossan Jun 17 '14 at 13:16
1

I've changed a little bit your approach to solve your problem.

jsFiddle

<div id="rating-submit">
    <ol class="rating-stars">
        <li rate="1"></li>
        <li rate="2"></li>
        <li rate="3"></li>
        <li rate="4"></li>
        <li rate="5"></li>
    </ol><!--End rating-stars-->
</div><!--End rating-submit-->

jQuery( document ).ready( function( $ ) {

    // Rating stars
    $( '.rating-stars li' ).on("click", function() {
        var i, len, rating = $( this ).attr( 'rate');

        $( '.rating-stars li').removeClass("rated");
        for(i = 0, len = rating; i < rating; i = i + 1){
            $( '.rating-stars li' ).eq(i).addClass("rated");
        }

    });

});

The problem with your old approach was that you could not trigger the click event on the li anymore, when they were overlapped by your div rating.

About the image, you need just a "one start on" "one off" not all the five stars.

Ivan
  • 408
  • 4
  • 14
0

before your addClass() call, remove the existing rating-x classes:

$( '#rating-submit .rating' ).removeClass('rating-1 rating-2 rating-3 rating-4 rating-5');

Important: There is a bug in your implementation that makes it impossible to click stars that are yellow. This is because the .rating div sits above the lis, which makes them unclickable.

Jonathan Nicol
  • 3,158
  • 1
  • 21
  • 22
0

You are on the wrong way.

The problem is that your yellow starts are over li elements, so we can't click on lower grey stars, and if we try, we don't know on which stars we have clicked.

You should not do like this, and add a class on every li elements which is yellow

Alcalyn
  • 1,531
  • 14
  • 25