﻿(function($)
{
	$.fn.pager = function(currentPage, max, increment, callback, settings)
	{
		settings = $.extend
		(
			{
				maxLinks: 11,
				showJump: false
			},
			settings
		);

		if (currentPage % 1 !== 0)
			throw "currentPage must be an integer.";

		var dropDownMenuActive = null;
		var maxPage = Math.ceil(max / increment);

		var createLink = function(content, unclickable)
		{
			var link;

			if (unclickable)
				link = $(document.createElement("div"));
			else
				link = $(document.createElement("a"));

			link.addClass("pager");
			link.append(content);

			return link;
		};

		var movePrevious = function(container)
		{
			if (currentPage === 0)
				currentPage = maxPage - 1;
			else
				currentPage--;

			callback(currentPage);
			render(container);
			trackAction("Prev");
		};

		var moveNext = function(container)
		{
			if (currentPage == maxPage - 1)
				currentPage = 0;
			else
				currentPage++;
			callback(currentPage);
			render(container);
			trackAction("Next");
		};

		var moveNextPage = function(container)
		{
			var pageCount = Math.max(1, settings.maxLinks - 2);
			if (currentPage >= maxPage - 1 - pageCount)
				currentPage = maxPage - 1;
			else
				currentPage += pageCount;
			callback(currentPage);
			render(container);
			trackAction("NextPage");
		};

		var movePrevPage = function(container)
		{
			var pageCount = Math.max(1, settings.maxLinks - 2);
			if (currentPage <= pageCount - 1)
				currentPage = 0;
			else
				currentPage -= pageCount;
			callback(currentPage);
			render(container);
			trackAction("PrevPage");
		};

		var setJumpContainerPosition = function()
		{
			var jumpLink = $("a[id=JumpLink]");

			if (jumpLink.length > 0)
			{
				var jumpList = $("#DivJumpContainer");
				jumpList.css("left", jumpLink.offset().left + "px");
				jumpList.css("top", jumpLink.offset().top + jumpLink.outerHeight() + 2 + "px");
			}
		};

		var setActiveMenu = function(menu)
		{
			dropDownMenuActive = menu;

			$.timer
			(
				200,
				function(timer)
				{
					dropDownMenuActive = null;
					timer.stop();
				}
			);
		};

		var onJumpLinkClick = function(e)
		{
			var menu = $("#DivJumpContainer");

			if (isMenuActive(menu))
				menu.slideUp();
			else
			{
				setJumpContainerPosition();
				setActiveMenu(menu);
				menu.slideDown();
				e.stopPropagation();
			}
		};

		var onJumpDivClick = function()
		{
			var jumpList = $("#DivJumpContainer");
			var container = $("#" + jumpList.attr("container"));

			currentPage = parseInt($(this).text(), 10) - 1;
			jumpList.slideToggle();
			callback(currentPage);
			render(container);
			trackAction("Jump");
		};

		var onJumpDivMouseover = function()
		{
			$(this).removeClass("inactive").addClass("active");
		};

		var onJumpDivMouseout = function()
		{
			$(this).removeClass("active").addClass("inactive");
		};

		var isMenuActive = function(menu)
		{
			return menu.css("display") == "block";
		};

		$("body").click
		(
			function()
			{
				$(".dropDownMenu").each
				(
					function()
					{
						var menu = $(this);
						if (dropDownMenuActive === null || menu.attr("id") != dropDownMenuActive.attr("id"))
							menu.slideUp();
					}
				);
			}
		);

		var render = function(container)
		{
			container.empty();

			var isCurrent = false;
			var linkCount = 1; // since the first link is always visible
			var ellipsis = createLink("...", false);

			container.append(ellipsis);
			var ellipsisWidth = ellipsis.width();
			ellipsis.remove();

			isCurrent = currentPage === 0;
			var firstPagerLink = createLink(1, isCurrent);
			if (isCurrent)
				firstPagerLink.addClass("pagercurrent");
			container.append(firstPagerLink);
			var firstPagerLinkWidth = firstPagerLink.width();

			isCurrent = (currentPage == maxPage - 1);
			var lastPagerLink = createLink(maxPage, isCurrent);
			if (isCurrent)
				lastPagerLink.addClass("pagercurrent");
			container.append(lastPagerLink);
			var lastPagerLinkWidth = lastPagerLink.width();
			lastPagerLink.remove();

			var minWidth = firstPagerLinkWidth + (ellipsisWidth * 2) + lastPagerLinkWidth;
			var ellipsisVisible = false;

			if (currentPage >= settings.maxLinks - 2 && maxPage > settings.maxLinks)
			{
				var firstEllipsis = ellipsis.clone();
				firstEllipsis.attr("id", "pagePrevEllipsis");
				container.append(firstEllipsis);
				ellipsisVisible = true;
			}

			var startPage = 2;

			if (ellipsisVisible)
			{
				var startPageOffset = Math.ceil((settings.maxLinks - 2) / 2) - 2;
				startPage = currentPage - startPageOffset;

				if (startPage > maxPage - settings.maxLinks)
					startPage = maxPage - settings.maxLinks + 2;
			}
			if (startPage <= 0)
				startPage = 2;

			for (var i = startPage; i <= maxPage; i++)
			{
				isCurrent = (currentPage == i - 1);
				var pagerLink = createLink(i, isCurrent);
				if (isCurrent)
					pagerLink.addClass("pagercurrent");
				container.append(pagerLink);
				linkCount++;

				if (linkCount < settings.maxLinks)
					continue;

				pagerLink.remove();
				container.append(lastPagerLink);

				if (i != maxPage)
				{
					ellipsis.insertBefore(lastPagerLink);
					ellipsis.attr("id", "pageNextEllipsis");
					ellipsisVisible = true;
				}

				break;
			}

			if (settings.showJump)
			{
				var jumpLink = createLink("jump", false);
				jumpLink.attr("id", "JumpLink");
				container.append(jumpLink);

				var jumpLinkItems = 20;
				var jumpLinkInterval = (max / jumpLinkItems);
				jumpLinkInterval = parseInt((jumpLinkInterval + 4) / 5, 10) * 5;
				jumpLink.click(onJumpLinkClick);

				if (max <= 20)
					jumpLink.hide();
				else if (container.attr("initialized") == "false")
				{
					var jumpList = $(document.createElement("div"));
					jumpList.attr("id", "DivJumpContainer");
					jumpList.attr("container", container.attr("id"));
					jumpList.addClass("bordercolor");
					jumpList.addClass("dropDownMenu");
					jumpList.css("line-height", "1.1em");
					jumpList.css("position", "absolute");
					jumpList.css("display", "none");
					jumpList.css("border-width", "1px");
					jumpList.css("border-style", "solid");
					jumpList.css("width", "10ex");
					jumpList.css("text-align", "center");
					jumpList.css("margin-left", "2px");
					jumpList.css("z-index", "500");
					$("body").append(jumpList);

					var height = 0;

					for (var i = jumpLinkInterval; i < max; i += jumpLinkInterval)
						jumpList.append("<div>" + i + "</div>");

					var jumpDivs = $("#DivJumpContainer div");
					jumpDivs.addClass("inactive");
					jumpDivs.css("padding-right", "1ex");
					jumpDivs.css("cursor", "pointer");
					jumpDivs.mouseover(onJumpDivMouseover);
					jumpDivs.mouseout(onJumpDivMouseout);
					jumpDivs.click(onJumpDivClick);
				}
			}

			if (maxPage > 1 && $("#DivPreviousNext").length === 0)
			{
				var prevNextContainer = $(document.createElement("div"));
				prevNextContainer.attr("id", "DivPreviousNext");
				container.parent().append(prevNextContainer);

				var previousLink = createLink('<abbr title="Previous">Prev</abbr>', false);
				prevNextContainer.append(previousLink);
				previousLink.click
				(
					function()
					{
						movePrevious(container);
					}
				);

				var nextLink = createLink("Next", false);
				prevNextContainer.append(nextLink);
				nextLink.click
				(
					function()
					{
						moveNext(container);
					}
				);

				if (container.attr("initialized") == "false")
				{
					$(document).unbind("keydown");
					
					$(document).keydown
					(
						function(e)
						{
							if (!e) e = window.event;

							switch (e.keyCode)
							{
								case 37:
									movePrevious(container);
									break;
								case 39:
									moveNext(container);
									break;
								default:
									return true;
							}

							if (e.stopPropagation)
								e.stopPropagation();
						}
					);
				}
			}

			$("a.pager").click
			(
				function()
				{
					if ($(this).text() == "...")
					{
						if ($(this).attr("id") == "pagePrevEllipsis")
							movePrevPage(container);
						else
							moveNextPage(container);
						return;
					}
					else if (isNaN($(this).text()))
						return;

					currentPage = parseInt($(this).text(), 10) - 1;
					callback(currentPage);
					render(container);
					trackAction("Page");
				}
			);

			container.attr("initialized", "true");
		};

		$(window).resize(setJumpContainerPosition);

		this.getPageCount = function(page)
		{
			return maxPage;
		};

		this.getPage = function(page)
		{
			return currentPage;
		};

		this.setPage = function(page)
		{
			currentPage = page;
			render($(this));
		};

		return this.each(function()
		{
			var container = $(this);
			container.attr("initialized", "false");
			render(container);
		});
	};

	trackAction = function(action)
	{
		if (typeof urchinTracker != "undefined")
		{
			var track = location.href;
			track = track.toLowerCase();
			var posDot = track.lastIndexOf('.');
			var posSlash = track.lastIndexOf('/');
			if (posSlash === null)
			{
				posSlash = track.lastIndexOf('\\');
				if (posSlash === null)
					posSlash = -1;
			}
			if (posDot && posSlash)
			{
				track = track.substring(posSlash + 1, posDot) + action;
				urchinTracker(track);
			}
		}
	};
})(jQuery);
