Star Rating Control with jQuery

Notice: This is a discussion thread for comments about the SitePoint article, Star Rating Control with jQuery.


awesome, one little error,
<label><input id=“rating-4” name=“rating” type=“radio” value=“4”/>2 Stars</label>
, the 2 Stars should be 4~

The for attribute.

What do you mean? What attribute?

Cool tutorial! I’m definitely going to try this to my site and see how it looks :stuck_out_tongue:

Just got a Jakob Nielsen book at the bookstore (!wow) and they have been using 7 choices for user ratings for a while now. The stayed away from even numbers : )

Oops, good catch, fixed now

I like everything EXCEPT for the facts that:

  1. you use a <div> and <input>s when, in my opinion, you should be using a more semantic approach, like an <ol> and <li>s, and
  2. I don’t think <label><input … />…</label> is how you’re supposed to be marking-up <label>s and <input>s, I thought that should be more like <label>…</label><input… />, no?
    Otherwise, nice one!
    Atg

@aarontgrogg: I personally have always preferred the input after the label, as you suggest, but I checked the spec while working on the book and the way Craig does it is entirely valid:

http://www.w3.org/TR/html401/interact/forms.html#h-17.9.1

It also saves you from having to put a for attribute in each label, as they will implicitly be associated with the correct input. Because this markup is repetitive enough already, I prefer in this case to use the wrapping method, as Craig has done.

But thanks for keeping us on our toes!

I’m looking into implementing a rating system but not one with stars. Instead i much prefer having limited choice. Mine will only have three choices: Dislike, Undecided, Like. In fact, I am just going to adopt the concept Zune does. Broken Heart, Empty, Heart. I never could sit here and rate anything on a scale. I either like or I don’t, or maybe I’m just undecided.

It’s your lucky day then, because the Star Rating Control with jQuery is expressly designed so that there is no middle ground to choose from, thus achieving much more accurate results from the people.

The tutorial has 8 different possible ratings, so it would be easy for you to bring these down to 3, and adjust the image to use your hearts instead of the stars.

If anyone was wanting it to be a jQuery plugin…
Call it like so:


jQuery( function ($) {
  $( '.stars' ).userRate();
} ); // Same as $(document).ready(...)

The plugin code:


( function ($) {
  $.fn.userRate = function () {
    return this.each( function () {
      var list = $( '<div></div>' );

      $( this )
        .find( 'input:radio' )
        .each( function (i) {
          var rate = $( this ).attr( 'value' )
            , item = $( '<a href="#"></a>' )
                .attr( 'title', rate )
                .addClass( i &#37; 2 == 1 ? 'right' : '' )
                .text( rate );

          addEvents( item );
          list.append( item );

          if ( $( this ).is( ':checked' ) )
            item.prevAll().andSelf().addClass( 'rating' );
        } );

        $( this ).append( list );
    } );
  };

  // Private Method
  function addEvents ( item ) {
    item
      .click( function (e) {
        var star = $( this )
          , link = star.parent();

        link
          .parent()
          .find( 'input:radio[value=' + star.text() + ']' )
          .attr( 'checked', true );

        link.children().removeClass( 'rating' );
        star.prevAll().andSelf().addClass( 'rating' );

        e.preventDefault();
      } )
      .hover( function () {
        $( this ).prevAll().andSelf().addClass( 'rating-over' );
      }, function () {
        $( this ).siblings().andSelf().removeClass( 'rating-over' );
      } );
  }
} )( jQuery );

Although, because this is not correctly handled by some screen readers it’s not recommended.

http://www.w3.org/TR/2008/NOTE-WCAG20-TECHS-20081211/H44.html

You should always use a for attribute.

^I was just going to say that. So, Amen.

I also put a space between the label text and the end of the input to prevent run-on words.

<label for=“rating-4”><input id=“rating-4” name=“rating” type=“radio” value=“4” /> 2 Stars</label>

How is the dropping of support for IE6 going to affect screen readers?

Developers will be aware that IE6 requires explicit association for labels, that they will leap on to the idea of using implicit association instead, if only to thumb their nose at IE6.

So, does this mean that screen readers will be negatively impacted due to that type of behaviour?

How is the dropping of support for IE6 going to affect screen readers?

Anyone on a fixed income due to disability and poor job prospects who shelled out 3000 euros (or 900 dollars or whatever the heck they cost) on JAWS 6 or 7 are pretty much stuck with IE6, because even getting Mozilla to work was very buggy. Upgrading to a newer browser can be free, but upgrading screen readers cost unless you are using one of the free ones.

So, yeah, many people could be negatively impacted. I guess you could lump them in with all the other forced-IE6-hangers-on.

Off Topic:

I’m having huge problems in FF3.5 with JAWS10 though. Simply having a for attribute it causing all labels of radio buttons to get read out 3 times! I need to find out if this is just my copy getting buggy or if there’s a real bug

Hi, This is excellent and just the thing I am looking for as it works with the keyboard :cool:. It works great on my pc with IE8 but when I put the same code on a pc running IE6 the radio buttons are hidden as expected but there is just a space where the stars should appear. I have tried this on several IE6 machines to no avail.:confused:
Does anyone know if this works with IE6 or what I need to do to get it working?
Many Thanks

Hi scootbkh,

I just checked the page, and there is indeed an issue in IE6. The jQuery code works fine, unfortunately IE6 chokes on some of the CSS we’re using.

There are two separate problems: first, the inline-block declaration used to “float” the stars next to each other doens’t work in IE6, so you can use float: left; and display: block; instead.

Second, and a little harder to work around, is that IE6 doesn’t support multiple class selectors on the same element. So, for example, a.rating.rating-right won’t work, as IE6 will only recognize the rating-right class and will apply those styles to all elements with that class, even if they don’t have the rating class. You could modify the jQuery to add additional markup, or do some conditional processing to determine what classes the element already had, but that would make things slower even on browsers for which there was no problem.

Instead, one solution would be to use a separate stylesheet for IE6 (using conditional comments), that relied on two separate sprite files instead of just one: one for the right half of the stars and one for the left. Then you could use one class rule to change the background-image and another to change the background-position, and you avoid the clash.

Although personally, my choice would be to degrade IE6 experience to the same as the non-javascript experience: a plain radio-button list!

Would you suggest that IE conditional comments are used to limit the loading of the script to IE browsers that are version 7 and above?

Well, either that or use an alternate stylesheet that relies on two images. Personally I don’t like spending more time on IE6 support than I spend on brushing my teeth, so I’d go with the default radio button form, but obviously that will vary from person to person and from project to project. I don’t like the idea of adding complexity to the script (with the corresponding performance hit) for the benefit of archaic browsers, and I also don’t like browser sniffing in scripts, so an alternate stylesheet seems like the best fix if you need those shiny stars in IE6.

So it’s a realistic choice between:

Use an alternate stylesheet and fancy footwork to support IE6

or

Fall back to the radio button appearance by preventing IE6 and below from loading the script.

I sympathise with how you feel about going to great efforts with IE6, especially when the browser will still work fine without it. I believe that allowing IE6 to work just the radio buttons is a better choice than messing around with the code structure to appease the idiosyncracies of IE6