// $Id$

/**
 * @author Henri MEDOT
 * @version last revision 2009-12-01
 */

$.fn.extend({
  scrollbarPaper: function() {
    this.each(function(i) {
      var $this = $(this);
      var paper = $this.data('paper');
      var refreshTimer = $this.data('refreshTimer');
      if (paper == null) {

        var barWidth = function() {
          var div = $('<div style="width:50px;height:50px;overflow:hidden;position:absolute;top:-200px;left:-200px;"><div style="height:100px;"></div></div>');
          $('body').append(div);
          var w1 = $('div', div).innerWidth();
          div.css('overflow-y', 'scroll');
          div.css('overflow-x', 'hidden');
          var w2 = $('div', div).innerWidth();
          div.remove();
          return Math.max(w1 - w2, 17);
        }.call();

        $this.before('<div class="scrollbarpaper-container" style="width:' + 1 + 'px"><div class="scrollbarpaper-track"><div class="scrollbarpaper-drag"><div class="scrollbarpaper-drag-top"></div><div class="scrollbarpaper-drag-bottom"></div></div></div></div>');
        paper = $this.prev();
        $this.append('<div class="scroll_clear" style="clear:both;"></div>');
        var content = $('> :first', $this);
        content.css('overflow', 'hidden');
		//$this.width($this.width() + barWidth);
		$this.css('padding-right', barWidth + 'px');
		paper.css('margin-left', '-' + barWidth + 'px');

        $this.data('barWidth',   barWidth);
        $this.data('paper',      paper);
        $this.data('refreshTimer',      refreshTimer);
        $this.data('track',      $('.scrollbarpaper-track', paper));
        $this.data('drag',       $('.scrollbarpaper-drag', paper));
        $this.data('dragTop',    $('.scrollbarpaper-drag-top', paper));
        $this.data('dragBottom', $('.scrollbarpaper-drag-bottom', paper));
        $this.data('content',    content);
        $this.data('clearer',    $('> :last', $this));
        paper.hide();
      }

      var barWidth =   $this.data('barWidth');
      var track =      $this.data('track');
      var drag =       $this.data('drag');
      var dragTop =    $this.data('dragTop');
      var dragBottom = $this.data('dragBottom');
      var content =    $this.data('content');
      var clearer =    $this.data('clearer');

		$('.scroll_clear').ready( function() {

		  var contentHeight = clearer.position().top - content.position().top;
		  $this.data('height', $this.height());
		  $this.data('contentHeight', contentHeight);
		  $this.data('offset', $this.offset());

		  $this.unbind();
		  var ratio = $this.height() / contentHeight;
		  if (ratio < 1) {

			paper.show();
			$this.css('padding-right', barWidth + 'px');
			paper.css('margin-left', '-' + barWidth + 'px');
			content.addClass('scrollbarpaper-visible');
			content.width($this.width() - content.innerWidth() + content.width() - barWidth);
			paper.height($this.height());
			var offset = $this.offset();
			paper.css('left', (offset.left + $this.innerWidth() - paper.width()) + 'px').css('top', offset.top);

			var dragHeight = Math.max(Math.round($this.height() * ratio), dragTop.height() + dragBottom.height());
			drag.height(dragHeight);
			var updateDragTop = function() {
			  drag.css('top', Math.min(Math.round($this.scrollTop() * ratio), $this.height() - dragHeight) + 'px');
			};
			updateDragTop();

			$this.scroll(function(event) {
			  updateDragTop();
			});

			var unbindMousemove = function() {
			  $('html').unbind('mousemove.scrollbarpaper');
			};
			drag.mousedown(function(event) {
			  unbindMousemove();
			  var offsetTop = event.pageY - drag.offset().top;
			  $('html').bind('mousemove.scrollbarpaper', function(event) {
				$this.scrollTop((event.pageY - $this.offset().top - offsetTop) / ratio);
				return false;
			  }).mouseup(unbindMousemove);
			  return false;
			});
			track.mousedown(function(event) {
				var offsetTop = event.pageY - drag.offset().top;
				wh = $this.innerHeight;//($this.height() && window.innerHeight < $(window).height()) ? window.innerHeight : $(window).height();
				wh = (offsetTop<0)? -wh : wh;
				$this.scrollTop($this.offset().top + wh);
				return false;
			});
		  }
		  else {
			$this.css('padding-right', '');
			paper.css('margin-left', '');
			$this.unbind();
			paper.hide();
			content.removeClass('scrollbarpaper-visible');
			content.width($this.width() - content.innerWidth() + content.width());
		  }

		  $this.refreshBar = function ()
		  {
			  clearTimeout($this.data('refreshTimer'));
			  var offset = $this.offset();
			  var dataOffset = $this.data('offset');
			  if (($this.height() != $this.data('height'))
			   || (clearer.position().top - content.position().top != $this.data('contentHeight'))
			   || (offset.top != dataOffset.top)
			   || (offset.left != dataOffset.left)) {
				$this.scrollbarPaper();
			  } else if($this.data('paper')!=null) {
				$this.data('refreshTimer', window.setTimeout($this.refreshBar, 200));
			  }
		  }
		  $this.data('refreshTimer', window.setTimeout($this.refreshBar, 200));
		});
    });
  },
  removeScrollbarPaper: function() {
		this.each(function(i) {
			var $this = $(this);
			clearTimeout($this.data('refreshTimer'));
			var paper = $this.data('paper');
			var content = $this.data('content');
			var track = $this.data('track');
			var clearer = $this.data('clearer');
			var drag =       $this.data('drag');
			var dragTop =    $this.data('dragTop');
			var dragBottom = $this.data('dragBottom');

			$this.css('padding-right', '');
			if(dragBottom)
				dragBottom.remove();
			if(dragTop)
				dragTop.remove();
			if(drag)
				drag.remove();
			if(clearer)
				clearer.remove();
			if(track)
				track.remove();
			if(paper)
				paper.remove();
			if(content) {
				content.removeClass('scrollbarpaper-visible');
				content.width($this.width() - content.innerWidth() + content.width());
			}
			$this.removeData('paper');
			$this.removeData('refreshTimer');
			$this.removeData('paper');
			$this.removeData('content');
			$this.removeData('track');
			$this.removeData('clearer');
			$this.removeData('drag');
			$this.removeData('dragTop');
			$this.removeData('dragBottom');
		});
	}
});

