/*
* copyright 2008
* Author: Renato Formato <renatoformato@virgilio.it>
* a plugin to scroll an element hovering the mouse
* Thanks to the jQuery library
* 
* 
*
* version 1.1 
* scroll in horizontal too $("el").pageScroller("container",{dir:"h"}) 
*
* version 1.0
* first release 
*
* Released under double MIT/GPL Licence
*
**/

(function($){
  $.fn.pageScroller = function(container,options){
    options = $.extend({dir:"v"},options);
    return this.each(function(){
      $.pageScroller.scrollInit(container,this,options);  
    });
  }

  $.pageScroller = {
    scrollInit: function(container,content,options) {
      var scrollContainer = $(container);
      var scrollContent = $(content);
      $.data(scrollContent[0],"scrollData",{direction:options.dir,up:false,down:false,easeValue:0,easeStartTime:null,easeDir:null,easeDuration:500,lastScrollTime:null,min_top:0,timeout:null,inverting:false,invert:false,container:scrollContainer[0]});
      var st,sb,bind = true;
      if(options.dir=="v" && !$("#scrollTop",scrollContainer).size()) {
        st = $("<div id='scrollTop'>");
        sb = $("<div id='scrollBottom'>");
      } else if(options.dir!="v" && !$("#scrollLeft",scrollContainer).size()) {
        st = $("<div id='scrollLeft'>");
        sb = $("<div id='scrollRight'>");      
      } else {
        bind = false;
      }
      if(bind) {
        st.insertAfter(scrollContainer).hover(function(){
          $.pageScroller.scrollPage.apply(scrollContent,['up',true]);
        },function() {
          var data = $.data(scrollContent[0],"scrollData");
          $.pageScroller.scrollEase.apply(data,['down']);
        });
        sb.insertAfter(scrollContainer).hover(function(){
          $.pageScroller.scrollPage.apply(scrollContent,['down',true]);
        },function() {
          var data = $.data(scrollContent[0],"scrollData");
          $.pageScroller.scrollEase.apply(data,['down']);
        });
      }
      var scrollResize = function() {
        var data = $.data(scrollContent[0],"scrollData");
        if(options.dir=="v")
          data.min_top = scrollContent.height()+parseInt(scrollContent.css("paddingTop"))+parseInt(scrollContent.css("paddingBottom"))-$(container).height();
        else
          data.min_top = scrollContent.width()+parseInt(scrollContent.css("paddingLeft"))+parseInt(scrollContent.css("paddingRight"))-$(container).width();        
      }
      scrollResize();
      $(window).resize(scrollResize);
    },
    scrollPage: function(dir,starting) {
        var el = this;
        var data = $.data(el[0],"scrollData");
        if(starting || data.invert) {
          var currentDir = false;
          if(data['up'])
            currentDir = 'up';
          if(data['down'])
            currentDir = 'down';
          if(!data.invert && currentDir && currentDir!=dir) {
            dir = currentDir;
            data.inverting = true;            
          } else {
            window.clearTimeout(data.timeout);
            dir = data.invert || dir;
            data[dir] = true;
            data.invert = false;
            data.lastScrollTime = new Date().getTime();
            $.pageScroller.scrollEase.apply(data,["up"]);
          }
        }
        var top = data.direction=="v"?data.container.scrollTop:data.container.scrollLeft;
        if(!data[dir]) return;
        if((dir=="up" && top<=0) || (dir=="down" && top<=-data.min_top)) {
          data[dir] = false;
          data.invert = false;
          data.inverting = false;
          data.easeValue = 0;
        } else {
          var now = new Date().getTime();
          var delta = now-data.lastScrollTime;
          data.lastScrollTime = now;
          top += parseInt($.pageScroller.scrollEase.call(data)*(delta/30)*(dir=="up"?-10:10));
          if(data.direction=="v")
            data.container.scrollTop = top;
          else 
            data.container.scrollLeft = top;
          if(data[dir])
            data.timeout = window.setTimeout(function(){$.pageScroller.scrollPage.apply(el,[dir])},0);
        }
    },
    scrollEase: function(dir) {
      //edge values
      var toValue = (dir||this.easeDir)=='down'?0:1;
      var fromValue = (toValue+1)%2;  
      if(dir!=window.undefined) {
        this.duration = 500;
        this.easeStartTime = new Date().getTime();
        this.easeDir = dir;
        //adjust duration if not starting from normal value 
        var ratio = (this.easeDir=='up'?1-this.easeValue:this.easeValue);
        if(this.easeValue!=fromValue)
          this.duration *= ratio; 
      }
      //time passed
      var timePassed = new Date().getTime()-this.easeStartTime;
      if(timePassed<this.duration) {
        var val = -Math.cos(timePassed*Math.PI/this.duration)/2+0.5; 
        return this.easeValue = (this.easeDir=='up'?val:1-val);
      }
      else {
        if(this.easeDir=='down'){
          if(this.inverting) {
            this.inverting = false;
            this.invert = this.up?"down":"up";
            this.up = !this.up;
            this.down = !this.down;
          } else {
            this.up = false;
            this.down = false;
          }
          toValue = 0;
        } 
        return this.easeValue = toValue;
      }
    }
    };
})(jQuery)
