/* 
 * jQuery.JSPclickNScroll v1.0
 *
 * Copyright (c) 2010 Joshua Faulkenberry
 * Dual licensed under the MIT and GPL licenses.
 * Joshua Faulkenberry
 *
 * $Date: 2010-10-25 18:55:27 -0700 (Mon, 25 Oct 2010) $
 * $Revision: 5 $
 */

(function($){ 
 
   jQuery.extend({
      mouse: {
         x: 0,
         y: 0
      },
      JSPclickNScroll: {
         mousedown:false,
         emaX: 0,
         emaY: 0
      }  
   });
   
   jQuery.fn.extend({
      JSPclickNScroll: function(options) {
         var ops = $.extend({
            allowHiliting:false,
            acceleration:.65,
            deceleration:.85,
            decelRate:64,
            reverse:false,
            rightMouse:false,
            allowThrowing:true,
            throwOnOut:true
         }, options || {});
         return this.each(function(){  
            var $this = $(this).data("options", ops);                                  
            if(!ops.allowHiliting) {
              if (jQuery.browser.msie) {
                 $this.get(0).onselectstart = function () { return false; };
              } 
              else {
                  $this.get(0).onmousedown = function(e){e.preventDefault()}
              }   
            }
            $this.mousedown(function(e) {
               $.JSPclickNScroll.mousedown = $this;
            }).mouseup(function(e) {                                   
               if(ops.allowThrowing) sling($(this));  
               $.JSPclickNScroll.mousedown = false;
            }).mouseout(function(e) { 
            	var from = e.relatedTarget || e.toElement;
                if (!from || from.nodeName == "HTML") {
	               if($.JSPclickNScroll.mousedown && ops.allowThrowing && ops.throwOnOut)  sling($(this));   
	               $.JSPclickNScroll.mousedown = false;
            	}
            })  
         });
      }      
   });
   
   function sling($this) {        
      var ops    = $this.data("options"),    
          changeX = ($.JSPclickNScroll.emaX)*ops.deceleration,   
          changeY = ($.JSPclickNScroll.emaY)*ops.deceleration;                                           
      if((changeX < .01 && changeX > -.01) || (changeY < .01 && changeY > -.01)) {return;}  
      move($this, changeX, changeY);            
      setTimeout(function() {
         sling($this);
      }, 1000/ops.decelRate);            
   }
   
	function move($this, changeX, changeY) {                                                                        
		if(($.JSPclickNScroll.emaX < 0 && changeX > 0) || ($.JSPclickNScroll.emaX > 0 && changeX < 0)) $.JSPclickNScroll.emaX = 0;
		if(($.JSPclickNScroll.emaY < 0 && changeY > 0) || ($.JSPclickNScroll.emaY > 0 && changeY < 0)) $.JSPclickNScroll.emaY = 0;

		var	ops    = $this.data("options"),                                                                       
			  amntX = ops.acceleration * changeX + (1 - ops.acceleration) * $.JSPclickNScroll.emaX,
			  amntY = ops.acceleration * changeY + (1 - ops.acceleration) * $.JSPclickNScroll.emaY,
			  scrollRight = $this[0].scrollWidth ? $this[0].scrollWidth - $this[0].clientWidth : $this[0].body.scrollWidth - $this[0].body.clientWidth,
			  scrollBottom = $this[0].scrollHeight ? $this[0].scrollHeight - $this[0].clientHeight : $this[0].body.scrollHeight - $this[0].body.clientHeight,
				api = $this.data('jsp');

		if(($this.scrollLeft() <= 0 && changeX <= 0) ||  ($this.scrollLeft() >= scrollRight && changeX >= 0)) {}  
		// else $this.scrollLeft($this.scrollLeft() + (amntX));
		api.scrollBy(amntX, 0);

		if(($this.scrollTop() <= 0 && changeY <= 0) ||  ($this.scrollTop() >= scrollBottom && changeY >= 0)) {}  
		// else $this.scrollTop($this.scrollTop() + (amntY));
		api.scrollBy(0, amntY);

		$.JSPclickNScroll.emaX = amntX;
		$.JSPclickNScroll.emaY = amntY;
	}
   
   $(document).mousemove(function(e) {                                     
      if($.JSPclickNScroll.mousedown) {      
         var $this  = $.JSPclickNScroll.mousedown,
             ops    = $this.data("options");
         if(ops.rightMouse && e.button != 2) return;
         else if(!ops.rightMouse && e.button == 2) return;    
         var changeX = e.pageX - $.mouse.x,   
             changeY = e.pageY - $.mouse.y; 
         if(!ops.reverse) {
          changeX = 0-changeX;
          changeY = 0-changeY;
         }                                                                  
         move($this, changeX, changeY);
      }  
      $.mouse = {
         x: e.pageX,
         y: e.pageY
      };                          
   }); 
   
})(jQuery);