(function($) {
  $.fn.scroller = function(options) {
    if (this.length && (scroller = $.data(this[0], 'scroller'))) {
      return scroller;
    }

    return this.each(function() {
      $.data(this, 'scroller', new $.scroller.init(this, options));
    });
  };

  $.scroller = {};

  $.scroller.defaults = {
    area: 20,
    velocity: 1,
    onChange: function(x, y) { this.scrollLeft = x; }
  };

  $.scroller.init = function(element, options) {
    this.options = $.extend($.scroller.defaults, options);
    this.scrollable = $(element);

    this.scrollable.hover($.scroller.start, $.scroller.stop);
  };

  $.scroller.start = function() {
    $.data(this, 'scroller').scrollable.bind('mousemove', $.scroller.getCoords);
  };

  $.scroller.stop = function() {
    var self = $.data(this, 'scroller');
    self.scrollable.unbind('mousemove');
    clearInterval(self.timer);
    self.timer = null;
  };

  $.scroller.getCoords = function(event) {
    var self = $.data(this, 'scroller');
    self.page = {
			x: event.pageX || event.clientX + document.documentElement.scrollLeft,
			y: event.pageY || event.clientY + document.documentElement.scrollTop
    };
    if (!self.timer) self.timer = setInterval(function() { $.scroller.scroll(self); }, 50);
  };

  $.scroller.scroll = function(self) {
    var el = $.scroller.getSize(self.scrollable[0]);

		var pos = self.scrollable.offset();
    pos = {
      x: pos.left,
      y: pos.top
    };

		var change = {x: 0, y: 0};
		for (var z in self.page){
			if (self.page[z] < (self.options.area + pos[z]) && el.scroll[z] != 0)
				change[z] = (self.page[z] - self.options.area - pos[z]) * self.options.velocity;
			else if (self.page[z] + self.options.area > (el.size[z] + pos[z]) && el.scroll[z] + el.size[z] != el.scrollSize[z])
				change[z] = (self.page[z] - el.size[z] + self.options.area - pos[z]) * self.options.velocity;
		}
		if (change.y || change.x) self.options.onChange.apply(self.scrollable[0], [el.scroll.x + change.x, el.scroll.y + change.y]);
  };

  $.scroller.getSize = function(self) {
		return {
			'scroll': {'x': self.scrollLeft, 'y': self.scrollTop},
			'size': {'x': self.offsetWidth, 'y': self.offsetHeight},
			'scrollSize': {'x': self.scrollWidth, 'y': self.scrollHeight}
		};
  };
})(jQuery);

