/*****************************************************************************
 Drag Hnadler
    Pure data object, passes new x and y coords to callbackfunction
    Methods:
        attach - Attaches an element to the drag handler, you can
                attach as many as you want to it

                Params for attach method:
                    dragElemId: id of element to be dragged
                    xLimits,yLimits: bounding areas for x and y dragable area,
                                    pass a false to restrict that axis
                    callBackFunction(newX,newY): a function to use the new x and y coords
******************************************************************************/
DragHandler = new function(){
    // public method. Attach an element to the drag handler
    this.attach = function(dragElemId,xLimits,yLimits,callBackFunction){
        var dragElem = document.getElementById(dragElemId);
        //initialize callback and limits
        if(typeof(callBackFunction)!='function') callBackFunction = false;
        if(typeof(xLimits)=='object'){
            xMin = xLimits[0];
            xMax = xLimits[1];
        }
        else xLimits = false;
        if(typeof(yLimits)=='object'){
            yMin = yLimits[0];
            yMax = yLimits[1];
        }
        else yLimits = false;
        //define an onmousedown for the attached element
        dragElem.onmousedown = function(e){
            e = e ? e : window.event; //cross browser support for IE

            //x-axis
            if(xLimits){
                if(isNaN(parseInt(dragElem.style.left))) dragElem.style.left = '0px'; //instantiate the top,left,zIndex to zero if not set
                dragElem.mouseX = e.clientX; //grab the mouse x position from the DOM
            }

            //y-axis
            if(yLimits){
                if(isNaN(parseInt(dragElem.style.top))) dragElem.style.top = minSlide+'px';
                dragElem.mouseY = e.clientY; //grab the mouse y position from the DOM
            }

            //z-index
            if(isNaN(parseInt(dragElem.style.zIndex))) dragElem.style.zIndex = 0; //lets you set your zindex if needed
            dragElem.style.zIndex += 50000; //elem lifts the dragged element to the top during drag

            //define an onmousemove event for the document (to drag the thing)
            document.onmousemove = function(e){
                var x = 0;
                var y = 0;
                var newX = 0;
                var newY = 0;
                e = e ? e : window.event; //cross browser support for IE (same as above)
                //x-axis
                if(xLimits){
                    x = parseInt(dragElem.style.left); //read the left value of the element
                    newX = x + (e.clientX - dragElem.mouseX);
                    if(newX<xMin) newX = xMin;
                    if(newX>xMax) newX = xMax;
                    dragElem.style.left = newX + 'px';
                    dragElem.mouseX = e.clientX; //set new mouse position for element
                }
                //y-axis
                if(yLimits){
                    y = parseInt(dragElem.style.top); //read the top value of the element
                    newY = y + (e.clientY - dragElem.mouseY);
                    if(newY<yMin) newY = yMin;
                    if(newY>yMax) newY = yMax;
                    dragElem.style.top = newY + 'px';
                    dragElem.mouseY = e.clientY;
                }
                if(callBackFunction) callBackFunction(newX,newY);
                return false;
            };

            //define an onmouseup event for the document (to stop the drag)
            document.onmouseup = function(){
                dragElem.style.zIndex -= 50000; //drop the element back to original z level

                document.onmousemove = null; //clear the documnet mouse events
                document.onmouseup = null;

                return false;
            };
            return false;
        };
        return false;
    }
}

/*****************************************************************************
 Wheel Handler
    Pure data object, passes delta (+1 or -1) to callbackfunction
    Methods:
        attach - Attaches an element to the wheelhandler, you can
                attach as many as you want to it

                Params for attach method:
                    elemId: id of element to be affected
                    callBackFunction(delta): a function to use the delta
******************************************************************************/
WheelHandler = new function(){
    this.attach = function(elemId,callBackFunction){

        //define function to attach to event
        function wheel(event){
            event = event ? event : window.event;
            var delta = 0;
            if(event.wheelDelta) delta = event.wheelDelta/120; //ie & opera
            else if(event.detail) delta = -event.detail/3; //mozilla

            if(delta) callBackFunction(delta); //handle if nonzero
            //prevent page scroll
            if(event.preventDefault) event.preventDefault();
            event.returnValue = false;
        }

        var elem = document.getElementById(elemId); //get element
        if(window.addEventListener) elem.addEventListener('DOMMouseScroll', wheel, false); //mozilla add event
        elem.onmousewheel = wheel; //other browsers add event
    }
}

ClickScrollHandler = new function(){
    this.attach = function(elemId,callBackFunction){
        var elem = document.getElementById(elemId); //get element
        if(window.addEventListener) elem.addEventListener('DOMMouseDown', callBackFunction, false); //mozilla add event
        elem.onmousedown = callBackFunction; //other browsers add event
    }
}

