var allready_called = new Array();
;if(window.jQuery) (function($){

	if ($.browser.msie) try { document.execCommand("BackgroundImageCache", false, true)} catch(e) { }
	// default settings
	$.rating = {
		cancel: 'Cancel Rating',   // advisory title for the 'cancel' link
		cancelValue: '',           // value to submit when user click the 'cancel' link
		split: 0,                  // split the star into how many parts?
		disableHover : [],
		position : 'horizontal',
		starWidth: 16,
		// required properties:
		groups: {},// allows multiple star ratings on one page
		event: {// plugin event handlers
			fill: function(n, el, settings, state){ // fill to the current mouse position.
		
				if (state == 'hover')
				{
					this.drain(n);
						
						if ( (jQuery.inArray(n,$.rating.disableHover)) == -1)
						{	
							
							if (settings.position == 'vertical')
							{	
								$(el).nextAll('.star_group_'+n).andSelf().addClass('star_'+(state || 'hover'));
							}
							else
							{
								$(el).prevAll('.star_group_'+n).andSelf().addClass('star_'+(state || 'hover'));
							}
						}
						// focus handler, as requested by focusdigital.co.uk
						var lnk = $(el).children('a'); val = lnk.text();
						if(settings.focus) settings.focus.apply($.rating.groups[n].valueElem[0], [val, lnk[0]]);
				}	
				else
				{				
					if ( (jQuery.inArray(n,allready_called)) == -1)
					{
						allready_called.push(n);				
						this.drain(n);
						
						if ( (jQuery.inArray(n,$.rating.disableHover)) == -1)
						{	
							
							if (settings.position == 'vertical')
							{	
								$(el).nextAll('.star_group_'+n).andSelf().addClass('star_'+(state || 'hover'));
							}
							else
							{
								$(el).prevAll('.star_group_'+n).andSelf().addClass('star_'+(state || 'hover'));
							}
						}
						// focus handler, as requested by focusdigital.co.uk
						var lnk = $(el).children('a'); val = lnk.text();
						if(settings.focus) settings.focus.apply($.rating.groups[n].valueElem[0], [val, lnk[0]]);
					}
				}
			
			},
			drain: function(n, el, settings)			
			{  
				if ( (jQuery.inArray(n,$.rating.disableHover)) == -1)
				{	
					$.rating.groups[n].valueElem.siblings('.star_group_'+n).removeClass('star_on').removeClass('star_hover');
				}
			},
			reset: function(n, el, settings)
			{ 
				if(!$($.rating.groups[n].current).is('.cancel'))
				{
					if (settings.position == 'vertical')
					{	
						$($.rating.groups[n].current).nextAll('.star_group_'+n).andSelf().addClass('star_on');
					}
					else
					{	
						$($.rating.groups[n].current).prevAll('.star_group_'+n).andSelf().addClass('star_on');
					}
				}
				
				var lnk = $(el).children('a'); val = lnk.text();
				if(settings.blur) settings.blur.apply($.rating.groups[n].valueElem[0], [val, lnk[0]]);
			},
			click: function(n, el, settings)
			{ // Selected a star or cancelled

				if ((jQuery.inArray(n,$.rating.disableHover)) == -1)
				{
					$(el).parent().children('div').removeClass("star_live").css('cursor','default');
					$.rating.groups[n].current = el;
					var lnk = $(el).children('a'); val = lnk.text();
					// Set value
					$.rating.groups[n].valueElem.val(val);
					// Update display
					$.rating.event.drain(n, el, settings);
					$.rating.event.reset(n, el, settings);
					// click callback, as requested here: http://plugins.jquery.com/node/1655
					if (settings.callback) settings.callback.apply($.rating.groups[n].valueElem[0], [val, lnk[0]]);
					$.rating.disableHover.push(n);
				}

			}
		}// plugin events
	};

	$.fn.rating = function(instanceSettings)
	{
		 
		if (this.length==0) return this; // quick fail

		instanceSettings = $.extend(
			{}/* new object */,
			$.rating/* global settings */,
			instanceSettings || {} /* just-in-time settings */
		);

		// loop through each matched element
		this.each(function(i)
		{	
			var settings = $.extend(
				{}/* new object */,
				instanceSettings || {} /* current call settings */,
				($.metadata? $(this).metadata(): ($.meta?$(this).data():null)) || {} /* metadata settings */
			);

			////if(window.console) console.log([this.name, settings.half, settings.split], '#');

			// Generate internal control ID
			// - ignore square brackets in element names
			var n = (this.name || 'unnamed-rating').replace(/\[|\]+/g, "_");

			// Grouping
			if(!$.rating.groups[n]) $.rating.groups[n] = {count: 0};
			i = $.rating.groups[n].count; $.rating.groups[n].count++;

			// Accept readOnly setting from 'disabled' property
			$.rating.groups[n].readOnly = $.rating.groups[n].readOnly || settings.readOnly || $(this).attr('disabled');

			// Things to do with the first element...
			if(i == 0)
			{
				// Create value element (disabled if readOnly)
				$.rating.groups[n].valueElem = $('<input type="hidden" name="' + n + '" value=""' + (settings.readOnly ? ' disabled="disabled"' : '') + '/>');
				// Insert value element into form
				$(this).before($.rating.groups[n].valueElem);

				if($.rating.groups[n].readOnly || settings.required){
					// DO NOT display 'cancel' button
				}
				else{
					// Display 'cancel' button
					$(this).before(
						$('<div class="cancel"><a title="' + settings.cancel + '">' + settings.cancelValue + '</a></div>')
						.mouseover(function(){ $.rating.event.drain(n, this, settings); $(this).addClass('star_on'); })
						.mouseout(function(){ $.rating.event.reset(n, this, settings); $(this).removeClass('star_on'); })
						.click(function(){ $.rating.event.click(n, this, settings); })
					);
				}
			}; // if (i == 0) (first element)

			// insert rating option right after preview element
			
			
			eStar = $('<div class="star"><a title="' + (this.title || this.value) + '">' + this.value + '</a></div>');
			$(this).after(eStar);
			

			// Half-stars?
			if(settings.half) settings.split = 2;

			// Prepare division settings
			if(typeof settings.split=='number' && settings.split>0){
				var stw = ($.fn.width ? $(eStar).width() : 0) || settings.starWidth;
				var spi = (i % settings.split), spw = Math.floor(stw/settings.split);
				$(eStar)
				// restrict star's width and hide overflow (already in CSS)
				.width(spw)
				// move the star left by using a negative margin
				// this is work-around to IE's stupid box model (position:relative doesn't work)
				.find('a').css({ 'margin-left':'-'+ (spi*spw) +'px' })
			};

			// Remember group name so controls within the same container don't get mixed up
			$(eStar).addClass('star_group_'+n);

			// readOnly?
			if($.rating.groups[n].readOnly)//{ //save a byte!
				// Mark star as readOnly so user can customize display
				$(eStar).addClass('star_readonly');
			//}  //save a byte!
			else
			{
				$(eStar).addClass('star_live')
				.mouseover(function(){  $.rating.event.drain(n, this, settings); $.rating.event.fill(n, this, settings, 'hover'); })
				.mouseout(function(){ $.rating.event.drain(n, this, settings); $.rating.event.reset(n, this, settings); })
				.click(function(){ $.rating.event.click(n, this, settings); });
			}; //save a byte!

			////if(window.console) console.log(['###', n, this.checked, $.rating.groups[n].initial]);
			if(this.checked) $.rating.groups[n].current = eStar;

			//remove this checkbox
			$(this).remove();

			// reset display if last element
			if(i + 1 == this.length) $.rating.event.reset(n, this, settings);

		}); // each element

		// initialize groups...
		
		for(n in $.rating.groups)
		{ 
			(function(c, v, n){ if(!c) return;
				$.rating.event.fill(n, c, instanceSettings || {}, 'on');
				$(v).val($(c).children('a').text());
			})
			($.rating.groups[n].current, $.rating.groups[n].valueElem, n);
		}; 

		return this; // don't break the chain...
		
	};


/*# AVOID COLLISIONS #*/
})(jQuery);
/*# AVOID COLLISIONS #*/
