jQuery.fn.scroller = function() {
    
    var opts = {
        duration: 500,
        easing: 'swing'
    }
    
    return this.each(function() {
        
        var contentDiv = $(this).find('.content');
        
        var paragraphs = contentDiv.find('p').length;
        
        if (paragraphs > 1) {
            var sBody = $('<div class="scroller"></div>');
            var sBar = $('<div class="bar"></div>');
            
            sBody.append(sBar);
            
            for (var i = 0; i < paragraphs; i++) {
                var newPoint = $('<div class="scrollPoint"></div>');
                newPoint.click(function() { scrollTo(sPoints.index($(this))); scrollText(sPoints.index($(this))) });
                if (i == paragraphs - 1)
                    newPoint.addClass('last');
                sBody.append(newPoint);
            }
            
            $(this).append(sBody);
            
            sBody.css('top', -(sBody.height() / 2))
            
            var sPoints = $(this).find('.scrollPoint');
            
            var diff = (sBar.height() - sPoints.height()) / 2;
            
            var maxPos = {
                top: sPoints.eq(0).position().top - diff,
                bottom: sPoints.eq(sPoints.length - 1).position().top - diff
            }
            
            sBar.css('top', maxPos.top);
            sBar.attr('actIndex', 0);
            
            sBar.mousedown(function(e) {
                $(document).mouseup(function() {
                    sBar.trigger('mouseup');
                }).mousemove(function(e) {
                    sBar.triggerHandler('mousemove', e);
                });
                this.isClicked = true;
                this.startPos = {
                	x: e.pageX,
                	y: e.pageY
                }
            });
            sBar.mouseup(function() {
               $(document).unbind('mouseup');
               this.isClicked = false;
               scrollToByPosition();
            });
            
            $(this).mousewheel(function(e, d) {
                e.preventDefault();
                d = (d < 0) ? -1 : 1;
                index = parseInt(sBar.attr('actIndex')) - d;
                
                if (index < 0)
                    index = 0;
                if (index >= sPoints.length)
                    index = sPoints.length - 1;
                
                scrollTo(index, scrollText(index));
            });
            
            $(document).mousemove(function(e) {
                var c = sBar.attr('isClicked');
                var startPos = sBar.attr('startPos');
                
                if (startPos == null || !c || e.pageY < sBody.offset().top || e.pageY > sBody.offset().top + sBody.height())
                    return false;
                
                var newPos = {
                	x: parseInt(sBar.css('left')) + e.pagex - startPos.x,
                	y: parseInt(sBar.css('top')) + e.pageY - startPos.y
                }
                
                if (newPos.y < maxPos.top)
                    newPos.y = maxPos.top;
                    
                if (newPos.y > maxPos.bottom)
                    newPos.y = maxPos.bottom;

                sBar.css('top', newPos.y);
                
                startPos.x = e.pageX;
                startPos.y = e.pageY;
            });
            
            function scrollToByPosition() {
                var middle = sBar.position().top + (sBar.height() / 2);
                var pointsDiff = (sPoints.eq(0).position().top + sPoints.eq(1).position().top - sPoints.height()) / 2;
                
                sPoints.each(function(i) {
                    var pointTop = $(this).position().top - pointsDiff;
                    var pointBottom = $(this).position().top + $(this).height() + pointsDiff;
                    
                    if (pointTop < middle && middle <= pointBottom) {
                        scrollTo(i);
                        scrollText(i);
                    }
                });
                return 0;
            }
            
            function scrollTo(nr, callback) {
                if (callback == null)
                    callback = function() { };

                sBar.stop(true, false).animate({
                    top: sPoints.eq(nr).position().top - diff
                }, opts.duration, opts.easing, callback);
                sBar.attr('actIndex', nr);
            }
            
            function scrollText(nr) {
                contentDiv.css({
                    position: 'absolute'
                });
                var margin = (contentDiv.parent().height() - contentDiv.find('p').eq(nr).height()) / 2;
                var newTop = - contentDiv.find('p').eq(nr).position().top + margin;
                
                if (nr == 0)
                    newTop = 0;
                
                contentDiv.stop(true, false).animate({
                    top: newTop
                }, opts.duration, opts.easing);
            }
        }
    });
}