/************************************************************
 Scroller Class
   use in conjunction with the DragHandler and WheelHandler
 Params:
   dragElemId - id of acutal element to be dragged
   scrollElemId - id of element that scrolls, ex) video list
   scrollbarElemId - id of scroll bar element
   displayWindowElemId - id of list view window element
   axis - does this scroll in the x or the y direction
           pass in 'x' or 'y'
   dragHandler - pass in the dragHandler object or false
   wheelHandler - pass in the wheelHandler object or false

 note: make sure this is instantiated after images have loaded
       into your key elements so sizes are captured properly
 ***********************************************************/
function Scroller(dragElemId,scrollElemId,scrollbarElemId,displayWindowElemId,dragHandler,wheelHandler,axis,scrollUpElemId,scrollDownElemId,clickHandler){
    
    //get the elements involved
    if(typeof(axis) == 'undefined') axis = 'y';
    var dragElem = document.getElementById(dragElemId);
    var list = document.getElementById(scrollElemId);
    var bar = document.getElementById(scrollbarElemId);
    var display = document.getElementById(displayWindowElemId);

    if(axis == 'y'){

        //get the heights of the elements
        var listHeight = list.offsetHeight;
        var barHeight = bar.offsetHeight;
        var displayHeight = display.offsetHeight;
        var dragElemHeight = dragElem.offsetHeight;

    }else{

        //get the widths of the elements
        var listHeight = list.offsetWidth;
        var barHeight = bar.offsetWidth;
        var displayHeight = display.offsetWidth;
        var dragElemHeight = dragElem.offsetWidth;

    }
    
    //set maxes and mins
    var minScroll = -1;
    var maxScroll = barHeight - dragElemHeight;
    if(listHeight<displayHeight) listHeight = displayHeight;
    var ratio = (listHeight - displayHeight)/maxScroll;

    //this is the callback function to pass to the drag handler, moves the list
    this.scroll = function(newX,newY){
        list.style.top = -ratio*newY+'px';
        list.style.left = -ratio*newX+'px';
    }
    
   
    if(axis == 'y'){
        //callback function for the wheel handler
        this.wheel = function(delta){
            var newY = parseInt(dragElem.style.top) - delta*15;
            if(newY>maxScroll) newY = maxScroll;
            if(newY<minScroll) newY = minScroll;
    
            list.style.top = -newY*ratio + 'px';
            dragElem.style.top = newY + 'px';
        }
        
        
        this.mousedown_up = function(){
            var move = 50;
            var newY = parseInt(dragElem.style.top) - move;
            if(newY>maxScroll) newY = maxScroll;
            if(newY<minScroll) newY = minScroll;
    
            list.style.top = -newY*ratio + 'px';
            dragElem.style.top = newY + 'px';
        }
        this.mousedown_down = function(){
            var move = -50;
            var newY = parseInt(dragElem.style.top) - move;
            if(newY>maxScroll) newY = maxScroll;
            if(newY<minScroll) newY = minScroll;
    
            list.style.top = -newY*ratio + 'px';
            dragElem.style.top = newY + 'px';
        }
    
        
    }else{
        //callback function for the wheel handler
        this.wheel = function(delta){
            var newX = parseInt(dragElem.style.left) - delta*15;
            if(newX>maxScroll) newX = maxScroll;
            if(newX<minScroll) newX = minScroll;
    
            list.style.left = -newX*ratio + 'px';
            dragElem.style.left = newX + 'px';
        }
        
        this.mousedown_up = function(){
            var move = 50;
            var newX = parseInt(dragElem.style.left) - move;
            if(newX>maxScroll) newX = maxScroll;
            if(newX<minScroll) newX = minScroll;
    
            list.style.left = -newX*ratio + 'px';
            dragElem.style.left = newX + 'px';
        }
        this.mousedown_down = function(){
            var move = -50;
            var newX = parseInt(dragElem.style.left) - move;
            if(newX>maxScroll) newX = maxScroll;
            if(newX<minScroll) newX = minScroll;
    
            list.style.left = -newX*ratio + 'px';
            dragElem.style.left = newX + 'px';
        }

    }

    //check for draghandler and wheelhandler
    if(typeof(dragHandler)!='object') dragHandler = false;
    if(typeof(wheelHandler)!='object') wheelHandler = false;
    if(typeof(clickHandler)!='object') clickHandler = false;
    xLimits = (axis == 'x') ? [minScroll, maxScroll] : false ;
    yLimits = (axis == 'y') ? [minScroll, maxScroll] : false;
    //attach to draghandler and wheel handler
    if(dragHandler) dragHandler.attach(dragElemId,xLimits,yLimits,this.scroll);
    if(wheelHandler) wheelHandler.attach(scrollElemId,this.wheel);
    if(clickHandler) clickHandler.attach(scrollUpElemId,this.mousedown_up);
    if(clickHandler) clickHandler.attach(scrollDownElemId,this.mousedown_down);
}

