2

Jquery headaches today.I am now trying to combine hover and click events in my jquery, the latest edit to my hover function has cancelled out my click event, I can see why (i think). The remove class is overriding my click event.

What i want to achieve is that when i hover over a star all siblings are highlighted, basically follow the mouse, then when i have decided upon a star to choose i should be able to click it and all its siblings plus the one i clicked have the addClass method applied

What i have so far

/* Hover Function */
$(document).ready(function(){
 $('.ratings li').hover(function(){
  $(this).prevAll().andSelf().addClass('goldstar');
   }, function() {
    $(this).prevAll().andSelf().removeClass('goldstar');
  });
});

/* Click Function */
$(document).ready(function(){
 $('.ratings li').click(function(){
  $(this).prevAll().andSelf().addClass('goldstar');
 });
});

/* Click functions to add a value */
$(document).ready(function(){
 $('#firstStar').click(function(){
  $('#hiddenRating').val(1);
 });
});

 $(document).ready(function(){
  $('#secondStar').click(function(){
    $('#hiddenRating').val(2);
 });
 });

 $(document).ready(function(){
  $('#thirdStar').click(function(){
   $('#hiddenRating').val(3);
  });
 });

$(document).ready(function(){
 $('#fourthStar').click(function(){
  $('#hiddenRating').val(4);
 });
});

$(document).ready(function(){
 $('#fifthStar').click(function(){
  $('#hiddenRating').val(5);
 });
});

The Form

   <%= form_for @rating do |f| %>
   <%= f.hidden_field :ratings, :id => "hiddenRating" %>
   <%= f.hidden_field :user_id, :value => current_user.id %>
   <%= f.hidden_field :recipe_id, :value => @recipe.id %>
   <div class="ratings">
<ul>
 <li id="firstStar"></li>
 <li id="secondStar"></li>
 <li id="thirdStar"></li>
 <li id="fourthStar"></li>
 <li id="fifthStar"></li>
</ul>
    </div>

Now I know there must be a better way of doing this, i have a lot of repeated code, but I am learning and would like to know of some ways to re factor this. is there a way to combine the .val methods into one?

With regards to the hover and click function I understand you can use the on method and pass hover and click? though not sure how to implement this

Any help appreciated,

Edit

Jsfiddle

Thanks

4
  • Can you make a jsfiddle please Commented Feb 20, 2013 at 14:59
  • done, though i havent included the form, just hover and click status Commented Feb 20, 2013 at 15:02
  • sorry fiddle incorrect, have updated Commented Feb 20, 2013 at 15:11
  • on a side note, you really should have only one document ready function Commented Feb 20, 2013 at 15:15

5 Answers 5

3

I have added two global variables clicked and chosed_index if you want to also make it selected to the last element the hover did reached you can by adding

chosed_index = $(this).index() + 1;  // in the hover listener 

jQuery Updated Code

$(document).ready(function(){
    var clicked = false; 
    var chosed_index = -1 ; 
    $('.ratings li').on('hover', function(){

           $(this).siblings().andSelf().removeClass('goldstar');         
           $(this).prevAll().andSelf().addClass('goldstar'); 

    }); 

    $('.ratings li').on('mouseleave', function(){
        $(this).siblings().andSelf().removeClass('goldstar');  


            $(".ratings li:nth-child("+chosed_index+")").prevAll().andSelf().addClass('goldstar');


    }); 



    $('.ratings li').click(function(){

        clicked = true; 
        chosed_index = $(this).index() + 1; 

        $(this).siblings().andSelf().removeClass('goldstar');
        $(this).prevAll().andSelf().addClass('goldstar');
    });
  });

Check the fiddle update

Fiddle

I hope this can help :)

Sign up to request clarification or add additional context in comments.

3 Comments

this is best because it retains the last selection
Thanks :) @tmsimont, glad I am improving my skills and helping others
I was just working on a very similar function - but you were faster ;-) I would just add another improvement by removing the ID in the <li>-elements so you can use this snippet for more than one "star-rating"-element.
2

Try simplifying your javascript.

$(function () {
    $('#stars li').hover(function () {
        var li = $(this);
        li.prevAll().andSelf().addClass('goldstar');
        }, function () {
        var li = $(this);
        li.prevAll().andSelf().removeClass('goldstar');
    });

    $('#stars li').click(function () {
        var li = $(this);
        $('#rating').text(li.data('rating'));
    });
})();

See this fiddle: http://jsfiddle.net/PVyXz/1/

9 Comments

There is no point caching a selector if your not reusing it. its good practice but totally not required for this answer
Agreed, just habit I guess as most of the event handlers I've been writing of recent have been more complicated.
I noticed that you are using data-attribute selectors, i guess this enables me to simplify my passing of a value?
I used the data-rating, so that you only need one event handler. This way if you move to a 10 star system, you don't have to change your js code to handle it, only your markup.
ah brilliant, that will make things easier, but having trouble seeing how i can implement in my setup, i get that i can add data-rating 1, data-rating 2 etc, but passing the val, at the moment i do this $(document).ready(function(){ $('#fifthStar').click(function(){ $('#hiddenRating').val(5); }); });
|
1

Add a "locked" class to the parent, so your JS knows if a selection has been made. Then only act on hover out if the selection is not made.

$(document).ready(function(){
  // hover function
  $('.ratings li').hover(function(){
     $(this).prevAll().andSelf().addClass('goldstar');
     $('.ratings').removeClass('locked');
   }, function() {
     if (!$('.ratings').hasClass('locked')) {
       $(this).prevAll().andSelf().removeClass('goldstar');
     }
  });
  //click function 
  $('.ratings li').click(function(){
    $(this).prevAll().andSelf().addClass('goldstar');
    $('.ratings').addClass('locked');
  });
});

fiddle: http://jsfiddle.net/q86b9/1/

Comments

1

use a separate class for the hover (one that is a shade or so lighter than gold)

can also clear the goldstar class on click for all li's for subsequent clicks

http://jsfiddle.net/pxfunc/vZDwg/14/

.ratings ul li.goldstarHover {
    color:yellow;
}
/* Hover Function */
$(document).ready(function () {
    $('.ratings li').hover(function () {
        $(this).prevAll().andSelf().addClass('goldstarHover');
    }, function () {
        $(this).prevAll().andSelf().removeClass('goldstarHover');
    });
});

/* Click Function */
$(document).ready(function () {
    $('.ratings li').click(function () {
        $('.ratings li').removeClass('goldstar');
        $(this).prevAll().andSelf().addClass('goldstar');
    });
});

Comments

0

My approach is slightly different, works like a charm tho. Might be far simpler for some to understand. The CSS does alot of the legwork using a parent class to override .savedgoldstar colors

http://jsfiddle.net/vZDwg/13/

/* Hover Function */
$(document).ready(function(){
 $('.ratings li').hover(function(){
     $(this).parent().addClass('hovered');
     $(this).prevAll().andSelf().addClass('goldstar');
   }, function() {
    $(this).parent().removeClass('hovered');
    $(this).prevAll().andSelf().removeClass('goldstar');
  });
});

/* Click Function */
$(document).ready(function(){
 $('.ratings li').click(function(){
  $(this).siblings().removeClass('savedgoldstar');
  $(this).prevAll().andSelf().addClass('savedgoldstar');
 });
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.