text: /*!
   * jQuery Raty - A Star Rating Plugin - http://wbotelhos.com/raty
   * -------------------------------------------------------------------
   *
   * jQuery Raty is a plugin that generates a customizable star rating.
   *
   * Licensed under The MIT License
   *
   * @version        2.4.5
   * @since          2010.06.11
   * @author         Washington Botelho
   * @documentation  wbotelhos.com/raty
   * @twitter        twitter.com/wbotelhos
   *
   * Usage:
   * -------------------------------------------------------------------
   * $('#star').raty();
   *
   * <div id="star"></div>
   *
   */
  
  ;(function($) {
  
  	var methods = {
  		init: function(settings) {
  			return this.each(function() {
  				var self	= this,
  					$this	= $(self).empty();
  	
  				self.opt = $.extend(true, {}, $.fn.raty.defaults, settings);
  
  				$this.data('settings', self.opt);
  
  				if (typeof self.opt.number == 'function') {
  					self.opt.number = self.opt.number.call(self);
  				} else {
  					self.opt.number = methods.between(self.opt.number, 0, 20)
  				}
  
  				if (self.opt.path.substring(self.opt.path.length - 1, self.opt.path.length) != '/') {
  					self.opt.path += '/';
  				}
  
  				if (typeof self.opt.score == 'function') {
  					self.opt.score = self.opt.score.call(self);
  				}
  
  				if (self.opt.score) {
  					self.opt.score = methods.between(self.opt.score, 0, self.opt.number);					
  				}
  
  				for (var i = 1; i <= self.opt.number; i++) {
  					$('<img />', {
  						src		: self.opt.path + ((!self.opt.score || self.opt.score < i) ? self.opt.starOff : self.opt.starOn),
  						alt		: i,
  						title	: (i <= self.opt.hints.length && self.opt.hints[i - 1] !== null) ? self.opt.hints[i - 1] : i
  					}).appendTo(self);
  
  					if (self.opt.space) {
  						$this.append((i < self.opt.number) ? '&#160;' : '');
  					}
  				}
  
  				self.stars = $this.children('img:not(".raty-cancel")');
  				self.score = $('<input />', { type: 'hidden', name: self.opt.scoreName }).appendTo(self);
  
  				if (self.opt.score && self.opt.score > 0) {
  					self.score.val(self.opt.score);
  					methods.roundStar.call(self, self.opt.score);
  				}
  
  				if (self.opt.iconRange) {
  					methods.fill.call(self, self.opt.score);	
  				}
  
  				methods.setTarget.call(self, self.opt.score, self.opt.targetKeep);
  
  				var space	= self.opt.space ? 4 : 0,
  					width	= self.opt.width || (self.opt.number * self.opt.size + self.opt.number * space);
  
  				if (self.opt.cancel) {
  					self.cancel = $('<img />', { src: self.opt.path + self.opt.cancelOff, alt: 'x', title: self.opt.cancelHint, 'class': 'raty-cancel' });
  
  					if (self.opt.cancelPlace == 'left') {
  						$this.prepend('&#160;').prepend(self.cancel);
  					} else {
  						$this.append('&#160;').append(self.cancel);
  					}
  
  					width += (self.opt.size + space);
  				}
  
  				if (self.opt.readOnly) {
  					methods.fixHint.call(self);
  
  					if (self.cancel) {
  						self.cancel.hide();
  					}
  				} else {
  					$this.css('cursor', 'pointer');
  
  					methods.bindAction.call(self);
  				}
  
  				$this.css('width', width);
  			});
  		}, between: function(value, min, max) {
  			return Math.min(Math.max(parseFloat(value), min), max);
  		}, bindAction: function() {
  			var self	= this,
  				$this	= $(self);
  
  			$this.mouseleave(function() {
  				var score = self.score.val() || undefined;
  
  				methods.initialize.call(self, score);
  				methods.setTarget.call(self, score, self.opt.targetKeep);
  
  				if (self.opt.mouseover) {
  					self.opt.mouseover.call(self, score);
  				}
  			});
  
  			var action = self.opt.half ? 'mousemove' : 'mouseover';
  
  			if (self.opt.cancel) {
  				self.cancel.mouseenter(function() {
  					$(this).attr('src', self.opt.path + self.opt.cancelOn);
  
  					self.stars.attr('src', self.opt.path + self.opt.starOff);
  
  					methods.setTarget.call(self, null, true);
  
  					if (self.opt.mouseover) {
  						self.opt.mouseover.call(self, null);
  					}
  				}).mouseleave(function() {
  					$(this).attr('src', self.opt.path + self.opt.cancelOff);
  
  					if (self.opt.mouseover) {
  						self.opt.mouseover.call(self, self.score.val() || null);
  					}
  				}).click(function(evt) {
  					self.score.removeAttr('value');
  
  					if (self.opt.click) {
  			          self.opt.click.call(self, null, evt);
  			        }
  				});
  			}
  
  			self.stars.bind(action, function(evt) {
  				var value = parseInt(this.alt, 10);
  
  				if (self.opt.half) {
  					var position	= parseFloat((evt.pageX - $(this).offset().left) / self.opt.size),
  						diff		= (position > .5) ? 1 : .5;
  
  					value = parseFloat(this.alt) - 1 + diff;
  
  					methods.fill.call(self, value);
  
  					if (self.opt.precision) {
  						value = value - diff + position;
  					}
  
  					methods.showHalf.call(self, value);
  				} else {
  					methods.fill.call(self, value);
  				}
  
  				$this.data('score', value);
  
  				methods.setTarget.call(self, value, true);
  
  				if (self.opt.mouseover) {
  					self.opt.mouseover.call(self, value, evt);
  				}
  			}).click(function(evt) {
  				self.score.val((self.opt.half || self.opt.precision) ? $this.data('score') : this.alt);
  
  				if (self.opt.click) {
  					self.opt.click.call(self, self.score.val(), evt);
  				}
  			});
  		}, cancel: function(isClick) {
  			return $(this).each(function() {
  				var self	= this, 
  					$this	= $(self);
  
  				if ($this.data('readonly') === true) {
  					return this;
  				}
  
  				if (isClick) {
  					methods.click.call(self, null);
  				} else {
  					methods.score.call(self, null);
  				}
  
  				self.score.removeAttr('value');
  			});
  		}, click: function(score) {
  			return $(this).each(function() {
  				if ($(this).data('readonly') === true) {
  					return this;
  				}
  
  				methods.initialize.call(this, score);
  
  				if (this.opt.click) {
  					this.opt.click.call(this, score);
  				} else {
  					methods.error.call(this, 'you must add the "click: function(score, evt) { }" callback.');
  				}
  
  				methods.setTarget.call(this, score, true);
  			});
  		}, error: function(message) {
  			$(this).html(message);
  
  			$.error(message);
  		}, fill: function(score) {
  			var self	= this,
  				number	= self.stars.length,
  				count	= 0,
  				$star	,
  				star	,
  				icon	;
  
  			for (var i = 1; i <= number; i++) {
  				$star = self.stars.eq(i - 1);
  
  				if (self.opt.iconRange && self.opt.iconRange.length > count) {
  					star = self.opt.iconRange[count];
  
  					if (self.opt.single) {
  						icon = (i == score) ? (star.on || self.opt.starOn) : (star.off || self.opt.starOff);
  					} else {
  						icon = (i <= score) ? (star.on || self.opt.starOn) : (star.off || self.opt.starOff);
  					}
  
  					if (i <= star.range) {
  						$star.attr('src', self.opt.path + icon);
  					}
  
  					if (i == star.range) {
  						count++;
  					}
  				} else {
  					if (self.opt.single) {
  						icon = (i == score) ? self.opt.starOn : self.opt.starOff;
  					} else {
  						icon = (i <= score) ? self.opt.starOn : self.opt.starOff;
  					}
  
  					$star.attr('src', self.opt.path + icon);
  				}
  			}
  		}, fixHint: function() {
  			var $this	= $(this),
  				score	= parseInt(this.score.val(), 10),
  				hint	= this.opt.noRatedMsg;
  
  			if (!isNaN(score) && score > 0) {
  				hint = (score <= this.opt.hints.length && this.opt.hints[score - 1] !== null) ? this.opt.hints[score - 1] : score;
  			}
  
  			$this.data('readonly', true).css('cursor', 'default').attr('title', hint);
  
  			this.score.attr('readonly', 'readonly');
  			this.stars.attr('title', hint);
  		}, getScore: function() {
  			var score	= [],
  				value	;
  
  			$(this).each(function() {
  				value = this.score.val();
  
  				score.push(value ? parseFloat(value) : undefined);
  			});
  
  			return (score.length > 1) ? score : score[0];
  		}, readOnly: function(isReadOnly) {
  			return this.each(function() {
  				var $this = $(this);
  
  				if ($this.data('readonly') === isReadOnly) {
  					return this;
  				}
  
  				if (this.cancel) {
  					if (isReadOnly) {
  						this.cancel.hide();
  					} else {
  						this.cancel.show();
  					}
  				}
  
  				if (isReadOnly) {
  					$this.unbind();
  
  					$this.children('img').unbind();
  
  					methods.fixHint.call(this);
  				} else {
  					methods.bindAction.call(this);
  					methods.unfixHint.call(this);
  				}
  
  				$this.data('readonly', isReadOnly);
  			});
  		}, reload: function() {
  			return methods.set.call(this, {});
  		}, roundStar: function(score) {
  			var diff = (score - Math.floor(score)).toFixed(2);
  
  			if (diff > this.opt.round.down) {
  				var icon = this.opt.starOn;								// Full up: [x.76 .. x.99]
  
  				if (diff < this.opt.round.up && this.opt.halfShow) {	// Half: [x.26 .. x.75]
  					icon = this.opt.starHalf;
  				} else if (diff < this.opt.round.full) {				// Full down: [x.00 .. x.5]
  					icon = this.opt.starOff;
  				}
  
  				this.stars.eq(Math.ceil(score) - 1).attr('src', this.opt.path + icon);
  			}															// Full down: [x.00 .. x.25]
  		}, score: function() {
  			return arguments.length ? methods.setScore.apply(this, arguments) : methods.getScore.call(this);
  		}, set: function(settings) {
  			this.each(function() {
  				var $this	= $(this),
  					actual	= $this.data('settings'),
  					clone	= $this.clone().removeAttr('style').insertBefore($this);
  
  				$this.remove();
  
  				clone.raty($.extend(actual, settings));
  			});
  
  			return $(this.selector);
  		}, setScore: function(score) {
  			return $(this).each(function() {
  				if ($(this).data('readonly') === true) {
  					return this;
  				}
  
  				methods.initialize.call(this, score);
  				methods.setTarget.call(this, score, true);
  			});
  		}, setTarget: function(value, isKeep) {
  			if (this.opt.target) {
  				var $target = $(this.opt.target);
  
  				if ($target.length == 0) {
  					methods.error.call(this, 'target selector invalid or missing!');
  				}
  
  				var score = value;
  
  				if (!isKeep || score === undefined) {
  					score = this.opt.targetText;
  				} else {
  					if (this.opt.targetType == 'hint') {
  						score = (score === null && this.opt.cancel)
  								? this.opt.cancelHint
  								: this.opt.hints[Math.ceil(score - 1)];
  					} else {
  						score = this.opt.precision
  								? parseFloat(score).toFixed(1)
  								: score;
  					}
  				}
  
  				if (this.opt.targetFormat.indexOf('{score}') < 0) {
  					methods.error.call(this, 'template "{score}" missing!');
  				}
  
  				if (value !== null) {
  					score = this.opt.targetFormat.toString().replace('{score}', score);
  				}
  
  				if ($target.is(':input')) {
  					$target.val(score);
  				} else {
  					$target.html(score);
  				}
  			}
  		}, showHalf: function(score) {
  			var diff = (score - Math.floor(score)).toFixed(1);
  
  			if (diff > 0 && diff < .6) {
  				this.stars.eq(Math.ceil(score) - 1).attr('src', this.opt.path + this.opt.starHalf);
  			}
  		}, initialize: function(score) {
  			score = !score ? 0 : methods.between(score, 0, this.opt.number);
  
  			methods.fill.call(this, score);
  
  			if (score > 0) {
  				if (this.opt.halfShow) {
  					methods.roundStar.call(this, score);
  				}
  
  				this.score.val(score);
  			}
  		}, unfixHint: function() {
  			for (var i = 0; i < this.opt.number; i++) {
  				this.stars.eq(i).attr('title', (i < this.opt.hints.length && this.opt.hints[i] !== null) ? this.opt.hints[i] : i);
  			}
  
  			$(this).data('readonly', false).css('cursor', 'pointer').removeAttr('title');
  
  			this.score.attr('readonly', 'readonly');
  		}
  	};
  
  	$.fn.raty = function(method) {
  		if (methods[method]) {
  			return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
  		} else if (typeof method === 'object' || !method) {
  			return methods.init.apply(this, arguments);
  		} else {
  			$.error('Method ' + method + ' does not exist!');
  		} 
  	};
  
  	$.fn.raty.defaults = {
  		cancel			: false,
  		cancelHint		: 'cancel this rating!',
  		cancelOff		: 'cancel-off.png',
  		cancelOn		: 'cancel-on.png',
  		cancelPlace		: 'left',
  		click			: undefined,
  		half			: false,
  		halfShow		: true,
  		hints			: ['bad', 'poor', 'regular', 'good', 'gorgeous'],
  		iconRange		: undefined,
  		mouseover		: undefined,
  		noRatedMsg		: 'not rated yet',
  		number			: 5,
  		path			: 'img/',
  		precision		: false,
  		round			: { down: .25, full: .6, up: .76 },
  		readOnly		: false,
  		score			: undefined,
  		scoreName		: 'score',
  		single			: false,
  		size			: 16,
  		space			: true,
  		starHalf		: 'star-half.png',
  		starOff			: 'star-off.png',
  		starOn			: 'star-on.png',
  		target			: undefined,
  		targetFormat	: '{score}',
  		targetKeep		: false,
  		targetText		: '',
  		targetType		: 'hint',
  		width			: undefined
  	};
  
  })(jQuery);
  