Star rating: Update stars on click and don't lose the actual vote on re-hover I'm trying to make a star based rating system. 

First of all, I don't like to make it all with JS and only innerHTML the rated stars in a given div. I want to make it more like a plugin with the ability to make anything votable and you just have to pass the classes.

My biggest problem, however, is that I'm setting classes on hover and removing them on mouse leave. That's just fine until the user clicks and the classes are set. Think you can imagine what happens if the user hovers again: The classes would get removed. 

But still I want the user to be able to change his vote. I managed it with two different divs where one is hidden. I absolutely don't feel comfortable with this solution:

&lt;div class="votable hide"&gt;
    &lt;i class="fa fa-3x fa-star-o" data-vote-type="1"&gt;&lt;/i&gt;
    &lt;i class="fa fa-3x fa-star-o" data-vote-type="2"&gt;&lt;/i&gt;
    &lt;i class="fa fa-3x fa-star-o" data-vote-type="3"&gt;&lt;/i&gt;
    &lt;i class="fa fa-3x fa-star-o" data-vote-type="4"&gt;&lt;/i&gt;
    &lt;i class="fa fa-3x fa-star-o" data-vote-type="5"&gt;&lt;/i&gt;
&lt;/div&gt;
&lt;div class="voted"&gt;
    &lt;i class="fa fa-3x fa-star" data-vote-type="1"&gt;&lt;/i&gt;
    &lt;i class="fa fa-3x fa-star" data-vote-type="2"&gt;&lt;/i&gt;
    &lt;i class="fa fa-3x fa-star" data-vote-type="3"&gt;&lt;/i&gt;
    &lt;i class="fa fa-3x fa-star-o" data-vote-type="4"&gt;&lt;/i&gt;
    &lt;i class="fa fa-3x fa-star-o" data-vote-type="5"&gt;&lt;/i&gt;
&lt;/div&gt;


With jQuery I'm enabling .votable on hover. On click I'm setting the actual vote to .voted and on mouse leave I'm hiding .votable and showing .voted.

$('.voted').hover(
    function() {
        $('.voted').addClass('hide');
        $('.votable').removeClass('hide');
    }
);

$('.votable').on('mouseleave',function(){
    $('.voted').removeClass('hide');
    $('.votable').addClass('hide');
});

$('.votable &gt; i').hover(
    function() {
        $(this).prevAll().andSelf().removeClass('fa-star-o').addClass('fa-star');
        $(this).nextAll().removeClass('fa-star').addClass('fa-star-o');
    },
    function() {
        $(this).prevAll().andSelf().removeClass('fa-star').addClass('fa-star-o');
    }
);

$('.votable &gt; i').click(function(e) {
    var vote_type = $(this).attr('data-vote-type');
    var el = $('.voted &gt; i[data-vote-type="' + vote_type + '"]');

    $(el).prevAll().andSelf().removeClass('fa-star-o').addClass('fa-star');
    $(el).nextAll().removeClass('fa-star').addClass('fa-star-o');
});


You can see the code working at my fiddle.

What would be a better way of achieving this?
About your HTML:


Consider using the meter element to display the rating:

&lt;meter min="0" max="5" value="3"&gt;★★★☆☆&lt;/meter&gt;


(However, I don’t know how current user agents present this, i.e., if they add some special styling.)
In any case, you should not use the i element for displaying an icon via CSS. Use span instead if you need an empty element.
If you don’t want to use a form for voting, consider using WAI-ARIA to make voting accessible.