﻿(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);

        window.pagerTimer = null;

        var previous = 0;

        var el = $(document);

        if (settings.listenElement) {
            if (typeof (settings.listenElement) == "string") {
                el = $('#' + settings.listenElement);
            }
            else {
                el = $(settings.listenElement);
            }
        }

        el.bind('pagerNext', function(e, data) {
            $.timer(10, function(ntimer) {
                ntimer.stop();
                moveNext(data.container);
                if (data && data.callback) {
                    data.callback(data.arguments);
                }
            });
        });

        el.bind('pagerPrevious', function(e, data) {
            $.timer(10, function(ntimer) {
                ntimer.stop();
                movePrevious(data.container);
                if (data && data.callback) {
                    data.callback(data.arguments);
                }
            });
        });

        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 (window.pagerTimer)
                window.pagerTimer.stop();
            if (currentPage === 0)
                currentPage = maxPage - 1;
            else
                currentPage--;

            var thisPage = currentPage;
            var thisCallback = callback;
            window.pagerTimer = $.timer(
                300,
                function(timer) {
                    thisCallback(thisPage);
                    timer.stop();
                }
            );
            render(container);
            trackAction("Prev");
        };

        var moveNext = function(container) {
            if (window.pagerTimer) {
                window.pagerTimer.stop();
            }
            if (currentPage == maxPage - 1)
                currentPage = 0;
            else
                currentPage++;

            var thisPage = currentPage;
            var thisCallback = callback;

            window.pagerTimer = $.timer(
                300,
                function(timer) {
                    thisCallback(thisPage);
                    timer.stop();
                }
            );
            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;
            var thisPage = currentPage;
            var thisCallback = callback;
            window.pagerTimer = $.timer(
                300,
                function(timer) {
                    thisCallback(thisPage);
                    timer.stop();
                }
            );
            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;
            var thisPage = currentPage;
            var thisCallback = callback;
            window.pagerTimer = $.timer(
                300,
                function(timer) {
                    thisCallback(thisPage);
                    timer.stop();
                }
            );
            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();

            if (maxPage <= 1)  // just dont create if only one page.
                return;

            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 ji = jumpLinkInterval; ji < max; ji += jumpLinkInterval)
                        jumpList.append("<div>" + ji + "</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 && $(container).parent().find("#DivPreviousNext").length === 0) {
                var prevNextContainer = $(document.createElement("div"));
                prevNextContainer.attr("id", "DivPreviousNext");
                container.parent().append(prevNextContainer);

                var triggerData = { container: $.extend({}, container) };

                var previousLink = createLink('<abbr title="Previous">Prev</abbr>', false);
                previousLink.attr('id', "previousLink");
                prevNextContainer.append(previousLink);
                previousLink.click
				(
					function() {
					    $(document).trigger("pagerPrevious", triggerData);
					}
				);

                var nextLink = createLink("Next", false);
                nextLink.attr("id", "nextLink");
                prevNextContainer.append(nextLink);



                nextLink.click
				(
					function() {
					    $(document).trigger("pagerNext", triggerData);
					}
				);

                if (container.attr("initialized") == "false") {
                    $(document).keydown
					(
						function(e) {
						    if (!e) e = window.event;

						    switch (e.keyCode) {
						        case 37:
						            $(document).trigger("pagerPrevious", triggerData);
						            break;
						        case 39:
						            $(document).trigger("pagerNext", triggerData);
						            break;
						        default:
						            return true;
						    }

						    if (e.stopPropagation)
						        e.stopPropagation();
						}
					);
                }
            }

            $("a.pager").click
			(
				function() {
				    if (window.pagerTimer)
				        window.pagerTimer.stop();

				    if ($(this).text() == "...") {
				        if ($(this).attr("id") == "pagePrevEllipsis")
				            movePrevPage(container);
				        else
				            moveNextPage(container);
				        return;
				    }
				    else if (isNaN($(this).text()))
				        return;

				    previous = currentPage;
				    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() {
            return currentPage;
        };

        this.setPage = function(page) {
            currentPage = page;
            render($(this));
        };

        this.getClickablePages = function() {
            var pages = [];
            var vis = $(".pager", this);
            vis.each(function(idx, elem) {
                if ($(elem).text() != "jump")
                    pages.push($(elem).text());
            });

            var firstEllipsis = true;
            for (var i = 0, l = pages.length; i < l; i++) {
                var text = pages[i];
                var currentPage = this.getPage() + 1;
                if (isNaN(parseInt(text, 10))) {
                    text = (firstEllipsis) ? currentPage - 5 : currentPage + 5;
                    firstEllipsis = false;
                }
                pages[i] = parseInt(text, 10) - 1;
            }
            return pages;
        };

        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);

