/*
   name         : ClassBehaviours, the javascript framework based on class-name parsing
   update         : 9.11.9
   author         : Maurice van Creij
   dependencies   : jquery.classbehaviours.js
   info         : http://www.classbehaviours.com/

    This file is part of jQuery.classBehaviours.

    ClassBehaviours is a javascript framework based on class-name parsing.
    Copyright (C) 2008  Maurice van Creij

    ClassBehaviours is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    ClassBehaviours is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with ClassBehaviours. If not, see http://www.gnu.org/licenses/gpl.html.
*/

   // create the jQuery object if it doesn't already exist
   if(typeof(jQuery)=='undefined') jQuery = function(){};

   // create the root classbehaviours object if it doesn't already exist
   if(typeof(jQuery.classBehaviours)=='undefined') jQuery.classBehaviours = function(){};

   // create the handlers child object if it doesn't already exist
   if(typeof(jQuery.classBehaviours.handlers)=='undefined') jQuery.classBehaviours.handlers = function(){}

   // Manages an artificial scroll bar
   jQuery.classBehaviours.handlers.artificialScrollBar = {
      // properties
      name: 'artificialScrollBar',
      interaction: false,
      interactor: null,
      scrollInterval: null,
      index: 0,
      // methods
      start: function(node){
         // give the scrollbar an id if it doesn't have one
         node.id = (node.id) ? node.id : this.name + this.index++ ;
         // get the objects inside
         allDivs = node.getElementsByTagName('DIV');
         // disable the normal scrollbar
         node.style.overflow = 'hidden';
         // show the artificial scrollbar
         allDivs[allDivs.length-5].style.display = 'block';
         // set the canvas event handlers
         node.onmouseover = this.overCanvas;
         node.onmouseout = this.offCanvas;
         // set the detector events
         allDivs[allDivs.length-1].onmousedown = this.onDown;
         allDivs[allDivs.length-1].onmousemove = this.onDrag;
         allDivs[allDivs.length-1].ondrag = this.onDrag;
         document.onmouseup = this.onUp;
         node.onmousewheel = this.onWheel;
         if(window.addEventListener) window.addEventListener('DOMMouseScroll', this.onWheel, false);
         // set the button event handlers
         allDivs[allDivs.length-3].onmousedown = this.buttonDown;
         allDivs[allDivs.length-3].onmouseup = this.buttonOff;
         allDivs[allDivs.length-3].onmouseout = this.buttonOff;
         allDivs[allDivs.length-4].onmousedown = this.buttonUp;
         allDivs[allDivs.length-4].onmouseup = this.buttonOff;
         allDivs[allDivs.length-4].onmouseout = this.buttonOff;
         // start position
         setTimeout('jQuery.classBehaviours.handlers.artificialScrollBar.moveTo(document.getElementById("'+node.id+'"), 0)', 100);
      },
      resize: function(rootNode){
         // get the required objects
         allDivs = rootNode.getElementsByTagName('DIV');
         contentNode = allDivs[0];
         indicatorNode = allDivs[allDivs.length-2];
      },
      moveTo: function(rootNode, position){
         // get the required objects
         allDivs = rootNode.getElementsByTagName('DIV');
         contentNode = allDivs[0];
         indicatorNode = allDivs[allDivs.length-2];
         scrollBarNode = allDivs[allDivs.length-5];
         // size the indicator
         contentToWindowRatio = contentNode.parentNode.offsetHeight / contentNode.offsetHeight;
         scrollBarHeight = indicatorNode.parentNode.offsetHeight;
         indicatorSize = contentToWindowRatio * scrollBarHeight;
         if(!isNaN(indicatorSize)) indicatorNode.style.height = Math.round(indicatorSize) + 'px';
         // hide the indicator when it's not needed
         scrollBarNode.style.visibility = (contentToWindowRatio>=1) ? 'hidden' : 'visible' ;
         // if the page is longer than the canvas
         if(contentToWindowRatio<1){
            // set the indicator position
            indicatorSurplus = indicatorSize / 2;
            indicatorPosition = position - indicatorSurplus;
            if(position < indicatorSurplus) indicatorPosition = 0;
            if(indicatorPosition > scrollBarHeight-indicatorSize) indicatorPosition = scrollBarHeight-indicatorSize;
            if(!isNaN(indicatorPosition)) indicatorNode.style.top = Math.round(indicatorPosition) + 'px';
            // set the content position
            scrollBarFraction = (position - indicatorSurplus) / (scrollBarHeight - indicatorSurplus * 2);
            contentOverlap = contentNode.offsetHeight - contentNode.parentNode.offsetHeight;
            contentPosition = scrollBarFraction * contentOverlap;
            if(contentPosition<0) contentPosition = 0;
            if(contentPosition>contentOverlap) contentPosition = contentOverlap;
            if(!isNaN(contentPosition)) contentNode.style.top = Math.round(0 - contentPosition) + "px";
         }
      },
      moveBy: function(rootNode, distance){
         if(rootNode){
            // get the required objects
            allDivs = rootNode.getElementsByTagName('DIV');
            contentNode = allDivs[0];
            indicatorNode = allDivs[allDivs.length-2];
            // get the current scroll position
            indicatorPosition = (indicatorNode.style.top) ? parseInt(indicatorNode.style.top) : 0 ;
            indicatorSize = (indicatorNode.style.height) ? parseInt(indicatorNode.style.height) : 0 ;
            // set the new scroll position
            this.moveTo(rootNode, indicatorPosition+indicatorSize/2+distance);
         }
      },
      // events
      onDown: function(that){
         var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
         var asb = jQuery.classBehaviours.handlers.artificialScrollBar;
         // activate the controls
         asb.interaction = true;
         // get the interaction location
         mouseY = (typeof(event)!='undefined' && navigator.userAgent.indexOf('Safari')<0) ? event.y : that.layerY ;
         // send the coordinates to the indicator
         asb.moveTo(objNode.parentNode.parentNode, mouseY);
         // cancel the click
         return false;
      },
      onDrag: function(that){
         var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
         var asb = jQuery.classBehaviours.handlers.artificialScrollBar;
         // if the controls are active
         if(asb.interaction){
            // get the interaction location
            mouseY = (typeof(event)!='undefined' && navigator.userAgent.indexOf('Safari')<0) ? event.y : that.layerY ;
            // send the coordinates to the indicator
            asb.moveTo(objNode.parentNode.parentNode, mouseY);
            // cancel the click
            return false;
         }
      },
      onUp: function(that){
         var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
         var asb = jQuery.classBehaviours.handlers.artificialScrollBar;
         // de-activate the controls
         asb.interaction = false;
         // cancel the click
         return false;
      },
      buttonUp: function(that){
         var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
         var asb = jQuery.classBehaviours.handlers.artificialScrollBar;
         // move the scroller 1 step up
         asb.moveBy(asb.interactor, -5);
         // set an interval
         asb.scrollInterval = setInterval("jQuery.classBehaviours.handlers.artificialScrollBar.moveBy(jQuery.classBehaviours.handlers.artificialScrollBar.interactor, -5)", 50);
         // cancel the click
         return false;
      },
      buttonDown: function(that){
         var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
         var asb = jQuery.classBehaviours.handlers.artificialScrollBar;
         // move the scroller 1 step down
         asb.moveBy(asb.interactor, 5);
         // set an interval
         asb.scrollInterval = setInterval("jQuery.classBehaviours.handlers.artificialScrollBar.moveBy(jQuery.classBehaviours.handlers.artificialScrollBar.interactor, 5)", 50);
         // cancel the click
         return false;
      },
      buttonOff: function(that){
         var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
         var asb = jQuery.classBehaviours.handlers.artificialScrollBar;
         // clear the scrolling interval
         clearInterval(asb.scrollInterval);
         // cancel the click
         return false;
      },
      onWheel: function(that){
         var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
         var asb = jQuery.classBehaviours.handlers.artificialScrollBar;
         // get the scroll distance
         distance = (window.event) ? window.event.wheelDelta/120 : -objNode.detail/3 ;
         // scroll the page
         asb.moveBy(asb.interactor, -5*distance);
         // cancel the click
         return false;
      },
      overCanvas: function(that){
         var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
         var asb = jQuery.classBehaviours.handlers.artificialScrollBar;
         // store the object hovered over
         asb.interactor = objNode;
      },
      offCanvas: function(that){
         var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
         var asb = jQuery.classBehaviours.handlers.artificialScrollBar;
         // store the object hovered over
         asb.interactor = null;
      }
   }

   // add this addon to the jQuery object
   if(typeof(jQuery.fn)!='undefined'){
      // extend jQuery with this method
      jQuery.fn.artificialScrollBar = function(){
         return this.each(
            function(){
               jQuery.classBehaviours.handlers.artificialScrollBar.start(this);
            }
         );
      };
      // set the event handler for this jQuery method
      $(document).ready(
         function(){
            $(".artificialScrollBar").artificialScrollBar();
         }
      );
   }

// JavaScript Document