// Scroller (01-August-2011)
// by Vic Phillips http://www.vicsjavascripts.org.uk

// Scroller (31-July-2011)
// by Vic Phillips - http://www.vicsjavascripts.org.uk/

/*
  A continuous scroller which provides a constant scroll speed across all browsers
  and with both 'Horizontal' and 'Vertical' modes of execution.
  The scroll may be controlled by inline event calls.

  The functional code size is 1.83K

  ****** Application Notes.

   **** The HTML and CSS Code.

    The scroller is rendered in a parent DIV.
    The parent DIV must be assigned a unique ID name.
    This parent DIV must have a CSS position of 'relative' or 'absolute'
    and the width and height defined by CSS class rule or inline style.

    The slider content is nested in the first element nested in the parent DIV.
    The slider content elements must have their width and height defined by CSS class rule or inline style.
    Do not use margin-Right for 'Horizontal' or margin-Bottom' for 'Vertical' applications.


   **** Initializing the Script.

    Each instance of the script must be initialized by calling function 'zxcScroller'
    after the page has loaded passing the instance options as an object.
    Each instance of the script must be assigned to a global variable to allow the script to be controlled by inline event calls.
    e.g.
     E1=new zxcScroller({
     ID:'example1',     // the unique ID name of the parent DIV.                        (string)
     Mode:'Horizontal', //(optional) the mode of execution, 'Horizontal' or 'Vertical'. (string, default = 'Horizontal')
     Duration:10,       //(optional) the scroll duration in seconds.                    (number, default = 10)
     Direction:1        //(optional) scroll >0 = clockwise, <0 = anticlockwise.         (number, default = 1 = left)
    });

   **** Controlling the Script.

    The script is controlled by inline event calls to functions 'Scroll' and 'Pause'


     ** Function 'Scroll'.
      function 'Scroll' is used to start and direction of the scroll.
      e.g.
       <div id="example1"  onmouseover="E1.Pause()" onmouseout="E1.Scroll();">
       <input type="button" name="" value="Scroll Left"  onmouseup="E1.Scroll(-1);" />
       <input type="button" name="" value="Scroll Right"  onmouseup="E1.Scroll(1);" />
       <input type="button" name="" value="Scroll Toggle"  onmouseup="E1.Scroll('toggle');" />
       <input type="button" name="" value="Scroll Speed"  onmouseup="E1.Scroll(5);" />
      where
       E1  = the global variable assigned the script instance.
       parameter 0 = (optional) the scroll direction, 1 = clockwise, -1 = anticlockwise. (number, default = the current direction)
       or
       parameter 0 = (optional) > 1 = the scroll duratation in seconds.                  (number, default = the default scroll duratation)
       or
       parameter 0 = (optional) toggle the scroll direction.                             (string, default = the current direction)

     ** Function 'Pause'.
      function 'Pause' is used to control the speed and direction of the scroll.
      e.g.
       <div id="example1"  onmouseover="E1.Pause()" onmouseout="E1.Scroll();">
      where
       E1  = the global variable assigned the script instance.

*/


// ****** Functional Code - NO NEED to Change.

function zxcScroller(o){
 //var mde=typeof(o.Mode)=='string'&&o.Mode.charAt(0).toUpperCase()=='V'?['top','height','offsetTop','offsetHeight']:['left','width','offsetLeft','offsetWidth'],obj=document.getElementById(o.ID),slide=obj.getElementsByTagName('DIV')[0],slider=document.createElement('DIV'),clds=slide.getElementsByTagName('*'),lst=clds[clds.length-1],sz,nu,z0=0,ms=o.Duration,ud=o.Direction,stp=false;
 var mde=typeof(o.Mode)=='string'&&o.Mode.charAt(0).toUpperCase()=='V'?['top','height','offsetTop','offsetHeight']:['left','width','offsetLeft','offsetWidth'],obj=document.getElementById(o.ID),slide=obj.getElementsByTagName('DIV')[0],slider=document.createElement('DIV'),clds=slide.childNodes,lst=clds[clds.length-1],sz,nu,z0=0,ms=o.Duration,ud=o.Direction,stp=false;
 
 obj.style.overflow='hidden';
 slider.style.position='absolute';
 slider.style.left='0px';
 slider.style.top='0px';
 obj.appendChild(slider);
 slide.style.position='absolute';
 slide.style[mde[1]]='20000px';
 sz=lst[mde[2]]+lst[mde[3]];
 nu=Math.ceil(obj[mde[3]]/sz)+1;
 if(sz < obj.offsetHeight) return;
 for (;z0<nu;z0++){
  slide=z0>0?slide.cloneNode(true):slide;
  slide.style[mde[0]]=z0*sz+'px';
  slider.appendChild(slide);
 }
 this.stp=false;
 this.ms=(typeof(ms)=='number'?ms*1000:10000)*(sz/obj.offsetHeight);
 this.obj=slider;
 this.mde=mde[0];
 this.sz=-sz;
 this.ud=typeof(ud)=='number'&&ud<0?true:false;
 this.now=this.ud?0:this.sz;
 this.to=null;

 this.addevt(document, 'mousemove', 'scrollmove',o.ID);
 this.scroll();
}

