﻿(function ($)
{
	$.fn.extend(
	{
		scrollList: function (direction, pixels_per_second, delay)
		{
			if ('undefined' == typeof (pixels_per_second))
			{
				pixels_per_second = 20;
			}

			if ('undefined' == typeof (delay))
			{
				delay = 1000;
			}

			if ('undefined' == typeof (direction) || -1 == $.inArray(direction, ['up', 'down', 'left', 'right']))
			{
				direction = 'up';
			}

			var $list = $(this);
			var $lis = $list.children('li');
			var $current_li;
			var pixels_per_millisecond = pixels_per_second / 1000;
			var easing = (delay == 0) ? 'linear' : 'swing';

			// Set position relative if position is currently static so top/left properties will affect it's position            
			if ('static' == $list.css('position'))
			{
				$list.css('position', 'relative');
			}

			/*
			* Remove text nodes between lis since they add spacing that 
			* will be removed when shifting lis from end to end
			*/
			if ('left' == direction || 'right' == direction)
			{
				var text = [];
				this.each(function ()
				{
					var children = this.childNodes;
					for (var i = 0; i < children.length; i++)
					{
						var child = children[i];
						if (child.nodeType == 3)
						{
							text.push(child);
						}
					}
				});

				$(this.pushStack(text)).remove();
			}

			if ('up' == direction || 'left' == direction)
			{
				$current_li = $lis.filter(':first');
			}
			else
			{

				/* 
				* If right or down, move the last li to the beginning and move the entire
				* list up/left to allow the next li to scroll into view rather than just appear.
				*/
				var $last_li = $lis.filter(':last');
				if ('down' == direction)
				{
					$list.css('top', '-' + $last_li.outerHeight() + 'px');
				}
				else
				{
					$list.css('left', '-' + $last_li.outerWidth() + 'px');
				}
				$last_li.remove();
				$lis.filter(':first').before($last_li);
				$lis = $list.children('li');
				$current_li = $lis.filter(':last');
			}


			function scrollListNext()
			{
				var distance, property;
				var css = {};

				if ('up' == direction || 'down' == direction)
				{
					property = 'top';
					distance = $current_li.outerHeight();
				}
				else
				{
					property = 'left';
					distance = $current_li.outerWidth();
				}

				switch (direction)
				{
					case 'up':
						css.top = '-' + distance + 'px';
						break;

					case 'right':
						css.left = 0;
						break;

					case 'down':
						css.top = 0;
						break;

					case 'left':
						css.left = '-' + distance + 'px';
						break;
				};

				var duration = distance / pixels_per_millisecond;
				$list.animate(css, duration, easing, function ()
				{
					$current_li.remove();
					if ('up' == direction || 'left' == direction)
					{
						$list.css(property, 0);
						$lis.filter(':last').after($current_li);
						$lis = $list.children('li');
						$current_li = $lis.filter(':first');
					}
					else
					{
						$list.css(property, '-' + distance + 'px');
						$lis.filter(':first').before($current_li);
						$lis = $list.children('li');
						$current_li = $lis.filter(':last');
					}

					setTimeout(scrollListNext, delay);
				});
			};

			setTimeout(scrollListNext, delay);
		}
	});
})(jQuery);
