2 ### jQuery Star Rating Plugin v3.14 - 2012-01-26 ###
3 * Home: http://www.fyneworks.com/jquery/star-rating/
4 * Code: http://code.google.com/p/jquery-star-rating-plugin/
6 * Dual licensed under the MIT and GPL licenses:
7 * http://www.opensource.org/licenses/mit-license.php
8 * http://www.gnu.org/licenses/gpl.html
12 /*# AVOID COLLISIONS #*/
13 ;if(window.jQuery) (function($){
14 /*# AVOID COLLISIONS #*/
16 // IE6 Background Image Fix
17 if ($.browser.msie) try { document.execCommand("BackgroundImageCache", false, true)} catch(e) { };
18 // Thanks to http://www.visualjquery.com/rating/rating_redux.html
20 // plugin initialization
21 $.fn.rating = function(options){
22 if(this.length==0) return this; // quick fail
25 if(typeof arguments[0]=='string'){
26 // Perform API methods on individual elements
29 return this.each(function(){
30 $.fn.rating.apply($(this), args);
33 // Invoke API method handler
34 $.fn.rating[arguments[0]].apply(this, $.makeArray(arguments).slice(1) || []);
39 // Initialize options for this call
40 var options = $.extend(
42 $.fn.rating.options/* default options */,
43 options || {} /* just-in-time options */
46 // Allow multiple controls with the same name by making each call unique
49 // loop through each matched element
51 .not('.star-rating-applied')
52 .addClass('star-rating-applied')
55 // Load control parameters / find context / etc
56 var control, input = $(this);
57 var eid = (this.name || 'unnamed-rating').replace(/\[|\]/g, '_').replace(/^\_+|\_+$/g,'');
58 var context = $(this.form || document.body);
60 // FIX: http://code.google.com/p/jquery-star-rating-plugin/issues/detail?id=23
61 var raters = context.data('rating');
62 if(!raters || raters.call!=$.fn.rating.calls) raters = { count:0, call:$.fn.rating.calls };
63 var rater = raters[eid];
65 // if rater is available, verify that the control still exists
66 if(rater) control = rater.data('rating');
68 if(rater && control)//{// save a byte!
69 // add star to control if rater is available and the same control still exists
74 // create new control if first star or control element was removed/replaced
76 // Initialize options for this rater
79 options || {} /* current call options */,
80 ($.metadata? input.metadata(): ($.meta?input.data():null)) || {}, /* metadata options */
81 { count:0, stars: [], inputs: [] }
84 // increment number of rating controls
85 control.serial = raters.count++;
87 // create rating element
88 rater = $('<span class="star-rating-control"/>');
91 // Mark element for initialization (once all stars are ready)
92 rater.addClass('rating-to-be-drawn');
94 // Accept readOnly setting from 'disabled' property
95 if(input.attr('disabled') || input.hasClass('disabled')) control.readOnly = true;
97 // Accept required setting from class property (class='required')
98 if(input.hasClass('required')) control.required = true;
100 // Create 'cancel' button
102 control.cancel = $('<div class="rating-cancel"><a title="' + control.cancel + '">' + control.cancelValue + '</a></div>')
103 .mouseover(function(){
104 $(this).rating('drain');
105 $(this).addClass('star-rating-hover');
106 //$(this).rating('focus');
108 .mouseout(function(){
109 $(this).rating('draw');
110 $(this).removeClass('star-rating-hover');
111 //$(this).rating('blur');
114 $(this).rating('select');
116 .data('rating', control)
119 }; // first element of group
121 // insert rating star
122 var star = $('<div class="star-rating rater-'+ control.serial +'"><a title="' + (this.title || this.value) + '">' + this.value + '</a></div>');
125 // inherit attributes from input element
126 if(this.id) star.attr('id', this.id);
127 if(this.className) star.addClass(this.className);
130 if(control.half) control.split = 2;
132 // Prepare division control
133 if(typeof control.split=='number' && control.split>0){
134 var stw = ($.fn.width ? star.width() : 0) || control.starWidth;
135 var spi = (control.count % control.split), spw = Math.floor(stw/control.split);
137 // restrict star's width and hide overflow (already in CSS)
139 // move the star left by using a negative margin
140 // this is work-around to IE's stupid box model (position:relative doesn't work)
141 .find('a').css({ 'margin-left':'-'+ (spi*spw) +'px' })
145 if(control.readOnly)//{ //save a byte!
146 // Mark star as readOnly so user can customize display
147 star.addClass('star-rating-readonly');
149 else//{ //save a byte!
150 // Enable hover css effects
151 star.addClass('star-rating-live')
152 // Attach mouse events
153 .mouseover(function(){
154 $(this).rating('fill');
155 $(this).rating('focus');
157 .mouseout(function(){
158 $(this).rating('draw');
159 $(this).rating('blur');
162 $(this).rating('select');
167 // set current selection
168 if(this.checked) control.current = star;
170 // set current select for links
171 if(this.nodeName=="A"){
172 if($(this).hasClass('selected'))
173 control.current = star;
176 // hide input element
179 // backward compatibility, form element to plugin
180 input.change(function(){
181 $(this).rating('select');
184 // attach reference to star to input element and vice-versa
185 star.data('rating.input', input.data('rating.star', star));
187 // store control information in form (or body when form not available)
188 control.stars[control.stars.length] = star[0];
189 control.inputs[control.inputs.length] = input[0];
190 control.rater = raters[eid] = rater;
191 control.context = context;
193 input.data('rating', control);
194 rater.data('rating', control);
195 star.data('rating', control);
196 context.data('rating', raters);
199 // Initialize ratings (first draw)
200 $('.rating-to-be-drawn').rating('draw').removeClass('rating-to-be-drawn');
202 return this; // don't break the chain...
205 /*--------------------------------------------------------*/
208 ### Core functionality and API ###
210 $.extend($.fn.rating, {
211 // Used to append a unique serial number to internal control ID
212 // each time the plugin is invoked so same name controls can co-exist
216 var control = this.data('rating'); if(!control) return this;
217 if(!control.focus) return this; // quick fail if not required
218 // find data for event
219 var input = $(this).data('rating.input') || $( this.tagName=='INPUT' ? this : null );
220 // focus handler, as requested by focusdigital.co.uk
221 if(control.focus) control.focus.apply(input[0], [input.val(), $('a', input.data('rating.star'))[0]]);
222 }, // $.fn.rating.focus
225 var control = this.data('rating'); if(!control) return this;
226 if(!control.blur) return this; // quick fail if not required
227 // find data for event
228 var input = $(this).data('rating.input') || $( this.tagName=='INPUT' ? this : null );
229 // blur handler, as requested by focusdigital.co.uk
230 if(control.blur) control.blur.apply(input[0], [input.val(), $('a', input.data('rating.star'))[0]]);
231 }, // $.fn.rating.blur
233 fill: function(){ // fill to the current mouse position.
234 var control = this.data('rating'); if(!control) return this;
235 // do not execute when control is in read-only mode
236 if(control.readOnly) return;
237 // Reset all stars and highlight them up to this element
238 this.rating('drain');
239 this.prevAll().andSelf().filter('.rater-'+ control.serial).addClass('star-rating-hover');
240 },// $.fn.rating.fill
242 drain: function() { // drain all the stars.
243 var control = this.data('rating'); if(!control) return this;
244 // do not execute when control is in read-only mode
245 if(control.readOnly) return;
247 control.rater.children().filter('.rater-'+ control.serial).removeClass('star-rating-on').removeClass('star-rating-hover');
248 },// $.fn.rating.drain
250 draw: function(){ // set value and stars to reflect current selection
251 var control = this.data('rating'); if(!control) return this;
253 this.rating('drain');
256 control.current.data('rating.input').attr('checked','checked');
257 control.current.prevAll().andSelf().filter('.rater-'+ control.serial).addClass('star-rating-on');
260 $(control.inputs).removeAttr('checked');
261 // Show/hide 'cancel' button
262 control.cancel[control.readOnly || control.required?'hide':'show']();
263 // Add/remove read-only classes to remove hand pointer
264 this.siblings()[control.readOnly?'addClass':'removeClass']('star-rating-readonly');
265 },// $.fn.rating.draw
271 select: function(value,wantCallBack){ // select a value
273 // ***** MODIFICATION *****
274 // Thanks to faivre.thomas - http://code.google.com/p/jquery-star-rating-plugin/issues/detail?id=27
276 // ***** LIST OF MODIFICATION *****
277 // ***** added Parameter wantCallBack : false if you don't want a callback. true or undefined if you want postback to be performed at the end of this method'
278 // ***** recursive calls to this method were like : ... .rating('select') it's now like .rating('select',undefined,wantCallBack); (parameters are set.)
279 // ***** line which is calling callback
280 // ***** /LIST OF MODIFICATION *****
282 var control = this.data('rating'); if(!control) return this;
283 // do not execute when control is in read-only mode
284 if(control.readOnly) return;
286 control.current = null;
287 // programmatically (based on user input)
288 if(typeof value!='undefined'){
289 // select by index (0 based)
290 if(typeof value=='number')
291 return $(control.stars[value]).rating('select',undefined,wantCallBack);
292 // select by literal value (must be passed as a string
293 if(typeof value=='string')
295 $.each(control.stars, function(){
296 if($(this).data('rating.input').val()==value) $(this).rating('select',undefined,wantCallBack);
300 control.current = this[0].tagName=='INPUT' ?
301 this.data('rating.star') :
302 (this.is('.rater-'+ control.serial) ? this : null);
304 // Update rating control state
305 this.data('rating', control);
308 // find data for event
309 var input = $( control.current ? control.current.data('rating.input') : null );
310 // click callback, as requested here: http://plugins.jquery.com/node/1655
312 // **** MODIFICATION *****
313 // Thanks to faivre.thomas - http://code.google.com/p/jquery-star-rating-plugin/issues/detail?id=27
315 //old line doing the callback :
316 //if(control.callback) control.callback.apply(input[0], [input.val(), $('a', control.current)[0]]);// callback event
318 //new line doing the callback (if i want :)
319 if((wantCallBack ||wantCallBack == undefined) && control.callback) control.callback.apply(input[0], [input.val(), $('a', control.current)[0]]);// callback event
320 //to ensure retro-compatibility, wantCallBack must be considered as true by default
321 // **** /MODIFICATION *****
323 },// $.fn.rating.select
329 readOnly: function(toggle, disable){ // make the control read-only (still submits value)
330 var control = this.data('rating'); if(!control) return this;
331 // setread-only status
332 control.readOnly = toggle || toggle==undefined ? true : false;
333 // enable/disable control value submission
334 if(disable) $(control.inputs).attr("disabled", "disabled");
335 else $(control.inputs).removeAttr("disabled");
336 // Update rating control state
337 this.data('rating', control);
340 },// $.fn.rating.readOnly
342 disable: function(){ // make read-only and never submit value
343 this.rating('readOnly', true, true);
344 },// $.fn.rating.disable
346 enable: function(){ // make read/write and submit value
347 this.rating('readOnly', false, false);
348 }// $.fn.rating.select
352 /*--------------------------------------------------------*/
355 ### Default Settings ###
356 eg.: You can override default control like this:
357 $.fn.rating.options.cancel = 'Clear';
359 $.fn.rating.options = { //$.extend($.fn.rating, { options: {
360 cancel: 'Cancel Rating', // advisory title for the 'cancel' link
361 cancelValue: '', // value to submit when user click the 'cancel' link
362 split: 0, // split the star into how many parts?
364 // Width of star image in case the plugin can't work it out. This can happen if
365 // the jQuery.dimensions plugin is not available OR the image is hidden at installation
368 //NB.: These don't need to be pre-defined (can be undefined/null) so let's save some code!
369 //half: false, // just a shortcut to control.split = 2
370 //required: false, // disables the 'cancel' button so user can only select one of the specified values
371 //readOnly: false, // disable rating plugin interaction/ values cannot be changed
372 //focus: function(){}, // executed when stars are focused
373 //blur: function(){}, // executed when stars are focused
374 //callback: function(){}, // executed when a star is clicked
377 /*--------------------------------------------------------*/
380 ### Default implementation ###
381 The plugin will attach itself to file inputs
382 with the class 'multi' when the page loads
385 $('input[type=radio].star').rating();
390 /*# AVOID COLLISIONS #*/
392 /*# AVOID COLLISIONS #*/