jQuery.fn.rating = function(settings) {
	settings = jQuery.extend({
		 cancel:'0',
		 currentValue:'',
		 showCancel: false,
		 cancelTitle: 'reset',
		 cancelPosition: 'after' // before / after
	}, settings);
	
	var prevElem = null;
	var valueElem = null;
	var container = $(this);
	var CancelElem = null;
	var event = {
		fill: function(el) { // fill to the current mouse position.
			var stars = $(valueElem).siblings('.grade');
			var index = stars.index(el) + 1;
			$(stars)
				.children('a').css('width', '100%').end()
				.slice(0, index).addClass('grade_on').end();
		},
		drain: function() { // drain all the stars.
			var stars = $(valueElem).siblings('.grade');
			$(stars)
				.filter('.grade_on').removeClass('grade_on').end()
				.filter('.grade_hover').removeClass('grade_hover').end();
		},
		reset: function() { // Reset the stars to the default index.
			var stars = $(valueElem).siblings('.grade');
			$(stars).slice(0, settings.currentValue).addClass('grade_on').end();
		}
	};
	var count = this.length;
	var initialIndex = -1;
	
	return this.each(function (i) {
		// prepend the value holder at the beginning
		if (i == 0)
		{
			valueElem = $('<input type="hidden" name="' + this.name + '" value="" >');
			$(this).before(valueElem);
		}
	    
		// prepend cancel option at the beginning
		if (settings.showCancel && settings.cancelPosition == 'before' && i == 0)
		{
			var CancelElem = $('<div class="cancel"><a href="#" title="' + settings.cancelTitle + '">' + settings.cancel + '</a></div>');
			prevElem = CancelElem;
			$(this).after(prevElem);	
		
			$(CancelElem)
				.mouseover(function(){
					//event.drain();
					$(this).addClass('grade_on')
				})
				.mouseout(function(){
					event.reset();
					$(this).removeClass('grade_on')
				});
		
			// click events.
			$(CancelElem).click(function() {
				settings.currentValue = $(this).children('a').text();
				$(valueElem).val(settings.currentValue);
				event.drain();
				return false;
			});
		}
		
		//insert rating option right after preview element
		preElemTemp  = $('<div class="grade grade' + (i + 1) + '"><a href="#" title="' + (this.title.length > 0 ? this.title : this.value) + '">' + this.value + '</a></div>');
		if (this.checked)
		{
			initialIndex = i;
			settings.currentValue = this.value;
			$(valueElem).val(settings.currentValue);
		}
		
		if (prevElem != null)
		{
			$(prevElem).after(preElemTemp);
		}
		else
		{
			$(this).after(preElemTemp);
		}
		$(preElemTemp)
			.mouseover(function(){
				event.drain();
				event.fill(this);
			})
			.mouseout(function(){
				event.drain();
				event.reset();
			});			
		$(preElemTemp).click(function() {
			settings.currentValue = $(this).children('a').text();
			$(valueElem).val(settings.currentValue);
			event.drain();
			event.fill(this);
			return false;
		});						
		prevElem = preElemTemp;
		preElemTemp = null;
		
		if (settings.showCancel && settings.cancelPosition == 'after' && i == count - 1) // append cancel option at the end
		{
			var CancelElem = $('<div class="cancel"><a href="#" title="' + settings.cancelTitle + '">' + settings.cancel + '</a></div>');
			prevElem = CancelElem;
			$(this).after(prevElem);	
		
			$(CancelElem)
				.mouseover(function(){
					//event.drain();
					$(this).addClass('grade_on')
				})
				.mouseout(function(){
					event.reset();
					$(this).removeClass('grade_on')
				});
		
			// click events.
			$(CancelElem).click(function() {
				settings.currentValue = $(this).children('a').text();
				$(valueElem).val(settings.currentValue);
				event.drain();
				return false;
			});
		}
		
		if (i == count - 1 && initialIndex > -1) // set the active stars to the current value
		{
			var stars = $(valueElem).siblings('.grade');
			$(stars)
				.children('a').css('width', '100%').end()
				.slice(0, initialIndex + 1).addClass('grade_on').end();
		}
		
		//remove this checkbox
		$(this).remove();
		if(i + 1 == this.length)
		{    
			event.reset();									
		}
		
	});
};
