Backbone Implementation of Lea Verou's Accessible Radio Buttons
HTML
<script src="http://documentcloud.github.com/underscore/underscore-min.js"></script>
<script src="http://documentcloud.github.com/backbone/backbone-min.js"></script>
<div id="raterBox1"></div>
<div id="raterBox2"></div>
<div id="raterTest">
<div id="raterBox"></div>
</div>
CSS
/* CSS was originated by Lea Verou. I made some very minor modifications to fit
my requirements */
.rating {
display:table-cell;
}
/* :not(:checked) is a filter, so that browsers that don’t support :checked don’t
follow these rules. Every browser that supports :checked also supports :not(), so
it doesn’t make the test unnecessarily selective */
.rating:not(:checked) > input {
position:absolute;
top:-9999px;
clip:rect(0,0,0,0);
}
.rating:not(:checked) > label {
float:right;
display:table-cell;
width:1em;
padding:0;
overflow:hidden;
white-space:nowrap;
cursor:pointer;
font-size:150%;
color:#ddd;
text-shadow:1px 1px #bbb, 2px 2px #666, .1em .1em .2em rgba(0,0,0,.5);
}
.rating:not(:checked) > label:before {
content: "\2605";
}
.rating > input:checked ~ label {
color: gold;
text-shadow:1px 1px #c60, 2px 2px #666, .1em .1em .2em rgba(0,0,0,.5);
}
.rating:not(:checked) > label:hover,
.rating:not(:checked) > label:hover ~ label {
color: #ea0;
text-shadow:1px 1px goldenrod, 2px 2px #B57340, .1em .1em .2em rgba(0,0,0,.5);
}
.rating > input:checked + label:hover,
.rating > input:checked + label:hover ~ label,
.rating > input:checked ~ label:hover,
.rating > input:checked ~ label:hover ~ label,
.rating > label:hover ~ input:checked ~ label {
color: #ea0;
text-shadow:1px 1px goldenrod, 2px 2px #B57340, .1em .1em .2em rgba(0,0,0,.5);
}
.rating > label:active {
position:relative;
}
.rating > .message {
font-size:.85em;
}
JavaScript
/**
* Accessible Ratings Widget
* Simple ratings widget that uses only CSS to highlight ratings stars.
* It is also keyboard accessible as it uses radio buttons, so conceivably
* could be placed in a form.
*
* CSS courtesy of Lea Verou. Awesome stuff.
*
* Options:
*
* el : Absolutely required. This is the element where the widget will be
* rendered.
*
* name : Defaults to "rating" if not supplied. But if several ratings widgets will be used
* on a form, this should be unique for posting purposes.
*
* scale : Defaults to 5, but should be an int >= 3
*
* titles : array (optional). Will be applied to each input, and also will
* display in a message container below the stars. The number of titles
* will override the scale. For instance, if you provide a scale of 5, but
* only provide 3 titles, only three stars will show up. The converse is
* true for more titles than scale.
*
*
* Public : setValue - Sets the rating and checks the proper star
* Methods
* : getValue - Gets the current rating value
*
* Events : ratingChanged + {rating : <clicked radio value>}
* Subscribe to widget and listen for ratingChanged to respond to event.
*
* Notes : Conceivably, I could have created a backing model for this view, however,
* my thinking was that this would act as a sub-view to another model-backed
* view. And as we could have several of these on the page, the backing models
* would consume memory unncessarily.
*
*/
var BDRatingStars = Backbone.View.extend({
initialize : function(options) {
//a rendering el is required
if (options === undefined || !options.el) {
throw 'No "el" provided, so widget has nowhere to render';
}
//the component id ensures that radio buttons remain
//unique. Otherwise, you can't have multiple rating widgets on a...