﻿
// returns true if current click event is likely occuring as the by-product of a drag operation
// this is done by comparing the current time with the time of the last mouseup event associated with a drag
var dragMouseUpTime = 0;
function dragClick() {
    if (new Date().getTime() - dragMouseUpTime < 50)
        return true;
    else
        return false;
}

function drag(e) {
    if (!e) e = window.event;       // IE event model - event is global object rather than passed to event handler
    if (e.target) {
        var elementToDrag = e.currentTarget;
    }
    else if (e.srcElement) {
        elementToDrag = this;
    }
    
    // prevent text selection in IE
    document.onselectstart = function() { return false; };
    // prevent IE from trying to drag an image
    elementToDrag.ondragstart = function() { return false; };

    // Prevent browsers from starting a preview image drag on image elements 
//    if (e.preventDefault)       // DOM Level2 event model
//        e.preventDefault()
//    else e.returnValue = false; // IE event model
//        
    // use the id attribute of this DOM element as an index into the Filmstrip collection to get the reference to the
    // Filmstrip instance which contains a reference to the projector instance we need to manipulate
    var f = Filmstrip.filmstripToDrag();
    if (!f) return;

    elementToDrag = f.container;
    var projector = Filmstrip.collection[elementToDrag.id].projector;
    Filmstrip.bringToFront(elementToDrag.id);
    
    projector.glideStop();

    // Will be set to true if mouse is dragged
    // If set to true then event bubbling will be canceled to keep drag click from also behaving like a regular click
    var dragged = false;
    
    // buffer to hold most recents velocity values
    var velocity = [];
    var MaxVelocityBufferSize = 10;
    var MaxVelocityTimespan = 100;  // period (in milliseconds) that velocity is measured
    
    // The mouse position (in window coordinates)
    // at which the drag begins 
    var startX = e.clientX, startY = e.clientY;    

    // The original position (in document coordinates) of the
    // element that is going to be dragged.  Since elementToDrag is 
    // absolutely positioned, we assume that its offsetParent is the
    // document body.
    var origX = elementToDrag.offsetLeft, origY = elementToDrag.offsetTop;

    // Even though the coordinates are computed in different 
    // coordinate systems, we can still compute the difference between them
    // and use it in the moveHandler() function.  This works because
    // the scrollbar position never changes during the drag.
    var deltaX = startX - origX, deltaY = startY - origY;

    // Register the event handlers that will respond to the mousemove events
    // and the mouseup event that follow this mousedown event.  
    if (document.addEventListener) {  // DOM Level 2 event model
        // Register capturing event handlers
        document.addEventListener("mousemove", moveHandler, true);
        document.addEventListener("mouseup", upHandler, true);
    }
    else if (document.attachEvent) {  // IE 5+ Event Model
        // In the IE event model, we capture events by calling
        // setCapture() on the element to capture them.
        elementToDrag.setCapture();
        elementToDrag.attachEvent("onmousemove", moveHandler);
        elementToDrag.attachEvent("onmouseup", upHandler);
        // Treat loss of mouse capture as a mouseup event
        elementToDrag.attachEvent("onlosecapture", upHandler);
    }
    else {  // IE 4 Event Model
        // In IE 4 we can't use attachEvent() or setCapture(), so we set
        // event handlers directly on the document object and hope that the
        // mouse events we need will bubble up.  
        var oldmovehandler = document.onmousemove; // used by upHandler() 
        var olduphandler = document.onmouseup;
        document.onmousemove = moveHandler;
        document.onmouseup = upHandler;
    }

    /**
     * This is the handler that captures mousemove events when an element
     * is being dragged. It is responsible for moving the element.
     **/
    function moveHandler(e) {
        if (!e) e = window.event;  // IE Event Model
        
        // Prevent browsers from starting a preview image drag on image elements 
        if (e.preventDefault)       // DOM Level2 event model
            e.preventDefault()
        else e.returnValue = false; // IE event model

        // Set to true because mouse has now been moved before mouseup occured
        dragged = true;

        // Move the element to the current mouse position, adjusted as
        // necessary by the offset of the initial mouse-click.
        var newX = e.clientX - deltaX;
        var dx = newX - parseInt(elementToDrag.style.left);
        if (dx !=0)
            projector.filmstrip.slide(dx);
        
        // track delta Y values to be used to set current film speed on mouse up
        var step = {};
        step.value = e.clientY-startY;
        step.time = new Date().getTime();
        velocity.unshift(step);
        if (velocity.length > MaxVelocityBufferSize)
            velocity.pop();
        
        // Move filmstrip in Y direction by advancing frames
        projector.move(step.value);
        startY = e.clientY;
    }

    /**
     * This is the handler that captures the final mouseup event that
     * occurs at the end of a drag.
     **/
    function upHandler(e) {
        if (!e) e = window.event;  // IE Event Model

        // Unregister the capturing event handlers.
        if (document.removeEventListener) {  // DOM event model
            document.removeEventListener("mouseup", upHandler, true);
            document.removeEventListener("mousemove", moveHandler, true);
            // cancel event bubbling if a drag occured
            if (dragged) e.stopPropagation();
        }
        else if (document.detachEvent) {  // IE 5+ Event Model
            elementToDrag.detachEvent("onlosecapture", upHandler);
            elementToDrag.detachEvent("onmouseup", upHandler);
            elementToDrag.detachEvent("onmousemove", moveHandler);
            elementToDrag.releaseCapture();
        }
        else {  // IE 4 Event Model
            // Restore the original handlers, if any
            document.onmouseup = olduphandler;
            document.onmousemove = oldmovehandler;
        }
        
        // change stepsize if a drag has occured.  Don't change it if this was just a click
        if (velocity.length > 0) {
            var v = VelocityOnUp();
            projector.glidesize = Math.round(Math.abs(v));
            if (v > 0)
                projector.glideDown();   
            else
                projector.glideUp();
        }

        // if this mouseup event occured at the end of a drag operation, record the time it ended so
        // global function dragClick() can determine if a mouse click appears to be the side effect of a drag operation
        if (dragged) dragMouseUpTime = new Date().getTime();
    }
    
    function VelocityOnUp() {
        var v = 0;
        var vcount = 0;
        var now = new Date().getTime();
        
        for (var i=0; i<velocity.length; i++) {
            if (now - velocity[i].time > MaxVelocityTimespan)
                break;
            v += velocity[i].value;
            vcount++;
        }        
    
        if (vcount > 0)
            v = v / vcount;

        return v;
    }
}


