/*

	scrollpane - jQuery Scroll Pane Plugin
	Author: 		Richard Metcalf
	Version:		1.0 (January 1, 2010)

*/
;
(function($){

    $.fn.scrollpane = function(opt){
        var sp = $.fn.scrollpane,
        over = function(e) {
            var o = sp.o[this.spindex];
            var doScrollH = false;
            var doScrollV = false;
            o.vW = $(o.$port).width();
            o.refW = o.vW/20;
            o.vH = $(o.$port).height();
            o.refH = o.vH/20;
            o.$clone = $(o.$pane).clone().css({
                'width':'',
                'height':'',
                'left':'',
                'top':''
            }).addClass(sp.c.cloneClass)[0];
            $(o.$port).append(o.$clone);
            $(o.$pane).width($(o.$clone).width()+1);
            $(o.$pane).height($(o.$clone).height()+1);
            o.modeW = 'scroll';
            o.modeH = 'scroll';
            o.mx = e.pageX;
            o.my = e.pageY;
            o.dx = $(o.$clone).width() - o.vW;
            o.dy = $(o.$clone).height() - o.vH;
            o.posX = 0;
            o.posY = 0;
            o.speedX = 0;
            o.speedY = 0;
            o.off = {};
            o.off.left = $(o.$pane).offset().left - $(o.$pane).position().left;
            o.off.top = $(o.$pane).offset().top - $(o.$pane).position().top;
            o.intervalX = null;
            o.intervalY = null;
            doScrollH = ((o.scroll == 'both' || o.scroll == 'h') && o.vW > 0);
            if (doScrollH && o.dx < 0) {
                $(o.$pane).animate({
                    left:0
                });
                doScrollH = false;
            }
            doScrollV = ((o.scroll == 'both' || o.scroll == 'v') && o.vH > 0);
            if (doScrollV && o.dy < 0) {
                $(o.$pane).animate({
                    top:0
                });
                doScrollV = false;
            }
            $(o.$indH).width(Math.round(o.vW*.2));
            if (o.indicatorH != 'off' && doScrollH) $(o.$indH).animate({
                opacity:.7
            },300);
            $(o.$indH).css('left',-$(o.$pane).position().left/o.dx*(o.vW*.8-parseInt($(o.$indH).css('margin-left'))-parseInt($(o.$indH).css('margin-right'))));
            $(o.$indV).height(Math.round(o.vH*.2));
            if (o.indicatorV != 'off' && doScrollV) $(o.$indV).animate({
                opacity:.7
            },300);
            $(o.$indV).css('top',-$(o.$pane).position().top/o.dy*(o.vH*.8-parseInt($(o.$indV).css('margin-top'))-parseInt($(o.$indV).css('margin-bottom'))));
            if (doScrollH || doScrollV) $(o.$port).bind('mousemove',move);
            if (doScrollV) $(o.$port).bind('mousewheel',wheel);

            o.onOver.call(o);
        },
        out = function() {
            var o = o = sp.o[this.spindex];
            if (o.intervalX) clearInterval(o.intervalX);
            if (o.intervalY) clearInterval(o.intervalY);
            $('.'+sp.c.cloneClass).remove();
            o.modeH = o.modeW = 'out';
            $(o.$indH).animate({
                opacity:0
            },400);
            $(o.$indV).animate({
                opacity:0
            },400);
            $(o.$port).unbind('mousemove',move);
            $(o.$port).unbind('mousewheel',wheel);
            o.onOut.call(o);
        },
        move = function(e) {
            var o = sp.o[this.spindex],
            incX,incY,
            mx2 = e.pageX,
            my2 = e.pageY,
            scrollX = function(){
                var pos;
                pos = parseInt($(o.$pane).position().left);
                if (o.posX < .1 && o.speedX < 0) o.speedX -= .5;
                if (o.posX > .9 && o.speedX > 0) o.speedX += .5;
                if (o.speedX < 0 && pos != 0) {
                    pos -= o.speedX;
                    if (Math.abs(pos+(o.dx*o.posX)) <= -o.speedX && o.posX >= .1) {
                        o.modeW = 'linear';
                        pos = -o.dx*o.posX;
                        o.speedX = 0;
                        clearInterval(o.intervalX);
                        o.intervalX = null;
                    }
                    if (pos>0) pos = 0;
                    $(o.$pane).css('left',pos);
                    $(o.$indH).css('left',-pos/o.dx*(o.vW*.8-parseInt($(o.$indH).css('margin-left'))-parseInt($(o.$indH).css('margin-right'))));
                }
                if (o.speedX > 0 && pos != -o.dx) {
                    pos -= o.speedX;
                    if (Math.abs(pos+(o.dx*o.posX)) <= o.speedX && o.posX <= .9) {
                        o.modeW = 'linear';
                        pos = -o.dx*o.posX;
                        o.speedX = 0;
                        clearInterval(o.intervalX);
                        o.intervalX = null;
                    }
                    if (pos<-o.dx) pos = -o.dx;
                    $(o.$pane).css('left',pos);
                    $(o.$indH).css('left',-pos/o.dx*(o.vW*.8-parseInt($(o.$indH).css('margin-left'))-parseInt($(o.$indH).css('margin-right'))));
                }
            },
            scrollY = function(){
                var pos;
                pos = parseInt($(o.$pane).position().top);
                if (o.posY < .1 && o.speedY < 0) o.speedY -= .5;
                if (o.posY > .9 && o.speedY > 0) o.speedY += .5;
                if (o.speedY < 0 && pos != 0) {
                    pos -= o.speedY;
                    if (Math.abs(pos+(o.dy*o.posY)) <= -o.speedY && o.posY >= .1) {
                        o.modeH = 'linear';
                        pos = -o.dy*o.posY;
                        o.speedY = 0;
                        clearInterval(o.intervalY);
                        o.intervalY = null;
                    }
                    if (pos>0) pos = 0;
                    $(o.$pane).css('top',pos);
                    $(o.$indV).css('top',-pos/o.dy*(o.vH*.8-parseInt($(o.$indV).css('margin-top'))-parseInt($(o.$indV).css('margin-bottom'))));
                }
                if (o.speedY > 0 && pos != -o.dy) {
                    pos -= o.speedY;
                    if (Math.abs(pos+(o.dy*o.posY)) <= o.speedY && o.posY <= .9) {
                        o.modeH = 'linear';
                        pos = -o.dy*o.posY;
                        o.speedY = 0;
                        clearInterval(o.intervalY);
                        o.intervalY = null;
                    }
                    if (pos<-o.dy) pos = -o.dy;
                    $(o.$pane).css('top',pos);
                    $(o.$indV).css('top',-pos/o.dy*(o.vH*.8-parseInt($(o.$indV).css('margin-top'))-parseInt($(o.$indV).css('margin-bottom'))));
                }
            };

            o.posX = (mx2-o.off.left)/o.vW;
            o.posY = (my2-o.off.top)/o.vH;

            if (o.posX > 0 && o.posX < 1 && o.posY > 0 && o.posY < 1) {
                if ((o.scroll == 'both' || o.scroll == 'h') && o.dx > 0 ) {

                    if (o.posX > 1) o.posX = 1;
                    if (o.posX < 0) o.posX = 0;

                    if (o.modeW == 'linear') {
                        if (o.posX < .1 || o.posX > .9) {
                            o.modeW = 'scroll';
                            o.mx = mx2;
                        } else {
                            $(o.$pane).css('left',-o.dx*o.posX);
                            $(o.$indH).css('left',o.posX*(o.vW*.8-parseInt($(o.$indH).css('margin-left'))-parseInt($(o.$indH).css('margin-right'))));
                        }
                    }
                    if (o.modeW == 'scroll') {
                        if (o.posX < .1 && o.speedX == 0) o.speedX = -1;
                        if (o.posX > .9 && o.speedX == 0) o.speedX = 1;
                        incX = mx2-o.mx;
                        if (Math.abs(incX)>o.refW*2) {
                            if ((incX<0 && o.speedX > 0) || (incX>0 && o.speedX < 0)) o.speedX = 0;
                            else o.speedX += (incX<0)?-1:1;
                            o.mx = mx2;
                        }
                        if (!o.intervalX && o.speedX) o.intervalX = setInterval(scrollX,o.timeoutX);
                    }
                }
                if ((o.scroll == 'both' || o.scroll == 'v') && o.dy > 0 ) {
                    if (o.posY > 1) o.posY = 1;
                    if (o.posY < 0) o.posY = 0;

                    if (o.modeH == 'linear') {
                        if (o.posY < .1 || o.posY > .9) {
                            o.modeH = 'scroll';
                            o.my = my2;
                        } else {
                            $(o.$pane).css('top',-o.dy*o.posY);
                            $(o.$indV).css('top',o.posY*(o.vH*.8-parseInt($(o.$indV).css('margin-top'))-parseInt($(o.$indV).css('margin-bottom'))));
                        }
                    }
                    if (o.modeH == 'scroll') {
                        if (o.posY < .1 && o.speedY == 0) o.speedY = -1;
                        if (o.posY > .9 && o.speedY == 0) o.speedY = 1;
                        incY = my2-o.my;
                        if (Math.abs(incY)>o.refH*2) {
                            if ((incY<0 && o.speedY > 0) || (incY>0 && o.speedY < 0)) o.speedY = 0;
                            else o.speedY += (incY<0)?-1:1;
                            o.my = my2;
                        }
                        if (!o.intervalY && o.speedY) o.intervalY = setInterval(scrollY,o.timeoutY);
                    }
                }
            }
            o.onMove.call(o);
        },
        click = function() {
            var o = sp.o[this.spindex];
            o.speedX = 0;
            o.speedY = 0;
            if (o.intervalX) {
                clearInterval(o.intervalX);
                o.intervalX = null;
            }
            if (o.intervalY) {
                clearInterval(o.intervalY);
                o.intervalY = null;
            }
            o.onClick.call(o);
        },
        wheel = function(e) {
            var o = sp.o[this.spindex];
            var delta;
            var pos = parseInt($(o.$pane).position().top);
            if (o.intervalY) {
                clearInterval(o.intervalY);
                o.intervalY = null;
            }
            if (e.wheelDelta) delta = e.wheelDelta/120;
            if (e.detail) delta = -e.detail/3;
            o.speedY = 0;
            pos += delta*10;
            if (pos > 0) pos = 0;
            else if (pos<-o.dy) pos = -o.dy;
            $(o.$pane).css('top',pos);
            $(o.$indV).css('top',-pos/o.dy*(o.vH*.8-parseInt($(o.$indV).css('margin-top'))-parseInt($(o.$indV).css('margin-bottom'))));
            return false;
        }

        return this.each(function(i,obj) {
            var s = sp.o.length,
            o = $.extend({},sp.defaults,opt);
            o.$port = $(this).parent().addClass(sp.c.viewportClass)[0];
            o.$port.spindex = s;
            o.$pane = obj;
            sp.o[s] = o;
            o.$indH = $('<div></div>').addClass(sp.c.indicatorClass).css({
                'opacity':0
            }).appendTo(o.$port)[0];
            o.$indV = $('<div></div>').addClass(sp.c.indicatorClass).css({
                'opacity':0
            }).appendTo(o.$port)[0];
            if (o.indicatorH != 'off') $(o.$indH).css(o.indicatorH,0);
            if (o.indicatorV != 'off') $(o.$indV).css(o.indicatorV,0);
            o.$clone = $(o.$pane).clone().addClass(sp.c.cloneClass)[0];
            $(o.$port).append(o.$clone);
            $(o.$pane).width($(o.$clone).width()+1);
            $(o.$pane).height($(o.$clone).height()+1);
            $('.'+sp.c.cloneClass).remove();
            $(this).addClass(sp.c.paneClass);
            $(o.$port).hover(over,out);
            $(o.$port).bind('click',click);
            if (o.speedH < 0 || o.speedH > 1) o.speedH = .5;
            if (o.speedV < 0 || o.speedV > 1) o.speedV = .5;
            o.timeoutX = parseInt(5+(1-o.speedH)*60);
            o.timeoutY = parseInt(5+(1-o.speedV)*60);
            o.onInit.call(o);
        });
    };

    var sp = $.fn.scrollpane;
    sp.o = [];
    sp.c = {
        viewportClass:  'sp-viewport',
        indicatorClass: 'sp-indicator',
        paneClass:      'sp-pane',
        cloneClass:     'sp-clone'
    };
    sp.defaults = {
        scroll:     'both',
        speedH:     .5,
        speedV:     .5,
        indicatorH: 'bottom',
        indicatorV: 'right',
        onInit:     function(){},
        onOver:     function(){},
        onOut:      function(){},
        onMove:     function(){},
        onClick:    function(){}
    };
    
})(jQuery);

