﻿// Author: Rémy Elazare
// This code has been downloaded from http://webscripts.softpedia.com/scriptDownload/jPaginator-Download-69468.html
(function ($) {
    $.fn.jPaginator = function (o) {
        if (this.size() != 1)
            $.error('You must use this plugin with a unique element');

        var s = {
            selectedPage: null,
            nbPages: 100,
            nbVisible: 10,
            widthPx: 30,
            marginPx: 1,
            overBtnLeft: null,
            overBtnRight: null,
            maxBtnLeft: null,
            maxBtnRight: null,
            withSlider: true,
            withAcceleration: true,
            speed: 2,
            coeffAcceleration: 2,
            minSlidesForSlider: 3,
            onPageClicked: null
        };

        var c = {
            realWid: 0,
            curNum: 1,
            infRel: 0,
            cInfMax: 0,
            cInf: 0,
            nbMove: 0,
            isMoving: false,
            isLimitL: false,
            isLimitR: false,
            listenSlider: true
        };

        return this.each(function () {
            var $this = $(this);
            if (o) $.extend(s, o);

            init();

            // events
            $(this).bind('reset', function (event, o) {
                $.extend(s, o);
                init();
            });

            if (s.withSlider) {
                $this.find(".paginator_slider").slider({ animate: false });

                $this.find(".paginator_slider").bind("slidechange.jPaginator", function (event, ui) {
                    return handleSliderChange(event, ui);
                });

                $this.find(".paginator_slider").bind("slide.jPaginator", function (event, ui) {
                    return handleSliderChange(event, ui);
                });
            }

            if (s.overBtnLeft) {
                $(s.overBtnLeft).bind('mouseenter.jPaginator', function () {
                    return onEnterButton($(this), 'left');
                });
            }
            if (s.overBtnLeft) {
                $(s.overBtnLeft).bind('mouseleave.jPaginator', function () {
                    return onLeaveButton($(this));
                });
            }
            if (s.overBtnRight) {
                $(s.overBtnRight).bind('mouseenter.jPaginator', function () {
                    return onEnterButton($(this), 'right');
                });
            }
            if (s.overBtnRight) {
                $(s.overBtnRight).bind('mouseleave.jPaginator', function () {
                    return onLeaveButton($(this));
                });
            }

            if (s.maxBtnLeft) {
                $(s.maxBtnLeft).bind('click.jPaginator', function () {
                    return moveToLimit('left');
                });
            }
            if (s.maxBtnRight) {
                $(s.maxBtnRight).bind('click.jPaginator', function () {
                    return moveToLimit('right');
                });
            }

            $this.find(".paginator_p").bind('mouseenter.jPaginator', function () {
                return onEnterNum($(this));
            });

            $this.find(".paginator_p").bind('mouseleave.jPaginator', function () {
                return onLeaveNum($(this));
            });

            function onClickNum(e) {
                var newPage = 1 * e.html();
                $this.find(".paginator_p.selected").removeClass("selected");
                s.selectedPage = newPage;

                goToSelectedPage();
                $($this.find(".paginator_p_bloc .paginator_p").get(s.selectedPage - c.curNum + 1)).addClass("selected");

                if (s.onPageClicked)
                    s.onPageClicked.call(this, $this, s.selectedPage);
            };

            function onEnterButton(e, dir) {
                c.isMoving = true;
                move(dir);
            };

            function onLeaveButton(e) {
                reset();
            };

            function onEnterNum(e) {
                $this.find(".paginator_p.over").removeClass("over");
                e.addClass("over");
            };

            function onLeaveNum(e) {
                $this.find(".paginator_p.over").removeClass("over");
            };

            function goToSelectedPage() {
                var newNum = s.selectedPage - Math.floor((s.nbVisible - 1) / 2);
                updateNum(newNum);

                c.listenSlider = false;
                moveSliderTo(c.cInf);
                c.listenSlider = true;
            };

            function updateNum(newNum) {
                $this.find(".paginator_p.selected").removeClass("selected");

                newNum = Math.min(s.nbPages - s.nbVisible + 1, newNum);
                newNum = Math.max(1, newNum);

                var n = newNum - 2;
                $this.find(".paginator_p_bloc .paginator_p").each(function (i) {
                    n += 1;
                    $(this).html(n);
                    if (s.selectedPage == n) {
                        $(this).addClass("selected");
                    }
                });

                $this.find(".paginator_p_bloc").css("left", "-" + c.realWid + "px");

                c.curNum = newNum;
                c.cInf = (newNum - 1) * c.realWid;
                c.infRel = 0;
            };

            function moveSliderTo(pos) {
                var newPc = Math.round((pos / c.cInfMax) * 100);
                var oldPc = $this.find(".paginator_slider").slider("option", "value");

                if (newPc != oldPc) {
                    $this.find(".paginator_slider").slider("option", "value", newPc);
                }
            };

            function handleSliderChange(e, ui) {
                if (!c.listenSlider) return;

                if (!c.isMoving) {
                    moveToPc(ui.value);
                }
            };

            function moveToPc(pc) {
                pc = Math.min(100, pc);
                pc = Math.max(0, pc);

                var realInf = Math.round(c.cInfMax * pc / 100);
                var gap = realInf - c.cInf;

                if (pc == 100) { updateNum(s.nbPages - s.nbVisible + 1); return; };
                if (pc == 0) { updateNum(1); return; };

                moveGap(gap);
            };


            function moveGap(gap) {
                var iGap = Math.abs(gap) / gap;
                var pxGap = c.infRel + gap;
                var pageGap = iGap * Math.floor(Math.abs(pxGap) / c.realWid);
                var dGap = pxGap % c.realWid;

                c.infRel = dGap;

                var cInfTmp = (c.curNum - 1) * c.realWid + c.infRel;

                var newPage = c.curNum + pageGap;
                if (newPage < 1) { cInfTmp = -1 };
                if (newPage > s.nbPages) { cInfTmp = c.cInfMax + 1 };

                if (cInfTmp < 0) { updateNum(1); c.cInf = 0; c.infRel = 0; moveSliderTo(0); c.isLimitL = true; reset(); return; }
                if (cInfTmp > c.cInfMax) { updateNum(s.nbPages); c.cInf = c.cInfMax; c.infRel = 0; moveSliderTo(c.cInfMax); c.isLimitR = true; reset(); return; }

                c.isLimitL = false; c.isLimitR = false;

                c.cInf = cInfTmp;

                if (gap == 0) return;
                if (pageGap != 0) updateNum(newPage);

                moveSliderTo(c.cInf);
                $this.find(".paginator_p_bloc").css("left", -1 * dGap - c.realWid + "px");

            };

            function reset() {
                c.nbMove = 0;
                c.isMoving = false;
            };

            function moveToLimit(dir) {
                if (c.isLimitR && dir == 'right') { return; }
                if (c.isLimitL && dir == 'left') { return; }

                var gap = Math.round(c.cInfMax / 10);

                if (dir == 'left') { gap *= -1; }

                moveGap(gap);

                setTimeout(function () {
                    c.nbMove += 1;
                    moveToLimit(dir);
                }, 20);
            };

            function move(dir) {
                if (c.isMoving) {
                    var gap = Math.min(Math.abs(s.speed), 5);
                    var coeff = Math.min(Math.abs(s.coeffAcceleration), 5);
                    if (s.withAcceleration) {
                        gap = Math.round(gap + Math.round(coeff * (c.nbMove * c.nbMove) / 80000));
                    }

                    if (dir == 'left') { gap *= -1; }

                    moveGap(gap);

                    setTimeout(function () {
                        c.nbMove += 1;
                        move(dir);
                    }, 10);
                }
            };

            function init() {
                var totalSlides, bSlider, bOver;

                s.nbVisible = Math.min(s.nbVisible, s.nbPages);

                $this.find(".paginator_p_bloc > .paginator_p").remove();
                // init c data
                for (i = 1; i <= s.nbVisible + 2; i++) {
                    $this.find(".paginator_p_bloc").append($("<a class='paginator_p'></a>"));
                }
                // hide over and max buttons if they're useless...    
                bOver = (s.nbVisible < s.nbPages);
                if (s.overBtnLeft) {
                    if (bOver) $(s.overBtnLeft).show(); else $(s.overBtnLeft).hide();
                }
                if (s.overBtnRight) {
                    if (bOver) $(s.overBtnRight).show(); else $(s.overBtnRight).hide();
                }
                if (s.maxBtnLeft) {
                    if (bOver) $(s.maxBtnLeft).show(); else $(s.maxBtnLeft).hide();
                }
                if (s.maxBtnRight) {
                    if (bOver) $(s.maxBtnRight).show(); else $(s.maxBtnRight).hide();
                }

                if (!bOver) {
                    $this.find(".paginator_slider").hide();
                    $this.find(".paginator_slider").children().hide();
                } else {
                    totalSlides = Math.ceil(s.nbPages / s.nbVisible); bSlider = s.withSlider;
                    if (totalSlides < s.minSlidesForSlider) bSlider = false; // hide slider when needed
                    else bSlider = s.withSlider;

                    if (!bSlider) {
                        $this.find(".paginator_slider").hide();
                        $this.find(".paginator_slider").children().hide();
                    } else {
                        $this.find(".paginator_slider").show();
                        $this.find(".paginator_slider").children().show();
                    }
                }

                var borderPx = 0;
                var sBorder = $this.find(".paginator_p").first().css("border-left-width");
                if (sBorder.indexOf("px") > 0) {
                    borderPx = sBorder.replace("px", "") * 1;
                }

                c.realWid = s.widthPx + s.marginPx * 2 + borderPx * 2;

                var widAll = 1 * c.realWid * s.nbVisible;

                $this.find(".paginator_p").css("width", s.widthPx + "px");
                $this.find(".paginator_p").css("margin", "0 " + s.marginPx + "px 0 " + s.marginPx + "px");

                $this.find(".paginator_p_wrap").css("width", widAll + "px");
                $this.find(".paginator_slider").css("width", widAll + "px");

                c.cInfMax = s.nbPages * c.realWid - (s.nbVisible * c.realWid);

                // init selected page
                s.selectedPage = Math.min(s.selectedPage, s.nbPages);
                goToSelectedPage(); moveGap(0);
                if (s.selectedPage)
                    $($this.find(".paginator_p_bloc .paginator_p").get(s.selectedPage - c.curNum + 1)).addClass("selected");

                $this.find(".paginator_p").bind('click.jPaginator', function () {
                    return onClickNum($(this));
                });
            }
        });
    };
})(jQuery);
