(function($)
{
	if ($.browser.msie)
	{
		var version = $.browser.version.split('.');
		if (version.length > 0 && (version[0] > 5
			|| (version[0] == 5 && version.length > 1 && version[1] >= 5)))
			$.teedyayRotationModel = 1;
		else
			$.teedyayRotationModel = null;
	}
	else if ($.browser.mozilla)
	{
		var version = $.browser.version.split('.');
		if (version.length > 0 && (version[0] > 1
			|| (version[0] == 1 && version.length > 1 && (version[1] > 9
			|| (version[1] == 9 && version.length > 2 && version[2] >= 1)))))
			$.teedyayRotationModel = 2;
		else
			$.teedyayRotationModel = null;
	}
	else if ($.browser.safari)
		$.teedyayRotationModel = 3;
	else
		$.teedyayRotationModel = null;
	
	$.fx.step.rotation = function(fx)
	{
		if (fx.state == 0)
		{
			fx.start = $(fx.elem).data('teedyayRotation');
			$(fx.elem).rotationCheckHaveIEStartPos();
			if (fx.start == null)
				fx.start = 0;
			fx.end = parseInt(fx.end, 10);
		}

		$(fx.elem).setRotation(fx.end * fx.pos + fx.start * (1 - fx.pos));
	};

	$.fn.rotationCheckHaveIEStartPos = function()
	{
		return this.each(function()
		{
			if ($(this).data('teedyayRotationStartPos') == null)
			{
				var offset = $(this).offset();
				var startPos =
				{
					halfWidth : $(this).width() / 2,
					halfHeight : $(this).height() / 2
				}
				$(this).data('teedyayRotationStartPos', startPos);

				$(this).data('teedyayRotationNominalLeft', offset.left);
				$(this).data('teedyayRotationNominalTop', offset.top);
			}
		});
	};

	var degToRadians = Math.PI / 180;
	/* After http://msdn.microsoft.com/en-us/library/ms533014(VS.85).aspx for the IE bit */
	$.fn.setRotation = function(deg)
	{
		return this.each(function()
		{
			$(this).data('teedyayRotation', deg);

			if ($.teedyayRotationModel == 1)
			{
				$(this).rotationCheckHaveIEStartPos();
				if (deg == 0)
					$(this).css("filter", "");
				else
				{
					$(this).css("filter", "progid:DXImageTransform.Microsoft.Matrix(sizingMethod='auto expand')"); // or 'clip to original'
					var rad = deg * degToRadians ;
					var costheta = Math.cos(rad);
					var sintheta = Math.sin(rad);

					this.filters.item(0).M11 = costheta;
					this.filters.item(0).M12 = -sintheta;
					this.filters.item(0).M21 = sintheta;
					this.filters.item(0).M22 = costheta;
				}

				var offset = $(this).offset();
				$(this).css('left', ($(this).data('teedyayRotationNominalLeft') + $(this).data('teedyayRotationStartPos').halfWidth - $(this).width() / 2) + 'px');
				$(this).css('top', ($(this).data('teedyayRotationNominalTop') + $(this).data('teedyayRotationStartPos').halfHeight - $(this).height() / 2) + 'px');
			}
			else if ($.teedyayRotationModel == 2)
			{
				$(this).css("-moz-transform", "rotate(" + deg + "deg)");
			}
			else if ($.teedyayRotationModel == 3)
			{
				$(this).css("-webkit-transform", "rotate(" + deg + "deg)");
			}
		});
	};

	if ($.teedyayRotationModel == 1)
	{
		$.fx.step.left = function(fx)
		{
			if (fx.state == 0)
			{
				// We store the left position and half the width as it was at the beginning of the animation
				var horiData = {};
				horiData.halfWidth = $(fx.elem).width() / 2;
				horiData.leftCentre = $(fx.elem).offset().left + horiData.halfWidth;
				$(fx.elem).data('teedyayRotationHori', horiData);

				if (fx.start == null)
					fx.start = 0;
			}

			// This is as jQuery would normally calculate it
			var left = fx.end * fx.pos + fx.start * (1 - fx.pos);
			$(fx.elem).data('teedyayRotationNominalLeft', left);

			if ($(fx.elem).data('teedyayRotationStartPos') != null)
			{
				// .. but we measure relative to the element's centre, bearing in mind that its width may have changed
				left = left + $(fx.elem).data('teedyayRotationHori').halfWidth - $(fx.elem).width() / 2;
			}
			$(fx.elem).css('left', left + 'px');
		};

		$.fx.step.top = function(fx)
		{
			if (fx.state == 0)
			{
				// We store the top position and half the height as it was at the beginning of the animation
				var vertData = {};
				vertData.halfHeight = $(fx.elem).height() / 2;
				vertData.topCentre = $(fx.elem).offset().top + vertData.halfHeight;
				$(fx.elem).data('teedyayRotationVert', vertData);

				if (fx.start == null)
					fx.start = 0;
			}

			// This is as jQuery would normally calculate it
			var top = fx.end * fx.pos + fx.start * (1 - fx.pos);
			$(fx.elem).data('teedyayRotationNominalTop', top);

			if ($(fx.elem).data('teedyayRotationStartPos') != null)
			{
				// .. but we measure relative to the element's centre, bearing in mind that its height may have changed
				top = top + $(fx.elem).data('teedyayRotationVert').halfHeight - $(fx.elem).height() / 2;
			}
			$(fx.elem).css('top', top + 'px');
		};
	}
})(jQuery);
