(function($) {
    var uid = 0;
    
    $.fn.tablescroller = function(height) {
        return this.each(function() {
            $.tablescroller($(this),height);
        });
    }
    
    $.tablescroller = function(tab,height) {
        var scrollerId = uid++;
        var body = $("tbody",tab);
        var head = $("thead",tab);
        var bodyHeight = body.height();
        var headHeight = head.height();
        if (bodyHeight < height) return; // does not need to be scrolled
        var limitHeight = bodyHeight - height;
        var limit = 0;
        var baseTop = body.position().top;
        var firstRow = 0;
        var row = 0;
        var numRows = 0;
        var rowHeight = [];
        $("tr",body).each(function() {
            var pos = $(this).position().top - baseTop;
            rowHeight[row] = pos;  
            if (pos < limitHeight) {
                numRows++;
            } else if (limit == 0) {
                limit = row;
            }
            row++;
        });
        var dataBody = $("<tbody></tbody>");
        var scrolltab = $("<table cellspacing='0' cellpadding='0'><tr>"
                    + "<td class='ui-scrollbar-content'><div></div></td>"
                    + "<td class='ui-scrollbar'>"
                    + "<div class='ui-scrollbar-up'></div>"
                    + "<div class='ui-scrollbar-slider'>"
                    +  "<div id='ui-scrollbar-handle-"+scrollerId+"' class='ui-scrollbar-handle'></div>"
                    + "</div>"
                    + "<div class='ui-scrollbar-down'></div>"
                    + "</td></tr></table>");
	    scrolltab.addClass(tab.attr('className'));                    
        tab.after(scrolltab);                    
        var scrollContent = $("td.ui-scrollbar-content > div",scrolltab);
        scrollContent.height(height+headHeight);
        scrollContent.append(tab);
        scrollContent.css("overflow","hidden");
        var handle = $("div.ui-scrollbar-handle",scrolltab);
        var slider = $("div.ui-scrollbar-slider",scrolltab);
        var upButton =  $("div.ui-scrollbar-up",scrolltab);
        var downButton =  $("div.ui-scrollbar-down",scrolltab);
        var scrollbarTd = $("td.ui-scrollbar",scrolltab);
        handle.css("position","absolute");
        slider.css("position","relative");
        upButton.click(function() {
            scrollto(firstRow-1); 
        });
        downButton.click(function() {
            scrollto(firstRow+1); 
        });
        slider.bind("click",function(e) {
            var mouseY = e.pageY;
            var handleY = handle.offset().top;
            if (mouseY < handleY) {
                scrollto(firstRow - numRows);
            } else if (mouseY > (handleY+handle.height())) {
                scrollto(firstRow + numRows);
            }
        });
        scrollbarTd.hover(
            function() {
                $(this).addClass("ui-scrollbar-hover");
            },
            function() {
                $(this).removeClass("ui-scrollbar-hover");
            }
        );
        var sliderHeight = height + headHeight - upButton.height() - downButton.height();
        slider.height(sliderHeight);
        var ratio = sliderHeight / bodyHeight;
        if (ratio > 1) ratio = 1;
        var buttonHeight = slider.height() * ratio;
        if (buttonHeight < 10) buttonHeight = 10;
        handle.height(buttonHeight);
        handle.draggable(
           {
             axis:'y',
             containment:'parent',
             handle:"#ui-scrollbar-handle-"+scrollerId,
             stop: function(e,ui) {
                 var maxTop = slider.height() - handle.height();
                 var pos = handle.position().top;
                 var ratio = pos / maxTop;
                 var row = limit * ratio;
                 scrollto(row);
             }
           }
        );
        var scrollto = function(rowInput) {
            row = parseInt(rowInput + .5);
            if (row < 0) row = 0;
            if (row > limit) row = limit;
            var dataRows = $("tr",dataBody);
            while (firstRow < row) {
                var curRow = $("tr:eq(0)",body);
                if (firstRow == 0) {
                    dataBody.prepend(curRow);
                } else {
                    $("tr",dataBody).eq(firstRow-1).after(curRow);
                }
                firstRow++;
            }
            while (firstRow > row) {
                firstRow--;
                var curRow = dataRows.eq(firstRow);
                body.prepend(curRow);
            }
            numRows = 0;
            var bodyRows = $("tr",body);
            var actualHeight = 0;
            while ((actualHeight < height) && (numRows < bodyRows.length)) {
                actualHeight += bodyRows.eq(numRows).height();
                numRows++;
            }
            
            var maxTop = slider.height() - handle.height();
            var curRatio = rowHeight[firstRow] / limitHeight;
            handle.css("top",(maxTop * curRatio)+"px");
        }
        scrollto(0);
    }
})(jQuery);