zxcScroller.prototype={

 Scroll:function(ud){
  this.Pause();
  this.ud=typeof(ud)=='number'&&(ud==1||ud==-1)?ud<0?true:false:typeof(ud)=='string'?!this.ud:this.ud;
  this.ms=typeof(ud)=='number'&&ud>1?ud*1000:this.ms;
  var oop=this;
  this.stp=false;
  this.to=setTimeout(function(){ oop.scroll(); },200);
 },
 scrollmove: function(e,h) {
    div=$('#'+h);
    mse = this.mse(e), x=mse[0] - (div.offset().left-$(document).scrollLeft()), y= mse[1] - (div.offset().top - $(document).scrollTop()), width=div.width(), height=div.height();
    if (x>0 && x<width && y>0 && y<height)
    {
        if(this.mde=='top')
        {
            if (y<(height/4))
            {
                if (this.ud && !this.stp) return;
                this.ud=true;
                this.Scroll();
            }
            else if(y>(height-(height/4)))
            {
                if (!this.ud && !this.stp) return;
                this.ud=false;
                this.Scroll();
            }
            else
            {
                this.Pause();
            }
        }
        else
        {
            if (x<(width/4))
            {
                if (this.ud && !this.stp) return;
                this.ud=true;
                this.Scroll();
            }
            else if(x>(width-(width/4)))
            {
                if (!this.ud && !this.stp) return;
                this.ud=false;
                this.Scroll();
            }
            else
            {
                this.Pause();
            }
        }
    }
    else if(this.stp)
        this.Scroll();

 },
 scrollout: function(e,h) {
    this.Scroll();
 },
 Pause:function(){
  clearTimeout(this.to);
  this.stp=true;
 },
 scroll:function(){
  this.Pause();
  this.stp=false;
  var f=this.now,t=this.ud?this.sz:0;
  this.animate(f,t,new Date(),this.ms*Math.abs((t-f)/this.sz));
  //this.animate(f,t,new Date(),this.ms);
 },
 addevt: function(o, t, f, h) {
    var oop = this;
    //if (this.obj.addEventListener) this.obj.addEventListener(t, function(e) { return oop[f](e, p); }, false);
    //else 
        var oop = this;
        if (o.addEventListener) o.addEventListener(t, function(e) { return oop[f](e, h); }, false);
        else if (o.attachEvent) o.attachEvent('on' + t, function(e) { return oop[f](e, h); });
 },
 animate:function(f,t,srt,mS){
  var oop=this,ms=new Date().getTime()-srt,now=(t-f)/mS*ms+f;
  if (isFinite(now)){
   this.now=now;
  }
  this.obj.style[this.mde]=this.now+'px';
  if (ms<mS){
   this.to=setTimeout(function(){ oop.animate(f,t,srt,mS); },10);
  }
  else {
   this.now=this.ud?0:this.sz;
   this.scroll();
  }
 },
 pos: function(obj) {
        var rtn = [0, 0];
        while (obj) {
            rtn[0] += obj.offsetLeft;
            rtn[1] += obj.offsetTop;
            obj = obj.offsetParent;
        }
        return rtn;
    },
 mse: function(e) {
        if (window.event) {
            var docs = [document.body.scrollLeft, document.body.scrollTop];
            if (!document.body.scrollTop) {
                docs = [document.documentElement.scrollLeft, document.documentElement.scrollTop];
            }
            return [e.clientX + docs[0], e.clientY + docs[1]];
        }
        return [e.pageX, e.pageY];
    }
}

