/**
 * Copyright (c) 2010 Sylvain Gougouzian (sylvain@gougouzian.fr) MIT
 * (http://www.opensource.org/licenses/mit-license.php) licensed. GNU GPL
 * (http://www.gnu.org/licenses/gpl.html) licensed.
 *
 * jQuery scrollBar v 0.2 by Sylvain Gougouzian http://sylvain.gougouzian.fr
 *
 * Requires: jQuery 1.3.2+ // http://www.jquery.com
 *
 * Compatible : Internet Explorer 6+, Firefox 1.5+, Safari 3+, Opera 9+, Chrome 0.9+
 */

jQuery(function($){
    $.fn.scrollbar = function(options){
        var el = this.eq(0).data("scrollbar");
        var opts = $.extend({}, $.fn.scrollbar.defaults, options);
        this.each(function(){
            el = new $scrollbar(this, opts);
        });
        return opts.api ? el : null;
    };
    
    $.scrollbar = function(e, opts){
        var self = this;
	    this.opts = opts;
        this.previousMousePos = -1;
		this.isMoving = false;
        this.texte = $(e);
        this.wt = this.texte.width();
		this.wh = this.texte.parent().height();
		var w = parseInt(opts.width);
        this.texte.width(this.wt - (parseInt(this.texte.css('padding-right')) + w)).height('auto').css({
            'position': 'absolute',
            'top': '0px'
        }).wrap('<div></div>');
        this.th = parseInt(this.texte.height());
        this.container = this.texte.parent();
		this.id = this.texte.attr('id');
        var scr = '<div id="' + this.id + '_scrollAbg" class="scrollbarTrack"><div id="' + this.id + '_scrollAsc" class="scrollbarDrag"></div></div>';
			scr += '<a id="' + this.id + '_scrollup" class="scrollbarArrowUp" style="width: ' + w + 'px; top: 0px;" href="#"><span class="bgWrapper">' + opts.textUp + '</span></a>';
			scr += '<a id="' + this.id + '_scrolldown" class="scrollbarArrowDown" style="width: ' + w + 'px; bottom: 0px;" href="#"><span class="bgWrapper">' + opts.textDown + '</span></a>';
        this.container.addClass('scrollbarContainer').attr('id', this.id + '_scroll').width(this.wt).height(this.wh).append(scr);
        this.sh = parseInt(this.wh - (2 * parseInt(this.opts.arrowHeight)));
		this.asc = $('#' + this.id + '_scrollAsc');
		$('#' + this.id + '_scrollAbg').width(w).height(this.sh).css('top', this.opts.arrowHeight);
		this.asc.width(w).css('top', '0px').bind('mousedown', function(e){
		    self.startDrag(e);
        });
		$(window).load(function () {
			$('*', self.container).focus(function(e){
				var pos = $(this).offset().top - self.texte.offset().top - 50;
				var viewportTop = -parseInt(self.texte.offset().top) || 0;
				var maxVisibleEleTop = viewportTop + self.wh;
				var eleInView = pos > viewportTop && pos < maxVisibleEleTop;
				if (!eleInView)
	            	self.moveTo(pos);
	        });
		})
		
		$(document).bind('mouseup', function(){
			self.previousMousePos = null;
            self.endDrag();
        });
        
        this.container.bind('mousewheel', function(event, delta){
            var dir = delta > 0 ? 'Up' : 'Down';
            if (dir == 'Up') {
				self.up();
            }
            else {
				self.down();
            }
            return false;
        });
        $("#" + this.id + "_scrollup").click(function(){
            self.up();
            return false;
        });
        $("#" + this.id + "_scrolldown").click(function(){
            self.down();
            return false;
        });
		$('a', $(this.texte)).each(function () {
			$(this).click(function () {
				var h = $(this).attr('href');
				if (h && h.substr(0, 1) == '#' && h.length > 1) {
					setTimeout(function() {
						self.moveTo(h);
					}, $.browser.safari ? 100 : 0);
					return false;
				}
			});
		});
        if ($('img', this.texte).length > 0) {
            $('img', this.texte).each(function (i) {
				$(this).load(function(){
					if (i == ($('img', self.texte).length - 1))
                		self.recalcHeight();
				});
            });
        }
        else {
            this.recalcHeight();
        }
    };
    
	var $scrollbar = $.scrollbar;
	
    $scrollbar.fn = $scrollbar.prototype = {
        scrollbar: '0.2'
    };
    
    $scrollbar.fn.extend = $scrollbar.extend = $.extend;
    
    $scrollbar.fn.extend({
        recalcHeight: function () {
			this.calcHeight();
			this.hashMove();
		},
		redraw: function (th) {
			this.th = th;
			this.recalcHeight();
			this.moveTo(0);
		},
		hashMove: function () {
			var self = this;
			if (location.hash && location.hash.length > 1) {
				setTimeout(function() { self.moveTo(location.hash); }, $.browser.safari ? 100 : 0);
			}
		},
        calcHeight: function() {
            var h = parseInt((this.wh * this.sh) / this.th);
			if (h > this.sh) h = this.sh;
			if (h == this.sh) h = 0;
			this.asc.height(h);
        },
        calcTextScroll: function(s){
            return (s * this.th) / this.sh;
        },
		calcDragScroll: function (s) {
			if (0 == this.asc.height()) return 0;
			return ((s * (this.sh - parseInt(this.asc.height()))) / (this.th - this.wh));
		},
        down: function(move){
			var s = parseInt((move == undefined ? this.opts.scrollPadding : move));
			this.asc.css('top', this.downScroll(s) + 'px');
            this.texte.css('top', this.downText(s) + 'px');
        },
		downScroll: function (s) {
			var d = parseInt(this.asc.css('top')) + s;
            if ((d + parseInt(this.asc.height())) > this.sh) 
                d = this.sh - parseInt(this.asc.height());
			if (0 == this.asc.height()) d = 0;
			return d;
		},
		downText: function (s) {
			var dt = parseInt(this.texte.css('top')) - parseInt(this.calcTextScroll(s));
            if (dt < (0 - (this.th - this.wh))) 
                dt = 0 - (this.th - this.wh);
			if (0 == this.asc.height()) dt = 0;
            return dt;
		},
        up: function(move){
            var s = parseInt((move == undefined ? this.opts.scrollPadding : move));
			this.asc.css('top', this.upScroll(s) + 'px');
            this.texte.css('top', this.upText(s) + 'px');
        },
		upScroll: function (s) {
			var d = parseInt(this.asc.css('top')) - s;
			if (0 == this.asc.height()) d = 0;
			return (d < 0 ? 0 : d);
		},
		upText: function (s) {
			var d = parseInt(this.texte.css('top')) + parseInt(this.calcTextScroll(s));
			if (0 == this.asc.height()) d = 0;
            return (d > 0 ? 0 : d);
		},
        startDrag: function(event){
            var self = this;
            this.previousMousePos = event.clientY;
            this.container.bind('mousemove', function(e){
                self.move(e);
            });
        },
        move: function(event){
            if (this.previousMousePos > event.clientY) {
                this.up(this.previousMousePos - event.clientY);
            }
            else {
                this.down(event.clientY - this.previousMousePos);
            }
            this.previousMousePos = event.clientY;
        },
		endDrag: function(){
			this.container.unbind('mousemove');
        },
		moveTo: function(pos) {
			if (typeof pos == "string") {
				$e = $(pos, this.texte);
				if (!$e.length) return;
				pos = $e.offset().top - this.texte.offset().top;
			}
			pos = parseInt(pos);
			if (this.th > this.wh) {
				if (pos > (this.th - this.wh)) pos = this.th - this.wh;
			}
			else {
				pos = 0;				
			}
			this.asc.css('top', this.calcDragScroll(pos) + 'px');
			this.texte.css('top', 0 - pos + 'px');
		},
		reinit: function (h) {
			$('#' + this.id + '_scroll').height(h);
			$('#' + this.id + '_scrollAbg').height(h);
			this.sh = h;
			this.wh = h;
			this.calcHeight();
			this.moveTo(0);
		}
    });
    $.fn.scrollbar.defaults = {
        width: '14px',
        arrowHeight: '11px',
        scrollPadding: '15px',
        textUp: ' ',
        textDown: ' ',
        api: false
    };
});