/*****************************************************************************
 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,y,newX,newY = null;
                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;
    }
}


/*****************************************************************************
 Drag Hnadler
    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
    }
}


/************************************************************
 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){
    //get the elements involved
    var dragElem = document.getElementById(dragElemId);
    var list = document.getElementById(scrollElemId);
    var bar = document.getElementById(scrollbarElemId);
    var display = document.getElementById(displayWindowElemId);

    //get the heights of the elements
    var listHeight = list.offsetHeight;
    var barHeight = bar.offsetHeight;
    var displayHeight = display.offsetHeight;
    var dragElemHeight = dragElem.offsetHeight;

    //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';
    }

    //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';
    }

    //check for draghandler and wheelhandler
    if(typeof(dragHandler)!='object') dragHandler = false;
    if(typeof(wheelHandler)!='object') wheelHandler = false;

    //attach to draghandler and wheel handler
    if(dragHandler) dragHandler.attach(dragElemId,false,[minScroll,maxScroll],this.scroll);
    if(wheelHandler) wheelHandler.attach(scrollElemId,this.wheel);
}
